summaryrefslogtreecommitdiffhomepage
path: root/packages/kernel/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'packages/kernel/src/runtime')
-rw-r--r--packages/kernel/src/runtime/run-turn.test.ts52
-rw-r--r--packages/kernel/src/runtime/run-turn.ts25
2 files changed, 63 insertions, 14 deletions
diff --git a/packages/kernel/src/runtime/run-turn.test.ts b/packages/kernel/src/runtime/run-turn.test.ts
index 667476f..9c19027 100644
--- a/packages/kernel/src/runtime/run-turn.test.ts
+++ b/packages/kernel/src/runtime/run-turn.test.ts
@@ -2,9 +2,9 @@ import { describe, expect, it } from "vitest";
import type { ChatMessage } from "../contracts/conversation.js";
import type { AgentEvent } from "../contracts/events.js";
import type { LogDeps, Logger, LogRecord, LogSink } from "../contracts/logging.js";
-import { createLogger } from "../contracts/logging.js";
import type { ProviderContract, ProviderEvent } from "../contracts/provider.js";
import type { ToolContract, ToolExecuteContext, ToolResult } from "../contracts/tool.js";
+import { createLogger } from "../logging/logger.js";
import { runTurn } from "./run-turn.js";
function delay(ms: number): Promise<void> {
@@ -1039,6 +1039,56 @@ describe("runTurn", () => {
expect(stepCloses[0].attributes?.["error.message"]).toContain("provider exploded");
}
});
+
+ it("emits a prompt span with verbatim body and small scalar attributes", async () => {
+ const tool = createFakeTool("echo", async () => ({ content: "echoed" }));
+
+ const provider = createFakeProvider([
+ [
+ { type: "text-delta", delta: "done" },
+ { type: "finish", reason: "stop" },
+ ],
+ ]);
+
+ const { logger, sink } = createTestLogger();
+
+ await runTurn({
+ provider,
+ messages: [userMessage],
+ tools: [tool],
+ dispatch: { maxConcurrent: 1, eager: false },
+ conversationId: "conv-1",
+ turnId: "turn-1",
+ emit: () => {},
+ logger,
+ });
+
+ const promptOpens = sink.records.filter((r) => r.kind === "span-open" && r.name === "prompt");
+ expect(promptOpens).toHaveLength(1);
+
+ const promptOpen = promptOpens[0];
+ if (promptOpen?.kind === "span-open") {
+ expect(promptOpen.body).toBeDefined();
+ const parsed = JSON.parse(promptOpen.body as string);
+ expect(parsed.messages).toEqual([userMessage]);
+ expect(parsed.tools).toHaveLength(1);
+ expect(parsed.tools[0].name).toBe("echo");
+
+ expect(promptOpen.attributes?.messageCount).toBe(1);
+ expect(promptOpen.attributes?.toolCount).toBe(1);
+ }
+
+ const promptCloses = sink.records.filter(
+ (r) => r.kind === "span-close" && r.name === "prompt",
+ );
+ expect(promptCloses).toHaveLength(1);
+
+ const logRecords = sink.records.filter(
+ (r) =>
+ r.kind === "log" && r.kind === "log" && (r as { msg: string }).msg === "prompt:before",
+ );
+ expect(logRecords).toHaveLength(0);
+ });
});
describe("provider logger threading", () => {
diff --git a/packages/kernel/src/runtime/run-turn.ts b/packages/kernel/src/runtime/run-turn.ts
index a78c31d..5e60641 100644
--- a/packages/kernel/src/runtime/run-turn.ts
+++ b/packages/kernel/src/runtime/run-turn.ts
@@ -167,22 +167,21 @@ async function executeStep(ctx: StepContext): Promise<StepResult> {
let stepUsage = zeroUsage();
let finishReason = "stop";
- // Open a step span with the verbatim pre-mutation prompt in its body (BEFORE capture).
+ // Open a step span; capture the verbatim pre-mutation prompt via a
+ // "prompt" child span whose body holds the serialized messages+tools.
let stepSpan: Span | undefined;
try {
stepSpan = ctx.logger.span("step");
- // Emit the verbatim pre-mutation prompt as a log record on the step span's logger.
- // This is the "BEFORE" capture — the messages + tools as handed to provider.stream.
- stepSpan.log.info("prompt:before", {
- "prompt.messages": JSON.stringify(ctx.messages),
- "prompt.tools": JSON.stringify(
- ctx.tools.map((t) => ({
- name: t.name,
- description: t.description,
- parameters: t.parameters,
- })),
- ),
- });
+ const promptBody = JSON.stringify({ messages: ctx.messages, tools: ctx.tools });
+ const promptSpan = stepSpan.child(
+ "prompt",
+ {
+ messageCount: ctx.messages.length,
+ toolCount: ctx.tools.length,
+ },
+ promptBody,
+ );
+ promptSpan.end();
} catch {
// Swallow — D7.
}