@agent-native/core 0.91.2 → 0.92.0
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 +2 -2
- package/corpus/core/CHANGELOG.md +17 -0
- package/corpus/core/docs/content/faq.mdx +17 -0
- package/corpus/core/docs/content/notifications.mdx +12 -6
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +140 -46
- package/corpus/core/src/agent/tool-search.ts +71 -4
- package/corpus/core/src/cli/index.ts +20 -0
- package/corpus/core/src/cli/upgrade.ts +798 -0
- package/corpus/core/src/client/AssistantChat.tsx +1 -1
- package/corpus/core/src/client/HighlightedCodeBlock.tsx +20 -3
- package/corpus/core/src/client/agent-chat-adapter.ts +31 -6
- package/corpus/core/src/client/chat/message-components.tsx +85 -8
- package/corpus/core/src/client/chat/tool-call-display.tsx +355 -144
- package/corpus/core/src/client/code-agent-chat-adapter.ts +2 -9
- package/corpus/core/src/client/session-replay.ts +3 -97
- package/corpus/core/src/client/settings/SettingsPanel.tsx +533 -389
- package/corpus/core/src/client/settings/SettingsSection.tsx +154 -17
- package/corpus/core/src/client/sse-event-processor.ts +29 -2
- package/corpus/core/src/extensions/actions.ts +113 -5
- package/corpus/core/src/notifications/channels.ts +88 -25
- package/corpus/core/src/notifications/registry.ts +17 -3
- package/corpus/core/src/notifications/types.ts +4 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +7 -3
- package/corpus/core/src/server/request-context.ts +7 -0
- package/corpus/core/src/styles/agent-conversation.css +1 -1
- package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/core/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/core/src/templates/default/AGENTS.md +10 -3
- package/corpus/core/src/templates/default/package.json +2 -1
- package/corpus/core/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/core/src/templates/headless/AGENTS.md +9 -3
- package/corpus/core/src/templates/headless/package.json +1 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/core/src/templates/workspace-root/AGENTS.md +10 -4
- package/corpus/core/src/templates/workspace-root/package.json +1 -0
- package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +5 -6
- package/corpus/templates/analytics/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/analytics/AGENTS.md +7 -5
- package/corpus/templates/analytics/actions/save-monitor.ts +14 -0
- package/corpus/templates/analytics/app/components/dashboard/DataTable.tsx +41 -6
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +122 -11
- package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +8 -2
- package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +151 -32
- package/corpus/templates/analytics/app/pages/monitoring/uptime/i18n.ts +17 -2
- package/corpus/templates/analytics/app/pages/monitoring/uptime/types.ts +4 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +54 -190
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-tables-keep-their-size-while-loading.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-monitoring-uptime-and-errors-tabs-now-clearly-show-which-view-is-active.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-uses-stock-rrweb-sizing-again-so-recorded.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-sidebar-dashboard-menus-now-open-above-the-dashboard-canvas.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-uptime-alerting-clarifies-in-app-inbox-vs-email-and-lets-you-paste-slack-or-webhook-urls-per-monitor.md +6 -0
- package/corpus/templates/analytics/docs/uptime-monitoring.md +13 -11
- package/corpus/templates/analytics/server/db/schema-monitoring.ts +4 -0
- package/corpus/templates/analytics/server/lib/uptime-monitors.ts +60 -12
- package/corpus/templates/analytics/server/plugins/db.ts +10 -0
- package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/assets/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/brain/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/calendar/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/clips/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/clips/changelog/2026-07-08-desktop-meeting-notes-stay-active-from-tray-and-shortcut-controls.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-desktop-meeting-popovers-can-start-notes-and-join-the-meetin.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-meeting-notes-keep-their-recording-state-when-the-desktop.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-meeting-reminder-dropdowns-now-expand-fully-instead-of-being.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +123 -3
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +15 -1
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +23 -0
- package/corpus/templates/clips/desktop/src/styles.css +23 -1
- package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +1 -3
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +40 -6
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -2
- package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +3 -5
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +23 -19
- package/corpus/templates/clips/desktop/src-tauri/src/shortcuts.rs +3 -3
- package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +0 -1
- package/corpus/templates/clips/desktop/src-tauri/src/state.rs +5 -0
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +18 -6
- package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/content/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/content/actions/_batch-utils.ts +8 -0
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +7 -5
- package/corpus/templates/content/actions/_database-source-utils.ts +776 -319
- package/corpus/templates/content/actions/_database-utils.ts +6 -1
- package/corpus/templates/content/actions/_property-utils.ts +168 -0
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +19 -12
- package/corpus/templates/content/actions/bind-content-database-source-field.ts +19 -12
- package/corpus/templates/content/actions/delete-document.ts +9 -13
- package/corpus/templates/content/actions/refresh-content-database-source.ts +5 -5
- package/corpus/templates/content/app/components/editor/body-hydration.ts +35 -11
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +47 -5
- package/corpus/templates/content/app/hooks/use-documents.ts +8 -2
- package/corpus/templates/content/changelog/2026-07-08-builder-source-sync-now-completes-reliably-on-hosted-databases.md +6 -0
- package/corpus/templates/content/changelog/2026-07-08-fixed-builder-database-sync-so-large-sources-continue-past-t.md +6 -0
- package/corpus/templates/content/server/plugins/db.ts +19 -0
- package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/design/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/dispatch/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/forms/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/macros/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/mail/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/plan/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/corpus/templates/slides/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/videos/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/voice/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/dist/agent/production-agent.d.ts +5 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +112 -42
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/tool-search.d.ts +2 -0
- package/dist/agent/tool-search.d.ts.map +1 -1
- package/dist/agent/tool-search.js +60 -4
- package/dist/agent/tool-search.js.map +1 -1
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/upgrade.d.ts +100 -0
- package/dist/cli/upgrade.d.ts.map +1 -0
- package/dist/cli/upgrade.js +678 -0
- package/dist/cli/upgrade.js.map +1 -0
- package/dist/client/AssistantChat.js +1 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/HighlightedCodeBlock.d.ts +2 -0
- package/dist/client/HighlightedCodeBlock.d.ts.map +1 -1
- package/dist/client/HighlightedCodeBlock.js +10 -1
- package/dist/client/HighlightedCodeBlock.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +32 -4
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +61 -8
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +12 -0
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +136 -42
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/code-agent-chat-adapter.js +2 -9
- package/dist/client/code-agent-chat-adapter.js.map +1 -1
- package/dist/client/session-replay.d.ts +0 -8
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +3 -80
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +52 -19
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsSection.d.ts +19 -4
- package/dist/client/settings/SettingsSection.d.ts.map +1 -1
- package/dist/client/settings/SettingsSection.js +33 -4
- package/dist/client/settings/SettingsSection.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +9 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +20 -2
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +85 -5
- package/dist/extensions/actions.js.map +1 -1
- package/dist/notifications/channels.d.ts +8 -3
- package/dist/notifications/channels.d.ts.map +1 -1
- package/dist/notifications/channels.js +61 -22
- package/dist/notifications/channels.js.map +1 -1
- package/dist/notifications/registry.d.ts.map +1 -1
- package/dist/notifications/registry.js +14 -3
- package/dist/notifications/registry.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/notifications/types.d.ts +4 -1
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/notifications/types.js.map +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-chat-plugin.d.ts +5 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +2 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js.map +1 -1
- package/dist/styles/agent-conversation.css +1 -1
- package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/dist/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/dist/templates/default/AGENTS.md +10 -3
- package/dist/templates/default/package.json +2 -1
- package/dist/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/dist/templates/headless/AGENTS.md +9 -3
- package/dist/templates/headless/package.json +1 -0
- package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/dist/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/dist/templates/workspace-root/AGENTS.md +10 -4
- package/dist/templates/workspace-root/package.json +1 -0
- package/docs/content/faq.mdx +17 -0
- package/docs/content/notifications.mdx +12 -6
- package/package.json +2 -2
- package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/src/templates/default/AGENTS.md +10 -3
- package/src/templates/default/package.json +2 -1
- package/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/src/templates/headless/AGENTS.md +9 -3
- package/src/templates/headless/package.json +1 -0
- package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +20 -2
- package/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/src/templates/workspace-root/AGENTS.md +10 -4
- package/src/templates/workspace-root/package.json +1 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-clamps-ultra-wide-viewports-while-keeping-the.md +0 -6
|
@@ -6,12 +6,14 @@ import {
|
|
|
6
6
|
IconLoader2,
|
|
7
7
|
IconCircleX,
|
|
8
8
|
IconCheck,
|
|
9
|
-
|
|
10
|
-
IconChevronDown,
|
|
9
|
+
IconChevronRight,
|
|
11
10
|
IconCopy,
|
|
11
|
+
IconCode,
|
|
12
|
+
IconBrandSlack,
|
|
13
|
+
IconTerminal2,
|
|
14
|
+
IconDatabase,
|
|
12
15
|
IconSearch,
|
|
13
|
-
|
|
14
|
-
IconArrowsMinimize,
|
|
16
|
+
IconFileCode,
|
|
15
17
|
IconShieldCheck,
|
|
16
18
|
IconX,
|
|
17
19
|
} from "@tabler/icons-react";
|
|
@@ -19,7 +21,7 @@ import React, {
|
|
|
19
21
|
useState,
|
|
20
22
|
useEffect,
|
|
21
23
|
useCallback,
|
|
22
|
-
|
|
24
|
+
useLayoutEffect,
|
|
23
25
|
useRef,
|
|
24
26
|
} from "react";
|
|
25
27
|
|
|
@@ -27,6 +29,7 @@ import type { ActionChatUIConfig } from "../../action-ui.js";
|
|
|
27
29
|
import type { AgentMcpAppPayload } from "../../mcp-client/app-result.js";
|
|
28
30
|
import { AgentTaskCard } from "../AgentTaskCard.js";
|
|
29
31
|
import { writeClipboardText } from "../clipboard.js";
|
|
32
|
+
import { Dialog, DialogContent, DialogTitle } from "../components/ui/dialog.js";
|
|
30
33
|
import { ConnectBuilderCard } from "../ConnectBuilderCard.js";
|
|
31
34
|
import { McpAppRenderer } from "../mcp-apps/McpAppRenderer.js";
|
|
32
35
|
import type { ContentPart } from "../sse-event-processor.js";
|
|
@@ -225,53 +228,97 @@ export function toolResultPayload(
|
|
|
225
228
|
};
|
|
226
229
|
}
|
|
227
230
|
|
|
228
|
-
// ───
|
|
231
|
+
// ─── Tool icon helpers ────────────────────────────────────────────────────────
|
|
229
232
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
function countTextMatches(text: string, query: string): number {
|
|
235
|
-
const needle = query.trim();
|
|
236
|
-
if (!needle) return 0;
|
|
237
|
-
return Array.from(text.matchAll(new RegExp(escapeRegExp(needle), "gi")))
|
|
238
|
-
.length;
|
|
239
|
-
}
|
|
233
|
+
type ToolIconComponent = React.ComponentType<{
|
|
234
|
+
className?: string;
|
|
235
|
+
size?: number | string;
|
|
236
|
+
}>;
|
|
240
237
|
|
|
241
|
-
function
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
238
|
+
function resolveToolIcon(toolName: string): ToolIconComponent {
|
|
239
|
+
const name = toolName.toLowerCase();
|
|
240
|
+
if (name.includes("slack")) return IconBrandSlack;
|
|
241
|
+
if (
|
|
242
|
+
name.includes("bash") ||
|
|
243
|
+
name.includes("shell") ||
|
|
244
|
+
name.includes("terminal") ||
|
|
245
|
+
name.includes("run-code") ||
|
|
246
|
+
name.includes("exec")
|
|
247
|
+
) {
|
|
248
|
+
return IconTerminal2;
|
|
249
|
+
}
|
|
250
|
+
if (
|
|
251
|
+
name.includes("sql") ||
|
|
252
|
+
name.includes("bigquery") ||
|
|
253
|
+
name.includes("db-query") ||
|
|
254
|
+
name.includes("query")
|
|
255
|
+
) {
|
|
256
|
+
return IconDatabase;
|
|
258
257
|
}
|
|
259
|
-
if (
|
|
260
|
-
|
|
258
|
+
if (
|
|
259
|
+
name.includes("search") ||
|
|
260
|
+
name.includes("find") ||
|
|
261
|
+
name.includes("grep")
|
|
262
|
+
) {
|
|
263
|
+
return IconSearch;
|
|
264
|
+
}
|
|
265
|
+
if (
|
|
266
|
+
name.includes("file") ||
|
|
267
|
+
name.includes("read") ||
|
|
268
|
+
name.includes("write") ||
|
|
269
|
+
name.includes("edit")
|
|
270
|
+
) {
|
|
271
|
+
return IconFileCode;
|
|
272
|
+
}
|
|
273
|
+
return IconCode;
|
|
261
274
|
}
|
|
262
275
|
|
|
263
|
-
// ───
|
|
276
|
+
// ─── Simple code viewer (Codex-style gray box) ────────────────────────────────
|
|
264
277
|
|
|
265
|
-
function
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
278
|
+
function SimpleCodeViewer({
|
|
279
|
+
text,
|
|
280
|
+
lang,
|
|
281
|
+
className,
|
|
282
|
+
maxHeightClass = "max-h-56",
|
|
283
|
+
}: {
|
|
284
|
+
text: string;
|
|
285
|
+
lang: string;
|
|
286
|
+
className?: string;
|
|
287
|
+
maxHeightClass?: string;
|
|
288
|
+
}) {
|
|
289
|
+
return (
|
|
290
|
+
<div
|
|
291
|
+
className={cn(
|
|
292
|
+
"agent-tool-code overflow-auto rounded-md bg-muted/70 font-mono text-[11px] leading-relaxed text-foreground",
|
|
293
|
+
maxHeightClass,
|
|
294
|
+
className,
|
|
295
|
+
)}
|
|
296
|
+
>
|
|
297
|
+
{lang !== "text" && (
|
|
298
|
+
<div className="sticky top-0 z-[1] flex items-center justify-between border-b border-border/40 bg-muted/90 px-2.5 py-1">
|
|
299
|
+
<span className="font-mono text-[10px] uppercase tracking-wide text-muted-foreground/80">
|
|
300
|
+
{lang}
|
|
301
|
+
</span>
|
|
302
|
+
</div>
|
|
303
|
+
)}
|
|
304
|
+
<HighlightedCodeBlock code={text} lang={lang} />
|
|
305
|
+
</div>
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function ToolOutputModal({
|
|
310
|
+
open,
|
|
311
|
+
onOpenChange,
|
|
312
|
+
title,
|
|
313
|
+
payload,
|
|
314
|
+
}: {
|
|
315
|
+
open: boolean;
|
|
316
|
+
onOpenChange: (open: boolean) => void;
|
|
317
|
+
title: string;
|
|
318
|
+
payload: ToolDetailPayload;
|
|
319
|
+
}) {
|
|
269
320
|
const [copied, setCopied] = useState(false);
|
|
270
321
|
const copyResetRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
271
|
-
const matchCount = useMemo(
|
|
272
|
-
() => countTextMatches(payload.text, search),
|
|
273
|
-
[payload.text, search],
|
|
274
|
-
);
|
|
275
322
|
|
|
276
323
|
useEffect(() => {
|
|
277
324
|
return () => {
|
|
@@ -292,81 +339,95 @@ function ToolDetailViewer({ payload }: { payload: ToolDetailPayload }) {
|
|
|
292
339
|
}, [payload.copyText]);
|
|
293
340
|
|
|
294
341
|
return (
|
|
295
|
-
<
|
|
296
|
-
<
|
|
297
|
-
<div className="
|
|
298
|
-
<
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
342
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
343
|
+
<DialogContent className="flex h-[min(80vh,720px)] w-[min(92vw,760px)] max-w-[760px] flex-col gap-0 overflow-hidden p-0">
|
|
344
|
+
<div className="flex shrink-0 items-center justify-between gap-3 border-b border-border px-5 py-3 pr-12">
|
|
345
|
+
<DialogTitle className="truncate text-sm font-medium">
|
|
346
|
+
{title}
|
|
347
|
+
</DialogTitle>
|
|
348
|
+
<button
|
|
349
|
+
type="button"
|
|
350
|
+
onClick={copyValue}
|
|
351
|
+
className="inline-flex h-7 items-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
352
|
+
>
|
|
353
|
+
{copied ? <IconCheck size={13} /> : <IconCopy size={13} />}
|
|
354
|
+
{copied ? "Copied" : "Copy"}
|
|
355
|
+
</button>
|
|
308
356
|
</div>
|
|
309
|
-
<
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
className={cn(
|
|
315
|
-
"inline-flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
316
|
-
searchOpen && "bg-accent text-foreground",
|
|
317
|
-
)}
|
|
318
|
-
>
|
|
319
|
-
<IconSearch size={12} />
|
|
320
|
-
</button>
|
|
321
|
-
<button
|
|
322
|
-
type="button"
|
|
323
|
-
onClick={() => setExpanded((v) => !v)}
|
|
324
|
-
aria-label={expanded ? "Shrink code viewer" : "Expand code viewer"}
|
|
325
|
-
aria-pressed={expanded}
|
|
326
|
-
className="inline-flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
327
|
-
>
|
|
328
|
-
{expanded ? (
|
|
329
|
-
<IconArrowsMinimize size={12} />
|
|
330
|
-
) : (
|
|
331
|
-
<IconArrowsMaximize size={12} />
|
|
332
|
-
)}
|
|
333
|
-
</button>
|
|
334
|
-
<button
|
|
335
|
-
type="button"
|
|
336
|
-
onClick={copyValue}
|
|
337
|
-
className="inline-flex h-6 items-center gap-1 rounded-md px-1.5 font-sans text-[11px] text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
338
|
-
>
|
|
339
|
-
{copied ? <IconCheck size={12} /> : <IconCopy size={12} />}
|
|
340
|
-
{copied ? "Copied" : "Copy"}
|
|
341
|
-
</button>
|
|
342
|
-
</div>
|
|
343
|
-
{searchOpen && (
|
|
344
|
-
<div className="flex items-center gap-2 border-b border-border/50 px-2.5 py-2">
|
|
345
|
-
<input
|
|
346
|
-
value={search}
|
|
347
|
-
onChange={(e) => setSearch(e.target.value)}
|
|
348
|
-
placeholder="Find"
|
|
349
|
-
className="h-7 min-w-0 flex-1 rounded-md border border-border bg-background px-2 text-xs text-foreground outline-none placeholder:text-muted-foreground focus:ring-1 focus:ring-ring"
|
|
357
|
+
<div className="min-h-0 flex-1 overflow-auto p-4">
|
|
358
|
+
<SimpleCodeViewer
|
|
359
|
+
text={payload.text}
|
|
360
|
+
lang={payload.lang}
|
|
361
|
+
maxHeightClass="max-h-none"
|
|
350
362
|
/>
|
|
351
|
-
<span className="shrink-0 text-[11px] text-muted-foreground">
|
|
352
|
-
{search.trim() ? matchCount : ""}
|
|
353
|
-
</span>
|
|
354
363
|
</div>
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
364
|
+
</DialogContent>
|
|
365
|
+
</Dialog>
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// ─── Collapsible height animation ─────────────────────────────────────────────
|
|
370
|
+
|
|
371
|
+
function AnimatedCollapse({
|
|
372
|
+
open,
|
|
373
|
+
children,
|
|
374
|
+
}: {
|
|
375
|
+
open: boolean;
|
|
376
|
+
children: React.ReactNode;
|
|
377
|
+
}) {
|
|
378
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
379
|
+
const [height, setHeight] = useState<number | "auto">(open ? "auto" : 0);
|
|
380
|
+
const [mounted, setMounted] = useState(open);
|
|
381
|
+
const reduceMotionRef = useRef(false);
|
|
382
|
+
|
|
383
|
+
useEffect(() => {
|
|
384
|
+
reduceMotionRef.current =
|
|
385
|
+
typeof window !== "undefined" &&
|
|
386
|
+
!!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
387
|
+
}, []);
|
|
388
|
+
|
|
389
|
+
useLayoutEffect(() => {
|
|
390
|
+
if (open) setMounted(true);
|
|
391
|
+
}, [open]);
|
|
392
|
+
|
|
393
|
+
useLayoutEffect(() => {
|
|
394
|
+
const el = ref.current;
|
|
395
|
+
if (!el || !mounted) return;
|
|
396
|
+
if (reduceMotionRef.current) {
|
|
397
|
+
setHeight(open ? "auto" : 0);
|
|
398
|
+
if (!open) setMounted(false);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (open) {
|
|
402
|
+
const full = el.scrollHeight;
|
|
403
|
+
setHeight(0);
|
|
404
|
+
const frame = requestAnimationFrame(() => setHeight(full));
|
|
405
|
+
return () => cancelAnimationFrame(frame);
|
|
406
|
+
}
|
|
407
|
+
setHeight(el.scrollHeight);
|
|
408
|
+
const frame = requestAnimationFrame(() => setHeight(0));
|
|
409
|
+
return () => cancelAnimationFrame(frame);
|
|
410
|
+
}, [open, mounted]);
|
|
411
|
+
|
|
412
|
+
const onTransitionEnd = useCallback(
|
|
413
|
+
(event: React.TransitionEvent<HTMLDivElement>) => {
|
|
414
|
+
if (event.propertyName !== "height") return;
|
|
415
|
+
if (open) setHeight("auto");
|
|
416
|
+
else setMounted(false);
|
|
417
|
+
},
|
|
418
|
+
[open],
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
if (!mounted) return null;
|
|
422
|
+
|
|
423
|
+
return (
|
|
424
|
+
<div
|
|
425
|
+
ref={ref}
|
|
426
|
+
className="overflow-hidden transition-[height] duration-200 ease-out"
|
|
427
|
+
style={{ height: height === "auto" ? "auto" : `${height}px` }}
|
|
428
|
+
onTransitionEnd={onTransitionEnd}
|
|
429
|
+
>
|
|
430
|
+
{children}
|
|
370
431
|
</div>
|
|
371
432
|
);
|
|
372
433
|
}
|
|
@@ -548,6 +609,7 @@ function ToolCallDisplayGeneric({
|
|
|
548
609
|
|
|
549
610
|
const isAgentCall = toolName.startsWith("agent:");
|
|
550
611
|
const [expanded, setExpanded] = useState(isAgentCall);
|
|
612
|
+
const [outputOpen, setOutputOpen] = useState(false);
|
|
551
613
|
const agentName = isAgentCall ? toolName.slice(6) : null;
|
|
552
614
|
const isAgentError = isAgentCall && result === "Error calling agent";
|
|
553
615
|
const agentStreamText = isAgentCall ? (argsText ?? "") : "";
|
|
@@ -659,34 +721,47 @@ function ToolCallDisplayGeneric({
|
|
|
659
721
|
? hasStreamText
|
|
660
722
|
: hasArgs || result !== undefined;
|
|
661
723
|
const isExpanded = isAgentCall ? hasStreamText && expanded : expanded;
|
|
724
|
+
const ToolIcon = resolveToolIcon(toolName);
|
|
725
|
+
const outputTitle = `Raw ${toolName} tool call output`;
|
|
662
726
|
|
|
663
727
|
return (
|
|
664
|
-
<div className="my-
|
|
728
|
+
<div className="group/tool my-0.5 w-full overflow-hidden">
|
|
665
729
|
{mcpApp && <McpAppRenderer app={mcpApp} className="mb-1.5" />}
|
|
666
730
|
<button
|
|
731
|
+
type="button"
|
|
667
732
|
onClick={() => canExpand && setExpanded(!isExpanded)}
|
|
668
733
|
aria-expanded={canExpand ? isExpanded : undefined}
|
|
669
734
|
className={cn(
|
|
670
|
-
"flex items-center gap-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
: "bg-muted text-muted-foreground hover:bg-accent",
|
|
735
|
+
"flex w-full items-center gap-1.5 rounded-md py-0.5 text-left text-[13px] text-muted-foreground transition-colors",
|
|
736
|
+
canExpand && "hover:text-foreground",
|
|
737
|
+
isRunning && "text-muted-foreground",
|
|
674
738
|
)}
|
|
675
739
|
>
|
|
676
|
-
<span className="shrink-0">
|
|
740
|
+
<span className="relative flex size-4 shrink-0 items-center justify-center">
|
|
677
741
|
{isRunning ? (
|
|
678
|
-
<IconLoader2 className="
|
|
742
|
+
<IconLoader2 className="size-3.5 animate-spin" />
|
|
679
743
|
) : isAgentError ? (
|
|
680
|
-
<IconCircleX className="
|
|
681
|
-
) : result !== undefined ? (
|
|
682
|
-
<IconCheck className="h-3 w-3 text-emerald-500" />
|
|
744
|
+
<IconCircleX className="size-3.5 text-destructive" />
|
|
683
745
|
) : (
|
|
684
|
-
|
|
746
|
+
<>
|
|
747
|
+
<ToolIcon
|
|
748
|
+
className={cn(
|
|
749
|
+
"size-3.5 transition-opacity",
|
|
750
|
+
canExpand && "group-hover/tool:opacity-0",
|
|
751
|
+
)}
|
|
752
|
+
/>
|
|
753
|
+
{canExpand && (
|
|
754
|
+
<IconChevronRight
|
|
755
|
+
className={cn(
|
|
756
|
+
"absolute size-3.5 opacity-0 transition-all group-hover/tool:opacity-100",
|
|
757
|
+
isExpanded && "rotate-90",
|
|
758
|
+
)}
|
|
759
|
+
/>
|
|
760
|
+
)}
|
|
761
|
+
</>
|
|
685
762
|
)}
|
|
686
763
|
</span>
|
|
687
|
-
<span className="
|
|
688
|
-
<span className="font-medium">{displayName}</span>
|
|
689
|
-
</span>
|
|
764
|
+
<span className="min-w-0 truncate font-normal">{displayName}</span>
|
|
690
765
|
{repeatCount && repeatCount > 1 && (
|
|
691
766
|
<span
|
|
692
767
|
className="shrink-0 rounded border border-border/60 px-1.5 py-0.5 text-[10px] leading-none text-muted-foreground"
|
|
@@ -695,16 +770,8 @@ function ToolCallDisplayGeneric({
|
|
|
695
770
|
{repeatCount}x
|
|
696
771
|
</span>
|
|
697
772
|
)}
|
|
698
|
-
{canExpand && (
|
|
699
|
-
<IconChevronDown
|
|
700
|
-
className={cn(
|
|
701
|
-
"ml-auto h-3 w-3 shrink-0 opacity-40",
|
|
702
|
-
isExpanded && "rotate-180",
|
|
703
|
-
)}
|
|
704
|
-
/>
|
|
705
|
-
)}
|
|
706
773
|
</button>
|
|
707
|
-
{isExpanded && isAgentCall && hasStreamText
|
|
774
|
+
<AnimatedCollapse open={isExpanded && isAgentCall && hasStreamText}>
|
|
708
775
|
<div
|
|
709
776
|
ref={streamRef}
|
|
710
777
|
className="mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground break-words max-h-48 overflow-y-auto agent-markdown prose prose-sm prose-invert max-w-none"
|
|
@@ -721,12 +788,36 @@ function ToolCallDisplayGeneric({
|
|
|
721
788
|
<span style={{ whiteSpace: "pre-wrap" }}>{agentStreamText}</span>
|
|
722
789
|
)}
|
|
723
790
|
</div>
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
791
|
+
</AnimatedCollapse>
|
|
792
|
+
<AnimatedCollapse
|
|
793
|
+
open={isExpanded && !isAgentCall && (hasArgs || result !== undefined)}
|
|
794
|
+
>
|
|
795
|
+
<div className="mt-1 space-y-2 pl-5">
|
|
796
|
+
{inputPayload && (
|
|
797
|
+
<SimpleCodeViewer
|
|
798
|
+
text={inputPayload.text}
|
|
799
|
+
lang={inputPayload.lang}
|
|
800
|
+
/>
|
|
801
|
+
)}
|
|
802
|
+
{resultPayload && (
|
|
803
|
+
<button
|
|
804
|
+
type="button"
|
|
805
|
+
onClick={() => setOutputOpen(true)}
|
|
806
|
+
aria-label={`View ${toolName} output`}
|
|
807
|
+
className="inline-flex size-6 items-center justify-center rounded-md text-muted-foreground/70 transition-colors hover:bg-accent hover:text-foreground"
|
|
808
|
+
>
|
|
809
|
+
<IconCode className="size-3.5" />
|
|
810
|
+
</button>
|
|
811
|
+
)}
|
|
729
812
|
</div>
|
|
813
|
+
</AnimatedCollapse>
|
|
814
|
+
{resultPayload && (
|
|
815
|
+
<ToolOutputModal
|
|
816
|
+
open={outputOpen}
|
|
817
|
+
onOpenChange={setOutputOpen}
|
|
818
|
+
title={outputTitle}
|
|
819
|
+
payload={resultPayload}
|
|
820
|
+
/>
|
|
730
821
|
)}
|
|
731
822
|
{approval && (
|
|
732
823
|
<ApprovalAffordance toolName={toolName} approval={approval} />
|
|
@@ -788,6 +879,8 @@ export function ReconnectStreamMessage({
|
|
|
788
879
|
const chatRunning = React.useContext(ChatRunningContext);
|
|
789
880
|
const streamingTextPartIndex =
|
|
790
881
|
content.at(-1)?.type === "text" ? content.length - 1 : -1;
|
|
882
|
+
const streamingReasoningPartIndex =
|
|
883
|
+
content.at(-1)?.type === "reasoning" ? content.length - 1 : -1;
|
|
791
884
|
|
|
792
885
|
return (
|
|
793
886
|
<div className="flex justify-start">
|
|
@@ -805,6 +898,15 @@ export function ReconnectStreamMessage({
|
|
|
805
898
|
/>
|
|
806
899
|
);
|
|
807
900
|
}
|
|
901
|
+
if (part.type === "reasoning") {
|
|
902
|
+
return (
|
|
903
|
+
<ReasoningCell
|
|
904
|
+
key={`reconnect-reasoning-${i}`}
|
|
905
|
+
text={part.text}
|
|
906
|
+
isStreaming={chatRunning && i === streamingReasoningPartIndex}
|
|
907
|
+
/>
|
|
908
|
+
);
|
|
909
|
+
}
|
|
808
910
|
if (part.type === "tool-call") {
|
|
809
911
|
return (
|
|
810
912
|
<ToolCallDisplay
|
|
@@ -832,6 +934,115 @@ export function ReconnectStreamMessage({
|
|
|
832
934
|
);
|
|
833
935
|
}
|
|
834
936
|
|
|
937
|
+
// ─── Reasoning / Thinking cell ────────────────────────────────────────────────
|
|
938
|
+
|
|
939
|
+
export function ReasoningCell({
|
|
940
|
+
text,
|
|
941
|
+
isStreaming = false,
|
|
942
|
+
defaultOpen,
|
|
943
|
+
}: {
|
|
944
|
+
text: string;
|
|
945
|
+
isStreaming?: boolean;
|
|
946
|
+
defaultOpen?: boolean;
|
|
947
|
+
}) {
|
|
948
|
+
const [open, setOpen] = useState(defaultOpen ?? isStreaming);
|
|
949
|
+
const trimmed = text.trim();
|
|
950
|
+
if (!trimmed && !isStreaming) return null;
|
|
951
|
+
|
|
952
|
+
return (
|
|
953
|
+
<div className="my-0.5 w-full">
|
|
954
|
+
<button
|
|
955
|
+
type="button"
|
|
956
|
+
onClick={() => setOpen((v) => !v)}
|
|
957
|
+
aria-expanded={open}
|
|
958
|
+
className="flex items-center gap-1.5 py-0.5 text-[13px] text-muted-foreground transition-colors hover:text-foreground"
|
|
959
|
+
>
|
|
960
|
+
<IconChevronRight
|
|
961
|
+
className={cn(
|
|
962
|
+
"size-3.5 shrink-0 transition-transform",
|
|
963
|
+
open && "rotate-90",
|
|
964
|
+
)}
|
|
965
|
+
/>
|
|
966
|
+
<span>{isStreaming ? "Thinking" : "Thought"}</span>
|
|
967
|
+
</button>
|
|
968
|
+
<AnimatedCollapse open={open}>
|
|
969
|
+
<div className="pl-5 pb-1 text-[13px] leading-relaxed text-muted-foreground whitespace-pre-wrap">
|
|
970
|
+
{trimmed || (isStreaming ? "…" : "")}
|
|
971
|
+
</div>
|
|
972
|
+
</AnimatedCollapse>
|
|
973
|
+
</div>
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// ─── Worked-for duration helpers ──────────────────────────────────────────────
|
|
978
|
+
|
|
979
|
+
export function formatWorkedDuration(ms: number): string {
|
|
980
|
+
const totalSeconds = Math.max(0, Math.round(ms / 1000));
|
|
981
|
+
if (totalSeconds < 60) {
|
|
982
|
+
return totalSeconds <= 1 ? "1s" : `${totalSeconds}s`;
|
|
983
|
+
}
|
|
984
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
985
|
+
const seconds = totalSeconds % 60;
|
|
986
|
+
if (minutes < 60) {
|
|
987
|
+
if (seconds === 0) return `${minutes}m`;
|
|
988
|
+
return `${minutes}m ${seconds}s`;
|
|
989
|
+
}
|
|
990
|
+
const hours = Math.floor(minutes / 60);
|
|
991
|
+
const remMinutes = minutes % 60;
|
|
992
|
+
if (remMinutes === 0) return `${hours}h`;
|
|
993
|
+
return `${hours}h ${remMinutes}m`;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
export function WorkedForSummary({
|
|
997
|
+
durationMs,
|
|
998
|
+
autoCollapse = false,
|
|
999
|
+
children,
|
|
1000
|
+
}: {
|
|
1001
|
+
durationMs?: number | null;
|
|
1002
|
+
/** When true, start open then animate closed (post-run collapse). */
|
|
1003
|
+
autoCollapse?: boolean;
|
|
1004
|
+
children: React.ReactNode;
|
|
1005
|
+
}) {
|
|
1006
|
+
const [open, setOpen] = useState(autoCollapse);
|
|
1007
|
+
const didAutoCollapseRef = useRef(false);
|
|
1008
|
+
|
|
1009
|
+
useEffect(() => {
|
|
1010
|
+
if (!autoCollapse || didAutoCollapseRef.current) return;
|
|
1011
|
+
didAutoCollapseRef.current = true;
|
|
1012
|
+
const frame = requestAnimationFrame(() => {
|
|
1013
|
+
setOpen(false);
|
|
1014
|
+
});
|
|
1015
|
+
return () => cancelAnimationFrame(frame);
|
|
1016
|
+
}, [autoCollapse]);
|
|
1017
|
+
|
|
1018
|
+
const label =
|
|
1019
|
+
durationMs != null && durationMs >= 1000
|
|
1020
|
+
? `Worked for ${formatWorkedDuration(durationMs)}`
|
|
1021
|
+
: "Worked";
|
|
1022
|
+
|
|
1023
|
+
return (
|
|
1024
|
+
<div className="my-1 w-full">
|
|
1025
|
+
<button
|
|
1026
|
+
type="button"
|
|
1027
|
+
onClick={() => setOpen((v) => !v)}
|
|
1028
|
+
aria-expanded={open}
|
|
1029
|
+
className="flex items-center gap-1.5 py-0.5 text-[13px] text-muted-foreground transition-colors hover:text-foreground"
|
|
1030
|
+
>
|
|
1031
|
+
<span>{label}</span>
|
|
1032
|
+
<IconChevronRight
|
|
1033
|
+
className={cn(
|
|
1034
|
+
"size-3.5 shrink-0 transition-transform",
|
|
1035
|
+
open && "rotate-90",
|
|
1036
|
+
)}
|
|
1037
|
+
/>
|
|
1038
|
+
</button>
|
|
1039
|
+
<AnimatedCollapse open={open}>
|
|
1040
|
+
<div className="pt-1">{children}</div>
|
|
1041
|
+
</AnimatedCollapse>
|
|
1042
|
+
</div>
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
835
1046
|
// ─── Re-export for AssistantMessage ───────────────────────────────────────────
|
|
836
1047
|
// AssistantMessage in AssistantChat.tsx uses FilesChangedSummary directly, so
|
|
837
1048
|
// re-export it so AssistantChat.tsx can import from one place.
|
|
@@ -357,16 +357,9 @@ function thinkingContentPartForCodeAgentTranscriptItem(
|
|
|
357
357
|
): ContentPart | null {
|
|
358
358
|
const text = item.text.trim();
|
|
359
359
|
if (!text) return null;
|
|
360
|
-
// Surface as a special "thinking" tool-call-like part so the chat renderer
|
|
361
|
-
// can display a collapsed-by-default "Thinking…" cell. Using a distinct
|
|
362
|
-
// toolName makes it easy to style in AssistantChat without a new content type.
|
|
363
360
|
return {
|
|
364
|
-
type: "
|
|
365
|
-
|
|
366
|
-
toolName: "thinking",
|
|
367
|
-
argsText: "",
|
|
368
|
-
args: {},
|
|
369
|
-
result: text,
|
|
361
|
+
type: "reasoning",
|
|
362
|
+
text,
|
|
370
363
|
};
|
|
371
364
|
}
|
|
372
365
|
|