@cognipeer/agent-sdk 0.16.0 → 0.17.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/dist/index.cjs +168 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.mjs +168 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1063,6 +1063,10 @@ type SubagentPendingRecord = {
|
|
|
1063
1063
|
/** Maps the child's pending approval/question id -> parent-surfaced id. */
|
|
1064
1064
|
pendingKind: "approval" | "user_question";
|
|
1065
1065
|
pendingId: string;
|
|
1066
|
+
/** The run's id on `subagent` events and in its trace; the resumed run keeps it. */
|
|
1067
|
+
spawnId?: string;
|
|
1068
|
+
/** Iterations the child had opened when it paused; the resumed run numbers on from there. */
|
|
1069
|
+
iterations?: number;
|
|
1066
1070
|
};
|
|
1067
1071
|
type SubagentToolNames = {
|
|
1068
1072
|
delegate: string;
|
|
@@ -2141,6 +2145,12 @@ type TraceSessionSummary = {
|
|
|
2141
2145
|
totalBytesIn: number;
|
|
2142
2146
|
totalBytesOut: number;
|
|
2143
2147
|
eventCounts: Record<string, number>;
|
|
2148
|
+
/**
|
|
2149
|
+
* Iterations run by sub-agents recording into this session. They count in
|
|
2150
|
+
* `eventCounts.agent_iteration` too; the root agent subtracts them to number
|
|
2151
|
+
* its own iterations.
|
|
2152
|
+
*/
|
|
2153
|
+
subagentIterations?: number;
|
|
2144
2154
|
};
|
|
2145
2155
|
/**
|
|
2146
2156
|
* `paused`: the run stopped to wait for a tool approval or an answer from the
|
|
@@ -2893,6 +2903,12 @@ type ToolCallContext = {
|
|
|
2893
2903
|
toolCallId?: string;
|
|
2894
2904
|
cancellationToken?: any;
|
|
2895
2905
|
signal?: AbortSignal;
|
|
2906
|
+
/**
|
|
2907
|
+
* Span id the tools node will give this call's `tool_call` trace event. Known
|
|
2908
|
+
* before the tool runs so that whatever it records (a sub-agent's spans) can
|
|
2909
|
+
* nest under it. Absent when the run is not traced.
|
|
2910
|
+
*/
|
|
2911
|
+
traceSpanId?: string;
|
|
2896
2912
|
};
|
|
2897
2913
|
type SmartToolFn = (args: any, context?: ToolCallContext) => Promise<any> | any;
|
|
2898
2914
|
type ToolCachePolicy = {
|
|
@@ -5595,7 +5611,11 @@ declare function recordTraceEvent(session: TraceSessionRuntime | undefined, even
|
|
|
5595
5611
|
status?: TraceEventRecord["status"];
|
|
5596
5612
|
/** Explicit parent span ID. Falls back to session.currentIterationSpanId when omitted. */
|
|
5597
5613
|
parentSpanId?: string;
|
|
5614
|
+
/** Pre-allocated span ID, for an event whose children are recorded before it is. */
|
|
5615
|
+
spanId?: string;
|
|
5598
5616
|
durationMs?: number;
|
|
5617
|
+
/** False for a span that wraps events already counted, so the totals do not take the time twice. */
|
|
5618
|
+
countDuration?: boolean;
|
|
5599
5619
|
inputTokens?: number;
|
|
5600
5620
|
outputTokens?: number;
|
|
5601
5621
|
totalTokens?: number;
|
|
@@ -5618,6 +5638,8 @@ declare function recordTraceEvent(session: TraceSessionRuntime | undefined, even
|
|
|
5618
5638
|
messageList?: any[];
|
|
5619
5639
|
/** Pre-built sections to use instead of auto-converting messageList */
|
|
5620
5640
|
sections?: TraceDataSection[];
|
|
5641
|
+
/** Identity sections kept even when logData is off; the caller vouches they carry no payload. */
|
|
5642
|
+
alwaysSections?: TraceDataSection[];
|
|
5621
5643
|
/**
|
|
5622
5644
|
* Tool MENU bound to this model call (`ai_call` events). Appended as a
|
|
5623
5645
|
* `tool_definitions` section AFTER messageList/sections resolution, so it
|
package/dist/index.d.ts
CHANGED
|
@@ -1063,6 +1063,10 @@ type SubagentPendingRecord = {
|
|
|
1063
1063
|
/** Maps the child's pending approval/question id -> parent-surfaced id. */
|
|
1064
1064
|
pendingKind: "approval" | "user_question";
|
|
1065
1065
|
pendingId: string;
|
|
1066
|
+
/** The run's id on `subagent` events and in its trace; the resumed run keeps it. */
|
|
1067
|
+
spawnId?: string;
|
|
1068
|
+
/** Iterations the child had opened when it paused; the resumed run numbers on from there. */
|
|
1069
|
+
iterations?: number;
|
|
1066
1070
|
};
|
|
1067
1071
|
type SubagentToolNames = {
|
|
1068
1072
|
delegate: string;
|
|
@@ -2141,6 +2145,12 @@ type TraceSessionSummary = {
|
|
|
2141
2145
|
totalBytesIn: number;
|
|
2142
2146
|
totalBytesOut: number;
|
|
2143
2147
|
eventCounts: Record<string, number>;
|
|
2148
|
+
/**
|
|
2149
|
+
* Iterations run by sub-agents recording into this session. They count in
|
|
2150
|
+
* `eventCounts.agent_iteration` too; the root agent subtracts them to number
|
|
2151
|
+
* its own iterations.
|
|
2152
|
+
*/
|
|
2153
|
+
subagentIterations?: number;
|
|
2144
2154
|
};
|
|
2145
2155
|
/**
|
|
2146
2156
|
* `paused`: the run stopped to wait for a tool approval or an answer from the
|
|
@@ -2893,6 +2903,12 @@ type ToolCallContext = {
|
|
|
2893
2903
|
toolCallId?: string;
|
|
2894
2904
|
cancellationToken?: any;
|
|
2895
2905
|
signal?: AbortSignal;
|
|
2906
|
+
/**
|
|
2907
|
+
* Span id the tools node will give this call's `tool_call` trace event. Known
|
|
2908
|
+
* before the tool runs so that whatever it records (a sub-agent's spans) can
|
|
2909
|
+
* nest under it. Absent when the run is not traced.
|
|
2910
|
+
*/
|
|
2911
|
+
traceSpanId?: string;
|
|
2896
2912
|
};
|
|
2897
2913
|
type SmartToolFn = (args: any, context?: ToolCallContext) => Promise<any> | any;
|
|
2898
2914
|
type ToolCachePolicy = {
|
|
@@ -5595,7 +5611,11 @@ declare function recordTraceEvent(session: TraceSessionRuntime | undefined, even
|
|
|
5595
5611
|
status?: TraceEventRecord["status"];
|
|
5596
5612
|
/** Explicit parent span ID. Falls back to session.currentIterationSpanId when omitted. */
|
|
5597
5613
|
parentSpanId?: string;
|
|
5614
|
+
/** Pre-allocated span ID, for an event whose children are recorded before it is. */
|
|
5615
|
+
spanId?: string;
|
|
5598
5616
|
durationMs?: number;
|
|
5617
|
+
/** False for a span that wraps events already counted, so the totals do not take the time twice. */
|
|
5618
|
+
countDuration?: boolean;
|
|
5599
5619
|
inputTokens?: number;
|
|
5600
5620
|
outputTokens?: number;
|
|
5601
5621
|
totalTokens?: number;
|
|
@@ -5618,6 +5638,8 @@ declare function recordTraceEvent(session: TraceSessionRuntime | undefined, even
|
|
|
5618
5638
|
messageList?: any[];
|
|
5619
5639
|
/** Pre-built sections to use instead of auto-converting messageList */
|
|
5620
5640
|
sections?: TraceDataSection[];
|
|
5641
|
+
/** Identity sections kept even when logData is off; the caller vouches they carry no payload. */
|
|
5642
|
+
alwaysSections?: TraceDataSection[];
|
|
5621
5643
|
/**
|
|
5622
5644
|
* Tool MENU bound to this model call (`ai_call` events). Appended as a
|
|
5623
5645
|
* `tool_definitions` section AFTER messageList/sections resolution, so it
|
package/dist/index.mjs
CHANGED
|
@@ -2203,7 +2203,7 @@ function recordTraceEvent(session, event) {
|
|
|
2203
2203
|
const baseLabel = event.label?.trim().length ? event.label.trim() : defaultEventLabel(event.type);
|
|
2204
2204
|
const eventLabel = `${baseLabel} #${sequence}`;
|
|
2205
2205
|
const durationMs = event.durationMs !== void 0 ? Number(event.durationMs) : void 0;
|
|
2206
|
-
if (!Number.isNaN(durationMs ?? NaN) && durationMs !== void 0) {
|
|
2206
|
+
if (!Number.isNaN(durationMs ?? NaN) && durationMs !== void 0 && event.countDuration !== false && !isSubagentTraceScope(session)) {
|
|
2207
2207
|
session.summary.totalDurationMs += durationMs;
|
|
2208
2208
|
}
|
|
2209
2209
|
const inputTokens = event.inputTokens !== void 0 ? Number(event.inputTokens) : void 0;
|
|
@@ -2252,10 +2252,13 @@ function recordTraceEvent(session, event) {
|
|
|
2252
2252
|
}
|
|
2253
2253
|
}
|
|
2254
2254
|
}
|
|
2255
|
+
if (event.alwaysSections?.length) {
|
|
2256
|
+
sections = ensureUniqueSections(id, [...event.alwaysSections, ...sections ?? []]);
|
|
2257
|
+
}
|
|
2255
2258
|
const resolvedModel = event.model ?? inferModelFromMessages(event.messageList);
|
|
2256
2259
|
const resolvedProvider = event.provider ?? inferProviderFromMessages(event.messageList);
|
|
2257
2260
|
const isAiCall = event.type === "ai_call";
|
|
2258
|
-
const spanId = generateSpanId();
|
|
2261
|
+
const spanId = event.spanId || generateSpanId();
|
|
2259
2262
|
const parentSpanId = event.parentSpanId || session.currentIterationSpanId || session.rootSpanId;
|
|
2260
2263
|
const record = {
|
|
2261
2264
|
sessionId: session.sessionId,
|
|
@@ -2349,6 +2352,58 @@ var DEFERRED_TRACE_EVENTS_KEY = "__deferredTraceEvents";
|
|
|
2349
2352
|
function isTraceSessionOpen(session) {
|
|
2350
2353
|
return Boolean(session) && !session.closed;
|
|
2351
2354
|
}
|
|
2355
|
+
var SUBAGENT_TRACE_SCOPE = Symbol("subagentTraceScope");
|
|
2356
|
+
function createSubagentTraceScope(parent, info) {
|
|
2357
|
+
const scope = { ...info, iterations: info.iterations ?? 0 };
|
|
2358
|
+
let currentIterationSpanId;
|
|
2359
|
+
return new Proxy(parent, {
|
|
2360
|
+
get(target, prop) {
|
|
2361
|
+
if (prop === SUBAGENT_TRACE_SCOPE) return scope;
|
|
2362
|
+
if (prop === "rootSpanId") return scope.agentSpanId;
|
|
2363
|
+
if (prop === "currentIterationSpanId") return currentIterationSpanId;
|
|
2364
|
+
return Reflect.get(target, prop);
|
|
2365
|
+
},
|
|
2366
|
+
set(target, prop, value) {
|
|
2367
|
+
if (prop === "currentIterationSpanId") {
|
|
2368
|
+
currentIterationSpanId = value;
|
|
2369
|
+
return true;
|
|
2370
|
+
}
|
|
2371
|
+
return Reflect.set(target, prop, value);
|
|
2372
|
+
}
|
|
2373
|
+
});
|
|
2374
|
+
}
|
|
2375
|
+
function subagentTraceScopeOf(session) {
|
|
2376
|
+
if (!session) return void 0;
|
|
2377
|
+
return session[SUBAGENT_TRACE_SCOPE];
|
|
2378
|
+
}
|
|
2379
|
+
function canPauseForHuman(session) {
|
|
2380
|
+
return subagentTraceScopeOf(session)?.hitl !== false;
|
|
2381
|
+
}
|
|
2382
|
+
function isSubagentTraceScope(session) {
|
|
2383
|
+
return subagentTraceScopeOf(session) !== void 0;
|
|
2384
|
+
}
|
|
2385
|
+
function recordSubagentSpan(session, span) {
|
|
2386
|
+
const sections = [];
|
|
2387
|
+
if (session.resolvedConfig.logData) {
|
|
2388
|
+
if (span.task !== void 0) sections.push({ kind: "message", label: "Task", role: "user", content: span.task });
|
|
2389
|
+
if (span.result) sections.push({ kind: "message", label: "Result", role: "assistant", content: span.result });
|
|
2390
|
+
}
|
|
2391
|
+
recordTraceEvent(session, {
|
|
2392
|
+
type: "span",
|
|
2393
|
+
spanId: span.spanId,
|
|
2394
|
+
parentSpanId: span.parentSpanId,
|
|
2395
|
+
label: `Sub-agent ${span.name}`,
|
|
2396
|
+
actor: { scope: "agent", name: span.name, role: "subagent" },
|
|
2397
|
+
status: span.status,
|
|
2398
|
+
durationMs: span.durationMs,
|
|
2399
|
+
// The child's own calls and the delegating tool_call already hold this time.
|
|
2400
|
+
countDuration: false,
|
|
2401
|
+
...span.error ? { error: { message: span.error } } : {},
|
|
2402
|
+
// The Console reads which sub-agent ran from here, so it survives logData off.
|
|
2403
|
+
alwaysSections: [{ kind: "metadata", label: "Sub-agent", data: sanitizeTracePayload(span.info) }],
|
|
2404
|
+
sections
|
|
2405
|
+
});
|
|
2406
|
+
}
|
|
2352
2407
|
function recordOrDeferTraceEvent(ctx, event, options) {
|
|
2353
2408
|
const session = ctx?.__traceSession;
|
|
2354
2409
|
if (isTraceSessionOpen(session)) {
|
|
@@ -4926,6 +4981,9 @@ ${append}`;
|
|
|
4926
4981
|
|
|
4927
4982
|
// src/utils/traceDecisions.ts
|
|
4928
4983
|
var TRACED_KEY = "__outcomeTraced";
|
|
4984
|
+
function surfacedFromSubagent(entry) {
|
|
4985
|
+
return Boolean(entry.metadata?.__subagent);
|
|
4986
|
+
}
|
|
4929
4987
|
function waitedMs(from, to) {
|
|
4930
4988
|
if (!from || !to) return void 0;
|
|
4931
4989
|
const ms = Date.parse(to) - Date.parse(from);
|
|
@@ -4939,7 +4997,7 @@ function sameJson(a, b) {
|
|
|
4939
4997
|
}
|
|
4940
4998
|
}
|
|
4941
4999
|
function recordApprovalRequested(session, entry) {
|
|
4942
|
-
if (!session) return;
|
|
5000
|
+
if (!session || surfacedFromSubagent(entry) || !canPauseForHuman(session)) return;
|
|
4943
5001
|
const logData = session.resolvedConfig.logData;
|
|
4944
5002
|
const sections = [
|
|
4945
5003
|
{
|
|
@@ -4970,7 +5028,7 @@ function recordHumanDecisions(session, state) {
|
|
|
4970
5028
|
if (!session) return;
|
|
4971
5029
|
const logData = session.resolvedConfig.logData;
|
|
4972
5030
|
for (const entry of state.pendingApprovals ?? []) {
|
|
4973
|
-
if (!entry.decidedAt || entry.metadata?.[TRACED_KEY]) continue;
|
|
5031
|
+
if (!entry.decidedAt || entry.metadata?.[TRACED_KEY] || surfacedFromSubagent(entry)) continue;
|
|
4974
5032
|
if (entry.status !== "approved" && entry.status !== "rejected") continue;
|
|
4975
5033
|
const approved = entry.status === "approved";
|
|
4976
5034
|
const edited = approved && entry.approvedArgs !== void 0 && !sameJson(entry.approvedArgs, entry.args);
|
|
@@ -5009,7 +5067,7 @@ function recordHumanDecisions(session, state) {
|
|
|
5009
5067
|
entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
|
|
5010
5068
|
}
|
|
5011
5069
|
for (const entry of state.pendingUserQuestions ?? []) {
|
|
5012
|
-
if (!entry.answeredAt || entry.metadata?.[TRACED_KEY]) continue;
|
|
5070
|
+
if (!entry.answeredAt || entry.metadata?.[TRACED_KEY] || surfacedFromSubagent(entry)) continue;
|
|
5013
5071
|
if (entry.status !== "answered" && entry.status !== "cancelled") continue;
|
|
5014
5072
|
const clientTool = readClientTool(entry);
|
|
5015
5073
|
if (clientTool) {
|
|
@@ -5055,7 +5113,7 @@ function recordHumanDecisions(session, state) {
|
|
|
5055
5113
|
}
|
|
5056
5114
|
}
|
|
5057
5115
|
function recordClientToolRequested(session, entry) {
|
|
5058
|
-
if (!session) return;
|
|
5116
|
+
if (!session || surfacedFromSubagent(entry) || !canPauseForHuman(session)) return;
|
|
5059
5117
|
const clientTool = readClientTool(entry);
|
|
5060
5118
|
if (!clientTool) return;
|
|
5061
5119
|
const sections = [
|
|
@@ -5711,6 +5769,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
5711
5769
|
toolCount += 1;
|
|
5712
5770
|
return { status: "error" };
|
|
5713
5771
|
}
|
|
5772
|
+
let traceSpanId;
|
|
5714
5773
|
try {
|
|
5715
5774
|
if (cachedHit !== void 0) {
|
|
5716
5775
|
const executionId2 = nanoid();
|
|
@@ -5790,7 +5849,8 @@ function createToolsNode(initialTools, opts) {
|
|
|
5790
5849
|
onEvent?.({ type: "tool_call", phase: "start", name: toolName, id: tc.id, args });
|
|
5791
5850
|
onProgress?.({ stage: "tools", message: `Running tool ${tc.name}` });
|
|
5792
5851
|
const anyTool = tool;
|
|
5793
|
-
|
|
5852
|
+
traceSpanId = traceSession ? generateSpanId() : void 0;
|
|
5853
|
+
const callOptions = { cancellationToken, signal: abortSignal, toolCallId, ...traceSpanId ? { traceSpanId } : {} };
|
|
5794
5854
|
const invokeOnce = async () => {
|
|
5795
5855
|
if (typeof anyTool.func === "function") return anyTool.func(args, callOptions);
|
|
5796
5856
|
if (typeof anyTool.invoke === "function") return anyTool.invoke(args, callOptions);
|
|
@@ -5973,6 +6033,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
5973
6033
|
const outputBytes = traceSession?.resolvedConfig.logData ? estimatePayloadBytes(sanitizedOutput) : void 0;
|
|
5974
6034
|
recordTraceEvent(traceSession, {
|
|
5975
6035
|
type: "tool_call",
|
|
6036
|
+
spanId: traceSpanId,
|
|
5976
6037
|
label: `Tool Execution - ${toolName}`,
|
|
5977
6038
|
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
5978
6039
|
...reportedFailure ? { status: "error", error: { message: reportedFailure } } : {},
|
|
@@ -6035,6 +6096,7 @@ function createToolsNode(initialTools, opts) {
|
|
|
6035
6096
|
const errorOutput = { message, stack: host?.has("postToolUse") ? void 0 : error?.stack };
|
|
6036
6097
|
recordTraceEvent(traceSession, {
|
|
6037
6098
|
type: "tool_call",
|
|
6099
|
+
spanId: traceSpanId,
|
|
6038
6100
|
label: `Tool Error - ${toolName}`,
|
|
6039
6101
|
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
6040
6102
|
status: "error",
|
|
@@ -6995,7 +7057,7 @@ function createAskUserQuestionTool(stateRef, config) {
|
|
|
6995
7057
|
questions: entry.questions,
|
|
6996
7058
|
allowFreeText
|
|
6997
7059
|
});
|
|
6998
|
-
recordTraceEvent(ctx.__traceSession, {
|
|
7060
|
+
if (canPauseForHuman(ctx.__traceSession)) recordTraceEvent(ctx.__traceSession, {
|
|
6999
7061
|
type: "user_question",
|
|
7000
7062
|
label: "Question to user",
|
|
7001
7063
|
timestamp: entry.requestedAt,
|
|
@@ -8278,19 +8340,22 @@ function createAgent(opts) {
|
|
|
8278
8340
|
detail: { reason: budget.reason, iteration: iterations }
|
|
8279
8341
|
});
|
|
8280
8342
|
}
|
|
8343
|
+
recordHumanDecisions(state.ctx?.__traceSession, state);
|
|
8281
8344
|
const ctx = { ...state.ctx || {}, __limitBreached: budget.reason };
|
|
8282
8345
|
state = { ...state, ctx };
|
|
8283
8346
|
break;
|
|
8284
8347
|
}
|
|
8285
8348
|
const traceSession = state.ctx?.__traceSession;
|
|
8286
8349
|
if (traceSession) {
|
|
8287
|
-
const
|
|
8350
|
+
const subagentScope = subagentTraceScopeOf(traceSession);
|
|
8351
|
+
const iterationNumber = subagentScope ? ++subagentScope.iterations : (traceSession.summary.eventCounts.agent_iteration ?? 0) - (traceSession.summary.subagentIterations ?? 0) + 1;
|
|
8288
8352
|
const iterEvent = recordTraceEvent(traceSession, {
|
|
8289
8353
|
type: "agent_iteration",
|
|
8290
8354
|
label: `Iteration ${iterationNumber}`,
|
|
8291
8355
|
actor: { scope: "agent", name: opts.name || "agent", role: "orchestrator" },
|
|
8292
8356
|
parentSpanId: traceSession.rootSpanId
|
|
8293
8357
|
});
|
|
8358
|
+
if (subagentScope) traceSession.summary.subagentIterations = (traceSession.summary.subagentIterations ?? 0) + 1;
|
|
8294
8359
|
if (iterEvent) {
|
|
8295
8360
|
traceSession.currentIterationSpanId = iterEvent.spanId;
|
|
8296
8361
|
}
|
|
@@ -8600,7 +8665,9 @@ function createAgent(opts) {
|
|
|
8600
8665
|
const inheritedSession = config?.__pluginSession;
|
|
8601
8666
|
ctx.__runId = inheritedSession?.runId ?? traceSession?.sessionId ?? `run_${nanoid(10)}`;
|
|
8602
8667
|
const stateHolder = inheritedSession?.stateHolder ?? { value: void 0 };
|
|
8603
|
-
const traceRecorder = createPluginTraceRecorder(
|
|
8668
|
+
const traceRecorder = createPluginTraceRecorder(
|
|
8669
|
+
() => traceSession ?? (subagentTraceScopeOf(ctx.__traceSession) ? ctx.__traceSession : void 0)
|
|
8670
|
+
);
|
|
8604
8671
|
const runHost = inheritedSession?.host ?? (pluginHost.hasAny() ? pluginHost.beginRun({
|
|
8605
8672
|
runId: ctx.__runId,
|
|
8606
8673
|
agentName: opts.name,
|
|
@@ -8843,7 +8910,7 @@ function createAgent(opts) {
|
|
|
8843
8910
|
name: toolName,
|
|
8844
8911
|
description: description || `Delegate task to agent ${opts.name || "Agent"}`,
|
|
8845
8912
|
schema,
|
|
8846
|
-
func: async ({ input }) => {
|
|
8913
|
+
func: async ({ input }, context) => {
|
|
8847
8914
|
const ref = delegatedTool._stateRef;
|
|
8848
8915
|
const parentCtx = ref.ctx || {};
|
|
8849
8916
|
const parentMessages = Array.isArray(ref.messages) ? ref.messages : [];
|
|
@@ -8876,6 +8943,33 @@ function createAgent(opts) {
|
|
|
8876
8943
|
input
|
|
8877
8944
|
);
|
|
8878
8945
|
const childCtx = { __delegationDepth: currentDepth + 1 };
|
|
8946
|
+
const parentSession = parentCtx.__traceSession;
|
|
8947
|
+
const traced = isTraceSessionOpen(parentSession);
|
|
8948
|
+
const agentSpanId = generateSpanId();
|
|
8949
|
+
const parentIterationSpanId = traced ? parentSession.currentIterationSpanId : void 0;
|
|
8950
|
+
if (traced && !withDefaults(opts.tracing).enabled) {
|
|
8951
|
+
childCtx.__traceSession = createSubagentTraceScope(parentSession, {
|
|
8952
|
+
agentSpanId,
|
|
8953
|
+
name: opts.name || "agent",
|
|
8954
|
+
mode: "asTool",
|
|
8955
|
+
hitl: false
|
|
8956
|
+
});
|
|
8957
|
+
}
|
|
8958
|
+
const startedAt = Date.now();
|
|
8959
|
+
const recordSpan = (status, extra) => {
|
|
8960
|
+
if (!traced || !isTraceSessionOpen(parentSession)) return;
|
|
8961
|
+
recordSubagentSpan(parentSession, {
|
|
8962
|
+
spanId: agentSpanId,
|
|
8963
|
+
parentSpanId: context?.traceSpanId ?? parentIterationSpanId,
|
|
8964
|
+
name: opts.name || "agent",
|
|
8965
|
+
status,
|
|
8966
|
+
durationMs: Date.now() - startedAt,
|
|
8967
|
+
error: extra.error,
|
|
8968
|
+
info: { name: opts.name || "agent", mode: "asTool", depth: currentDepth + 1, parentToolCallId: context?.toolCallId, status: status === "success" ? "ok" : "error" },
|
|
8969
|
+
task: input,
|
|
8970
|
+
result: extra.result
|
|
8971
|
+
});
|
|
8972
|
+
};
|
|
8879
8973
|
const childConfig = {
|
|
8880
8974
|
onEvent: parentCtx.__onEvent ? (e) => {
|
|
8881
8975
|
if (e?.type === "finalAnswer" || e?.type === "metadata") return;
|
|
@@ -8891,7 +8985,14 @@ function createAgent(opts) {
|
|
|
8891
8985
|
stream: Boolean(parentCtx.__streaming),
|
|
8892
8986
|
cancellationToken: parentCtx.__cancellationToken ?? parentCtx.__abortSignal
|
|
8893
8987
|
};
|
|
8894
|
-
|
|
8988
|
+
let res;
|
|
8989
|
+
try {
|
|
8990
|
+
res = await instance.invoke({ messages: childMessages, ctx: childCtx }, childConfig);
|
|
8991
|
+
} catch (err) {
|
|
8992
|
+
recordSpan("error", { error: err?.message || String(err) });
|
|
8993
|
+
throw err;
|
|
8994
|
+
}
|
|
8995
|
+
recordSpan("success", { result: res.content });
|
|
8895
8996
|
return {
|
|
8896
8997
|
content: res.content,
|
|
8897
8998
|
output: res.output,
|
|
@@ -11054,11 +11155,42 @@ function mergeChildUsage(ref, childState, baseline, tag) {
|
|
|
11054
11155
|
async function runChild(spec, input, deps, ref, opts) {
|
|
11055
11156
|
const parentCtx = ref.ctx || {};
|
|
11056
11157
|
const parentOnEvent = parentCtx.__onEvent;
|
|
11057
|
-
const spawnId = `sa_${nanoid(6)}`;
|
|
11158
|
+
const spawnId = opts.record?.spawnId ?? `sa_${nanoid(6)}`;
|
|
11058
11159
|
const start = Date.now();
|
|
11059
11160
|
const usageTag = { name: spec.name, id: spawnId, mode: spec.mode };
|
|
11060
11161
|
const parentHost = parentCtx.__plugins;
|
|
11061
11162
|
const childDepth = (Number(parentCtx.__delegationDepth) || 0) + 1;
|
|
11163
|
+
const parentSession = parentCtx.__traceSession;
|
|
11164
|
+
const traced = isTraceSessionOpen(parentSession);
|
|
11165
|
+
const agentSpanId = generateSpanId();
|
|
11166
|
+
const parentIterationSpanId = traced ? parentSession.currentIterationSpanId : void 0;
|
|
11167
|
+
const traceScope = traced ? createSubagentTraceScope(parentSession, { agentSpanId, name: spec.name, spawnId, mode: spec.mode, hitl: opts.allowHITL, iterations: opts.record?.iterations }) : void 0;
|
|
11168
|
+
const recordSegment = (status, info) => {
|
|
11169
|
+
if (!traced || !isTraceSessionOpen(parentSession)) return;
|
|
11170
|
+
recordSubagentSpan(parentSession, {
|
|
11171
|
+
spanId: agentSpanId,
|
|
11172
|
+
// The tool_call span only exists once the tool returns; a paused child
|
|
11173
|
+
// has not returned, so its span hangs off the iteration.
|
|
11174
|
+
parentSpanId: status === "pending" ? parentIterationSpanId : opts.parentSpanId ?? parentIterationSpanId,
|
|
11175
|
+
name: spec.name,
|
|
11176
|
+
status,
|
|
11177
|
+
durationMs: Date.now() - start,
|
|
11178
|
+
error: info.error,
|
|
11179
|
+
info: {
|
|
11180
|
+
id: spawnId,
|
|
11181
|
+
name: spec.name,
|
|
11182
|
+
mode: spec.mode,
|
|
11183
|
+
parallel: opts.parallel,
|
|
11184
|
+
depth: childDepth,
|
|
11185
|
+
parentToolCallId: opts.parentToolCallId,
|
|
11186
|
+
status: info.subagentStatus,
|
|
11187
|
+
...info.note ? { note: info.note } : {},
|
|
11188
|
+
...spec.metadata ? { metadata: spec.metadata } : {}
|
|
11189
|
+
},
|
|
11190
|
+
task: info.input,
|
|
11191
|
+
result: info.content
|
|
11192
|
+
});
|
|
11193
|
+
};
|
|
11062
11194
|
const emitStart = (task) => {
|
|
11063
11195
|
parentOnEvent?.({ type: "subagent", phase: "start", name: spec.name, id: spawnId, mode: spec.mode, parallel: opts.parallel, parentToolCallId: opts.parentToolCallId, input: task });
|
|
11064
11196
|
};
|
|
@@ -11066,6 +11198,15 @@ async function runChild(spec, input, deps, ref, opts) {
|
|
|
11066
11198
|
result2.durationMs ?? (result2.durationMs = Date.now() - start);
|
|
11067
11199
|
deps.registryRef.results.push(result2);
|
|
11068
11200
|
const message = result2.error || result2.note || result2.status;
|
|
11201
|
+
const traceStatus = result2.status === "ok" || result2.status === "incomplete" ? "success" : result2.status === "blocked" ? "skipped" : "error";
|
|
11202
|
+
recordSegment(traceStatus, {
|
|
11203
|
+
subagentStatus: result2.status,
|
|
11204
|
+
input,
|
|
11205
|
+
// `message` falls back to the status itself ("ok"): only a failed or refused run has an error to show.
|
|
11206
|
+
error: traceStatus === "success" ? void 0 : message,
|
|
11207
|
+
note: result2.note,
|
|
11208
|
+
content: result2.content
|
|
11209
|
+
});
|
|
11069
11210
|
parentOnEvent?.({
|
|
11070
11211
|
type: "subagent",
|
|
11071
11212
|
phase: FAILED_STATUSES.has(result2.status) ? "error" : "result",
|
|
@@ -11164,6 +11305,7 @@ async function runChild(spec, input, deps, ref, opts) {
|
|
|
11164
11305
|
ctx: { __delegationDepth: currentDepth + 1 }
|
|
11165
11306
|
};
|
|
11166
11307
|
}
|
|
11308
|
+
if (traceScope) childInput = { ...childInput, ctx: { ...childInput.ctx || {}, __traceSession: traceScope } };
|
|
11167
11309
|
const usageBaseline = childInput.usage?.perRequest?.length ?? 0;
|
|
11168
11310
|
let res;
|
|
11169
11311
|
try {
|
|
@@ -11204,8 +11346,11 @@ async function runChild(spec, input, deps, ref, opts) {
|
|
|
11204
11346
|
input,
|
|
11205
11347
|
childState: cleanChildState(childState),
|
|
11206
11348
|
pendingKind: "approval",
|
|
11207
|
-
pendingId: childEntry.id
|
|
11349
|
+
pendingId: childEntry.id,
|
|
11350
|
+
spawnId,
|
|
11351
|
+
iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0
|
|
11208
11352
|
};
|
|
11353
|
+
recordSegment("pending", { subagentStatus: "paused", input });
|
|
11209
11354
|
parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
|
|
11210
11355
|
return { kind: "approval", toolCallId: surfaced.toolCallId, approvalId: surfaced.id };
|
|
11211
11356
|
}
|
|
@@ -11227,8 +11372,11 @@ async function runChild(spec, input, deps, ref, opts) {
|
|
|
11227
11372
|
input,
|
|
11228
11373
|
childState: cleanChildState(childState),
|
|
11229
11374
|
pendingKind: "user_question",
|
|
11230
|
-
pendingId: childEntry.id
|
|
11375
|
+
pendingId: childEntry.id,
|
|
11376
|
+
spawnId,
|
|
11377
|
+
iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0
|
|
11231
11378
|
};
|
|
11379
|
+
recordSegment("pending", { subagentStatus: "paused", input });
|
|
11232
11380
|
parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
|
|
11233
11381
|
return { kind: "user_question", toolCallId: surfaced.toolCallId, id: surfaced.id };
|
|
11234
11382
|
}
|
|
@@ -11332,7 +11480,7 @@ function createDelegateTool(deps) {
|
|
|
11332
11480
|
if (!budget.ok) return refusal(budget.reason);
|
|
11333
11481
|
d.registryRef.spawnedCount += 1;
|
|
11334
11482
|
}
|
|
11335
|
-
return toToolReturn(await runChild(spec, record?.input ?? input, d, ref, { allowHITL: true, parentToolCallId, isResume: !!record, record, reserved: !record }));
|
|
11483
|
+
return toToolReturn(await runChild(spec, record?.input ?? input, d, ref, { allowHITL: true, parentToolCallId, isResume: !!record, record, reserved: !record, parentSpanId: context?.traceSpanId }));
|
|
11336
11484
|
}
|
|
11337
11485
|
});
|
|
11338
11486
|
tool._deps = deps;
|
|
@@ -11377,7 +11525,7 @@ function createSpawnTool(deps) {
|
|
|
11377
11525
|
if (!budget.ok) return refusal(budget.reason);
|
|
11378
11526
|
d.registryRef.spawnedCount += 1;
|
|
11379
11527
|
}
|
|
11380
|
-
return toToolReturn(await runChild(spec, record?.input ?? args.input, d, ref, { allowHITL: true, parentToolCallId, isResume: !!record, record, reserved: !record }));
|
|
11528
|
+
return toToolReturn(await runChild(spec, record?.input ?? args.input, d, ref, { allowHITL: true, parentToolCallId, isResume: !!record, record, reserved: !record, parentSpanId: context?.traceSpanId }));
|
|
11381
11529
|
}
|
|
11382
11530
|
});
|
|
11383
11531
|
tool._deps = deps;
|
|
@@ -11460,7 +11608,8 @@ function createParallelTool(deps) {
|
|
|
11460
11608
|
allowHITL: false,
|
|
11461
11609
|
parentToolCallId: `${parentToolCallId}#${i}`,
|
|
11462
11610
|
parallel: true,
|
|
11463
|
-
reserved: true
|
|
11611
|
+
reserved: true,
|
|
11612
|
+
parentSpanId: context?.traceSpanId
|
|
11464
11613
|
});
|
|
11465
11614
|
results[i] = outcome.kind === "result" ? outcome.result : { name: entry.spec.name, mode: entry.spec.mode, status: "error", input: entry.input, error: "Unexpected pause in parallel child." };
|
|
11466
11615
|
}
|
|
@@ -15755,6 +15904,7 @@ function otelTracing(config) {
|
|
|
15755
15904
|
sessionEnd: async ({ status, durationMs, error }, ctx) => {
|
|
15756
15905
|
const state = ctx.state;
|
|
15757
15906
|
const session = state.ctx?.__traceSession;
|
|
15907
|
+
if (isSubagentTraceScope(session)) return;
|
|
15758
15908
|
if (!session) {
|
|
15759
15909
|
const message = "otelTracing exported nothing: the agent has no trace session. Enable the SDK's tracing runtime with `tracing: { enabled: true }` \u2014 the plugin exports the session the runtime records, it does not record one itself.";
|
|
15760
15910
|
ctx.logger.warn(message);
|