@davidorex/pi-jit-agents 0.14.6 → 0.26.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/agent-spec.d.ts.map +1 -1
- package/dist/agent-spec.js +69 -5
- package/dist/agent-spec.js.map +1 -1
- package/dist/budget-enforcer.d.ts +43 -0
- package/dist/budget-enforcer.d.ts.map +1 -0
- package/dist/budget-enforcer.js +172 -0
- package/dist/budget-enforcer.js.map +1 -0
- package/dist/compile.d.ts +39 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +357 -24
- package/dist/compile.js.map +1 -1
- package/dist/dispatch-inline.d.ts +25 -0
- package/dist/dispatch-inline.d.ts.map +1 -0
- package/dist/dispatch-inline.js +41 -0
- package/dist/dispatch-inline.js.map +1 -0
- package/dist/field-path.d.ts +32 -0
- package/dist/field-path.d.ts.map +1 -0
- package/dist/field-path.js +48 -0
- package/dist/field-path.js.map +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/jit-runtime.d.ts +3 -3
- package/dist/jit-runtime.d.ts.map +1 -1
- package/dist/jit-runtime.js +5 -5
- package/dist/jit-runtime.js.map +1 -1
- package/dist/markers.d.ts +28 -0
- package/dist/markers.d.ts.map +1 -0
- package/dist/markers.js +36 -0
- package/dist/markers.js.map +1 -0
- package/dist/renderer-registry.d.ts +44 -0
- package/dist/renderer-registry.d.ts.map +1 -0
- package/dist/renderer-registry.js +128 -0
- package/dist/renderer-registry.js.map +1 -0
- package/dist/template.d.ts.map +1 -1
- package/dist/template.js +10 -3
- package/dist/template.js.map +1 -1
- package/dist/trace-redactor.d.ts +1 -1
- package/dist/trace-redactor.js +1 -1
- package/dist/trace-writer.js +2 -2
- package/dist/types.d.ts +82 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -3
package/dist/compile.js
CHANGED
|
@@ -12,20 +12,166 @@
|
|
|
12
12
|
* from instructions.
|
|
13
13
|
*/
|
|
14
14
|
import fs from "node:fs";
|
|
15
|
-
import
|
|
16
|
-
import { readBlock } from "@davidorex/pi-
|
|
15
|
+
import { buildIdIndex } from "@davidorex/pi-context";
|
|
16
|
+
import { readBlock } from "@davidorex/pi-context/block-api";
|
|
17
|
+
import { schemaPath, tryResolveContextDir } from "@davidorex/pi-context/context-dir";
|
|
18
|
+
import { enforceBudget } from "./budget-enforcer.js";
|
|
19
|
+
import { dispatchInlineMacro } from "./dispatch-inline.js";
|
|
17
20
|
import { AgentCompileError } from "./errors.js";
|
|
21
|
+
import { expandFieldPathShorthand } from "./field-path.js";
|
|
22
|
+
import { cycleMarker, unrenderedMarker } from "./markers.js";
|
|
18
23
|
import { renderTemplate, renderTemplateFile } from "./template.js";
|
|
19
24
|
/**
|
|
20
|
-
*
|
|
25
|
+
* Register the composition-time Nunjucks globals on a template environment.
|
|
26
|
+
*
|
|
27
|
+
* Three globals are registered, scoped to the closure-captured state passed in:
|
|
28
|
+
*
|
|
29
|
+
* - `resolve(id)` — looks up an item by ID via the lazy idIndex; returns
|
|
30
|
+
* ItemLocation or null. Used by macros to dispatch
|
|
31
|
+
* cross-block references.
|
|
32
|
+
* - `render_recursive(loc, depth)` — renders an item via the registered
|
|
33
|
+
* per-item macro (resolved through the renderer registry).
|
|
34
|
+
* Cycle-detected via the visited set.
|
|
35
|
+
* - `enforceBudget(rendered, blockName, fieldPathOrShorthand)` — measures
|
|
36
|
+
* rendered text against the field's `x-prompt-budget`
|
|
37
|
+
* annotation, returning truncated output when over budget;
|
|
38
|
+
* pass-through when annotation absent. Truncation warnings
|
|
39
|
+
* are appended to `warningsCollector` (closure-captured by
|
|
40
|
+
* the caller) so callers can surface them after compile
|
|
41
|
+
* returns.
|
|
42
|
+
*
|
|
43
|
+
* Used by both `compileAgent` (this module) and `renderItemById` in pi-workflows
|
|
44
|
+
* — the single source of truth for the composition-globals contract. Adding
|
|
45
|
+
* a new global, changing a signature, or adjusting a fallback means editing
|
|
46
|
+
* here and the contract propagates to every caller.
|
|
47
|
+
*
|
|
48
|
+
* The visited-set lifetime is one call to this function — sequential calls on
|
|
49
|
+
* the same env get isolated cycle scopes. addGlobal overwrites prior bindings,
|
|
50
|
+
* which is intentional (each composition pass owns its own scope).
|
|
51
|
+
*/
|
|
52
|
+
export function registerCompositionGlobals(opts) {
|
|
53
|
+
const { env, cwd, rendererRegistry, getIdIndex, warningsCollector } = opts;
|
|
54
|
+
env.addGlobal("resolve", (id) => {
|
|
55
|
+
if (typeof id !== "string" || id.length === 0)
|
|
56
|
+
return null;
|
|
57
|
+
try {
|
|
58
|
+
return getIdIndex().get(id) ?? null;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
const visitedThisPass = new Set();
|
|
65
|
+
env.addGlobal("render_recursive", (loc, depth) => {
|
|
66
|
+
if (!loc || typeof loc !== "object")
|
|
67
|
+
return "";
|
|
68
|
+
const location = loc;
|
|
69
|
+
const itemId = location.item?.id;
|
|
70
|
+
const idStr = typeof itemId === "string" ? itemId : "";
|
|
71
|
+
const blockName = typeof location.block === "string" ? location.block : "?";
|
|
72
|
+
if (idStr.length > 0 && visitedThisPass.has(idStr)) {
|
|
73
|
+
return cycleMarker(idStr);
|
|
74
|
+
}
|
|
75
|
+
const macroRef = rendererRegistry?.lookup(blockName) ?? null;
|
|
76
|
+
if (!macroRef) {
|
|
77
|
+
return unrenderedMarker(blockName, idStr);
|
|
78
|
+
}
|
|
79
|
+
const depthNum = typeof depth === "number" && Number.isFinite(depth) ? depth : 0;
|
|
80
|
+
if (idStr.length > 0)
|
|
81
|
+
visitedThisPass.add(idStr);
|
|
82
|
+
try {
|
|
83
|
+
return dispatchInlineMacro({
|
|
84
|
+
env,
|
|
85
|
+
templatePath: macroRef.templatePath,
|
|
86
|
+
macroName: macroRef.macroName,
|
|
87
|
+
item: location.item,
|
|
88
|
+
depth: depthNum,
|
|
89
|
+
errorContext: `${blockName}/${idStr}`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
if (idStr.length > 0)
|
|
94
|
+
visitedThisPass.delete(idStr);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
env.addGlobal("enforceBudget", (rendered, blockName, fieldPathOrShorthand) => {
|
|
98
|
+
// Defensive coercion — Nunjucks may pass non-string values when a
|
|
99
|
+
// macro references an undefined field. Treat undefined / null as
|
|
100
|
+
// empty string to remain pass-through rather than throw.
|
|
101
|
+
const renderedStr = typeof rendered === "string" ? rendered : rendered === undefined || rendered === null ? "" : String(rendered);
|
|
102
|
+
if (typeof blockName !== "string" || blockName.length === 0)
|
|
103
|
+
return renderedStr;
|
|
104
|
+
if (typeof fieldPathOrShorthand !== "string" || fieldPathOrShorthand.length === 0)
|
|
105
|
+
return renderedStr;
|
|
106
|
+
const schemaFile = schemaPath(cwd, blockName);
|
|
107
|
+
if (!fs.existsSync(schemaFile))
|
|
108
|
+
return renderedStr; // no schema → pass-through
|
|
109
|
+
let schema;
|
|
110
|
+
try {
|
|
111
|
+
schema = JSON.parse(fs.readFileSync(schemaFile, "utf-8"));
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return renderedStr; // unreadable / unparseable schema → pass-through
|
|
115
|
+
}
|
|
116
|
+
const fieldPath = expandFieldPathShorthand(fieldPathOrShorthand);
|
|
117
|
+
let result;
|
|
118
|
+
try {
|
|
119
|
+
result = enforceBudget(renderedStr, schema, fieldPath);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Malformed annotation — pass through the original text rather
|
|
123
|
+
// than corrupt the prompt. The annotation error is silently
|
|
124
|
+
// swallowed at this layer; future work may surface it via a
|
|
125
|
+
// separate structured warning channel.
|
|
126
|
+
return renderedStr;
|
|
127
|
+
}
|
|
128
|
+
if (result.warning)
|
|
129
|
+
warningsCollector.push(result.warning);
|
|
130
|
+
return result.output;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/** Escape the 3 XML structural entities (& first, order matters) so block content
|
|
134
|
+
* cannot forge a </context_block> close tag and break the data boundary. Quotes are
|
|
135
|
+
* NOT escaped — they don't threaten element-text boundaries and escaping them would
|
|
136
|
+
* degrade JSON-body readability. (FGAP-081; pi leaves its own trusted bodies raw, but
|
|
137
|
+
* our blocks carry semi-trusted user/agent content.) */
|
|
138
|
+
function escapeXmlText(s) {
|
|
139
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Wrap injected block content in an anti-injection boundary.
|
|
21
143
|
*
|
|
22
144
|
* Block data rendered into a prompt must be visibly marked as data, not
|
|
23
|
-
* instructions.
|
|
24
|
-
*
|
|
145
|
+
* instructions. The boundary is a pi 0.75.x house-style XML `<context_block>`
|
|
146
|
+
* tag whose `role="data"` attribute carries the data/not-instructions semantic;
|
|
147
|
+
* structural escaping of the body prevents the content from forging a close tag.
|
|
148
|
+
* This applies at the framework level so every agent gets the guarantee
|
|
149
|
+
* regardless of what its template authors.
|
|
25
150
|
*/
|
|
26
151
|
function wrapBlockContent(blockName, content) {
|
|
27
152
|
const rendered = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
28
|
-
return [
|
|
153
|
+
return [
|
|
154
|
+
`<context_block name="${escapeXmlText(blockName)}" role="data">`,
|
|
155
|
+
escapeXmlText(rendered),
|
|
156
|
+
`</context_block>`,
|
|
157
|
+
].join("\n");
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Per-item variant of {@link wrapBlockContent}.
|
|
161
|
+
*
|
|
162
|
+
* Same pi 0.75.x XML `<context_block>` boundary (with `role="data"` + structural
|
|
163
|
+
* escaping), but item-scoped: the `item` attribute names the resolved id alongside
|
|
164
|
+
* the source block so the boundary is honest about the granularity — a single item
|
|
165
|
+
* is data, just like a whole block, but the narrower scope is explicit so downstream
|
|
166
|
+
* readers (and the LLM) cannot mistake it for whole-block content.
|
|
167
|
+
*/
|
|
168
|
+
function wrapItemContent(blockName, itemId, content) {
|
|
169
|
+
const rendered = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
170
|
+
return [
|
|
171
|
+
`<context_block name="${escapeXmlText(blockName)}" item="${escapeXmlText(itemId)}" role="data">`,
|
|
172
|
+
escapeXmlText(rendered),
|
|
173
|
+
`</context_block>`,
|
|
174
|
+
].join("\n");
|
|
29
175
|
}
|
|
30
176
|
/**
|
|
31
177
|
* Resolve an outputSchema value that may be a `block:<name>` sentinel.
|
|
@@ -37,7 +183,7 @@ function resolveOutputSchemaForCompile(outputSchema, cwd) {
|
|
|
37
183
|
return undefined;
|
|
38
184
|
if (outputSchema.startsWith("block:")) {
|
|
39
185
|
const blockName = outputSchema.slice("block:".length);
|
|
40
|
-
return
|
|
186
|
+
return schemaPath(cwd, blockName);
|
|
41
187
|
}
|
|
42
188
|
return outputSchema;
|
|
43
189
|
}
|
|
@@ -65,30 +211,210 @@ export function compileAgent(spec, ctx) {
|
|
|
65
211
|
// when the block is missing / the .project dir absent), distinct from the
|
|
66
212
|
// anti-injection-wrapped string the templates see.
|
|
67
213
|
const contextValues = {};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
214
|
+
// Lazily-built ID index, shared across all object-form entries in this
|
|
215
|
+
// compile call. We accept `ctx.idIndex` from the caller for reuse; otherwise
|
|
216
|
+
// we build at most once on demand. The lazy `getIdIndex` closure also
|
|
217
|
+
// backs the `resolve` and `render_recursive` Nunjucks globals registered
|
|
218
|
+
// below — so a template that calls `resolve("DEC-0001")` triggers index
|
|
219
|
+
// construction even when no object-form entry needed it.
|
|
220
|
+
let cachedIdIndex = ctx.idIndex;
|
|
221
|
+
const getIdIndex = () => {
|
|
222
|
+
if (!cachedIdIndex) {
|
|
223
|
+
try {
|
|
224
|
+
cachedIdIndex = buildIdIndex(ctx.cwd);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
if (err instanceof Error && err.name === "BootstrapNotFoundError") {
|
|
228
|
+
// Substrate absent — return empty index. Downstream resolution
|
|
229
|
+
// fails with the existing AgentCompileError contract rather
|
|
230
|
+
// than letting the bootstrap exception propagate to template
|
|
231
|
+
// global callers (resolve / render_recursive). Preserves the
|
|
232
|
+
// pre-DEC-0015 graceful-skip semantic per DEC-0021 gate-2.
|
|
233
|
+
cachedIdIndex = new Map();
|
|
77
234
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
templateContext[key] = null;
|
|
235
|
+
else {
|
|
236
|
+
throw err;
|
|
81
237
|
}
|
|
82
238
|
}
|
|
83
239
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
240
|
+
return cachedIdIndex;
|
|
241
|
+
};
|
|
242
|
+
if (spec.contextBlocks && spec.contextBlocks.length > 0) {
|
|
243
|
+
// tryResolveContextDir returns null when the substrate is absent — projectDirExists
|
|
244
|
+
// stays false. Downstream per-group logic (lines below) treats !projectDirExists as
|
|
245
|
+
// the canonical "no substrate" signal and either nulls whole-block surfaces OR throws
|
|
246
|
+
// AgentCompileError for unresolvable item-form entries. Preserves pre-DEC-0015
|
|
247
|
+
// graceful-skip semantic per DEC-0021 gate-2 closure. Only the missing-pointer case
|
|
248
|
+
// degrades; a malformed pointer / read failure still throws from within the primitive.
|
|
249
|
+
const projectDirPath = tryResolveContextDir(ctx.cwd);
|
|
250
|
+
const projectDirExists = projectDirPath !== null && fs.existsSync(projectDirPath);
|
|
251
|
+
const groups = new Map();
|
|
252
|
+
const ensureGroup = (name, index) => {
|
|
253
|
+
let g = groups.get(name);
|
|
254
|
+
if (!g) {
|
|
255
|
+
g = { name, stringEntry: false, wholeBlockEntry: null, itemEntries: [], firstIndex: index };
|
|
256
|
+
groups.set(name, g);
|
|
257
|
+
}
|
|
258
|
+
return g;
|
|
259
|
+
};
|
|
260
|
+
// Pass 1 — classify each entry, preserving spec authoring order
|
|
261
|
+
// inside `itemEntries` (push order = spec order).
|
|
262
|
+
spec.contextBlocks.forEach((entry, index) => {
|
|
263
|
+
if (typeof entry === "string") {
|
|
264
|
+
const g = ensureGroup(entry, index);
|
|
265
|
+
g.stringEntry = true;
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const ref = entry;
|
|
269
|
+
const g = ensureGroup(ref.name, index);
|
|
270
|
+
if (ref.item) {
|
|
271
|
+
g.itemEntries.push({ ref, index });
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
// Last whole-block-with-hints entry wins for the singular
|
|
275
|
+
// `_<name>` slot; keeping last is the simplest deterministic
|
|
276
|
+
// rule and matches the pre-Plan-4.1 forEach-overwrite behavior
|
|
277
|
+
// for the (rare) case where someone declares two whole-block
|
|
278
|
+
// hints for the same name.
|
|
279
|
+
g.wholeBlockEntry = ref;
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
// Pass 2 — emit keys per the contract documented above.
|
|
283
|
+
for (const g of groups.values()) {
|
|
284
|
+
const baseKey = `_${g.name.replace(/-/g, "_")}`;
|
|
285
|
+
// Whole-block surface (string form OR object whole-block-with-hints
|
|
286
|
+
// form). String entry takes precedence for `_<name>` /
|
|
287
|
+
// `contextValues[<name>]`; if no string but a whole-block object
|
|
288
|
+
// entry exists, the object entry fills the same slot.
|
|
289
|
+
if (g.stringEntry || g.wholeBlockEntry) {
|
|
290
|
+
if (!projectDirExists) {
|
|
291
|
+
contextValues[g.name] = null;
|
|
292
|
+
templateContext[baseKey] = null;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
try {
|
|
296
|
+
const blockData = readBlock(ctx.cwd, g.name);
|
|
297
|
+
contextValues[g.name] = blockData;
|
|
298
|
+
templateContext[baseKey] = blockData !== null ? wrapBlockContent(g.name, blockData) : null;
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
contextValues[g.name] = null;
|
|
302
|
+
templateContext[baseKey] = null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// Hint variables for the whole-block-with-hints object form. These
|
|
307
|
+
// are independent of the per-item path — they belong to the
|
|
308
|
+
// whole-block-with-hints entry only. Per-item depth/focus live
|
|
309
|
+
// inside the `_<name>_items` array elements (see below).
|
|
310
|
+
if (g.wholeBlockEntry) {
|
|
311
|
+
templateContext[`${baseKey}_depth`] = g.wholeBlockEntry.depth ?? 0;
|
|
312
|
+
if (g.wholeBlockEntry.focus) {
|
|
313
|
+
templateContext[`${baseKey}_focus`] = g.wholeBlockEntry.focus;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// Per-item path — populates the array slot for any group with at
|
|
317
|
+
// least one object-with-item entry. Resolution is eager: the first
|
|
318
|
+
// unresolvable id throws and aborts the compile, naming the
|
|
319
|
+
// original spec.contextBlocks index of the offending entry.
|
|
320
|
+
if (g.itemEntries.length > 0) {
|
|
321
|
+
if (!projectDirExists) {
|
|
322
|
+
const first = g.itemEntries[0];
|
|
323
|
+
if (!first)
|
|
324
|
+
continue;
|
|
325
|
+
throw new AgentCompileError(spec.name, `contextBlocks[${first.index}]: cannot resolve item '${first.ref.item}' in block '${first.ref.name}' — '.project/' directory does not exist at ${ctx.cwd}`);
|
|
326
|
+
}
|
|
327
|
+
const idIndex = getIdIndex();
|
|
328
|
+
const arrayElems = [];
|
|
329
|
+
const rawArrayElems = [];
|
|
330
|
+
for (const { ref, index } of g.itemEntries) {
|
|
331
|
+
const itemId = ref.item;
|
|
332
|
+
if (!itemId)
|
|
333
|
+
continue;
|
|
334
|
+
const loc = idIndex.get(itemId);
|
|
335
|
+
if (!loc) {
|
|
336
|
+
throw new AgentCompileError(spec.name, `contextBlocks[${index}]: item id '${itemId}' not found (declared block '${ref.name}'). Verify the id exists in '.project/${ref.name}.json' and that buildIdIndex covers its host block.`);
|
|
337
|
+
}
|
|
338
|
+
const wrapped = wrapItemContent(ref.name, itemId, loc.item);
|
|
339
|
+
arrayElems.push({
|
|
340
|
+
item: wrapped,
|
|
341
|
+
raw: loc.item,
|
|
342
|
+
depth: ref.depth ?? 0,
|
|
343
|
+
focus: ref.focus ?? null,
|
|
344
|
+
id: itemId,
|
|
345
|
+
name: ref.name,
|
|
346
|
+
});
|
|
347
|
+
rawArrayElems.push(loc.item);
|
|
348
|
+
}
|
|
349
|
+
templateContext[`${baseKey}_items`] = arrayElems;
|
|
350
|
+
contextValues[`${g.name}_items`] = rawArrayElems;
|
|
351
|
+
// Singular-key backward-compat: only when there is exactly one
|
|
352
|
+
// object-with-item entry AND no string sibling for the same
|
|
353
|
+
// name. The string-sibling exclusion is the mixed-shape
|
|
354
|
+
// precedence rule — `_<name>` already names the whole-block
|
|
355
|
+
// surface, so `_<name>_item` would be ambiguous about which
|
|
356
|
+
// surface it refers to.
|
|
357
|
+
if (g.itemEntries.length === 1 && !g.stringEntry) {
|
|
358
|
+
const only = g.itemEntries[0];
|
|
359
|
+
const elem = arrayElems[0];
|
|
360
|
+
if (only && elem) {
|
|
361
|
+
templateContext[`${baseKey}_item`] = elem.item;
|
|
362
|
+
templateContext[`${baseKey}_depth`] = elem.depth;
|
|
363
|
+
if (only.ref.focus) {
|
|
364
|
+
templateContext[`${baseKey}_focus`] = only.ref.focus;
|
|
365
|
+
}
|
|
366
|
+
contextValues[`${g.name}_item`] = elem.raw;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
89
369
|
}
|
|
90
370
|
}
|
|
91
371
|
}
|
|
372
|
+
// Nunjucks globals for per-item macro composition (Plans 6/7/8 consumers,
|
|
373
|
+
// plus the v0.24.0 enforceBudget global). Registration is delegated to
|
|
374
|
+
// `registerCompositionGlobals` so that both compileAgent and
|
|
375
|
+
// `renderItemById` (in pi-workflows) share the same composition-globals
|
|
376
|
+
// contract — adding or modifying a global means editing one helper, not
|
|
377
|
+
// two parallel paths.
|
|
378
|
+
//
|
|
379
|
+
// Behavioural contract per global:
|
|
380
|
+
//
|
|
381
|
+
// `resolve(id)` — lazy idIndex lookup; returns the ItemLocation
|
|
382
|
+
// or null. Templates use it as the dispatch
|
|
383
|
+
// primitive for cross-reference inlining.
|
|
384
|
+
//
|
|
385
|
+
// `render_recursive(loc, depth)`
|
|
386
|
+
// — looks up the per-item macro via the renderer
|
|
387
|
+
// registry, then renders it with `(item, depth)`
|
|
388
|
+
// bound. Cycle detection is scoped to this
|
|
389
|
+
// composition pass via a closure-local Set keyed
|
|
390
|
+
// on `loc.item.id`. On a re-entry the helper
|
|
391
|
+
// returns `[cycle: <id>]` and does not recurse.
|
|
392
|
+
// The visited entry is removed after rendering
|
|
393
|
+
// so sibling subtrees can reach the same item
|
|
394
|
+
// at the same depth (only true ancestor cycles
|
|
395
|
+
// are blocked).
|
|
396
|
+
//
|
|
397
|
+
// `enforceBudget(rendered, blockName, fieldPathOrShorthand)`
|
|
398
|
+
// — measures rendered text against the named field's
|
|
399
|
+
// `x-prompt-budget` annotation; returns truncated
|
|
400
|
+
// output when over budget, pass-through when the
|
|
401
|
+
// annotation is absent or the schema is missing.
|
|
402
|
+
// Truncation warnings are appended to the
|
|
403
|
+
// closure-captured `compilePassWarnings` array
|
|
404
|
+
// and surfaced on `CompiledAgent.budgetWarnings`
|
|
405
|
+
// after compile returns.
|
|
406
|
+
//
|
|
407
|
+
// addGlobal overwrites prior registrations on the same env — intentional;
|
|
408
|
+
// each compileAgent call owns its own visited-set + warnings scope.
|
|
409
|
+
const env = ctx.env;
|
|
410
|
+
const compilePassWarnings = [];
|
|
411
|
+
registerCompositionGlobals({
|
|
412
|
+
env,
|
|
413
|
+
cwd: ctx.cwd,
|
|
414
|
+
rendererRegistry: ctx.rendererRegistry,
|
|
415
|
+
getIdIndex,
|
|
416
|
+
warningsCollector: compilePassWarnings,
|
|
417
|
+
});
|
|
92
418
|
let systemPrompt;
|
|
93
419
|
if (spec.systemPromptTemplate) {
|
|
94
420
|
systemPrompt = renderTemplateFile(ctx.env, spec.systemPromptTemplate, templateContext);
|
|
@@ -113,6 +439,13 @@ export function compileAgent(spec, ctx) {
|
|
|
113
439
|
model: spec.model,
|
|
114
440
|
outputSchema: resolveOutputSchemaForCompile(spec.outputSchema, ctx.cwd),
|
|
115
441
|
contextValues,
|
|
442
|
+
// Surface budget-truncation warnings collected during composition.
|
|
443
|
+
// Empty array means no enforceBudget call exceeded a budget; the
|
|
444
|
+
// field is included unconditionally so consumers can rely on its
|
|
445
|
+
// presence for trace pipelines without optional-chaining ceremony.
|
|
446
|
+
// (Legacy consumers reading the previous shape still work — the
|
|
447
|
+
// field is an optional addition on the type, not a rename.)
|
|
448
|
+
budgetWarnings: compilePassWarnings.length > 0 ? compilePassWarnings : undefined,
|
|
116
449
|
};
|
|
117
450
|
}
|
|
118
451
|
//# sourceMappingURL=compile.js.map
|
package/dist/compile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type nunjucks from "nunjucks";
|
|
2
|
+
export interface DispatchInlineMacroOptions {
|
|
3
|
+
/** Active Nunjucks environment whose globals the macro is expected to consume. */
|
|
4
|
+
env: nunjucks.Environment;
|
|
5
|
+
/** Absolute path to the per-item macro file. */
|
|
6
|
+
templatePath: string;
|
|
7
|
+
/** Macro name to invoke inside the macro file. */
|
|
8
|
+
macroName: string;
|
|
9
|
+
/** Item payload bound to the macro's `item` parameter. */
|
|
10
|
+
item: unknown;
|
|
11
|
+
/** Recursion depth bound to the macro's `depth` parameter. */
|
|
12
|
+
depth: number;
|
|
13
|
+
/**
|
|
14
|
+
* Opaque prefix dropped into the `[render_error: <errorContext>: <detail>]`
|
|
15
|
+
* marker on failure. Typical shape: `<kind>/<id>`.
|
|
16
|
+
*/
|
|
17
|
+
errorContext: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Read the macro source, inline-dispatch the named macro with `item`/`depth`
|
|
21
|
+
* bound, and return the rendered output. On file-read failure or render-time
|
|
22
|
+
* exception, returns the corresponding `[render_error: …]` marker.
|
|
23
|
+
*/
|
|
24
|
+
export declare function dispatchInlineMacro(opts: DispatchInlineMacroOptions): string;
|
|
25
|
+
//# sourceMappingURL=dispatch-inline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-inline.d.ts","sourceRoot":"","sources":["../src/dispatch-inline.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAGrC,MAAM,WAAW,0BAA0B;IAC1C,kFAAkF;IAClF,GAAG,EAAE,QAAQ,CAAC,WAAW,CAAC;IAC1B,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,IAAI,EAAE,OAAO,CAAC;IACd,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,MAAM,CAgB5E"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline-by-source macro dispatch.
|
|
3
|
+
*
|
|
4
|
+
* Both `renderItemById` (pi-workflows) and `render_recursive` (the Nunjucks
|
|
5
|
+
* global registered by `registerCompositionGlobals` in this package) need to
|
|
6
|
+
* render an item through an absolute-path per-item macro file. The shared
|
|
7
|
+
* approach: read the macro file source, append `{{ <macroName>(item, depth) }}`
|
|
8
|
+
* so the dispatch resolves regardless of the env's FileSystemLoader search
|
|
9
|
+
* paths, then `renderString` against a context that exposes `item` and
|
|
10
|
+
* `depth`. Any failure surfaces as a `[render_error: <errorContext>: <detail>]`
|
|
11
|
+
* marker so the caller's output contract holds.
|
|
12
|
+
*
|
|
13
|
+
* The `errorContext` parameter is the caller-composed prefix that lands inside
|
|
14
|
+
* the `[render_error: …]` marker; emit-site shape varies (`<kind>/<id>`) so
|
|
15
|
+
* the helper keeps it as opaque text.
|
|
16
|
+
*/
|
|
17
|
+
import fs from "node:fs";
|
|
18
|
+
import { renderErrorMarker } from "./markers.js";
|
|
19
|
+
/**
|
|
20
|
+
* Read the macro source, inline-dispatch the named macro with `item`/`depth`
|
|
21
|
+
* bound, and return the rendered output. On file-read failure or render-time
|
|
22
|
+
* exception, returns the corresponding `[render_error: …]` marker.
|
|
23
|
+
*/
|
|
24
|
+
export function dispatchInlineMacro(opts) {
|
|
25
|
+
const { env, templatePath, macroName, item, depth, errorContext } = opts;
|
|
26
|
+
let macroSource;
|
|
27
|
+
try {
|
|
28
|
+
macroSource = fs.readFileSync(templatePath, "utf-8");
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return renderErrorMarker(`${errorContext}: macro file unreadable at ${templatePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
32
|
+
}
|
|
33
|
+
const inline = `${macroSource}\n{{ ${macroName}(item, depth) }}`;
|
|
34
|
+
try {
|
|
35
|
+
return env.renderString(inline, { item, depth });
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
return renderErrorMarker(`${errorContext}: ${err instanceof Error ? err.message : String(err)}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=dispatch-inline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-inline.js","sourceRoot":"","sources":["../src/dispatch-inline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAoBjD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAgC;IACnE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IACzE,IAAI,WAAmB,CAAC;IACxB,IAAI,CAAC;QACJ,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO,iBAAiB,CACvB,GAAG,YAAY,8BAA8B,YAAY,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAChH,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,WAAW,QAAQ,SAAS,kBAAkB,CAAC;IACjE,IAAI,CAAC;QACJ,OAAO,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO,iBAAiB,CAAC,GAAG,YAAY,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClG,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema-field path expansion helpers.
|
|
3
|
+
*
|
|
4
|
+
* Translation between the readable dotted shorthand callers prefer
|
|
5
|
+
* (`decisions.items.context`) and the JSON-pointer form the budget enforcer
|
|
6
|
+
* and other JSON-Schema-aware consumers consume
|
|
7
|
+
* (`/properties/decisions/items/properties/context`). Pulled out of compile.ts
|
|
8
|
+
* so the canonical implementation lives in one place — pi-workflows'
|
|
9
|
+
* test-helpers consumes the export rather than re-implementing the same
|
|
10
|
+
* expansion locally.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Translate a dotted shorthand schema-field reference into a JSON-pointer path.
|
|
14
|
+
*
|
|
15
|
+
* Accepts either:
|
|
16
|
+
* - JSON pointer (`/properties/decisions/items/properties/context`) — passes through.
|
|
17
|
+
* - Dotted shorthand (`decisions.items.context`) — expands each segment as a
|
|
18
|
+
* `properties/<segment>` pair, with `items` translated literally to the
|
|
19
|
+
* `items` keyword (the standard JSON-Schema array-element key). The
|
|
20
|
+
* shorthand expansion is idempotent for inputs that already begin with
|
|
21
|
+
* `/`, so callers can pass either form without ceremony.
|
|
22
|
+
*
|
|
23
|
+
* Examples:
|
|
24
|
+
* "decisions.items.context"
|
|
25
|
+
* → "/properties/decisions/items/properties/context"
|
|
26
|
+
* "decisions.items.consequences.items"
|
|
27
|
+
* → "/properties/decisions/items/properties/consequences/items"
|
|
28
|
+
* "/properties/foo/properties/bar"
|
|
29
|
+
* → "/properties/foo/properties/bar" (unchanged)
|
|
30
|
+
*/
|
|
31
|
+
export declare function expandFieldPathShorthand(fieldPathOrShorthand: string): string;
|
|
32
|
+
//# sourceMappingURL=field-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-path.d.ts","sourceRoot":"","sources":["../src/field-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CAAC,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAa7E"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema-field path expansion helpers.
|
|
3
|
+
*
|
|
4
|
+
* Translation between the readable dotted shorthand callers prefer
|
|
5
|
+
* (`decisions.items.context`) and the JSON-pointer form the budget enforcer
|
|
6
|
+
* and other JSON-Schema-aware consumers consume
|
|
7
|
+
* (`/properties/decisions/items/properties/context`). Pulled out of compile.ts
|
|
8
|
+
* so the canonical implementation lives in one place — pi-workflows'
|
|
9
|
+
* test-helpers consumes the export rather than re-implementing the same
|
|
10
|
+
* expansion locally.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Translate a dotted shorthand schema-field reference into a JSON-pointer path.
|
|
14
|
+
*
|
|
15
|
+
* Accepts either:
|
|
16
|
+
* - JSON pointer (`/properties/decisions/items/properties/context`) — passes through.
|
|
17
|
+
* - Dotted shorthand (`decisions.items.context`) — expands each segment as a
|
|
18
|
+
* `properties/<segment>` pair, with `items` translated literally to the
|
|
19
|
+
* `items` keyword (the standard JSON-Schema array-element key). The
|
|
20
|
+
* shorthand expansion is idempotent for inputs that already begin with
|
|
21
|
+
* `/`, so callers can pass either form without ceremony.
|
|
22
|
+
*
|
|
23
|
+
* Examples:
|
|
24
|
+
* "decisions.items.context"
|
|
25
|
+
* → "/properties/decisions/items/properties/context"
|
|
26
|
+
* "decisions.items.consequences.items"
|
|
27
|
+
* → "/properties/decisions/items/properties/consequences/items"
|
|
28
|
+
* "/properties/foo/properties/bar"
|
|
29
|
+
* → "/properties/foo/properties/bar" (unchanged)
|
|
30
|
+
*/
|
|
31
|
+
export function expandFieldPathShorthand(fieldPathOrShorthand) {
|
|
32
|
+
if (fieldPathOrShorthand.startsWith("/"))
|
|
33
|
+
return fieldPathOrShorthand;
|
|
34
|
+
if (fieldPathOrShorthand === "")
|
|
35
|
+
return "";
|
|
36
|
+
const segments = fieldPathOrShorthand.split(".");
|
|
37
|
+
const out = [];
|
|
38
|
+
for (const seg of segments) {
|
|
39
|
+
if (seg === "items") {
|
|
40
|
+
out.push("items");
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
out.push("properties", seg);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return `/${out.join("/")}`;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=field-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-path.js","sourceRoot":"","sources":["../src/field-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,wBAAwB,CAAC,oBAA4B;IACpE,IAAI,oBAAoB,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,oBAAoB,CAAC;IACtE,IAAI,oBAAoB,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACP,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACF,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC5B,CAAC"}
|