@agent-native/core 0.35.3 → 0.37.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.
Files changed (80) hide show
  1. package/dist/cli/index.js +1 -1
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/cli/skills.d.ts.map +1 -1
  4. package/dist/cli/skills.js +249 -11
  5. package/dist/cli/skills.js.map +1 -1
  6. package/dist/client/AssistantChat.d.ts.map +1 -1
  7. package/dist/client/AssistantChat.js +25 -25
  8. package/dist/client/AssistantChat.js.map +1 -1
  9. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  10. package/dist/client/MultiTabAssistantChat.js +32 -15
  11. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  12. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  13. package/dist/client/agent-chat-adapter.js +68 -24
  14. package/dist/client/agent-chat-adapter.js.map +1 -1
  15. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  16. package/dist/client/composer/ComposerPlusMenu.js +174 -8
  17. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  18. package/dist/client/composer/PromptComposer.d.ts +2 -0
  19. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  20. package/dist/client/composer/PromptComposer.js +2 -2
  21. package/dist/client/composer/PromptComposer.js.map +1 -1
  22. package/dist/client/composer/TiptapComposer.js +1 -1
  23. package/dist/client/composer/TiptapComposer.js.map +1 -1
  24. package/dist/client/context-xray/ContextMeter.d.ts +2 -1
  25. package/dist/client/context-xray/ContextMeter.d.ts.map +1 -1
  26. package/dist/client/context-xray/ContextMeter.js +19 -25
  27. package/dist/client/context-xray/ContextMeter.js.map +1 -1
  28. package/dist/client/context-xray/ContextXRayPanel.d.ts +1 -3
  29. package/dist/client/context-xray/ContextXRayPanel.d.ts.map +1 -1
  30. package/dist/client/context-xray/ContextXRayPanel.js +27 -24
  31. package/dist/client/context-xray/ContextXRayPanel.js.map +1 -1
  32. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  33. package/dist/client/conversation/AgentConversation.js +2 -1
  34. package/dist/client/conversation/AgentConversation.js.map +1 -1
  35. package/dist/client/dynamic-suggestions.d.ts +13 -7
  36. package/dist/client/dynamic-suggestions.d.ts.map +1 -1
  37. package/dist/client/dynamic-suggestions.js +23 -12
  38. package/dist/client/dynamic-suggestions.js.map +1 -1
  39. package/dist/client/index.d.ts +1 -0
  40. package/dist/client/index.d.ts.map +1 -1
  41. package/dist/client/index.js +1 -0
  42. package/dist/client/index.js.map +1 -1
  43. package/dist/client/route-state.d.ts +116 -0
  44. package/dist/client/route-state.d.ts.map +1 -0
  45. package/dist/client/route-state.js +205 -0
  46. package/dist/client/route-state.js.map +1 -0
  47. package/dist/client/sse-event-processor.d.ts +1 -0
  48. package/dist/client/sse-event-processor.d.ts.map +1 -1
  49. package/dist/client/sse-event-processor.js +62 -15
  50. package/dist/client/sse-event-processor.js.map +1 -1
  51. package/dist/client/tool-display.d.ts +4 -0
  52. package/dist/client/tool-display.d.ts.map +1 -0
  53. package/dist/client/tool-display.js +28 -0
  54. package/dist/client/tool-display.js.map +1 -0
  55. package/dist/client/use-chat-threads.d.ts.map +1 -1
  56. package/dist/client/use-chat-threads.js +40 -31
  57. package/dist/client/use-chat-threads.js.map +1 -1
  58. package/dist/client/use-external-value.d.ts.map +1 -1
  59. package/dist/client/use-external-value.js +14 -7
  60. package/dist/client/use-external-value.js.map +1 -1
  61. package/dist/extensions/html-shell.d.ts +3 -2
  62. package/dist/extensions/html-shell.d.ts.map +1 -1
  63. package/dist/extensions/html-shell.js +12 -2
  64. package/dist/extensions/html-shell.js.map +1 -1
  65. package/dist/extensions/routes.js +2 -7
  66. package/dist/extensions/routes.js.map +1 -1
  67. package/dist/server/core-routes-plugin.js +2 -2
  68. package/dist/server/core-routes-plugin.js.map +1 -1
  69. package/dist/server/security-headers.d.ts +16 -19
  70. package/dist/server/security-headers.d.ts.map +1 -1
  71. package/dist/server/security-headers.js +24 -25
  72. package/dist/server/security-headers.js.map +1 -1
  73. package/dist/templates/default/AGENTS.md +7 -1
  74. package/dist/templates/default/app/hooks/use-navigation-state.ts +10 -76
  75. package/docs/content/context-awareness.md +90 -48
  76. package/docs/content/creating-templates.md +22 -1
  77. package/docs/content/external-agents.md +1 -1
  78. package/package.json +2 -1
  79. package/src/templates/default/AGENTS.md +7 -1
  80. package/src/templates/default/app/hooks/use-navigation-state.ts +10 -76
