@agent-native/core 0.131.7 → 0.132.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 +123 -0
- package/corpus/core/docs/content/durable-background-runs.mdx +15 -6
- package/corpus/core/docs/design/durable-agent-runs.md +15 -11
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/activity.ts +127 -10
- package/corpus/core/src/a2a/index.ts +3 -0
- package/corpus/core/src/agent/durable-background.ts +38 -28
- package/corpus/core/src/agent/harness/background.ts +12 -2
- package/corpus/core/src/agent/production-agent.ts +18 -15
- package/corpus/core/src/agent/run-store.ts +45 -3
- package/corpus/core/src/application-state/handlers.ts +45 -0
- package/corpus/core/src/application-state/index.ts +3 -0
- package/corpus/core/src/application-state/store.ts +38 -34
- package/corpus/core/src/audit/redact.ts +104 -18
- package/corpus/core/src/cli/create.ts +115 -16
- package/corpus/core/src/client/AgentPanel.tsx +2 -7
- package/corpus/core/src/client/AssistantChat.tsx +10 -2
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +3 -0
- package/corpus/core/src/client/RunStuckBanner.tsx +29 -6
- package/corpus/core/src/client/agent-chat.ts +4 -9
- package/corpus/core/src/client/application-state.ts +115 -12
- package/corpus/core/src/client/dynamic-suggestions.ts +4 -12
- package/corpus/core/src/client/frame-protocol.ts +5 -1
- package/corpus/core/src/client/guided-questions.tsx +12 -23
- package/corpus/core/src/db/client.ts +148 -28
- package/corpus/core/src/db/create-get-db.ts +39 -6
- package/corpus/core/src/db/runtime-diagnostics.ts +41 -6
- package/corpus/core/src/deploy/build.ts +26 -33
- package/corpus/core/src/feature-flags/store.ts +10 -5
- package/corpus/core/src/integrations/a2a-continuations-store.ts +11 -0
- package/corpus/core/src/integrations/config-store.ts +13 -0
- package/corpus/core/src/integrations/google-docs-poller.ts +26 -2
- package/corpus/core/src/mcp-client/routes.ts +33 -2
- package/corpus/core/src/onboarding/plugin.ts +31 -25
- package/corpus/core/src/org/accept-pending.ts +2 -0
- package/corpus/core/src/org/auto-join-domain.ts +2 -0
- package/corpus/core/src/org/context.ts +35 -10
- package/corpus/core/src/org/handlers.ts +6 -0
- package/corpus/core/src/org/request-org-cache.ts +71 -0
- package/corpus/core/src/resources/store.ts +10 -9
- package/corpus/core/src/scripts/runner.ts +6 -3
- package/corpus/core/src/secrets/storage.ts +97 -5
- package/corpus/core/src/server/action-change.ts +33 -0
- package/corpus/core/src/server/action-routes.ts +11 -9
- package/corpus/core/src/server/agent-teams.ts +10 -2
- package/corpus/core/src/server/better-auth-instance.ts +39 -12
- package/corpus/core/src/server/core-routes-plugin.ts +19 -2
- package/corpus/core/src/server/credential-provider.ts +57 -14
- package/corpus/core/src/server/http-response-telemetry.ts +1 -0
- package/corpus/core/src/server/poll.ts +95 -57
- package/corpus/core/src/server/voice-providers-status.ts +19 -4
- package/corpus/core/src/workspace-files/tool.ts +18 -11
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +38 -0
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +1 -1
- package/corpus/templates/analytics/actions/ensure-native-v2-dashboards.ts +299 -0
- package/corpus/templates/analytics/actions/list-native-v2-dashboard-templates.ts +34 -0
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +82 -0
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +2 -2
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +40 -34
- package/corpus/templates/analytics/app/hooks/use-user-pref.ts +3 -3
- package/corpus/templates/analytics/app/i18n-data.ts +40 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +18 -10
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +14 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +1 -0
- package/corpus/templates/analytics/app/routes/chart.tsx +3 -0
- package/corpus/templates/analytics/changelog/2026-07-30-analytics-dashboards-now-expose-native-funnel-heatmap-callou.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-30-analytics-now-ships-reusable-native-v2-dashboard-manifests-w.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-report-render.ts +81 -1
- package/corpus/templates/analytics/server/lib/native-v2-dashboards.ts +457 -0
- package/corpus/templates/analytics/server/lib/report-chart-svg.ts +73 -2
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/analytics/shared/dashboard-funnel.ts +83 -0
- package/corpus/templates/clips/actions/generate-workflow.ts +6 -4
- package/corpus/templates/clips/actions/reconcile-workflow-generation.ts +257 -0
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +166 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -1
- package/corpus/templates/clips/changelog/2026-07-27-stopped-agent-runs-no-longer-leave-generated-workflow-cards-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-30-workflow-generation-now-stops-retrying-after-repeated-failur.md +6 -0
- package/corpus/templates/clips/shared/workflow.ts +5 -0
- package/corpus/templates/content/changelog/2026-07-30-long-running-delegated-requests-now-continue-reliably.md +6 -0
- package/corpus/templates/content/netlify.toml +3 -0
- package/corpus/templates/content/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +2 -1
- package/corpus/templates/slides/actions/patch-deck.ts +25 -1
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +17 -4
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +9 -1
- package/corpus/templates/slides/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +11 -3
- package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +39 -11
- package/corpus/templates/slides/app/pages/Index.tsx +2 -2
- package/corpus/templates/slides/changelog/2026-07-30-slide-previews-keep-their-aspect-ratio-isolate-embedded-styl.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-30-slides-no-longer-lose-decks-while-organization-access-is-loa.md +6 -0
- package/corpus/toolkit/CHANGELOG.md +8 -0
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/composer/runtime-adapters.tsx +16 -11
- package/dist/a2a/activity.d.ts +22 -4
- package/dist/a2a/activity.d.ts.map +1 -1
- package/dist/a2a/activity.js +97 -11
- package/dist/a2a/activity.js.map +1 -1
- package/dist/a2a/index.d.ts +1 -1
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +1 -1
- package/dist/a2a/index.js.map +1 -1
- package/dist/agent/durable-background.d.ts +13 -8
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +36 -28
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/harness/background.d.ts.map +1 -1
- package/dist/agent/harness/background.js +12 -2
- package/dist/agent/harness/background.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +18 -15
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-store.d.ts +2 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +44 -3
- package/dist/agent/run-store.js.map +1 -1
- package/dist/application-state/handlers.d.ts +15 -0
- package/dist/application-state/handlers.d.ts.map +1 -1
- package/dist/application-state/handlers.js +42 -2
- package/dist/application-state/handlers.js.map +1 -1
- package/dist/application-state/index.d.ts +2 -2
- package/dist/application-state/index.d.ts.map +1 -1
- package/dist/application-state/index.js +2 -2
- package/dist/application-state/index.js.map +1 -1
- package/dist/application-state/store.d.ts +11 -0
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +37 -40
- package/dist/application-state/store.js.map +1 -1
- package/dist/audit/redact.d.ts +25 -2
- package/dist/audit/redact.d.ts.map +1 -1
- package/dist/audit/redact.js +85 -21
- package/dist/audit/redact.js.map +1 -1
- package/dist/cli/create.d.ts +8 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +98 -16
- package/dist/cli/create.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +2 -7
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +10 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +1 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/RunStuckBanner.d.ts +11 -1
- package/dist/client/RunStuckBanner.d.ts.map +1 -1
- package/dist/client/RunStuckBanner.js +20 -7
- package/dist/client/RunStuckBanner.js.map +1 -1
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +4 -6
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/application-state.d.ts +11 -0
- package/dist/client/application-state.d.ts.map +1 -1
- package/dist/client/application-state.js +87 -9
- package/dist/client/application-state.js.map +1 -1
- package/dist/client/dynamic-suggestions.d.ts.map +1 -1
- package/dist/client/dynamic-suggestions.js +4 -13
- package/dist/client/dynamic-suggestions.js.map +1 -1
- package/dist/client/frame-protocol.d.ts +1 -0
- package/dist/client/frame-protocol.d.ts.map +1 -1
- package/dist/client/frame-protocol.js.map +1 -1
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +6 -22
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db/client.d.ts +57 -10
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +122 -31
- package/dist/db/client.js.map +1 -1
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +31 -7
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/db/runtime-diagnostics.d.ts +1 -0
- package/dist/db/runtime-diagnostics.d.ts.map +1 -1
- package/dist/db/runtime-diagnostics.js +31 -6
- package/dist/db/runtime-diagnostics.js.map +1 -1
- package/dist/deploy/build.d.ts +5 -20
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +18 -30
- package/dist/deploy/build.js.map +1 -1
- package/dist/feature-flags/store.d.ts.map +1 -1
- package/dist/feature-flags/store.js +10 -5
- package/dist/feature-flags/store.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +12 -0
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/config-store.d.ts +1 -0
- package/dist/integrations/config-store.d.ts.map +1 -1
- package/dist/integrations/config-store.js +11 -0
- package/dist/integrations/config-store.js.map +1 -1
- package/dist/integrations/google-docs-poller.d.ts.map +1 -1
- package/dist/integrations/google-docs-poller.js +19 -2
- package/dist/integrations/google-docs-poller.js.map +1 -1
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/mcp/screen-memory-stdio.d.ts.map +1 -1
- package/dist/mcp-client/routes.d.ts.map +1 -1
- package/dist/mcp-client/routes.js +30 -2
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/notifications/routes.d.ts +6 -6
- package/dist/onboarding/plugin.d.ts.map +1 -1
- package/dist/onboarding/plugin.js +12 -8
- package/dist/onboarding/plugin.js.map +1 -1
- package/dist/org/accept-pending.d.ts.map +1 -1
- package/dist/org/accept-pending.js +2 -0
- package/dist/org/accept-pending.js.map +1 -1
- package/dist/org/auto-join-domain.d.ts.map +1 -1
- package/dist/org/auto-join-domain.js +2 -0
- package/dist/org/auto-join-domain.js.map +1 -1
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +29 -9
- package/dist/org/context.js.map +1 -1
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/org/handlers.js +5 -0
- package/dist/org/handlers.js.map +1 -1
- package/dist/org/request-org-cache.d.ts +16 -0
- package/dist/org/request-org-cache.d.ts.map +1 -0
- package/dist/org/request-org-cache.js +62 -0
- package/dist/org/request-org-cache.js.map +1 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/resources/store.d.ts.map +1 -1
- package/dist/resources/store.js +11 -9
- package/dist/resources/store.js.map +1 -1
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +3 -3
- package/dist/scripts/runner.js.map +1 -1
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +82 -5
- package/dist/secrets/storage.js.map +1 -1
- package/dist/server/action-change.d.ts +20 -0
- package/dist/server/action-change.d.ts.map +1 -1
- package/dist/server/action-change.js +29 -0
- package/dist/server/action-change.js.map +1 -1
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +7 -8
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-teams.d.ts.map +1 -1
- package/dist/server/agent-teams.js +10 -2
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +31 -14
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +1 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +18 -4
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +16 -0
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +49 -13
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/http-response-telemetry.d.ts.map +1 -1
- package/dist/server/http-response-telemetry.js +1 -0
- package/dist/server/http-response-telemetry.js.map +1 -1
- package/dist/server/poll.d.ts +6 -0
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +84 -47
- package/dist/server/poll.js.map +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/voice-providers-status.d.ts.map +1 -1
- package/dist/server/voice-providers-status.js +12 -3
- package/dist/server/voice-providers-status.js.map +1 -1
- package/dist/workspace-files/tool.d.ts.map +1 -1
- package/dist/workspace-files/tool.js +18 -11
- package/dist/workspace-files/tool.js.map +1 -1
- package/docs/content/durable-background-runs.mdx +15 -6
- package/docs/design/durable-agent-runs.md +15 -11
- package/package.json +3 -3
- package/src/a2a/activity.ts +127 -10
- package/src/a2a/index.ts +3 -0
- package/src/agent/durable-background.ts +38 -28
- package/src/agent/harness/background.ts +12 -2
- package/src/agent/production-agent.ts +18 -15
- package/src/agent/run-store.ts +45 -3
- package/src/application-state/handlers.ts +45 -0
- package/src/application-state/index.ts +3 -0
- package/src/application-state/store.ts +38 -34
- package/src/audit/redact.ts +104 -18
- package/src/cli/create.ts +115 -16
- package/src/client/AgentPanel.tsx +2 -7
- package/src/client/AssistantChat.tsx +10 -2
- package/src/client/MultiTabAssistantChat.tsx +3 -0
- package/src/client/RunStuckBanner.tsx +29 -6
- package/src/client/agent-chat.ts +4 -9
- package/src/client/application-state.ts +115 -12
- package/src/client/dynamic-suggestions.ts +4 -12
- package/src/client/frame-protocol.ts +5 -1
- package/src/client/guided-questions.tsx +12 -23
- package/src/db/client.ts +148 -28
- package/src/db/create-get-db.ts +39 -6
- package/src/db/runtime-diagnostics.ts +41 -6
- package/src/deploy/build.ts +26 -33
- package/src/feature-flags/store.ts +10 -5
- package/src/integrations/a2a-continuations-store.ts +11 -0
- package/src/integrations/config-store.ts +13 -0
- package/src/integrations/google-docs-poller.ts +26 -2
- package/src/mcp-client/routes.ts +33 -2
- package/src/onboarding/plugin.ts +31 -25
- package/src/org/accept-pending.ts +2 -0
- package/src/org/auto-join-domain.ts +2 -0
- package/src/org/context.ts +35 -10
- package/src/org/handlers.ts +6 -0
- package/src/org/request-org-cache.ts +71 -0
- package/src/resources/store.ts +10 -9
- package/src/scripts/runner.ts +6 -3
- package/src/secrets/storage.ts +97 -5
- package/src/server/action-change.ts +33 -0
- package/src/server/action-routes.ts +11 -9
- package/src/server/agent-teams.ts +10 -2
- package/src/server/better-auth-instance.ts +39 -12
- package/src/server/core-routes-plugin.ts +19 -2
- package/src/server/credential-provider.ts +57 -14
- package/src/server/http-response-telemetry.ts +1 -0
- package/src/server/poll.ts +95 -57
- package/src/server/voice-providers-status.ts +19 -4
- package/src/workspace-files/tool.ts +18 -11
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
useRef,
|
|
7
7
|
useLayoutEffect,
|
|
8
8
|
useCallback,
|
|
9
|
+
useId,
|
|
9
10
|
type ReactNode,
|
|
10
11
|
} from "react";
|
|
11
12
|
import ReactMarkdown from "react-markdown";
|
|
@@ -477,6 +478,8 @@ function AutoFitContent({
|
|
|
477
478
|
|
|
478
479
|
/** Renders blank slide HTML content and applies white filter to logo images */
|
|
479
480
|
function BlankSlideContent({ content }: { content: string }) {
|
|
481
|
+
const scopeId = `slide-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
482
|
+
const scopeSelector = `[data-slide-content-scope="${scopeId}"]`;
|
|
480
483
|
// Memoize derived strings + the dangerouslySetInnerHTML object on `content` so
|
|
481
484
|
// the prop value has a stable reference across re-renders. React 19 only checks
|
|
482
485
|
// reference equality on `dangerouslySetInnerHTML` and unconditionally re-assigns
|
|
@@ -505,6 +508,7 @@ function BlankSlideContent({ content }: { content: string }) {
|
|
|
505
508
|
return before + ' style="filter:brightness(0) invert(1);"' + close;
|
|
506
509
|
},
|
|
507
510
|
),
|
|
511
|
+
{ scopeSelector },
|
|
508
512
|
);
|
|
509
513
|
|
|
510
514
|
return {
|
|
@@ -516,7 +520,10 @@ function BlankSlideContent({ content }: { content: string }) {
|
|
|
516
520
|
|
|
517
521
|
if (mermaidBlocks.length > 0) {
|
|
518
522
|
return (
|
|
519
|
-
<div
|
|
523
|
+
<div
|
|
524
|
+
className="slide-content text-white/90 w-full block h-full"
|
|
525
|
+
data-slide-content-scope={scopeId}
|
|
526
|
+
>
|
|
520
527
|
<MermaidHtmlContent
|
|
521
528
|
html={htmlWithPlaceholders}
|
|
522
529
|
mermaidBlocks={mermaidBlocks}
|
|
@@ -528,6 +535,7 @@ function BlankSlideContent({ content }: { content: string }) {
|
|
|
528
535
|
return (
|
|
529
536
|
<div
|
|
530
537
|
className="slide-content text-white/90 w-full block h-full"
|
|
538
|
+
data-slide-content-scope={scopeId}
|
|
531
539
|
dangerouslySetInnerHTML={dangerousHtml}
|
|
532
540
|
/>
|
|
533
541
|
);
|
|
@@ -143,7 +143,7 @@ export function Layout({ children }: LayoutProps) {
|
|
|
143
143
|
}
|
|
144
144
|
/>
|
|
145
145
|
</div>
|
|
146
|
-
<div className="agent-layout-main-surface flex h-full flex-1 flex-col overflow-hidden">
|
|
146
|
+
<div className="agent-layout-main-surface flex h-full min-w-0 flex-1 flex-col overflow-hidden">
|
|
147
147
|
{/* Mobile-only nav strip with hamburger — only when there's no page toolbar */}
|
|
148
148
|
{!ownToolbar && (
|
|
149
149
|
<div className="flex h-12 items-center border-b border-border px-4 md:hidden shrink-0">
|
|
@@ -1029,7 +1029,7 @@ export const defaultSlideContent: Record<SlideLayout, string> = {
|
|
|
1029
1029
|
};
|
|
1030
1030
|
|
|
1031
1031
|
export function DeckProvider({ children }: { children: ReactNode }) {
|
|
1032
|
-
const { data: org } = useOrg();
|
|
1032
|
+
const { data: org, isLoading: orgLoading } = useOrg();
|
|
1033
1033
|
const [decks, setDecks] = useState<Deck[]>([]);
|
|
1034
1034
|
const [loading, setLoading] = useState(true);
|
|
1035
1035
|
const [loadError, setLoadError] = useState(false);
|
|
@@ -1362,6 +1362,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1362
1362
|
const requestId = ++deckBaselineRequestIdRef.current;
|
|
1363
1363
|
const createSeqAtRequest = localCreateSeqRef.current;
|
|
1364
1364
|
const requestedOpenDeckId = currentOpenDeckIdFromWindow();
|
|
1365
|
+
setLoading(true);
|
|
1365
1366
|
const loaded = await fetchDecksForCurrentRoute();
|
|
1366
1367
|
if (
|
|
1367
1368
|
requestId !== deckBaselineRequestIdRef.current ||
|
|
@@ -1371,11 +1372,13 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1371
1372
|
}
|
|
1372
1373
|
if (loaded === null) {
|
|
1373
1374
|
setLoadError(true);
|
|
1375
|
+
setLoading(false);
|
|
1374
1376
|
return "failed";
|
|
1375
1377
|
}
|
|
1376
1378
|
lastExternalUpdateRef.current = Date.now();
|
|
1377
1379
|
resetDeckBaseline(loaded, createSeqAtRequest);
|
|
1378
1380
|
setLoadError(false);
|
|
1381
|
+
setLoading(false);
|
|
1379
1382
|
return "loaded";
|
|
1380
1383
|
}, [resetDeckBaseline]);
|
|
1381
1384
|
|
|
@@ -1385,6 +1388,10 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1385
1388
|
|
|
1386
1389
|
// Load decks from API on mount
|
|
1387
1390
|
useEffect(() => {
|
|
1391
|
+
// The deck query is scoped by the active organization on the server. Do
|
|
1392
|
+
// not turn the pre-scope empty response into the app's authoritative empty
|
|
1393
|
+
// state while the org query is still hydrating.
|
|
1394
|
+
if (orgLoading) return;
|
|
1388
1395
|
const requestId = ++deckBaselineRequestIdRef.current;
|
|
1389
1396
|
const createSeqAtRequest = localCreateSeqRef.current;
|
|
1390
1397
|
const requestedOpenDeckId = currentOpenDeckIdFromWindow();
|
|
@@ -1405,7 +1412,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1405
1412
|
setLoadError(loaded === null);
|
|
1406
1413
|
setLoading(false);
|
|
1407
1414
|
});
|
|
1408
|
-
}, [resetDeckBaseline]);
|
|
1415
|
+
}, [orgLoading, resetDeckBaseline]);
|
|
1409
1416
|
|
|
1410
1417
|
// Switching orgs re-scopes list-decks server-side but leaves this context's
|
|
1411
1418
|
// in-memory list untouched, so the previous org's decks linger. Reload when
|
|
@@ -1413,6 +1420,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1413
1420
|
// up on the mount fetch above.
|
|
1414
1421
|
const lastOrgIdRef = useRef<string | null | undefined>(undefined);
|
|
1415
1422
|
useEffect(() => {
|
|
1423
|
+
if (orgLoading) return;
|
|
1416
1424
|
const orgId = org?.orgId ?? null;
|
|
1417
1425
|
if (lastOrgIdRef.current === undefined) {
|
|
1418
1426
|
lastOrgIdRef.current = orgId;
|
|
@@ -1421,7 +1429,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
|
|
|
1421
1429
|
if (lastOrgIdRef.current === orgId) return;
|
|
1422
1430
|
lastOrgIdRef.current = orgId;
|
|
1423
1431
|
void reloadDecks();
|
|
1424
|
-
}, [org?.orgId, reloadDecks]);
|
|
1432
|
+
}, [org?.orgId, orgLoading, reloadDecks]);
|
|
1425
1433
|
|
|
1426
1434
|
// Fallback polling for deck list + open-deck changes. SSE is the primary
|
|
1427
1435
|
// path; this catches agent/db writes that bypass it without hammering idle
|
|
@@ -197,16 +197,40 @@ function sanitizeStyle(style: string): string {
|
|
|
197
197
|
.join("; ");
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
function
|
|
200
|
+
function scopeCssSelector(selector: string, scopeSelector?: string): string {
|
|
201
|
+
const trimmed = selector.trim();
|
|
202
|
+
if (!scopeSelector || !trimmed || trimmed.startsWith("@")) return trimmed;
|
|
203
|
+
|
|
204
|
+
return trimmed
|
|
205
|
+
.split(",")
|
|
206
|
+
.map((part) => {
|
|
207
|
+
const item = part.trim();
|
|
208
|
+
if (!item) return "";
|
|
209
|
+
if (item === "*") return `${scopeSelector}, ${scopeSelector} *`;
|
|
210
|
+
if (/^(?:html|body|:root)\b/i.test(item)) {
|
|
211
|
+
return item.replace(/^(?:html|body|:root)\b/i, scopeSelector);
|
|
212
|
+
}
|
|
213
|
+
return `${scopeSelector} ${item}`;
|
|
214
|
+
})
|
|
215
|
+
.filter(Boolean)
|
|
216
|
+
.join(", ");
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function sanitizeStyleSheet(css: string, scopeSelector?: string): string {
|
|
201
220
|
return css
|
|
202
221
|
.replace(/@import[^;]+;?/gi, "")
|
|
203
222
|
.replace(/([^{}]+)\{([^{}]*)\}/g, (_match, selector, body) => {
|
|
204
223
|
const safeBody = sanitizeStyle(String(body));
|
|
205
|
-
|
|
224
|
+
const safeSelector = scopeCssSelector(String(selector), scopeSelector);
|
|
225
|
+
return safeBody && safeSelector ? `${safeSelector} { ${safeBody}; }` : "";
|
|
206
226
|
});
|
|
207
227
|
}
|
|
208
228
|
|
|
209
|
-
function cleanNode(
|
|
229
|
+
function cleanNode(
|
|
230
|
+
node: Node,
|
|
231
|
+
doc: Document,
|
|
232
|
+
scopeSelector?: string,
|
|
233
|
+
): Node | null {
|
|
210
234
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
211
235
|
return doc.createTextNode(node.textContent ?? "");
|
|
212
236
|
}
|
|
@@ -218,7 +242,7 @@ function cleanNode(node: Node, doc: Document): Node | null {
|
|
|
218
242
|
if (DROP_WITH_CHILDREN.has(tag)) return null;
|
|
219
243
|
|
|
220
244
|
if (tag === "style") {
|
|
221
|
-
const safeCss = sanitizeStyleSheet(el.textContent ?? "");
|
|
245
|
+
const safeCss = sanitizeStyleSheet(el.textContent ?? "", scopeSelector);
|
|
222
246
|
if (!safeCss.trim()) return null;
|
|
223
247
|
const out = doc.createElement("style");
|
|
224
248
|
out.textContent = safeCss;
|
|
@@ -268,17 +292,17 @@ function cleanNode(node: Node, doc: Document): Node | null {
|
|
|
268
292
|
}
|
|
269
293
|
|
|
270
294
|
for (const child of Array.from(el.childNodes)) {
|
|
271
|
-
const cleaned = cleanNode(child, doc);
|
|
295
|
+
const cleaned = cleanNode(child, doc, scopeSelector);
|
|
272
296
|
if (cleaned) out.appendChild(cleaned);
|
|
273
297
|
}
|
|
274
298
|
|
|
275
299
|
return out;
|
|
276
300
|
}
|
|
277
301
|
|
|
278
|
-
function sanitizeHtmlString(html: string): string {
|
|
302
|
+
function sanitizeHtmlString(html: string, scopeSelector?: string): string {
|
|
279
303
|
return html
|
|
280
304
|
.replace(/<style\b[^>]*>([\s\S]*?)<\/style>/gi, (_match, css) => {
|
|
281
|
-
const safeCss = sanitizeStyleSheet(String(css));
|
|
305
|
+
const safeCss = sanitizeStyleSheet(String(css), scopeSelector);
|
|
282
306
|
return safeCss
|
|
283
307
|
? `<style>${safeCss.replace(/<\/style/gi, "<\\/style")}</style>`
|
|
284
308
|
: "";
|
|
@@ -314,19 +338,23 @@ function sanitizeHtmlString(html: string): string {
|
|
|
314
338
|
);
|
|
315
339
|
}
|
|
316
340
|
|
|
317
|
-
export function sanitizeSlideHtml(
|
|
341
|
+
export function sanitizeSlideHtml(
|
|
342
|
+
html: string,
|
|
343
|
+
options?: { scopeSelector?: string },
|
|
344
|
+
): string {
|
|
345
|
+
const scopeSelector = options?.scopeSelector;
|
|
318
346
|
if (typeof DOMParser === "undefined") {
|
|
319
|
-
return sanitizeHtmlString(html);
|
|
347
|
+
return sanitizeHtmlString(html, scopeSelector);
|
|
320
348
|
}
|
|
321
349
|
|
|
322
350
|
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
323
351
|
const fragment = doc.createDocumentFragment();
|
|
324
352
|
for (const style of Array.from(doc.head.querySelectorAll("style"))) {
|
|
325
|
-
const cleaned = cleanNode(style, doc);
|
|
353
|
+
const cleaned = cleanNode(style, doc, scopeSelector);
|
|
326
354
|
if (cleaned) fragment.appendChild(cleaned);
|
|
327
355
|
}
|
|
328
356
|
for (const child of Array.from(doc.body.childNodes)) {
|
|
329
|
-
const cleaned = cleanNode(child, doc);
|
|
357
|
+
const cleaned = cleanNode(child, doc, scopeSelector);
|
|
330
358
|
if (cleaned) fragment.appendChild(cleaned);
|
|
331
359
|
}
|
|
332
360
|
|
|
@@ -597,7 +597,7 @@ export default function Index() {
|
|
|
597
597
|
"Start a `manage-progress` run so progress appears in the app header. Add the first slide as soon as it is ready, then continue one slide at a time so the editor visibly fills in.",
|
|
598
598
|
"After reading any requested or imported source material, but before adding the first slide, choose a concise, specific deck title from the user's request and source material. Call `patch-deck` with `deckId: \"" +
|
|
599
599
|
deckId +
|
|
600
|
-
'"` and `operations: [{ "op": "patch-deck-fields", "fields": { "title": "<generated title>" } }]`. Never leave a generated deck named "Untitled Deck" or another placeholder.',
|
|
600
|
+
'"` and `operations: [{ "op": "patch-deck-fields", "fields": { "title": "<generated title>" } }]`. Include only `title` in `fields`; omit all other optional fields. Never leave a generated deck named "Untitled Deck" or another placeholder.',
|
|
601
601
|
"If the user asks for a standalone visual, diagram, hero, one-pager, poster, or a couple of visuals, create only the requested one/few polished visual slides. Do not pad the result into a full presentation.",
|
|
602
602
|
"Add slides ONE AT A TIME using the `add-slide` action with --deckId=" +
|
|
603
603
|
deckId +
|
|
@@ -746,7 +746,7 @@ export default function Index() {
|
|
|
746
746
|
);
|
|
747
747
|
|
|
748
748
|
return (
|
|
749
|
-
<main className="flex-1 overflow-y-auto px-4 sm:px-6
|
|
749
|
+
<main className="min-w-0 flex-1 overflow-y-auto px-4 py-6 sm:px-6 sm:py-10">
|
|
750
750
|
{loading ? (
|
|
751
751
|
<>
|
|
752
752
|
<div className="flex items-center justify-end mb-4">
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @agent-native/toolkit
|
|
2
2
|
|
|
3
|
+
## 0.12.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 89e5910: Memoize the composer runtime adapters context value so consumer effects stop
|
|
8
|
+
re-running on every provider render. The voice input preference was re-read from
|
|
9
|
+
app state, and the sidebar-state listener re-subscribed, once per render.
|
|
10
|
+
|
|
3
11
|
## 0.12.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createContext,
|
|
3
3
|
useContext,
|
|
4
|
+
useMemo,
|
|
4
5
|
type ComponentType,
|
|
5
6
|
type ReactNode,
|
|
6
7
|
} from "react";
|
|
@@ -251,18 +252,22 @@ export function ComposerRuntimeAdaptersProvider({
|
|
|
251
252
|
adapters: ComposerRuntimeAdapters;
|
|
252
253
|
children: ReactNode;
|
|
253
254
|
}) {
|
|
255
|
+
// Consumers key effects off this value; a fresh identity per render re-runs
|
|
256
|
+
// every one of them (app-state reads, event subscriptions) on each render.
|
|
257
|
+
const value = useMemo(
|
|
258
|
+
() => ({
|
|
259
|
+
...fallbackAdapters,
|
|
260
|
+
...adapters,
|
|
261
|
+
models: { ...fallbackModels, ...adapters.models },
|
|
262
|
+
agentChat: { ...fallbackAdapters.agentChat, ...adapters.agentChat },
|
|
263
|
+
builder: { ...fallbackAdapters.builder, ...adapters.builder },
|
|
264
|
+
resources: { ...fallbackAdapters.resources, ...adapters.resources },
|
|
265
|
+
voice: { ...fallbackAdapters.voice, ...adapters.voice },
|
|
266
|
+
}),
|
|
267
|
+
[adapters],
|
|
268
|
+
);
|
|
254
269
|
return (
|
|
255
|
-
<ComposerRuntimeAdaptersContext.Provider
|
|
256
|
-
value={{
|
|
257
|
-
...fallbackAdapters,
|
|
258
|
-
...adapters,
|
|
259
|
-
models: { ...fallbackModels, ...adapters.models },
|
|
260
|
-
agentChat: { ...fallbackAdapters.agentChat, ...adapters.agentChat },
|
|
261
|
-
builder: { ...fallbackAdapters.builder, ...adapters.builder },
|
|
262
|
-
resources: { ...fallbackAdapters.resources, ...adapters.resources },
|
|
263
|
-
voice: { ...fallbackAdapters.voice, ...adapters.voice },
|
|
264
|
-
}}
|
|
265
|
-
>
|
|
270
|
+
<ComposerRuntimeAdaptersContext.Provider value={value}>
|
|
266
271
|
{children}
|
|
267
272
|
</ComposerRuntimeAdaptersContext.Provider>
|
|
268
273
|
);
|
package/dist/a2a/activity.d.ts
CHANGED
|
@@ -4,17 +4,33 @@ export declare const A2A_AGENT_ACTIVITY_KIND = "agent-native/agent-activity";
|
|
|
4
4
|
export declare const A2A_AGENT_ACTIVITY_VERSION = 1;
|
|
5
5
|
export declare const MAX_A2A_ACTIVITY_REASONING_CHARS = 32768;
|
|
6
6
|
export declare const MAX_A2A_ACTIVITY_RESPONSE_CHARS = 32768;
|
|
7
|
-
export declare const MAX_A2A_ACTIVITY_TOTAL_CHARS = 98304;
|
|
8
7
|
export declare const MAX_A2A_ACTIVITY_REASONING_SEGMENTS = 128;
|
|
9
8
|
export declare const MAX_A2A_ACTIVITY_TOOL_CALLS = 64;
|
|
10
9
|
export declare const MAX_A2A_ACTIVITY_TOOL_NAME_CHARS = 96;
|
|
11
10
|
export declare const MAX_A2A_ACTIVITY_TOOL_ID_CHARS = 128;
|
|
11
|
+
export declare const MAX_A2A_ACTIVITY_TOOL_INPUT_CHARS = 1024;
|
|
12
|
+
export declare const MAX_A2A_ACTIVITY_TOOL_RESULT_CHARS = 512;
|
|
13
|
+
/**
|
|
14
|
+
* Shared ceiling for every recorded tool input/result across the snapshot. The
|
|
15
|
+
* per-call caps alone allow 64 × 1536 chars, which would push a busy run past
|
|
16
|
+
* `MAX_A2A_ACTIVITY_TOTAL_CHARS` and make `parseA2AAgentActivityPart` reject
|
|
17
|
+
* the whole snapshot — trading missing arguments for a missing trace.
|
|
18
|
+
*/
|
|
19
|
+
export declare const MAX_A2A_ACTIVITY_TOOL_PAYLOAD_CHARS = 16384;
|
|
20
|
+
export declare const MAX_A2A_ACTIVITY_TOTAL_CHARS: number;
|
|
12
21
|
export type A2AAgentActivityPhase = "reasoning" | "tool" | "responding" | "complete" | "error";
|
|
13
22
|
export type A2AAgentActivityToolStatus = "running" | "completed" | "failed";
|
|
14
23
|
export interface A2AAgentActivityToolCall {
|
|
15
24
|
name: string;
|
|
16
25
|
id?: string;
|
|
17
26
|
status: A2AAgentActivityToolStatus;
|
|
27
|
+
/**
|
|
28
|
+
* Redacted, size-capped JSON of the call's arguments. Absent when the call
|
|
29
|
+
* had none, or when the snapshot's shared payload budget was already spent.
|
|
30
|
+
*/
|
|
31
|
+
input?: string;
|
|
32
|
+
/** Redacted, size-capped head of the tool result (`tool_done` only). */
|
|
33
|
+
result?: string;
|
|
18
34
|
}
|
|
19
35
|
export interface A2AAgentActivitySnapshot extends Record<string, unknown> {
|
|
20
36
|
kind: typeof A2A_AGENT_ACTIVITY_KIND;
|
|
@@ -42,9 +58,11 @@ export interface A2AAgentActivityState {
|
|
|
42
58
|
}
|
|
43
59
|
export declare function createA2AAgentActivityState(startedAt?: number): A2AAgentActivityState;
|
|
44
60
|
/**
|
|
45
|
-
* Converts internal loop events into a bounded activity snapshot.
|
|
46
|
-
*
|
|
47
|
-
* results
|
|
61
|
+
* Converts internal loop events into a bounded activity snapshot. Reasoning
|
|
62
|
+
* text is carried verbatim (it was already emitted to the local chat); tool
|
|
63
|
+
* arguments and results are carried only in redacted, size-capped form so the
|
|
64
|
+
* delegated run stays diagnosable without the snapshot becoming a secondary
|
|
65
|
+
* store of secrets or payloads.
|
|
48
66
|
*/
|
|
49
67
|
export declare function applyA2AAgentActivityEvent(state: A2AAgentActivityState, event: AgentChatEvent, updatedAt?: number): A2AAgentActivityState;
|
|
50
68
|
export declare function buildA2AAgentActivitySnapshot(state: A2AAgentActivityState): A2AAgentActivitySnapshot;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../src/a2a/activity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../src/a2a/activity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEjD,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AACrE,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C,eAAO,MAAM,gCAAgC,QAAS,CAAC;AACvD,eAAO,MAAM,+BAA+B,QAAS,CAAC;AACtD,eAAO,MAAM,mCAAmC,MAAM,CAAC;AACvD,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAC9C,eAAO,MAAM,gCAAgC,KAAK,CAAC;AACnD,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,iCAAiC,OAAO,CAAC;AACtD,eAAO,MAAM,kCAAkC,MAAM,CAAC;AACtD;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,QAAS,CAAC;AAC1D,eAAO,MAAM,4BAA4B,QACK,CAAC;AAE/C,MAAM,MAAM,qBAAqB,GAC7B,WAAW,GACX,MAAM,GACN,YAAY,GACZ,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,MAAM,0BAA0B,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE5E,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,0BAA0B,CAAC;IACnC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAyB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACvE,IAAI,EAAE,OAAO,uBAAuB,CAAC;IACrC,OAAO,EAAE,OAAO,0BAA0B,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,qBAAqB,CAAC;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,wBAAwB,EAAE,CAAC;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,qBAAqB,CAAC;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,wBAAwB,EAAE,CAAC;IACtC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,2BAA2B,CACzC,SAAS,SAAa,GACrB,qBAAqB,CAUvB;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,qBAAqB,EAC5B,KAAK,EAAE,cAAc,EACrB,SAAS,SAAa,GACrB,qBAAqB,CA8DvB;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,qBAAqB,GAC3B,wBAAwB,CAc1B;AAMD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,qBAAqB,GAC3B,QAAQ,CAEV;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,IAAI,GAAG,OAAO,GACnB,wBAAwB,GAAG,IAAI,CA2BjC"}
|
package/dist/a2a/activity.js
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import { sanitizeToolErrorText } from "../agent/tool-error-redaction.js";
|
|
2
|
+
import { redactArgsToJson, redactTextToSummary } from "../audit/redact.js";
|
|
2
3
|
export const A2A_AGENT_ACTIVITY_KIND = "agent-native/agent-activity";
|
|
3
4
|
export const A2A_AGENT_ACTIVITY_VERSION = 1;
|
|
4
5
|
export const MAX_A2A_ACTIVITY_REASONING_CHARS = 32_768;
|
|
5
6
|
export const MAX_A2A_ACTIVITY_RESPONSE_CHARS = 32_768;
|
|
6
|
-
export const MAX_A2A_ACTIVITY_TOTAL_CHARS = 98_304;
|
|
7
7
|
export const MAX_A2A_ACTIVITY_REASONING_SEGMENTS = 128;
|
|
8
8
|
export const MAX_A2A_ACTIVITY_TOOL_CALLS = 64;
|
|
9
9
|
export const MAX_A2A_ACTIVITY_TOOL_NAME_CHARS = 96;
|
|
10
10
|
export const MAX_A2A_ACTIVITY_TOOL_ID_CHARS = 128;
|
|
11
|
+
export const MAX_A2A_ACTIVITY_TOOL_INPUT_CHARS = 1024;
|
|
12
|
+
export const MAX_A2A_ACTIVITY_TOOL_RESULT_CHARS = 512;
|
|
13
|
+
/**
|
|
14
|
+
* Shared ceiling for every recorded tool input/result across the snapshot. The
|
|
15
|
+
* per-call caps alone allow 64 × 1536 chars, which would push a busy run past
|
|
16
|
+
* `MAX_A2A_ACTIVITY_TOTAL_CHARS` and make `parseA2AAgentActivityPart` reject
|
|
17
|
+
* the whole snapshot — trading missing arguments for a missing trace.
|
|
18
|
+
*/
|
|
19
|
+
export const MAX_A2A_ACTIVITY_TOOL_PAYLOAD_CHARS = 16_384;
|
|
20
|
+
export const MAX_A2A_ACTIVITY_TOTAL_CHARS = 98_304 + MAX_A2A_ACTIVITY_TOOL_PAYLOAD_CHARS;
|
|
11
21
|
export function createA2AAgentActivityState(startedAt = Date.now()) {
|
|
12
22
|
return {
|
|
13
23
|
sequence: 0,
|
|
@@ -20,9 +30,11 @@ export function createA2AAgentActivityState(startedAt = Date.now()) {
|
|
|
20
30
|
};
|
|
21
31
|
}
|
|
22
32
|
/**
|
|
23
|
-
* Converts internal loop events into a bounded activity snapshot.
|
|
24
|
-
*
|
|
25
|
-
* results
|
|
33
|
+
* Converts internal loop events into a bounded activity snapshot. Reasoning
|
|
34
|
+
* text is carried verbatim (it was already emitted to the local chat); tool
|
|
35
|
+
* arguments and results are carried only in redacted, size-capped form so the
|
|
36
|
+
* delegated run stays diagnosable without the snapshot becoming a secondary
|
|
37
|
+
* store of secrets or payloads.
|
|
26
38
|
*/
|
|
27
39
|
export function applyA2AAgentActivityEvent(state, event, updatedAt = Date.now()) {
|
|
28
40
|
const next = { ...state, updatedAt: normalizeTimestamp(updatedAt) };
|
|
@@ -33,14 +45,19 @@ export function applyA2AAgentActivityEvent(state, event, updatedAt = Date.now())
|
|
|
33
45
|
next.reasoning = appendBoundedSegment(next.reasoning, event.text, MAX_A2A_ACTIVITY_REASONING_CHARS, next.toolCalls.length);
|
|
34
46
|
changed = true;
|
|
35
47
|
break;
|
|
36
|
-
case "tool_start":
|
|
48
|
+
case "tool_start": {
|
|
37
49
|
next.activePhase = "tool";
|
|
38
|
-
|
|
50
|
+
const input = captureToolInput(event.input, remainingPayloadBudget(next.toolCalls));
|
|
51
|
+
next.toolCalls = appendToolCall(next.toolCalls, {
|
|
52
|
+
...toolFromEvent(event),
|
|
53
|
+
...(input ? { input } : {}),
|
|
54
|
+
});
|
|
39
55
|
changed = true;
|
|
40
56
|
break;
|
|
57
|
+
}
|
|
41
58
|
case "tool_done":
|
|
42
59
|
next.activePhase = "tool";
|
|
43
|
-
next.toolCalls = settleToolCall(next.toolCalls, toolFromEvent(event));
|
|
60
|
+
next.toolCalls = settleToolCall(next.toolCalls, toolFromEvent(event), event);
|
|
44
61
|
changed = true;
|
|
45
62
|
break;
|
|
46
63
|
case "text":
|
|
@@ -123,6 +140,38 @@ function toolFromEvent(event) {
|
|
|
123
140
|
: "completed",
|
|
124
141
|
};
|
|
125
142
|
}
|
|
143
|
+
function payloadChars(tool) {
|
|
144
|
+
return (tool.input?.length ?? 0) + (tool.result?.length ?? 0);
|
|
145
|
+
}
|
|
146
|
+
function remainingPayloadBudget(current, excludeIndex = -1) {
|
|
147
|
+
const used = current.reduce((total, tool, index) => index === excludeIndex ? total : total + payloadChars(tool), 0);
|
|
148
|
+
return Math.max(0, MAX_A2A_ACTIVITY_TOOL_PAYLOAD_CHARS - used);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Redacted, capped JSON of the arguments, or `undefined` when there is nothing
|
|
152
|
+
* to record or the shared budget cannot fit a whole (still-parseable) capture.
|
|
153
|
+
* A partial JSON string would be worse than none — the reader could not tell a
|
|
154
|
+
* clipped object from a different one.
|
|
155
|
+
*/
|
|
156
|
+
function captureToolInput(input, budget) {
|
|
157
|
+
const cap = Math.min(MAX_A2A_ACTIVITY_TOOL_INPUT_CHARS, budget);
|
|
158
|
+
if (cap < MAX_A2A_ACTIVITY_TOOL_INPUT_CHARS / 8)
|
|
159
|
+
return undefined;
|
|
160
|
+
const json = redactArgsToJson(input, { maxJson: cap, maxString: 256 });
|
|
161
|
+
// JSON.stringify escapes control characters, so the result is already safe
|
|
162
|
+
// for the snapshot without a `sanitizeText` pass — which would rewrite
|
|
163
|
+
// `"token":"[redacted]"` into unparseable JSON.
|
|
164
|
+
if (!json || json === "{}" || json.length > cap)
|
|
165
|
+
return undefined;
|
|
166
|
+
return json;
|
|
167
|
+
}
|
|
168
|
+
function captureToolResult(result, budget) {
|
|
169
|
+
const cap = Math.min(MAX_A2A_ACTIVITY_TOOL_RESULT_CHARS, budget);
|
|
170
|
+
if (!result || cap <= 0)
|
|
171
|
+
return undefined;
|
|
172
|
+
const summary = redactTextToSummary(result, cap);
|
|
173
|
+
return summary ? sanitizeText(summary, cap) || undefined : undefined;
|
|
174
|
+
}
|
|
126
175
|
function appendBoundedSegment(current, addition, maxChars, precedingToolCount) {
|
|
127
176
|
const used = current.reduce((total, text) => total + text.length, 0);
|
|
128
177
|
if (used >= maxChars ||
|
|
@@ -148,15 +197,34 @@ function appendToolCall(current, tool) {
|
|
|
148
197
|
? [...current, tool]
|
|
149
198
|
: current;
|
|
150
199
|
}
|
|
151
|
-
function settleToolCall(current, tool) {
|
|
200
|
+
function settleToolCall(current, tool, event) {
|
|
152
201
|
for (let index = current.length - 1; index >= 0; index -= 1) {
|
|
153
202
|
const existing = current[index];
|
|
154
203
|
if ((tool.id && tool.id === existing.id) ||
|
|
155
204
|
(!tool.id && tool.name === existing.name)) {
|
|
156
|
-
|
|
205
|
+
// The matching `tool_start` already paid for its input; reuse it rather
|
|
206
|
+
// than re-capturing (and re-charging) the same arguments.
|
|
207
|
+
let budget = remainingPayloadBudget(current, index);
|
|
208
|
+
const input = existing.input ?? captureToolInput(event.input, budget) ?? undefined;
|
|
209
|
+
budget -= input?.length ?? 0;
|
|
210
|
+
const result = captureToolResult(event.result, budget);
|
|
211
|
+
const settled = {
|
|
212
|
+
...tool,
|
|
213
|
+
...(input ? { input } : {}),
|
|
214
|
+
...(result ? { result } : {}),
|
|
215
|
+
};
|
|
216
|
+
return current.map((value, itemIndex) => itemIndex === index ? settled : value);
|
|
157
217
|
}
|
|
158
218
|
}
|
|
159
|
-
|
|
219
|
+
let budget = remainingPayloadBudget(current);
|
|
220
|
+
const input = captureToolInput(event.input, budget);
|
|
221
|
+
budget -= input?.length ?? 0;
|
|
222
|
+
const result = captureToolResult(event.result, budget);
|
|
223
|
+
return appendToolCall(current, {
|
|
224
|
+
...tool,
|
|
225
|
+
...(input ? { input } : {}),
|
|
226
|
+
...(result ? { result } : {}),
|
|
227
|
+
});
|
|
160
228
|
}
|
|
161
229
|
function sanitizeText(value, maxChars) {
|
|
162
230
|
return sanitizeToolErrorText(value)
|
|
@@ -200,10 +268,26 @@ function isSafeToolCall(value) {
|
|
|
200
268
|
if (!isRecord(value) || !isSafeToolName(value.name))
|
|
201
269
|
return false;
|
|
202
270
|
return ((value.id === undefined || isSafeToolId(value.id)) &&
|
|
271
|
+
(value.input === undefined ||
|
|
272
|
+
isSafeCapturedText(value.input, MAX_A2A_ACTIVITY_TOOL_INPUT_CHARS)) &&
|
|
273
|
+
(value.result === undefined ||
|
|
274
|
+
isSafeCapturedText(value.result, MAX_A2A_ACTIVITY_TOOL_RESULT_CHARS)) &&
|
|
203
275
|
(value.status === "running" ||
|
|
204
276
|
value.status === "completed" ||
|
|
205
277
|
value.status === "failed"));
|
|
206
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* Captured input/result are producer-side redacted strings. Unlike reasoning
|
|
281
|
+
* text they are NOT re-sanitized on read: `sanitizeToolErrorText` rewrites
|
|
282
|
+
* `"token":"…"` into unparseable JSON, so a round-trip equality check would
|
|
283
|
+
* reject every legitimate capture. Bound the length and reject raw control
|
|
284
|
+
* characters instead.
|
|
285
|
+
*/
|
|
286
|
+
function isSafeCapturedText(value, maxChars) {
|
|
287
|
+
return (typeof value === "string" &&
|
|
288
|
+
value.length <= maxChars &&
|
|
289
|
+
!/[\u0000-\u0008\u000b-\u001f\u007f]/.test(value));
|
|
290
|
+
}
|
|
207
291
|
function isSafeText(value, maxChars) {
|
|
208
292
|
return (typeof value === "string" &&
|
|
209
293
|
value.length <= maxChars &&
|
|
@@ -234,7 +318,9 @@ function activityCharacterCount(data) {
|
|
|
234
318
|
return total;
|
|
235
319
|
return (total +
|
|
236
320
|
(typeof tool.name === "string" ? tool.name.length : 0) +
|
|
237
|
-
(typeof tool.id === "string" ? tool.id.length : 0)
|
|
321
|
+
(typeof tool.id === "string" ? tool.id.length : 0) +
|
|
322
|
+
(typeof tool.input === "string" ? tool.input.length : 0) +
|
|
323
|
+
(typeof tool.result === "string" ? tool.result.length : 0));
|
|
238
324
|
}, 0)
|
|
239
325
|
: 0;
|
|
240
326
|
return reasoning + response + tools;
|