@davidorex/pi-jit-agents 0.14.6

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/README.md +45 -0
  3. package/dist/agent-spec.d.ts +24 -0
  4. package/dist/agent-spec.d.ts.map +1 -0
  5. package/dist/agent-spec.js +126 -0
  6. package/dist/agent-spec.js.map +1 -0
  7. package/dist/agent-trace-sdk.d.ts +42 -0
  8. package/dist/agent-trace-sdk.d.ts.map +1 -0
  9. package/dist/agent-trace-sdk.js +177 -0
  10. package/dist/agent-trace-sdk.js.map +1 -0
  11. package/dist/compile.d.ts +17 -0
  12. package/dist/compile.d.ts.map +1 -0
  13. package/dist/compile.js +118 -0
  14. package/dist/compile.js.map +1 -0
  15. package/dist/errors.d.ts +36 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +56 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/index.d.ts +22 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +18 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/introspect.d.ts +17 -0
  24. package/dist/introspect.d.ts.map +1 -0
  25. package/dist/introspect.js +22 -0
  26. package/dist/introspect.js.map +1 -0
  27. package/dist/jit-runtime.d.ts +106 -0
  28. package/dist/jit-runtime.d.ts.map +1 -0
  29. package/dist/jit-runtime.js +583 -0
  30. package/dist/jit-runtime.js.map +1 -0
  31. package/dist/template.d.ts +36 -0
  32. package/dist/template.d.ts.map +1 -0
  33. package/dist/template.js +78 -0
  34. package/dist/template.js.map +1 -0
  35. package/dist/trace-redactor.d.ts +43 -0
  36. package/dist/trace-redactor.d.ts.map +1 -0
  37. package/dist/trace-redactor.js +173 -0
  38. package/dist/trace-redactor.js.map +1 -0
  39. package/dist/trace-writer.d.ts +13 -0
  40. package/dist/trace-writer.d.ts.map +1 -0
  41. package/dist/trace-writer.js +112 -0
  42. package/dist/trace-writer.js.map +1 -0
  43. package/dist/types.d.ts +185 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +2 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +71 -0
  48. package/schemas/agent-trace.schema.json +191 -0
  49. package/schemas/trace-config.schema.json +58 -0
  50. package/schemas/verdict.schema.json +14 -0