@@ -0,0 +1,205 @@
1
+ import { useCallback, useEffect, useMemo, useRef } from "react";
2
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
3
+ import { useLocation, useNavigate, } from "react-router";
4
+ import { deleteClientAppState, readClientAppState, setClientAppState, } from "./application-state.js";
5
+ const SAFE_BROWSER_TAB_ID_RE = /^[A-Za-z0-9_-]{1,96}$/;
6
+ function normalizeBrowserTabId(browserTabId) {
7
+ if (typeof browserTabId !== "string")
8
+ return undefined;
9
+ const trimmed = browserTabId.trim();
10
+ return SAFE_BROWSER_TAB_ID_RE.test(trimmed) ? trimmed : undefined;
11
+ }
12
+ function appStateKeyForBrowserTab(key, browserTabId) {
13
+ return browserTabId ? `${key}:${browserTabId}` : key;
14
+ }
15
+ function routeLocationFromReactRouter(location) {
16
+ return {
17
+ pathname: location.pathname,
18
+ search: location.search,
19
+ hash: location.hash,
20
+ searchParams: new URLSearchParams(location.search),
21
+ location,
22
+ };
23
+ }
24
+ function uniqueKeys(keys) {
25
+ return Array.from(new Set(keys));
26
+ }
27
+ function defaultCommandDedupKey(command) {
28
+ if (command && typeof command === "object" && "_writeId" in command) {
29
+ const writeId = command._writeId;
30
+ if (typeof writeId === "string" && writeId)
31
+ return writeId;
32
+ }
33
+ return JSON.stringify(command);
34
+ }
35
+ function currentRouterPath(location) {
36
+ return `${location.pathname}${location.search}${location.hash}`;
37
+ }
38
+ function stringifyForWriteDedup(value) {
39
+ try {
40
+ return JSON.stringify(value);
41
+ }
42
+ catch {
43
+ return "";
44
+ }
45
+ }
46
+ /**
47
+ * Keeps semantic UI state agent-visible and consumes agent-authored one-shot
48
+ * commands. This is the framework primitive behind route/navigation sync; it
49
+ * intentionally knows nothing about app-specific route shapes.
50
+ */
51
+ export function useSemanticNavigationState(options) {
52
+ const { requestSource, commandRefetchInterval = 2_000, enabled = true, keepalive = true, writeDebounceMs = 0, } = options;
53
+ const queryClient = useQueryClient();
54
+ const navigationKeys = useMemo(() => uniqueKeys(options.navigationKeys ?? ["navigation"]), [options.navigationKeys]);
55
+ const commandKeys = useMemo(() => uniqueKeys(options.commandKeys ?? ["navigate"]), [options.commandKeys]);
56
+ const commandQueryKey = useMemo(() => options.commandQueryKey ?? ["navigate-command"], [options.commandQueryKey]);
57
+ const navigationState = options.state ?? null;
58
+ const navigationWriteDedup = stringifyForWriteDedup({
59
+ keys: navigationKeys,
60
+ state: navigationState,
61
+ });
62
+ const getCommandDedupKeyRef = useRef(options.getCommandDedupKey);
63
+ const onCommandRef = useRef(options.onCommand);
64
+ const onErrorRef = useRef(options.onError);
65
+ getCommandDedupKeyRef.current = options.getCommandDedupKey;
66
+ onCommandRef.current = options.onCommand;
67
+ onErrorRef.current = options.onError;
68
+ const lastNavigationWriteRef = useRef(null);
69
+ useEffect(() => {
70
+ if (!enabled)
71
+ return;
72
+ if (lastNavigationWriteRef.current === navigationWriteDedup)
73
+ return;
74
+ lastNavigationWriteRef.current = navigationWriteDedup;
75
+ const write = () => {
76
+ for (const key of navigationKeys) {
77
+ setClientAppState(key, navigationState, {
78
+ keepalive,
79
+ requestSource,
80
+ }).catch((error) => onErrorRef.current?.(error));
81
+ }
82
+ };
83
+ if (writeDebounceMs > 0) {
84
+ const timer = setTimeout(write, writeDebounceMs);
85
+ return () => clearTimeout(timer);
86
+ }
87
+ write();
88
+ }, [
89
+ enabled,
90
+ keepalive,
91
+ navigationKeys,
92
+ navigationState,
93
+ navigationWriteDedup,
94
+ requestSource,
95
+ writeDebounceMs,
96
+ ]);
97
+ const commandQuery = useQuery({
98
+ queryKey: commandQueryKey,
99
+ enabled,
100
+ retry: false,
101
+ refetchInterval: commandRefetchInterval,
102
+ queryFn: async () => {
103
+ for (const key of commandKeys) {
104
+ const command = await readClientAppState(key);
105
+ if (command !== null && command !== undefined) {
106
+ return { key, command };
107
+ }
108
+ }
109
+ return null;
110
+ },
111
+ });
112
+ const clearCommand = useCallback(async () => {
113
+ await Promise.all(commandKeys.map((key) => deleteClientAppState(key, { requestSource }).catch((error) => {
114
+ onErrorRef.current?.(error);
115
+ })));
116
+ queryClient.setQueryData(commandQueryKey, null);
117
+ }, [commandKeys, commandQueryKey, queryClient, requestSource]);
118
+ const lastProcessedDedupKeyRef = useRef(null);
119
+ useEffect(() => {
120
+ const envelope = commandQuery.data;
121
+ if (!enabled || !envelope)
122
+ return;
123
+ const dedupKey = getCommandDedupKeyRef.current?.(envelope.command) ??
124
+ defaultCommandDedupKey(envelope.command);
125
+ const consume = () => {
126
+ deleteClientAppState(envelope.key, { requestSource }).catch((error) => onErrorRef.current?.(error));
127
+ queryClient.setQueryData(commandQueryKey, null);
128
+ };
129
+ if (lastProcessedDedupKeyRef.current === dedupKey) {
130
+ consume();
131
+ return;
132
+ }
133
+ lastProcessedDedupKeyRef.current = dedupKey;
134
+ consume();
135
+ Promise.resolve(onCommandRef.current(envelope.command)).catch((error) => onErrorRef.current?.(error));
136
+ }, [commandQuery.data, commandQueryKey, enabled, queryClient, requestSource]);
137
+ return {
138
+ navigationState,
139
+ command: commandQuery.data,
140
+ commandQueryKey,
141
+ clearCommand,
142
+ };
143
+ }
144
+ /**
145
+ * React Router convenience wrapper around `useSemanticNavigationState`.
146
+ *
147
+ * Use URL query params as the source of truth for shareable filters. This hook
148
+ * writes semantic aliases and stable IDs to `navigation`; the framework's
149
+ * built-in URL sync separately exposes raw `pathname`, `search`, and
150
+ * `searchParams` through `<current-url>` and the `set-search-params` tool.
151
+ */
152
+ export function useAgentRouteState(options) {
153
+ const { navigationKey = "navigation", commandKey = "navigate", writeGlobalNavigation = true, readGlobalCommandFallback = true, } = options;
154
+ const location = useLocation();
155
+ const navigate = useNavigate();
156
+ const browserTabId = useMemo(() => normalizeBrowserTabId(options.browserTabId), [options.browserTabId]);
157
+ const navigationKeys = useMemo(() => {
158
+ const scopedKey = appStateKeyForBrowserTab(navigationKey, browserTabId);
159
+ const keys = [scopedKey];
160
+ if (browserTabId && writeGlobalNavigation)
161
+ keys.push(navigationKey);
162
+ return uniqueKeys(keys);
163
+ }, [browserTabId, navigationKey, writeGlobalNavigation]);
164
+ const commandKeys = useMemo(() => {
165
+ const scopedKey = appStateKeyForBrowserTab(commandKey, browserTabId);
166
+ const keys = [scopedKey];
167
+ if (browserTabId && readGlobalCommandFallback)
168
+ keys.push(commandKey);
169
+ return uniqueKeys(keys);
170
+ }, [browserTabId, commandKey, readGlobalCommandFallback]);
171
+ const commandQueryKey = useMemo(() => options.commandQueryKey ?? [
172
+ "navigate-command",
173
+ commandKey,
174
+ browserTabId ?? "global",
175
+ ], [browserTabId, commandKey, options.commandQueryKey]);
176
+ const routeLocation = useMemo(() => routeLocationFromReactRouter(location), [location]);
177
+ const navigationState = options.getNavigationState(routeLocation) ?? null;
178
+ return useSemanticNavigationState({
179
+ state: navigationState,
180
+ navigationKeys,
181
+ commandKeys,
182
+ commandQueryKey,
183
+ requestSource: options.requestSource,
184
+ commandRefetchInterval: options.refetchInterval,
185
+ enabled: options.enabled,
186
+ keepalive: options.keepalive,
187
+ writeDebounceMs: options.writeDebounceMs,
188
+ getCommandDedupKey: options.getCommandDedupKey,
189
+ onError: options.onError,
190
+ onCommand: (command) => {
191
+ const path = options.getCommandPath(command);
192
+ if (!path)
193
+ return;
194
+ options.onNavigate?.(command, path);
195
+ if (path === currentRouterPath(location))
196
+ return;
197
+ const navigateOptions = options.navigateOptions;
198
+ const resolvedOptions = typeof navigateOptions === "function"
199
+ ? navigateOptions(command)
200
+ : navigateOptions;
201
+ navigate(path, resolvedOptions);
202
+ },
203
+ });
204
+ }
205
+ //# sourceMappingURL=route-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-state.js","sourceRoot":"","sources":["../../src/client/route-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAiB,MAAM,uBAAuB,CAAC;AAChF,OAAO,EACL,WAAW,EACX,WAAW,GAGZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AA4HvD,SAAS,qBAAqB,CAAC,YAAqB;IAClD,IAAI,OAAO,YAAY,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACvD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;IACpC,OAAO,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACpE,CAAC;AAED,SAAS,wBAAwB,CAAC,GAAW,EAAE,YAAqB;IAClE,OAAO,YAAY,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AACvD,CAAC;AAED,SAAS,4BAA4B,CAAC,QAAkB;IACtD,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,YAAY,EAAE,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC;QAClD,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAAuB;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAgB;IAC9C,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,UAAU,IAAI,OAAO,EAAE,CAAC;QACpE,MAAM,OAAO,GAAI,OAAkC,CAAC,QAAQ,CAAC;QAC7D,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;IAC7D,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAkB;IAC3C,OAAO,GAAG,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC5C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAIxC,OAA4E;IAE5E,MAAM,EACJ,aAAa,EACb,sBAAsB,GAAG,KAAK,EAC9B,OAAO,GAAG,IAAI,EACd,SAAS,GAAG,IAAI,EAChB,eAAe,GAAG,CAAC,GACpB,GAAG,OAAO,CAAC;IAEZ,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,cAAc,GAAG,OAAO,CAC5B,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,IAAI,CAAC,YAAY,CAAC,CAAC,EAC1D,CAAC,OAAO,CAAC,cAAc,CAAC,CACzB,CAAC;IACF,MAAM,WAAW,GAAG,OAAO,CACzB,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,UAAU,CAAC,CAAC,EACrD,CAAC,OAAO,CAAC,WAAW,CAAC,CACtB,CAAC;IACF,MAAM,eAAe,GAAG,OAAO,CAC7B,GAAG,EAAE,CAAC,OAAO,CAAC,eAAe,IAAI,CAAC,kBAAkB,CAAC,EACrD,CAAC,OAAO,CAAC,eAAe,CAAC,CAC1B,CAAC;IACF,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;IAC9C,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;QAClD,IAAI,EAAE,cAAc;QACpB,KAAK,EAAE,eAAe;KACvB,CAAC,CAAC;IAEH,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjE,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,qBAAqB,CAAC,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAC3D,YAAY,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IACzC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAErC,MAAM,sBAAsB,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAE3D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,IAAI,sBAAsB,CAAC,OAAO,KAAK,oBAAoB;YAAE,OAAO;QACpE,sBAAsB,CAAC,OAAO,GAAG,oBAAoB,CAAC;QAEtD,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;gBACjC,iBAAiB,CAAC,GAAG,EAAE,eAAe,EAAE;oBACtC,SAAS;oBACT,aAAa;iBACd,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YACnD,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;YACjD,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QACD,KAAK,EAAE,CAAC;IACV,CAAC,EAAE;QACD,OAAO;QACP,SAAS;QACT,cAAc;QACd,eAAe;QACf,oBAAoB;QACpB,aAAa;QACb,eAAe;KAChB,CAAC,CAAC;IAEH,MAAM,YAAY,GAChB,QAAQ,CAA4D;QAClE,QAAQ,EAAE,eAAe;QACzB,OAAO;QACP,KAAK,EAAE,KAAK;QACZ,eAAe,EAAE,sBAAsB;QACvC,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;gBAC9B,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAkB,GAAG,CAAC,CAAC;gBAC/D,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC9C,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;gBAC1B,CAAC;YACH,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC,CAAC;IAEL,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,OAAO,CAAC,GAAG,CACf,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACtB,oBAAoB,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YAC3D,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC,CAAC,CACH,CACF,CAAC;QACF,WAAW,CAAC,YAAY,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC,EAAE,CAAC,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;IAE/D,MAAM,wBAAwB,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAE7D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC;QACnC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ;YAAE,OAAO;QAElC,MAAM,QAAQ,GACZ,qBAAqB,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;YACjD,sBAAsB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,oBAAoB,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CACpE,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAC5B,CAAC;YACF,WAAW,CAAC,YAAY,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC,CAAC;QAEF,IAAI,wBAAwB,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAClD,OAAO,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,wBAAwB,CAAC,OAAO,GAAG,QAAQ,CAAC;QAC5C,OAAO,EAAE,CAAC;QAEV,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CACtE,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAC5B,CAAC;IACJ,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;IAE9E,OAAO;QACL,eAAe;QACf,OAAO,EAAE,YAAY,CAAC,IAAI;QAC1B,eAAe;QACf,YAAY;KACb,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAIhC,OAAoE;IAEpE,MAAM,EACJ,aAAa,GAAG,YAAY,EAC5B,UAAU,GAAG,UAAU,EACvB,qBAAqB,GAAG,IAAI,EAC5B,yBAAyB,GAAG,IAAI,GACjC,GAAG,OAAO,CAAC;IAEZ,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,YAAY,CAAC,EACjD,CAAC,OAAO,CAAC,YAAY,CAAC,CACvB,CAAC;IACF,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE;QAClC,MAAM,SAAS,GAAG,wBAAwB,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QACxE,MAAM,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QACzB,IAAI,YAAY,IAAI,qBAAqB;YAAE,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACpE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,EAAE,CAAC,YAAY,EAAE,aAAa,EAAE,qBAAqB,CAAC,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;QAC/B,MAAM,SAAS,GAAG,wBAAwB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QACzB,IAAI,YAAY,IAAI,yBAAyB;YAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,OAAO,CAC7B,GAAG,EAAE,CACH,OAAO,CAAC,eAAe,IAAI;QACzB,kBAAkB;QAClB,UAAU;QACV,YAAY,IAAI,QAAQ;KACzB,EACH,CAAC,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,eAAe,CAAC,CACpD,CAAC;IAEF,MAAM,aAAa,GAAG,OAAO,CAC3B,GAAG,EAAE,CAAC,4BAA4B,CAAC,QAAQ,CAAC,EAC5C,CAAC,QAAQ,CAAC,CACX,CAAC;IACF,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC;IAE1E,OAAO,0BAA0B,CAAmC;QAClE,KAAK,EAAE,eAAe;QACtB,cAAc;QACd,WAAW;QACX,eAAe;QACf,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,sBAAsB,EAAE,OAAO,CAAC,eAAe;QAC/C,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;YACrB,MAAM,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,OAAO,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACpC,IAAI,IAAI,KAAK,iBAAiB,CAAC,QAAQ,CAAC;gBAAE,OAAO;YAEjD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;YAChD,MAAM,eAAe,GACnB,OAAO,eAAe,KAAK,UAAU;gBACnC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC;gBAC1B,CAAC,CAAC,eAAe,CAAC;YACtB,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAClC,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useQuery, useQueryClient, type QueryKey } from \"@tanstack/react-query\";\nimport {\n useLocation,\n useNavigate,\n type Location,\n type NavigateOptions,\n} from \"react-router\";\nimport {\n deleteClientAppState,\n readClientAppState,\n setClientAppState,\n} from \"./application-state.js\";\n\nconst SAFE_BROWSER_TAB_ID_RE = /^[A-Za-z0-9_-]{1,96}$/;\n\nexport interface SemanticNavigationCommandEnvelope<NavigateCommand> {\n key: string;\n command: NavigateCommand;\n}\n\nexport interface UseSemanticNavigationStateOptions<\n NavigationState,\n NavigateCommand = NavigationState,\n> {\n /**\n * Compact, semantic screen state to expose to the agent: view names, record\n * IDs, active tabs, and useful aliases. Keep URL query params in the URL\n * unless the app needs a human-readable semantic alias.\n */\n state: NavigationState | null | undefined;\n /** Application-state keys the UI should write. Defaults to [`navigation`]. */\n navigationKeys?: readonly string[];\n /** Application-state keys to read for one-shot agent commands. Defaults to [`navigate`]. */\n commandKeys?: readonly string[];\n /** React Query key used for command polling/cache. Defaults to [`navigate-command`]. */\n commandQueryKey?: QueryKey;\n /** Request source tag for `useDbSync({ ignoreSource })` jitter prevention. */\n requestSource?: string;\n /** Poll interval for command reads. Defaults to 2000ms. Pass false to disable polling. */\n commandRefetchInterval?: number | false;\n /** Disable both navigation writes and command reads. */\n enabled?: boolean;\n /** Navigation writes use keepalive by default because they often fire during unload. */\n keepalive?: boolean;\n /** Debounce navigation writes. Defaults to 0ms. */\n writeDebounceMs?: number;\n /** Custom duplicate-command key. Defaults to `_writeId` or JSON content. */\n getCommandDedupKey?: (command: NavigateCommand) => string;\n /** Called once for each non-duplicate command after the command is consumed. */\n onCommand: (command: NavigateCommand) => void | Promise<void>;\n /** Optional sink for best-effort navigation write/read/delete/command errors. */\n onError?: (error: unknown) => void;\n}\n\nexport interface UseSemanticNavigationStateResult<\n NavigationState,\n NavigateCommand = NavigationState,\n> {\n navigationState: NavigationState | null;\n command:\n | SemanticNavigationCommandEnvelope<NavigateCommand>\n | null\n | undefined;\n commandQueryKey: QueryKey;\n clearCommand: () => Promise<void>;\n}\n\nexport interface AgentRouteLocation {\n pathname: string;\n search: string;\n hash: string;\n searchParams: URLSearchParams;\n location: Location;\n}\n\nexport interface UseAgentRouteStateOptions<\n NavigationState,\n NavigateCommand = NavigationState,\n> {\n /**\n * Derive compact, semantic screen state from the current React Router URL.\n * The framework separately exposes raw `pathname`, `search`, and parsed\n * `searchParams` through `<current-url>`.\n */\n getNavigationState: (\n location: AgentRouteLocation,\n ) => NavigationState | null | undefined;\n /**\n * Convert an agent-authored one-shot command into an app-local React Router\n * path. Return null to consume and ignore malformed or unsupported commands.\n */\n getCommandPath: (command: NavigateCommand) => string | null | undefined;\n /** Application-state key the UI writes. Defaults to `navigation`. */\n navigationKey?: string;\n /** Application-state key the agent writes for one-shot navigation. */\n commandKey?: string;\n /** Current browser tab id. Enables tab-scoped reads/writes. */\n browserTabId?: string;\n /** Request source tag for `useDbSync({ ignoreSource })` jitter prevention. */\n requestSource?: string;\n /**\n * Also write the unscoped navigation key when browserTabId is present.\n * Defaults to true so CLI/external agents still have a useful fallback.\n */\n writeGlobalNavigation?: boolean;\n /**\n * Fall back to the unscoped command key when no tab-scoped command exists.\n * Defaults to true for backwards compatibility with existing navigate tools.\n */\n readGlobalCommandFallback?: boolean;\n /** React Query key used for command polling/cache. */\n commandQueryKey?: QueryKey;\n /** Poll interval for command reads. Defaults to 2000ms. Pass false to disable polling. */\n refetchInterval?: number | false;\n /** Disable both navigation writes and command reads. */\n enabled?: boolean;\n /** Navigation writes use keepalive by default because they often fire during unload. */\n keepalive?: boolean;\n /** Debounce navigation writes. Defaults to 0ms. */\n writeDebounceMs?: number;\n /** Custom duplicate-command key. Defaults to `_writeId` or JSON content. */\n getCommandDedupKey?: (command: NavigateCommand) => string;\n /** React Router navigate options, or a function of the consumed command. */\n navigateOptions?:\n | NavigateOptions\n | ((command: NavigateCommand) => NavigateOptions | undefined);\n /** Called after a command is consumed and before React Router navigation. */\n onNavigate?: (command: NavigateCommand, path: string) => void;\n /** Optional sink for best-effort navigation write/read/delete errors. */\n onError?: (error: unknown) => void;\n}\n\nexport interface UseAgentRouteStateResult<\n NavigationState,\n NavigateCommand = NavigationState,\n> extends UseSemanticNavigationStateResult<NavigationState, NavigateCommand> {}\n\nfunction normalizeBrowserTabId(browserTabId?: string): string | undefined {\n if (typeof browserTabId !== \"string\") return undefined;\n const trimmed = browserTabId.trim();\n return SAFE_BROWSER_TAB_ID_RE.test(trimmed) ? trimmed : undefined;\n}\n\nfunction appStateKeyForBrowserTab(key: string, browserTabId?: string): string {\n return browserTabId ? `${key}:${browserTabId}` : key;\n}\n\nfunction routeLocationFromReactRouter(location: Location): AgentRouteLocation {\n return {\n pathname: location.pathname,\n search: location.search,\n hash: location.hash,\n searchParams: new URLSearchParams(location.search),\n location,\n };\n}\n\nfunction uniqueKeys(keys: readonly string[]): string[] {\n return Array.from(new Set(keys));\n}\n\nfunction defaultCommandDedupKey(command: unknown): string {\n if (command && typeof command === \"object\" && \"_writeId\" in command) {\n const writeId = (command as { _writeId?: unknown })._writeId;\n if (typeof writeId === \"string\" && writeId) return writeId;\n }\n return JSON.stringify(command);\n}\n\nfunction currentRouterPath(location: Location): string {\n return `${location.pathname}${location.search}${location.hash}`;\n}\n\nfunction stringifyForWriteDedup(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return \"\";\n }\n}\n\n/**\n * Keeps semantic UI state agent-visible and consumes agent-authored one-shot\n * commands. This is the framework primitive behind route/navigation sync; it\n * intentionally knows nothing about app-specific route shapes.\n */\nexport function useSemanticNavigationState<\n NavigationState,\n NavigateCommand = NavigationState,\n>(\n options: UseSemanticNavigationStateOptions<NavigationState, NavigateCommand>,\n): UseSemanticNavigationStateResult<NavigationState, NavigateCommand> {\n const {\n requestSource,\n commandRefetchInterval = 2_000,\n enabled = true,\n keepalive = true,\n writeDebounceMs = 0,\n } = options;\n\n const queryClient = useQueryClient();\n const navigationKeys = useMemo(\n () => uniqueKeys(options.navigationKeys ?? [\"navigation\"]),\n [options.navigationKeys],\n );\n const commandKeys = useMemo(\n () => uniqueKeys(options.commandKeys ?? [\"navigate\"]),\n [options.commandKeys],\n );\n const commandQueryKey = useMemo<QueryKey>(\n () => options.commandQueryKey ?? [\"navigate-command\"],\n [options.commandQueryKey],\n );\n const navigationState = options.state ?? null;\n const navigationWriteDedup = stringifyForWriteDedup({\n keys: navigationKeys,\n state: navigationState,\n });\n\n const getCommandDedupKeyRef = useRef(options.getCommandDedupKey);\n const onCommandRef = useRef(options.onCommand);\n const onErrorRef = useRef(options.onError);\n getCommandDedupKeyRef.current = options.getCommandDedupKey;\n onCommandRef.current = options.onCommand;\n onErrorRef.current = options.onError;\n\n const lastNavigationWriteRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n if (lastNavigationWriteRef.current === navigationWriteDedup) return;\n lastNavigationWriteRef.current = navigationWriteDedup;\n\n const write = () => {\n for (const key of navigationKeys) {\n setClientAppState(key, navigationState, {\n keepalive,\n requestSource,\n }).catch((error) => onErrorRef.current?.(error));\n }\n };\n\n if (writeDebounceMs > 0) {\n const timer = setTimeout(write, writeDebounceMs);\n return () => clearTimeout(timer);\n }\n write();\n }, [\n enabled,\n keepalive,\n navigationKeys,\n navigationState,\n navigationWriteDedup,\n requestSource,\n writeDebounceMs,\n ]);\n\n const commandQuery =\n useQuery<SemanticNavigationCommandEnvelope<NavigateCommand> | null>({\n queryKey: commandQueryKey,\n enabled,\n retry: false,\n refetchInterval: commandRefetchInterval,\n queryFn: async () => {\n for (const key of commandKeys) {\n const command = await readClientAppState<NavigateCommand>(key);\n if (command !== null && command !== undefined) {\n return { key, command };\n }\n }\n return null;\n },\n });\n\n const clearCommand = useCallback(async () => {\n await Promise.all(\n commandKeys.map((key) =>\n deleteClientAppState(key, { requestSource }).catch((error) => {\n onErrorRef.current?.(error);\n }),\n ),\n );\n queryClient.setQueryData(commandQueryKey, null);\n }, [commandKeys, commandQueryKey, queryClient, requestSource]);\n\n const lastProcessedDedupKeyRef = useRef<string | null>(null);\n\n useEffect(() => {\n const envelope = commandQuery.data;\n if (!enabled || !envelope) return;\n\n const dedupKey =\n getCommandDedupKeyRef.current?.(envelope.command) ??\n defaultCommandDedupKey(envelope.command);\n const consume = () => {\n deleteClientAppState(envelope.key, { requestSource }).catch((error) =>\n onErrorRef.current?.(error),\n );\n queryClient.setQueryData(commandQueryKey, null);\n };\n\n if (lastProcessedDedupKeyRef.current === dedupKey) {\n consume();\n return;\n }\n lastProcessedDedupKeyRef.current = dedupKey;\n consume();\n\n Promise.resolve(onCommandRef.current(envelope.command)).catch((error) =>\n onErrorRef.current?.(error),\n );\n }, [commandQuery.data, commandQueryKey, enabled, queryClient, requestSource]);\n\n return {\n navigationState,\n command: commandQuery.data,\n commandQueryKey,\n clearCommand,\n };\n}\n\n/**\n * React Router convenience wrapper around `useSemanticNavigationState`.\n *\n * Use URL query params as the source of truth for shareable filters. This hook\n * writes semantic aliases and stable IDs to `navigation`; the framework's\n * built-in URL sync separately exposes raw `pathname`, `search`, and\n * `searchParams` through `<current-url>` and the `set-search-params` tool.\n */\nexport function useAgentRouteState<\n NavigationState,\n NavigateCommand = NavigationState,\n>(\n options: UseAgentRouteStateOptions<NavigationState, NavigateCommand>,\n): UseAgentRouteStateResult<NavigationState, NavigateCommand> {\n const {\n navigationKey = \"navigation\",\n commandKey = \"navigate\",\n writeGlobalNavigation = true,\n readGlobalCommandFallback = true,\n } = options;\n\n const location = useLocation();\n const navigate = useNavigate();\n const browserTabId = useMemo(\n () => normalizeBrowserTabId(options.browserTabId),\n [options.browserTabId],\n );\n const navigationKeys = useMemo(() => {\n const scopedKey = appStateKeyForBrowserTab(navigationKey, browserTabId);\n const keys = [scopedKey];\n if (browserTabId && writeGlobalNavigation) keys.push(navigationKey);\n return uniqueKeys(keys);\n }, [browserTabId, navigationKey, writeGlobalNavigation]);\n const commandKeys = useMemo(() => {\n const scopedKey = appStateKeyForBrowserTab(commandKey, browserTabId);\n const keys = [scopedKey];\n if (browserTabId && readGlobalCommandFallback) keys.push(commandKey);\n return uniqueKeys(keys);\n }, [browserTabId, commandKey, readGlobalCommandFallback]);\n const commandQueryKey = useMemo<QueryKey>(\n () =>\n options.commandQueryKey ?? [\n \"navigate-command\",\n commandKey,\n browserTabId ?? \"global\",\n ],\n [browserTabId, commandKey, options.commandQueryKey],\n );\n\n const routeLocation = useMemo(\n () => routeLocationFromReactRouter(location),\n [location],\n );\n const navigationState = options.getNavigationState(routeLocation) ?? null;\n\n return useSemanticNavigationState<NavigationState, NavigateCommand>({\n state: navigationState,\n navigationKeys,\n commandKeys,\n commandQueryKey,\n requestSource: options.requestSource,\n commandRefetchInterval: options.refetchInterval,\n enabled: options.enabled,\n keepalive: options.keepalive,\n writeDebounceMs: options.writeDebounceMs,\n getCommandDedupKey: options.getCommandDedupKey,\n onError: options.onError,\n onCommand: (command) => {\n const path = options.getCommandPath(command);\n if (!path) return;\n options.onNavigate?.(command, path);\n if (path === currentRouterPath(location)) return;\n\n const navigateOptions = options.navigateOptions;\n const resolvedOptions =\n typeof navigateOptions === \"function\"\n ? navigateOptions(command)\n : navigateOptions;\n navigate(path, resolvedOptions);\n },\n });\n}\n"]}
@@ -11,6 +11,7 @@ export type ContentPart = {
11
11
  args: Record<string, string>;
12
12
  result?: string;
13
13
  mcpApp?: AgentMcpAppPayload;
14
+ activity?: boolean;
14
15
  };
