@agent-native/core 0.118.1 → 0.119.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 +1 -1
- package/corpus/core/CHANGELOG.md +11 -0
- package/corpus/core/docs/content/a2a-protocol.mdx +15 -0
- package/corpus/core/docs/content/template-chat.mdx +1 -1
- package/corpus/core/docs/content/template-plan.mdx +3 -3
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/activity.ts +371 -0
- package/corpus/core/src/a2a/client.ts +3 -1
- package/corpus/core/src/a2a/index.ts +21 -0
- package/corpus/core/src/a2a/types.ts +8 -0
- package/corpus/core/src/agent/model-config.ts +19 -23
- package/corpus/core/src/agent/production-agent.ts +167 -100
- package/corpus/core/src/agent/types.ts +16 -1
- package/corpus/core/src/client/chat/tool-call-display.tsx +190 -35
- package/corpus/core/src/client/chat-model-groups.ts +67 -27
- package/corpus/core/src/client/sharing/ShareButton.tsx +1 -27
- package/corpus/core/src/client/sharing/ShareDialog.tsx +0 -16
- package/corpus/core/src/client/sharing/useShareButtonController.ts +0 -7
- package/corpus/core/src/client/sharing/useShareDialogController.ts +0 -2
- package/corpus/core/src/client/sse-event-processor.ts +85 -1
- package/corpus/core/src/localization/default-messages.ts +6 -0
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +1 -18
- package/corpus/core/src/scripts/call-agent.ts +49 -6
- package/corpus/core/src/server/agent-chat-plugin.ts +50 -10
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -0
- package/corpus/templates/clips/changelog/2026-07-23-fixed-recordings-failing-to-save-with-a-cancelled-or-cleanup.md +6 -0
- package/corpus/templates/clips/server/plugins/db.ts +9 -1
- package/dist/a2a/activity.d.ts +50 -0
- package/dist/a2a/activity.d.ts.map +1 -0
- package/dist/a2a/activity.js +236 -0
- package/dist/a2a/activity.js.map +1 -0
- package/dist/a2a/client.d.ts +2 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +1 -1
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/index.d.ts +2 -1
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +1 -0
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/types.d.ts +1 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts +2 -2
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/model-config.d.ts +16 -16
- package/dist/agent/model-config.d.ts.map +1 -1
- package/dist/agent/model-config.js +19 -23
- package/dist/agent/model-config.js.map +1 -1
- package/dist/agent/production-agent.d.ts +26 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +137 -80
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/types.d.ts +10 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +63 -14
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat-model-groups.d.ts.map +1 -1
- package/dist/client/chat-model-groups.js +44 -21
- package/dist/client/chat-model-groups.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +1 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -4
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/client/sharing/ShareDialog.js +1 -2
- package/dist/client/sharing/ShareDialog.js.map +1 -1
- package/dist/client/sharing/useShareButtonController.d.ts +0 -1
- package/dist/client/sharing/useShareButtonController.d.ts.map +1 -1
- package/dist/client/sharing/useShareButtonController.js +0 -6
- package/dist/client/sharing/useShareButtonController.js.map +1 -1
- package/dist/client/sharing/useShareDialogController.d.ts +0 -1
- package/dist/client/sharing/useShareDialogController.d.ts.map +1 -1
- package/dist/client/sharing/useShareDialogController.js +0 -1
- package/dist/client/sharing/useShareDialogController.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +12 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +63 -1
- package/dist/client/sse-event-processor.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/collab/struct-routes.d.ts +1 -1
- package/dist/localization/default-messages.d.ts +6 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +6 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +1 -18
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +49 -6
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +38 -10
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -0
- package/docs/content/a2a-protocol.mdx +15 -0
- package/docs/content/template-chat.mdx +1 -1
- package/docs/content/template-plan.mdx +3 -3
- package/package.json +1 -1
- package/src/a2a/activity.ts +371 -0
- package/src/a2a/client.ts +3 -1
- package/src/a2a/index.ts +21 -0
- package/src/a2a/types.ts +8 -0
- package/src/agent/model-config.ts +19 -23
- package/src/agent/production-agent.ts +167 -100
- package/src/agent/types.ts +16 -1
- package/src/client/chat/tool-call-display.tsx +190 -35
- package/src/client/chat-model-groups.ts +67 -27
- package/src/client/sharing/ShareButton.tsx +1 -27
- package/src/client/sharing/ShareDialog.tsx +0 -16
- package/src/client/sharing/useShareButtonController.ts +0 -7
- package/src/client/sharing/useShareDialogController.ts +0 -2
- package/src/client/sse-event-processor.ts +85 -1
- package/src/localization/default-messages.ts +6 -0
- package/src/scripts/agent-engines/list-agent-engines.ts +1 -18
- package/src/scripts/call-agent.ts +49 -6
- package/src/server/agent-chat-plugin.ts +50 -10
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -0
- package/corpus/core/src/observability/hosted-model-experiment.ts +0 -118
- package/dist/observability/hosted-model-experiment.d.ts +0 -39
- package/dist/observability/hosted-model-experiment.d.ts.map +0 -1
- package/dist/observability/hosted-model-experiment.js +0 -90
- package/dist/observability/hosted-model-experiment.js.map +0 -1
- package/src/observability/hosted-model-experiment.ts +0 -118
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.119.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6f485ac: Remove the redundant Done action from shared share popovers and dialogs.
|
|
8
|
+
- 6f485ac: Stream delegated A2A agent activity into an indented chat run with live reasoning, tool status, elapsed time, and a scroll-free final response.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- 6f485ac: Use GPT-5.6 Luna as the default for Builder Gateway and OpenAI connections, keep Claude Sonnet 5 for Anthropic connections, and order the model picker from lowest to highest cost.
|
|
13
|
+
|
|
3
14
|
## 0.118.1
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -434,6 +434,21 @@ Like `callAgent()`, the CLI defaults to async + poll (`invokeAgent` → `callAge
|
|
|
434
434
|
|
|
435
435
|
The target resolves the same way as `agentNative.invoke()`: by workspace app id, by app name, or by a full URL — so the same command works against a sibling app in a multi-app workspace or an arbitrary A2A peer elsewhere.
|
|
436
436
|
|
|
437
|
+
## Delegated agent activity {#delegated-agent-activity}
|
|
438
|
+
|
|
439
|
+
Agent Native peers may attach an optional `data` part with
|
|
440
|
+
`kind: "agent-native/agent-activity"` to task status messages. It carries a
|
|
441
|
+
bounded snapshot of the user-visible reasoning summaries, tool names and
|
|
442
|
+
completion states, elapsed time, and progressive response text. Calling apps
|
|
443
|
+
render these updates as a nested agent run and collapse the work history when
|
|
444
|
+
the delegated task finishes.
|
|
445
|
+
|
|
446
|
+
The activity part never includes tool inputs, tool results, credentials, or
|
|
447
|
+
hidden provider reasoning. Treat it as untrusted presentation data, never as
|
|
448
|
+
identity, authorization, approval, routing, or artifact validation. External
|
|
449
|
+
A2A peers can omit the extension; their ordinary status text and final response
|
|
450
|
+
still render in the same delegated-agent surface.
|
|
451
|
+
|
|
437
452
|
## Task lifecycle {#task-lifecycle}
|
|
438
453
|
|
|
439
454
|
Each message creates a task that moves through these states:
|
|
@@ -13,7 +13,7 @@ If you want a finished domain product shape, start from [Calendar](/docs/templat
|
|
|
13
13
|
<Screen
|
|
14
14
|
surface="desktop"
|
|
15
15
|
html={
|
|
16
|
-
"<div style='min-height:560px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;padding:56px 40px'><div style='display:flex;flex-direction:column;align-items:center;justify-content:center;gap:28px;width:min(700px,92%);min-height:430px'><div style='height:34px'></div><div style='text-align:center'><h1 style='margin:0'>How can I help?</h1><p class='wf-muted' style='margin:10px 0 0'>Chat about anything. Add actions, components, pages, jobs, or your own backend.</p></div><div class='wf-card' style='width:100%;min-height:150px;display:flex;flex-direction:column;gap:18px'><span class='wf-muted'>Message the agent...</span><div style='flex:1'></div><div style='display:flex;align-items:center;gap:10px'><span data-icon='plus' aria-label='Attach'></span><div style='flex:1'></div><span class='wf-pill'>
|
|
16
|
+
"<div style='min-height:560px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;padding:56px 40px'><div style='display:flex;flex-direction:column;align-items:center;justify-content:center;gap:28px;width:min(700px,92%);min-height:430px'><div style='height:34px'></div><div style='text-align:center'><h1 style='margin:0'>How can I help?</h1><p class='wf-muted' style='margin:10px 0 0'>Chat about anything. Add actions, components, pages, jobs, or your own backend.</p></div><div class='wf-card' style='width:100%;min-height:150px;display:flex;flex-direction:column;gap:18px'><span class='wf-muted'>Message the agent...</span><div style='flex:1'></div><div style='display:flex;align-items:center;gap:10px'><span data-icon='plus' aria-label='Attach'></span><div style='flex:1'></div><span class='wf-pill'>GPT-5.6 Luna · Auto</span><span class='wf-pill'>Act</span><button class='primary'>↑</button></div></div><div style='height:34px'></div></div></div>"
|
|
17
17
|
}
|
|
18
18
|
/>
|
|
19
19
|
</WireframeBlock>
|
|
@@ -232,9 +232,9 @@ Generating a plan or recap runs a full agentic session against your coding
|
|
|
232
232
|
agent's LLM, not a lightweight template fill, so cost scales with the size of
|
|
233
233
|
the diff or plan and the model you choose.
|
|
234
234
|
|
|
235
|
-
- The app's
|
|
236
|
-
|
|
237
|
-
|
|
235
|
+
- The app's default chat model is GPT-5.6 Luna. Direct Anthropic connections
|
|
236
|
+
keep Claude Sonnet 5 as their default. Change models any time in **Settings**;
|
|
237
|
+
Haiku is the cheaper Claude option.
|
|
238
238
|
- Automated PR recaps from the GitHub Action run separately from the
|
|
239
239
|
interactive app and have their own model and cost knobs — see
|
|
240
240
|
[PR Visual Recap](/docs/pr-visual-recap) for `VISUAL_RECAP_MODEL`,
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.119.0",
|
|
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": {
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { sanitizeToolErrorText } from "../agent/tool-error-redaction.js";
|
|
2
|
+
import type { AgentChatEvent } from "../agent/types.js";
|
|
3
|
+
import type { DataPart, Part } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export const A2A_AGENT_ACTIVITY_KIND = "agent-native/agent-activity";
|
|
6
|
+
export const A2A_AGENT_ACTIVITY_VERSION = 1;
|
|
7
|
+
export const MAX_A2A_ACTIVITY_REASONING_CHARS = 32_768;
|
|
8
|
+
export const MAX_A2A_ACTIVITY_RESPONSE_CHARS = 32_768;
|
|
9
|
+
export const MAX_A2A_ACTIVITY_TOTAL_CHARS = 98_304;
|
|
10
|
+
export const MAX_A2A_ACTIVITY_REASONING_SEGMENTS = 128;
|
|
11
|
+
export const MAX_A2A_ACTIVITY_TOOL_CALLS = 64;
|
|
12
|
+
export const MAX_A2A_ACTIVITY_TOOL_NAME_CHARS = 96;
|
|
13
|
+
export const MAX_A2A_ACTIVITY_TOOL_ID_CHARS = 128;
|
|
14
|
+
|
|
15
|
+
export type A2AAgentActivityPhase =
|
|
16
|
+
| "reasoning"
|
|
17
|
+
| "tool"
|
|
18
|
+
| "responding"
|
|
19
|
+
| "complete"
|
|
20
|
+
| "error";
|
|
21
|
+
|
|
22
|
+
export type A2AAgentActivityToolStatus = "running" | "completed" | "failed";
|
|
23
|
+
|
|
24
|
+
export interface A2AAgentActivityToolCall {
|
|
25
|
+
name: string;
|
|
26
|
+
id?: string;
|
|
27
|
+
status: A2AAgentActivityToolStatus;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface A2AAgentActivitySnapshot extends Record<string, unknown> {
|
|
31
|
+
kind: typeof A2A_AGENT_ACTIVITY_KIND;
|
|
32
|
+
version: typeof A2A_AGENT_ACTIVITY_VERSION;
|
|
33
|
+
sequence: number;
|
|
34
|
+
startedAt: number;
|
|
35
|
+
updatedAt: number;
|
|
36
|
+
durationMs: number;
|
|
37
|
+
activePhase: A2AAgentActivityPhase;
|
|
38
|
+
reasoning: string[];
|
|
39
|
+
toolCalls: A2AAgentActivityToolCall[];
|
|
40
|
+
responseText?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface A2AAgentActivityState {
|
|
44
|
+
sequence: number;
|
|
45
|
+
startedAt: number;
|
|
46
|
+
updatedAt: number;
|
|
47
|
+
activePhase: A2AAgentActivityPhase;
|
|
48
|
+
reasoning: string[];
|
|
49
|
+
toolCalls: A2AAgentActivityToolCall[];
|
|
50
|
+
responseText: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function createA2AAgentActivityState(
|
|
54
|
+
startedAt = Date.now(),
|
|
55
|
+
): A2AAgentActivityState {
|
|
56
|
+
return {
|
|
57
|
+
sequence: 0,
|
|
58
|
+
startedAt,
|
|
59
|
+
updatedAt: startedAt,
|
|
60
|
+
activePhase: "reasoning",
|
|
61
|
+
reasoning: [],
|
|
62
|
+
toolCalls: [],
|
|
63
|
+
responseText: "",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Converts internal loop events into a bounded activity snapshot. It carries
|
|
69
|
+
* only reasoning text already emitted to the local chat, never tool inputs or
|
|
70
|
+
* results.
|
|
71
|
+
*/
|
|
72
|
+
export function applyA2AAgentActivityEvent(
|
|
73
|
+
state: A2AAgentActivityState,
|
|
74
|
+
event: AgentChatEvent,
|
|
75
|
+
updatedAt = Date.now(),
|
|
76
|
+
): A2AAgentActivityState {
|
|
77
|
+
const next = { ...state, updatedAt: normalizeTimestamp(updatedAt) };
|
|
78
|
+
let changed = false;
|
|
79
|
+
|
|
80
|
+
switch (event.type) {
|
|
81
|
+
case "thinking":
|
|
82
|
+
next.activePhase = "reasoning";
|
|
83
|
+
next.reasoning = appendBoundedSegment(
|
|
84
|
+
next.reasoning,
|
|
85
|
+
event.text,
|
|
86
|
+
MAX_A2A_ACTIVITY_REASONING_CHARS,
|
|
87
|
+
next.toolCalls.length,
|
|
88
|
+
);
|
|
89
|
+
changed = true;
|
|
90
|
+
break;
|
|
91
|
+
case "tool_start":
|
|
92
|
+
next.activePhase = "tool";
|
|
93
|
+
next.responseText = "";
|
|
94
|
+
next.toolCalls = appendToolCall(next.toolCalls, toolFromEvent(event));
|
|
95
|
+
changed = true;
|
|
96
|
+
break;
|
|
97
|
+
case "tool_done":
|
|
98
|
+
next.activePhase = "tool";
|
|
99
|
+
next.toolCalls = settleToolCall(next.toolCalls, toolFromEvent(event));
|
|
100
|
+
changed = true;
|
|
101
|
+
break;
|
|
102
|
+
case "text":
|
|
103
|
+
next.activePhase = "responding";
|
|
104
|
+
next.responseText = appendBoundedText(
|
|
105
|
+
next.responseText,
|
|
106
|
+
event.text,
|
|
107
|
+
MAX_A2A_ACTIVITY_RESPONSE_CHARS,
|
|
108
|
+
);
|
|
109
|
+
changed = true;
|
|
110
|
+
break;
|
|
111
|
+
case "done":
|
|
112
|
+
next.activePhase = "complete";
|
|
113
|
+
changed = true;
|
|
114
|
+
break;
|
|
115
|
+
case "error":
|
|
116
|
+
next.activePhase = "error";
|
|
117
|
+
changed = true;
|
|
118
|
+
break;
|
|
119
|
+
case "clear":
|
|
120
|
+
next.responseText = "";
|
|
121
|
+
changed = true;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return changed ? { ...next, sequence: state.sequence + 1 } : state;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function buildA2AAgentActivitySnapshot(
|
|
129
|
+
state: A2AAgentActivityState,
|
|
130
|
+
): A2AAgentActivitySnapshot {
|
|
131
|
+
return {
|
|
132
|
+
kind: A2A_AGENT_ACTIVITY_KIND,
|
|
133
|
+
version: A2A_AGENT_ACTIVITY_VERSION,
|
|
134
|
+
sequence: state.sequence,
|
|
135
|
+
startedAt: state.startedAt,
|
|
136
|
+
updatedAt: state.updatedAt,
|
|
137
|
+
durationMs: Math.max(0, state.updatedAt - state.startedAt),
|
|
138
|
+
activePhase: state.activePhase,
|
|
139
|
+
reasoning: state.reasoning,
|
|
140
|
+
toolCalls: state.toolCalls,
|
|
141
|
+
...(state.responseText ? { responseText: state.responseText } : {}),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function buildA2AAgentActivityPart(
|
|
146
|
+
state: A2AAgentActivityState,
|
|
147
|
+
): DataPart {
|
|
148
|
+
return { type: "data", data: buildA2AAgentActivitySnapshot(state) };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function parseA2AAgentActivityPart(
|
|
152
|
+
part: Part | unknown,
|
|
153
|
+
): A2AAgentActivitySnapshot | null {
|
|
154
|
+
if (!part || typeof part !== "object") return null;
|
|
155
|
+
const candidate = part as { type?: unknown; data?: unknown };
|
|
156
|
+
if (candidate.type !== "data" || !isRecord(candidate.data)) return null;
|
|
157
|
+
const data = candidate.data;
|
|
158
|
+
if (
|
|
159
|
+
data.kind !== A2A_AGENT_ACTIVITY_KIND ||
|
|
160
|
+
data.version !== A2A_AGENT_ACTIVITY_VERSION ||
|
|
161
|
+
!isSafeInteger(data.sequence) ||
|
|
162
|
+
!isSafeInteger(data.startedAt) ||
|
|
163
|
+
!isSafeInteger(data.updatedAt) ||
|
|
164
|
+
!isSafeInteger(data.durationMs) ||
|
|
165
|
+
!isPhase(data.activePhase) ||
|
|
166
|
+
data.updatedAt < data.startedAt ||
|
|
167
|
+
data.durationMs !== data.updatedAt - data.startedAt ||
|
|
168
|
+
!isSafeReasoning(data.reasoning) ||
|
|
169
|
+
!isSafeToolCalls(data.toolCalls) ||
|
|
170
|
+
(data.responseText !== undefined &&
|
|
171
|
+
!isSafeText(data.responseText, MAX_A2A_ACTIVITY_RESPONSE_CHARS)) ||
|
|
172
|
+
activityCharacterCount(data) > MAX_A2A_ACTIVITY_TOTAL_CHARS
|
|
173
|
+
) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return data as unknown as A2AAgentActivitySnapshot;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function toolFromEvent(
|
|
181
|
+
event: Extract<AgentChatEvent, { type: "tool_start" | "tool_done" }>,
|
|
182
|
+
): A2AAgentActivityToolCall {
|
|
183
|
+
const id = sanitizeToolId(event.id);
|
|
184
|
+
return {
|
|
185
|
+
name: sanitizeToolName(event.tool),
|
|
186
|
+
...(id ? { id } : {}),
|
|
187
|
+
status:
|
|
188
|
+
event.type === "tool_start"
|
|
189
|
+
? "running"
|
|
190
|
+
: event.isError
|
|
191
|
+
? "failed"
|
|
192
|
+
: "completed",
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function appendBoundedText(
|
|
197
|
+
current: string,
|
|
198
|
+
addition: string,
|
|
199
|
+
maxChars: number,
|
|
200
|
+
) {
|
|
201
|
+
return sanitizeText(`${current}${addition}`, maxChars);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function appendBoundedSegment(
|
|
205
|
+
current: string[],
|
|
206
|
+
addition: string,
|
|
207
|
+
maxChars: number,
|
|
208
|
+
precedingToolCount: number,
|
|
209
|
+
): string[] {
|
|
210
|
+
const used = current.reduce((total, text) => total + text.length, 0);
|
|
211
|
+
if (
|
|
212
|
+
used >= maxChars ||
|
|
213
|
+
current.length >= MAX_A2A_ACTIVITY_REASONING_SEGMENTS
|
|
214
|
+
) {
|
|
215
|
+
return current;
|
|
216
|
+
}
|
|
217
|
+
const text = sanitizeText(addition, maxChars - used);
|
|
218
|
+
if (!text) return current;
|
|
219
|
+
const next = [...current];
|
|
220
|
+
while (
|
|
221
|
+
next.length < precedingToolCount &&
|
|
222
|
+
next.length < MAX_A2A_ACTIVITY_REASONING_SEGMENTS
|
|
223
|
+
) {
|
|
224
|
+
next.push("");
|
|
225
|
+
}
|
|
226
|
+
if (next.length === precedingToolCount) {
|
|
227
|
+
return [...next, text];
|
|
228
|
+
}
|
|
229
|
+
next[precedingToolCount] = `${next[precedingToolCount] ?? ""}${text}`;
|
|
230
|
+
return next;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function appendToolCall(
|
|
234
|
+
current: A2AAgentActivityToolCall[],
|
|
235
|
+
tool: A2AAgentActivityToolCall,
|
|
236
|
+
): A2AAgentActivityToolCall[] {
|
|
237
|
+
return current.length < MAX_A2A_ACTIVITY_TOOL_CALLS
|
|
238
|
+
? [...current, tool]
|
|
239
|
+
: current;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function settleToolCall(
|
|
243
|
+
current: A2AAgentActivityToolCall[],
|
|
244
|
+
tool: A2AAgentActivityToolCall,
|
|
245
|
+
): A2AAgentActivityToolCall[] {
|
|
246
|
+
for (let index = current.length - 1; index >= 0; index -= 1) {
|
|
247
|
+
const existing = current[index];
|
|
248
|
+
if (
|
|
249
|
+
(tool.id && tool.id === existing.id) ||
|
|
250
|
+
(!tool.id && tool.name === existing.name)
|
|
251
|
+
) {
|
|
252
|
+
return current.map((value, itemIndex) =>
|
|
253
|
+
itemIndex === index ? tool : value,
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return appendToolCall(current, tool);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function sanitizeText(value: string, maxChars: number): string {
|
|
261
|
+
return sanitizeToolErrorText(value)
|
|
262
|
+
.replace(/\r\n?/g, "\n")
|
|
263
|
+
.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, "")
|
|
264
|
+
.slice(0, maxChars);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function sanitizeToolName(value: string): string {
|
|
268
|
+
return sanitizeText(value, MAX_A2A_ACTIVITY_TOOL_NAME_CHARS) || "tool";
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function sanitizeToolId(value: string | undefined): string | undefined {
|
|
272
|
+
const sanitized = value
|
|
273
|
+
? sanitizeText(value, MAX_A2A_ACTIVITY_TOOL_ID_CHARS)
|
|
274
|
+
: "";
|
|
275
|
+
return sanitized || undefined;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function normalizeTimestamp(value: number): number {
|
|
279
|
+
return isSafeInteger(value) ? value : Date.now();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
283
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function isSafeInteger(value: unknown): value is number {
|
|
287
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function isPhase(value: unknown): value is A2AAgentActivityPhase {
|
|
291
|
+
return ["reasoning", "tool", "responding", "complete", "error"].includes(
|
|
292
|
+
value as string,
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function isSafeReasoning(value: unknown): value is string[] {
|
|
297
|
+
return (
|
|
298
|
+
Array.isArray(value) &&
|
|
299
|
+
value.length <= MAX_A2A_ACTIVITY_REASONING_SEGMENTS &&
|
|
300
|
+
value.reduce(
|
|
301
|
+
(total, text) =>
|
|
302
|
+
total + (typeof text === "string" ? text.length : Infinity),
|
|
303
|
+
0,
|
|
304
|
+
) <= MAX_A2A_ACTIVITY_REASONING_CHARS &&
|
|
305
|
+
value.every((text) => isSafeText(text, MAX_A2A_ACTIVITY_REASONING_CHARS))
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function isSafeToolCalls(value: unknown): value is A2AAgentActivityToolCall[] {
|
|
310
|
+
return (
|
|
311
|
+
Array.isArray(value) &&
|
|
312
|
+
value.length <= MAX_A2A_ACTIVITY_TOOL_CALLS &&
|
|
313
|
+
value.every(isSafeToolCall)
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function isSafeToolCall(value: unknown): value is A2AAgentActivityToolCall {
|
|
318
|
+
if (!isRecord(value) || !isSafeToolName(value.name)) return false;
|
|
319
|
+
return (
|
|
320
|
+
(value.id === undefined || isSafeToolId(value.id)) &&
|
|
321
|
+
(value.status === "running" ||
|
|
322
|
+
value.status === "completed" ||
|
|
323
|
+
value.status === "failed")
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function isSafeText(value: unknown, maxChars: number): value is string {
|
|
328
|
+
return (
|
|
329
|
+
typeof value === "string" &&
|
|
330
|
+
value.length <= maxChars &&
|
|
331
|
+
value === sanitizeText(value, maxChars)
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function isSafeToolName(value: unknown): value is string {
|
|
336
|
+
return (
|
|
337
|
+
typeof value === "string" &&
|
|
338
|
+
value.length <= MAX_A2A_ACTIVITY_TOOL_NAME_CHARS &&
|
|
339
|
+
value === sanitizeToolName(value)
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function isSafeToolId(value: unknown): value is string {
|
|
344
|
+
return (
|
|
345
|
+
typeof value === "string" &&
|
|
346
|
+
value.length <= MAX_A2A_ACTIVITY_TOOL_ID_CHARS &&
|
|
347
|
+
value === sanitizeToolId(value)
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function activityCharacterCount(data: Record<string, unknown>): number {
|
|
352
|
+
const reasoning = Array.isArray(data.reasoning)
|
|
353
|
+
? data.reasoning.reduce(
|
|
354
|
+
(total, text) => total + (typeof text === "string" ? text.length : 0),
|
|
355
|
+
0,
|
|
356
|
+
)
|
|
357
|
+
: 0;
|
|
358
|
+
const response =
|
|
359
|
+
typeof data.responseText === "string" ? data.responseText.length : 0;
|
|
360
|
+
const tools = Array.isArray(data.toolCalls)
|
|
361
|
+
? data.toolCalls.reduce((total, tool) => {
|
|
362
|
+
if (!isRecord(tool)) return total;
|
|
363
|
+
return (
|
|
364
|
+
total +
|
|
365
|
+
(typeof tool.name === "string" ? tool.name.length : 0) +
|
|
366
|
+
(typeof tool.id === "string" ? tool.id.length : 0)
|
|
367
|
+
);
|
|
368
|
+
}, 0)
|
|
369
|
+
: 0;
|
|
370
|
+
return reasoning + response + tools;
|
|
371
|
+
}
|
|
@@ -647,6 +647,8 @@ export async function callAgent(
|
|
|
647
647
|
text: string,
|
|
648
648
|
opts?: {
|
|
649
649
|
apiKey?: string;
|
|
650
|
+
/** Additional transport metadata. Receivers must not use it as identity. */
|
|
651
|
+
metadata?: Record<string, unknown>;
|
|
650
652
|
contextId?: string;
|
|
651
653
|
userEmail?: string;
|
|
652
654
|
orgDomain?: string;
|
|
@@ -694,7 +696,7 @@ export async function callAgent(
|
|
|
694
696
|
onUpdate?: (task: Task) => void;
|
|
695
697
|
},
|
|
696
698
|
): Promise<string> {
|
|
697
|
-
const metadata: Record<string, unknown> = {};
|
|
699
|
+
const metadata: Record<string, unknown> = { ...opts?.metadata };
|
|
698
700
|
if (opts?.userEmail) metadata.userEmail = opts.userEmail;
|
|
699
701
|
if (opts?.orgDomain) metadata.orgDomain = opts.orgDomain;
|
|
700
702
|
if (opts?.requestOrigin) metadata.requestOrigin = opts.requestOrigin;
|
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
export { mountA2A, verifyA2AToken } from "./server.js";
|
|
3
3
|
export type { A2ATokenPayload } from "./server.js";
|
|
4
4
|
export { generateAgentCard } from "./agent-card.js";
|
|
5
|
+
export {
|
|
6
|
+
A2A_AGENT_ACTIVITY_KIND,
|
|
7
|
+
A2A_AGENT_ACTIVITY_VERSION,
|
|
8
|
+
MAX_A2A_ACTIVITY_REASONING_CHARS,
|
|
9
|
+
MAX_A2A_ACTIVITY_REASONING_SEGMENTS,
|
|
10
|
+
MAX_A2A_ACTIVITY_RESPONSE_CHARS,
|
|
11
|
+
MAX_A2A_ACTIVITY_TOOL_CALLS,
|
|
12
|
+
MAX_A2A_ACTIVITY_TOTAL_CHARS,
|
|
13
|
+
MAX_A2A_ACTIVITY_TOOL_ID_CHARS,
|
|
14
|
+
MAX_A2A_ACTIVITY_TOOL_NAME_CHARS,
|
|
15
|
+
applyA2AAgentActivityEvent,
|
|
16
|
+
buildA2AAgentActivityPart,
|
|
17
|
+
buildA2AAgentActivitySnapshot,
|
|
18
|
+
createA2AAgentActivityState,
|
|
19
|
+
parseA2AAgentActivityPart,
|
|
20
|
+
} from "./activity.js";
|
|
5
21
|
|
|
6
22
|
// Client
|
|
7
23
|
export { A2AClient, callAction, callAgent, signA2AToken } from "./client.js";
|
|
@@ -38,6 +54,11 @@ export type {
|
|
|
38
54
|
A2ACorrelationMetadata,
|
|
39
55
|
A2AReadOnlyActionInvocation,
|
|
40
56
|
A2AReadOnlyActionResult,
|
|
57
|
+
A2AAgentActivityPhase,
|
|
58
|
+
A2AAgentActivitySnapshot,
|
|
59
|
+
A2AAgentActivityState,
|
|
60
|
+
A2AAgentActivityToolCall,
|
|
61
|
+
A2AAgentActivityToolStatus,
|
|
41
62
|
} from "./types.js";
|
|
42
63
|
export type {
|
|
43
64
|
AgentInvocationErrorCode,
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
// A2A Protocol types (spec v0.3) + framework config types
|
|
2
2
|
import type { PublicAgentActionConfig } from "../action.js";
|
|
3
3
|
|
|
4
|
+
export type {
|
|
5
|
+
A2AAgentActivityPhase,
|
|
6
|
+
A2AAgentActivitySnapshot,
|
|
7
|
+
A2AAgentActivityState,
|
|
8
|
+
A2AAgentActivityToolCall,
|
|
9
|
+
A2AAgentActivityToolStatus,
|
|
10
|
+
} from "./activity.js";
|
|
11
|
+
|
|
4
12
|
// --- Parts (content atoms) ---
|
|
5
13
|
|
|
6
14
|
export interface TextPart {
|
|
@@ -242,11 +242,11 @@ function openRouterModelId(provider: string, model: string): string {
|
|
|
242
242
|
return `${provider}/${model}`;
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
const FRAMEWORK_DEFAULT_OPENAI_MODEL = "gpt-5.6-
|
|
246
|
-
const FRAMEWORK_DEFAULT_BUILDER_MODEL = ANTHROPIC_DEFAULT_MODEL_ID;
|
|
245
|
+
const FRAMEWORK_DEFAULT_OPENAI_MODEL = "gpt-5.6-luna";
|
|
247
246
|
const FRAMEWORK_DEFAULT_BUILDER_OPENAI_MODEL = builderGatewayModelId(
|
|
248
247
|
FRAMEWORK_DEFAULT_OPENAI_MODEL,
|
|
249
248
|
);
|
|
249
|
+
const FRAMEWORK_DEFAULT_BUILDER_MODEL = FRAMEWORK_DEFAULT_BUILDER_OPENAI_MODEL;
|
|
250
250
|
const FRAMEWORK_DEFAULT_OPENROUTER_MODEL = openRouterModelId(
|
|
251
251
|
"openai",
|
|
252
252
|
FRAMEWORK_DEFAULT_OPENAI_MODEL,
|
|
@@ -257,14 +257,14 @@ export const AGENT_MODEL_CONFIG = {
|
|
|
257
257
|
defaultModel: FRAMEWORK_DEFAULT_BUILDER_MODEL,
|
|
258
258
|
supportedModels: [
|
|
259
259
|
"auto",
|
|
260
|
-
"claude-opus-4-8",
|
|
261
|
-
CLAUDE_SONNET_MODEL_ID,
|
|
262
|
-
"claude-haiku-4-5",
|
|
263
260
|
FRAMEWORK_DEFAULT_BUILDER_OPENAI_MODEL,
|
|
264
261
|
"gpt-5-6-terra",
|
|
265
|
-
"gpt-5-6-
|
|
266
|
-
"
|
|
262
|
+
"gpt-5-6-sol",
|
|
263
|
+
"claude-haiku-4-5",
|
|
264
|
+
CLAUDE_SONNET_MODEL_ID,
|
|
265
|
+
"claude-opus-4-8",
|
|
267
266
|
"gemini-3-5-flash",
|
|
267
|
+
"gemini-3-1-pro",
|
|
268
268
|
// Flash-Lite is a transcription-only public id. Advertising it as an
|
|
269
269
|
// agent-chat option routes through a Vertex preview model whose
|
|
270
270
|
// availability can lapse while the id remains accepted, leaving chat
|
|
@@ -274,39 +274,35 @@ export const AGENT_MODEL_CONFIG = {
|
|
|
274
274
|
anthropic: {
|
|
275
275
|
defaultModel: ANTHROPIC_DEFAULT_MODEL_ID,
|
|
276
276
|
supportedModels: [
|
|
277
|
-
"claude-fable-5",
|
|
278
|
-
"claude-opus-4-8",
|
|
279
|
-
CLAUDE_SONNET_MODEL_ID,
|
|
280
277
|
"claude-haiku-4-5-20251001",
|
|
278
|
+
CLAUDE_SONNET_MODEL_ID,
|
|
279
|
+
"claude-opus-4-8",
|
|
280
|
+
"claude-fable-5",
|
|
281
281
|
],
|
|
282
282
|
},
|
|
283
283
|
aiSdk: {
|
|
284
284
|
anthropic: {
|
|
285
285
|
defaultModel: ANTHROPIC_DEFAULT_MODEL_ID,
|
|
286
286
|
supportedModels: [
|
|
287
|
-
"claude-fable-5",
|
|
288
|
-
"claude-opus-4-8",
|
|
289
|
-
CLAUDE_SONNET_MODEL_ID,
|
|
290
287
|
"claude-haiku-4-5-20251001",
|
|
288
|
+
CLAUDE_SONNET_MODEL_ID,
|
|
289
|
+
"claude-opus-4-8",
|
|
290
|
+
"claude-fable-5",
|
|
291
291
|
],
|
|
292
292
|
},
|
|
293
293
|
openai: {
|
|
294
294
|
defaultModel: FRAMEWORK_DEFAULT_OPENAI_MODEL,
|
|
295
|
-
supportedModels: [
|
|
296
|
-
FRAMEWORK_DEFAULT_OPENAI_MODEL,
|
|
297
|
-
"gpt-5.6-terra",
|
|
298
|
-
"gpt-5.6-luna",
|
|
299
|
-
],
|
|
295
|
+
supportedModels: ["gpt-5.6-luna", "gpt-5.6-terra", "gpt-5.6-sol"],
|
|
300
296
|
},
|
|
301
297
|
openrouter: {
|
|
302
298
|
defaultModel: FRAMEWORK_DEFAULT_OPENROUTER_MODEL,
|
|
303
299
|
supportedModels: [
|
|
304
|
-
"anthropic/claude-fable-5",
|
|
305
|
-
"anthropic/claude-opus-4.8",
|
|
306
|
-
OPENROUTER_CLAUDE_SONNET_MODEL_ID,
|
|
307
|
-
FRAMEWORK_DEFAULT_OPENROUTER_MODEL,
|
|
308
|
-
"openai/gpt-5.6-terra",
|
|
309
300
|
"openai/gpt-5.6-luna",
|
|
301
|
+
"openai/gpt-5.6-terra",
|
|
302
|
+
"openai/gpt-5.6-sol",
|
|
303
|
+
OPENROUTER_CLAUDE_SONNET_MODEL_ID,
|
|
304
|
+
"anthropic/claude-opus-4.8",
|
|
305
|
+
"anthropic/claude-fable-5",
|
|
310
306
|
// Current stable Gemini on OpenRouter (2.5 Flash is GA)
|
|
311
307
|
"google/gemini-2.5-flash",
|
|
312
308
|
"z-ai/glm-5.2",
|