@springbrand/agent-runtime 0.2.0-alpha.16 → 0.2.0-alpha.17
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/package.json +1 -1
- package/src/adapter/cloudflare/sandbox/adapter.ts +61 -36
- package/src/adapter/cloudflare/universal-agent/preparation.ts +0 -2
- package/src/adapter/cloudflare/workspace/scoped-workspace.ts +23 -18
- package/src/db/index.ts +5 -0
- package/src/db/schema.ts +15 -0
- package/src/db/telemetry-outbox.repo.ts +151 -0
- package/src/index.ts +1 -0
- package/src/kernel/approval-lifecycle.ts +35 -3
- package/src/kernel/bindings.ts +0 -1
- package/src/kernel/interaction-lifecycle.ts +35 -6
- package/src/layers/orchestration/temporary-agent/workspace.ts +4 -4
- package/src/lib/prompt.ts +22 -15
- package/src/pi/assembly/context.ts +2 -2
- package/src/pi/message/conversion.ts +13 -1
- package/src/pi/runtime-adapter/execution.ts +26 -26
- package/src/pi/runtime-adapter/models.ts +144 -44
- package/src/pi/tool/ai-adapter.ts +2 -2
- package/src/pi/tool/base.ts +31 -25
- package/src/pi/tool/compiler.ts +5 -103
- package/src/pi/turn/tool-recovery.ts +11 -1
- package/src/runtime-agent.ts +24 -0
- package/src/runtime-assembler.ts +29 -15
- package/src/runtime-definition.ts +2 -0
- package/src/runtime.ts +362 -20
- package/src/telemetry/contract.ts +389 -0
- package/src/telemetry/coordinator.ts +143 -0
- package/src/telemetry/delivery.ts +138 -0
- package/src/telemetry/ids.ts +60 -0
- package/src/telemetry/index.ts +7 -0
- package/src/telemetry/recorder.ts +61 -0
- package/src/telemetry/runtime-telemetry.ts +484 -0
- package/src/telemetry/sanitize.ts +97 -0
- package/src/tool-registry.ts +11 -11
- package/src/lib/telemetry-dev.ts +0 -47
package/src/pi/tool/base.ts
CHANGED
|
@@ -276,31 +276,37 @@ export function basePiToolCandidates(
|
|
|
276
276
|
},
|
|
277
277
|
},
|
|
278
278
|
},
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
279
|
+
{
|
|
280
|
+
...candidate({
|
|
281
|
+
name: "suggest_followups",
|
|
282
|
+
label: "Suggest follow-ups",
|
|
283
|
+
description:
|
|
284
|
+
"Offer the user 2-4 optional follow-up directions after completing a substantive task (a report, an analysis, a multi-step job). Call this at most once, and it MUST be the very last thing you do: finish all of your prose FIRST, then call this tool and END the turn immediately — do NOT write any text after calling it. Do NOT call it for small talk, quick answers, or while a task is still in progress.",
|
|
285
|
+
parameters: suggestFollowupsParameters,
|
|
286
|
+
async execute(_toolCallId, input) {
|
|
287
|
+
return result({ noted: true, count: input.items.length });
|
|
288
|
+
},
|
|
289
|
+
}),
|
|
290
|
+
direct: true,
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
...candidate({
|
|
294
|
+
name: "update_plan",
|
|
295
|
+
label: "Update plan",
|
|
296
|
+
description:
|
|
297
|
+
"Maintain the user-visible plan for the current task. Call this whenever a task involves 2 or more steps, and again every time the plan or a step's status changes. Always pass the FULL plan — it replaces the previous plan entirely (idempotent overwrite), so omitted steps disappear.",
|
|
298
|
+
parameters: updatePlanParameters,
|
|
299
|
+
prepareArguments: normalizeUpdatePlanArguments,
|
|
300
|
+
async execute(_toolCallId, input) {
|
|
301
|
+
return result({
|
|
302
|
+
ok: true,
|
|
303
|
+
total: input.steps.length,
|
|
304
|
+
done: input.steps.filter((step) => step.status === "done").length,
|
|
305
|
+
});
|
|
306
|
+
},
|
|
307
|
+
}),
|
|
308
|
+
direct: true,
|
|
309
|
+
},
|
|
304
310
|
...(webSearch ? [webSearchPiToolCandidate(webSearch)] : []),
|
|
305
311
|
];
|
|
306
312
|
}
|
package/src/pi/tool/compiler.ts
CHANGED
|
@@ -46,7 +46,9 @@ export interface PiToolInteractionSpec {
|
|
|
46
46
|
export interface PiToolCandidate {
|
|
47
47
|
readonly owner: string;
|
|
48
48
|
readonly tool: AgentTool<any, any>;
|
|
49
|
-
/**
|
|
49
|
+
/** Keep this Tool Direct-only instead of also offering it through Code Mode. */
|
|
50
|
+
readonly direct?: true;
|
|
51
|
+
/** @internal Tools also callable through this Code Mode candidate. */
|
|
50
52
|
readonly codeExecutionTools?: readonly PiToolCandidate[];
|
|
51
53
|
/** Conservative maximum used in the stable Runtime descriptor. */
|
|
52
54
|
readonly requiredExecutionLevel: ExecutionLevel;
|
|
@@ -78,15 +80,6 @@ export interface CompilePiToolsOptions {
|
|
|
78
80
|
) => void | Promise<void>;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
/** 记录一次 Pi 工具调用的耗时、结果大小和溢出状态。 */
|
|
82
|
-
export interface PiToolTelemetry {
|
|
83
|
-
readonly tool: string;
|
|
84
|
-
readonly ms: number;
|
|
85
|
-
readonly ok: boolean;
|
|
86
|
-
readonly bytes: number;
|
|
87
|
-
readonly spill: boolean;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
83
|
const governanceState = Symbol("PiToolGovernanceState");
|
|
91
84
|
|
|
92
85
|
/** 向 Pi Agent 提供工具后置钩子,并为编译器保留同一 Turn 的治理状态。 */
|
|
@@ -116,7 +109,6 @@ interface PiToolGovernanceState {
|
|
|
116
109
|
readonly terminalCalls: Set<string>;
|
|
117
110
|
totalFailures: number;
|
|
118
111
|
aborted: boolean;
|
|
119
|
-
readonly telemetry?: (event: PiToolTelemetry) => void;
|
|
120
112
|
}
|
|
121
113
|
|
|
122
114
|
// #endregion
|
|
@@ -163,57 +155,6 @@ function callKey(toolName: string, args: unknown): string {
|
|
|
163
155
|
return `${toolName}\0${(hash >>> 0).toString(36)}`;
|
|
164
156
|
}
|
|
165
157
|
|
|
166
|
-
// 估算工具结果给 Durable Object 带来的字节压力。
|
|
167
|
-
// `emitToolTelemetry()` 在每次成功、失败或阻断后调用它。
|
|
168
|
-
// artifact_ref 已把大结果外溢,因此必须使用 details 中的原始字节数而不是小引用自身的大小。
|
|
169
|
-
function resultPressure(result: AgentToolResult<unknown>): {
|
|
170
|
-
bytes: number;
|
|
171
|
-
spill: boolean;
|
|
172
|
-
} {
|
|
173
|
-
const details = result.details as {
|
|
174
|
-
kind?: string;
|
|
175
|
-
bytes?: number;
|
|
176
|
-
} | undefined;
|
|
177
|
-
if (
|
|
178
|
-
details?.kind === "artifact_ref" &&
|
|
179
|
-
typeof details.bytes === "number"
|
|
180
|
-
) {
|
|
181
|
-
return { bytes: details.bytes, spill: true };
|
|
182
|
-
}
|
|
183
|
-
try {
|
|
184
|
-
return {
|
|
185
|
-
bytes: JSON.stringify(result).length,
|
|
186
|
-
spill: false,
|
|
187
|
-
};
|
|
188
|
-
} catch {
|
|
189
|
-
return { bytes: 0, spill: false };
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// 尽力把一次工具调用的计量事件交给可选遥测端口。
|
|
194
|
-
// 受治理 execute 方法在每条终止路径上调用。
|
|
195
|
-
// 遥测是观测而非业务逻辑,所以端口抛错必须被吞掉,不能改变工具结果。
|
|
196
|
-
function emitToolTelemetry(
|
|
197
|
-
state: PiToolGovernanceState | undefined,
|
|
198
|
-
tool: string,
|
|
199
|
-
startedAt: number,
|
|
200
|
-
ok: boolean,
|
|
201
|
-
result: AgentToolResult<unknown>,
|
|
202
|
-
): void {
|
|
203
|
-
if (!state?.telemetry) return;
|
|
204
|
-
const pressure = resultPressure(result);
|
|
205
|
-
try {
|
|
206
|
-
state.telemetry({
|
|
207
|
-
tool,
|
|
208
|
-
ms: Math.max(0, Math.round(performance.now() - startedAt)),
|
|
209
|
-
ok,
|
|
210
|
-
...pressure,
|
|
211
|
-
});
|
|
212
|
-
} catch {
|
|
213
|
-
// Observability must not change Tool execution.
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
158
|
// Most Pi adapters keep the original Tool value in details and its serialized
|
|
218
159
|
// model form in one text block. Spill that original once instead of duplicating
|
|
219
160
|
// it inside an AgentToolResult JSON envelope.
|
|
@@ -313,15 +254,12 @@ function blockReason(
|
|
|
313
254
|
*
|
|
314
255
|
* 状态用 symbol 绑定到钩子对象,让编译后的工具和 Pi 后置钩子共享一份 Turn 计数而不暴露公开可变 API。
|
|
315
256
|
*/
|
|
316
|
-
export function createPiToolGovernance(
|
|
317
|
-
telemetry?: (event: PiToolTelemetry) => void,
|
|
318
|
-
): PiToolGovernance {
|
|
257
|
+
export function createPiToolGovernance(): PiToolGovernance {
|
|
319
258
|
const state: PiToolGovernanceState = {
|
|
320
259
|
failures: new Map(),
|
|
321
260
|
terminalCalls: new Set(),
|
|
322
261
|
totalFailures: 0,
|
|
323
262
|
aborted: false,
|
|
324
|
-
telemetry,
|
|
325
263
|
};
|
|
326
264
|
const governance: PiToolGovernance = {
|
|
327
265
|
[governanceState]: state,
|
|
@@ -338,7 +276,7 @@ export function createPiToolGovernance(
|
|
|
338
276
|
return governance;
|
|
339
277
|
}
|
|
340
278
|
|
|
341
|
-
//
|
|
279
|
+
// 为一个候选工具包上输出限额、持久化结算和重试治理。
|
|
342
280
|
// `compilePiTools()` 对最终 Tool Surface 中的每个候选项调用。
|
|
343
281
|
// 一个共享包装边界可确保所有工具无论成功还是失败都经过 settle,不能由各工具自行选择是否持久化。
|
|
344
282
|
function governedTool(
|
|
@@ -355,7 +293,6 @@ function governedTool(
|
|
|
355
293
|
// Pi 工具循环选中编译后的工具时调用,调用方应传入稳定 toolCall id 供结算去重。
|
|
356
294
|
// 输出限额必须发生在 settle 之前,否则 Durable Object 会持久化一份与模型最终所见不同的过大结果。
|
|
357
295
|
async execute(toolCallId, args, signal, onUpdate) {
|
|
358
|
-
const startedAt = performance.now();
|
|
359
296
|
const blocked = blockReason(
|
|
360
297
|
state,
|
|
361
298
|
toolCallId,
|
|
@@ -380,22 +317,8 @@ function governedTool(
|
|
|
380
317
|
source: candidate.source,
|
|
381
318
|
});
|
|
382
319
|
} catch (settlementFailure) {
|
|
383
|
-
emitToolTelemetry(
|
|
384
|
-
state,
|
|
385
|
-
candidate.tool.name,
|
|
386
|
-
startedAt,
|
|
387
|
-
false,
|
|
388
|
-
result,
|
|
389
|
-
);
|
|
390
320
|
throw settlementFailure;
|
|
391
321
|
}
|
|
392
|
-
emitToolTelemetry(
|
|
393
|
-
state,
|
|
394
|
-
candidate.tool.name,
|
|
395
|
-
startedAt,
|
|
396
|
-
false,
|
|
397
|
-
result,
|
|
398
|
-
);
|
|
399
322
|
throw cause;
|
|
400
323
|
}
|
|
401
324
|
|
|
@@ -434,13 +357,6 @@ function governedTool(
|
|
|
434
357
|
candidate.tool.name,
|
|
435
358
|
args,
|
|
436
359
|
);
|
|
437
|
-
emitToolTelemetry(
|
|
438
|
-
state,
|
|
439
|
-
candidate.tool.name,
|
|
440
|
-
startedAt,
|
|
441
|
-
false,
|
|
442
|
-
result,
|
|
443
|
-
);
|
|
444
360
|
const boundedMessage = (result.content[0] as { text: string }).text;
|
|
445
361
|
throw cause instanceof Error &&
|
|
446
362
|
failure === cause &&
|
|
@@ -470,25 +386,11 @@ function governedTool(
|
|
|
470
386
|
candidate.tool.name,
|
|
471
387
|
args,
|
|
472
388
|
);
|
|
473
|
-
emitToolTelemetry(
|
|
474
|
-
state,
|
|
475
|
-
candidate.tool.name,
|
|
476
|
-
startedAt,
|
|
477
|
-
false,
|
|
478
|
-
result,
|
|
479
|
-
);
|
|
480
389
|
throw cause;
|
|
481
390
|
}
|
|
482
391
|
state?.failures.delete(
|
|
483
392
|
callKey(candidate.tool.name, args),
|
|
484
393
|
);
|
|
485
|
-
emitToolTelemetry(
|
|
486
|
-
state,
|
|
487
|
-
candidate.tool.name,
|
|
488
|
-
startedAt,
|
|
489
|
-
true,
|
|
490
|
-
result,
|
|
491
|
-
);
|
|
492
394
|
return result;
|
|
493
395
|
},
|
|
494
396
|
};
|
|
@@ -732,7 +732,17 @@ export function planPiToolRecovery(
|
|
|
732
732
|
}
|
|
733
733
|
|
|
734
734
|
// 已结算 Tool 先补齐续跑;未结算 Tool 只有声明幂等时才自动重试。
|
|
735
|
-
|
|
735
|
+
const tools = Object.values(state.toolCalls);
|
|
736
|
+
const codeModeParents = tools
|
|
737
|
+
.filter((tool) => tool.toolName === "execute")
|
|
738
|
+
.map((tool) => `${tool.toolCallId}:`);
|
|
739
|
+
for (const tool of tools) {
|
|
740
|
+
// 旧版把 Code Mode 内层调用写成独立 Pi attempt,但只有父
|
|
741
|
+
// execute 会产生 settlement。这些带父调用前缀的记录不是可
|
|
742
|
+
// 独立恢复的 Tool;父 execute 才是唯一恢复边界。
|
|
743
|
+
if (codeModeParents.some((prefix) => tool.toolCallId.startsWith(prefix))) {
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
736
746
|
if (tool.result) {
|
|
737
747
|
const key = `tool:${tool.toolCallId}:settled`;
|
|
738
748
|
const plan = tool.needsContinuation
|
package/src/runtime-agent.ts
CHANGED
|
@@ -56,6 +56,7 @@ import type {
|
|
|
56
56
|
RuntimeAgentRole,
|
|
57
57
|
RuntimeAgentToolResult,
|
|
58
58
|
} from "./runtime-agent-context";
|
|
59
|
+
import type { AgentTelemetryBinding } from "./telemetry/contract";
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
62
|
* 本文件把应用提供的 Config Definition 与 Planner 接到 Cloudflare Agent 生命周期。
|
|
@@ -111,6 +112,11 @@ interface RuntimeAgentDefinitionBase<
|
|
|
111
112
|
| RuntimeAgentHooks<Env, Config, Command, Change>
|
|
112
113
|
| ((context: RuntimeAgentPlanningContext<Env, Command, Change>) =>
|
|
113
114
|
RuntimeAgentHooks<Env, Config, Command, Change>);
|
|
115
|
+
|
|
116
|
+
/** Prepare the optional telemetry consumer for this concrete Agent facet. */
|
|
117
|
+
readonly telemetry?: (
|
|
118
|
+
context: RuntimeAgentPlanningContext<Env, Command, Change>,
|
|
119
|
+
) => AgentTelemetryBinding | undefined;
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
export interface ReadonlyRuntimeAgentDefinition<
|
|
@@ -415,11 +421,23 @@ export function defineRuntimeAgent<
|
|
|
415
421
|
: hooks as RuntimeAgentHooks<Env, Config, Command, Change>;
|
|
416
422
|
};
|
|
417
423
|
|
|
424
|
+
const resolveDefinitionTelemetry = (
|
|
425
|
+
context: RuntimeAgentPlanningContext<Env, Command, Change>,
|
|
426
|
+
): AgentTelemetryBinding | undefined => {
|
|
427
|
+
const telemetry = definition.telemetry;
|
|
428
|
+
if (!telemetry) return undefined;
|
|
429
|
+
return (telemetry as (
|
|
430
|
+
context: RuntimeAgentPlanningContext<Env, Command, Change>,
|
|
431
|
+
) => AgentTelemetryBinding | undefined)(context);
|
|
432
|
+
};
|
|
433
|
+
|
|
418
434
|
const GeneratedRuntimeAgent = {
|
|
419
435
|
[definition.name]: class extends AgentToolRuntimeKernel<Env> {
|
|
420
436
|
private hasLoadedRuntime = false;
|
|
421
437
|
private loadedRuntimeKey?: string;
|
|
422
438
|
private loading?: Promise<void>;
|
|
439
|
+
private telemetryResolved = false;
|
|
440
|
+
private resolvedTelemetry?: AgentTelemetryBinding;
|
|
423
441
|
private temporaryLaunch?: TemporaryAgentLaunch<Config>;
|
|
424
442
|
private temporaryDispose?: () => Promise<void>;
|
|
425
443
|
private temporaryCleanup?: Promise<void>;
|
|
@@ -609,6 +627,11 @@ export function defineRuntimeAgent<
|
|
|
609
627
|
{ timeoutMs: RUNTIME_LOAD_TIMEOUT_MS },
|
|
610
628
|
));
|
|
611
629
|
let hooks = resolveDefinitionHooks(context);
|
|
630
|
+
if (!this.telemetryResolved) {
|
|
631
|
+
this.resolvedTelemetry = resolveDefinitionTelemetry(context);
|
|
632
|
+
this.telemetryResolved = true;
|
|
633
|
+
}
|
|
634
|
+
const telemetry = this.resolvedTelemetry;
|
|
612
635
|
if (this.role === "temporary") {
|
|
613
636
|
this.temporaryDispose = tools.dispose;
|
|
614
637
|
tools = this.applyTemporaryToolPolicy(tools);
|
|
@@ -620,6 +643,7 @@ export function defineRuntimeAgent<
|
|
|
620
643
|
tools,
|
|
621
644
|
resources: loaded.resources,
|
|
622
645
|
hooks,
|
|
646
|
+
...(telemetry ? { telemetry } : {}),
|
|
623
647
|
});
|
|
624
648
|
|
|
625
649
|
await this.initCandidate(candidate);
|
package/src/runtime-assembler.ts
CHANGED
|
@@ -61,6 +61,10 @@ import { skillPiToolCandidates } from "./pi/tool/skill";
|
|
|
61
61
|
import { createWebSearch } from "./pi/tool/web-search";
|
|
62
62
|
import { subagentPiToolCandidates } from "./pi/tool/subagent";
|
|
63
63
|
import { resolvePiModel } from "./pi/runtime-adapter/models";
|
|
64
|
+
import {
|
|
65
|
+
normalizeAgentTelemetryBinding,
|
|
66
|
+
type AgentTelemetryBinding,
|
|
67
|
+
} from "./telemetry/contract";
|
|
64
68
|
|
|
65
69
|
/** Runtime Assembler:校验一份扁平输入并生成可原子提交的 Snapshot。 */
|
|
66
70
|
|
|
@@ -92,6 +96,7 @@ export interface RuntimeAssemblyInput {
|
|
|
92
96
|
readonly subagents?: RuntimeSubagentPort;
|
|
93
97
|
readonly schedule?: RuntimeSchedulePort;
|
|
94
98
|
readonly turnEvents?: RuntimeTurnEventsPort;
|
|
99
|
+
readonly telemetry?: AgentTelemetryBinding;
|
|
95
100
|
readonly commitGuards: readonly (() => Promise<void>)[];
|
|
96
101
|
readonly degradations: readonly RuntimeDegradation[];
|
|
97
102
|
}
|
|
@@ -120,6 +125,7 @@ export interface RuntimeCandidate {
|
|
|
120
125
|
readonly commitGuards: readonly (() => Promise<void>)[];
|
|
121
126
|
readonly hooks?: RuntimeAgentHooks<Cloudflare.Env, unknown, never, never>;
|
|
122
127
|
readonly turnEvents?: RuntimeTurnEventsPort;
|
|
128
|
+
readonly telemetry?: AgentTelemetryBinding;
|
|
123
129
|
}
|
|
124
130
|
|
|
125
131
|
const DISABLED_MEMORY: RuntimeMemoryProfile = Object.freeze({
|
|
@@ -244,14 +250,10 @@ async function createToolSurface(
|
|
|
244
250
|
}
|
|
245
251
|
const mergeable = finalized.filter(
|
|
246
252
|
(candidate) =>
|
|
253
|
+
!candidate.direct &&
|
|
247
254
|
!candidate.interaction &&
|
|
248
255
|
typeof candidate.tool.execute === "function",
|
|
249
256
|
);
|
|
250
|
-
const direct = finalized.filter(
|
|
251
|
-
(candidate) =>
|
|
252
|
-
candidate.interaction ||
|
|
253
|
-
typeof candidate.tool.execute !== "function",
|
|
254
|
-
);
|
|
255
257
|
const codeExecutionTools = Object.freeze([...mergeable]);
|
|
256
258
|
return Object.freeze([
|
|
257
259
|
Object.freeze({
|
|
@@ -262,7 +264,7 @@ async function createToolSurface(
|
|
|
262
264
|
),
|
|
263
265
|
codeExecutionTools,
|
|
264
266
|
}),
|
|
265
|
-
...
|
|
267
|
+
...finalized,
|
|
266
268
|
]);
|
|
267
269
|
},
|
|
268
270
|
}),
|
|
@@ -304,6 +306,7 @@ class RuntimeBuilder {
|
|
|
304
306
|
private readonly enabledSubagents = new Set<string>();
|
|
305
307
|
private subagents?: RuntimeSubagentPort;
|
|
306
308
|
private turnEvents?: RuntimeTurnEventsPort;
|
|
309
|
+
private telemetry?: AgentTelemetryBinding;
|
|
307
310
|
private readonly commitGuards: Array<() => Promise<void>> = [];
|
|
308
311
|
private readonly degradations: RuntimeDegradation[] = [];
|
|
309
312
|
|
|
@@ -336,6 +339,9 @@ class RuntimeBuilder {
|
|
|
336
339
|
}
|
|
337
340
|
this.subagents = input.subagents;
|
|
338
341
|
this.turnEvents = input.turnEvents;
|
|
342
|
+
this.telemetry = input.telemetry
|
|
343
|
+
? normalizeAgentTelemetryBinding(input.telemetry)
|
|
344
|
+
: undefined;
|
|
339
345
|
this.commitGuards.push(...input.commitGuards);
|
|
340
346
|
}
|
|
341
347
|
|
|
@@ -564,6 +570,7 @@ class RuntimeBuilder {
|
|
|
564
570
|
commitGuards: Object.freeze([
|
|
565
571
|
...this.commitGuards,
|
|
566
572
|
]),
|
|
573
|
+
...(this.telemetry ? { telemetry: this.telemetry } : {}),
|
|
567
574
|
});
|
|
568
575
|
}
|
|
569
576
|
|
|
@@ -621,23 +628,28 @@ export function toolRegistryPiToolCandidates(
|
|
|
621
628
|
if (deny.has(name)) continue;
|
|
622
629
|
if (allowsTool?.(name) === false) continue;
|
|
623
630
|
const normalized = requiredName(name, "Platform Tool");
|
|
631
|
+
const {
|
|
632
|
+
label,
|
|
633
|
+
description,
|
|
634
|
+
parameters,
|
|
635
|
+
execute,
|
|
636
|
+
owner = "platform",
|
|
637
|
+
...metadata
|
|
638
|
+
} = spec;
|
|
624
639
|
candidates.push(Object.freeze({
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
...(spec.alwaysRequiresApproval
|
|
628
|
-
? { alwaysRequiresApproval: true }
|
|
629
|
-
: {}),
|
|
640
|
+
...metadata,
|
|
641
|
+
owner,
|
|
630
642
|
tool: Object.freeze({
|
|
631
643
|
name: normalized,
|
|
632
|
-
label
|
|
633
|
-
description
|
|
634
|
-
parameters
|
|
644
|
+
label,
|
|
645
|
+
description,
|
|
646
|
+
parameters,
|
|
635
647
|
async execute(
|
|
636
648
|
toolCallId: string,
|
|
637
649
|
input: unknown,
|
|
638
650
|
signal?: AbortSignal,
|
|
639
651
|
) {
|
|
640
|
-
const result = await
|
|
652
|
+
const result = await execute(input, {
|
|
641
653
|
toolCallId,
|
|
642
654
|
signal: signal ?? new AbortController().signal,
|
|
643
655
|
});
|
|
@@ -822,6 +834,7 @@ export async function assembleRuntimeSnapshot<
|
|
|
822
834
|
: {}),
|
|
823
835
|
extensions: resources.extensions,
|
|
824
836
|
...(turnEvents ? { turnEvents } : {}),
|
|
837
|
+
...(input.telemetry ? { telemetry: input.telemetry } : {}),
|
|
825
838
|
commitGuards: [],
|
|
826
839
|
degradations: [
|
|
827
840
|
...(toolAssembly.degradations ?? []),
|
|
@@ -848,6 +861,7 @@ export async function assembleRuntimeSnapshot<
|
|
|
848
861
|
}
|
|
849
862
|
: {}),
|
|
850
863
|
...(turnEvents ? { turnEvents } : {}),
|
|
864
|
+
...(candidate.telemetry ? { telemetry: candidate.telemetry } : {}),
|
|
851
865
|
});
|
|
852
866
|
}
|
|
853
867
|
|
|
@@ -27,6 +27,7 @@ import type {
|
|
|
27
27
|
RuntimeAssemblyContext,
|
|
28
28
|
RuntimeAgentPlanningContext,
|
|
29
29
|
} from "./runtime-agent-context";
|
|
30
|
+
import type { AgentTelemetryBinding } from "./telemetry/contract";
|
|
30
31
|
|
|
31
32
|
export interface RuntimeProfileContribution {
|
|
32
33
|
readonly model: string;
|
|
@@ -184,4 +185,5 @@ export interface AssembleRuntimeSnapshotInput<
|
|
|
184
185
|
readonly tools: import("./tool-registry").ToolAssemblyResult;
|
|
185
186
|
readonly resources: ResolvedResources;
|
|
186
187
|
readonly hooks?: RuntimeAgentHooks<Env, Config, Command, Change>;
|
|
188
|
+
readonly telemetry?: AgentTelemetryBinding;
|
|
187
189
|
}
|