@springbrand/agent-runtime 0.2.0-alpha.38 → 0.2.0-alpha.39

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@springbrand/agent-runtime",
3
- "version": "0.2.0-alpha.38",
3
+ "version": "0.2.0-alpha.39",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src",
@@ -543,6 +543,25 @@ export interface CreatePreparedPiTurnOptions {
543
543
  readonly durability: PiTurnDurability;
544
544
  /** Reports paired model-generation lifecycle facts to the Runtime owner. */
545
545
  readonly onGeneration?: PiGenerationLifecycleObserver;
546
+ /** Reports Code Mode child Tool starts without adding Pi recovery state. */
547
+ readonly onNestedToolStarted?: (input: Readonly<{
548
+ parentToolCallId: string;
549
+ toolCallId: string;
550
+ toolName: string;
551
+ input: unknown;
552
+ occurredAt: number;
553
+ }>) => void;
554
+ /** Reports Code Mode child Tool outcomes without adding Pi settlements. */
555
+ readonly onNestedToolFinished?: (input: Readonly<{
556
+ parentToolCallId: string;
557
+ toolCallId: string;
558
+ toolName: string;
559
+ outcome: "completed" | "failed" | "cancelled";
560
+ durationMs: number;
561
+ output?: import("@earendil-works/pi-agent-core").AgentToolResult<unknown>;
562
+ error?: unknown;
563
+ occurredAt: number;
564
+ }>) => void;
546
565
  /** Per-Submission executors for tools whose metadata is fixed at assembly time. */
547
566
  readonly toolExecutors?: Readonly<Record<
548
567
  string,
@@ -634,6 +653,7 @@ export class PreparedPiTurnAdapter {
634
653
  private readonly turn: PiTurnAdapter;
635
654
  private readonly abortController = new AbortController();
636
655
  private readonly candidates: readonly PiToolCandidate[];
656
+ private nestedToolOrdinal = 0;
637
657
  private assistantOrdinal: number;
638
658
  private readonly encoder: PiChunkEncoder;
639
659
  private readonly steerMessageIds: string[] = [];
@@ -805,12 +825,44 @@ export class PreparedPiTurnAdapter {
805
825
  }
806
826
  const execute = options.toolExecutors?.[candidate.tool.name] ??
807
827
  candidate.tool.execute;
808
- return execute(
809
- toolCallId,
828
+ if (recordRecoveryAttempt || !toolCallIdPrefix) {
829
+ return execute(toolCallId, input, signal, onUpdate);
830
+ }
831
+ const startedAt = Date.now();
832
+ const telemetryToolCallId = `${toolCallId}:${++this.nestedToolOrdinal}`;
833
+ options.onNestedToolStarted?.({
834
+ parentToolCallId: toolCallIdPrefix,
835
+ toolCallId: telemetryToolCallId,
836
+ toolName: candidate.tool.name,
810
837
  input,
811
- signal,
812
- onUpdate,
813
- );
838
+ occurredAt: startedAt,
839
+ });
840
+ try {
841
+ const output = await execute(toolCallId, input, signal, onUpdate);
842
+ const occurredAt = Date.now();
843
+ options.onNestedToolFinished?.({
844
+ parentToolCallId: toolCallIdPrefix,
845
+ toolCallId: telemetryToolCallId,
846
+ toolName: candidate.tool.name,
847
+ outcome: "completed",
848
+ durationMs: occurredAt - startedAt,
849
+ output,
850
+ occurredAt,
851
+ });
852
+ return output;
853
+ } catch (error) {
854
+ const occurredAt = Date.now();
855
+ options.onNestedToolFinished?.({
856
+ parentToolCallId: toolCallIdPrefix,
857
+ toolCallId: telemetryToolCallId,
858
+ toolName: candidate.tool.name,
859
+ outcome: signal?.aborted ? "cancelled" : "failed",
860
+ durationMs: occurredAt - startedAt,
861
+ error,
862
+ occurredAt,
863
+ });
864
+ throw error;
865
+ }
814
866
  },
815
867
  },
816
868
  });
package/src/runtime.ts CHANGED
@@ -975,6 +975,28 @@ export abstract class AgentRuntimeKernel<
975
975
  occurredAt: event.timestamp,
976
976
  });
977
977
  },
978
+ onNestedToolStarted: (event) => {
979
+ this.telemetry.capture("toolStarted", {
980
+ submissionId: submission.submissionId,
981
+ ...event,
982
+ });
983
+ },
984
+ onNestedToolFinished: (event) => {
985
+ this.telemetry.capture("toolFinished", {
986
+ submissionId: submission.submissionId,
987
+ parentToolCallId: event.parentToolCallId,
988
+ toolCallId: event.toolCallId,
989
+ toolName: event.toolName,
990
+ outcome: event.outcome,
991
+ durationMs: event.durationMs,
992
+ ...(event.output ? {
993
+ output: event.output,
994
+ outputBytes: json(event.output).length,
995
+ } : {}),
996
+ ...(event.error ? { error: errorText(event.error) } : {}),
997
+ occurredAt: event.occurredAt,
998
+ });
999
+ },
978
1000
  ...(toolExecutors && Object.keys(toolExecutors).length > 0
979
1001
  ? { toolExecutors }
980
1002
  : {}),
@@ -223,6 +223,7 @@ export class RuntimeTelemetry {
223
223
  submissionId: string;
224
224
  toolCallId: string;
225
225
  toolName: string;
226
+ parentToolCallId?: string;
226
227
  input?: unknown;
227
228
  occurredAt?: number;
228
229
  }>): TelemetryRecordResult {
@@ -235,10 +236,9 @@ export class RuntimeTelemetry {
235
236
  ...(input.input === undefined ? {} : { input: input.input as never }),
236
237
  }, {
237
238
  ...input,
238
- parentOperationId: telemetryOperations.turn(
239
- this.resource.sessionId,
240
- input.submissionId,
241
- ),
239
+ parentOperationId: input.parentToolCallId
240
+ ? telemetryOperations.tool(input.submissionId, input.parentToolCallId)
241
+ : telemetryOperations.turn(this.resource.sessionId, input.submissionId),
242
242
  });
243
243
  }
244
244
 
@@ -246,6 +246,7 @@ export class RuntimeTelemetry {
246
246
  submissionId: string;
247
247
  toolCallId: string;
248
248
  toolName: string;
249
+ parentToolCallId?: string;
249
250
  outcome: "completed" | "failed" | "cancelled";
250
251
  durationMs?: number;
251
252
  outputBytes?: number;
@@ -268,10 +269,9 @@ export class RuntimeTelemetry {
268
269
  ...(input.error ? { error: input.error } : {}),
269
270
  }, {
270
271
  ...input,
271
- parentOperationId: telemetryOperations.turn(
272
- this.resource.sessionId,
273
- input.submissionId,
274
- ),
272
+ parentOperationId: input.parentToolCallId
273
+ ? telemetryOperations.tool(input.submissionId, input.parentToolCallId)
274
+ : telemetryOperations.turn(this.resource.sessionId, input.submissionId),
275
275
  });
276
276
  }
277
277