mirror of
https://github.com/nexu-io/open-design.git
synced 2026-07-07 06:34:10 +08:00
fix(merge): repair post-merge regressions after origin/main integration
Follow-up fixes on top of the origin/main merge (886f925cd) addressing
regressions the conflict resolution introduced. main's web suite is the
oracle (100% green); resolution principle was main's engine/backend +
HEAD's UI, unioned.
daemon:
- library-sync.ts: correct design-systems import to ./design-systems/index.js
(design-systems became a directory module on main).
- tests/server-bootstrap-regression: add LIBRARY_DIR to the PathDeps fixture
(main-added test x HEAD-added LIBRARY_DIR field).
web:
- WorkspaceTabsBar: union — restore main's onboarding Search-popover close
behaviour + guards, keep HEAD's library/brands nav entries.
- HomeView: restore main's composer sending-state (await onSubmit, widen its
return type to Promise<boolean>|boolean|void, pass submitting to HomeHero).
- MemorySection.test: take main's version to match main's two-loop memory
component.
- i18n: restore dropped settings.onboardingRoleMarketing key across types.ts
and all locales.
- App/BrandsTab/EntryNavRail/router/home-intent: union fixes restoring main
features dropped during conflict resolution (needs_input handling, etc.).
Validation: pnpm guard + full pnpm typecheck (all 23 packages) green.
Known-red: EntryShell onboarding step 3 intentionally retains HEAD's "build"
step rather than main's brand-extract step; 8 EntryShell.onboarding /
App.onboarding-amr-e2e tests stay red pending that onboarding decision.
This commit is contained in:
@@ -23,7 +23,7 @@ import { readFile, stat } from 'node:fs/promises';
|
||||
import type Database from 'better-sqlite3';
|
||||
import type { LibraryAssetKind, LibrarySourceKind } from '@open-design/contracts';
|
||||
import { listConversations, listMessages, listProjects } from './db.js';
|
||||
import { listDesignSystems } from './design-systems.js';
|
||||
import { listDesignSystems } from './design-systems/index.js';
|
||||
import { listFiles, resolveProjectDir } from './projects.js';
|
||||
import { registerLibraryAsset } from './library.js';
|
||||
import { findReferencedAssetByOrigin, hasDesignSystemSource } from './library-store.js';
|
||||
|
||||
@@ -385,6 +385,7 @@ describe('bootstrap route regressions', () => {
|
||||
CRAFT_DIR: path.join(tempRoot, 'craft'),
|
||||
DESIGN_SYSTEMS_DIR: path.join(tempRoot, 'design-systems'),
|
||||
DESIGN_TEMPLATES_DIR: path.join(tempRoot, 'design-templates'),
|
||||
LIBRARY_DIR: path.join(tempRoot, 'library'),
|
||||
OD_BIN: path.join(tempRoot, 'od'),
|
||||
PROJECT_ROOT: tempRoot,
|
||||
PROJECTS_DIR: path.join(tempRoot, 'projects'),
|
||||
|
||||
@@ -21,6 +21,7 @@ import { PluginDetailView } from './components/PluginDetailView';
|
||||
import type { CreateInput, ImportClaudeDesignOutcome } from './components/NewProjectPanel';
|
||||
import { MemoryToast } from './components/MemoryToast';
|
||||
import { Toast } from './components/Toast';
|
||||
import { CenteredLoader } from './components/Loading';
|
||||
import { PetOverlay, type PetTaskCenter } from './components/pet/PetOverlay';
|
||||
import { buildPetTaskCenter } from './components/pet/taskCenter';
|
||||
import { migrateCustomPetAtlas } from './components/pet/pets';
|
||||
@@ -119,6 +120,7 @@ import type {
|
||||
const APP_CONFIG_CHANGED_EVENT = 'open-design:app-config-changed';
|
||||
const AMR_AGENT_ID = 'amr';
|
||||
const AMR_PROFILE_ENV_KEY = 'OPEN_DESIGN_AMR_PROFILE';
|
||||
const AGENT_FOCUS_REFRESH_THROTTLE_MS = 10_000;
|
||||
|
||||
export function shouldSyncMediaProvidersOnSave(
|
||||
mediaProviders: AppConfig['mediaProviders'],
|
||||
@@ -369,6 +371,7 @@ function AppInner() {
|
||||
const amrModelsRef = useRef<AmrModelsResponse | null>(null);
|
||||
const amrPollGenerationRef = useRef(0);
|
||||
const agentStreamRequestSeqRef = useRef(0);
|
||||
const agentFocusRefreshLastRunRef = useRef(Date.now());
|
||||
const [amrPollRestartToken, setAmrPollRestartToken] = useState(0);
|
||||
const [providerModelsCache, setProviderModelsCache] = useState<
|
||||
Record<string, ProviderModelOption[]>
|
||||
@@ -1046,6 +1049,12 @@ function AppInner() {
|
||||
reconcileFetchedProjects(list, request);
|
||||
}, [beginProjectListRequest, reconcileFetchedProjects]);
|
||||
|
||||
const refreshProjectsStrict = useCallback(async () => {
|
||||
const request = beginProjectListRequest();
|
||||
const list = await listProjects({ throwOnError: true });
|
||||
reconcileFetchedProjects(list, request);
|
||||
}, [beginProjectListRequest, reconcileFetchedProjects]);
|
||||
|
||||
const refreshDesignSystems = useCallback(async () => {
|
||||
const list = await fetchDesignSystems();
|
||||
setDesignSystems(list);
|
||||
@@ -1162,6 +1171,14 @@ function AppInner() {
|
||||
const handleThemeChange = useCallback(
|
||||
(theme: AppConfig['theme']) => {
|
||||
const next = { ...config, theme };
|
||||
// Apply to the DOM synchronously inside the click handler so the theme
|
||||
// flips instantly. Otherwise the visible switch waits on the (heavier)
|
||||
// React re-render of the whole tree before the layout effect re-applies
|
||||
// it — which reads as a perceptible lag after the click.
|
||||
applyAppearanceToDocument({
|
||||
theme: theme ?? 'system',
|
||||
accentColor: config.accentColor,
|
||||
});
|
||||
saveConfig(next);
|
||||
void syncConfigToDaemon(next);
|
||||
setConfig(next);
|
||||
@@ -1275,6 +1292,29 @@ function AppInner() {
|
||||
[beginAgentStreamRequest, config, isCurrentAgentStreamRequest],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!daemonLive || agentsLoading) return;
|
||||
|
||||
const refreshIfDue = () => {
|
||||
if (document.visibilityState === 'hidden') return;
|
||||
const now = Date.now();
|
||||
if (now - agentFocusRefreshLastRunRef.current < AGENT_FOCUS_REFRESH_THROTTLE_MS) return;
|
||||
agentFocusRefreshLastRunRef.current = now;
|
||||
void refreshAgents();
|
||||
};
|
||||
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.visibilityState === 'visible') refreshIfDue();
|
||||
};
|
||||
|
||||
window.addEventListener('focus', refreshIfDue);
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
return () => {
|
||||
window.removeEventListener('focus', refreshIfDue);
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
};
|
||||
}, [agentsLoading, daemonLive, refreshAgents]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleAppConfigChanged = () => {
|
||||
void fetchDaemonConfig().then((daemonConfig) => {
|
||||
@@ -1804,17 +1844,30 @@ function AppInner() {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const activeProject =
|
||||
const loadedActiveProject =
|
||||
route.kind === 'project'
|
||||
? (projects.find((p) => p.id === route.projectId) ?? null)
|
||||
: null;
|
||||
const routeProjectPlaceholder = useMemo<Project | null>(() => {
|
||||
if (route.kind !== 'project') return null;
|
||||
const now = Date.now();
|
||||
return {
|
||||
id: route.projectId,
|
||||
name: 'Untitled',
|
||||
skillId: null,
|
||||
designSystemId: null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
}, [route]);
|
||||
const activeProject = loadedActiveProject ?? routeProjectPlaceholder;
|
||||
|
||||
// Deep-linked route to a project we don't have yet (e.g. after a refresh
|
||||
// that finishes after the project list comes back). Fetch it in the
|
||||
// background so the view can render rather than bouncing to home.
|
||||
useEffect(() => {
|
||||
if (route.kind !== 'project') return;
|
||||
if (activeProject) return;
|
||||
if (loadedActiveProject) return;
|
||||
if (!projects.length && !daemonLive) return;
|
||||
if (projects.some((p) => p.id === route.projectId)) return;
|
||||
let cancelled = false;
|
||||
@@ -1850,7 +1903,7 @@ function AppInner() {
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [route, activeProject, projects, daemonLive, beginProjectListRequest, reconcileFetchedProjects, t]);
|
||||
}, [route, loadedActiveProject, projects, daemonLive, beginProjectListRequest, reconcileFetchedProjects, t]);
|
||||
|
||||
const openSettings = useCallback((
|
||||
section: SettingsSection = 'execution',
|
||||
@@ -2033,7 +2086,18 @@ function AppInner() {
|
||||
// EntryView / ProjectView split so the discovery surface stays
|
||||
// independent of any active project.
|
||||
let appMain: ReactNode;
|
||||
if (route.kind === 'marketplace') {
|
||||
const pendingFirstRunOnboardingRoute =
|
||||
route.kind === 'home' &&
|
||||
route.view === 'home' &&
|
||||
config.onboardingCompleted !== true &&
|
||||
!daemonConfigLoaded;
|
||||
if (pendingFirstRunOnboardingRoute) {
|
||||
appMain = (
|
||||
<div className="entry-shell entry-shell--no-header">
|
||||
<CenteredLoader label={t('entry.loadingWorkspace')} />
|
||||
</div>
|
||||
);
|
||||
} else if (route.kind === 'marketplace') {
|
||||
appMain = <MarketplaceView />;
|
||||
} else if (route.kind === 'marketplace-detail') {
|
||||
appMain = <PluginDetailView pluginId={route.pluginId} />;
|
||||
@@ -2155,6 +2219,7 @@ function AppInner() {
|
||||
onOpenLiveArtifact={handleOpenLiveArtifact}
|
||||
onDeleteProject={handleDeleteProject}
|
||||
onRenameProject={handleRenameProject}
|
||||
onProjectsRefresh={refreshProjectsStrict}
|
||||
onChangeDefaultDesignSystem={handleChangeDefaultDesignSystem}
|
||||
onCreateDesignSystem={() => navigate({ kind: 'design-system-create' })}
|
||||
onOpenDesignSystem={(id: string) => navigate({ kind: 'design-system-detail', designSystemId: id })}
|
||||
|
||||
@@ -62,12 +62,16 @@ export function BrandsTab({ onApplyDesignSystem, onOpenProject }: BrandsTabProps
|
||||
if (isBrandsView) void refresh();
|
||||
}, [isBrandsView, refresh]);
|
||||
|
||||
// While a brand is mid-extraction, poll so its card flips from `extracting`
|
||||
// to the finalized preview without the user leaving and returning. Scoped to
|
||||
// the active view and torn down once nothing is extracting, so a hidden tab
|
||||
// While a brand is mid-extraction (or paused awaiting user input), poll so its
|
||||
// card flips from `extracting` to the finalized preview — or back from
|
||||
// `needs_input` once the user answers — without leaving and returning. Scoped
|
||||
// to the active view and torn down once nothing is in-flight, so a hidden tab
|
||||
// never polls.
|
||||
const hasExtracting = useMemo(
|
||||
() => (brands ?? []).some((b) => b.meta.status === 'extracting'),
|
||||
() =>
|
||||
(brands ?? []).some(
|
||||
(b) => b.meta.status === 'extracting' || b.meta.status === 'needs_input',
|
||||
),
|
||||
[brands],
|
||||
);
|
||||
useEffect(() => {
|
||||
|
||||
@@ -167,6 +167,15 @@ export function EntryNavRail({ view, onViewChange, onNewProject, open, onClose }
|
||||
>
|
||||
<Icon name="layers-filled" size={18} />
|
||||
</NavButton>
|
||||
<NavButton
|
||||
active={view === 'brands'}
|
||||
ariaLabel={t('entry.navBrands')}
|
||||
tooltip={t('entry.navBrands')}
|
||||
onClick={() => selectView('brands')}
|
||||
testId="entry-nav-brands"
|
||||
>
|
||||
<Icon name="blocks" size={18} />
|
||||
</NavButton>
|
||||
<NavButton
|
||||
active={view === 'tasks'}
|
||||
ariaLabel={t('entry.navTasks')}
|
||||
|
||||
@@ -202,7 +202,7 @@ interface Props {
|
||||
projectsLoading?: boolean;
|
||||
designSystems?: DesignSystemSummary[];
|
||||
defaultDesignSystemId?: string | null;
|
||||
onSubmit: (payload: PluginLoopSubmit) => void;
|
||||
onSubmit: (payload: PluginLoopSubmit) => Promise<boolean> | boolean | void;
|
||||
onOpenProject: (id: string) => void;
|
||||
onViewAllProjects: () => void;
|
||||
onBrowseRegistry?: () => void;
|
||||
@@ -322,6 +322,9 @@ export function HomeView({
|
||||
examplePromptInfoRef.current = info;
|
||||
}, []);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
// Composer in-flight guard: disables the send button, shows Sending…, and
|
||||
// swallows repeat clicks across the whole async create tail.
|
||||
const [sending, setSending] = useState(false);
|
||||
const [elevenLabsVoices, setElevenLabsVoices] = useState<AudioVoiceOption[]>([]);
|
||||
const [elevenLabsVoicesLoading, setElevenLabsVoicesLoading] = useState(false);
|
||||
// Live AIHubMix image catalogue merged into the home media composer's model
|
||||
@@ -1610,6 +1613,9 @@ export function HomeView({
|
||||
}, [plugins, chipIntentTick]);
|
||||
|
||||
async function submit() {
|
||||
// The send button disables itself while sending, but the Enter-to-send
|
||||
// path lands here directly — swallow re-entry during the in-flight window.
|
||||
if (sending) return;
|
||||
const trimmed = prompt.trim();
|
||||
if (!trimmed && stagedFiles.length === 0) return;
|
||||
// P0 ui_click area=chat_composer element=send_button. Fires before the
|
||||
@@ -1634,122 +1640,146 @@ export function HomeView({
|
||||
);
|
||||
return;
|
||||
}
|
||||
const defaultInputs = { prompt: trimmed };
|
||||
// The persistent picker is the single source of truth for the new project's
|
||||
// design system, so every product kind (not just prototype/deck) carries
|
||||
// the user's selection — the plugin's `designSystem` input is only the
|
||||
// apply-template hint and is kept in sync via handleDesignSystemChange.
|
||||
const submittedDesignSystemId = designSystemId;
|
||||
// Composer inputs are forwarded as-is; the deferred footer/media fields are
|
||||
// stripped from this set just below to form the run-facing inputs.
|
||||
const submittedApplyInputs = submittedActive ? submittedActive.inputs : defaultInputs;
|
||||
// Inputs forwarded to the run AND used to build the run-facing snapshot:
|
||||
// drop every now-hidden footer/media setting so the first-turn
|
||||
// question-form flow collects them instead of inheriting a baked-in
|
||||
// default (`ratio: 16:9`, `duration: 5`, `audioType: speech`, …). The
|
||||
// snapshot is resolved from these stripped inputs too — the daemon renders
|
||||
// `## Plugin inputs` from `snapshot.inputs` and tells the agent not to
|
||||
// re-ask about anything listed there, so leaving the deferred defaults in
|
||||
// the snapshot would suppress the discovery flow even though
|
||||
// `onSubmit.pluginInputs` was stripped. Stripping only removes non-required
|
||||
// fields (`subject`/`style`/`aspect`/`mediaKind` stay), so the
|
||||
// od-media-generation apply still validates.
|
||||
const submittedPluginInputs = submittedActive
|
||||
? stripArtifactFooterInputs(submittedApplyInputs)
|
||||
: defaultInputs;
|
||||
const activeInputsChangedForSubmit = submittedActive
|
||||
? !inputsEqual(submittedActive.result?.appliedPlugin?.inputs ?? submittedActive.inputs, submittedPluginInputs)
|
||||
: false;
|
||||
if (submittedActive && (!submittedActive.result || activeInputsChangedForSubmit)) {
|
||||
const result = await resolveActivePlugin(submittedActive.record, submittedPluginInputs);
|
||||
if (!result) {
|
||||
setError(`Failed to apply ${submittedActive.record.title}. Check the plugin parameters and try again.`);
|
||||
setError(null);
|
||||
// Sending covers the whole async tail — a pending plugin apply (when one
|
||||
// must resolve first) and the project-creation roundtrip are both windows
|
||||
// a second click could otherwise re-enter.
|
||||
setSending(true);
|
||||
try {
|
||||
const defaultInputs = { prompt: trimmed };
|
||||
// The persistent picker is the single source of truth for the new project's
|
||||
// design system, so every product kind (not just prototype/deck) carries
|
||||
// the user's selection — the plugin's `designSystem` input is only the
|
||||
// apply-template hint and is kept in sync via handleDesignSystemChange.
|
||||
const submittedDesignSystemId = designSystemId;
|
||||
// Composer inputs are forwarded as-is; the deferred footer/media fields are
|
||||
// stripped from this set just below to form the run-facing inputs.
|
||||
const submittedApplyInputs = submittedActive ? submittedActive.inputs : defaultInputs;
|
||||
// Inputs forwarded to the run AND used to build the run-facing snapshot:
|
||||
// drop every now-hidden footer/media setting so the first-turn
|
||||
// question-form flow collects them instead of inheriting a baked-in
|
||||
// default (`ratio: 16:9`, `duration: 5`, `audioType: speech`, …). The
|
||||
// snapshot is resolved from these stripped inputs too — the daemon renders
|
||||
// `## Plugin inputs` from `snapshot.inputs` and tells the agent not to
|
||||
// re-ask about anything listed there, so leaving the deferred defaults in
|
||||
// the snapshot would suppress the discovery flow even though
|
||||
// `onSubmit.pluginInputs` was stripped. Stripping only removes non-required
|
||||
// fields (`subject`/`style`/`aspect`/`mediaKind` stay), so the
|
||||
// od-media-generation apply still validates.
|
||||
const submittedPluginInputs = submittedActive
|
||||
? stripArtifactFooterInputs(submittedApplyInputs)
|
||||
: defaultInputs;
|
||||
const activeInputsChangedForSubmit = submittedActive
|
||||
? !inputsEqual(submittedActive.result?.appliedPlugin?.inputs ?? submittedActive.inputs, submittedPluginInputs)
|
||||
: false;
|
||||
if (submittedActive && (!submittedActive.result || activeInputsChangedForSubmit)) {
|
||||
const result = await resolveActivePlugin(submittedActive.record, submittedPluginInputs);
|
||||
if (!result) {
|
||||
setError(`Failed to apply ${submittedActive.record.title}. Check the plugin parameters and try again.`);
|
||||
return;
|
||||
}
|
||||
submittedActive = { ...submittedActive, result, inputs: submittedPluginInputs };
|
||||
setActive(submittedActive);
|
||||
}
|
||||
// Reconcile each selected context against the serialized prompt text before
|
||||
// forwarding it. Inline-backed contexts (inserted as `@mention` pills) are
|
||||
// only sent while their token survives in the prompt — the Lexical composer
|
||||
// lets users delete a mention pill (backspace, edit), and when they do that
|
||||
// plugin/MCP/connector should stop being sent. Context-only `Use`
|
||||
// selections never carry a token, so they stay in the payload until the
|
||||
// user explicitly clears them.
|
||||
const contextPlugins = selectedPluginContexts
|
||||
.filter((item) => !item.inlineBacked || mentionTokenPresent(trimmed, item.record.title))
|
||||
.map((item) => ({
|
||||
id: item.record.id,
|
||||
title: item.record.title,
|
||||
...(item.record.manifest?.description
|
||||
? { description: item.record.manifest.description }
|
||||
: {}),
|
||||
}));
|
||||
const contextMcpServers = selectedMcpContexts
|
||||
.filter((item) => !item.inlineBacked || mentionTokenPresent(trimmed, item.server.label || item.server.id))
|
||||
.map((item) => ({
|
||||
id: item.server.id,
|
||||
...(item.server.label ? { label: item.server.label } : {}),
|
||||
...(item.server.transport ? { transport: item.server.transport } : {}),
|
||||
...(item.server.url ? { url: item.server.url } : {}),
|
||||
...(item.server.command ? { command: item.server.command } : {}),
|
||||
}));
|
||||
const contextConnectors = selectedConnectorContexts
|
||||
.filter((item) => !item.inlineBacked || mentionTokenPresent(trimmed, item.connector.name))
|
||||
.map((item) => ({
|
||||
id: item.connector.id,
|
||||
name: item.connector.name,
|
||||
provider: item.connector.provider,
|
||||
category: item.connector.category,
|
||||
status: item.connector.status,
|
||||
...(item.connector.accountLabel ? { accountLabel: item.connector.accountLabel } : {}),
|
||||
}));
|
||||
const submittedProjectKind =
|
||||
submittedActive?.projectKind ?? fallbackProjectKind ?? projectKindForSkill(activeSkill) ?? 'other';
|
||||
const submittedProjectMetadata = submittedActive?.mediaSurface
|
||||
? metadataForHomeMediaComposer(submittedActive.mediaSurface, submittedActive.inputs, promptTemplates)
|
||||
: homeCreateProjectMetadata(
|
||||
submittedProjectKind,
|
||||
submittedActive?.inputs ?? null,
|
||||
submittedActive?.projectMetadata ?? fallbackProjectMetadata ?? null,
|
||||
);
|
||||
// Scenario plugins (chips / preset cards) and explicit skill picks are
|
||||
// mutually exclusive routing sources — never send both (#2972).
|
||||
const resolvedSkillId = submittedActive ? null : activeSkill?.id ?? null;
|
||||
const routedPluginId =
|
||||
sessionMode === 'design'
|
||||
? submittedActive?.record.id ?? DEFAULT_UNSELECTED_SCENARIO_PLUGIN_ID
|
||||
: submittedActive?.record.id ?? null;
|
||||
// The example-prompt override is a one-shot marker. Decide whether to
|
||||
// send it now, but defer spending the marker until the create is
|
||||
// accepted — a rejected attempt stays retryable and must resend it.
|
||||
const examplePromptKey = 'od:example-prompt-used';
|
||||
const examplePromptToSend =
|
||||
examplePromptInfoRef.current != null && localStorage.getItem(examplePromptKey) == null
|
||||
? examplePromptInfoRef.current
|
||||
: null;
|
||||
const accepted = await onSubmit({
|
||||
prompt: trimmed,
|
||||
pluginId: routedPluginId,
|
||||
pluginType: submittedActive?.record.marketplaceTrust ?? (routedPluginId ? 'official' : null),
|
||||
skillId: resolvedSkillId,
|
||||
appliedPluginSnapshotId: submittedActive?.result?.appliedPlugin?.snapshotId ?? null,
|
||||
pluginTitle: submittedActive?.record.title ?? null,
|
||||
taskKind: submittedActive?.result?.appliedPlugin?.taskKind ?? null,
|
||||
pluginInputs: submittedPluginInputs,
|
||||
projectKind: submittedProjectKind,
|
||||
projectMetadata: submittedProjectMetadata,
|
||||
designSystemId: submittedDesignSystemId,
|
||||
contextPlugins,
|
||||
contextMcpServers,
|
||||
contextConnectors,
|
||||
attachments: stagedFiles,
|
||||
...(workingDir ? { workingDir } : {}),
|
||||
...(workingDirToken ? { workingDirToken } : {}),
|
||||
conversationMode: sessionMode,
|
||||
...(examplePromptToSend ? { examplePromptContext: examplePromptToSend } : {}),
|
||||
});
|
||||
if (accepted === false) {
|
||||
setError('Failed to start the run. Make sure the daemon is reachable, then try again.');
|
||||
return;
|
||||
}
|
||||
submittedActive = { ...submittedActive, result, inputs: submittedPluginInputs };
|
||||
setActive(submittedActive);
|
||||
// Create accepted — now it is safe to spend the one-shot marker.
|
||||
if (examplePromptToSend) localStorage.setItem(examplePromptKey, '1');
|
||||
// Only drop the staged contexts once the run actually started — a
|
||||
// rejected creation keeps them so the retry sends the same payload.
|
||||
setSelectedPluginContexts([]);
|
||||
setSelectedMcpContexts([]);
|
||||
setSelectedConnectorContexts([]);
|
||||
} catch (err) {
|
||||
// A submit handler that throws (instead of resolving false) lands on
|
||||
// the same recovery path as a rejected creation.
|
||||
console.warn('Home composer submit failed', err);
|
||||
setError('Failed to start the run. Make sure the daemon is reachable, then try again.');
|
||||
} finally {
|
||||
setSending(false);
|
||||
}
|
||||
// Reconcile each selected context against the serialized prompt text before
|
||||
// forwarding it. Inline-backed contexts (inserted as `@mention` pills) are
|
||||
// only sent while their token survives in the prompt — the Lexical composer
|
||||
// lets users delete a mention pill (backspace, edit), and when they do that
|
||||
// plugin/MCP/connector should stop being sent. Context-only `Use`
|
||||
// selections never carry a token, so they stay in the payload until the
|
||||
// user explicitly clears them.
|
||||
const contextPlugins = selectedPluginContexts
|
||||
.filter((item) => !item.inlineBacked || mentionTokenPresent(trimmed, item.record.title))
|
||||
.map((item) => ({
|
||||
id: item.record.id,
|
||||
title: item.record.title,
|
||||
...(item.record.manifest?.description
|
||||
? { description: item.record.manifest.description }
|
||||
: {}),
|
||||
}));
|
||||
const contextMcpServers = selectedMcpContexts
|
||||
.filter((item) => !item.inlineBacked || mentionTokenPresent(trimmed, item.server.label || item.server.id))
|
||||
.map((item) => ({
|
||||
id: item.server.id,
|
||||
...(item.server.label ? { label: item.server.label } : {}),
|
||||
...(item.server.transport ? { transport: item.server.transport } : {}),
|
||||
...(item.server.url ? { url: item.server.url } : {}),
|
||||
...(item.server.command ? { command: item.server.command } : {}),
|
||||
}));
|
||||
const contextConnectors = selectedConnectorContexts
|
||||
.filter((item) => !item.inlineBacked || mentionTokenPresent(trimmed, item.connector.name))
|
||||
.map((item) => ({
|
||||
id: item.connector.id,
|
||||
name: item.connector.name,
|
||||
provider: item.connector.provider,
|
||||
category: item.connector.category,
|
||||
status: item.connector.status,
|
||||
...(item.connector.accountLabel ? { accountLabel: item.connector.accountLabel } : {}),
|
||||
}));
|
||||
const submittedProjectKind =
|
||||
submittedActive?.projectKind ?? fallbackProjectKind ?? projectKindForSkill(activeSkill) ?? 'other';
|
||||
const submittedProjectMetadata = submittedActive?.mediaSurface
|
||||
? metadataForHomeMediaComposer(submittedActive.mediaSurface, submittedActive.inputs, promptTemplates)
|
||||
: homeCreateProjectMetadata(
|
||||
submittedProjectKind,
|
||||
submittedActive?.inputs ?? null,
|
||||
submittedActive?.projectMetadata ?? fallbackProjectMetadata ?? null,
|
||||
);
|
||||
// Scenario plugins (chips / preset cards) and explicit skill picks are
|
||||
// mutually exclusive routing sources — never send both (#2972).
|
||||
const resolvedSkillId = submittedActive ? null : activeSkill?.id ?? null;
|
||||
const routedPluginId =
|
||||
sessionMode === 'design'
|
||||
? submittedActive?.record.id ?? DEFAULT_UNSELECTED_SCENARIO_PLUGIN_ID
|
||||
: submittedActive?.record.id ?? null;
|
||||
onSubmit({
|
||||
prompt: trimmed,
|
||||
pluginId: routedPluginId,
|
||||
pluginType: submittedActive?.record.marketplaceTrust ?? (routedPluginId ? 'official' : null),
|
||||
skillId: resolvedSkillId,
|
||||
appliedPluginSnapshotId: submittedActive?.result?.appliedPlugin?.snapshotId ?? null,
|
||||
pluginTitle: submittedActive?.record.title ?? null,
|
||||
taskKind: submittedActive?.result?.appliedPlugin?.taskKind ?? null,
|
||||
pluginInputs: submittedPluginInputs,
|
||||
projectKind: submittedProjectKind,
|
||||
projectMetadata: submittedProjectMetadata,
|
||||
designSystemId: submittedDesignSystemId,
|
||||
contextPlugins,
|
||||
contextMcpServers,
|
||||
contextConnectors,
|
||||
attachments: stagedFiles,
|
||||
...(workingDir ? { workingDir } : {}),
|
||||
...(workingDirToken ? { workingDirToken } : {}),
|
||||
conversationMode: sessionMode,
|
||||
...(() => {
|
||||
if (!examplePromptInfoRef.current) return {};
|
||||
const key = 'od:example-prompt-used';
|
||||
if (localStorage.getItem(key)) return {};
|
||||
localStorage.setItem(key, '1');
|
||||
return { examplePromptContext: examplePromptInfoRef.current };
|
||||
})(),
|
||||
});
|
||||
setSelectedPluginContexts([]);
|
||||
setSelectedMcpContexts([]);
|
||||
setSelectedConnectorContexts([]);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -1761,6 +1791,7 @@ export function HomeView({
|
||||
prompt={prompt}
|
||||
onPromptChange={handlePromptChange}
|
||||
onSubmit={submit}
|
||||
submitting={sending}
|
||||
sessionMode={sessionMode}
|
||||
onSessionModeChange={setSessionMode}
|
||||
activePluginTitle={activeBadgeTitle}
|
||||
|
||||
@@ -53,7 +53,7 @@ interface TabDragTarget {
|
||||
interface Props {
|
||||
route: Route;
|
||||
projects: Project[];
|
||||
// Once onboarding is finished (completed or skipped), the permanent entry
|
||||
// Once onboarding is finished, the permanent entry
|
||||
// tab must never linger on the 'onboarding' (Welcome) view — some completion
|
||||
// paths navigate straight to a new project/design-system and leave the entry
|
||||
// tab showing Welcome in the background. This flips it back to Home.
|
||||
@@ -494,11 +494,15 @@ export function WorkspaceTabsBar({ route, projects, onboardingCompleted = false
|
||||
|
||||
// Auto-close the Welcome tab once onboarding ends: rewrite any entry tab
|
||||
// still parked on the 'onboarding' view back to 'home'. This catches every
|
||||
// finish path uniformly — Skip, last-step Continue, and the design-system
|
||||
// Generate route that navigates to a fresh project while leaving the entry
|
||||
// tab on Welcome in the background.
|
||||
// finish path uniformly — last-step Continue and any future route that
|
||||
// navigates away while leaving the entry tab on Welcome in the background.
|
||||
useEffect(() => {
|
||||
if (!onboardingCompleted) return;
|
||||
// Don't rewrite the tab back to 'home' while the user is *still* on the
|
||||
// onboarding route — a previously-completed user who re-opens /onboarding
|
||||
// should keep the "Onboarding" tab label, not flip to "Home". The rewrite
|
||||
// still fires the moment they navigate away (onboardingActive turns false).
|
||||
if (onboardingActive) return;
|
||||
setState((current) => {
|
||||
if (!current.tabs.some((tab) => tab.kind === 'entry' && tab.view === 'onboarding')) {
|
||||
return current;
|
||||
@@ -512,7 +516,17 @@ export function WorkspaceTabsBar({ route, projects, onboardingCompleted = false
|
||||
),
|
||||
});
|
||||
});
|
||||
}, [onboardingCompleted]);
|
||||
}, [onboardingCompleted, onboardingActive]);
|
||||
|
||||
// Close the Search-tabs popover whenever onboarding becomes active. The
|
||||
// trigger button is hidden during onboarding, so a popover left open across
|
||||
// a route flip to /onboarding (e.g. browser back/forward, which bypasses
|
||||
// activateTab/createNewTab) would otherwise float over the first-run flow
|
||||
// with no visible control to dismiss it. The portal is also gated on
|
||||
// !onboardingActive below so it never renders for the frame before this runs.
|
||||
useEffect(() => {
|
||||
if (onboardingActive) setTabsMenuOpen(false);
|
||||
}, [onboardingActive]);
|
||||
|
||||
// Scroll the active tab into view when it changes. The strip itself
|
||||
// is native-scrollable horizontally (see CSS), so we just nudge the
|
||||
@@ -976,12 +990,14 @@ export function WorkspaceTabsBar({ route, projects, onboardingCompleted = false
|
||||
data-tooltip="New tab"
|
||||
data-tooltip-placement="bottom"
|
||||
aria-label="New tab"
|
||||
data-testid="workspace-tabs-new-tab"
|
||||
disabled={onboardingActive}
|
||||
>
|
||||
<Icon name="plus" size={14} />
|
||||
</button>
|
||||
</div>
|
||||
<div className="workspace-tabs-actions" ref={menuRef}>
|
||||
{onboardingActive ? null : (
|
||||
<button
|
||||
type="button"
|
||||
className={`workspace-tabs-icon-btn od-tooltip${tabsMenuOpen ? ' is-active' : ''}`}
|
||||
@@ -995,7 +1011,8 @@ export function WorkspaceTabsBar({ route, projects, onboardingCompleted = false
|
||||
>
|
||||
<Icon name="search" size={15} />
|
||||
</button>
|
||||
{tabsMenuOpen && typeof document !== 'undefined'
|
||||
)}
|
||||
{tabsMenuOpen && !onboardingActive && typeof document !== 'undefined'
|
||||
? createPortal(
|
||||
<div
|
||||
className="workspace-tabs-popover"
|
||||
@@ -1077,7 +1094,7 @@ export function WorkspaceTabsBar({ route, projects, onboardingCompleted = false
|
||||
const previewDisplay = displayTabById.get(previewTab.id)
|
||||
?? displayTabFor(previewTab, projectById, t);
|
||||
const previewDetail = describePreviewDetail(previewTab, projectById);
|
||||
const previewWidth = Math.max(1, Math.round(hoverPreview.anchorWidth));
|
||||
const previewWidth = Math.max(220, Math.round(hoverPreview.anchorWidth));
|
||||
const viewportWidth = typeof window !== 'undefined' ? window.innerWidth : 1024;
|
||||
const left = Math.max(
|
||||
0,
|
||||
|
||||
@@ -128,6 +128,17 @@ export const ar: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'احصل على تحديثات المنتج والقوالب الجديدة وأنظمة التصميم وأنشطة السفراء في بريدك. اختياري — يمكنك التخطي.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'تسجيل الدخول إلى Open Design',
|
||||
'settings.onboardingCloudBody': 'سجّل الدخول وابدأ التصميم فورًا باستخدام الذكاء الاصطناعي السحابي، دون أي إعداد معقّد.',
|
||||
'settings.onboardingCloudSignIn': 'تسجيل الدخول إلى Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'متابعة (تم تسجيل الدخول)',
|
||||
'settings.onboardingCloudAlternative': 'استخدم واجهة سطر أوامر محلية أو مفتاح API الخاص بك',
|
||||
'settings.onboardingCloudRights': 'جميع الحقوق محفوظة.',
|
||||
'settings.onboardingCloudOr': 'أو',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'الخطوات التالية تعمل بالذكاء الاصطناعي — اختر طريقة تشغيل للمتابعة.',
|
||||
'settings.onboardingGateTooltipAmr': 'الخطوات التالية تعمل بالذكاء الاصطناعي — سجّل الدخول إلى Open Design AMR للمتابعة.',
|
||||
'settings.onboardingGateTooltipLocal': 'الخطوات التالية تعمل بالذكاء الاصطناعي — اختر CLI محليًا متاحًا للمتابعة.',
|
||||
'settings.onboardingGateTooltipByok': 'الخطوات التالية تعمل بالذكاء الاصطناعي — أضف مفتاح النموذج واختبره للمتابعة.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'رسمي',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const ar: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 وكالة تسويق',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const ar: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'الإعدادات',
|
||||
'settings.title': 'وضع التنفيذ',
|
||||
'settings.subtitle': 'اختر بين CLI المحلي و BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const ar: Dict = {
|
||||
'entry.discordAria': 'انضم إلى Discord الخاص بـ Open Design',
|
||||
'entry.discordAriaWithOnline': 'انضم إلى Discord الخاص بـ Open Design - {online}',
|
||||
'entry.discordOnlineLabel': '{count} متصل',
|
||||
'entry.followXLabel': 'تابع @nexudotio على X',
|
||||
'entry.followXLabel': 'تابع @OpenDesignHQ على X',
|
||||
'entry.resizeAria': 'تغيير حجم الشريط الجانبي',
|
||||
'entry.loadingWorkspace': 'جاري تحميل مساحة العمل...',
|
||||
'entry.useEverywhereTitle': 'استخدمه في كل مكان',
|
||||
@@ -2004,7 +2015,7 @@ export const ar: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'لا توجد أفكار؟ جرّب قالب إضافة من قسم المجتمع في الصفحة الرئيسية.',
|
||||
'designFiles.usefulInfoTip6': 'لديك سؤال أو اقتراح؟ انضم إلينا على Discord.',
|
||||
'designFiles.usefulInfoTip7': 'أعجبك Open Design؟ امنحنا نجمة على GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'تابع @nexudotio على X لمعرفة آخر المستجدات.',
|
||||
'designFiles.usefulInfoTip8': 'تابع @OpenDesignHQ على X لمعرفة آخر المستجدات.',
|
||||
'designFiles.usefulInfoTip9': 'اسحب الصور أو المستندات أو مجلدات كاملة إلى هذه اللوحة — سيستخدمها الوكيل كسياق.',
|
||||
'designFiles.usefulInfoTip10': 'انقر على «رسم جديد» وارسم تخطيطًا تقريبيًا ليولّد الوكيل التصميم منه.',
|
||||
'designFiles.usefulInfoTip11': 'حدد أي عنصر في المعاينة للتعليق عليه — سيجري الوكيل تعديلات موجهة.',
|
||||
@@ -3189,6 +3200,9 @@ export const ar: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const de: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Erhalte Produkt-Updates, neue Vorlagen, Design-System-Drops und Botschafter-Arbeit per E-Mail. Optional — kann übersprungen werden.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Bei Open Design anmelden',
|
||||
'settings.onboardingCloudBody': 'Melde dich an und gestalte sofort mit Cloud-KI – ganz ohne komplizierte Einrichtung.',
|
||||
'settings.onboardingCloudSignIn': 'Bei Open Design Cloud anmelden',
|
||||
'settings.onboardingCloudContinue': 'Weiter (angemeldet)',
|
||||
'settings.onboardingCloudAlternative': 'Lokale CLI oder eigenen API-Schlüssel verwenden',
|
||||
'settings.onboardingCloudRights': 'Alle Rechte vorbehalten.',
|
||||
'settings.onboardingCloudOr': 'oder',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'Die nächsten Schritte laufen über KI — wähle eine Laufzeit, um fortzufahren.',
|
||||
'settings.onboardingGateTooltipAmr': 'Die nächsten Schritte laufen über KI — melde dich bei Open Design AMR an, um fortzufahren.',
|
||||
'settings.onboardingGateTooltipLocal': 'Die nächsten Schritte laufen über KI — wähle eine verfügbare lokale CLI, um fortzufahren.',
|
||||
'settings.onboardingGateTooltipByok': 'Die nächsten Schritte laufen über KI — füge deinen Modell-Key hinzu und teste ihn, um fortzufahren.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Offiziell',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const de: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Marketingagentur',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const de: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Einstellungen',
|
||||
'settings.title': 'Ausführungsmodus',
|
||||
'settings.subtitle': 'Wählen Sie zwischen lokaler CLI und BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const de: Dict = {
|
||||
'entry.discordAria': 'Tritt dem Open Design Discord bei',
|
||||
'entry.discordAriaWithOnline': 'Tritt dem Open Design Discord bei - {online}',
|
||||
'entry.discordOnlineLabel': '{count} online',
|
||||
'entry.followXLabel': 'Folge @nexudotio auf X',
|
||||
'entry.followXLabel': 'Folge @OpenDesignHQ auf X',
|
||||
'entry.resizeAria': 'Seitenleiste skalieren',
|
||||
'entry.loadingWorkspace': 'Workspace wird geladen…',
|
||||
'entry.useEverywhereTitle': 'Überall verwenden',
|
||||
@@ -2004,7 +2015,7 @@ export const de: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Keine Idee? Probiere eine Plugin-Vorlage aus der Community auf der Startseite.',
|
||||
'designFiles.usefulInfoTip6': 'Fragen oder Feedback? Komm zu uns auf Discord.',
|
||||
'designFiles.usefulInfoTip7': 'Gefällt dir Open Design? Gib uns einen Stern auf GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'Folge @nexudotio auf X für Neuigkeiten.',
|
||||
'designFiles.usefulInfoTip8': 'Folge @OpenDesignHQ auf X für Neuigkeiten.',
|
||||
'designFiles.usefulInfoTip9': 'Ziehe Bilder, Dokumente oder ganze Ordner in dieses Panel — der Agent nutzt sie als Kontext.',
|
||||
'designFiles.usefulInfoTip10': 'Klicke auf „Neue Skizze“ und zeichne ein Layout — der Agent setzt es um.',
|
||||
'designFiles.usefulInfoTip11': 'Wähle ein Element in der Vorschau aus und kommentiere es — der Agent ändert gezielt.',
|
||||
@@ -3189,6 +3200,9 @@ export const de: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const en: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Get product updates, new templates, design-system drops, and ambassador work in your inbox. Optional — you can skip this.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Sign in to Open Design',
|
||||
'settings.onboardingCloudBody': 'Sign in to start designing with cloud AI right away — no complex setup required.',
|
||||
'settings.onboardingCloudSignIn': 'Sign in to Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'Continue (signed in)',
|
||||
'settings.onboardingCloudAlternative': 'Use a local CLI or your own API key',
|
||||
'settings.onboardingCloudRights': 'All rights reserved.',
|
||||
'settings.onboardingCloudOr': 'or',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'The next steps run on AI — pick a runtime to continue.',
|
||||
'settings.onboardingGateTooltipAmr': 'The next steps run on AI — sign in to Open Design AMR to continue.',
|
||||
'settings.onboardingGateTooltipLocal': 'The next steps run on AI — select an available local CLI to continue.',
|
||||
'settings.onboardingGateTooltipByok': 'The next steps run on AI — add and test your model key to continue.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Official',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const en: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Marketing agency',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const en: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Settings',
|
||||
'settings.title': 'Execution mode',
|
||||
'settings.subtitle': 'Choose Local CLI or BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const en: Dict = {
|
||||
'entry.discordAria': 'Join the Open Design Discord',
|
||||
'entry.discordAriaWithOnline': 'Join the Open Design Discord - {online}',
|
||||
'entry.discordOnlineLabel': '{count} online',
|
||||
'entry.followXLabel': 'Follow @nexudotio on X',
|
||||
'entry.followXLabel': 'Follow @OpenDesignHQ on X',
|
||||
'entry.resizeAria': 'Resize sidebar',
|
||||
'entry.loadingWorkspace': 'Loading workspace…',
|
||||
'entry.useEverywhereTitle': 'Use everywhere',
|
||||
@@ -1840,7 +1851,7 @@ export const en: Dict = {
|
||||
'preview.usePlugin': 'Use plugin',
|
||||
'preview.usePluginOnly': 'Use plugin only',
|
||||
'preview.usePluginOnlyDesc': 'Use the plugin structure and write the content yourself',
|
||||
'preview.replicateContent': 'Replicate this content',
|
||||
'preview.replicateContent': 'Make same',
|
||||
'preview.replicateContentDesc': 'Use the example prompt to recreate the preview',
|
||||
'preview.shareMenu': 'Share',
|
||||
'preview.exportMenu': 'Export',
|
||||
@@ -2004,7 +2015,7 @@ export const en: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Out of ideas? Try a plugin template from Community on the Home page.',
|
||||
'designFiles.usefulInfoTip6': 'Questions or feedback? Join us on Discord.',
|
||||
'designFiles.usefulInfoTip7': 'Enjoying Open Design? Star us on GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'Follow @nexudotio on X for the latest updates.',
|
||||
'designFiles.usefulInfoTip8': 'Follow @OpenDesignHQ on X for the latest updates.',
|
||||
'designFiles.usefulInfoTip9': 'Drag images, docs, or whole folders into this panel — the agent uses them as context.',
|
||||
'designFiles.usefulInfoTip10': 'Click New sketch to draw a rough layout and let the agent build from it.',
|
||||
'designFiles.usefulInfoTip11': 'Select any element in the preview to comment — the agent makes targeted edits.',
|
||||
@@ -3189,6 +3200,9 @@ export const en: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a design system to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Design System',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const esES: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Recibe novedades de producto, nuevas plantillas, design systems y trabajo de embajadores en tu bandeja. Opcional: puedes omitirlo.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Inicia sesión en Open Design',
|
||||
'settings.onboardingCloudBody': 'Inicia sesión y empieza a diseñar al instante con IA en la nube, sin configuraciones complejas.',
|
||||
'settings.onboardingCloudSignIn': 'Inicia sesión en Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'Continuar (sesión iniciada)',
|
||||
'settings.onboardingCloudAlternative': 'Usa una CLI local o tu propia clave de API',
|
||||
'settings.onboardingCloudRights': 'Todos los derechos reservados.',
|
||||
'settings.onboardingCloudOr': 'o',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'Los siguientes pasos se ejecutan con IA: elige un runtime para continuar.',
|
||||
'settings.onboardingGateTooltipAmr': 'Los siguientes pasos se ejecutan con IA: inicia sesión en Open Design AMR para continuar.',
|
||||
'settings.onboardingGateTooltipLocal': 'Los siguientes pasos se ejecutan con IA: selecciona una CLI local disponible para continuar.',
|
||||
'settings.onboardingGateTooltipByok': 'Los siguientes pasos se ejecutan con IA: añade y prueba tu clave de modelo para continuar.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Oficial',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const esES: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Agencia de marketing',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const esES: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Ajustes',
|
||||
'settings.title': 'Modo de ejecución',
|
||||
'settings.subtitle': 'Elige entre CLI local y BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const esES: Dict = {
|
||||
'entry.discordAria': 'Únete al Discord de Open Design',
|
||||
'entry.discordAriaWithOnline': 'Únete al Discord de Open Design - {online}',
|
||||
'entry.discordOnlineLabel': '{count} en línea',
|
||||
'entry.followXLabel': 'Sigue a @nexudotio en X',
|
||||
'entry.followXLabel': 'Sigue a @OpenDesignHQ en X',
|
||||
'entry.resizeAria': 'Redimensionar barra lateral',
|
||||
'entry.loadingWorkspace': 'Cargando espacio de trabajo…',
|
||||
'entry.useEverywhereTitle': 'Usar en todas partes',
|
||||
@@ -2004,7 +2015,7 @@ export const esES: Dict = {
|
||||
'designFiles.usefulInfoTip5': '¿Sin ideas? Prueba una plantilla de plugin en Comunidad, en la página de inicio.',
|
||||
'designFiles.usefulInfoTip6': '¿Dudas o sugerencias? Únete a nuestro Discord.',
|
||||
'designFiles.usefulInfoTip7': '¿Te gusta Open Design? Danos una estrella en GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'Sigue a @nexudotio en X para conocer las novedades.',
|
||||
'designFiles.usefulInfoTip8': 'Sigue a @OpenDesignHQ en X para conocer las novedades.',
|
||||
'designFiles.usefulInfoTip9': 'Arrastra imágenes, documentos o carpetas enteras a este panel: el agente los usará como contexto.',
|
||||
'designFiles.usefulInfoTip10': 'Haz clic en «Nuevo boceto», dibuja un layout y deja que el agente lo genere.',
|
||||
'designFiles.usefulInfoTip11': 'Selecciona cualquier elemento en la vista previa para comentarlo: el agente hará cambios concretos.',
|
||||
@@ -3189,6 +3200,9 @@ export const esES: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const fa: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Get product updates, new templates, design-system drops, and ambassador work in your inbox. Optional — you can skip this.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'ورود به Open Design',
|
||||
'settings.onboardingCloudBody': 'وارد شوید و بیدرنگ با هوش مصنوعی ابری طراحی را آغاز کنید؛ بدون هیچ پیکربندی پیچیدهای.',
|
||||
'settings.onboardingCloudSignIn': 'ورود به Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'ادامه (وارد شدهاید)',
|
||||
'settings.onboardingCloudAlternative': 'از یک CLI محلی یا کلید API خودتان استفاده کنید',
|
||||
'settings.onboardingCloudRights': 'همهٔ حقوق محفوظ است.',
|
||||
'settings.onboardingCloudOr': 'یا',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'مراحل بعدی با هوش مصنوعی اجرا میشوند — برای ادامه یک روش اجرا انتخاب کنید.',
|
||||
'settings.onboardingGateTooltipAmr': 'مراحل بعدی با هوش مصنوعی اجرا میشوند — برای ادامه وارد Open Design AMR شوید.',
|
||||
'settings.onboardingGateTooltipLocal': 'مراحل بعدی با هوش مصنوعی اجرا میشوند — برای ادامه یک CLI محلی در دسترس انتخاب کنید.',
|
||||
'settings.onboardingGateTooltipByok': 'مراحل بعدی با هوش مصنوعی اجرا میشوند — برای ادامه کلید مدل خود را افزوده و تست کنید.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'رسمی',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const fa: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 آژانس بازاریابی',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const fa: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'تنظیمات',
|
||||
'settings.title': 'حالت اجرا',
|
||||
'settings.subtitle': 'بین CLI محلی و BYOK انتخاب کنید.',
|
||||
@@ -464,7 +475,7 @@ export const fa: Dict = {
|
||||
'entry.discordAria': 'به Discord اوپن دیزاین بپیوندید',
|
||||
'entry.discordAriaWithOnline': 'به Discord اوپن دیزاین بپیوندید - {online}',
|
||||
'entry.discordOnlineLabel': '{count} آنلاین',
|
||||
'entry.followXLabel': 'دنبال کردن @nexudotio در X',
|
||||
'entry.followXLabel': 'دنبال کردن @OpenDesignHQ در X',
|
||||
'entry.resizeAria': 'تغییر اندازه نوار کناری',
|
||||
'entry.loadingWorkspace': 'در حال بارگذاری فضای کاری…',
|
||||
'entry.useEverywhereTitle': 'استفاده در همهجا',
|
||||
@@ -2004,7 +2015,7 @@ export const fa: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'ایدهای ندارید؟ قالبهای افزونه در بخش انجمن صفحهٔ اصلی را امتحان کنید.',
|
||||
'designFiles.usefulInfoTip6': 'سؤال یا پیشنهادی دارید؟ به Discord ما بپیوندید.',
|
||||
'designFiles.usefulInfoTip7': 'از Open Design راضی هستید؟ در GitHub به ما ستاره بدهید.',
|
||||
'designFiles.usefulInfoTip8': 'برای آخرین خبرها @nexudotio را در X دنبال کنید.',
|
||||
'designFiles.usefulInfoTip8': 'برای آخرین خبرها @OpenDesignHQ را در X دنبال کنید.',
|
||||
'designFiles.usefulInfoTip9': 'تصاویر، اسناد یا حتی کل پوشهها را به این پنل بکشید — عامل از آنها به عنوان زمینه استفاده میکند.',
|
||||
'designFiles.usefulInfoTip10': 'روی «طرح جدید» کلیک کنید و یک چیدمان بکشید تا عامل بر اساس آن بسازد.',
|
||||
'designFiles.usefulInfoTip11': 'هر عنصری را در پیشنمایش انتخاب و نظر بدهید — عامل همان بخش را اصلاح میکند.',
|
||||
@@ -3184,6 +3195,9 @@ export const fa: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const fr: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Recevez les nouveautés produit, les nouveaux modèles, les nouveaux systèmes de design et les réalisations des ambassadeurs par e-mail. Facultatif — vous pouvez ignorer cette étape.',
|
||||
'settings.onboardingConnectTitle': 'Choisir un runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Se connecter à Open Design',
|
||||
'settings.onboardingCloudBody': 'Connectez-vous et créez immédiatement avec l’IA cloud, sans configuration complexe.',
|
||||
'settings.onboardingCloudSignIn': 'Se connecter à Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'Continuer (connecté)',
|
||||
'settings.onboardingCloudAlternative': 'Utiliser une CLI locale ou votre propre clé API',
|
||||
'settings.onboardingCloudRights': 'Tous droits réservés.',
|
||||
'settings.onboardingCloudOr': 'ou',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'Les étapes suivantes tournent sur IA — choisissez un runtime pour continuer.',
|
||||
'settings.onboardingGateTooltipAmr': 'Les étapes suivantes tournent sur IA — connectez-vous à Open Design AMR pour continuer.',
|
||||
'settings.onboardingGateTooltipLocal': 'Les étapes suivantes tournent sur IA — sélectionnez une CLI locale disponible pour continuer.',
|
||||
'settings.onboardingGateTooltipByok': 'Les étapes suivantes tournent sur IA — ajoutez et testez votre clé de modèle pour continuer.',
|
||||
'settings.onboardingRecommended': 'Recommandé',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Officiel',
|
||||
'settings.onboardingLocalTitle': 'Agent de code local',
|
||||
@@ -169,6 +180,7 @@ export const fr: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Ingénieur',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Agence marketing',
|
||||
'settings.onboardingRoleGrowth': '📈 Croissance',
|
||||
'settings.onboardingRoleOps': '⚙️ Opérations',
|
||||
'settings.onboardingRoleFounder': '🚀 Fondateur / dirigeant',
|
||||
@@ -197,7 +209,6 @@ export const fr: Dict = {
|
||||
'settings.onboardingBack': 'Retour',
|
||||
'settings.onboardingContinue': 'Continuer',
|
||||
'settings.onboardingFinish': 'Terminer la configuration',
|
||||
'settings.onboardingSkip': 'Ignorer pour l’instant',
|
||||
'settings.kicker': 'Paramètres',
|
||||
'settings.title': 'Mode d\'exécution',
|
||||
'settings.subtitle': 'Choisissez entre CLI local et BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const fr: Dict = {
|
||||
'entry.discordAria': 'Rejoindre le Discord d’Open Design',
|
||||
'entry.discordAriaWithOnline': 'Rejoindre le Discord d’Open Design - {online}',
|
||||
'entry.discordOnlineLabel': '{count} en ligne',
|
||||
'entry.followXLabel': 'Suivre @nexudotio sur X',
|
||||
'entry.followXLabel': 'Suivre @OpenDesignHQ sur X',
|
||||
'entry.resizeAria': 'Redimensionner la barre latérale',
|
||||
'entry.loadingWorkspace': 'Chargement de l\'espace de travail…',
|
||||
'entry.useEverywhereTitle': 'Utiliser partout',
|
||||
@@ -2004,7 +2015,7 @@ export const fr: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'En panne d’idées ? Essayez un modèle de plugin dans Communauté, sur l’accueil.',
|
||||
'designFiles.usefulInfoTip6': 'Questions ou suggestions ? Rejoignez-nous sur Discord.',
|
||||
'designFiles.usefulInfoTip7': 'Open Design vous plaît ? Donnez-nous une étoile sur GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'Suivez @nexudotio sur X pour suivre les nouveautés.',
|
||||
'designFiles.usefulInfoTip8': 'Suivez @OpenDesignHQ sur X pour suivre les nouveautés.',
|
||||
'designFiles.usefulInfoTip9': 'Glissez images, documents ou dossiers entiers dans ce panneau — l’agent les utilisera comme contexte.',
|
||||
'designFiles.usefulInfoTip10': 'Cliquez sur « Nouveau croquis », dessinez une mise en page et laissez l’agent la générer.',
|
||||
'designFiles.usefulInfoTip11': 'Sélectionnez un élément dans l’aperçu pour le commenter — l’agent fera des retouches ciblées.',
|
||||
@@ -3189,6 +3200,9 @@ export const fr: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const hu: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Get product updates, new templates, design-system drops, and ambassador work in your inbox. Optional — you can skip this.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Bejelentkezés az Open Designba',
|
||||
'settings.onboardingCloudBody': 'Jelentkezz be, és azonnal tervezz felhőalapú MI-vel – bonyolult beállítás nélkül.',
|
||||
'settings.onboardingCloudSignIn': 'Bejelentkezés az Open Design Cloudba',
|
||||
'settings.onboardingCloudContinue': 'Folytatás (bejelentkezve)',
|
||||
'settings.onboardingCloudAlternative': 'Helyi CLI vagy saját API-kulcs használata',
|
||||
'settings.onboardingCloudRights': 'Minden jog fenntartva.',
|
||||
'settings.onboardingCloudOr': 'vagy',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'A következő lépések MI-n futnak — válassz futtatókörnyezetet a folytatáshoz.',
|
||||
'settings.onboardingGateTooltipAmr': 'A következő lépések MI-n futnak — jelentkezz be az Open Design AMR-be a folytatáshoz.',
|
||||
'settings.onboardingGateTooltipLocal': 'A következő lépések MI-n futnak — válassz egy elérhető helyi CLI-t a folytatáshoz.',
|
||||
'settings.onboardingGateTooltipByok': 'A következő lépések MI-n futnak — add meg és teszteld a modellkulcsodat a folytatáshoz.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Hivatalos',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const hu: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Marketingügynökség',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const hu: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Beállítások',
|
||||
'settings.title': 'Végrehajtási mód',
|
||||
'settings.subtitle': 'Válassz helyi CLI és BYOK között.',
|
||||
@@ -464,7 +475,7 @@ export const hu: Dict = {
|
||||
'entry.discordAria': 'Csatlakozás az Open Design Discordhoz',
|
||||
'entry.discordAriaWithOnline': 'Csatlakozás az Open Design Discordhoz - {online}',
|
||||
'entry.discordOnlineLabel': '{count} online',
|
||||
'entry.followXLabel': 'Kövesd a @nexudotio fiókot az X-en',
|
||||
'entry.followXLabel': 'Kövesd a @OpenDesignHQ fiókot az X-en',
|
||||
'entry.resizeAria': 'Oldalsáv átméretezése',
|
||||
'entry.loadingWorkspace': 'Munkaterület betöltése…',
|
||||
'entry.useEverywhereTitle': 'Használat bárhol',
|
||||
@@ -2004,7 +2015,7 @@ export const hu: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Nincs ötleted? Próbálj ki egy plugin sablont a kezdőlap Közösség részében.',
|
||||
'designFiles.usefulInfoTip6': 'Kérdésed vagy javaslatod van? Csatlakozz hozzánk Discordon.',
|
||||
'designFiles.usefulInfoTip7': 'Tetszik az Open Design? Adj egy csillagot GitHubon.',
|
||||
'designFiles.usefulInfoTip8': 'Kövesd a @nexudotio fiókot X-en a friss hírekért.',
|
||||
'designFiles.usefulInfoTip8': 'Kövesd a @OpenDesignHQ fiókot X-en a friss hírekért.',
|
||||
'designFiles.usefulInfoTip9': 'Húzz képeket, dokumentumokat vagy egész mappákat erre a panelre — az ügynök kontextusként használja őket.',
|
||||
'designFiles.usefulInfoTip10': 'Kattints az „Új vázlat” gombra, rajzolj egy elrendezést, és az ügynök elkészíti.',
|
||||
'designFiles.usefulInfoTip11': 'Jelölj ki bármilyen elemet az előnézetben és írj megjegyzést — az ügynök célzottan módosít.',
|
||||
@@ -3189,6 +3200,9 @@ export const hu: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const id: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Get product updates, new templates, design-system drops, and ambassador work in your inbox. Optional — you can skip this.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Masuk ke Open Design',
|
||||
'settings.onboardingCloudBody': 'Masuk dan langsung mulai mendesain dengan AI cloud, tanpa pengaturan rumit.',
|
||||
'settings.onboardingCloudSignIn': 'Masuk ke Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'Lanjutkan (sudah masuk)',
|
||||
'settings.onboardingCloudAlternative': 'Gunakan CLI lokal atau kunci API Anda sendiri',
|
||||
'settings.onboardingCloudRights': 'Semua hak dilindungi.',
|
||||
'settings.onboardingCloudOr': 'atau',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'Langkah berikutnya berjalan dengan AI — pilih runtime untuk melanjutkan.',
|
||||
'settings.onboardingGateTooltipAmr': 'Langkah berikutnya berjalan dengan AI — masuk ke Open Design AMR untuk melanjutkan.',
|
||||
'settings.onboardingGateTooltipLocal': 'Langkah berikutnya berjalan dengan AI — pilih CLI lokal yang tersedia untuk melanjutkan.',
|
||||
'settings.onboardingGateTooltipByok': 'Langkah berikutnya berjalan dengan AI — tambahkan dan uji kunci model Anda untuk melanjutkan.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Resmi',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const id: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Agensi pemasaran',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const id: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Pengaturan',
|
||||
'settings.title': 'Mode eksekusi',
|
||||
'settings.subtitle': 'Pilih antara CLI lokal dan BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const id: Dict = {
|
||||
'entry.discordAria': 'Gabung Discord Open Design',
|
||||
'entry.discordAriaWithOnline': 'Gabung Discord Open Design - {online}',
|
||||
'entry.discordOnlineLabel': '{count} online',
|
||||
'entry.followXLabel': 'Ikuti @nexudotio di X',
|
||||
'entry.followXLabel': 'Ikuti @OpenDesignHQ di X',
|
||||
'entry.resizeAria': 'Ubah ukuran sidebar',
|
||||
'entry.loadingWorkspace': 'Memuat workspace...',
|
||||
'entry.useEverywhereTitle': 'Gunakan di mana saja',
|
||||
@@ -2004,7 +2015,7 @@ export const id: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Belum ada ide? Coba template plugin di Komunitas pada halaman Beranda.',
|
||||
'designFiles.usefulInfoTip6': 'Ada pertanyaan atau saran? Gabung Discord kami.',
|
||||
'designFiles.usefulInfoTip7': 'Suka Open Design? Beri kami bintang di GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'Ikuti @nexudotio di X untuk kabar terbaru.',
|
||||
'designFiles.usefulInfoTip8': 'Ikuti @OpenDesignHQ di X untuk kabar terbaru.',
|
||||
'designFiles.usefulInfoTip9': 'Seret gambar, dokumen, atau seluruh folder ke panel ini — agen akan memakainya sebagai konteks.',
|
||||
'designFiles.usefulInfoTip10': 'Klik Sketsa baru, gambar tata letak kasar, dan biarkan agen membuatnya.',
|
||||
'designFiles.usefulInfoTip11': 'Pilih elemen apa pun di pratinjau untuk berkomentar — agen akan mengubahnya secara terarah.',
|
||||
@@ -3189,6 +3200,9 @@ export const id: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const it: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Ricevi novità di prodotto, nuovi template, design system e attività degli ambassador nella tua casella. Opzionale — puoi saltare.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Accedi a Open Design',
|
||||
'settings.onboardingCloudBody': 'Accedi e inizia subito a progettare con l’IA nel cloud, senza configurazioni complesse.',
|
||||
'settings.onboardingCloudSignIn': 'Accedi a Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'Continua (accesso effettuato)',
|
||||
'settings.onboardingCloudAlternative': 'Usa una CLI locale o la tua chiave API',
|
||||
'settings.onboardingCloudRights': 'Tutti i diritti riservati.',
|
||||
'settings.onboardingCloudOr': 'o',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'I passaggi successivi vengono eseguiti tramite IA — scegli un runtime per continuare.',
|
||||
'settings.onboardingGateTooltipAmr': 'I passaggi successivi vengono eseguiti tramite IA — accedi a Open Design AMR per continuare.',
|
||||
'settings.onboardingGateTooltipLocal': 'I passaggi successivi vengono eseguiti tramite IA — seleziona una CLI locale disponibile per continuare.',
|
||||
'settings.onboardingGateTooltipByok': 'I passaggi successivi vengono eseguiti tramite IA — aggiungi e testa la tua chiave del modello per continuare.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Ufficiale',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const it: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Agenzia di marketing',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const it: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Impostazioni',
|
||||
'settings.title': 'Esecuzione e modello',
|
||||
'settings.subtitle': 'Scegli tra CLI locale e BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const it: Dict = {
|
||||
'entry.discordAria': 'Unisciti al Discord di Open Design',
|
||||
'entry.discordAriaWithOnline': 'Unisciti al Discord di Open Design - {online}',
|
||||
'entry.discordOnlineLabel': '{count} online',
|
||||
'entry.followXLabel': 'Segui @nexudotio su X',
|
||||
'entry.followXLabel': 'Segui @OpenDesignHQ su X',
|
||||
'entry.resizeAria': 'Ridimensiona la barra laterale',
|
||||
'entry.loadingWorkspace': 'Caricamento dello spazio di lavoro…',
|
||||
'entry.useEverywhereTitle': 'Usa ovunque',
|
||||
@@ -2004,7 +2015,7 @@ export const it: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Senza idee? Prova un template plugin nella Community in Home.',
|
||||
'designFiles.usefulInfoTip6': 'Domande o suggerimenti? Unisciti al nostro Discord.',
|
||||
'designFiles.usefulInfoTip7': 'Ti piace Open Design? Lascia una stella su GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'Segui @nexudotio su X per le ultime novità.',
|
||||
'designFiles.usefulInfoTip8': 'Segui @OpenDesignHQ su X per le ultime novità.',
|
||||
'designFiles.usefulInfoTip9': 'Trascina immagini, documenti o intere cartelle in questo pannello — l’agente li userà come contesto.',
|
||||
'designFiles.usefulInfoTip10': 'Clicca su «Nuovo schizzo», disegna un layout e lascia che l’agente lo generi.',
|
||||
'designFiles.usefulInfoTip11': 'Seleziona un elemento nell’anteprima per commentarlo — l’agente farà modifiche mirate.',
|
||||
@@ -3189,6 +3200,9 @@ export const it: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const ja: Dict = {
|
||||
'settings.onboardingNewsletterBody': '製品アップデート、新しいテンプレート、デザインシステム、アンバサダーの活動をメールでお届けします。任意 — スキップできます。',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Open Design にサインイン',
|
||||
'settings.onboardingCloudBody': 'サインインすれば、クラウド AI ですぐにデザインを始められます。複雑な設定は一切不要です。',
|
||||
'settings.onboardingCloudSignIn': 'Open Design Cloud にサインイン',
|
||||
'settings.onboardingCloudContinue': '続行(ログイン済み)',
|
||||
'settings.onboardingCloudAlternative': 'ローカル CLI または自分の API キーを使う',
|
||||
'settings.onboardingCloudRights': 'All rights reserved.',
|
||||
'settings.onboardingCloudOr': 'または',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'この先のステップは AI で実行されます。続けるには実行方法を選んでください。',
|
||||
'settings.onboardingGateTooltipAmr': 'この先のステップは AI で実行されます。続けるには Open Design AMR にサインインしてください。',
|
||||
'settings.onboardingGateTooltipLocal': 'この先のステップは AI で実行されます。続けるには利用可能なローカル CLI を選んでください。',
|
||||
'settings.onboardingGateTooltipByok': 'この先のステップは AI で実行されます。続けるにはモデルキーを追加してテストしてください。',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': '公式',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const ja: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 マーケティング代理店',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const ja: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': '設定',
|
||||
'settings.title': '実行モード',
|
||||
'settings.subtitle': 'ローカル CLI と BYOK のどちらを使うか選択します。',
|
||||
@@ -464,7 +475,7 @@ export const ja: Dict = {
|
||||
'entry.discordAria': 'Open Design の Discord に参加',
|
||||
'entry.discordAriaWithOnline': 'Open Design の Discord に参加 - {online}',
|
||||
'entry.discordOnlineLabel': '{count} 人がオンライン',
|
||||
'entry.followXLabel': 'X で @nexudotio をフォロー',
|
||||
'entry.followXLabel': 'X で @OpenDesignHQ をフォロー',
|
||||
'entry.resizeAria': 'サイドバーをリサイズ',
|
||||
'entry.loadingWorkspace': 'ワークスペースを読み込み中…',
|
||||
'entry.useEverywhereTitle': 'どこでも使う',
|
||||
@@ -2004,7 +2015,7 @@ export const ja: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'アイデアに迷ったら、ホームのコミュニティにあるプラグインテンプレートをお試しください。',
|
||||
'designFiles.usefulInfoTip6': '質問やご意見は、Discord でお気軽にどうぞ。',
|
||||
'designFiles.usefulInfoTip7': '気に入ったら、GitHub でスターをお願いします。',
|
||||
'designFiles.usefulInfoTip8': 'X で @nexudotio をフォローして最新情報をチェック。',
|
||||
'designFiles.usefulInfoTip8': 'X で @OpenDesignHQ をフォローして最新情報をチェック。',
|
||||
'designFiles.usefulInfoTip9': '画像やドキュメント、フォルダーごとこのパネルにドラッグすると、エージェントがコンテキストとして使用します。',
|
||||
'designFiles.usefulInfoTip10': 'スケッチ機能でラフなレイアウトを描くと、エージェントがそれを元に生成します。',
|
||||
'designFiles.usefulInfoTip11': 'プレビューで要素を選択してコメントすると、エージェントがその箇所を修正します。',
|
||||
@@ -3189,6 +3200,9 @@ export const ja: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const ko: Dict = {
|
||||
'settings.onboardingNewsletterBody': '제품 업데이트, 새 템플릿, 디자인 시스템, 앰배서더 활동을 메일로 받아보세요. 선택 사항이며 건너뛸 수 있습니다.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Open Design에 로그인',
|
||||
'settings.onboardingCloudBody': '로그인하면 클라우드 AI로 바로 디자인을 시작할 수 있습니다. 복잡한 설정이 전혀 필요 없습니다.',
|
||||
'settings.onboardingCloudSignIn': 'Open Design Cloud에 로그인',
|
||||
'settings.onboardingCloudContinue': '계속 (로그인됨)',
|
||||
'settings.onboardingCloudAlternative': '로컬 CLI 또는 자체 API 키 사용',
|
||||
'settings.onboardingCloudRights': 'All rights reserved.',
|
||||
'settings.onboardingCloudOr': '또는',
|
||||
'settings.onboardingGateTooltipNoRuntime': '다음 단계는 AI로 실행됩니다 — 계속하려면 실행 방식을 선택하세요.',
|
||||
'settings.onboardingGateTooltipAmr': '다음 단계는 AI로 실행됩니다 — 계속하려면 Open Design AMR에 로그인하세요.',
|
||||
'settings.onboardingGateTooltipLocal': '다음 단계는 AI로 실행됩니다 — 계속하려면 사용 가능한 로컬 CLI를 선택하세요.',
|
||||
'settings.onboardingGateTooltipByok': '다음 단계는 AI로 실행됩니다 — 계속하려면 모델 키를 추가하고 테스트하세요.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': '공식',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const ko: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 마케팅 에이전시',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const ko: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': '설정',
|
||||
'settings.title': '실행 모드',
|
||||
'settings.subtitle': '로컬 CLI와 BYOK 중에서 선택하세요.',
|
||||
@@ -464,7 +475,7 @@ export const ko: Dict = {
|
||||
'entry.discordAria': 'Open Design Discord 참여하기',
|
||||
'entry.discordAriaWithOnline': 'Open Design Discord 참여하기 - {online}',
|
||||
'entry.discordOnlineLabel': '{count}명 온라인',
|
||||
'entry.followXLabel': 'X에서 @nexudotio 팔로우하기',
|
||||
'entry.followXLabel': 'X에서 @OpenDesignHQ 팔로우하기',
|
||||
'entry.resizeAria': '사이드바 크기 조절',
|
||||
'entry.loadingWorkspace': '워크스페이스를 불러오는 중…',
|
||||
'entry.useEverywhereTitle': '어디서나 사용',
|
||||
@@ -2004,7 +2015,7 @@ export const ko: Dict = {
|
||||
'designFiles.usefulInfoTip5': '아이디어가 없다면 홈의 커뮤니티에서 플러그인 템플릿을 사용해 보세요.',
|
||||
'designFiles.usefulInfoTip6': '질문이나 제안이 있다면 Discord에서 함께 이야기해요.',
|
||||
'designFiles.usefulInfoTip7': '마음에 드셨다면 GitHub에서 스타를 눌러 주세요.',
|
||||
'designFiles.usefulInfoTip8': 'X에서 @nexudotio를 팔로우하고 최신 소식을 받아 보세요.',
|
||||
'designFiles.usefulInfoTip8': 'X에서 @OpenDesignHQ를 팔로우하고 최신 소식을 받아 보세요.',
|
||||
'designFiles.usefulInfoTip9': '이미지, 문서, 폴더째로 이 패널에 끌어다 놓으면 에이전트가 문맥으로 활용합니다.',
|
||||
'designFiles.usefulInfoTip10': '새 스케치로 레이아웃을 그리면 에이전트가 그대로 만들어 줍니다.',
|
||||
'designFiles.usefulInfoTip11': '미리보기에서 요소를 선택해 댓글을 남기면 에이전트가 해당 부분만 수정합니다.',
|
||||
@@ -3189,6 +3200,9 @@ export const ko: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const pl: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Otrzymuj nowości produktowe, nowe szablony, design systemy i działania ambasadorów na skrzynkę. Opcjonalne — możesz pominąć.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Zaloguj się do Open Design',
|
||||
'settings.onboardingCloudBody': 'Zaloguj się i od razu zacznij projektować z chmurową SI — bez skomplikowanej konfiguracji.',
|
||||
'settings.onboardingCloudSignIn': 'Zaloguj się do Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'Kontynuuj (zalogowano)',
|
||||
'settings.onboardingCloudAlternative': 'Użyj lokalnego CLI lub własnego klucza API',
|
||||
'settings.onboardingCloudRights': 'Wszelkie prawa zastrzeżone.',
|
||||
'settings.onboardingCloudOr': 'lub',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'Kolejne kroki działają na AI — wybierz środowisko uruchomieniowe, aby kontynuować.',
|
||||
'settings.onboardingGateTooltipAmr': 'Kolejne kroki działają na AI — zaloguj się do Open Design AMR, aby kontynuować.',
|
||||
'settings.onboardingGateTooltipLocal': 'Kolejne kroki działają na AI — wybierz dostępne lokalne CLI, aby kontynuować.',
|
||||
'settings.onboardingGateTooltipByok': 'Kolejne kroki działają na AI — dodaj i przetestuj swój klucz modelu, aby kontynuować.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Oficjalne',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const pl: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Agencja marketingowa',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const pl: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Ustawienia',
|
||||
'settings.title': 'Tryb wykonywania',
|
||||
'settings.subtitle': 'Wybierz lokalne CLI albo BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const pl: Dict = {
|
||||
'entry.discordAria': 'Dołącz do Discorda Open Design',
|
||||
'entry.discordAriaWithOnline': 'Dołącz do Discorda Open Design - {online}',
|
||||
'entry.discordOnlineLabel': '{count} online',
|
||||
'entry.followXLabel': 'Obserwuj @nexudotio na X',
|
||||
'entry.followXLabel': 'Obserwuj @OpenDesignHQ na X',
|
||||
'entry.resizeAria': 'Zmień rozmiar paska bocznego',
|
||||
'entry.loadingWorkspace': 'Ładowanie obszaru roboczego…',
|
||||
'entry.useEverywhereTitle': 'Używaj wszędzie',
|
||||
@@ -2004,7 +2015,7 @@ export const pl: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Brak pomysłów? Wypróbuj szablon wtyczki w sekcji Społeczność na stronie głównej.',
|
||||
'designFiles.usefulInfoTip6': 'Pytania lub sugestie? Dołącz do nas na Discordzie.',
|
||||
'designFiles.usefulInfoTip7': 'Podoba Ci się Open Design? Zostaw gwiazdkę na GitHubie.',
|
||||
'designFiles.usefulInfoTip8': 'Obserwuj @nexudotio na X, by śledzić nowości.',
|
||||
'designFiles.usefulInfoTip8': 'Obserwuj @OpenDesignHQ na X, by śledzić nowości.',
|
||||
'designFiles.usefulInfoTip9': 'Przeciągnij obrazy, dokumenty lub całe foldery do tego panelu — agent użyje ich jako kontekstu.',
|
||||
'designFiles.usefulInfoTip10': 'Kliknij „Nowy szkic”, narysuj układ, a agent wygeneruje go za Ciebie.',
|
||||
'designFiles.usefulInfoTip11': 'Zaznacz dowolny element w podglądzie i dodaj komentarz — agent wprowadzi punktowe zmiany.',
|
||||
@@ -3189,6 +3200,9 @@ export const pl: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const ptBR: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Receba novidades do produto, novos templates, design systems e trabalho de embaixadores no seu e-mail. Opcional — você pode pular.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Entrar no Open Design',
|
||||
'settings.onboardingCloudBody': 'Entre e comece a criar na hora com IA na nuvem, sem configurações complicadas.',
|
||||
'settings.onboardingCloudSignIn': 'Entrar no Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'Continuar (conectado)',
|
||||
'settings.onboardingCloudAlternative': 'Usar uma CLI local ou sua própria chave de API',
|
||||
'settings.onboardingCloudRights': 'Todos os direitos reservados.',
|
||||
'settings.onboardingCloudOr': 'ou',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'As próximas etapas rodam em IA — escolha um runtime para continuar.',
|
||||
'settings.onboardingGateTooltipAmr': 'As próximas etapas rodam em IA — faça login no Open Design AMR para continuar.',
|
||||
'settings.onboardingGateTooltipLocal': 'As próximas etapas rodam em IA — selecione uma CLI local disponível para continuar.',
|
||||
'settings.onboardingGateTooltipByok': 'As próximas etapas rodam em IA — adicione e teste sua chave de modelo para continuar.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Oficial',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const ptBR: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Agência de marketing',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const ptBR: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Configurações',
|
||||
'settings.title': 'Modo de execução',
|
||||
'settings.subtitle': 'Escolha entre CLI local e BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const ptBR: Dict = {
|
||||
'entry.discordAria': 'Entre no Discord do Open Design',
|
||||
'entry.discordAriaWithOnline': 'Entre no Discord do Open Design - {online}',
|
||||
'entry.discordOnlineLabel': '{count} online',
|
||||
'entry.followXLabel': 'Siga @nexudotio no X',
|
||||
'entry.followXLabel': 'Siga @OpenDesignHQ no X',
|
||||
'entry.resizeAria': 'Redimensionar barra lateral',
|
||||
'entry.loadingWorkspace': 'Carregando área de trabalho…',
|
||||
'entry.useEverywhereTitle': 'Usar em qualquer lugar',
|
||||
@@ -2004,7 +2015,7 @@ export const ptBR: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Sem ideias? Experimente um template de plugin na Comunidade, na página inicial.',
|
||||
'designFiles.usefulInfoTip6': 'Dúvidas ou sugestões? Entre no nosso Discord.',
|
||||
'designFiles.usefulInfoTip7': 'Gostou do Open Design? Deixe uma estrela no GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'Siga @nexudotio no X para acompanhar as novidades.',
|
||||
'designFiles.usefulInfoTip8': 'Siga @OpenDesignHQ no X para acompanhar as novidades.',
|
||||
'designFiles.usefulInfoTip9': 'Arraste imagens, documentos ou pastas inteiras para este painel — o agente usará tudo como contexto.',
|
||||
'designFiles.usefulInfoTip10': 'Clique em «Novo rascunho», desenhe um layout e deixe o agente gerá-lo.',
|
||||
'designFiles.usefulInfoTip11': 'Selecione qualquer elemento na prévia para comentar — o agente fará ajustes pontuais.',
|
||||
@@ -3189,6 +3200,9 @@ export const ptBR: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const ru: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Получайте новости продукта, новые шаблоны, дизайн-системы и работу амбассадоров на почту. Необязательно — можно пропустить.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Войти в Open Design',
|
||||
'settings.onboardingCloudBody': 'Войдите и сразу начните создавать с облачным ИИ — без сложных настроек.',
|
||||
'settings.onboardingCloudSignIn': 'Войти в Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'Продолжить (вы вошли)',
|
||||
'settings.onboardingCloudAlternative': 'Использовать локальный CLI или свой ключ API',
|
||||
'settings.onboardingCloudRights': 'Все права защищены.',
|
||||
'settings.onboardingCloudOr': 'или',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'Следующие шаги выполняются на ИИ — выберите способ запуска, чтобы продолжить.',
|
||||
'settings.onboardingGateTooltipAmr': 'Следующие шаги выполняются на ИИ — войдите в Open Design AMR, чтобы продолжить.',
|
||||
'settings.onboardingGateTooltipLocal': 'Следующие шаги выполняются на ИИ — выберите доступный локальный CLI, чтобы продолжить.',
|
||||
'settings.onboardingGateTooltipByok': 'Следующие шаги выполняются на ИИ — добавьте и протестируйте ключ модели, чтобы продолжить.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Официальный',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const ru: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Маркетинговое агентство',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const ru: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Настройки',
|
||||
'settings.title': 'Режим выполнения',
|
||||
'settings.subtitle': 'Выберите локальный CLI или BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const ru: Dict = {
|
||||
'entry.discordAria': 'Присоединиться к Discord-сообществу Open Design',
|
||||
'entry.discordAriaWithOnline': 'Присоединиться к Discord-сообществу Open Design — {online}',
|
||||
'entry.discordOnlineLabel': '{count} онлайн',
|
||||
'entry.followXLabel': 'Подписаться на @nexudotio в X',
|
||||
'entry.followXLabel': 'Подписаться на @OpenDesignHQ в X',
|
||||
'entry.resizeAria': 'Изменить размер боковой панели',
|
||||
'entry.loadingWorkspace': 'Загрузка рабочего пространства…',
|
||||
'entry.useEverywhereTitle': 'Использовать везде',
|
||||
@@ -2004,7 +2015,7 @@ export const ru: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Нет идей? Попробуйте шаблон плагина в разделе «Сообщество» на главной.',
|
||||
'designFiles.usefulInfoTip6': 'Вопросы или идеи? Присоединяйтесь к нам в Discord.',
|
||||
'designFiles.usefulInfoTip7': 'Нравится Open Design? Поставьте звезду на GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'Подписывайтесь на @nexudotio в X, чтобы не пропустить новинки.',
|
||||
'designFiles.usefulInfoTip8': 'Подписывайтесь на @OpenDesignHQ в X, чтобы не пропустить новинки.',
|
||||
'designFiles.usefulInfoTip9': 'Перетащите изображения, документы или целые папки в эту панель — агент использует их как контекст.',
|
||||
'designFiles.usefulInfoTip10': 'Нажмите «Новый эскиз», нарисуйте макет — агент сгенерирует дизайн по нему.',
|
||||
'designFiles.usefulInfoTip11': 'Выделите любой элемент в предпросмотре и оставьте комментарий — агент внесёт точечные правки.',
|
||||
@@ -3189,6 +3200,9 @@ export const ru: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const th: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Get product updates, new templates, design-system drops, and ambassador work in your inbox. Optional — you can skip this.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'ลงชื่อเข้าใช้ Open Design',
|
||||
'settings.onboardingCloudBody': 'ลงชื่อเข้าใช้แล้วเริ่มออกแบบด้วย AI บนคลาวด์ได้ทันที โดยไม่ต้องตั้งค่าที่ซับซ้อน',
|
||||
'settings.onboardingCloudSignIn': 'ลงชื่อเข้าใช้ Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'ดำเนินการต่อ (เข้าสู่ระบบแล้ว)',
|
||||
'settings.onboardingCloudAlternative': 'ใช้ CLI ในเครื่องหรือคีย์ API ของคุณเอง',
|
||||
'settings.onboardingCloudRights': 'สงวนลิขสิทธิ์ทั้งหมด',
|
||||
'settings.onboardingCloudOr': 'หรือ',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'ขั้นตอนต่อไปทำงานด้วย AI — เลือกวิธีรันเพื่อดำเนินการต่อ',
|
||||
'settings.onboardingGateTooltipAmr': 'ขั้นตอนต่อไปทำงานด้วย AI — ลงชื่อเข้าใช้ Open Design AMR เพื่อดำเนินการต่อ',
|
||||
'settings.onboardingGateTooltipLocal': 'ขั้นตอนต่อไปทำงานด้วย AI — เลือก CLI ในเครื่องที่พร้อมใช้งานเพื่อดำเนินการต่อ',
|
||||
'settings.onboardingGateTooltipByok': 'ขั้นตอนต่อไปทำงานด้วย AI — เพิ่มและทดสอบคีย์โมเดลของคุณเพื่อดำเนินการต่อ',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'อย่างเป็นทางการ',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const th: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 เอเจนซีการตลาด',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const th: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'การตั้งค่า',
|
||||
'settings.title': 'โหมดการรัน',
|
||||
'settings.subtitle': 'เลือกระหว่าง Local CLI และ BYOK',
|
||||
@@ -464,7 +475,7 @@ export const th: Dict = {
|
||||
'entry.discordAria': 'เข้าร่วม Discord ของ Open Design',
|
||||
'entry.discordAriaWithOnline': 'เข้าร่วม Discord ของ Open Design - {online}',
|
||||
'entry.discordOnlineLabel': 'ออนไลน์ {count} คน',
|
||||
'entry.followXLabel': 'ติดตาม @nexudotio บน X',
|
||||
'entry.followXLabel': 'ติดตาม @OpenDesignHQ บน X',
|
||||
'entry.resizeAria': 'ปรับขนาดแถบด้านข้าง',
|
||||
'entry.loadingWorkspace': 'กำลังโหลดพื้นที่ทำงาน…',
|
||||
'entry.useEverywhereTitle': 'ใช้ได้ทุกที่',
|
||||
@@ -2004,7 +2015,7 @@ export const th: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'ยังไม่มีไอเดีย? ลองเทมเพลตปลั๊กอินในคอมมูนิตี้บนหน้าแรก',
|
||||
'designFiles.usefulInfoTip6': 'มีคำถามหรือข้อเสนอแนะ? เข้าร่วม Discord ของเรา',
|
||||
'designFiles.usefulInfoTip7': 'ถ้าชอบ Open Design ฝากกดดาวให้เราบน GitHub',
|
||||
'designFiles.usefulInfoTip8': 'ติดตาม @nexudotio บน X เพื่อรับข่าวสารล่าสุด',
|
||||
'designFiles.usefulInfoTip8': 'ติดตาม @OpenDesignHQ บน X เพื่อรับข่าวสารล่าสุด',
|
||||
'designFiles.usefulInfoTip9': 'ลากรูป เอกสาร หรือทั้งโฟลเดอร์มาที่แผงนี้ เอเจนต์จะใช้เป็นบริบท',
|
||||
'designFiles.usefulInfoTip10': 'กด สเก็ตช์ใหม่ วาดเลย์เอาต์คร่าว ๆ แล้วให้เอเจนต์สร้างตาม',
|
||||
'designFiles.usefulInfoTip11': 'เลือกองค์ประกอบใดก็ได้ในพรีวิวเพื่อคอมเมนต์ เอเจนต์จะแก้ไขเฉพาะจุด',
|
||||
@@ -3189,6 +3200,9 @@ export const th: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const tr: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Ürün güncellemelerini, yeni şablonları, tasarım sistemlerini ve elçi çalışmalarını gelen kutunuzda alın. İsteğe bağlı — atlayabilirsiniz.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Open Design’a giriş yap',
|
||||
'settings.onboardingCloudBody': 'Giriş yap ve bulut yapay zekâsıyla hemen tasarlamaya başla — karmaşık kurulum gerekmez.',
|
||||
'settings.onboardingCloudSignIn': 'Open Design Cloud’a giriş yap',
|
||||
'settings.onboardingCloudContinue': 'Devam et (giriş yapıldı)',
|
||||
'settings.onboardingCloudAlternative': 'Yerel bir CLI ya da kendi API anahtarını kullan',
|
||||
'settings.onboardingCloudRights': 'Tüm hakları saklıdır.',
|
||||
'settings.onboardingCloudOr': 'veya',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'Sonraki adımlar yapay zekâ ile çalışır — devam etmek için bir çalışma yöntemi seçin.',
|
||||
'settings.onboardingGateTooltipAmr': 'Sonraki adımlar yapay zekâ ile çalışır — devam etmek için Open Design AMR’ye giriş yapın.',
|
||||
'settings.onboardingGateTooltipLocal': 'Sonraki adımlar yapay zekâ ile çalışır — devam etmek için kullanılabilir bir yerel CLI seçin.',
|
||||
'settings.onboardingGateTooltipByok': 'Sonraki adımlar yapay zekâ ile çalışır — devam etmek için model anahtarınızı ekleyip test edin.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Resmi',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const tr: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Pazarlama ajansı',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const tr: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Ayarlar',
|
||||
'settings.title': 'Yürütme modu',
|
||||
'settings.subtitle': 'Yerel CLI ile BYOK arasında seçim yapın.',
|
||||
@@ -464,7 +475,7 @@ export const tr: Dict = {
|
||||
'entry.discordAria': 'Open Design Discord\'una katılın',
|
||||
'entry.discordAriaWithOnline': 'Open Design Discord\'una katılın - {online}',
|
||||
'entry.discordOnlineLabel': '{count} çevrimiçi',
|
||||
'entry.followXLabel': 'X\'te @nexudotio hesabını takip et',
|
||||
'entry.followXLabel': 'X\'te @OpenDesignHQ hesabını takip et',
|
||||
'entry.resizeAria': 'Yan çubuğu yeniden boyutlandır',
|
||||
'entry.loadingWorkspace': 'Çalışma alanı yükleniyor…',
|
||||
'entry.useEverywhereTitle': 'Her yerde kullan',
|
||||
@@ -2004,7 +2015,7 @@ export const tr: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Fikriniz mi yok? Ana sayfadaki Topluluk bölümünden bir eklenti şablonu deneyin.',
|
||||
'designFiles.usefulInfoTip6': 'Soru veya öneriniz mi var? Discord sunucumuza katılın.',
|
||||
'designFiles.usefulInfoTip7': 'Beğendiyseniz GitHub üzerinde bize yıldız verin.',
|
||||
'designFiles.usefulInfoTip8': 'Yenilikler için X üzerinde @nexudotio hesabını takip edin.',
|
||||
'designFiles.usefulInfoTip8': 'Yenilikler için X üzerinde @OpenDesignHQ hesabını takip edin.',
|
||||
'designFiles.usefulInfoTip9': 'Görselleri, dokümanları veya klasörleri bu panele sürükleyin; ajan onları bağlam olarak kullanır.',
|
||||
'designFiles.usefulInfoTip10': 'Yeni eskiz ile kaba bir düzen çizin, ajan onu tasarıma dönüştürsün.',
|
||||
'designFiles.usefulInfoTip11': 'Önizlemede herhangi bir ögeyi seçip yorum bırakın; ajan hedefli düzenleme yapar.',
|
||||
@@ -3189,6 +3200,9 @@ export const tr: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const uk: Dict = {
|
||||
'settings.onboardingNewsletterBody': 'Отримуйте новини продукту, нові шаблони, дизайн-системи та роботу амбасадорів на пошту. Необов’язково — можна пропустити.',
|
||||
'settings.onboardingConnectTitle': 'Choose a runtime',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': 'Увійти в Open Design',
|
||||
'settings.onboardingCloudBody': 'Увійдіть і одразу почніть створювати з хмарним ШІ — без складних налаштувань.',
|
||||
'settings.onboardingCloudSignIn': 'Увійти в Open Design Cloud',
|
||||
'settings.onboardingCloudContinue': 'Продовжити (ви увійшли)',
|
||||
'settings.onboardingCloudAlternative': 'Використати локальний CLI або власний ключ API',
|
||||
'settings.onboardingCloudRights': 'Усі права захищено.',
|
||||
'settings.onboardingCloudOr': 'або',
|
||||
'settings.onboardingGateTooltipNoRuntime': 'Наступні кроки виконуються на ШІ — виберіть спосіб запуску, щоб продовжити.',
|
||||
'settings.onboardingGateTooltipAmr': 'Наступні кроки виконуються на ШІ — увійдіть в Open Design AMR, щоб продовжити.',
|
||||
'settings.onboardingGateTooltipLocal': 'Наступні кроки виконуються на ШІ — виберіть доступний локальний CLI, щоб продовжити.',
|
||||
'settings.onboardingGateTooltipByok': 'Наступні кроки виконуються на ШІ — додайте та протестуйте ключ моделі, щоб продовжити.',
|
||||
'settings.onboardingRecommended': 'Recommended',
|
||||
'settings.onboardingAmrCloudOfficialBadge': 'Офіційний',
|
||||
'settings.onboardingLocalTitle': 'Local coding agent',
|
||||
@@ -169,6 +180,7 @@ export const uk: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 Designer',
|
||||
'settings.onboardingRoleEngineer': '💻 Engineer',
|
||||
'settings.onboardingRoleMarketing': '📣 Marketing',
|
||||
'settings.onboardingRoleAgency': '📣 Маркетингова агенція',
|
||||
'settings.onboardingRoleGrowth': '📈 Growth',
|
||||
'settings.onboardingRoleOps': '⚙️ Operations',
|
||||
'settings.onboardingRoleFounder': '🚀 Founder / executive',
|
||||
@@ -197,7 +209,6 @@ export const uk: Dict = {
|
||||
'settings.onboardingBack': 'Back',
|
||||
'settings.onboardingContinue': 'Continue',
|
||||
'settings.onboardingFinish': 'Finish setup',
|
||||
'settings.onboardingSkip': 'Skip for now',
|
||||
'settings.kicker': 'Налаштування',
|
||||
'settings.title': 'Режим виконання',
|
||||
'settings.subtitle': 'Виберіть локальний CLI або BYOK.',
|
||||
@@ -464,7 +475,7 @@ export const uk: Dict = {
|
||||
'entry.discordAria': 'Приєднатися до Discord Open Design',
|
||||
'entry.discordAriaWithOnline': 'Приєднатися до Discord Open Design - {online}',
|
||||
'entry.discordOnlineLabel': '{count} онлайн',
|
||||
'entry.followXLabel': 'Стежити за @nexudotio в X',
|
||||
'entry.followXLabel': 'Стежити за @OpenDesignHQ в X',
|
||||
'entry.resizeAria': 'Змінити розмір бічної панелі',
|
||||
'entry.loadingWorkspace': 'Завантаження робочого простору…',
|
||||
'entry.useEverywhereTitle': 'Використовувати скрізь',
|
||||
@@ -2004,7 +2015,7 @@ export const uk: Dict = {
|
||||
'designFiles.usefulInfoTip5': 'Немає ідей? Спробуйте шаблон плагіна в розділі «Спільнота» на головній.',
|
||||
'designFiles.usefulInfoTip6': 'Питання чи пропозиції? Приєднуйтесь до нас у Discord.',
|
||||
'designFiles.usefulInfoTip7': 'Подобається Open Design? Поставте зірку на GitHub.',
|
||||
'designFiles.usefulInfoTip8': 'Стежте за @nexudotio в X, щоб дізнаватися про новинки.',
|
||||
'designFiles.usefulInfoTip8': 'Стежте за @OpenDesignHQ в X, щоб дізнаватися про новинки.',
|
||||
'designFiles.usefulInfoTip9': 'Перетягніть зображення, документи чи цілі папки в цю панель — агент використає їх як контекст.',
|
||||
'designFiles.usefulInfoTip10': 'Натисніть «Новий ескіз», намалюйте макет — агент згенерує дизайн за ним.',
|
||||
'designFiles.usefulInfoTip11': 'Виділіть будь-який елемент у попередньому перегляді й залиште коментар — агент внесе точкові правки.',
|
||||
@@ -3189,6 +3200,9 @@ export const uk: Dict = {
|
||||
'brand.colorsCount': '{count} colors',
|
||||
'brand.extracting': 'Extracting…',
|
||||
'brand.failed': 'Extraction failed',
|
||||
'brand.needsInput': 'Needs input',
|
||||
'brand.needsInputHint': 'Extraction paused — open the project to finish verification or answer the question.',
|
||||
'brand.appliedToChat': 'Using {name}',
|
||||
'brand.previewEmpty': 'Select a brand to preview',
|
||||
'brand.viewDetails': 'View details',
|
||||
'newBrand.title': 'New Brand',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const zhCN: Dict = {
|
||||
'settings.onboardingNewsletterBody': '留下邮箱,接收产品更新、新模板、设计系统资源和社区活动。',
|
||||
'settings.onboardingConnectTitle': '选择运行方式',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': '登录 Open Design',
|
||||
'settings.onboardingCloudBody': '登录后可直接用云端 AI 开始设计,无需任何复杂配置。',
|
||||
'settings.onboardingCloudSignIn': '登录 Open Design 云端',
|
||||
'settings.onboardingCloudContinue': '继续(已登录)',
|
||||
'settings.onboardingCloudAlternative': '使用本地 CLI 或自己的 API Key',
|
||||
'settings.onboardingCloudRights': '保留所有权利。',
|
||||
'settings.onboardingCloudOr': '或',
|
||||
'settings.onboardingGateTooltipNoRuntime': '后续流程由 AI 运行,请先选择一种运行方式。',
|
||||
'settings.onboardingGateTooltipAmr': '后续流程由 AI 运行,请先登录 Open Design AMR。',
|
||||
'settings.onboardingGateTooltipLocal': '后续流程由 AI 运行,请先选择一个可用的本地 CLI。',
|
||||
'settings.onboardingGateTooltipByok': '后续流程由 AI 运行,请先填写并测试通过你的模型 Key。',
|
||||
'settings.onboardingRecommended': '推荐',
|
||||
'settings.onboardingAmrCloudOfficialBadge': '官方',
|
||||
'settings.onboardingLocalTitle': '本地 Coding Agent',
|
||||
@@ -169,6 +180,7 @@ export const zhCN: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 设计师',
|
||||
'settings.onboardingRoleEngineer': '💻 研发',
|
||||
'settings.onboardingRoleMarketing': '📣 营销',
|
||||
'settings.onboardingRoleAgency': '📣 营销代理商',
|
||||
'settings.onboardingRoleGrowth': '📈 增长',
|
||||
'settings.onboardingRoleOps': '⚙️ 运营',
|
||||
'settings.onboardingRoleFounder': '🚀 创始人 / 管理者',
|
||||
@@ -197,7 +209,6 @@ export const zhCN: Dict = {
|
||||
'settings.onboardingBack': '上一步',
|
||||
'settings.onboardingContinue': '继续',
|
||||
'settings.onboardingFinish': '完成',
|
||||
'settings.onboardingSkip': '先跳过',
|
||||
'settings.kicker': '设置',
|
||||
'settings.title': '执行模式',
|
||||
'settings.subtitle': '在本机 CLI 与 BYOK 之间选择。',
|
||||
@@ -464,7 +475,7 @@ export const zhCN: Dict = {
|
||||
'entry.discordAria': '加入 Open Design Discord',
|
||||
'entry.discordAriaWithOnline': '加入 Open Design Discord - {online}',
|
||||
'entry.discordOnlineLabel': '{count} 在线',
|
||||
'entry.followXLabel': '在 X 上关注 @nexudotio',
|
||||
'entry.followXLabel': '在 X 上关注 @OpenDesignHQ',
|
||||
'entry.resizeAria': '调整侧边栏宽度',
|
||||
'entry.loadingWorkspace': '正在加载工作区…',
|
||||
'entry.useEverywhereTitle': '随处使用',
|
||||
@@ -2004,7 +2015,7 @@ export const zhCN: Dict = {
|
||||
'designFiles.usefulInfoTip5': '没有想法?试试首页 Community 的插件模板,一键生成同款。',
|
||||
'designFiles.usefulInfoTip6': '遇到问题或有建议?加入 Discord 和我们聊聊。',
|
||||
'designFiles.usefulInfoTip7': '觉得好用?在 GitHub 给我们点个 Star。',
|
||||
'designFiles.usefulInfoTip8': '在 X 上关注 @nexudotio,第一时间了解新功能。',
|
||||
'designFiles.usefulInfoTip8': '在 X 上关注 @OpenDesignHQ,第一时间了解新功能。',
|
||||
'designFiles.usefulInfoTip9': '把图片、文档甚至整个文件夹拖到当前面板,智能体都会用作上下文。',
|
||||
'designFiles.usefulInfoTip10': '点「新建草图」手绘一个布局,让智能体照着生成。',
|
||||
'designFiles.usefulInfoTip11': '在预览中圈选任意元素发表评论,智能体会针对性修改。',
|
||||
@@ -3190,6 +3201,9 @@ export const zhCN: Dict = {
|
||||
'brand.colorsCount': '{count} 种颜色',
|
||||
'brand.extracting': '提取中…',
|
||||
'brand.failed': '提取失败',
|
||||
'brand.needsInput': '需要操作',
|
||||
'brand.needsInputHint': '提取已暂停 —— 打开项目完成验证或回答问题。',
|
||||
'brand.appliedToChat': '正在使用 {name}',
|
||||
'brand.previewEmpty': '选择一个设计系统进行预览',
|
||||
'brand.viewDetails': '查看详情',
|
||||
'newBrand.title': '新建设计系统',
|
||||
|
||||
@@ -128,6 +128,17 @@ export const zhTW: Dict = {
|
||||
'settings.onboardingNewsletterBody': '在信箱裡收到產品更新、新模版、設計系統與大使活動。選填——可以跳過。',
|
||||
'settings.onboardingConnectTitle': '選擇執行方式',
|
||||
'settings.onboardingConnectBody': '',
|
||||
'settings.onboardingCloudTitle': '登入 Open Design',
|
||||
'settings.onboardingCloudBody': '登入後可直接用雲端 AI 開始設計,無需任何複雜設定。',
|
||||
'settings.onboardingCloudSignIn': '登入 Open Design 雲端',
|
||||
'settings.onboardingCloudContinue': '繼續(已登入)',
|
||||
'settings.onboardingCloudAlternative': '使用本機 CLI 或自己的 API Key',
|
||||
'settings.onboardingCloudRights': '保留所有權利。',
|
||||
'settings.onboardingCloudOr': '或',
|
||||
'settings.onboardingGateTooltipNoRuntime': '後續流程由 AI 執行,請先選擇一種執行方式。',
|
||||
'settings.onboardingGateTooltipAmr': '後續流程由 AI 執行,請先登入 Open Design AMR。',
|
||||
'settings.onboardingGateTooltipLocal': '後續流程由 AI 執行,請先選擇一個可用的本機 CLI。',
|
||||
'settings.onboardingGateTooltipByok': '後續流程由 AI 執行,請先填寫並測試通過你的模型 Key。',
|
||||
'settings.onboardingRecommended': '推荐',
|
||||
'settings.onboardingAmrCloudOfficialBadge': '官方',
|
||||
'settings.onboardingLocalTitle': '本地 Coding Agent',
|
||||
@@ -169,6 +180,7 @@ export const zhTW: Dict = {
|
||||
'settings.onboardingRoleDesigner': '🎨 設計師',
|
||||
'settings.onboardingRoleEngineer': '💻 研發',
|
||||
'settings.onboardingRoleMarketing': '📣 行銷',
|
||||
'settings.onboardingRoleAgency': '📣 行銷代理商',
|
||||
'settings.onboardingRoleGrowth': '📈 增長',
|
||||
'settings.onboardingRoleOps': '⚙️ 營運',
|
||||
'settings.onboardingRoleFounder': '🚀 創辦人 / 管理者',
|
||||
@@ -197,7 +209,6 @@ export const zhTW: Dict = {
|
||||
'settings.onboardingBack': '上一步',
|
||||
'settings.onboardingContinue': '继续',
|
||||
'settings.onboardingFinish': '完成設定',
|
||||
'settings.onboardingSkip': '先跳過',
|
||||
'settings.kicker': '設定',
|
||||
'settings.title': '執行模式',
|
||||
'settings.subtitle': '在本機 CLI 與 BYOK 之間選擇。',
|
||||
@@ -464,7 +475,7 @@ export const zhTW: Dict = {
|
||||
'entry.discordAria': '加入 Open Design Discord',
|
||||
'entry.discordAriaWithOnline': '加入 Open Design Discord - {online}',
|
||||
'entry.discordOnlineLabel': '{count} 在線',
|
||||
'entry.followXLabel': '在 X 上追蹤 @nexudotio',
|
||||
'entry.followXLabel': '在 X 上追蹤 @OpenDesignHQ',
|
||||
'entry.resizeAria': '調整側邊欄寬度',
|
||||
'entry.loadingWorkspace': '正在載入工作區…',
|
||||
'entry.useEverywhereTitle': '隨處使用',
|
||||
@@ -2004,7 +2015,7 @@ export const zhTW: Dict = {
|
||||
'designFiles.usefulInfoTip5': '沒有想法?試試首頁「社群」的外掛模板,一鍵生成同款。',
|
||||
'designFiles.usefulInfoTip6': '遇到問題或有建議?加入 Discord 和我們聊聊。',
|
||||
'designFiles.usefulInfoTip7': '覺得好用?在 GitHub 給我們點個 Star。',
|
||||
'designFiles.usefulInfoTip8': '在 X 上關注 @nexudotio,第一時間了解新功能。',
|
||||
'designFiles.usefulInfoTip8': '在 X 上關注 @OpenDesignHQ,第一時間了解新功能。',
|
||||
'designFiles.usefulInfoTip9': '把圖片、文件甚至整個資料夾拖到目前面板,智慧體都會用作上下文。',
|
||||
'designFiles.usefulInfoTip10': '點「新建草圖」手繪一個版面,讓智慧體照著生成。',
|
||||
'designFiles.usefulInfoTip11': '在預覽中圈選任意元素發表評論,智慧體會針對性修改。',
|
||||
@@ -3190,6 +3201,9 @@ export const zhTW: Dict = {
|
||||
'brand.colorsCount': '{count} 種顏色',
|
||||
'brand.extracting': '擷取中…',
|
||||
'brand.failed': '擷取失敗',
|
||||
'brand.needsInput': '需要操作',
|
||||
'brand.needsInputHint': '提取已暫停 —— 開啟專案完成驗證或回答問題。',
|
||||
'brand.appliedToChat': '正在使用 {name}',
|
||||
'brand.previewEmpty': '選擇一個品牌進行預覽',
|
||||
'brand.viewDetails': '查看詳情',
|
||||
'newBrand.title': '新增品牌',
|
||||
|
||||
@@ -152,6 +152,17 @@ export interface Dict {
|
||||
'settings.onboardingNewsletterBody': string;
|
||||
'settings.onboardingConnectTitle': string;
|
||||
'settings.onboardingConnectBody': string;
|
||||
'settings.onboardingCloudTitle': string;
|
||||
'settings.onboardingCloudBody': string;
|
||||
'settings.onboardingCloudSignIn': string;
|
||||
'settings.onboardingCloudContinue': string;
|
||||
'settings.onboardingCloudAlternative': string;
|
||||
'settings.onboardingCloudOr': string;
|
||||
'settings.onboardingCloudRights': string;
|
||||
'settings.onboardingGateTooltipNoRuntime': string;
|
||||
'settings.onboardingGateTooltipAmr': string;
|
||||
'settings.onboardingGateTooltipLocal': string;
|
||||
'settings.onboardingGateTooltipByok': string;
|
||||
'settings.onboardingRecommended': string;
|
||||
'settings.onboardingAmrCloudOfficialBadge': string;
|
||||
'settings.onboardingLocalTitle': string;
|
||||
@@ -193,6 +204,7 @@ export interface Dict {
|
||||
'settings.onboardingRoleDesigner': string;
|
||||
'settings.onboardingRoleEngineer': string;
|
||||
'settings.onboardingRoleMarketing': string;
|
||||
'settings.onboardingRoleAgency': string;
|
||||
'settings.onboardingRoleGrowth': string;
|
||||
'settings.onboardingRoleOps': string;
|
||||
'settings.onboardingRoleFounder': string;
|
||||
@@ -221,7 +233,6 @@ export interface Dict {
|
||||
'settings.onboardingBack': string;
|
||||
'settings.onboardingContinue': string;
|
||||
'settings.onboardingFinish': string;
|
||||
'settings.onboardingSkip': string;
|
||||
'settings.kicker': string;
|
||||
'settings.title': string;
|
||||
'settings.subtitle': string;
|
||||
@@ -3332,6 +3343,9 @@ export interface Dict {
|
||||
'brand.colorsCount': string;
|
||||
'brand.extracting': string;
|
||||
'brand.failed': string;
|
||||
'brand.needsInput': string;
|
||||
'brand.needsInputHint': string;
|
||||
'brand.appliedToChat': string;
|
||||
'brand.previewEmpty': string;
|
||||
'brand.viewDetails': string;
|
||||
'newBrand.title': string;
|
||||
|
||||
@@ -96,10 +96,13 @@ export function parseRoute(pathname: string): Route {
|
||||
return { kind: 'home', view: 'design-systems' };
|
||||
}
|
||||
if (parts[0] === 'brands') {
|
||||
// Brands merged into Design systems: a brand is a `user:<id>` design system
|
||||
// and extraction now starts from the design-system create wizard. Legacy
|
||||
// `/brands` and `/brands/:id` deep-links redirect onto the unified tab.
|
||||
return { kind: 'home', view: 'design-systems' };
|
||||
// The Brands tab shows everything inline in its preview panel; there is no
|
||||
// separate detail view. A `/brands/:id` deep-link just preselects which
|
||||
// brand the inline preview renders.
|
||||
if (parts[1]) {
|
||||
return { kind: 'home', view: 'brands', brandId: decodeURIComponent(parts[1]) };
|
||||
}
|
||||
return { kind: 'home', view: 'brands' };
|
||||
}
|
||||
if (parts[0] === 'automations' || parts[0] === 'tasks') {
|
||||
return { kind: 'home', view: 'tasks' };
|
||||
|
||||
@@ -12,12 +12,21 @@
|
||||
export const HOME_CHIP_INTENT_EVENT = 'od:home-chip-intent';
|
||||
|
||||
let pendingChipId: string | null = null;
|
||||
let pendingNotice: string | null = null;
|
||||
|
||||
export interface HomeChipOptions {
|
||||
/** A one-shot confirmation banner HomeView shows once it consumes the chip —
|
||||
* e.g. "Using Ramp Brand Kit" after "Use in new chat". Makes an otherwise
|
||||
* invisible navigate+apply visibly verifiable to the user. */
|
||||
notice?: string;
|
||||
}
|
||||
|
||||
// Queue a Home composer chip to auto-select on the next Home render, then
|
||||
// notify any mounted HomeView. Safe to call before HomeView exists — the
|
||||
// pending id survives until consumed.
|
||||
export function requestHomeChip(chipId: string): void {
|
||||
// pending id (and optional confirmation notice) survives until consumed.
|
||||
export function requestHomeChip(chipId: string, options?: HomeChipOptions): void {
|
||||
pendingChipId = chipId;
|
||||
pendingNotice = options?.notice ?? null;
|
||||
if (typeof window !== 'undefined') {
|
||||
window.dispatchEvent(new CustomEvent(HOME_CHIP_INTENT_EVENT, { detail: { chipId } }));
|
||||
}
|
||||
@@ -30,6 +39,14 @@ export function consumePendingHomeChip(): string | null {
|
||||
return chipId;
|
||||
}
|
||||
|
||||
// Read and clear the pending confirmation notice queued alongside the chip.
|
||||
// Returns null when none is queued. Consume AFTER consumePendingHomeChip.
|
||||
export function consumePendingHomeNotice(): string | null {
|
||||
const notice = pendingNotice;
|
||||
pendingNotice = null;
|
||||
return notice;
|
||||
}
|
||||
|
||||
// Peek without consuming — lets a consumer bail early (e.g. plugins not yet
|
||||
// loaded) without dropping the pending intent.
|
||||
export function hasPendingHomeChip(): boolean {
|
||||
|
||||
@@ -66,6 +66,10 @@ async function openManualMemoryTab() {
|
||||
fireEvent.click(await screen.findByRole('tab', { name: 'Add manually' }));
|
||||
}
|
||||
|
||||
async function openAdvancedMemoryModal() {
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'Advanced' }));
|
||||
}
|
||||
|
||||
// The top-level "Memories" / "How it works" tabs render their label plus a
|
||||
// caption, so their accessible name is composite. Match by the leading label.
|
||||
const howItWorksTopTab = { name: /^How it works/ } as const;
|
||||
@@ -203,7 +207,6 @@ describe('MemorySection', () => {
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('UI preferences')).toBeTruthy();
|
||||
});
|
||||
expect(screen.getByText('✓ Memory created')).toBeTruthy();
|
||||
expect(createBodies).toEqual([
|
||||
{
|
||||
name: 'UI preferences',
|
||||
@@ -290,9 +293,7 @@ describe('MemorySection', () => {
|
||||
|
||||
renderMemorySection();
|
||||
|
||||
// The entry editor opened from a tree node renders inside the Add-manually
|
||||
// sub-tab.
|
||||
await openManualMemoryTab();
|
||||
await openAdvancedMemoryModal();
|
||||
const treeSummary = await screen.findByText('Memory tree');
|
||||
const treeDetails = treeSummary.closest('details')!;
|
||||
expect(within(treeDetails).getByText('/project')).toBeTruthy();
|
||||
@@ -378,6 +379,7 @@ describe('MemorySection', () => {
|
||||
|
||||
renderMemorySection();
|
||||
|
||||
await openAdvancedMemoryModal();
|
||||
const treeDetails = (await screen.findByText('Memory tree')).closest('details')!;
|
||||
const childRow = within(treeDetails)
|
||||
.getByText('Design agent goal')
|
||||
@@ -427,9 +429,7 @@ describe('MemorySection', () => {
|
||||
|
||||
renderMemorySection();
|
||||
|
||||
// The "✓ Index saved" flash toast renders inside the Add-manually sub-tab,
|
||||
// so open it before saving the index.
|
||||
await openManualMemoryTab();
|
||||
await openAdvancedMemoryModal();
|
||||
fireEvent.click(await screen.findByText('MEMORY.md (index)'));
|
||||
const indexArea = await findMemoryIndexTextarea();
|
||||
fireEvent.change(indexArea, {
|
||||
@@ -440,9 +440,8 @@ describe('MemorySection', () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save index' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('✓ Index saved')).toBeTruthy();
|
||||
expect(putBodies).toEqual(['# Memory\n\n- Existing bullet\n- New bullet\n']);
|
||||
});
|
||||
expect(putBodies).toEqual(['# Memory\n\n- Existing bullet\n- New bullet\n']);
|
||||
});
|
||||
|
||||
it('reveals the editor after editing an existing memory entry', async () => {
|
||||
@@ -563,6 +562,7 @@ describe('MemorySection', () => {
|
||||
const savedRow = await screen.findByText('UI preferences');
|
||||
const extractionRow = await screen.findByText('Remember I prefer dark mode');
|
||||
await openAddMemories();
|
||||
await openAdvancedMemoryModal();
|
||||
const indexSummary = screen.getByText('MEMORY.md (index)')
|
||||
.closest('summary') as HTMLElement;
|
||||
|
||||
@@ -572,7 +572,8 @@ describe('MemorySection', () => {
|
||||
expect(extractionRow.closest('.library-card')?.className).toContain(
|
||||
'memory-extraction-card',
|
||||
);
|
||||
expect(indexSummary.closest('.memory-advanced-section')).toBeTruthy();
|
||||
expect(indexSummary.closest('.memory-action-modal--advanced')).toBeTruthy();
|
||||
expect(indexSummary.closest('.memory-advanced-card')).toBeTruthy();
|
||||
expect(indexSummary.closest('.memory-records-section')).toBeNull();
|
||||
expect(screen.queryByText('Extraction history')).toBeNull();
|
||||
expect(indexSummary.className).toContain('memory-details-summary');
|
||||
@@ -1490,7 +1491,7 @@ describe('MemorySection', () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('✓ Memory saved')).toBeTruthy();
|
||||
expect(screen.getByText('Updated preference')).toBeTruthy();
|
||||
});
|
||||
expect(putBodies).toEqual([
|
||||
{
|
||||
@@ -1501,7 +1502,6 @@ describe('MemorySection', () => {
|
||||
body: '- Prefer spacious layouts',
|
||||
},
|
||||
]);
|
||||
expect(screen.getByText('Updated preference')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('keeps the expanded preview control visually distinct from delete', async () => {
|
||||
@@ -1706,6 +1706,7 @@ describe('MemorySection', () => {
|
||||
|
||||
renderMemorySection();
|
||||
|
||||
await openAdvancedMemoryModal();
|
||||
fireEvent.click(await screen.findByText('MEMORY.md (index)'));
|
||||
const indexArea = await findMemoryIndexTextarea();
|
||||
fireEvent.change(indexArea, {
|
||||
|
||||
Reference in New Issue
Block a user