@agent-native/core 0.7.4 → 0.7.7
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/README.md +6 -5
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +8 -4
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/types.d.ts +1 -1
- package/dist/agent/engine/types.d.ts.map +1 -1
- package/dist/agent/production-agent.d.ts +7 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +153 -118
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +4 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +46 -25
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +12 -3
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +25 -4
- package/dist/agent/run-store.js.map +1 -1
- package/dist/chat-threads/store.d.ts +13 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +66 -10
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +8 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/info.d.ts +2 -0
- package/dist/cli/info.d.ts.map +1 -0
- package/dist/cli/info.js +103 -0
- package/dist/cli/info.js.map +1 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +249 -85
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +12 -1
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +3 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +46 -2
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/VoiceButton.d.ts +21 -0
- package/dist/client/composer/VoiceButton.d.ts.map +1 -0
- package/dist/client/composer/VoiceButton.js +51 -0
- package/dist/client/composer/VoiceButton.js.map +1 -0
- package/dist/client/composer/useVoiceDictation.d.ts +38 -0
- package/dist/client/composer/useVoiceDictation.d.ts.map +1 -0
- package/dist/client/composer/useVoiceDictation.js +398 -0
- package/dist/client/composer/useVoiceDictation.js.map +1 -0
- package/dist/client/onboarding/OnboardingPanel.js +2 -2
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +5 -4
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +90 -24
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/resources/McpServerDetail.d.ts +15 -0
- package/dist/client/resources/McpServerDetail.d.ts.map +1 -0
- package/dist/client/resources/McpServerDetail.js +65 -0
- package/dist/client/resources/McpServerDetail.js.map +1 -0
- package/dist/client/resources/ResourceEditor.js +1 -1
- package/dist/client/resources/ResourceEditor.js.map +1 -1
- package/dist/client/resources/ResourceTree.d.ts +6 -1
- package/dist/client/resources/ResourceTree.d.ts.map +1 -1
- package/dist/client/resources/ResourceTree.js +18 -7
- package/dist/client/resources/ResourceTree.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +191 -20
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/use-mcp-servers.d.ts +68 -0
- package/dist/client/resources/use-mcp-servers.d.ts.map +1 -0
- package/dist/client/resources/use-mcp-servers.js +83 -0
- package/dist/client/resources/use-mcp-servers.js.map +1 -0
- package/dist/client/resources/use-resources.d.ts +39 -1
- package/dist/client/resources/use-resources.d.ts.map +1 -1
- package/dist/client/resources/use-resources.js +102 -0
- package/dist/client/resources/use-resources.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +3 -2
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.d.ts +14 -0
- package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -0
- package/dist/client/settings/VoiceTranscriptionSection.js +111 -0
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -0
- package/dist/client/sharing/ShareButton.d.ts +6 -4
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +299 -34
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareDialog.d.ts +22 -4
- package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/client/sharing/ShareDialog.js +170 -148
- package/dist/client/sharing/ShareDialog.js.map +1 -1
- package/dist/client/sharing/VisibilityBadge.d.ts.map +1 -1
- package/dist/client/sharing/VisibilityBadge.js +1 -2
- package/dist/client/sharing/VisibilityBadge.js.map +1 -1
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +20 -1
- package/dist/client/use-action.js.map +1 -1
- package/dist/db/migrations.d.ts +18 -3
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +25 -3
- package/dist/db/migrations.js.map +1 -1
- package/dist/deploy/workspace-core.js +2 -2
- package/dist/mcp-client/config.d.ts +20 -1
- package/dist/mcp-client/config.d.ts.map +1 -1
- package/dist/mcp-client/config.js +28 -11
- package/dist/mcp-client/config.js.map +1 -1
- package/dist/mcp-client/hub-client.d.ts +38 -0
- package/dist/mcp-client/hub-client.d.ts.map +1 -0
- package/dist/mcp-client/hub-client.js +147 -0
- package/dist/mcp-client/hub-client.js.map +1 -0
- package/dist/mcp-client/hub-routes.d.ts +42 -0
- package/dist/mcp-client/hub-routes.d.ts.map +1 -0
- package/dist/mcp-client/hub-routes.js +114 -0
- package/dist/mcp-client/hub-routes.js.map +1 -0
- package/dist/mcp-client/index.d.ts +15 -0
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +35 -0
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/mcp-client/manager.d.ts +54 -8
- package/dist/mcp-client/manager.d.ts.map +1 -1
- package/dist/mcp-client/manager.js +276 -59
- package/dist/mcp-client/manager.js.map +1 -1
- package/dist/mcp-client/remote-store.d.ts +102 -0
- package/dist/mcp-client/remote-store.d.ts.map +1 -0
- package/dist/mcp-client/remote-store.js +200 -0
- package/dist/mcp-client/remote-store.js.map +1 -0
- package/dist/mcp-client/routes.d.ts +55 -0
- package/dist/mcp-client/routes.d.ts.map +1 -0
- package/dist/mcp-client/routes.js +384 -0
- package/dist/mcp-client/routes.js.map +1 -0
- package/dist/mcp-client/visibility.d.ts +16 -0
- package/dist/mcp-client/visibility.d.ts.map +1 -0
- package/dist/mcp-client/visibility.js +45 -0
- package/dist/mcp-client/visibility.js.map +1 -0
- package/dist/org/context.js +2 -2
- package/dist/org/context.js.map +1 -1
- package/dist/org/handlers.js +2 -2
- package/dist/org/handlers.js.map +1 -1
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +30 -0
- package/dist/resources/handlers.js.map +1 -1
- package/dist/secrets/register-framework-secrets.d.ts +13 -0
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -0
- package/dist/secrets/register-framework-secrets.js +59 -0
- package/dist/secrets/register-framework-secrets.js.map +1 -0
- package/dist/secrets/register.d.ts.map +1 -1
- package/dist/secrets/register.js +8 -1
- package/dist/secrets/register.js.map +1 -1
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +22 -2
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +16 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +237 -70
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/app-url.d.ts.map +1 -1
- package/dist/server/app-url.js +11 -3
- package/dist/server/app-url.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +50 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +99 -4
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +44 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +6 -0
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/date-utils.d.ts +15 -0
- package/dist/server/date-utils.d.ts.map +1 -0
- package/dist/server/date-utils.js +41 -0
- package/dist/server/date-utils.js.map +1 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts +3 -0
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +13 -3
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/request-context.d.ts +9 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +10 -0
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +26 -0
- package/dist/server/transcribe-voice.d.ts.map +1 -0
- package/dist/server/transcribe-voice.js +143 -0
- package/dist/server/transcribe-voice.js.map +1 -0
- package/dist/styles/agent-native.css +111 -0
- package/dist/tailwind.preset.d.ts +2 -2
- package/dist/tailwind.preset.d.ts.map +1 -1
- package/dist/tailwind.preset.js +27 -7
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/templates/default/app/global.css +65 -68
- package/dist/templates/default/components.json +1 -1
- package/dist/templates/default/package.json +2 -4
- package/dist/templates/default/vite.config.ts +3 -0
- package/dist/templates/workspace-core/package.json +1 -4
- package/dist/templates/workspace-core/src/index.ts +1 -1
- package/dist/templates/workspace-core/styles/tokens.css +22 -0
- package/dist/templates/workspace-core/tsconfig.json +1 -1
- package/dist/vite/client.d.ts +6 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +18 -1
- package/dist/vite/client.js.map +1 -1
- package/docs/content/actions.md +169 -74
- package/docs/content/agent-teams.md +139 -0
- package/docs/content/cloneable-saas.md +98 -0
- package/docs/content/creating-templates.md +9 -11
- package/docs/content/deployment.md +2 -9
- package/docs/content/drop-in-agent.md +200 -0
- package/docs/content/enterprise-workspace.md +22 -10
- package/docs/content/getting-started.md +34 -19
- package/docs/content/integrations.md +3 -3
- package/docs/content/key-concepts.md +50 -23
- package/docs/content/mcp-clients.md +71 -0
- package/docs/content/pure-agent-apps.md +69 -0
- package/docs/content/recurring-jobs.md +123 -0
- package/docs/content/skills-guide.md +8 -0
- package/docs/content/template-analytics.md +190 -0
- package/docs/content/template-calendar.md +151 -0
- package/docs/content/template-clips.md +55 -0
- package/docs/content/template-content.md +141 -0
- package/docs/content/template-dispatch.md +58 -0
- package/docs/content/template-forms.md +51 -0
- package/docs/content/template-mail.md +169 -0
- package/docs/content/template-slides.md +218 -0
- package/docs/content/template-starter.md +68 -0
- package/docs/content/template-video.md +162 -0
- package/docs/content/voice-input.md +59 -0
- package/docs/content/what-is-agent-native.md +142 -45
- package/docs/content/workspace-management.md +1 -0
- package/docs/content/{resources.md → workspace.md} +94 -42
- package/package.json +9 -16
- package/src/templates/default/app/global.css +65 -68
- package/src/templates/default/components.json +1 -1
- package/src/templates/default/package.json +2 -4
- package/src/templates/default/vite.config.ts +3 -0
- package/src/templates/workspace-core/package.json +1 -4
- package/src/templates/workspace-core/src/index.ts +1 -1
- package/src/templates/workspace-core/styles/tokens.css +22 -0
- package/src/templates/workspace-core/tsconfig.json +1 -1
- package/dist/templates/default/postcss.config.js +0 -6
- package/dist/templates/default/tailwind.config.ts +0 -7
- package/dist/templates/workspace-core/tailwind.preset.ts +0 -34
- package/src/templates/default/postcss.config.js +0 -6
- package/src/templates/default/tailwind.config.ts +0 -7
- package/src/templates/workspace-core/tailwind.preset.ts +0 -34
|
@@ -26,15 +26,22 @@ const markdownStyles = `
|
|
|
26
26
|
.agent-markdown h3 { font-size: 1em; font-weight: 600; margin: 0.75em 0 0.25em; }
|
|
27
27
|
.agent-markdown strong { font-weight: 600; }
|
|
28
28
|
.agent-markdown em { font-style: italic; }
|
|
29
|
-
.agent-markdown code { font-size: 0.875em; padding: 0.15em 0.35em; border-radius: 0.25em; background: var(--
|
|
30
|
-
.agent-markdown pre { margin: 0.5em 0; padding: 0.75em 1em; border-radius: 0.375em; background: var(--
|
|
31
|
-
.agent-markdown pre code { padding: 0; background: transparent; font-size: 0.8125em; }
|
|
32
|
-
.agent-markdown
|
|
29
|
+
.agent-markdown code { font-size: 0.875em; padding: 0.15em 0.35em; border-radius: 0.25em; background: hsl(var(--muted, 0 0% 15%)); color: hsl(var(--foreground, 0 0% 90%)); }
|
|
30
|
+
.agent-markdown pre { margin: 0.5em 0; padding: 0.75em 1em; border-radius: 0.375em; background: hsl(var(--muted, 0 0% 15%)); color: hsl(var(--foreground, 0 0% 90%)); overflow-x: auto; }
|
|
31
|
+
.agent-markdown pre code { padding: 0; background: transparent; font-size: 0.8125em; color: inherit; }
|
|
32
|
+
.agent-markdown-shiki { margin: 0.5em 0; border-radius: 0.375em; overflow: hidden; font-size: 0.8125em; }
|
|
33
|
+
.agent-markdown-shiki pre { margin: 0; padding: 0.75em 1em; overflow-x: auto; background: var(--shiki-light-bg); color: var(--shiki-light); }
|
|
34
|
+
.agent-markdown-shiki pre code { background: transparent; padding: 0; font-size: inherit; color: inherit; }
|
|
35
|
+
.agent-markdown-shiki pre span { color: var(--shiki-light); background: var(--shiki-light-bg); }
|
|
36
|
+
.dark .agent-markdown-shiki pre { background: var(--shiki-dark-bg); color: var(--shiki-dark); }
|
|
37
|
+
.dark .agent-markdown-shiki pre span { color: var(--shiki-dark); background: var(--shiki-dark-bg); }
|
|
38
|
+
@media (prefers-color-scheme: dark) { :root:not(.light) .agent-markdown-shiki pre { background: var(--shiki-dark-bg); color: var(--shiki-dark); } :root:not(.light) .agent-markdown-shiki pre span { color: var(--shiki-dark); background: var(--shiki-dark-bg); } }
|
|
39
|
+
.agent-markdown hr { border: none; border-top: 1px solid hsl(var(--border, 0 0% 20%)); margin: 0.75em 0; }
|
|
33
40
|
.agent-markdown a { text-decoration: underline; text-underline-offset: 2px; }
|
|
34
|
-
.agent-markdown blockquote { border-left: 2px solid var(--
|
|
41
|
+
.agent-markdown blockquote { border-left: 2px solid hsl(var(--border, 0 0% 20%)); padding-left: 0.75em; margin: 0.5em 0; opacity: 0.8; }
|
|
35
42
|
.agent-markdown table { border-collapse: collapse; margin: 0.5em 0; font-size: 0.875em; }
|
|
36
|
-
.agent-markdown th, .agent-markdown td { border: 1px solid var(--
|
|
37
|
-
.agent-markdown th { font-weight: 600; background: var(--
|
|
43
|
+
.agent-markdown th, .agent-markdown td { border: 1px solid hsl(var(--border, 0 0% 20%)); padding: 0.35em 0.65em; text-align: left; }
|
|
44
|
+
.agent-markdown th { font-weight: 600; background: hsl(var(--muted, 0 0% 15%)); color: hsl(var(--foreground, 0 0% 90%)); }
|
|
38
45
|
`;
|
|
39
46
|
let stylesInjected = false;
|
|
40
47
|
function injectMarkdownStyles() {
|
|
@@ -56,6 +63,92 @@ function extractCodeText(child) {
|
|
|
56
63
|
}
|
|
57
64
|
return "";
|
|
58
65
|
}
|
|
66
|
+
let highlighterLoader = null;
|
|
67
|
+
function loadHighlighter() {
|
|
68
|
+
if (!highlighterLoader) {
|
|
69
|
+
highlighterLoader = (async () => {
|
|
70
|
+
const [{ createHighlighterCore }, { createOnigurumaEngine }] = await Promise.all([
|
|
71
|
+
import("shiki/core"),
|
|
72
|
+
import("shiki/engine/oniguruma"),
|
|
73
|
+
]);
|
|
74
|
+
return createHighlighterCore({
|
|
75
|
+
themes: [
|
|
76
|
+
import("shiki/themes/github-light-default.mjs"),
|
|
77
|
+
import("shiki/themes/github-dark-default.mjs"),
|
|
78
|
+
],
|
|
79
|
+
langs: [
|
|
80
|
+
import("shiki/langs/javascript.mjs"),
|
|
81
|
+
import("shiki/langs/typescript.mjs"),
|
|
82
|
+
import("shiki/langs/jsx.mjs"),
|
|
83
|
+
import("shiki/langs/tsx.mjs"),
|
|
84
|
+
import("shiki/langs/json.mjs"),
|
|
85
|
+
import("shiki/langs/css.mjs"),
|
|
86
|
+
import("shiki/langs/html.mjs"),
|
|
87
|
+
import("shiki/langs/markdown.mjs"),
|
|
88
|
+
import("shiki/langs/bash.mjs"),
|
|
89
|
+
import("shiki/langs/shellscript.mjs"),
|
|
90
|
+
import("shiki/langs/python.mjs"),
|
|
91
|
+
import("shiki/langs/yaml.mjs"),
|
|
92
|
+
],
|
|
93
|
+
engine: createOnigurumaEngine(import("shiki/wasm")),
|
|
94
|
+
});
|
|
95
|
+
})().catch((error) => {
|
|
96
|
+
// Reset on failure so a future code block can retry instead of
|
|
97
|
+
// silently failing forever on a stale chunk / network blip.
|
|
98
|
+
highlighterLoader = null;
|
|
99
|
+
throw error;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return highlighterLoader;
|
|
103
|
+
}
|
|
104
|
+
// Map a few common aliases to languages we bundled above.
|
|
105
|
+
const LANG_ALIASES = {
|
|
106
|
+
js: "javascript",
|
|
107
|
+
ts: "typescript",
|
|
108
|
+
sh: "bash",
|
|
109
|
+
shell: "bash",
|
|
110
|
+
zsh: "bash",
|
|
111
|
+
py: "python",
|
|
112
|
+
yml: "yaml",
|
|
113
|
+
md: "markdown",
|
|
114
|
+
};
|
|
115
|
+
function HighlightedCodeBlock({ code, lang }) {
|
|
116
|
+
const [html, setHtml] = useState(null);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
let cancelled = false;
|
|
119
|
+
loadHighlighter()
|
|
120
|
+
.then((highlighter) => {
|
|
121
|
+
const requested = (lang || "text").toLowerCase();
|
|
122
|
+
const resolved = LANG_ALIASES[requested] ?? requested;
|
|
123
|
+
const loaded = highlighter.getLoadedLanguages();
|
|
124
|
+
const finalLang = loaded.includes(resolved) ? resolved : "text";
|
|
125
|
+
return highlighter.codeToHtml(code, {
|
|
126
|
+
lang: finalLang,
|
|
127
|
+
themes: {
|
|
128
|
+
light: "github-light-default",
|
|
129
|
+
dark: "github-dark-default",
|
|
130
|
+
},
|
|
131
|
+
defaultColor: false,
|
|
132
|
+
});
|
|
133
|
+
})
|
|
134
|
+
.then((out) => {
|
|
135
|
+
if (!cancelled)
|
|
136
|
+
setHtml(out);
|
|
137
|
+
})
|
|
138
|
+
.catch(() => {
|
|
139
|
+
// Unknown language or other shiki failure — fall back to plain pre.
|
|
140
|
+
if (!cancelled)
|
|
141
|
+
setHtml(null);
|
|
142
|
+
});
|
|
143
|
+
return () => {
|
|
144
|
+
cancelled = true;
|
|
145
|
+
};
|
|
146
|
+
}, [code, lang]);
|
|
147
|
+
if (html) {
|
|
148
|
+
return (_jsx("div", { className: "agent-markdown-shiki", dangerouslySetInnerHTML: { __html: html } }));
|
|
149
|
+
}
|
|
150
|
+
return (_jsx("pre", { children: _jsx("code", { className: lang ? `language-${lang}` : undefined, children: code }) }));
|
|
151
|
+
}
|
|
59
152
|
const markdownComponents = {
|
|
60
153
|
pre(props) {
|
|
61
154
|
const { children, ...rest } = props;
|
|
@@ -67,6 +160,11 @@ const markdownComponents = {
|
|
|
67
160
|
const parsed = parseEmbedBody(body);
|
|
68
161
|
return (_jsx(IframeEmbed, { ...parsed }));
|
|
69
162
|
}
|
|
163
|
+
const langMatch = className.match(/\blanguage-([\w+-]+)\b/);
|
|
164
|
+
if (langMatch) {
|
|
165
|
+
const code = extractCodeText(childProps.children).replace(/\n$/, "");
|
|
166
|
+
return _jsx(HighlightedCodeBlock, { code: code, lang: langMatch[1] });
|
|
167
|
+
}
|
|
70
168
|
}
|
|
71
169
|
return _jsx("pre", { ...rest, children: children });
|
|
72
170
|
},
|
|
@@ -115,6 +213,10 @@ function ComposerAttachmentPreviewStrip() {
|
|
|
115
213
|
return null;
|
|
116
214
|
return (_jsx("div", { className: "flex flex-wrap gap-2 px-2 pt-2", children: attachments.map((attachment) => (_jsx(ComposerAttachmentPreviewCard, { attachment: attachment, onRemove: handleRemove }, attachment.id))) }));
|
|
117
215
|
}
|
|
216
|
+
// Provides the parent's combined running state to tool-call renderers so they
|
|
217
|
+
// can stop spinning when the user clicks stop. `thread.isRunning` alone misses
|
|
218
|
+
// the force-stopped case; `part.result === undefined` alone ignores stop.
|
|
219
|
+
const ChatRunningContext = React.createContext(false);
|
|
118
220
|
// ─── Tool Call Display ──────────────────────────────────────────────────────
|
|
119
221
|
// Shared presentational component for rendering a tool call pill + result.
|
|
120
222
|
// Used by both the normal message path (ToolCallFallback) and the reconnect
|
|
@@ -191,8 +293,8 @@ function ToolCallDisplay({ toolName, argsText, args, result, isRunning, }) {
|
|
|
191
293
|
: JSON.stringify(result, null, 2) }))] }));
|
|
192
294
|
}
|
|
193
295
|
function ToolCallFallback({ toolName, args, argsText, result, }) {
|
|
194
|
-
const
|
|
195
|
-
const isRunning = result === undefined &&
|
|
296
|
+
const chatRunning = React.useContext(ChatRunningContext);
|
|
297
|
+
const isRunning = result === undefined && chatRunning;
|
|
196
298
|
return (_jsx(ToolCallDisplay, { toolName: toolName, args: args, argsText: argsText, result: typeof result === "string"
|
|
197
299
|
? result
|
|
198
300
|
: result !== undefined
|
|
@@ -204,6 +306,7 @@ function ToolCallFallback({ toolName, args, argsText, result, }) {
|
|
|
204
306
|
// assistant-ui's runtime). Uses the same visual styling as normal messages.
|
|
205
307
|
function ReconnectStreamMessage({ content }) {
|
|
206
308
|
const endRef = useRef(null);
|
|
309
|
+
const chatRunning = React.useContext(ChatRunningContext);
|
|
207
310
|
useEffect(() => {
|
|
208
311
|
endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
|
|
209
312
|
}, [content]);
|
|
@@ -212,7 +315,7 @@ function ReconnectStreamMessage({ content }) {
|
|
|
212
315
|
return (_jsx("div", { className: "agent-markdown break-words", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: markdownComponents, children: part.text }) }, `reconnect-text-${i}`));
|
|
213
316
|
}
|
|
214
317
|
if (part.type === "tool-call") {
|
|
215
|
-
return (_jsx(ToolCallDisplay, { toolName: part.toolName, argsText: part.argsText, args: part.args, result: part.result, isRunning: part.result === undefined }, `reconnect-tool-${i}`));
|
|
318
|
+
return (_jsx(ToolCallDisplay, { toolName: part.toolName, argsText: part.argsText, args: part.args, result: part.result, isRunning: part.result === undefined && chatRunning }, `reconnect-tool-${i}`));
|
|
216
319
|
}
|
|
217
320
|
return null;
|
|
218
321
|
}), _jsx("div", { ref: endRef })] }) }));
|
|
@@ -372,7 +475,7 @@ function AssistantMessage() {
|
|
|
372
475
|
} }) }), isComplete && (_jsx("div", { className: "mt-1 flex items-center gap-0.5 opacity-0 group-hover:opacity-100", children: _jsx("button", { onClick: handleCopy, className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: copied ? (_jsx(IconCheck, { className: "h-3 w-3" })) : (_jsx(IconCopy, { className: "h-3 w-3" })) }) }))] }));
|
|
373
476
|
}
|
|
374
477
|
// ─── Thinking Indicator ─────────────────────────────────────────────────────
|
|
375
|
-
function ThinkingIndicator() {
|
|
478
|
+
function ThinkingIndicator({ label = "Thinking" } = {}) {
|
|
376
479
|
const [dots, setDots] = useState(0);
|
|
377
480
|
useEffect(() => {
|
|
378
481
|
const interval = setInterval(() => {
|
|
@@ -380,7 +483,7 @@ function ThinkingIndicator() {
|
|
|
380
483
|
}, 400);
|
|
381
484
|
return () => clearInterval(interval);
|
|
382
485
|
}, []);
|
|
383
|
-
return (_jsx("div", { className: "flex items-center text-muted-foreground", children: _jsxs("span", { className: "text-xs", children: [
|
|
486
|
+
return (_jsx("div", { className: "flex items-center text-muted-foreground", children: _jsxs("span", { className: "text-xs", children: [label, ".".repeat(dots)] }) }));
|
|
384
487
|
}
|
|
385
488
|
// ─── API Key Setup Card ─────────────────────────────────────────────────────
|
|
386
489
|
function ApiKeySetupCard({ apiUrl }) {
|
|
@@ -518,6 +621,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
518
621
|
const [authError, setAuthError] = useState(null);
|
|
519
622
|
const [usageLimitReached, setUsageLimitReached] = useState(null);
|
|
520
623
|
const [queuedMessages, setQueuedMessages] = useState([]);
|
|
624
|
+
// Tracks the JSON of the last queue we successfully persisted so the
|
|
625
|
+
// debounced save effect can skip no-op writes (e.g. restore-from-server
|
|
626
|
+
// on mount, or queue state that hasn't actually changed).
|
|
627
|
+
const lastPersistedQueueRef = useRef("[]");
|
|
521
628
|
const [showContinue, setShowContinue] = useState(false);
|
|
522
629
|
const [isReconnecting, setIsReconnecting] = useState(false);
|
|
523
630
|
const [reconnectContent, setReconnectContent] = useState([]);
|
|
@@ -567,6 +674,13 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
567
674
|
titleGeneratedRef.current = true; // Don't re-generate for restored threads
|
|
568
675
|
threadRuntime.import(ensureMessageMetadata(repo));
|
|
569
676
|
}
|
|
677
|
+
// Restore user-queued messages that were persisted before reload.
|
|
678
|
+
if (Array.isArray(repo?.queuedMessages)) {
|
|
679
|
+
setQueuedMessages(repo.queuedMessages);
|
|
680
|
+
// Mark as restored so the debounced save effect doesn't write
|
|
681
|
+
// the same data back to the server on mount.
|
|
682
|
+
lastPersistedQueueRef.current = JSON.stringify(repo.queuedMessages);
|
|
683
|
+
}
|
|
570
684
|
}
|
|
571
685
|
// Also skip title generation if thread already has a title
|
|
572
686
|
if (data.title) {
|
|
@@ -577,9 +691,19 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
577
691
|
const runRes = await fetch(`${apiUrl}/runs/active?threadId=${encodeURIComponent(threadId)}`);
|
|
578
692
|
if (runRes.ok) {
|
|
579
693
|
const runInfo = await runRes.json();
|
|
580
|
-
//
|
|
581
|
-
// (
|
|
582
|
-
|
|
694
|
+
// Defense in depth: if the server says status="running" but the
|
|
695
|
+
// heartbeat is stale (producer died before the server-side reap
|
|
696
|
+
// sweep noticed), treat it as dead. 5s tolerates normal jitter
|
|
697
|
+
// around the 1.5s heartbeat without false positives.
|
|
698
|
+
const heartbeatAt = typeof runInfo.heartbeatAt === "number"
|
|
699
|
+
? runInfo.heartbeatAt
|
|
700
|
+
: null;
|
|
701
|
+
const looksStale = runInfo.status === "running" &&
|
|
702
|
+
heartbeatAt != null &&
|
|
703
|
+
Date.now() - heartbeatAt > 5000;
|
|
704
|
+
// If the run already completed or looks stale, just re-fetch
|
|
705
|
+
// thread data (don't enter "Thinking." reconnection mode).
|
|
706
|
+
if (runInfo.status !== "running" || looksStale) {
|
|
583
707
|
try {
|
|
584
708
|
const refreshRes = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}`);
|
|
585
709
|
if (refreshRes.ok) {
|
|
@@ -591,6 +715,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
591
715
|
if (repo?.messages?.length > 0) {
|
|
592
716
|
threadRuntime.import(ensureMessageMetadata(repo));
|
|
593
717
|
}
|
|
718
|
+
if (Array.isArray(repo?.queuedMessages)) {
|
|
719
|
+
setQueuedMessages(repo.queuedMessages);
|
|
720
|
+
lastPersistedQueueRef.current = JSON.stringify(repo.queuedMessages);
|
|
721
|
+
}
|
|
594
722
|
}
|
|
595
723
|
}
|
|
596
724
|
}
|
|
@@ -610,12 +738,11 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
610
738
|
// can abort it even if clicked before the function body runs.
|
|
611
739
|
const abortCtrl = new AbortController();
|
|
612
740
|
reconnectAbortRef.current = abortCtrl;
|
|
613
|
-
// Watchdog: poll /runs/active to detect when the run
|
|
614
|
-
// longer running server-side
|
|
615
|
-
//
|
|
616
|
-
//
|
|
617
|
-
//
|
|
618
|
-
// instead of showing "Thinking..." forever.
|
|
741
|
+
// Watchdog: poll /runs/active every 1s to detect when the run
|
|
742
|
+
// is no longer running server-side, or the heartbeat has gone
|
|
743
|
+
// stale (producer died). Aborts the SSE fetch so we fall
|
|
744
|
+
// through to thread refresh instead of showing "Thinking..."
|
|
745
|
+
// forever.
|
|
619
746
|
const watchdog = setInterval(async () => {
|
|
620
747
|
try {
|
|
621
748
|
const res = await fetch(`${apiUrl}/runs/active?threadId=${encodeURIComponent(threadId)}`);
|
|
@@ -625,7 +752,13 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
625
752
|
return;
|
|
626
753
|
}
|
|
627
754
|
const info = await res.json();
|
|
628
|
-
|
|
755
|
+
const hb = typeof info.heartbeatAt === "number"
|
|
756
|
+
? info.heartbeatAt
|
|
757
|
+
: null;
|
|
758
|
+
const stale = info.status === "running" &&
|
|
759
|
+
hb != null &&
|
|
760
|
+
Date.now() - hb > 5000;
|
|
761
|
+
if (info.status !== "running" || stale) {
|
|
629
762
|
abortCtrl.abort();
|
|
630
763
|
clearInterval(watchdog);
|
|
631
764
|
}
|
|
@@ -633,15 +766,16 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
633
766
|
catch {
|
|
634
767
|
// Network blip — keep polling
|
|
635
768
|
}
|
|
636
|
-
},
|
|
769
|
+
}, 1000);
|
|
637
770
|
// Hard cap: no single reconnect should wedge the UI for
|
|
638
|
-
// more than
|
|
639
|
-
//
|
|
640
|
-
//
|
|
771
|
+
// more than 20s. With the 1s watchdog + stale-heartbeat
|
|
772
|
+
// detection + startup reap, this only triggers in truly
|
|
773
|
+
// pathological cases. Keeps "Reconnecting…" from feeling
|
|
774
|
+
// infinite.
|
|
641
775
|
const maxReconnectTimer = setTimeout(() => {
|
|
642
776
|
abortCtrl.abort();
|
|
643
777
|
clearInterval(watchdog);
|
|
644
|
-
},
|
|
778
|
+
}, 20_000);
|
|
645
779
|
const streamReconnect = async () => {
|
|
646
780
|
try {
|
|
647
781
|
const sseRes = await fetch(`${apiUrl}/runs/${encodeURIComponent(runInfo.runId)}/events?after=0`, { signal: abortCtrl.signal });
|
|
@@ -839,6 +973,36 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
839
973
|
useEffect(() => {
|
|
840
974
|
onMessageCountChange?.(messages.length);
|
|
841
975
|
}, [messages.length, onMessageCountChange]);
|
|
976
|
+
// Persist queued messages to the server so they survive reloads. Debounced
|
|
977
|
+
// to 300ms so typing-and-queuing-rapidly doesn't hammer the endpoint.
|
|
978
|
+
// Stores them in thread_data.queuedMessages via POST /threads/:id/queued.
|
|
979
|
+
useEffect(() => {
|
|
980
|
+
if (!threadId)
|
|
981
|
+
return;
|
|
982
|
+
if (!hasRestoredRef.current)
|
|
983
|
+
return;
|
|
984
|
+
const serialized = JSON.stringify(queuedMessages);
|
|
985
|
+
if (serialized === lastPersistedQueueRef.current)
|
|
986
|
+
return;
|
|
987
|
+
const timer = setTimeout(() => {
|
|
988
|
+
(async () => {
|
|
989
|
+
try {
|
|
990
|
+
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}/queued`, {
|
|
991
|
+
method: "POST",
|
|
992
|
+
headers: { "Content-Type": "application/json" },
|
|
993
|
+
body: JSON.stringify({ queuedMessages }),
|
|
994
|
+
});
|
|
995
|
+
if (res.ok) {
|
|
996
|
+
lastPersistedQueueRef.current = serialized;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
catch {
|
|
1000
|
+
// Best-effort — next queue change will retry.
|
|
1001
|
+
}
|
|
1002
|
+
})();
|
|
1003
|
+
}, 300);
|
|
1004
|
+
return () => clearTimeout(timer);
|
|
1005
|
+
}, [queuedMessages, threadId, apiUrl]);
|
|
842
1006
|
// Listen for missing API key events from the adapter
|
|
843
1007
|
useEffect(() => {
|
|
844
1008
|
const handler = () => setMissingApiKey(true);
|
|
@@ -1027,65 +1191,65 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1027
1191
|
}, 100);
|
|
1028
1192
|
return () => clearInterval(interval);
|
|
1029
1193
|
}, [isRunning]);
|
|
1030
|
-
return (_jsxs("div", { className: cn("flex flex-1 flex-col h-full min-h-0 text-foreground", className), children: [showHeader && (_jsxs("div", { className: "flex h-11 shrink-0 items-center justify-between border-b border-border px-4", children: [_jsx("span", { className: "text-[13px] font-medium text-muted-foreground", children: "Agent" }), _jsx("div", { className: "flex items-center gap-1", children: onSwitchToCli && (_jsxs("button", { onClick: onSwitchToCli, className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", title: "Switch to CLI", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] })) })] })), _jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: authError ? (_jsxs("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-destructive/10", children: _jsx(IconLock, { className: "h-5 w-5 text-destructive" }) }), _jsxs("div", { className: "text-center max-w-[280px]", children: [_jsx("p", { className: "text-sm font-medium text-foreground mb-1", children: authError.sessionExpired
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1194
|
+
return (_jsx(ChatRunningContext.Provider, { value: isRunning, children: _jsxs("div", { className: cn("flex flex-1 flex-col h-full min-h-0 text-foreground", className), children: [showHeader && (_jsxs("div", { className: "flex h-11 shrink-0 items-center justify-between border-b border-border px-4", children: [_jsx("span", { className: "text-[13px] font-medium text-muted-foreground", children: "Agent" }), _jsx("div", { className: "flex items-center gap-1", children: onSwitchToCli && (_jsxs("button", { onClick: onSwitchToCli, className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", title: "Switch to CLI", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] })) })] })), _jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: authError ? (_jsxs("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-destructive/10", children: _jsx(IconLock, { className: "h-5 w-5 text-destructive" }) }), _jsxs("div", { className: "text-center max-w-[280px]", children: [_jsx("p", { className: "text-sm font-medium text-foreground mb-1", children: authError.sessionExpired
|
|
1195
|
+
? "Session expired"
|
|
1196
|
+
: "Authentication required" }), _jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: authError.sessionExpired ? ("Your session may have expired. Log out and log back in to reconnect.") : (_jsxs(_Fragment, { children: ["You need to log in to use the agent. If you're running locally, add", " ", _jsx("code", { className: "bg-muted px-1 py-0.5 rounded text-[10px]", children: "AUTH_MODE=local" }), " ", "to your", " ", _jsx("code", { className: "bg-muted px-1 py-0.5 rounded text-[10px]", children: ".env" }), " ", "file and restart the dev server."] })) })] }), _jsxs("div", { className: "flex gap-2", children: [authError.sessionExpired && (_jsx("button", { onClick: async () => {
|
|
1197
|
+
try {
|
|
1198
|
+
await fetch("/_agent-native/auth/logout", {
|
|
1199
|
+
method: "POST",
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
catch { }
|
|
1203
|
+
window.location.reload();
|
|
1204
|
+
}, className: "text-xs text-destructive hover:text-destructive/80 px-3 py-1.5 rounded-md border border-destructive/30 hover:bg-destructive/10", children: "Log out" })), _jsx("button", { onClick: () => {
|
|
1205
|
+
setAuthError(null);
|
|
1206
|
+
window.location.reload();
|
|
1207
|
+
}, className: "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent", children: "Retry" })] })] })) : missingApiKey ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(ApiKeySetupCard, { apiUrl: apiUrl }) })) : usageLimitReached ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(BuilderCtaCard, { reason: "usage_limit", usageCents: usageLimitReached.usageCents, limitCents: usageLimitReached.limitCents, apiUrl: apiUrl }) })) : isRestoring ? (_jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "flex justify-end", children: _jsx("div", { className: "h-8 w-32 rounded-lg bg-muted animate-pulse" }) }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "h-4 w-48 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-64 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-40 rounded bg-muted animate-pulse" })] })] })) : messages.length === 0 && !isReconnecting ? (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-16 px-4 h-full", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-muted", children: _jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground" }) }), _jsx("p", { className: "text-sm text-muted-foreground text-center max-w-[240px]", children: emptyStateText ?? "How can I help you?" }), suggestions && suggestions.length > 0 && (_jsx("div", { className: "flex flex-col gap-1.5 w-full max-w-[280px]", children: suggestions.map((suggestion) => (_jsx("button", { onClick: () => {
|
|
1208
|
+
threadRuntime.append({
|
|
1209
|
+
role: "user",
|
|
1210
|
+
content: [{ type: "text", text: suggestion }],
|
|
1211
|
+
});
|
|
1212
|
+
}, className: "w-full rounded-lg border border-border px-3 py-2 text-left text-[13px] text-muted-foreground hover:bg-accent hover:text-foreground", children: suggestion }, suggestion))) }))] })) : (_jsxs("div", { className: "agent-thread-content flex flex-col gap-4 px-4 py-4", children: [_jsx(ThreadPrimitive.Messages, { components: {
|
|
1213
|
+
UserMessage,
|
|
1214
|
+
AssistantMessage,
|
|
1215
|
+
} }), showContinue && !showRunningInUI && (_jsx("div", { className: "flex justify-center py-2", children: _jsx("button", { type: "button", onClick: () => {
|
|
1216
|
+
setShowContinue(false);
|
|
1217
|
+
addToQueue("Continue from where you left off.");
|
|
1218
|
+
}, className: "rounded-lg border border-border bg-background px-4 py-2 text-sm font-medium text-foreground hover:bg-accent", children: "Continue" }) })), (isReconnecting || reconnectFrozen) &&
|
|
1219
|
+
reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), showRunningInUI && (_jsx(ThinkingIndicator, { label: isReconnecting ? "Reconnecting" : "Thinking" })), queuedMessages.map((msg) => {
|
|
1220
|
+
const displayText = msg.text
|
|
1221
|
+
.replace(/<context>[\s\S]*?<\/context>\n?/g, "")
|
|
1222
|
+
.trim();
|
|
1223
|
+
return (_jsx("div", { className: "flex justify-end group", children: _jsxs("div", { className: "relative max-w-[85%] rounded-lg bg-accent/50 text-foreground/60 px-3 py-2 text-sm leading-relaxed whitespace-pre-wrap break-words", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground mb-1 font-medium uppercase tracking-wide", children: [_jsx(IconClock, { className: "h-3 w-3" }), "Queued"] }), displayText, msg.images && msg.images.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5 mt-1.5", children: msg.images.map((img, j) => (_jsx("img", { src: img, alt: "", className: "h-12 w-12 rounded object-cover border border-border/50" }, j))) })), _jsx("button", { type: "button", onClick: () => setQueuedMessages((prev) => prev.filter((m) => m.id !== msg.id)), "aria-label": "Remove from queue", className: "absolute -top-2 -right-2 flex h-5 w-5 items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 group-hover:opacity-100 focus-visible:opacity-100 hover:text-foreground hover:bg-accent shadow-sm", children: _jsx(IconX, { className: "h-3 w-3" }) })] }) }, msg.id));
|
|
1224
|
+
})] })) }), showScrollToBottom && (_jsx("div", { className: "shrink-0 flex justify-center -mb-1", children: _jsx("button", { type: "button", onClick: scrollToBottom, className: "flex h-7 w-7 items-center justify-center rounded-full border border-border bg-background shadow-sm hover:bg-accent", "aria-label": "Scroll to bottom", children: _jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" }) }) })), composerSlot, _jsx("div", { className: "agent-composer-area shrink-0 px-3 py-2", children: _jsxs(ComposerPrimitive.Root, { className: "flex flex-col rounded-lg border border-input bg-background focus-within:ring-1 focus-within:ring-ring", children: [_jsx(ComposerAttachmentPreviewStrip, {}), _jsx(TiptapComposer, { focusRef: tiptapRef, placeholder: isRunning
|
|
1225
|
+
? queuedMessages.length > 0
|
|
1226
|
+
? `${queuedMessages.length} queued — type another...`
|
|
1227
|
+
: "Queue a message..."
|
|
1228
|
+
: undefined, onSubmit: isRunning
|
|
1229
|
+
? (text, references) => addToQueue(text, undefined, references.length > 0 ? references : undefined)
|
|
1230
|
+
: undefined, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, extraActionButton: showRunningInUI ? (_jsx("button", { type: "button", onClick: () => {
|
|
1231
|
+
// Nuclear stop: flip forceStopped so isRunning is false
|
|
1232
|
+
// immediately. This unblocks submission even if the
|
|
1233
|
+
// runtime or reconnect state is stuck.
|
|
1234
|
+
setForceStopped(true);
|
|
1235
|
+
if (isReconnecting) {
|
|
1236
|
+
if (reconnectRunIdRef.current) {
|
|
1237
|
+
fetch(`${apiUrl}/runs/${encodeURIComponent(reconnectRunIdRef.current)}/abort`, { method: "POST" });
|
|
1238
|
+
}
|
|
1239
|
+
reconnectAbortRef.current?.abort();
|
|
1240
|
+
reconnectAbortRef.current = null;
|
|
1241
|
+
reconnectRunIdRef.current = null;
|
|
1242
|
+
setIsReconnecting(false);
|
|
1243
|
+
setReconnectFrozen(reconnectContent.length > 0);
|
|
1074
1244
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
detail: {
|
|
1084
|
-
isRunning: false,
|
|
1085
|
-
tabId: tabId || threadId,
|
|
1086
|
-
},
|
|
1087
|
-
}));
|
|
1088
|
-
}, className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-muted text-foreground hover:bg-muted/80", title: "Stop generating", children: _jsx(IconPlayerStop, { className: "h-3.5 w-3.5" }) })) : undefined })] }) })] }));
|
|
1245
|
+
threadRuntime.cancelRun();
|
|
1246
|
+
window.dispatchEvent(new CustomEvent("builder.chatRunning", {
|
|
1247
|
+
detail: {
|
|
1248
|
+
isRunning: false,
|
|
1249
|
+
tabId: tabId || threadId,
|
|
1250
|
+
},
|
|
1251
|
+
}));
|
|
1252
|
+
}, className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-muted text-foreground hover:bg-muted/80", title: "Stop generating", children: _jsx(IconPlayerStop, { className: "h-3.5 w-3.5" }) })) : undefined })] }) })] }) }));
|
|
1089
1253
|
});
|
|
1090
1254
|
export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = "/_agent-native/agent-chat", tabId, threadId, ...props }, ref) {
|
|
1091
1255
|
const adapter = useMemo(() => createAgentChatAdapter({ apiUrl, tabId, threadId }), [apiUrl, tabId, threadId]);
|