@agent-native/core 0.147.0 → 0.148.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/analytics/DEVELOPING.md +50 -3
- package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
- package/corpus/templates/analytics/app/i18n/index.ts +14 -29
- package/corpus/templates/analytics/app/i18n-data.ts +10 -10
- package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
- package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +197 -18
- package/corpus/templates/analytics/server/db/schema.ts +23 -0
- package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
- package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
- package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
- package/corpus/templates/analytics/server/plugins/db.ts +42 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/assets/app/i18n/index.ts +14 -29
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/brain/app/i18n/index.ts +14 -29
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/chat/app/i18n/index.ts +14 -29
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
- package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
- package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
- package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
- package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
- package/corpus/templates/clips/desktop/src/app.tsx +1 -1
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/content/app/i18n/index.ts +14 -29
- package/corpus/templates/crm/app/i18n/index.ts +14 -29
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/design/actions/import-code.ts +2 -43
- package/corpus/templates/design/app/i18n/index.ts +14 -29
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/dispatch/app/i18n-data.ts +1 -1
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/factory/AGENTS.md +40 -49
- package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
- package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
- package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
- package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
- package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
- package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
- package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
- package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
- package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
- package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
- package/corpus/templates/factory/app/routes/factory.tsx +95 -42
- package/corpus/templates/factory/server/db/schema.ts +37 -0
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
- package/corpus/templates/factory/server/triage/audit.ts +79 -0
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/forms/app/i18n/index.ts +14 -29
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/macros/app/i18n/index.ts +14 -29
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/mail/app/i18n/index.ts +14 -29
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
- package/corpus/templates/plan/app/i18n/index.ts +14 -29
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/slides/actions/import-code.ts +2 -43
- package/corpus/templates/slides/app/i18n/index.ts +14 -29
- package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
- package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
- package/corpus/templates/tasks/app/i18n/index.ts +14 -29
- package/dist/agent/engine/ai-sdk-engine.js +2 -1
- package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
- package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
- package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
- package/dist/agent/engine/provider-endpoint-validation.js +26 -0
- package/dist/agent/engine/provider-env-vars.d.ts +1 -1
- package/dist/agent/engine/provider-env-vars.js +1 -1
- package/dist/agent/engine/registry.d.ts +8 -6
- package/dist/agent/engine/registry.js +37 -24
- package/dist/agent/tool-search.d.ts +1 -0
- package/dist/agent/tool-search.js +17 -1
- package/dist/automations/service.js +4 -10
- package/dist/brand-kit/brand-signals.d.ts +13 -0
- package/dist/brand-kit/brand-signals.js +15 -0
- package/dist/brand-kit/index.d.ts +2 -2
- package/dist/brand-kit/index.js +1 -1
- package/dist/cli/plan-blocks.d.ts +3 -18
- package/dist/cli/plan-blocks.js +2 -95
- package/dist/cli/plan-publish-store.d.ts +2 -61
- package/dist/cli/plan-publish-store.js +2 -127
- package/dist/cli/skills-content/connection.d.ts +1 -1
- package/dist/cli/skills-content/connection.js +1 -52
- package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-recap-skill.js +1 -553
- package/dist/client/agent-engine-key.d.ts +14 -4
- package/dist/client/agent-engine-key.js +51 -5
- package/dist/client/agent-provider-catalog.d.ts +20 -0
- package/dist/client/agent-provider-catalog.js +100 -0
- package/dist/client/blocks/index.d.ts +1 -0
- package/dist/client/blocks/index.js +1 -0
- package/dist/client/blocks/library/diagram.js +1 -1
- package/dist/client/blocks/library/sanitize-html.js +66 -2
- package/dist/client/blocks/library/wireframe-kit.js +69 -0
- package/dist/client/chat/run-recovery.js +4 -48
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +4 -4
- package/dist/client/chat-first/copy.js +1 -0
- package/dist/client/chat-first/types.d.ts +1 -0
- package/dist/client/chat-first.js +4 -3
- package/dist/client/i18n.d.ts +14 -0
- package/dist/client/i18n.js +18 -0
- package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
- package/dist/client/settings/ProviderSetupForm.js +145 -0
- package/dist/client/settings/SettingsPanel.js +52 -49
- package/dist/client/settings/index.d.ts +2 -0
- package/dist/client/settings/index.js +2 -0
- package/dist/coding-tools/run-code.d.ts +5 -0
- package/dist/coding-tools/run-code.js +196 -36
- package/dist/coding-tools/tool-orchestration.d.ts +10 -0
- package/dist/coding-tools/tool-orchestration.js +107 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/jobs/frontmatter.d.ts +9 -0
- package/dist/jobs/frontmatter.js +16 -0
- package/dist/jobs/scheduler.js +8 -8
- package/dist/jobs/tools.d.ts +1 -1
- package/dist/jobs/tools.js +2 -7
- package/dist/localization/default-messages.d.ts +20 -0
- package/dist/localization/default-messages.js +25 -5
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +2 -2
- package/dist/onboarding/app-profile.js +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
- package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
- package/dist/server/agent-chat/run-code-tools.js +3 -1
- package/dist/server/agent-chat-plugin.js +6 -6
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.js +43 -12
- package/dist/server/agents-bundle.js +2 -1
- package/dist/server/auth.js +21 -5
- package/dist/server/credential-provider.js +1 -0
- package/dist/server/design-token-utils.d.ts +18 -0
- package/dist/server/design-token-utils.js +31 -0
- package/dist/server/onboarding-html.js +22 -2
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/styles/blocks.css +132 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/chat/app/i18n/index.ts +14 -29
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/default/app/i18n/index.ts +14 -29
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/triggers/dispatcher.js +1 -8
- package/docs/content/actions.mdx +4 -1
- package/docs/content/agent-surfaces.mdx +8 -6
- package/docs/content/automations.mdx +1 -1
- package/docs/content/database.mdx +6 -1
- package/docs/content/docs-components.mdx +22 -14
- package/docs/content/drop-in-agent.mdx +1 -1
- package/docs/content/environment-variables.mdx +39 -38
- package/docs/content/getting-started-actions.mdx +5 -4
- package/docs/content/getting-started-pages.mdx +7 -6
- package/docs/content/getting-started.mdx +4 -3
- package/docs/content/notifications.mdx +6 -6
- package/docs/content/progress.mdx +5 -5
- package/docs/content/routing.mdx +3 -1
- package/docs/content/server-database.mdx +13 -4
- package/docs/content/server-overview.mdx +9 -9
- package/docs/content/server-plugins.mdx +10 -4
- package/docs/content/server-routes.mdx +7 -2
- package/docs/content/tracking.mdx +4 -4
- package/docs/content/what-is-agent-native.mdx +4 -4
- package/package.json +4 -4
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/chat/app/i18n/index.ts +14 -29
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/default/app/i18n/index.ts +14 -29
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type AgentProviderId = "anthropic" | "openai" | "openrouter" | "google" | "groq" | "mistral" | "cohere" | "ollama";
|
|
2
|
+
export interface AgentProviderOption {
|
|
3
|
+
id: AgentProviderId;
|
|
4
|
+
engine: string;
|
|
5
|
+
label: string;
|
|
6
|
+
description: string;
|
|
7
|
+
key?: string;
|
|
8
|
+
endpointKey?: string;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
defaultModel: string;
|
|
11
|
+
supportedModels: readonly string[];
|
|
12
|
+
docsUrl?: string;
|
|
13
|
+
supportsCustomModel?: boolean;
|
|
14
|
+
supportsEndpoint?: boolean;
|
|
15
|
+
endpointPlaceholder?: string;
|
|
16
|
+
kind: "cloud" | "gateway" | "local";
|
|
17
|
+
}
|
|
18
|
+
export declare const AGENT_PROVIDER_CATALOG: readonly AgentProviderOption[];
|
|
19
|
+
export declare function getAgentProviderOption(provider: AgentProviderId): AgentProviderOption;
|
|
20
|
+
export declare function providerIdForEngine(engine: string): AgentProviderId | null;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { OLLAMA_BASE_URL_ENV_VAR, OPENAI_BASE_URL_ENV_VAR, PROVIDER_ENV_META, } from "../agent/engine/provider-env-vars.js";
|
|
2
|
+
import { AI_SDK_MODEL_CONFIG, ANTHROPIC_MODEL_CONFIG, } from "../agent/model-config.js";
|
|
3
|
+
const PROVIDER_LABELS = {
|
|
4
|
+
anthropic: "Anthropic",
|
|
5
|
+
openai: "OpenAI",
|
|
6
|
+
openrouter: "OpenRouter",
|
|
7
|
+
google: "Google Gemini",
|
|
8
|
+
groq: "Groq",
|
|
9
|
+
mistral: "Mistral",
|
|
10
|
+
cohere: "Cohere",
|
|
11
|
+
ollama: "Ollama",
|
|
12
|
+
};
|
|
13
|
+
const PROVIDER_DESCRIPTIONS = {
|
|
14
|
+
anthropic: "Claude models with your own API key.",
|
|
15
|
+
openai: "GPT models and OpenAI-compatible gateways.",
|
|
16
|
+
openrouter: "One key for hundreds of hosted models.",
|
|
17
|
+
google: "Gemini models with a Google AI key.",
|
|
18
|
+
groq: "Fast inference for open models.",
|
|
19
|
+
mistral: "Mistral models through the Mistral API.",
|
|
20
|
+
cohere: "Command models through the Cohere API.",
|
|
21
|
+
ollama: "Run local models from Ollama on your machine.",
|
|
22
|
+
};
|
|
23
|
+
const PROVIDER_DOCS = {
|
|
24
|
+
anthropic: "https://console.anthropic.com/settings/keys",
|
|
25
|
+
openai: "https://platform.openai.com/api-keys",
|
|
26
|
+
openrouter: "https://openrouter.ai/keys",
|
|
27
|
+
google: "https://aistudio.google.com/apikey",
|
|
28
|
+
groq: "https://console.groq.com/keys",
|
|
29
|
+
mistral: "https://console.mistral.ai/api-keys/",
|
|
30
|
+
cohere: "https://dashboard.cohere.com/api-keys",
|
|
31
|
+
};
|
|
32
|
+
const PROVIDER_ORDER = [
|
|
33
|
+
"openrouter",
|
|
34
|
+
"ollama",
|
|
35
|
+
"anthropic",
|
|
36
|
+
"openai",
|
|
37
|
+
"google",
|
|
38
|
+
"groq",
|
|
39
|
+
"mistral",
|
|
40
|
+
"cohere",
|
|
41
|
+
];
|
|
42
|
+
function modelConfig(provider) {
|
|
43
|
+
if (provider === "anthropic")
|
|
44
|
+
return ANTHROPIC_MODEL_CONFIG;
|
|
45
|
+
return AI_SDK_MODEL_CONFIG[provider];
|
|
46
|
+
}
|
|
47
|
+
export const AGENT_PROVIDER_CATALOG = PROVIDER_ORDER.map((id) => {
|
|
48
|
+
const config = modelConfig(id);
|
|
49
|
+
const envMeta = PROVIDER_ENV_META[id];
|
|
50
|
+
const isOllama = id === "ollama";
|
|
51
|
+
return {
|
|
52
|
+
id,
|
|
53
|
+
engine: id === "anthropic" ? "anthropic" : `ai-sdk:${id}`,
|
|
54
|
+
label: PROVIDER_LABELS[id],
|
|
55
|
+
description: PROVIDER_DESCRIPTIONS[id],
|
|
56
|
+
...(envMeta
|
|
57
|
+
? { key: envMeta.envVar, placeholder: envMeta.placeholder }
|
|
58
|
+
: {}),
|
|
59
|
+
...(id === "openai"
|
|
60
|
+
? { endpointKey: OPENAI_BASE_URL_ENV_VAR }
|
|
61
|
+
: isOllama
|
|
62
|
+
? { endpointKey: OLLAMA_BASE_URL_ENV_VAR }
|
|
63
|
+
: {}),
|
|
64
|
+
defaultModel: config.defaultModel,
|
|
65
|
+
supportedModels: config.supportedModels,
|
|
66
|
+
...(PROVIDER_DOCS[id] ? { docsUrl: PROVIDER_DOCS[id] } : {}),
|
|
67
|
+
...(id === "openrouter" || isOllama ? { supportsCustomModel: true } : {}),
|
|
68
|
+
...(id === "openai" || isOllama
|
|
69
|
+
? {
|
|
70
|
+
supportsEndpoint: true,
|
|
71
|
+
endpointPlaceholder: isOllama
|
|
72
|
+
? "http://localhost:11434"
|
|
73
|
+
: "https://gateway.example/v1",
|
|
74
|
+
}
|
|
75
|
+
: {}),
|
|
76
|
+
kind: isOllama
|
|
77
|
+
? "local"
|
|
78
|
+
: id === "openrouter"
|
|
79
|
+
? "gateway"
|
|
80
|
+
: "cloud",
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
export function getAgentProviderOption(provider) {
|
|
84
|
+
const option = AGENT_PROVIDER_CATALOG.find((item) => item.id === provider);
|
|
85
|
+
if (!option)
|
|
86
|
+
throw new Error(`Unknown AI provider: ${provider}`);
|
|
87
|
+
return option;
|
|
88
|
+
}
|
|
89
|
+
export function providerIdForEngine(engine) {
|
|
90
|
+
if (engine === "anthropic" || engine === "ai-sdk:anthropic") {
|
|
91
|
+
return "anthropic";
|
|
92
|
+
}
|
|
93
|
+
if (engine.startsWith("ai-sdk:")) {
|
|
94
|
+
const provider = engine.slice("ai-sdk:".length);
|
|
95
|
+
if (AGENT_PROVIDER_CATALOG.some((option) => option.id === provider)) {
|
|
96
|
+
return provider;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
@@ -45,6 +45,7 @@ export { questionFormSchema, questionFormMdx, visualQuestionsSchema, visualQuest
|
|
|
45
45
|
export { diagramBlock, DiagramRead, DiagramEdit } from "./library/diagram.js";
|
|
46
46
|
export { diagramSchema, diagramMdx, type DiagramData, type DiagramNode, type DiagramEdge, type DiagramNote, } from "./library/diagram.config.js";
|
|
47
47
|
export { wireframeBlock, WireframeBlock, WireframeEditor, } from "./library/wireframe.js";
|
|
48
|
+
export { sanitizeDiagramHtml, sanitizeWireframeCss, sanitizeWireframeHtml, scopeDesignCss, } from "./library/sanitize-html.js";
|
|
48
49
|
export { wireframeSchema, wireframeMdx, createStableWireframeNodeId, WIREFRAME_SURFACES, WIREFRAME_EL_NAMES, type WireframeData, type WireframeNode, type WireframeElName, type WireframeTone, type WireframeSurface, type WireframeRenderMode, } from "./library/wireframe.config.js";
|
|
49
50
|
export { Screen, renderNode, renderNodes, hasRenderer, NODE_REGISTRY, KitConfigContext, RoughOverlay, HTML_ROUGH_SELECTOR, useWireframeStyle, setWireframeStyle, toggleWireframeStyle, useIsDark, type WireframeStyle, } from "./library/wireframe-kit.js";
|
|
50
51
|
export { renderWireframeIconHtml } from "./library/wireframe-icons.js";
|
|
@@ -56,6 +56,7 @@ export { questionFormSchema, questionFormMdx, visualQuestionsSchema, visualQuest
|
|
|
56
56
|
export { diagramBlock, DiagramRead, DiagramEdit } from "./library/diagram.js";
|
|
57
57
|
export { diagramSchema, diagramMdx, } from "./library/diagram.config.js";
|
|
58
58
|
export { wireframeBlock, WireframeBlock, WireframeEditor, } from "./library/wireframe.js";
|
|
59
|
+
export { sanitizeDiagramHtml, sanitizeWireframeCss, sanitizeWireframeHtml, scopeDesignCss, } from "./library/sanitize-html.js";
|
|
59
60
|
export { wireframeSchema, wireframeMdx, createStableWireframeNodeId, WIREFRAME_SURFACES, WIREFRAME_EL_NAMES, } from "./library/wireframe.config.js";
|
|
60
61
|
export { Screen, renderNode, renderNodes, hasRenderer, NODE_REGISTRY, KitConfigContext, RoughOverlay, HTML_ROUGH_SELECTOR, useWireframeStyle, setWireframeStyle, toggleWireframeStyle, useIsDark, } from "./library/wireframe-kit.js";
|
|
61
62
|
export { renderWireframeIconHtml } from "./library/wireframe-icons.js";
|
|
@@ -41,7 +41,7 @@ import { RoughOverlay, toggleWireframeStyle, useIsDark, useWireframeStyle, } fro
|
|
|
41
41
|
/* HTML/SVG diagram path */
|
|
42
42
|
/* -------------------------------------------------------------------------- */
|
|
43
43
|
/** The rough-overlay selector for diagram bordered boxes (mirrors the plan). */
|
|
44
|
-
const DIAGRAM_ROUGH_SELECTOR = "[data-rough],.diagram-panel,.diagram-node,.diagram-box,.diagram-pill,.diagram-card,[class*='card'],[class*='box'],[class*='panel'],[class*='pill'],[class*='chip'],[class*='badge'],hr";
|
|
44
|
+
const DIAGRAM_ROUGH_SELECTOR = "[data-rough],.diagram-panel,.diagram-node,.diagram-box,.diagram-pill,.diagram-card,.diagram-arrow[data-arrow],[class*='card'],[class*='box'],[class*='panel'],[class*='pill'],[class*='chip'],[class*='badge'],hr";
|
|
45
45
|
function HtmlDiagram({ data, ctx, compact, }) {
|
|
46
46
|
const ref = useRef(null);
|
|
47
47
|
const isDark = useIsDark();
|
|
@@ -30,6 +30,28 @@ const URL_ATTRS = new Set([
|
|
|
30
30
|
"ping",
|
|
31
31
|
]);
|
|
32
32
|
const SAFE_SCHEMES = new Set(["http:", "https:", "mailto:", "tel:", "ftp:"]);
|
|
33
|
+
const DIAGRAM_ARROW_DIRECTIONS = new Set([
|
|
34
|
+
"right",
|
|
35
|
+
"left",
|
|
36
|
+
"up",
|
|
37
|
+
"down",
|
|
38
|
+
"both",
|
|
39
|
+
"refresh",
|
|
40
|
+
]);
|
|
41
|
+
const DIAGRAM_ARROW_ENTITY_TEXT = {
|
|
42
|
+
"→": "→",
|
|
43
|
+
"←": "←",
|
|
44
|
+
"↑": "↑",
|
|
45
|
+
"↓": "↓",
|
|
46
|
+
"↔": "↔",
|
|
47
|
+
"←": "←",
|
|
48
|
+
"↑": "↑",
|
|
49
|
+
"→": "→",
|
|
50
|
+
"↓": "↓",
|
|
51
|
+
"↔": "↔",
|
|
52
|
+
"➡": "➡",
|
|
53
|
+
"↻": "↻",
|
|
54
|
+
};
|
|
33
55
|
const WHITESPACE = /\s+/g;
|
|
34
56
|
const HAS_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
|
|
35
57
|
const SAFE_DATA_IMAGE = /^data:image\/(png|jpe?g|gif|webp);/i;
|
|
@@ -109,6 +131,47 @@ function stripWireframeThemeClasses(value) {
|
|
|
109
131
|
.filter((className) => !isWireframeThemeClass(className))
|
|
110
132
|
.join(" ");
|
|
111
133
|
}
|
|
134
|
+
function diagramArrowDirection(value) {
|
|
135
|
+
const normalized = value
|
|
136
|
+
.replace(/&(?:r|l|u|d|h)arr;|&#(?:8592|8593|8594|8595|8596|8635|10145);/gi, (entity) => DIAGRAM_ARROW_ENTITY_TEXT[entity.toLowerCase()] ?? entity)
|
|
137
|
+
.replace(/\uFE0F/g, "")
|
|
138
|
+
.trim();
|
|
139
|
+
if (DIAGRAM_ARROW_DIRECTIONS.has(normalized))
|
|
140
|
+
return normalized;
|
|
141
|
+
if (/[↔⇄⇆⇔]/u.test(normalized))
|
|
142
|
+
return "both";
|
|
143
|
+
if (/[←⬅⇐]/u.test(normalized))
|
|
144
|
+
return "left";
|
|
145
|
+
if (/[↑⬆⇑]/u.test(normalized))
|
|
146
|
+
return "up";
|
|
147
|
+
if (/[↓⬇⇓]/u.test(normalized))
|
|
148
|
+
return "down";
|
|
149
|
+
if (/[↻↺⟳⟲]/u.test(normalized))
|
|
150
|
+
return "refresh";
|
|
151
|
+
if (/[→➡➜➔➝➞➟➠⇢⇒]/u.test(normalized))
|
|
152
|
+
return "right";
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
function normalizeDiagramArrows(root) {
|
|
156
|
+
root.querySelectorAll(".diagram-arrow").forEach((node) => {
|
|
157
|
+
const explicit = node.getAttribute("data-arrow");
|
|
158
|
+
const direction = DIAGRAM_ARROW_DIRECTIONS.has(explicit ?? "")
|
|
159
|
+
? explicit
|
|
160
|
+
: diagramArrowDirection(node.textContent ?? "");
|
|
161
|
+
if (!direction)
|
|
162
|
+
return;
|
|
163
|
+
node.setAttribute("data-arrow", direction);
|
|
164
|
+
node.replaceChildren();
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function normalizeFallbackDiagramArrows(html) {
|
|
168
|
+
return html.replace(/(<(?:div|span)\b[^>]*\bclass\s*=\s*(?:"[^"]*\bdiagram-arrow\b[^"]*"|'[^']*\bdiagram-arrow\b[^']*')[^>]*>)([\s\S]*?)(<\/(?:div|span)>)/gi, (_match, open, body, close) => {
|
|
169
|
+
const direction = diagramArrowDirection(body);
|
|
170
|
+
if (!direction)
|
|
171
|
+
return `${open}${body}${close}`;
|
|
172
|
+
return `${open.replace(/>$/, ` data-arrow="${direction}">`)}${close}`;
|
|
173
|
+
});
|
|
174
|
+
}
|
|
112
175
|
/** Conservative no-DOM fallback for any non-browser code path (SSR). */
|
|
113
176
|
function fallbackStrip(html, options) {
|
|
114
177
|
// Drop the whole url attribute if its value (whitespace/control-stripped)
|
|
@@ -147,13 +210,14 @@ export function sanitizeDiagramHtml(html) {
|
|
|
147
210
|
if (!html)
|
|
148
211
|
return "";
|
|
149
212
|
if (typeof DOMParser === "undefined" || typeof document === "undefined") {
|
|
150
|
-
return fallbackStrip(html)
|
|
213
|
+
return normalizeFallbackDiagramArrows(fallbackStrip(html)
|
|
151
214
|
.replace(/<\/?\s*(?:math|foreignObject|foreignobject)\b[^>]*>/gi, "")
|
|
152
|
-
.replace(/\s(?:@[\w:.-]+|x-on:[\w:.-]+|:on[\w:.-]+|x-bind:on[\w:.-]+|:style|x-bind:style)\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, "");
|
|
215
|
+
.replace(/\s(?:@[\w:.-]+|x-on:[\w:.-]+|:on[\w:.-]+|x-bind:on[\w:.-]+|:style|x-bind:style)\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, ""));
|
|
153
216
|
}
|
|
154
217
|
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
155
218
|
doc.querySelectorAll(DIAGRAM_BLOCKED_TAGS).forEach((el) => el.remove());
|
|
156
219
|
sanitizeElementAttributes(doc.body, { stripRuntimeDirectives: true });
|
|
220
|
+
normalizeDiagramArrows(doc.body);
|
|
157
221
|
return doc.body.innerHTML;
|
|
158
222
|
}
|
|
159
223
|
export function sanitizeWireframeCss(css) {
|
|
@@ -745,6 +745,18 @@ function elementStroke(node, fallback) {
|
|
|
745
745
|
if (explicit)
|
|
746
746
|
return explicit;
|
|
747
747
|
const cs = getComputedStyle(node);
|
|
748
|
+
if (node.classList.contains("diagram-arrow")) {
|
|
749
|
+
const color = cs.color;
|
|
750
|
+
const normalizedColor = color.replace(/\s+/g, "").toLowerCase();
|
|
751
|
+
const isTransparent = normalizedColor === "transparent" ||
|
|
752
|
+
normalizedColor.endsWith("/0)") ||
|
|
753
|
+
(normalizedColor.startsWith("rgb") &&
|
|
754
|
+
normalizedColor.split(",").length === 4 &&
|
|
755
|
+
normalizedColor.endsWith(",0)"));
|
|
756
|
+
if (color && !isTransparent) {
|
|
757
|
+
return color;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
748
760
|
for (const side of [
|
|
749
761
|
"borderTopColor",
|
|
750
762
|
"borderLeftColor",
|
|
@@ -831,6 +843,56 @@ function build(scope, opts) {
|
|
|
831
843
|
strokeWidth: sw,
|
|
832
844
|
preserveVertices: true,
|
|
833
845
|
});
|
|
846
|
+
const drawRoughArrow = (direction, x, y, w, h, stroke, sw, seedBase) => {
|
|
847
|
+
let lineIndex = 0;
|
|
848
|
+
const drawLine = (x1, y1, x2, y2) => {
|
|
849
|
+
push(gen.line(x1, y1, x2, y2, makeOpts(stroke, sw, seedFrom(seedBase, "line", lineIndex++))), stroke, sw);
|
|
850
|
+
};
|
|
851
|
+
const drawDirectional = (fromX, fromY, toX, toY) => {
|
|
852
|
+
const angle = Math.atan2(toY - fromY, toX - fromX);
|
|
853
|
+
const length = Math.hypot(toX - fromX, toY - fromY);
|
|
854
|
+
const head = Math.min(7, Math.max(4, length * 0.28));
|
|
855
|
+
const shaftEndX = toX - Math.cos(angle) * head;
|
|
856
|
+
const shaftEndY = toY - Math.sin(angle) * head;
|
|
857
|
+
drawLine(fromX, fromY, shaftEndX, shaftEndY);
|
|
858
|
+
const spread = Math.PI / 6;
|
|
859
|
+
drawLine(toX, toY, toX - Math.cos(angle - spread) * head, toY - Math.sin(angle - spread) * head);
|
|
860
|
+
drawLine(toX, toY, toX - Math.cos(angle + spread) * head, toY - Math.sin(angle + spread) * head);
|
|
861
|
+
};
|
|
862
|
+
const centerX = x + w / 2;
|
|
863
|
+
const centerY = y + h / 2;
|
|
864
|
+
const pad = Math.min(3, w / 5, h / 5);
|
|
865
|
+
const horizontalFrom = x + pad;
|
|
866
|
+
const horizontalTo = x + w - pad;
|
|
867
|
+
const verticalFrom = y + pad;
|
|
868
|
+
const verticalTo = y + h - pad;
|
|
869
|
+
if (direction === "refresh") {
|
|
870
|
+
const diameter = Math.max(8, Math.min(w, h) - pad * 2);
|
|
871
|
+
const start = -Math.PI * 0.8;
|
|
872
|
+
const stop = Math.PI * 1.15;
|
|
873
|
+
push(gen.arc(centerX, centerY, diameter, diameter, start, stop, false, makeOpts(stroke, sw, seedFrom(seedBase, "arc"))), stroke, sw);
|
|
874
|
+
drawDirectional(x + w - pad - 5, y + pad + 1, x + w - pad, y + pad + 1);
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
if (direction === "down") {
|
|
878
|
+
drawDirectional(centerX, verticalFrom, centerX, verticalTo);
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
if (direction === "up") {
|
|
882
|
+
drawDirectional(centerX, verticalTo, centerX, verticalFrom);
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
if (direction === "left") {
|
|
886
|
+
drawDirectional(horizontalTo, centerY, horizontalFrom, centerY);
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
if (direction === "both") {
|
|
890
|
+
drawDirectional(horizontalFrom, centerY, horizontalTo, centerY);
|
|
891
|
+
drawDirectional(horizontalTo, centerY, horizontalFrom, centerY);
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
drawDirectional(horizontalFrom, centerY, horizontalTo, centerY);
|
|
895
|
+
};
|
|
834
896
|
if (opts.drawFrame && hasDrawableRoughBounds(layoutW, layoutH, 2)) {
|
|
835
897
|
const sw = 2;
|
|
836
898
|
push(gen.path(roundedRectPath(2, 2, layoutW - 4, layoutH - 4, opts.frameRadius), {
|
|
@@ -858,6 +920,13 @@ function build(scope, opts) {
|
|
|
858
920
|
: rawStroke;
|
|
859
921
|
const sw = Number(readVar(node, "--rough-w")) || 1.4;
|
|
860
922
|
const seed = seedFrom(kind, Math.round(x), Math.round(y), Math.round(w), Math.round(h), index++);
|
|
923
|
+
const arrow = node.classList.contains("diagram-arrow")
|
|
924
|
+
? node.getAttribute("data-arrow")
|
|
925
|
+
: null;
|
|
926
|
+
if (arrow) {
|
|
927
|
+
drawRoughArrow(arrow, x, y, w, h, stroke, sw, seedFrom("arrow", seed));
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
861
930
|
const o = makeOpts(stroke, sw, seed);
|
|
862
931
|
let drawable;
|
|
863
932
|
if (kind === "ellipse") {
|
|
@@ -5,11 +5,11 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
5
5
|
// by AssistantChatInner.
|
|
6
6
|
import { IconLoader2, IconCheck, IconCopy, IconX, IconChevronDown, IconGitFork, IconGauge, IconSettings, IconArrowRight, IconAlertTriangle, IconPlayerPlay, IconRefresh, IconPlus, IconClipboardList, } from "@tabler/icons-react";
|
|
7
7
|
import { useState, useEffect, useCallback, useRef } from "react";
|
|
8
|
-
import { saveAgentEngineApiKey, } from "../agent-engine-key.js";
|
|
9
8
|
import { agentNativePath } from "../api-path.js";
|
|
10
9
|
import { writeClipboardText } from "../clipboard.js";
|
|
11
10
|
import { isProviderAuthenticationError } from "../error-format.js";
|
|
12
11
|
import { useT } from "../i18n.js";
|
|
12
|
+
import { AgentProviderSetupForm } from "../settings/ProviderSetupForm.js";
|
|
13
13
|
import { useBuilderConnectFlow } from "../settings/useBuilderStatus.js";
|
|
14
14
|
import { cn } from "../utils.js";
|
|
15
15
|
// ─── Metadata extractors ──────────────────────────────────────────────────────
|
|
@@ -132,65 +132,21 @@ export function BuilderConnectCta({ variant = "primary", onConnected, }) {
|
|
|
132
132
|
return (_jsxs("div", { className: containerClass, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "Connect Builder.io" }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5 max-w-[220px]", children: "Free credits for LLM, hosting, and more \u2014 no API key needed" }), error && _jsx("p", { className: "mt-1 text-[10px] text-destructive", children: error })] }), _jsx("button", { type: "button", onClick: () => start(), disabled: connecting, className: "ml-auto inline-flex items-center gap-1 shrink-0 rounded-md bg-foreground px-3 py-1.5 text-[11px] font-medium no-underline text-background hover:opacity-90 disabled:opacity-60 disabled:cursor-wait", "aria-busy": connecting, children: connecting ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { size: 10, className: "animate-spin" }), "Waiting\u2026"] })) : ("Connect") })] }));
|
|
133
133
|
}
|
|
134
134
|
// ─── ApiKeyConnect ────────────────────────────────────────────────────────────
|
|
135
|
-
const API_KEY_PROVIDERS = [
|
|
136
|
-
{ value: "anthropic", label: "Anthropic", placeholder: "sk-ant-…" },
|
|
137
|
-
{ value: "openai", label: "OpenAI", placeholder: "sk-…" },
|
|
138
|
-
];
|
|
139
135
|
export function ApiKeyConnect({ onConnected }) {
|
|
140
|
-
|
|
141
|
-
const [provider, setProvider] = useState("anthropic");
|
|
142
|
-
const [apiKey, setApiKey] = useState("");
|
|
143
|
-
const [saving, setSaving] = useState(false);
|
|
144
|
-
const [error, setError] = useState(null);
|
|
145
|
-
const active = API_KEY_PROVIDERS.find((p) => p.value === provider);
|
|
146
|
-
const handleSave = useCallback(async () => {
|
|
147
|
-
if (!apiKey.trim() || saving)
|
|
148
|
-
return;
|
|
149
|
-
setSaving(true);
|
|
150
|
-
setError(null);
|
|
151
|
-
try {
|
|
152
|
-
await saveAgentEngineApiKey({ provider, apiKey });
|
|
153
|
-
setApiKey("");
|
|
154
|
-
onConnected?.();
|
|
155
|
-
}
|
|
156
|
-
catch (err) {
|
|
157
|
-
setError(err instanceof Error ? err.message : "Could not save the key.");
|
|
158
|
-
}
|
|
159
|
-
finally {
|
|
160
|
-
setSaving(false);
|
|
161
|
-
}
|
|
162
|
-
}, [apiKey, onConnected, provider, saving]);
|
|
163
|
-
return (_jsxs("div", { className: "rounded-md border border-border bg-background/60 p-3", children: [_jsx("div", { className: "mb-2 text-[11px] font-medium text-foreground", children: t("agentPanel.addOwnKeys", { defaultValue: "Add your own keys" }) }), _jsx("p", { className: "mb-2.5 text-[11px] leading-relaxed text-muted-foreground", children: "Stored securely for this app only." }), _jsx("div", { role: "tablist", "aria-label": "API key provider", className: "mb-2 inline-flex rounded-md border border-border bg-muted/40 p-0.5", children: API_KEY_PROVIDERS.map((option) => {
|
|
164
|
-
const selected = option.value === provider;
|
|
165
|
-
return (_jsx("button", { type: "button", role: "tab", "aria-selected": selected, onClick: () => {
|
|
166
|
-
setProvider(option.value);
|
|
167
|
-
setError(null);
|
|
168
|
-
}, className: cn("rounded px-2.5 py-1 text-[11px] font-medium transition-colors", selected
|
|
169
|
-
? "bg-background text-foreground shadow-sm"
|
|
170
|
-
: "text-muted-foreground hover:text-foreground"), children: option.label }, option.value));
|
|
171
|
-
}) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { type: "password", value: apiKey, autoComplete: "off", spellCheck: false, placeholder: active.placeholder, onChange: (e) => {
|
|
172
|
-
setApiKey(e.target.value);
|
|
173
|
-
if (error)
|
|
174
|
-
setError(null);
|
|
175
|
-
}, onKeyDown: (e) => {
|
|
176
|
-
if (e.key === "Enter") {
|
|
177
|
-
e.preventDefault();
|
|
178
|
-
void handleSave();
|
|
179
|
-
}
|
|
180
|
-
}, className: "h-8 min-w-0 flex-1 rounded-md border border-input bg-background px-2.5 text-[12px] text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background" }), _jsx("button", { type: "button", onClick: handleSave, disabled: !apiKey.trim() || saving, className: "inline-flex h-8 shrink-0 items-center gap-1 rounded-md bg-foreground px-3 text-[11px] font-medium text-background hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-60", children: saving ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { size: 11, className: "animate-spin" }), "Saving\u2026"] })) : ("Save") })] }), error ? (_jsx("p", { className: "mt-2 text-[11px] text-destructive", children: error })) : null] }));
|
|
136
|
+
return (_jsx(AgentProviderSetupForm, { onConnected: () => onConnected?.(), layout: "compact", showTitle: false }));
|
|
181
137
|
}
|
|
182
138
|
export function BuilderSetupContent({ onConnected, layout = "default", }) {
|
|
183
139
|
const t = useT();
|
|
184
140
|
const [keyOpen, setKeyOpen] = useState(false);
|
|
185
141
|
const sidebarLayout = layout === "sidebar";
|
|
186
142
|
return (_jsxs("div", { className: cn("agent-builder-setup-content", sidebarLayout && "agent-builder-setup-card--sidebar"), children: [_jsxs("div", { className: cn("agent-builder-setup-card__content flex flex-col sm:flex-row sm:items-center sm:justify-between", sidebarLayout ? "gap-2" : "gap-3"), children: [_jsxs("div", { className: "agent-builder-setup-card__copy min-w-0", children: [_jsx("h3", { className: "text-[13px] font-medium text-foreground", children: t("agentPanel.connectAi", { defaultValue: "Connect AI" }) }), _jsx("p", { className: "mt-0.5 text-[11px] leading-relaxed text-muted-foreground", children: t("agentPanel.builderOrOwnKeys", {
|
|
187
|
-
defaultValue: "
|
|
143
|
+
defaultValue: "Choose Builder.io or custom keys.",
|
|
188
144
|
}) })] }), _jsxs("div", { className: cn("agent-builder-setup-card__actions flex shrink-0", sidebarLayout
|
|
189
145
|
? "flex-col items-start gap-1 sm:items-center"
|
|
190
146
|
: "flex-nowrap items-center gap-2"), children: [_jsx(BuilderConnectCta, { variant: "compact", onConnected: onConnected }), _jsx("button", { type: "button", onClick: () => setKeyOpen((open) => !open), className: cn("agent-builder-setup-card__key-button inline-flex shrink-0 items-center whitespace-nowrap rounded-md text-[11px] font-medium", sidebarLayout
|
|
191
147
|
? "h-7 border-0 bg-transparent px-0 text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
192
148
|
: "h-8 border border-border bg-background px-3 text-foreground hover:bg-accent"), "aria-expanded": keyOpen, children: t("agentPanel.addOwnKeys", {
|
|
193
|
-
defaultValue: "
|
|
149
|
+
defaultValue: "Custom keys",
|
|
194
150
|
}) })] })] }), keyOpen ? (_jsx("div", { className: "mt-3", children: _jsx(ApiKeyConnect, { onConnected: onConnected }) })) : null] }));
|
|
195
151
|
}
|
|
196
152
|
export function BuilderSetupCard({ onConnected, bouncePulse, fullWidth, layout = "default", }) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ChatFirstAppRailProps } from "./types.js";
|
|
2
|
-
export declare function ChatFirstAppsRail({ apps, activeAppId, loading, error, collapsed, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onCreateApp, createAppTrigger, renderIcon, copy, }: ChatFirstAppRailProps): import("react").JSX.Element;
|
|
2
|
+
export declare function ChatFirstAppsRail({ apps, activeAppId, loading, error, collapsed, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy, }: ChatFirstAppRailProps): import("react").JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger, Skeleton, Tooltip, TooltipContent, TooltipTrigger, } from "@agent-native/toolkit/ui";
|
|
3
|
-
import { IconChevronDown, IconChevronUp, IconPin, IconPlus, } from "@tabler/icons-react";
|
|
3
|
+
import { IconApps, IconChevronDown, IconChevronUp, IconPin, IconPlus, } from "@tabler/icons-react";
|
|
4
4
|
import { useMemo, useState } from "react";
|
|
5
5
|
import { orderChatFirstAppIds, readChatFirstAppLayout, writeChatFirstAppLayout, } from "../chat-first.js";
|
|
6
6
|
import { cn } from "../utils.js";
|
|
@@ -36,7 +36,7 @@ function AppRows({ apps, activeAppId, layout, onDragStart, onDrop, onDragEnd, on
|
|
|
36
36
|
}), "aria-pressed": pinned, title: pinned ? copy("removePinned") : copy("pinTop"), onClick: () => onTogglePinned(app.id), children: _jsx(IconPin, { size: 13, strokeWidth: pinned ? 2.2 : 1.6, "aria-hidden": "true" }) }), _jsx("span", { className: "sr-only", children: `${index + 1} of ${orderedApps.length}` })] }) }), _jsxs(ContextMenuContent, { children: [_jsxs(ContextMenuItem, { onSelect: () => onTogglePinned(app.id), children: [_jsx(IconPin, { size: 14, "aria-hidden": "true" }), pinned ? copy("removePinned") : copy("pinTop")] }), _jsx(ContextMenuSeparator, {}), _jsxs(ContextMenuItem, { disabled: index === 0, onSelect: () => onMove(app.id, -1), children: [_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" }), copy("moveUp")] }), _jsxs(ContextMenuItem, { disabled: index === orderedApps.length - 1, onSelect: () => onMove(app.id, 1), children: [_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" }), copy("moveDown")] })] })] }, app.id));
|
|
37
37
|
}) }));
|
|
38
38
|
}
|
|
39
|
-
export function ChatFirstAppsRail({ apps, activeAppId, loading = false, error, collapsed = false, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onCreateApp, createAppTrigger, renderIcon, copy = defaultChatFirstCopy, }) {
|
|
39
|
+
export function ChatFirstAppsRail({ apps, activeAppId, loading = false, error, collapsed = false, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy = defaultChatFirstCopy, }) {
|
|
40
40
|
const [localLayout, setLocalLayout] = useState(() => readChatFirstAppLayout());
|
|
41
41
|
const layout = controlledLayout ?? localLayout;
|
|
42
42
|
const [draggedAppId, setDraggedAppId] = useState(null);
|
|
@@ -97,7 +97,7 @@ export function ChatFirstAppsRail({ apps, activeAppId, loading = false, error, c
|
|
|
97
97
|
? [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "size-9 rounded-md" }, index)))
|
|
98
98
|
: visibleApps.map((app) => (_jsx("button", { type: "button", "data-chat-first-app": true, "data-app-id": app.id, className: cn("flex size-9 items-center justify-center rounded-md transition-colors", activeAppId === app.id
|
|
99
99
|
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
100
|
-
: "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), onClick: () => onOpenApp(app), "aria-label": copy("openApp", { name: app.name }), title: app.name, children: renderIcon(app) }, app.id))), error ? (_jsx("span", { className: "size-1.5 rounded-full bg-destructive", title: error, "aria-label": error })) : null] }));
|
|
100
|
+
: "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), onClick: () => onOpenApp(app), "aria-label": copy("openApp", { name: app.name }), title: app.name, children: renderIcon(app) }, app.id))), onOpenAllApps ? (_jsx("button", { type: "button", "data-chat-first-all-apps": true, className: "flex size-9 items-center justify-center rounded-md text-sidebar-foreground/70 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", onClick: onOpenAllApps, "aria-label": copy("allApps"), title: copy("allApps"), children: _jsx(IconApps, { size: 16, "aria-hidden": "true" }) })) : null, error ? (_jsx("span", { className: "size-1.5 rounded-full bg-destructive", title: error, "aria-label": error })) : null] }));
|
|
101
101
|
}
|
|
102
|
-
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "mt-3 px-2 pb-2 pt-2", "aria-label": copy("workspaceApps"), children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 px-1 text-[11px] font-medium text-sidebar-foreground/50", children: [_jsx("span", { children: copy("workspaceApps") }), _jsx("span", { className: "ml-auto", children: createTrigger })] }), loading && apps.length === 0 ? (_jsx("div", { className: "space-y-0.5 px-1", children: [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "h-7 w-full rounded-md" }, index))) })) : apps.length === 0 ? (_jsxs("div", { className: "px-1", children: [_jsx("p", { className: "text-xs text-sidebar-foreground/55", children: copy("noWorkspaceApps") }), createAppTrigger ? (createTrigger) : onCreateApp ? (_jsxs("button", { type: "button", className: "mt-1 inline-flex h-6 items-center gap-1.5 rounded-md border border-sidebar-border px-2 text-xs text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onCreateApp, children: [_jsx(IconPlus, { size: 13, "aria-hidden": "true" }), copy("createApp")] })) : (createTrigger)] })) : (_jsx(AppRows, { apps: visibleApps, activeAppId: activeAppId, layout: layout, onDragStart: setDraggedAppId, onDrop: reorderApps, onDragEnd: () => setDraggedAppId(null), onOpenApp: onOpenApp, onTogglePinned: togglePinned, onMove: moveApp, renderIcon: renderIcon, copy: copy })), hasMoreApps || showAllApps ? (_jsxs("button", { type: "button", className: "mt-0.5 flex h-6 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: () => setShowAllApps((value) => !value), children: [showAllApps ? (_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" })) : (_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" })), showAllApps ? copy("showLess") : copy("showMore")] })) : null, error ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "mt-1 flex items-center gap-1 px-1 text-[10px] text-destructive/80", onClick: onRetry, "aria-label": error, children: [_jsx("span", { className: "size-1.5 rounded-full bg-destructive" }), onRetry ? copy("retry") : copy("appsLoadError")] }) }), _jsx(TooltipContent, { side: "right", children: error })] })) : null] }));
|
|
102
|
+
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "mt-3 px-2 pb-2 pt-2", "aria-label": copy("workspaceApps"), children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 px-1 text-[11px] font-medium text-sidebar-foreground/50", children: [_jsx("span", { children: copy("workspaceApps") }), _jsx("span", { className: "ml-auto", children: createTrigger })] }), loading && apps.length === 0 ? (_jsx("div", { className: "space-y-0.5 px-1", children: [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "h-7 w-full rounded-md" }, index))) })) : apps.length === 0 ? (_jsxs("div", { className: "px-1", children: [_jsx("p", { className: "text-xs text-sidebar-foreground/55", children: copy("noWorkspaceApps") }), createAppTrigger ? (createTrigger) : onCreateApp ? (_jsxs("button", { type: "button", className: "mt-1 inline-flex h-6 items-center gap-1.5 rounded-md border border-sidebar-border px-2 text-xs text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onCreateApp, children: [_jsx(IconPlus, { size: 13, "aria-hidden": "true" }), copy("createApp")] })) : (createTrigger)] })) : (_jsx(AppRows, { apps: visibleApps, activeAppId: activeAppId, layout: layout, onDragStart: setDraggedAppId, onDrop: reorderApps, onDragEnd: () => setDraggedAppId(null), onOpenApp: onOpenApp, onTogglePinned: togglePinned, onMove: moveApp, renderIcon: renderIcon, copy: copy })), hasMoreApps || showAllApps ? (_jsxs("button", { type: "button", className: "mt-0.5 flex h-6 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: () => setShowAllApps((value) => !value), children: [showAllApps ? (_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" })) : (_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" })), showAllApps ? copy("showLess") : copy("showMore")] })) : null, onOpenAllApps ? (_jsx("div", { className: "mt-1 border-t border-sidebar-border/60 pt-1", children: _jsxs("button", { type: "button", "data-chat-first-all-apps": true, className: "flex h-7 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/55 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onOpenAllApps, children: [_jsx(IconApps, { size: 14, "aria-hidden": "true" }), _jsx("span", { children: copy("allApps") })] }) })) : null, error ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "mt-1 flex items-center gap-1 px-1 text-[10px] text-destructive/80", onClick: onRetry, "aria-label": error, children: [_jsx("span", { className: "size-1.5 rounded-full bg-destructive" }), onRetry ? copy("retry") : copy("appsLoadError")] }) }), _jsx(TooltipContent, { side: "right", children: error })] })) : null] }));
|
|
103
103
|
}
|
|
@@ -44,6 +44,7 @@ export interface ChatFirstAppRailProps {
|
|
|
44
44
|
onLayoutError?: (reason: "unavailable" | "write-failed") => void;
|
|
45
45
|
onRetry?: () => void;
|
|
46
46
|
onOpenApp: (app: ChatFirstAppItem) => void;
|
|
47
|
+
onOpenAllApps?: () => void;
|
|
47
48
|
onCreateApp?: () => void;
|
|
48
49
|
createAppTrigger?: ReactNode;
|
|
49
50
|
renderIcon: (app: ChatFirstAppItem) => ReactNode;
|
|
@@ -235,16 +235,17 @@ function browserStorage() {
|
|
|
235
235
|
}
|
|
236
236
|
export function readChatFirstModeState(storage = browserStorage()) {
|
|
237
237
|
if (!storage) {
|
|
238
|
-
return { enabled:
|
|
238
|
+
return { enabled: true, availability: "unavailable" };
|
|
239
239
|
}
|
|
240
240
|
try {
|
|
241
|
+
const stored = storage.getItem(CHAT_FIRST_MODE_STORAGE_KEY);
|
|
241
242
|
return {
|
|
242
|
-
enabled:
|
|
243
|
+
enabled: stored == null ? true : stored === "true",
|
|
243
244
|
availability: "available",
|
|
244
245
|
};
|
|
245
246
|
}
|
|
246
247
|
catch {
|
|
247
|
-
return { enabled:
|
|
248
|
+
return { enabled: true, availability: "unavailable" };
|
|
248
249
|
}
|
|
249
250
|
}
|
|
250
251
|
export function readChatFirstMode(storage = browserStorage()) {
|
package/dist/client/i18n.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import { type LocaleCode, type LocaleMetadata, type LocalePreference, type Local
|
|
|
3
3
|
export { DEFAULT_LOCALE, LOCALE_HYDRATION_GLOBAL, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, localeDirection, normalizeLocaleCode, normalizeLocalePreference, normalizeLocalizationPreference, resolveLocaleFromCandidates, resolveLocaleFromPreference, type LocaleCode, type LocaleMetadata, type LocalePreference, type LocalizationPreference, } from "../localization/shared.js";
|
|
4
4
|
export { getLocaleInitScript } from "../localization/server.js";
|
|
5
5
|
export type LocaleMessages = Record<string, unknown>;
|
|
6
|
+
export type AgentNativeI18nLocaleLoader = () => Promise<LocaleMessages | {
|
|
7
|
+
default: LocaleMessages;
|
|
8
|
+
}>;
|
|
6
9
|
export interface LocaleHydrationPayload {
|
|
7
10
|
locale?: LocaleCode;
|
|
8
11
|
preference?: LocalizationPreference;
|
|
@@ -21,6 +24,17 @@ export interface AgentNativeI18nCatalog {
|
|
|
21
24
|
*/
|
|
22
25
|
supportedLocales?: readonly LocaleCode[];
|
|
23
26
|
}
|
|
27
|
+
export declare function createAgentNativeI18nCatalog(args: {
|
|
28
|
+
messages: LocaleMessages;
|
|
29
|
+
localeLoaders: Partial<Record<LocaleCode, AgentNativeI18nLocaleLoader>>;
|
|
30
|
+
namespace?: string;
|
|
31
|
+
sourceLocale?: LocaleCode;
|
|
32
|
+
supportedLocales?: readonly LocaleCode[];
|
|
33
|
+
}): AgentNativeI18nCatalog & {
|
|
34
|
+
messages: LocaleMessages;
|
|
35
|
+
sourceLocale: LocaleCode;
|
|
36
|
+
loadMessages: (locale: LocaleCode) => Promise<LocaleMessages | null>;
|
|
37
|
+
};
|
|
24
38
|
export interface AgentNativeI18nProviderProps {
|
|
25
39
|
children: React.ReactNode;
|
|
26
40
|
catalog?: AgentNativeI18nCatalog;
|
package/dist/client/i18n.js
CHANGED
|
@@ -12,6 +12,24 @@ import { callAction } from "./use-action.js";
|
|
|
12
12
|
import { cn } from "./utils.js";
|
|
13
13
|
export { DEFAULT_LOCALE, LOCALE_HYDRATION_GLOBAL, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, localeDirection, normalizeLocaleCode, normalizeLocalePreference, normalizeLocalizationPreference, resolveLocaleFromCandidates, resolveLocaleFromPreference, } from "../localization/shared.js";
|
|
14
14
|
export { getLocaleInitScript } from "../localization/server.js";
|
|
15
|
+
function isAgentNativeI18nModuleNamespace(value) {
|
|
16
|
+
return Object.prototype.toString.call(value) === "[object Module]";
|
|
17
|
+
}
|
|
18
|
+
export function createAgentNativeI18nCatalog(args) {
|
|
19
|
+
return {
|
|
20
|
+
namespace: args.namespace,
|
|
21
|
+
sourceLocale: args.sourceLocale ?? DEFAULT_LOCALE,
|
|
22
|
+
messages: args.messages,
|
|
23
|
+
supportedLocales: args.supportedLocales,
|
|
24
|
+
loadMessages: async (locale) => {
|
|
25
|
+
const loader = args.localeLoaders[locale];
|
|
26
|
+
if (!loader)
|
|
27
|
+
return null;
|
|
28
|
+
const loaded = await loader();
|
|
29
|
+
return isAgentNativeI18nModuleNamespace(loaded) ? loaded.default : loaded;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
15
33
|
const LocaleContext = globalThis.__AGENT_NATIVE_LOCALE_CONTEXT__ ??
|
|
16
34
|
(globalThis.__AGENT_NATIVE_LOCALE_CONTEXT__ =
|
|
17
35
|
createContext(null));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type AgentProviderId, type AgentProviderOption } from "../agent-provider-catalog.js";
|
|
2
|
+
export interface AgentProviderPickerProps {
|
|
3
|
+
value: AgentProviderId;
|
|
4
|
+
onChange: (provider: AgentProviderId) => void;
|
|
5
|
+
options?: readonly AgentProviderOption[];
|
|
6
|
+
configuredProviders?: ReadonlySet<AgentProviderId>;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
className?: string;
|
|
9
|
+
layout?: "compact" | "page";
|
|
10
|
+
}
|
|
11
|
+
export declare function AgentProviderPicker({ value, onChange, options, configuredProviders, disabled, className, layout, }: AgentProviderPickerProps): import("react").JSX.Element;
|
|
12
|
+
export interface AgentProviderSetupFormProps {
|
|
13
|
+
initialProvider?: AgentProviderId;
|
|
14
|
+
configuredProviders?: ReadonlySet<AgentProviderId>;
|
|
15
|
+
onConnected?: (provider: AgentProviderId) => void;
|
|
16
|
+
scope?: "user" | "org";
|
|
17
|
+
layout?: "compact" | "page";
|
|
18
|
+
showTitle?: boolean;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function AgentProviderSetupForm({ initialProvider, configuredProviders, onConnected, scope, layout, showTitle, className, }: AgentProviderSetupFormProps): import("react").JSX.Element;
|