@@ -0,0 +1,583 @@
1
+ /**
2
+ * In-process LLM dispatch with phantom-tool structured output enforcement.
3
+ *
4
+ * Implements D4 (jit-agents-spec.md §4): the unified `executeAgent` primitive
5
+ * that both workflow agent steps and monitor classify calls consume. There is
6
+ * one dispatch path across the framework — not one for workflows and another
7
+ * for monitors.
8
+ *
9
+ * Phantom tool pattern: when a compiled agent declares an outputSchema, the
10
+ * dispatch call passes a synthetic Tool constructed from the schema to pi-ai
11
+ * with forced toolChoice. The LLM produces ToolCall.arguments matching the
12
+ * schema; the arguments are extracted as the typed result. No text parsing,
13
+ * no JSON.parse of free-form output.
14
+ *
15
+ * Thinking: NOT passed. Anthropic's API rejects thinking + forced toolChoice.
16
+ * This is a documented active constraint. Agents that need thinking cannot use
17
+ * schema-bound output in this release.
18
+ */
19
+ import fs from "node:fs";
20
+ import { validateFromFile } from "@davidorex/pi-project/schema-validator";
21
+ import { complete as piAiComplete, Type } from "@mariozechner/pi-ai";
22
+ import { AgentDispatchError } from "./errors.js";
23
+ import { loadProjectRedactionConfig, redactLlmResponse, redactSensitiveData, } from "./trace-redactor.js";
24
+ import { writeAgentTrace } from "./trace-writer.js";
25
+ /**
26
+ * Minimal ULID generator (Crockford base32, 26 chars: 10 timestamp + 16 random).
27
+ *
28
+ * Inline rather than a dependency: ulid is not in this workspace, the algorithm
29
+ * fits in a few lines, and the requirement is simply that ids be lexicographically
30
+ * sortable across concurrent executeAgent calls (the agent-trace.schema.json
31
+ * `traceId` pattern enforces 26-char Crockford base32).
32
+ *
33
+ * Monotonic-within-millisecond is approximated by the random-suffix component;
34
+ * we do not implement the strict ULID monotonic-tiebreaker because the trace
35
+ * pipeline tolerates rare same-ms collisions (entries are sorted by id, but
36
+ * same-ms ties resolve consistently within a single-process run via the random
37
+ * lower bits, and cross-process traces interleave at directory listing level).
38
+ */
39
+ const CROCKFORD_BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
40
+ function newUlid(now = Date.now()) {
41
+ // 48-bit timestamp → 10 base32 chars.
42
+ let ts = now;
43
+ const tsChars = new Array(10);
44
+ for (let i = 9; i >= 0; i--) {
45
+ tsChars[i] = CROCKFORD_BASE32[ts % 32] ?? "0";
46
+ ts = Math.floor(ts / 32);
47
+ }
48
+ // 80 random bits → 16 base32 chars. Math.random suffices (collision risk
49
+ // is non-zero but the trace use-case does not require crypto-grade ids).
50
+ const randChars = new Array(16);
51
+ for (let i = 0; i < 16; i++) {
52
+ randChars[i] = CROCKFORD_BASE32[Math.floor(Math.random() * 32)] ?? "0";
53
+ }
54
+ return tsChars.join("") + randChars.join("");
55
+ }
56
+ /**
57
+ * Recursively redact string leaves of an arbitrary value. Numbers, booleans,
58
+ * null, and undefined pass through unchanged. Strings run through
59
+ * redactSensitiveData. Arrays and plain objects are walked depth-first.
60
+ *
61
+ * Used for the `collectedValue` field of context_collection trace entries —
62
+ * collectors may return strings, arrays, or objects, so a single string-only
63
+ * redactor is insufficient.
64
+ */
65
+ function deepRedact(value, config) {
66
+ if (typeof value === "string")
67
+ return redactSensitiveData(value, config);
68
+ if (value === null || value === undefined)
69
+ return value;
70
+ if (Array.isArray(value))
71
+ return value.map((v) => deepRedact(v, config));
72
+ if (typeof value === "object") {
73
+ const out = {};
74
+ for (const [k, v] of Object.entries(value)) {
75
+ out[k] = deepRedact(v, config);
76
+ }
77
+ return out;
78
+ }
79
+ return value;
80
+ }
81
+ /**
82
+ * Map an executeAgent return value to the `verdictResult` shape required by
83
+ * agent-trace.schema.json (`{ verdict, description?, severity?, newPattern? }`).
84
+ *
85
+ * The schema's `verdict` enum is `clean | flag | new | error`. Phantom-tool
86
+ * outputs from monitor classifiers produce `CLEAN | FLAG | NEW` (uppercase) per
87
+ * verdict.schema.json — we lowercase here. Non-classifier agents produce
88
+ * arbitrary structured output or text; in that case we synthesize a `clean`
89
+ * verdict and attach a description so the trace remains schema-valid.
90
+ *
91
+ * `error` is reserved for the failure path (set in the catch handler).
92
+ */
93
+ function normalizeVerdict(output) {
94
+ if (output && typeof output === "object" && !Array.isArray(output)) {
95
+ const obj = output;
96
+ const rawVerdict = typeof obj.verdict === "string" ? obj.verdict.toLowerCase() : undefined;
97
+ if (rawVerdict === "clean" || rawVerdict === "flag" || rawVerdict === "new" || rawVerdict === "error") {
98
+ const result = { verdict: rawVerdict };
99
+ if (typeof obj.description === "string")
100
+ result.description = obj.description;
101
+ if (typeof obj.severity === "string")
102
+ result.severity = obj.severity;
103
+ if (typeof obj.newPattern === "string")
104
+ result.newPattern = obj.newPattern;
105
+ return result;
106
+ }
107
+ }
108
+ // Non-verdict output (e.g. workflow agent step structured result, free text):
109
+ // stamp as `clean` and stringify-describe for trace fidelity.
110
+ const description = typeof output === "string" ? output : output === undefined ? "" : JSON.stringify(output).slice(0, 2_000);
111
+ return { verdict: "clean", description };
112
+ }
113
+ /**
114
+ * Extract token usage from an AssistantMessage in the shape required by the
115
+ * trace schema's `usage` definition (camelCase, totalTokens summed).
116
+ */
117
+ function traceUsageFromMessage(msg) {
118
+ const u = msg.usage;
119
+ const input = u?.input ?? 0;
120
+ const output = u?.output ?? 0;
121
+ const cacheRead = u?.cacheRead ?? 0;
122
+ const cacheWrite = u?.cacheWrite ?? 0;
123
+ return {
124
+ inputTokens: input,
125
+ outputTokens: output,
126
+ cacheRead,
127
+ cacheWrite,
128
+ totalTokens: input + output,
129
+ };
130
+ }
131
+ /**
132
+ * Best-effort string identifier for a pi-ai Model<Api> instance. The Model
133
+ * shape carries `id` (model id) and `provider` (provider id); the trace schema
134
+ * wants a single string. Falls back to JSON.stringify for unrecognized shapes.
135
+ */
136
+ function modelToString(model) {
137
+ if (model && typeof model === "object") {
138
+ const m = model;
139
+ const provider = typeof m.provider === "string" ? m.provider : undefined;
140
+ const id = typeof m.id === "string" ? m.id : undefined;
141
+ if (provider && id)
142
+ return `${provider}/${id}`;
143
+ if (id)
144
+ return id;
145
+ if (provider)
146
+ return provider;
147
+ }
148
+ return typeof model === "string" ? model : JSON.stringify(model);
149
+ }
150
+ /**
151
+ * Wrap a writeAgentTrace call with a try/catch so trace failures cannot abort
152
+ * dispatch (per DEC-0005's intentional independence of trace from classify).
153
+ * Failures emit a stderr diagnostic prefixed with the pi-jit-agents tag and
154
+ * are otherwise swallowed.
155
+ */
156
+ function safeWriteTrace(entry, tracePath) {
157
+ try {
158
+ writeAgentTrace(entry, { tracePath });
159
+ }
160
+ catch (err) {
161
+ const msg = err instanceof Error ? err.message : String(err);
162
+ // eslint-disable-next-line no-console -- non-fatal diagnostic channel.
163
+ console.error(`[pi-jit-agents] trace write failed (${tracePath}): ${msg}`);
164
+ }
165
+ }
166
+ /**
167
+ * Build a phantom Tool from a JSON Schema file for forced structured output.
168
+ *
169
+ * For the common shape (top-level `type: object` with `required` and
170
+ * `properties` where each property has a primitive `type` and optional
171
+ * `enum`), produces a TypeBox Type.Object matching the schema. Complex shapes
172
+ * (allOf, anyOf, conditional) fall back to a relaxed Type.Object that accepts
173
+ * any object — post-hoc validation via `validateFromFile` catches violations.
174
+ *
175
+ * The tool is never executed — it exists only as a schema constraint that
176
+ * pi-ai enforces via forced toolChoice.
177
+ */
178
+ export function buildPhantomTool(schemaPath, toolName = "jit_result", description = "Output the typed result") {
179
+ const raw = fs.readFileSync(schemaPath, "utf-8");
180
+ const schema = JSON.parse(raw);
181
+ const parameters = jsonSchemaToTypeBox(schema);
182
+ return {
183
+ name: toolName,
184
+ description,
185
+ parameters: parameters,
186
+ };
187
+ }
188
+ /**
189
+ * Map a pi-ai `Api` kind plus a phantom tool name to the `toolChoice` shape
190
+ * the corresponding driver expects.
191
+ *
192
+ * This is the architectural normalization point referenced by ADR-0003: the
193
+ * forced-toolChoice protocol divergence across Anthropic / OpenAI-compatible
194
+ * / Google providers is collapsed here, not at each consumer call site.
195
+ *
196
+ * Coverage map (pi-ai 0.70.2 — verified against
197
+ * `node_modules/@mariozechner/pi-ai/dist/providers/*`):
198
+ *
199
+ * - `anthropic-messages` — passes object through unchanged. Anthropic
200
+ * Messages API expects `{type:"tool", name}`.
201
+ * - `bedrock-converse-stream` — accepts `{type:"tool", name}` and translates
202
+ * internally to Bedrock Converse's `{tool:{name}}` shape (driver line
203
+ * 611-612 of amazon-bedrock.js).
204
+ * - `openai-completions` — passthrough. OpenAI / OpenRouter / OpenAI-
205
+ * compatible gateways expect `{type:"function", function:{name}}` or
206
+ * string `"required"`. Mismatch here is the proximate cause of the
207
+ * "Tool '' not found in provided tools" 400 surfaced post-7edf3a2.
208
+ * - `mistral-conversations` — driver passes the object through its own
209
+ * `mapToolChoice` which reads `choice.function.name`, so the OpenAI-
210
+ * compatible function form is required.
211
+ * - `openai-responses`, `openai-codex-responses`, `azure-openai-responses`
212
+ * — pi-ai 0.70.2 drivers do NOT honor `options.toolChoice` (codex hard-
213
+ * codes `tool_choice: "auto"`; the other two drop it entirely). The
214
+ * OpenAI-compatible function form is emitted here as the canonical
215
+ * shape for the day pi-ai begins forwarding it; today the value is
216
+ * ignored and forced toolChoice is unenforceable on these drivers.
217
+ * Tracked as a pi-ai upstream gap; do not paper over here.
218
+ * - `google-generative-ai`, `google-gemini-cli`, `google-vertex` — drivers
219
+ * accept only string `"any" | "auto" | "none"` (mapped to FunctionCalling-
220
+ * ConfigMode). Specific-tool pinning is not exposed. `"any"` forces
221
+ * tool use; adequate for the phantom-tool single-tool pattern (the model
222
+ * has only one tool to call) but fails to pin a specific tool when
223
+ * multiple tools are present.
224
+ * - Unknown / custom api strings — Anthropic-format default. Matches the
225
+ * pre-fix behavior that worked end-to-end for `anthropic-messages` and
226
+ * preserves backward compatibility for any consumer that registered a
227
+ * custom api provider expecting that shape.
228
+ */
229
+ export function normalizeToolChoice(api, toolName) {
230
+ switch (api) {
231
+ case "anthropic-messages":
232
+ case "bedrock-converse-stream":
233
+ return { type: "tool", name: toolName };
234
+ case "openai-completions":
235
+ case "mistral-conversations":
236
+ case "openai-responses":
237
+ case "openai-codex-responses":
238
+ case "azure-openai-responses":
239
+ return { type: "function", function: { name: toolName } };
240
+ case "google-generative-ai":
241
+ case "google-gemini-cli":
242
+ case "google-vertex":
243
+ return "any";
244
+ default:
245
+ return { type: "tool", name: toolName };
246
+ }
247
+ }
248
+ /**
249
+ * Convert a JSON Schema object to a TypeBox schema.
250
+ *
251
+ * Handles the shape used by verdict.schema.json and the initial test fixtures.
252
+ * Falls back to Type.Any() for unsupported constructs — the phantom tool
253
+ * enforces structural shape; full validation is post-hoc.
254
+ */
255
+ function jsonSchemaToTypeBox(schema) {
256
+ const type = schema.type;
257
+ if (type !== "object") {
258
+ return Type.Any();
259
+ }
260
+ const properties = (schema.properties ?? {});
261
+ const required = new Set(Array.isArray(schema.required) ? schema.required : []);
262
+ const props = {};
263
+ for (const [key, propSchema] of Object.entries(properties)) {
264
+ const propType = propertyToTypeBox(propSchema);
265
+ props[key] = required.has(key) ? propType : Type.Optional(propType);
266
+ }
267
+ return Type.Object(props);
268
+ }
269
+ function propertyToTypeBox(propSchema) {
270
+ const t = propSchema.type;
271
+ const enumValues = propSchema.enum;
272
+ const description = typeof propSchema.description === "string" ? propSchema.description : undefined;
273
+ const opts = description ? { description } : {};
274
+ if (Array.isArray(enumValues) && enumValues.every((v) => typeof v === "string")) {
275
+ return Type.Union(enumValues.map((v) => Type.Literal(v)), opts);
276
+ }
277
+ switch (t) {
278
+ case "string":
279
+ return Type.String(opts);
280
+ case "number":
281
+ return Type.Number(opts);
282
+ case "integer":
283
+ return Type.Integer(opts);
284
+ case "boolean":
285
+ return Type.Boolean(opts);
286
+ case "array":
287
+ return Type.Array(Type.Any(), opts);
288
+ case "object":
289
+ return jsonSchemaToTypeBox(propSchema);
290
+ default:
291
+ return Type.Any();
292
+ }
293
+ }
294
+ /**
295
+ * Extract concatenated text content from an AssistantMessage.
296
+ */
297
+ function extractText(msg) {
298
+ return msg.content
299
+ .filter((c) => c.type === "text")
300
+ .map((c) => c.text)
301
+ .join("");
302
+ }
303
+ /**
304
+ * Default usage object. Populated from AssistantMessage.usage when available.
305
+ */
306
+ function emptyUsage() {
307
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };
308
+ }
309
+ function usageFromMessage(msg) {
310
+ const usage = emptyUsage();
311
+ if (!msg.usage)
312
+ return usage;
313
+ usage.input = msg.usage.input ?? 0;
314
+ usage.output = msg.usage.output ?? 0;
315
+ usage.cacheRead = msg.usage.cacheRead ?? 0;
316
+ usage.cacheWrite = msg.usage.cacheWrite ?? 0;
317
+ usage.cost =
318
+ (msg.usage.cost?.input ?? 0) +
319
+ (msg.usage.cost?.output ?? 0) +
320
+ (msg.usage.cost?.cacheRead ?? 0) +
321
+ (msg.usage.cost?.cacheWrite ?? 0);
322
+ return usage;
323
+ }
324
+ /**
325
+ * Execute a compiled agent in-process.
326
+ *
327
+ * When `compiled.outputSchema` is set: build a phantom tool from the schema,
328
+ * call pi-ai's `complete` with forced toolChoice, extract ToolCall.arguments,
329
+ * and validate post-hoc against the schema file.
330
+ *
331
+ * When `compiled.outputSchema` is absent: call `complete` without tools and
332
+ * return the extracted text as `output`.
333
+ *
334
+ * Test hook: `completeFn` overrides the pi-ai `complete` import for unit
335
+ * tests that do not make real LLM calls.
336
+ */
337
+ export async function executeAgent(compiled, dispatch, completeFn = piAiComplete) {
338
+ // --- Trace bootstrap -----------------------------------------------------
339
+ // Trace capture is gated on dispatch.tracePath being a non-empty string.
340
+ // `undefined` and `null` both disable tracing. When disabled, every trace
341
+ // emission below short-circuits via the `tracePath !== null` guard at the
342
+ // safeWriteTrace call sites, leaving the pre-existing dispatch behavior
343
+ // observably unchanged.
344
+ const tracePath = typeof dispatch.tracePath === "string" ? dispatch.tracePath : null;
345
+ const tracingEnabled = tracePath !== null;
346
+ // Resolve the redaction config once per executeAgent call. Failure here
347
+ // must not abort dispatch — a malformed config falls back to the builtin
348
+ // pattern set with a stderr diagnostic.
349
+ let redactionConfig;
350
+ if (tracingEnabled && typeof dispatch.redactionConfigPath === "string") {
351
+ try {
352
+ const patterns = loadProjectRedactionConfig(dispatch.redactionConfigPath);
353
+ redactionConfig = { patterns };
354
+ }
355
+ catch (err) {
356
+ const msg = err instanceof Error ? err.message : String(err);
357
+ // eslint-disable-next-line no-console -- non-fatal diagnostic channel.
358
+ console.error(`[pi-jit-agents] redaction config load failed (${dispatch.redactionConfigPath}): ${msg}`);
359
+ }
360
+ }
361
+ const sessionStartMs = Date.now();
362
+ const sessionStartId = newUlid(sessionStartMs);
363
+ let classifyCallId = null;
364
+ let classifyResponseId = null;
365
+ if (tracingEnabled && tracePath !== null) {
366
+ safeWriteTrace({
367
+ type: "session_start",
368
+ id: sessionStartId,
369
+ parentId: null,
370
+ timestamp: new Date(sessionStartMs).toISOString(),
371
+ sessionId: sessionStartId,
372
+ monitorName: typeof dispatch.monitorName === "string" ? dispatch.monitorName : null,
373
+ agentName: compiled.spec.name,
374
+ model: modelToString(dispatch.model),
375
+ cwd: process.cwd(),
376
+ }, tracePath);
377
+ }
378
+ // --- Existing dispatch logic --------------------------------------------
379
+ const messages = [
380
+ {
381
+ role: "user",
382
+ content: [{ type: "text", text: compiled.taskPrompt }],
383
+ timestamp: Date.now(),
384
+ },
385
+ ];
386
+ const systemPrompt = compiled.systemPrompt;
387
+ const maxTokens = dispatch.maxTokens ?? 1024;
388
+ // classify_call is emitted just before the LLM call: at this point the
389
+ // rendered prompts (system + task) are fully available. Per the schema,
390
+ // `renderedPrompt` is a single string — we concatenate system and task
391
+ // with a delimiter so trace consumers see exactly what dispatch sent.
392
+ if (tracingEnabled && tracePath !== null) {
393
+ const renderedPromptRaw = systemPrompt
394
+ ? `[SYSTEM]\n${systemPrompt}\n[TASK]\n${compiled.taskPrompt}`
395
+ : compiled.taskPrompt;
396
+ classifyCallId = newUlid();
397
+ safeWriteTrace({
398
+ type: "classify_call",
399
+ id: classifyCallId,
400
+ parentId: sessionStartId,
401
+ timestamp: new Date().toISOString(),
402
+ renderedPrompt: redactSensitiveData(renderedPromptRaw, redactionConfig),
403
+ inputText: redactSensitiveData(compiled.taskPrompt, redactionConfig),
404
+ }, tracePath);
405
+ // One context_collection entry per resolved collector. Path A: the
406
+ // CompiledAgent now carries `contextValues` populated by compileAgent.
407
+ // We deep-redact each collected value and emit immediately after
408
+ // classify_call so the parent chain is intact even when downstream
409
+ // dispatch fails.
410
+ const ts = new Date().toISOString();
411
+ for (const [collectorId, collectedValue] of Object.entries(compiled.contextValues)) {
412
+ safeWriteTrace({
413
+ type: "context_collection",
414
+ id: newUlid(),
415
+ parentId: classifyCallId,
416
+ timestamp: ts,
417
+ collectorId,
418
+ collectedValue: deepRedact(collectedValue, redactionConfig),
419
+ // Collection time is not yet measured at the compileAgent boundary;
420
+ // reserved for a future instrumentation pass.
421
+ collectionTimeMs: 0,
422
+ }, tracePath);
423
+ }
424
+ }
425
+ let response;
426
+ try {
427
+ const context = { messages };
428
+ if (systemPrompt)
429
+ context.systemPrompt = systemPrompt;
430
+ const options = {
431
+ apiKey: dispatch.auth.apiKey,
432
+ headers: dispatch.auth.headers,
433
+ maxTokens,
434
+ signal: dispatch.signal,
435
+ };
436
+ if (compiled.outputSchema) {
437
+ const phantomTool = buildPhantomTool(compiled.outputSchema);
438
+ context.tools = [phantomTool];
439
+ options.toolChoice = normalizeToolChoice(dispatch.model.api, phantomTool.name);
440
+ }
441
+ response = await completeFn(dispatch.model, context, options);
442
+ }
443
+ catch (err) {
444
+ // Dispatch itself failed — emit a synthetic verdict_decision + trace_end
445
+ // with verdict=error so the trace remains parent-chain complete, then
446
+ // rethrow per the original contract.
447
+ if (tracingEnabled && tracePath !== null) {
448
+ const errorMsg = err instanceof Error ? err.message : String(err);
449
+ const verdictId = newUlid();
450
+ const errVerdict = {
451
+ verdict: "error",
452
+ description: redactSensitiveData(errorMsg.slice(0, 2_000), redactionConfig),
453
+ };
454
+ safeWriteTrace({
455
+ type: "verdict_decision",
456
+ id: verdictId,
457
+ // classify_response did not happen — chain off classify_call when
458
+ // available, otherwise off session_start.
459
+ parentId: classifyCallId ?? sessionStartId,
460
+ timestamp: new Date().toISOString(),
461
+ finalResult: errVerdict,
462
+ mappingDecisionRationale: redactSensitiveData("dispatch failed before LLM response", redactionConfig),
463
+ }, tracePath);
464
+ safeWriteTrace({
465
+ type: "trace_end",
466
+ id: newUlid(),
467
+ parentId: sessionStartId,
468
+ timestamp: new Date().toISOString(),
469
+ totalDurationMs: Date.now() - sessionStartMs,
470
+ verdict: errVerdict,
471
+ }, tracePath);
472
+ }
473
+ if (dispatch.signal?.aborted) {
474
+ throw new AgentDispatchError(compiled.spec.name, "cancelled", {
475
+ cause: err instanceof Error ? err : new Error(String(err)),
476
+ });
477
+ }
478
+ const cause = err instanceof Error ? err : new Error(String(err));
479
+ throw new AgentDispatchError(compiled.spec.name, cause.message, { cause });
480
+ }
481
+ // classify_response: emitted after the AssistantMessage is in hand. The
482
+ // content array runs through redactLlmResponse to strip credentials echoed
483
+ // in the model output; usage / stopReason are passthrough numerics/enums.
484
+ if (tracingEnabled && tracePath !== null) {
485
+ const redactedResponse = redactLlmResponse({ content: response.content }, redactionConfig);
486
+ classifyResponseId = newUlid();
487
+ const responseEntry = {
488
+ type: "classify_response",
489
+ id: classifyResponseId,
490
+ parentId: classifyCallId ?? sessionStartId,
491
+ timestamp: new Date().toISOString(),
492
+ stopReason: response.stopReason ?? "unknown",
493
+ usage: traceUsageFromMessage(response),
494
+ content: redactedResponse.content,
495
+ };
496
+ if (typeof response.errorMessage === "string") {
497
+ responseEntry.errorMessage = redactSensitiveData(response.errorMessage, redactionConfig);
498
+ }
499
+ safeWriteTrace(responseEntry, tracePath);
500
+ }
501
+ const usage = usageFromMessage(response);
502
+ let result;
503
+ try {
504
+ if (compiled.outputSchema) {
505
+ const toolCall = response.content.find((c) => c.type === "toolCall");
506
+ if (!toolCall) {
507
+ const contentTypes = response.content.map((c) => c.type).join(", ");
508
+ const errMsg = response.errorMessage ? ` error: ${response.errorMessage}` : "";
509
+ throw new AgentDispatchError(compiled.spec.name, `no tool call in response (content types: [${contentTypes}]${errMsg})`, { stopReason: response.stopReason });
510
+ }
511
+ const args = toolCall.arguments;
512
+ validateFromFile(compiled.outputSchema, args, `output for agent '${compiled.spec.name}'`);
513
+ result = { output: args, raw: response, usage };
514
+ }
515
+ else {
516
+ result = { output: extractText(response), raw: response, usage };
517
+ }
518
+ }
519
+ catch (err) {
520
+ // Output validation / tool-call extraction failed. Mirror the dispatch-
521
+ // failure trace pattern so the parent chain remains complete, then
522
+ // rethrow so callers see the original error.
523
+ if (tracingEnabled && tracePath !== null) {
524
+ const errorMsg = err instanceof Error ? err.message : String(err);
525
+ const errVerdict = {
526
+ verdict: "error",
527
+ description: redactSensitiveData(errorMsg.slice(0, 2_000), redactionConfig),
528
+ };
529
+ safeWriteTrace({
530
+ type: "verdict_decision",
531
+ id: newUlid(),
532
+ parentId: classifyResponseId ?? classifyCallId ?? sessionStartId,
533
+ timestamp: new Date().toISOString(),
534
+ finalResult: errVerdict,
535
+ mappingDecisionRationale: redactSensitiveData("output extraction or validation failed", redactionConfig),
536
+ }, tracePath);
537
+ safeWriteTrace({
538
+ type: "trace_end",
539
+ id: newUlid(),
540
+ parentId: sessionStartId,
541
+ timestamp: new Date().toISOString(),
542
+ totalDurationMs: Date.now() - sessionStartMs,
543
+ verdict: errVerdict,
544
+ }, tracePath);
545
+ }
546
+ throw err;
547
+ }
548
+ // Success path: verdict_decision + trace_end. The verdict normalizer maps
549
+ // classifier output (CLEAN/FLAG/NEW) to the schema enum (clean/flag/new)
550
+ // and synthesizes a `clean` verdict for non-classifier agents so the trace
551
+ // remains schema-valid for both surfaces.
552
+ if (tracingEnabled && tracePath !== null) {
553
+ const finalResultRaw = normalizeVerdict(result.output);
554
+ const finalResult = { verdict: finalResultRaw.verdict };
555
+ if (finalResultRaw.description !== undefined) {
556
+ finalResult.description = redactSensitiveData(finalResultRaw.description, redactionConfig);
557
+ }
558
+ if (finalResultRaw.severity !== undefined) {
559
+ finalResult.severity = finalResultRaw.severity;
560
+ }
561
+ if (finalResultRaw.newPattern !== undefined) {
562
+ finalResult.newPattern = redactSensitiveData(finalResultRaw.newPattern, redactionConfig);
563
+ }
564
+ safeWriteTrace({
565
+ type: "verdict_decision",
566
+ id: newUlid(),
567
+ parentId: classifyResponseId ?? classifyCallId ?? sessionStartId,
568
+ timestamp: new Date().toISOString(),
569
+ finalResult,
570
+ mappingDecisionRationale: redactSensitiveData("executeAgent returned", redactionConfig),
571
+ }, tracePath);
572
+ safeWriteTrace({
573
+ type: "trace_end",
574
+ id: newUlid(),
575
+ parentId: sessionStartId,
576
+ timestamp: new Date().toISOString(),
577
+ totalDurationMs: Date.now() - sessionStartMs,
578
+ verdict: finalResult,
579
+ }, tracePath);
580
+ }
581
+ return result;
582
+ }
583
+ //# sourceMappingURL=jit-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jit-runtime.js","sourceRoot":"","sources":["../src/jit-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import nunjucks from "nunjucks";
2
+ export interface TemplateEnvContext {
3
+ /** Project root. Resolves the project-level tier. */
4
+ cwd: string;
5
+ /** Optional consumer-supplied builtin template directory. */
6
+ builtinDir?: string;
7
+ /** Test hook to override the user tier. Defaults to `~/.pi/agent/templates/`. */
8
+ userDir?: string;
9
+ }
10
+ /**
11
+ * Create a Nunjucks environment with three-tier template discovery.
12
+ *
13
+ * Returns a no-op loader environment (plain strings pass through) when no
14
+ * tier directory exists. This is not an error — an agent with an entirely
15
+ * inline prompt uses no templates at all.
16
+ */
17
+ export declare function createTemplateEnv(ctx: TemplateEnvContext): nunjucks.Environment;
18
+ /**
19
+ * Render a template string through Nunjucks.
20
+ *
21
+ * Protects `${{ }}` workflow expressions from Nunjucks by escaping them
22
+ * before rendering and restoring them after.
23
+ */
24
+ export declare function renderTemplate(env: nunjucks.Environment, templateStr: string, context: Record<string, unknown>): string;
25
+ /**
26
+ * Render a named template file through Nunjucks.
27
+ *
28
+ * The template name is resolved by the environment's FileSystemLoader through
29
+ * the configured three-tier search.
30
+ *
31
+ * Absolute paths bypass the loader and are read directly. This supports
32
+ * fully-resolved AgentSpec fields where systemPromptTemplate / taskPromptTemplate
33
+ * carry absolute paths after loadAgent (per D1).
34
+ */
35
+ export declare function renderTemplateFile(env: nunjucks.Environment, templateName: string, context: Record<string, unknown>): string;
36
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAoBA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,MAAM,WAAW,kBAAkB;IAClC,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,kBAAkB,GAAG,QAAQ,CAAC,WAAW,CAe/E;AASD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,GAAG,EAAE,QAAQ,CAAC,WAAW,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAIR;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CACjC,GAAG,EAAE,QAAQ,CAAC,WAAW,EACzB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAMR"}