@agent-native/core 0.84.29 → 0.84.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +7 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/chat/tool-call-display.tsx +50 -8
- package/corpus/core/src/client/sse-event-processor.ts +17 -4
- package/corpus/core/src/server/ssr-handler.ts +152 -8
- package/corpus/templates/design/app/pages/DesignEditor.tsx +45 -2
- package/corpus/templates/design/changelog/2026-07-01-design-previews-refresh-immediately-after-agent-screen-edits.md +6 -0
- package/dist/client/chat/tool-call-display.d.ts +1 -0
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +22 -5
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +13 -4
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +111 -8
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.84.30
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 80e618a: Fix hosted Google Analytics / Tag Manager injection by baking the measurement id into Nitro server bundles and merging the required GA/GTM script, connect, and image hosts into existing stricter document CSPs.
|
|
8
|
+
- 80e618a: Improve chat tool-preparation UX by hiding zero-byte progress, using clearer preparation/writing copy, and showing a delayed long-running update hint.
|
|
9
|
+
|
|
3
10
|
## 0.84.29
|
|
4
11
|
|
|
5
12
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.84.
|
|
3
|
+
"version": "0.84.30",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -70,6 +70,43 @@ export const ApprovalContext = React.createContext<ApprovalContextValue | null>(
|
|
|
70
70
|
null,
|
|
71
71
|
);
|
|
72
72
|
|
|
73
|
+
export const TOOL_LONG_RUNNING_HINT_DELAY_MS = 45_000;
|
|
74
|
+
|
|
75
|
+
function ToolLongRunningHintShell({
|
|
76
|
+
toolName,
|
|
77
|
+
isRunning,
|
|
78
|
+
children,
|
|
79
|
+
}: {
|
|
80
|
+
toolName: string;
|
|
81
|
+
isRunning: boolean;
|
|
82
|
+
children: React.ReactNode;
|
|
83
|
+
}) {
|
|
84
|
+
const [showLongRunningHint, setShowLongRunningHint] = useState(false);
|
|
85
|
+
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (!isRunning) {
|
|
88
|
+
setShowLongRunningHint(false);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
setShowLongRunningHint(false);
|
|
92
|
+
const timeout = window.setTimeout(() => {
|
|
93
|
+
setShowLongRunningHint(true);
|
|
94
|
+
}, TOOL_LONG_RUNNING_HINT_DELAY_MS);
|
|
95
|
+
return () => window.clearTimeout(timeout);
|
|
96
|
+
}, [isRunning, toolName]);
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<>
|
|
100
|
+
{children}
|
|
101
|
+
{isRunning && showLongRunningHint && (
|
|
102
|
+
<div className="mt-0.5 px-2.5 text-[11px] leading-snug text-muted-foreground/80">
|
|
103
|
+
Still working. Large updates can take a minute or two.
|
|
104
|
+
</div>
|
|
105
|
+
)}
|
|
106
|
+
</>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
73
110
|
// ─── Tool-payload formatting ──────────────────────────────────────────────────
|
|
74
111
|
|
|
75
112
|
type ToolDetailSection = "input" | "result";
|
|
@@ -435,38 +472,43 @@ export function ToolCallDisplay({
|
|
|
435
472
|
// These must be separate components so hook order in ToolCallDisplayGeneric
|
|
436
473
|
// is always stable (no conditional hook calls).
|
|
437
474
|
const toolKind = structuredMeta?.toolKind as string | undefined;
|
|
475
|
+
const wrapToolDisplay = (children: React.ReactNode) => (
|
|
476
|
+
<ToolLongRunningHintShell toolName={toolName} isRunning={isRunning}>
|
|
477
|
+
{children}
|
|
478
|
+
</ToolLongRunningHintShell>
|
|
479
|
+
);
|
|
438
480
|
if (toolKind === "bash") {
|
|
439
|
-
return (
|
|
481
|
+
return wrapToolDisplay(
|
|
440
482
|
<BashCell
|
|
441
483
|
meta={
|
|
442
484
|
structuredMeta as unknown as Parameters<typeof BashCell>[0]["meta"]
|
|
443
485
|
}
|
|
444
486
|
output={result}
|
|
445
487
|
isRunning={isRunning}
|
|
446
|
-
|
|
488
|
+
/>,
|
|
447
489
|
);
|
|
448
490
|
}
|
|
449
491
|
if (toolKind === "edit") {
|
|
450
|
-
return (
|
|
492
|
+
return wrapToolDisplay(
|
|
451
493
|
<EditCell
|
|
452
494
|
meta={
|
|
453
495
|
structuredMeta as unknown as Parameters<typeof EditCell>[0]["meta"]
|
|
454
496
|
}
|
|
455
497
|
isRunning={isRunning}
|
|
456
|
-
|
|
498
|
+
/>,
|
|
457
499
|
);
|
|
458
500
|
}
|
|
459
501
|
if (toolKind === "write") {
|
|
460
|
-
return (
|
|
502
|
+
return wrapToolDisplay(
|
|
461
503
|
<WriteCell
|
|
462
504
|
meta={
|
|
463
505
|
structuredMeta as unknown as Parameters<typeof WriteCell>[0]["meta"]
|
|
464
506
|
}
|
|
465
507
|
isRunning={isRunning}
|
|
466
|
-
|
|
508
|
+
/>,
|
|
467
509
|
);
|
|
468
510
|
}
|
|
469
|
-
return (
|
|
511
|
+
return wrapToolDisplay(
|
|
470
512
|
<ToolCallDisplayGeneric
|
|
471
513
|
toolName={toolName}
|
|
472
514
|
argsText={argsText}
|
|
@@ -477,7 +519,7 @@ export function ToolCallDisplay({
|
|
|
477
519
|
isRunning={isRunning}
|
|
478
520
|
approval={approval}
|
|
479
521
|
repeatCount={repeatCount}
|
|
480
|
-
|
|
522
|
+
/>,
|
|
481
523
|
);
|
|
482
524
|
}
|
|
483
525
|
|
|
@@ -205,13 +205,26 @@ function baseActivityLabel(ev: SSEEvent, tool?: string): string {
|
|
|
205
205
|
return humanizeToolLabelText(ev.label ?? "Working", tool);
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
function preparationActivityLabel(
|
|
209
|
+
tool: string | undefined,
|
|
210
|
+
progressBytes: number | undefined,
|
|
211
|
+
): string {
|
|
212
|
+
const action = humanizeToolName(tool);
|
|
213
|
+
if (progressBytes === undefined) {
|
|
214
|
+
return `Starting ${action}...`;
|
|
215
|
+
}
|
|
216
|
+
if (progressBytes <= 0) {
|
|
217
|
+
return `Preparing ${action}...`;
|
|
218
|
+
}
|
|
219
|
+
return `Writing ${action}... (${formatProgressBytes(progressBytes)} prepared)`;
|
|
220
|
+
}
|
|
221
|
+
|
|
208
222
|
function visibleActivityLabel(ev: SSEEvent, tool?: string): string {
|
|
209
|
-
const label = baseActivityLabel(ev, tool);
|
|
210
223
|
const progressBytes = activityProgressBytes(ev);
|
|
211
|
-
if (
|
|
212
|
-
return
|
|
224
|
+
if (isPreparingActionActivity(ev)) {
|
|
225
|
+
return preparationActivityLabel(tool, progressBytes);
|
|
213
226
|
}
|
|
214
|
-
return
|
|
227
|
+
return baseActivityLabel(ev, tool);
|
|
215
228
|
}
|
|
216
229
|
|
|
217
230
|
function findPendingToolCallIndex(
|
|
@@ -277,6 +277,59 @@ type CspDirective = {
|
|
|
277
277
|
tokens: string[];
|
|
278
278
|
};
|
|
279
279
|
|
|
280
|
+
const CSP_DIRECTIVES_WITH_VALUE_TOKENS = new Set([
|
|
281
|
+
"base-uri",
|
|
282
|
+
"block-all-mixed-content",
|
|
283
|
+
"child-src",
|
|
284
|
+
"connect-src",
|
|
285
|
+
"default-src",
|
|
286
|
+
"fenced-frame-src",
|
|
287
|
+
"font-src",
|
|
288
|
+
"form-action",
|
|
289
|
+
"frame-ancestors",
|
|
290
|
+
"frame-src",
|
|
291
|
+
"img-src",
|
|
292
|
+
"manifest-src",
|
|
293
|
+
"media-src",
|
|
294
|
+
"navigate-to",
|
|
295
|
+
"object-src",
|
|
296
|
+
"plugin-types",
|
|
297
|
+
"prefetch-src",
|
|
298
|
+
"referrer",
|
|
299
|
+
"reflected-xss",
|
|
300
|
+
"require-sri-for",
|
|
301
|
+
"require-trusted-types-for",
|
|
302
|
+
"report-to",
|
|
303
|
+
"report-uri",
|
|
304
|
+
"sandbox",
|
|
305
|
+
"script-src",
|
|
306
|
+
"script-src-attr",
|
|
307
|
+
"script-src-elem",
|
|
308
|
+
"style-src",
|
|
309
|
+
"style-src-attr",
|
|
310
|
+
"style-src-elem",
|
|
311
|
+
"trusted-types",
|
|
312
|
+
"upgrade-insecure-requests",
|
|
313
|
+
"webrtc",
|
|
314
|
+
"worker-src",
|
|
315
|
+
]);
|
|
316
|
+
|
|
317
|
+
function hasCommaJoinedCspPolicies(policy: string): boolean {
|
|
318
|
+
let commaIndex = policy.indexOf(",");
|
|
319
|
+
while (commaIndex !== -1) {
|
|
320
|
+
const afterComma = policy.slice(commaIndex + 1);
|
|
321
|
+
const directive = /^\s+([a-z][a-z0-9-]*)(?=\s|;|$)/i.exec(afterComma)?.[1];
|
|
322
|
+
if (
|
|
323
|
+
directive &&
|
|
324
|
+
CSP_DIRECTIVES_WITH_VALUE_TOKENS.has(directive.toLowerCase())
|
|
325
|
+
) {
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
commaIndex = policy.indexOf(",", commaIndex + 1);
|
|
329
|
+
}
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
|
|
280
333
|
function parseCsp(policy: string): CspDirective[] {
|
|
281
334
|
return policy
|
|
282
335
|
.split(";")
|
|
@@ -349,13 +402,96 @@ function appendToExistingCspDirective(
|
|
|
349
402
|
existing.tokens = appendCspTokens(existing.tokens, additions);
|
|
350
403
|
}
|
|
351
404
|
|
|
352
|
-
function
|
|
405
|
+
function hasStrictNonceScriptPolicy(tokens: readonly string[]): boolean {
|
|
406
|
+
return tokens.some(
|
|
407
|
+
(token) => token === "'strict-dynamic'" || token.startsWith("'nonce-"),
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function appendToScriptCspDirective(
|
|
412
|
+
directives: CspDirective[],
|
|
413
|
+
name: string,
|
|
414
|
+
additions: readonly string[],
|
|
415
|
+
): boolean {
|
|
416
|
+
const existing = findCspDirective(directives, name);
|
|
417
|
+
if (existing) {
|
|
418
|
+
if (hasStrictNonceScriptPolicy(existing.tokens)) return false;
|
|
419
|
+
existing.tokens = appendCspTokens(existing.tokens, additions);
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const defaultSrc = findCspDirective(directives, "default-src");
|
|
424
|
+
if (!defaultSrc || hasStrictNonceScriptPolicy(defaultSrc.tokens)) {
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
directives.push({
|
|
428
|
+
name,
|
|
429
|
+
tokens: appendCspTokens([...defaultSrc.tokens], additions),
|
|
430
|
+
});
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function appendToEffectiveScriptElementCspDirective(
|
|
435
|
+
directives: CspDirective[],
|
|
436
|
+
additions: readonly string[],
|
|
437
|
+
): boolean {
|
|
438
|
+
const scriptSrcElem = findCspDirective(directives, "script-src-elem");
|
|
439
|
+
if (scriptSrcElem) {
|
|
440
|
+
if (hasStrictNonceScriptPolicy(scriptSrcElem.tokens)) return false;
|
|
441
|
+
scriptSrcElem.tokens = appendCspTokens(scriptSrcElem.tokens, additions);
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return appendToScriptCspDirective(directives, "script-src", additions);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function augmentExistingEnforcedCspForFrameworkScripts(
|
|
449
|
+
policy: string,
|
|
450
|
+
options: {
|
|
451
|
+
gaScriptSrcTokens: readonly string[];
|
|
452
|
+
gaEnabled: boolean;
|
|
453
|
+
},
|
|
454
|
+
): string {
|
|
455
|
+
// Multiple CSP headers are surfaced by Headers.get() as one comma-joined
|
|
456
|
+
// string. CSP is not a comma-list header, so serializing a parsed combined
|
|
457
|
+
// value would turn two policies into one invalid policy. Leave those headers
|
|
458
|
+
// app-owned; a comma inside a source/report URL is still safe to parse.
|
|
459
|
+
if (hasCommaJoinedCspPolicies(policy)) return policy;
|
|
460
|
+
|
|
461
|
+
const directives = parseCsp(policy);
|
|
462
|
+
if (!directives.length) return policy;
|
|
463
|
+
|
|
464
|
+
if (options.gaEnabled) {
|
|
465
|
+
const addedScriptElement = appendToEffectiveScriptElementCspDirective(
|
|
466
|
+
directives,
|
|
467
|
+
options.gaScriptSrcTokens,
|
|
468
|
+
);
|
|
469
|
+
if (addedScriptElement) {
|
|
470
|
+
appendToExistingOrDefaultCspDirective(
|
|
471
|
+
directives,
|
|
472
|
+
"connect-src",
|
|
473
|
+
GA_CSP_CONNECT_HOSTS,
|
|
474
|
+
);
|
|
475
|
+
appendToExistingOrDefaultCspDirective(
|
|
476
|
+
directives,
|
|
477
|
+
"img-src",
|
|
478
|
+
GA_CSP_IMG_HOSTS,
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return serializeCsp(directives);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function augmentExistingReportOnlyCspForFrameworkScripts(
|
|
353
487
|
policy: string,
|
|
354
488
|
options: {
|
|
355
489
|
scriptSrcTokens: readonly string[];
|
|
356
490
|
gaEnabled: boolean;
|
|
357
491
|
},
|
|
358
492
|
): string {
|
|
493
|
+
if (hasCommaJoinedCspPolicies(policy)) return policy;
|
|
494
|
+
|
|
359
495
|
const directives = parseCsp(policy);
|
|
360
496
|
if (!directives.length) return policy;
|
|
361
497
|
|
|
@@ -364,7 +500,6 @@ function augmentExistingCspForFrameworkScripts(
|
|
|
364
500
|
"script-src",
|
|
365
501
|
options.scriptSrcTokens,
|
|
366
502
|
);
|
|
367
|
-
// `script-src-elem` overrides `script-src` for script tags when present.
|
|
368
503
|
appendToExistingCspDirective(
|
|
369
504
|
directives,
|
|
370
505
|
"script-src-elem",
|
|
@@ -409,10 +544,11 @@ function augmentExistingCspForFrameworkScripts(
|
|
|
409
544
|
* instead of reporting a violation on every page load.
|
|
410
545
|
*
|
|
411
546
|
* If an app or host already sends an enforced CSP with `script-src`,
|
|
412
|
-
* `script-src-elem`, `connect-src`, `img-src`, or `default-src`, we merge
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
547
|
+
* `script-src-elem`, `connect-src`, `img-src`, or `default-src`, we merge only
|
|
548
|
+
* GA-specific allowances into existing host/hash policies. Strict nonce or
|
|
549
|
+
* `strict-dynamic` script policies stay app-owned because blindly appending
|
|
550
|
+
* hashes or hosts would widen the policy without reliably loading our injected
|
|
551
|
+
* scripts.
|
|
416
552
|
*
|
|
417
553
|
* Templates additionally render a theme-init inline script whose exact content
|
|
418
554
|
* varies by template (default theme param, custom docs variant, etc.) and which
|
|
@@ -440,6 +576,7 @@ function applyDocumentCsp(headers: Headers, sentryScript: string | null): void {
|
|
|
440
576
|
const gaInlineBody = getGaInlineConfigScriptBody();
|
|
441
577
|
const gaHash = gaInlineBody ? computeInlineScriptHash(gaInlineBody) : null;
|
|
442
578
|
const gaHosts = gaInlineBody ? [...GA_CSP_SCRIPT_HOSTS] : [];
|
|
579
|
+
const gaScriptSrcTokens = [...(gaHash ? [gaHash] : []), ...gaHosts];
|
|
443
580
|
const scriptSrcTokens = [
|
|
444
581
|
"'self'",
|
|
445
582
|
...(sentryHash ? [sentryHash] : []),
|
|
@@ -449,6 +586,7 @@ function applyDocumentCsp(headers: Headers, sentryScript: string | null): void {
|
|
|
449
586
|
|
|
450
587
|
const cspAugmentOptions = {
|
|
451
588
|
scriptSrcTokens,
|
|
589
|
+
gaScriptSrcTokens,
|
|
452
590
|
gaEnabled: Boolean(gaInlineBody),
|
|
453
591
|
};
|
|
454
592
|
const existing = headers.get("content-security-policy") ?? "";
|
|
@@ -460,7 +598,10 @@ function applyDocumentCsp(headers: Headers, sentryScript: string | null): void {
|
|
|
460
598
|
} else {
|
|
461
599
|
headers.set(
|
|
462
600
|
"content-security-policy",
|
|
463
|
-
|
|
601
|
+
augmentExistingEnforcedCspForFrameworkScripts(
|
|
602
|
+
existing,
|
|
603
|
+
cspAugmentOptions,
|
|
604
|
+
),
|
|
464
605
|
);
|
|
465
606
|
}
|
|
466
607
|
|
|
@@ -471,7 +612,10 @@ function applyDocumentCsp(headers: Headers, sentryScript: string | null): void {
|
|
|
471
612
|
} else {
|
|
472
613
|
headers.set(
|
|
473
614
|
"content-security-policy-report-only",
|
|
474
|
-
|
|
615
|
+
augmentExistingReportOnlyCspForFrameworkScripts(
|
|
616
|
+
existingRo,
|
|
617
|
+
cspAugmentOptions,
|
|
618
|
+
),
|
|
475
619
|
);
|
|
476
620
|
}
|
|
477
621
|
}
|
|
@@ -67,7 +67,10 @@ import {
|
|
|
67
67
|
type TweakSelections,
|
|
68
68
|
} from "@shared/resolve-tweaks";
|
|
69
69
|
import { utilityStem, widthToPrefix } from "@shared/responsive-classes";
|
|
70
|
-
import {
|
|
70
|
+
import {
|
|
71
|
+
normalizeDesignSourceType,
|
|
72
|
+
type DesignSourceType,
|
|
73
|
+
} from "@shared/source-mode";
|
|
71
74
|
import {
|
|
72
75
|
IconArrowLeft,
|
|
73
76
|
IconArrowUpRight,
|
|
@@ -347,6 +350,28 @@ function getContentSignature(content: string): string {
|
|
|
347
350
|
return `${content.length}:${hash.toString(36)}`;
|
|
348
351
|
}
|
|
349
352
|
|
|
353
|
+
export function getOverviewScreenRuntimeReplacementKey({
|
|
354
|
+
screenId,
|
|
355
|
+
updatedAt,
|
|
356
|
+
content,
|
|
357
|
+
}: {
|
|
358
|
+
screenId: string;
|
|
359
|
+
updatedAt?: string | null;
|
|
360
|
+
content: string;
|
|
361
|
+
}) {
|
|
362
|
+
return [screenId, updatedAt ?? "", getContentSignature(content)].join(":");
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export function shouldUseOverviewRuntimeReplacement({
|
|
366
|
+
sourceType,
|
|
367
|
+
externalSnapshotHtml,
|
|
368
|
+
}: {
|
|
369
|
+
sourceType?: DesignSourceType | null;
|
|
370
|
+
externalSnapshotHtml?: string | null;
|
|
371
|
+
}) {
|
|
372
|
+
return sourceType === "inline" && !externalSnapshotHtml;
|
|
373
|
+
}
|
|
374
|
+
|
|
350
375
|
function dedupeStringIds(ids: string[]): string[] {
|
|
351
376
|
return Array.from(new Set(ids.filter(Boolean)));
|
|
352
377
|
}
|
|
@@ -17258,12 +17283,26 @@ ${serializedHtml}
|
|
|
17258
17283
|
const screenBridgeUrl = screen.bridgeUrl;
|
|
17259
17284
|
const screenSnapshot =
|
|
17260
17285
|
liveScreenSnapshotsById[screen.id]?.html;
|
|
17286
|
+
const screenContentSignature =
|
|
17287
|
+
getContentSignature(screenContent);
|
|
17288
|
+
const useRuntimeReplacement =
|
|
17289
|
+
shouldUseOverviewRuntimeReplacement({
|
|
17290
|
+
sourceType: screenSourceType,
|
|
17291
|
+
externalSnapshotHtml: screenSnapshot,
|
|
17292
|
+
});
|
|
17293
|
+
const runtimeReplacementKey = useRuntimeReplacement
|
|
17294
|
+
? getOverviewScreenRuntimeReplacementKey({
|
|
17295
|
+
screenId: screen.id,
|
|
17296
|
+
updatedAt: screen.updatedAt,
|
|
17297
|
+
content: screenContent,
|
|
17298
|
+
})
|
|
17299
|
+
: undefined;
|
|
17261
17300
|
const screenContentKey = screenIsActive
|
|
17262
17301
|
? [screen.id, contentRenderRevision].join(":")
|
|
17263
17302
|
: [
|
|
17264
17303
|
screen.id,
|
|
17265
17304
|
screen.updatedAt ?? "",
|
|
17266
|
-
|
|
17305
|
+
screenContentSignature,
|
|
17267
17306
|
0,
|
|
17268
17307
|
].join(":");
|
|
17269
17308
|
|
|
@@ -17271,6 +17310,10 @@ ${serializedHtml}
|
|
|
17271
17310
|
<DesignCanvas
|
|
17272
17311
|
content={screenContent}
|
|
17273
17312
|
contentKey={screenContentKey}
|
|
17313
|
+
runtimeReplacementContent={
|
|
17314
|
+
useRuntimeReplacement ? screenContent : undefined
|
|
17315
|
+
}
|
|
17316
|
+
runtimeReplacementKey={runtimeReplacementKey}
|
|
17274
17317
|
screenId={screen.id}
|
|
17275
17318
|
zoom={100}
|
|
17276
17319
|
deviceFrame="none"
|
|
@@ -16,6 +16,7 @@ export type ApprovalContextValue = {
|
|
|
16
16
|
onApprove: (approvalKey: string) => void;
|
|
17
17
|
};
|
|
18
18
|
export declare const ApprovalContext: React.Context<ApprovalContextValue | null>;
|
|
19
|
+
export declare const TOOL_LONG_RUNNING_HINT_DELAY_MS = 45000;
|
|
19
20
|
type ToolDetailSection = "input" | "result";
|
|
20
21
|
export type ToolDetailPayload = {
|
|
21
22
|
section: ToolDetailSection;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-call-display.d.ts","sourceRoot":"","sources":["../../../src/client/chat/tool-call-display.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAcpE,OAAO,KAMN,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAKzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAIL,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAmBhC,eAAO,MAAM,kBAAkB,wBAA6B,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,8DAA8D;IAC9D,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,CAAC;AACF,eAAO,MAAM,eAAe,4CAE3B,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-call-display.d.ts","sourceRoot":"","sources":["../../../src/client/chat/tool-call-display.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAcpE,OAAO,KAMN,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAKzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAIL,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAmBhC,eAAO,MAAM,kBAAkB,wBAA6B,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,8DAA8D;IAC9D,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,CAAC;AACF,eAAO,MAAM,eAAe,4CAE3B,CAAC;AAEF,eAAO,MAAM,+BAA+B,QAAS,CAAC;AAuCtD,KAAK,iBAAiB,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC5C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAiEF,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,iBAAiB,GAAG,IAAI,CAyB1B;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,iBAAiB,GAAG,IAAI,CAU1B;AA8ND,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,MAAM,EACN,MAAM,EACN,SAAS,EACT,cAAc,EACd,QAAQ,EACR,WAAW,GACZ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,qBAsDA;AAwND,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,GAAG,IAAI,EACR,EAAE,wBAAwB,GAAG;IAC5B,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,qBAwBA;AAMD,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,GACR,EAAE;IACD,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB,qBA8CA;AAKD,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IconLoader2, IconCircleX, IconCheck, IconSquareFilled, IconChevronDown, IconCopy, IconSearch, IconArrowsMaximize, IconArrowsMinimize, IconShieldCheck, IconX, } from "@tabler/icons-react";
|
|
3
3
|
import React, { useState, useEffect, useCallback, useMemo, useRef, } from "react";
|
|
4
4
|
import { AgentTaskCard } from "../AgentTaskCard.js";
|
|
@@ -14,6 +14,22 @@ import { isBuiltinDataWidgetActionRenderer, resolveBuiltinActionChatRenderer, re
|
|
|
14
14
|
// Exported so AssistantChatInner can provide a context value.
|
|
15
15
|
export const ChatRunningContext = React.createContext(false);
|
|
16
16
|
export const ApprovalContext = React.createContext(null);
|
|
17
|
+
export const TOOL_LONG_RUNNING_HINT_DELAY_MS = 45_000;
|
|
18
|
+
function ToolLongRunningHintShell({ toolName, isRunning, children, }) {
|
|
19
|
+
const [showLongRunningHint, setShowLongRunningHint] = useState(false);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!isRunning) {
|
|
22
|
+
setShowLongRunningHint(false);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
setShowLongRunningHint(false);
|
|
26
|
+
const timeout = window.setTimeout(() => {
|
|
27
|
+
setShowLongRunningHint(true);
|
|
28
|
+
}, TOOL_LONG_RUNNING_HINT_DELAY_MS);
|
|
29
|
+
return () => window.clearTimeout(timeout);
|
|
30
|
+
}, [isRunning, toolName]);
|
|
31
|
+
return (_jsxs(_Fragment, { children: [children, isRunning && showLongRunningHint && (_jsx("div", { className: "mt-0.5 px-2.5 text-[11px] leading-snug text-muted-foreground/80", children: "Still working. Large updates can take a minute or two." }))] }));
|
|
32
|
+
}
|
|
17
33
|
function stringifyToolValue(value, pretty = false) {
|
|
18
34
|
if (typeof value === "string")
|
|
19
35
|
return value;
|
|
@@ -192,16 +208,17 @@ export function ToolCallDisplay({ toolName, argsText, args, result, mcpApp, chat
|
|
|
192
208
|
// These must be separate components so hook order in ToolCallDisplayGeneric
|
|
193
209
|
// is always stable (no conditional hook calls).
|
|
194
210
|
const toolKind = structuredMeta?.toolKind;
|
|
211
|
+
const wrapToolDisplay = (children) => (_jsx(ToolLongRunningHintShell, { toolName: toolName, isRunning: isRunning, children: children }));
|
|
195
212
|
if (toolKind === "bash") {
|
|
196
|
-
return (_jsx(BashCell, { meta: structuredMeta, output: result, isRunning: isRunning }));
|
|
213
|
+
return wrapToolDisplay(_jsx(BashCell, { meta: structuredMeta, output: result, isRunning: isRunning }));
|
|
197
214
|
}
|
|
198
215
|
if (toolKind === "edit") {
|
|
199
|
-
return (_jsx(EditCell, { meta: structuredMeta, isRunning: isRunning }));
|
|
216
|
+
return wrapToolDisplay(_jsx(EditCell, { meta: structuredMeta, isRunning: isRunning }));
|
|
200
217
|
}
|
|
201
218
|
if (toolKind === "write") {
|
|
202
|
-
return (_jsx(WriteCell, { meta: structuredMeta, isRunning: isRunning }));
|
|
219
|
+
return wrapToolDisplay(_jsx(WriteCell, { meta: structuredMeta, isRunning: isRunning }));
|
|
203
220
|
}
|
|
204
|
-
return (_jsx(ToolCallDisplayGeneric, { toolName: toolName, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: isRunning, approval: approval, repeatCount: repeatCount }));
|
|
221
|
+
return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: isRunning, approval: approval, repeatCount: repeatCount }));
|
|
205
222
|
}
|
|
206
223
|
function ToolCallDisplayGeneric({ toolName, argsText, args, result, mcpApp, chatUI, isRunning, approval, repeatCount, }) {
|
|
207
224
|
const streamRef = useRef(null);
|