15
16
  export interface SSEEvent {
16
17
  type: string;
@@ -1 +1 @@
1
- {"version":3,"file":"sse-event-processor.d.ts","sourceRoot":"","sources":["../../src/client/sse-event-processor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sse-event-processor.d.ts","sourceRoot":"","sources":["../../src/client/sse-event-processor.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { formatChatErrorText, normalizeChatError } from "./error-format.js";
2
+ import { humanizeToolLabelText, runningToolLabel } from "./tool-display.js";
2
3
  export class AgentAutoContinueSignal extends Error {
3
4
  reason;
4
5
  maxIterations;
@@ -12,6 +13,17 @@ export class AgentAutoContinueSignal extends Error {
12
13
  }
13
14
  }
14
15
  export const SSE_NO_PROGRESS_TIMEOUT_MS = 75_000;
16
+ function findPendingToolCallIndex(content, toolName) {
17
+ for (let i = content.length - 1; i >= 0; i--) {
18
+ const part = content[i];
19
+ if (part.type === "tool-call" &&
20
+ part.toolName === toolName &&
21
+ part.result === undefined) {
22
+ return i;
23
+ }
24
+ }
25
+ return -1;
26
+ }
15
27
  function appendActivityTrail(trail, next) {
16
28
  const label = next.label.trim();
17
29
  if (!label)
@@ -169,19 +181,36 @@ export function processEvent(ev, content, toolCallCounter, tabId) {
169
181
  };
170
182
  }
171
183
  if (ev.type === "activity") {
184
+ const tool = ev.tool?.trim() || undefined;
185
+ const label = humanizeToolLabelText(ev.label ?? "Working", tool);
172
186
  if (typeof window !== "undefined") {
173
187
  window.dispatchEvent(new CustomEvent("agent-chat:activity", {
174
188
  detail: {
175
- label: ev.label ?? "Working",
176
- ...(ev.tool ? { tool: ev.tool } : {}),
189
+ label,
190
+ ...(tool ? { tool } : {}),
177
191
  tabId,
178
192
  },
179
193
  }));
180
194
  }
181
- return { action: "continue" };
195
+ if (!tool)
196
+ return { action: "continue" };
197
+ const pendingToolCallIndex = findPendingToolCallIndex(content, tool);
198
+ if (pendingToolCallIndex === -1) {
199
+ content.push({
200
+ type: "tool-call",
201
+ toolCallId: `tc_${++toolCallCounter.value}`,
202
+ toolName: tool,
203
+ argsText: "",
204
+ args: {},
205
+ activity: true,
206
+ });
207
+ }
208
+ return {
209
+ action: "yield",
210
+ result: { content: [...content] },
211
+ };
182
212
  }
183
213
  if (ev.type === "tool_start") {
184
- const toolCallId = `tc_${++toolCallCounter.value}`;
185
214
  const args = (ev.input ?? {});
186
215
  const tool = ev.tool ?? "unknown";
187
216
  if (typeof window !== "undefined") {
@@ -190,19 +219,36 @@ export function processEvent(ev, content, toolCallCounter, tabId) {
190
219
  }));
191
220
  window.dispatchEvent(new CustomEvent("agent-chat:activity", {
192
221
  detail: {
193
- label: `Running ${tool}`,
222
+ label: runningToolLabel(tool),
194
223
  tool,
195
224
  tabId,
196
225
  },
197
226
  }));
198
227
  }
199
- content.push({
200
- type: "tool-call",
201
- toolCallId,
202
- toolName: tool,
203
- argsText: JSON.stringify(args),
204
- args,
205
- });
228
+ const pendingToolCallIndex = findPendingToolCallIndex(content, tool);
229
+ const pendingToolCall = pendingToolCallIndex >= 0 ? content[pendingToolCallIndex] : undefined;
230
+ if (pendingToolCall &&
231
+ pendingToolCall.type === "tool-call" &&
232
+ pendingToolCall.activity === true &&
233
+ pendingToolCall.argsText === "" &&
234
+ Object.keys(pendingToolCall.args).length === 0) {
235
+ content[pendingToolCallIndex] = {
236
+ type: "tool-call",
237
+ toolCallId: pendingToolCall.toolCallId,
238
+ toolName: tool,
239
+ argsText: JSON.stringify(args),
240
+ args,
241
+ };
242
+ }
243
+ else {
244
+ content.push({
245
+ type: "tool-call",
246
+ toolCallId: `tc_${++toolCallCounter.value}`,
247
+ toolName: tool,
248
+ argsText: JSON.stringify(args),
249
+ args,
250
+ });
251
+ }
206
252
  return {
207
253
  action: "yield",
208
254
  result: { content: [...content] },
@@ -492,15 +538,16 @@ export async function* readSSEStream(body, content, toolCallCounter, tabId, onSe
492
538
  activityTrail.length = 0;
493
539
  }
494
540
  else if (ev.type === "activity") {
541
+ const tool = ev.tool?.trim() || undefined;
495
542
  appendActivityTrail(activityTrail, {
496
- label: ev.label ?? "Working",
497
- ...(ev.tool ? { tool: ev.tool } : {}),
543
+ label: humanizeToolLabelText(ev.label ?? "Working", tool),
544
+ ...(tool ? { tool } : {}),
498
545
  });
499
546
  }
500
547
  else if (ev.type === "tool_start") {
501
548
  const tool = ev.tool ?? "unknown";
502
549
  appendActivityTrail(activityTrail, {
503
- label: `Running ${tool}`,
550
+ label: runningToolLabel(tool),
504
551
  tool,
505
552
  });
506
553
  }