@earendil-works/pi-agent-core 0.85.0 → 0.86.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/README.md +16 -6
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +64 -22
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent.d.ts +5 -3
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +15 -6
- package/dist/agent.js.map +1 -1
- package/dist/harness/config.d.ts +1 -1
- package/dist/harness/config.d.ts.map +1 -1
- package/dist/harness/config.js +10 -2
- package/dist/harness/config.js.map +1 -1
- package/dist/harness/env/nodejs.d.ts +2 -1
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +98 -27
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/execution/tools.d.ts +1 -1
- package/dist/harness/execution/tools.d.ts.map +1 -1
- package/dist/harness/execution/tools.js +0 -2
- package/dist/harness/execution/tools.js.map +1 -1
- package/dist/harness/messages.d.ts.map +1 -1
- package/dist/harness/messages.js +1 -0
- package/dist/harness/messages.js.map +1 -1
- package/dist/harness/pico3/bash.d.ts +10 -0
- package/dist/harness/pico3/bash.d.ts.map +1 -0
- package/dist/harness/pico3/bash.js +25 -0
- package/dist/harness/pico3/bash.js.map +1 -0
- package/dist/harness/pico3/bounded.d.ts +21 -0
- package/dist/harness/pico3/bounded.d.ts.map +1 -0
- package/dist/harness/pico3/bounded.js +98 -0
- package/dist/harness/pico3/bounded.js.map +1 -0
- package/dist/harness/pico3/chord.d.ts +41 -0
- package/dist/harness/pico3/chord.d.ts.map +1 -0
- package/dist/harness/pico3/chord.js +130 -0
- package/dist/harness/pico3/chord.js.map +1 -0
- package/dist/harness/pico3/context.d.ts +16 -0
- package/dist/harness/pico3/context.d.ts.map +1 -0
- package/dist/harness/pico3/context.js +88 -0
- package/dist/harness/pico3/context.js.map +1 -0
- package/dist/harness/pico3/harness.d.ts +197 -0
- package/dist/harness/pico3/harness.d.ts.map +1 -0
- package/dist/harness/pico3/harness.js +654 -0
- package/dist/harness/pico3/harness.js.map +1 -0
- package/dist/harness/pico3/hooks.d.ts +10 -0
- package/dist/harness/pico3/hooks.d.ts.map +1 -0
- package/dist/harness/pico3/hooks.js +33 -0
- package/dist/harness/pico3/hooks.js.map +1 -0
- package/dist/harness/pico3/index.d.ts +19 -0
- package/dist/harness/pico3/index.d.ts.map +1 -0
- package/dist/harness/pico3/index.js +15 -0
- package/dist/harness/pico3/index.js.map +1 -0
- package/dist/harness/pico3/jsonl.d.ts +58 -0
- package/dist/harness/pico3/jsonl.d.ts.map +1 -0
- package/dist/harness/pico3/jsonl.js +325 -0
- package/dist/harness/pico3/jsonl.js.map +1 -0
- package/dist/harness/pico3/kinds/collapse.d.ts +49 -0
- package/dist/harness/pico3/kinds/collapse.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/collapse.js +191 -0
- package/dist/harness/pico3/kinds/collapse.js.map +1 -0
- package/dist/harness/pico3/kinds/entries.d.ts +78 -0
- package/dist/harness/pico3/kinds/entries.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/entries.js +13 -0
- package/dist/harness/pico3/kinds/entries.js.map +1 -0
- package/dist/harness/pico3/kinds/frames.d.ts +9 -0
- package/dist/harness/pico3/kinds/frames.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/frames.js +75 -0
- package/dist/harness/pico3/kinds/frames.js.map +1 -0
- package/dist/harness/pico3/kinds/generation.d.ts +94 -0
- package/dist/harness/pico3/kinds/generation.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/generation.js +504 -0
- package/dist/harness/pico3/kinds/generation.js.map +1 -0
- package/dist/harness/pico3/kinds/job.d.ts +44 -0
- package/dist/harness/pico3/kinds/job.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/job.js +143 -0
- package/dist/harness/pico3/kinds/job.js.map +1 -0
- package/dist/harness/pico3/kinds/plugin.d.ts +15 -0
- package/dist/harness/pico3/kinds/plugin.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/plugin.js +35 -0
- package/dist/harness/pico3/kinds/plugin.js.map +1 -0
- package/dist/harness/pico3/kinds/post-tools.d.ts +22 -0
- package/dist/harness/pico3/kinds/post-tools.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/post-tools.js +145 -0
- package/dist/harness/pico3/kinds/post-tools.js.map +1 -0
- package/dist/harness/pico3/kinds/task-api.d.ts +3 -0
- package/dist/harness/pico3/kinds/task-api.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/task-api.js +45 -0
- package/dist/harness/pico3/kinds/task-api.js.map +1 -0
- package/dist/harness/pico3/kinds/tool.d.ts +43 -0
- package/dist/harness/pico3/kinds/tool.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/tool.js +373 -0
- package/dist/harness/pico3/kinds/tool.js.map +1 -0
- package/dist/harness/pico3/membrane.d.ts +23 -0
- package/dist/harness/pico3/membrane.d.ts.map +1 -0
- package/dist/harness/pico3/membrane.js +141 -0
- package/dist/harness/pico3/membrane.js.map +1 -0
- package/dist/harness/pico3/memory.d.ts +53 -0
- package/dist/harness/pico3/memory.d.ts.map +1 -0
- package/dist/harness/pico3/memory.js +264 -0
- package/dist/harness/pico3/memory.js.map +1 -0
- package/dist/harness/pico3/scheduler.d.ts +46 -0
- package/dist/harness/pico3/scheduler.d.ts.map +1 -0
- package/dist/harness/pico3/scheduler.js +438 -0
- package/dist/harness/pico3/scheduler.js.map +1 -0
- package/dist/harness/pico3/session.d.ts +263 -0
- package/dist/harness/pico3/session.d.ts.map +1 -0
- package/dist/harness/pico3/session.js +1347 -0
- package/dist/harness/pico3/session.js.map +1 -0
- package/dist/harness/pico3/system.d.ts +126 -0
- package/dist/harness/pico3/system.d.ts.map +1 -0
- package/dist/harness/pico3/system.js +244 -0
- package/dist/harness/pico3/system.js.map +1 -0
- package/dist/harness/pico3/types.d.ts +973 -0
- package/dist/harness/pico3/types.d.ts.map +1 -0
- package/dist/harness/pico3/types.js +96 -0
- package/dist/harness/pico3/types.js.map +1 -0
- package/dist/harness/pico3/view.d.ts +34 -0
- package/dist/harness/pico3/view.d.ts.map +1 -0
- package/dist/harness/pico3/view.js +417 -0
- package/dist/harness/pico3/view.js.map +1 -0
- package/dist/harness/runtime/drive/boundary.d.ts.map +1 -1
- package/dist/harness/runtime/drive/boundary.js +6 -3
- package/dist/harness/runtime/drive/boundary.js.map +1 -1
- package/dist/harness/runtime/drive/response.d.ts.map +1 -1
- package/dist/harness/runtime/drive/response.js +4 -4
- package/dist/harness/runtime/drive/response.js.map +1 -1
- package/dist/harness/runtime/drive/retry.d.ts +2 -2
- package/dist/harness/runtime/drive/retry.d.ts.map +1 -1
- package/dist/harness/runtime/drive/retry.js +3 -6
- package/dist/harness/runtime/drive/retry.js.map +1 -1
- package/dist/harness/runtime/drive/structural.d.ts.map +1 -1
- package/dist/harness/runtime/drive/structural.js +5 -5
- package/dist/harness/runtime/drive/structural.js.map +1 -1
- package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -1
- package/dist/harness/runtime/drive/tool-placement.js +2 -27
- package/dist/harness/runtime/drive/tool-placement.js.map +1 -1
- package/dist/harness/runtime/drive/tools.d.ts.map +1 -1
- package/dist/harness/runtime/drive/tools.js.map +1 -1
- package/dist/harness/session/fork-policy.d.ts +20 -12
- package/dist/harness/session/fork-policy.d.ts.map +1 -1
- package/dist/harness/session/fork-policy.js +45 -12
- package/dist/harness/session/fork-policy.js.map +1 -1
- package/dist/harness/session/fork.d.ts +0 -2
- package/dist/harness/session/fork.d.ts.map +1 -1
- package/dist/harness/session/fork.js +20 -68
- package/dist/harness/session/fork.js.map +1 -1
- package/dist/harness/session/in-memory-storage-state.d.ts +5 -5
- package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -1
- package/dist/harness/session/in-memory-storage-state.js +99 -39
- package/dist/harness/session/in-memory-storage-state.js.map +1 -1
- package/dist/harness/session/index.d.ts +1 -1
- package/dist/harness/session/index.d.ts.map +1 -1
- package/dist/harness/session/index.js +1 -1
- package/dist/harness/session/index.js.map +1 -1
- package/dist/harness/session/jsonl/fork.d.ts +38 -0
- package/dist/harness/session/jsonl/fork.d.ts.map +1 -0
- package/dist/harness/session/jsonl/fork.js +264 -0
- package/dist/harness/session/jsonl/fork.js.map +1 -0
- package/dist/harness/session/jsonl/io.d.ts +14 -0
- package/dist/harness/session/jsonl/io.d.ts.map +1 -0
- package/dist/harness/session/jsonl/io.js +86 -0
- package/dist/harness/session/jsonl/io.js.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts +33 -8
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -1
- package/dist/harness/session/jsonl/legacy-v3.js +285 -206
- package/dist/harness/session/jsonl/legacy-v3.js.map +1 -1
- package/dist/harness/session/jsonl/repo.d.ts +2 -1
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +36 -20
- package/dist/harness/session/jsonl/repo.js.map +1 -1
- package/dist/harness/session/jsonl/storage.d.ts +4 -5
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
- package/dist/harness/session/jsonl/storage.js +39 -113
- package/dist/harness/session/jsonl/storage.js.map +1 -1
- package/dist/harness/session/memory.d.ts +3 -5
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +9 -14
- package/dist/harness/session/memory.js.map +1 -1
- package/dist/harness/session/testing/conformance/session-repo.d.ts +2 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -1
- package/dist/harness/session/testing/conformance/session-repo.js +220 -1
- package/dist/harness/session/testing/conformance/session-repo.js.map +1 -1
- package/dist/harness/session/testing/index.d.ts +1 -1
- package/dist/harness/session/testing/index.d.ts.map +1 -1
- package/dist/harness/session/testing/index.js +1 -1
- package/dist/harness/session/testing/index.js.map +1 -1
- package/dist/harness/session/types.d.ts +1 -0
- package/dist/harness/session/types.d.ts.map +1 -1
- package/dist/harness/session/types.js.map +1 -1
- package/dist/harness/types.d.ts +14 -0
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/proxy.d.ts +2 -2
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js.map +1 -1
- package/dist/types.d.ts +30 -14
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +10 -6
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
export function defineSystemSection(definition) {
|
|
2
|
+
return Object.freeze(definition);
|
|
3
|
+
}
|
|
4
|
+
export const systemSections = {
|
|
5
|
+
identity: defineSystemSection({ key: "identity", render: (v) => v }),
|
|
6
|
+
environment: defineSystemSection({
|
|
7
|
+
key: "environment",
|
|
8
|
+
render: (v) => `Working directory: ${v.cwd}`,
|
|
9
|
+
}),
|
|
10
|
+
skills: defineSystemSection({
|
|
11
|
+
key: "skills",
|
|
12
|
+
render: (v) => v.map((s) => `- ${s.name}: ${s.description}`).join("\n"),
|
|
13
|
+
}),
|
|
14
|
+
};
|
|
15
|
+
export const sectionSeed = (section, value) => ({
|
|
16
|
+
key: section.key,
|
|
17
|
+
value,
|
|
18
|
+
});
|
|
19
|
+
export const removeSection = (key) => ({ key, remove: true });
|
|
20
|
+
export async function foldCanonical(reads, conversationId) {
|
|
21
|
+
const managed = [];
|
|
22
|
+
let before;
|
|
23
|
+
let baseline = null;
|
|
24
|
+
scan: for (;;) {
|
|
25
|
+
const page = await reads.scanEntries({
|
|
26
|
+
conversationId,
|
|
27
|
+
kind: "pi.system",
|
|
28
|
+
limit: 64,
|
|
29
|
+
...(before === undefined ? {} : { before }),
|
|
30
|
+
});
|
|
31
|
+
for (const e of page) {
|
|
32
|
+
managed.push(e);
|
|
33
|
+
if (e.data.baseline) {
|
|
34
|
+
baseline = e.id;
|
|
35
|
+
break scan;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (page.length < 64)
|
|
39
|
+
break;
|
|
40
|
+
before = page[page.length - 1].id;
|
|
41
|
+
}
|
|
42
|
+
managed.reverse();
|
|
43
|
+
const canonical = new Map();
|
|
44
|
+
for (const e of managed)
|
|
45
|
+
for (const r of e.data.sections)
|
|
46
|
+
r.action === "remove"
|
|
47
|
+
? canonical.delete(r.key)
|
|
48
|
+
: canonical.set(r.key, { value: r.value, rendered: r.rendered });
|
|
49
|
+
return { canonical, newestManaged: managed[managed.length - 1]?.id ?? null, newestBaseline: baseline };
|
|
50
|
+
}
|
|
51
|
+
class Draft {
|
|
52
|
+
values = new Map();
|
|
53
|
+
wrappers = new Map();
|
|
54
|
+
touched = new Set();
|
|
55
|
+
constructor(seed) {
|
|
56
|
+
for (const [k, s] of seed)
|
|
57
|
+
this.values.set(k, s.value);
|
|
58
|
+
}
|
|
59
|
+
get(section) {
|
|
60
|
+
const v = this.values.get(section.key);
|
|
61
|
+
return v === undefined ? undefined : structuredClone(v);
|
|
62
|
+
}
|
|
63
|
+
set(section, value) {
|
|
64
|
+
this.values.set(section.key, value);
|
|
65
|
+
this.touched.add(section.key);
|
|
66
|
+
}
|
|
67
|
+
delete(section) {
|
|
68
|
+
this.values.delete(section.key);
|
|
69
|
+
this.wrappers.delete(section.key);
|
|
70
|
+
this.touched.add(section.key);
|
|
71
|
+
}
|
|
72
|
+
wrap(section, transform) {
|
|
73
|
+
(this.wrappers.get(section.key) ?? this.wrappers.set(section.key, []).get(section.key)).push(transform);
|
|
74
|
+
this.touched.add(section.key);
|
|
75
|
+
}
|
|
76
|
+
snapshot() {
|
|
77
|
+
return {
|
|
78
|
+
values: new Map(this.values),
|
|
79
|
+
wrappers: new Map([...this.wrappers].map(([k, v]) => [k, [...v]])),
|
|
80
|
+
touched: new Set(this.touched),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
restore(s) {
|
|
84
|
+
this.values = s.values;
|
|
85
|
+
this.wrappers = s.wrappers;
|
|
86
|
+
this.touched = s.touched;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Render touched sections (wrappers apply after rendering, in registration order); untouched keep their stored text. */
|
|
90
|
+
function freeze(draft, canonical, registry) {
|
|
91
|
+
const desired = new Map();
|
|
92
|
+
for (const [key, value] of draft.values) {
|
|
93
|
+
if (!draft.touched.has(key)) {
|
|
94
|
+
const prev = canonical.get(key);
|
|
95
|
+
if (prev)
|
|
96
|
+
desired.set(key, prev);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const def = registry.get(key);
|
|
100
|
+
if (def === undefined)
|
|
101
|
+
continue; // unregistered: cannot re-render; treated as removed
|
|
102
|
+
let rendered = def.render(value);
|
|
103
|
+
for (const w of draft.wrappers.get(key) ?? [])
|
|
104
|
+
rendered = w(rendered);
|
|
105
|
+
desired.set(key, { value, rendered });
|
|
106
|
+
}
|
|
107
|
+
return desired;
|
|
108
|
+
}
|
|
109
|
+
export const sameSnapshot = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
110
|
+
export async function takeSnapshot(tx, conversationId, sections, tools) {
|
|
111
|
+
const { canonical, newestManaged, newestBaseline } = await foldCanonical(tx, conversationId);
|
|
112
|
+
const head = await tx.newestEntry(conversationId, { withHead: true });
|
|
113
|
+
const r = tx.snapshot({ doc: "rewindable", conversationId }); // a plain copy: the snapshot outlives this transaction
|
|
114
|
+
const conv = await tx.conversation(conversationId);
|
|
115
|
+
return {
|
|
116
|
+
snapshot: {
|
|
117
|
+
newestManaged,
|
|
118
|
+
newestBaseline,
|
|
119
|
+
newestHead: head?.id ?? null,
|
|
120
|
+
settings: {
|
|
121
|
+
...(r.model === undefined ? {} : { model: r.model }),
|
|
122
|
+
thinkingLevel: r.thinkingLevel,
|
|
123
|
+
selectedTools: [...r.selectedTools],
|
|
124
|
+
profile: r.profile,
|
|
125
|
+
},
|
|
126
|
+
sectionsRev: sections.revision,
|
|
127
|
+
toolsRev: tools.revision,
|
|
128
|
+
},
|
|
129
|
+
canonical,
|
|
130
|
+
seed: newestManaged === null ? conv?.sections : undefined, // §8.1: the seed applies while there is no local managed entry
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/** Off the line: seed the draft, run handlers, freeze. */
|
|
134
|
+
export async function prepareDraft(rt, sections, canonical, seed, settings, onReport, ctx) {
|
|
135
|
+
const draft = new Draft(canonical);
|
|
136
|
+
for (const s of seed ?? [])
|
|
137
|
+
"remove" in s ? draft.delete({ key: s.key }) : draft.set({ key: s.key, render: () => "" }, s.value);
|
|
138
|
+
const defaultTools = [];
|
|
139
|
+
for (const name of settings.selectedTools) {
|
|
140
|
+
const t = rt.tools.get(name);
|
|
141
|
+
t ? defaultTools.push(t) : onReport(`selected tool ${name} is not registered`);
|
|
142
|
+
}
|
|
143
|
+
let tools = defaultTools;
|
|
144
|
+
for (const binding of rt.hooks.handlers()) {
|
|
145
|
+
const before = draft.snapshot();
|
|
146
|
+
try {
|
|
147
|
+
const out = await binding.handlers.systemInstructions?.({ sections: draft, config: settings, tools: defaultTools }, binding.api, ctx);
|
|
148
|
+
if (out?.tools)
|
|
149
|
+
tools = out.tools;
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (ctx.abortSignal?.aborted)
|
|
153
|
+
throw error;
|
|
154
|
+
draft.restore(before); // collect / skip: this handler's edits are rolled back
|
|
155
|
+
onReport(String(error));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return { desired: freeze(draft, canonical, sections.map), tools };
|
|
159
|
+
}
|
|
160
|
+
/** On the line, in the `prepared` commit: diff desired against canonical; baseline if a head intervened. */
|
|
161
|
+
export async function planManagedEntry(tx, conversationId, snapshot, canonical, desired, tools, now) {
|
|
162
|
+
// §12.4: no managed history at all → first preparation appends a full baseline; and a usable
|
|
163
|
+
// baseline must follow the newest head.
|
|
164
|
+
const needBaseline = snapshot.newestManaged === null ||
|
|
165
|
+
(snapshot.newestHead !== null &&
|
|
166
|
+
(snapshot.newestBaseline === null || snapshot.newestHead > snapshot.newestBaseline));
|
|
167
|
+
const toolOf = (t) => ({
|
|
168
|
+
name: t.name,
|
|
169
|
+
description: t.description,
|
|
170
|
+
parameters: structuredClone(t.parameters),
|
|
171
|
+
});
|
|
172
|
+
// Previous effective tools: those declared by the newest managed entry chain (we recompute from canonical's owner: the tail message).
|
|
173
|
+
const { messages } = await tx.context(conversationId);
|
|
174
|
+
const previous = new Map();
|
|
175
|
+
for (const m of messages)
|
|
176
|
+
if (m.role === "system") {
|
|
177
|
+
for (const t of m.toolsRemoved ?? [])
|
|
178
|
+
previous.delete(t.name);
|
|
179
|
+
for (const t of m.toolsAdded ?? [])
|
|
180
|
+
previous.set(t.name, t);
|
|
181
|
+
}
|
|
182
|
+
if (needBaseline) {
|
|
183
|
+
const sections = [...desired].map(([key, s]) => ({
|
|
184
|
+
key,
|
|
185
|
+
action: "set",
|
|
186
|
+
value: s.value,
|
|
187
|
+
rendered: s.rendered,
|
|
188
|
+
}));
|
|
189
|
+
const content = sections.map((s) => (s.action === "set" ? `## ${s.key}\n${s.rendered}` : "")).join("\n\n");
|
|
190
|
+
const { entries } = await tx.context(conversationId);
|
|
191
|
+
const edits = entries
|
|
192
|
+
.filter((e) => e.kind === "pi.system" && e.id > (snapshot.newestHead ?? 0))
|
|
193
|
+
.map((e) => ({ target: e.id, action: "omit" }));
|
|
194
|
+
const message = {
|
|
195
|
+
role: "system",
|
|
196
|
+
content,
|
|
197
|
+
toolsAdded: tools.map(toolOf),
|
|
198
|
+
timestamp: now,
|
|
199
|
+
};
|
|
200
|
+
return { data: { baseline: true, sections }, model: [message], ...(edits.length ? { edits } : {}) };
|
|
201
|
+
}
|
|
202
|
+
const changed = [];
|
|
203
|
+
for (const [key, s] of desired) {
|
|
204
|
+
const prev = canonical.get(key);
|
|
205
|
+
if (!prev || prev.rendered !== s.rendered || JSON.stringify(prev.value) !== JSON.stringify(s.value))
|
|
206
|
+
changed.push({ key, action: "set", value: s.value, rendered: s.rendered });
|
|
207
|
+
}
|
|
208
|
+
for (const key of canonical.keys())
|
|
209
|
+
if (!desired.has(key))
|
|
210
|
+
changed.push({ key, action: "remove" });
|
|
211
|
+
const added = tools.filter((t) => !previous.has(t.name));
|
|
212
|
+
const removed = [...previous.values()].filter((p) => !tools.some((t) => t.name === p.name));
|
|
213
|
+
if (changed.length === 0 && added.length === 0 && removed.length === 0)
|
|
214
|
+
return undefined;
|
|
215
|
+
const renderChanged = changed.some((s) => s.action === "remove" || canonical.get(s.key)?.rendered !== s.rendered);
|
|
216
|
+
if (!renderChanged && added.length === 0 && removed.length === 0)
|
|
217
|
+
return { data: { sections: changed }, model: [] }; // metadata-only delta
|
|
218
|
+
const content = changed
|
|
219
|
+
.map((s) => s.action === "set"
|
|
220
|
+
? `The ${s.key} section now reads:\n${s.rendered}`
|
|
221
|
+
: `The ${s.key} section no longer applies.`)
|
|
222
|
+
.join("\n\n");
|
|
223
|
+
const message = {
|
|
224
|
+
role: "system",
|
|
225
|
+
content,
|
|
226
|
+
...(added.length ? { toolsAdded: added.map(toolOf) } : {}),
|
|
227
|
+
...(removed.length ? { toolsRemoved: removed } : {}),
|
|
228
|
+
timestamp: now,
|
|
229
|
+
};
|
|
230
|
+
return { data: { sections: changed }, model: [message] };
|
|
231
|
+
}
|
|
232
|
+
/** Tools effective in a projected request: fold toolsAdded/toolsRemoved across its SystemMessages. */
|
|
233
|
+
export function effectiveTools(messages) {
|
|
234
|
+
const tools = new Map();
|
|
235
|
+
for (const m of messages)
|
|
236
|
+
if (m.role === "system") {
|
|
237
|
+
for (const t of m.toolsRemoved ?? [])
|
|
238
|
+
tools.delete(t.name);
|
|
239
|
+
for (const t of m.toolsAdded ?? [])
|
|
240
|
+
tools.set(t.name, t);
|
|
241
|
+
}
|
|
242
|
+
return [...tools.values()];
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/harness/pico3/system.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Context } from \"@earendil-works/chord\";\nimport type {\n\tAnyToolDeclaration,\n\tContextEdit,\n\tCoreTx,\n\tEntry,\n\tHookInfo,\n\tHookResult,\n\tId,\n\tJsonValue,\n\tRewindableState,\n\tRuntime,\n\tStored,\n\tSystemMessage,\n} from \"./types.ts\";\n\n// ---------------------------------------------------------------------------\n// Sections (pico §12.1). A section is a stable key plus a pure renderer. Only\n// keys, payloads and rendered text are stored; never renderers.\n// ---------------------------------------------------------------------------\n\nexport interface SystemSection<T extends JsonValue = JsonValue> {\n\treadonly key: string;\n\trender(value: T): string;\n}\nexport function defineSystemSection<T extends JsonValue>(definition: {\n\tkey: string;\n\trender(value: T): string;\n}): SystemSection<T> {\n\treturn Object.freeze(definition);\n}\n\nexport type EnvironmentInfo = { cwd: string };\nexport type SkillInfo = { name: string; description: string };\nexport const systemSections = {\n\tidentity: defineSystemSection<string>({ key: \"identity\", render: (v) => v }),\n\tenvironment: defineSystemSection<EnvironmentInfo>({\n\t\tkey: \"environment\",\n\t\trender: (v) => `Working directory: ${v.cwd}`,\n\t}),\n\tskills: defineSystemSection<SkillInfo[]>({\n\t\tkey: \"skills\",\n\t\trender: (v) => v.map((s) => `- ${s.name}: ${s.description}`).join(\"\\n\"),\n\t}),\n} as const;\n\n/** Section seed for a new conversation (§8.1): set with a checked pair, or remove an inherited key. */\nexport type SectionSeed = { key: string; value: JsonValue } | { key: string; remove: true };\nexport const sectionSeed = <T extends JsonValue>(section: SystemSection<T>, value: T): SectionSeed => ({\n\tkey: section.key,\n\tvalue,\n});\nexport const removeSection = (key: string): SectionSeed => ({ key, remove: true });\n\n// ---------------------------------------------------------------------------\n// The managed entry (§12.3)\n// ---------------------------------------------------------------------------\n\nexport type SectionRecord =\n\t| { key: string; action: \"set\"; value: JsonValue; rendered: string }\n\t| { key: string; action: \"remove\" };\nexport type SystemEntryData = { baseline?: true; sections: SectionRecord[] };\n/** A metadata-only delta has `model: []`. */\nexport type SystemEntry = Entry & { kind: \"pi.system\"; model: [] | [Stored<SystemMessage>]; data: SystemEntryData };\n\n// ---------------------------------------------------------------------------\n// Canonical state (§12.4): fold the fork-visible managed entries from the\n// newest baseline forward. Uses the kind scan; never depends on heads or edits.\n// ---------------------------------------------------------------------------\n\ntype SectionState = { value: JsonValue; rendered: string };\nexport type Canonical = Map<string, SectionState>; // insertion order is canonical order\n\nexport async function foldCanonical(\n\treads: Pick<CoreTx, \"scanEntries\">,\n\tconversationId: Id,\n): Promise<{ canonical: Canonical; newestManaged: Id | null; newestBaseline: Id | null }> {\n\tconst managed: SystemEntry[] = [];\n\tlet before: Id | undefined;\n\tlet baseline: Id | null = null;\n\tscan: for (;;) {\n\t\tconst page = await reads.scanEntries({\n\t\t\tconversationId,\n\t\t\tkind: \"pi.system\",\n\t\t\tlimit: 64,\n\t\t\t...(before === undefined ? {} : { before }),\n\t\t});\n\t\tfor (const e of page) {\n\t\t\tmanaged.push(e as SystemEntry);\n\t\t\tif ((e as SystemEntry).data.baseline) {\n\t\t\t\tbaseline = e.id;\n\t\t\t\tbreak scan;\n\t\t\t}\n\t\t}\n\t\tif (page.length < 64) break;\n\t\tbefore = page[page.length - 1]!.id;\n\t}\n\tmanaged.reverse();\n\tconst canonical: Canonical = new Map();\n\tfor (const e of managed)\n\t\tfor (const r of e.data.sections)\n\t\t\tr.action === \"remove\"\n\t\t\t\t? canonical.delete(r.key)\n\t\t\t\t: canonical.set(r.key, { value: r.value, rendered: r.rendered });\n\treturn { canonical, newestManaged: managed[managed.length - 1]?.id ?? null, newestBaseline: baseline };\n}\n\n// ---------------------------------------------------------------------------\n// Draft (§12.2): what `systemInstructions` handlers edit.\n// ---------------------------------------------------------------------------\n\nexport interface SystemSectionDraft {\n\tget<T extends JsonValue>(section: SystemSection<T>): T | undefined; // owned copy\n\tset<T extends JsonValue>(section: SystemSection<T>, value: T): void; // existing key keeps position; new key appends\n\tdelete(section: { key: string }): void;\n\twrap<T extends JsonValue>(section: SystemSection<T>, transform: (rendered: string) => string): void; // preparation-local\n}\n\nclass Draft implements SystemSectionDraft {\n\tvalues = new Map<string, JsonValue>();\n\twrappers = new Map<string, ((r: string) => string)[]>();\n\ttouched = new Set<string>();\n\tconstructor(seed: Canonical) {\n\t\tfor (const [k, s] of seed) this.values.set(k, s.value);\n\t}\n\tget<T extends JsonValue>(section: SystemSection<T>) {\n\t\tconst v = this.values.get(section.key);\n\t\treturn v === undefined ? undefined : (structuredClone(v) as T);\n\t}\n\tset<T extends JsonValue>(section: SystemSection<T>, value: T) {\n\t\tthis.values.set(section.key, value);\n\t\tthis.touched.add(section.key);\n\t}\n\tdelete(section: { key: string }) {\n\t\tthis.values.delete(section.key);\n\t\tthis.wrappers.delete(section.key);\n\t\tthis.touched.add(section.key);\n\t}\n\twrap<T extends JsonValue>(section: SystemSection<T>, transform: (r: string) => string) {\n\t\t(this.wrappers.get(section.key) ?? this.wrappers.set(section.key, []).get(section.key)!).push(transform);\n\t\tthis.touched.add(section.key);\n\t}\n\tsnapshot() {\n\t\treturn {\n\t\t\tvalues: new Map(this.values),\n\t\t\twrappers: new Map([...this.wrappers].map(([k, v]) => [k, [...v]])),\n\t\t\ttouched: new Set(this.touched),\n\t\t};\n\t}\n\trestore(s: ReturnType<Draft[\"snapshot\"]>) {\n\t\tthis.values = s.values;\n\t\tthis.wrappers = s.wrappers;\n\t\tthis.touched = s.touched;\n\t}\n}\n\n/** Render touched sections (wrappers apply after rendering, in registration order); untouched keep their stored text. */\nfunction freeze(draft: Draft, canonical: Canonical, registry: ReadonlyMap<string, SystemSection>): Canonical {\n\tconst desired: Canonical = new Map();\n\tfor (const [key, value] of draft.values) {\n\t\tif (!draft.touched.has(key)) {\n\t\t\tconst prev = canonical.get(key);\n\t\t\tif (prev) desired.set(key, prev);\n\t\t\tcontinue;\n\t\t}\n\t\tconst def = registry.get(key);\n\t\tif (def === undefined) continue; // unregistered: cannot re-render; treated as removed\n\t\tlet rendered = (def as SystemSection).render(value);\n\t\tfor (const w of draft.wrappers.get(key) ?? []) rendered = w(rendered);\n\t\tdesired.set(key, { value, rendered });\n\t}\n\treturn desired;\n}\n\n// ---------------------------------------------------------------------------\n// Preparation (§12.5)\n// ---------------------------------------------------------------------------\n\nexport interface SectionRegistry {\n\treadonly map: ReadonlyMap<string, SystemSection>;\n\treadonly revision: number;\n}\nexport interface ToolRegistry {\n\treadonly map: ReadonlyMap<string, AnyToolDeclaration>;\n\treadonly revision: number;\n}\n\n/** Snapshot S. Compared field by field before the `prepared` commit. */\nexport interface PreparationSnapshot {\n\tnewestManaged: Id | null;\n\tnewestBaseline: Id | null;\n\tnewestHead: Id | null;\n\tsettings: { model?: JsonValue; thinkingLevel: JsonValue; selectedTools: string[]; profile: JsonValue };\n\tsectionsRev: number;\n\ttoolsRev: number;\n}\nexport const sameSnapshot = (a: PreparationSnapshot, b: PreparationSnapshot) => JSON.stringify(a) === JSON.stringify(b);\n\nexport async function takeSnapshot(\n\ttx: Pick<CoreTx, \"scanEntries\" | \"newestEntry\" | \"snapshot\" | \"conversation\">,\n\tconversationId: Id,\n\tsections: SectionRegistry,\n\ttools: ToolRegistry,\n): Promise<{ snapshot: PreparationSnapshot; canonical: Canonical; seed: readonly SectionSeed[] | undefined }> {\n\tconst { canonical, newestManaged, newestBaseline } = await foldCanonical(tx, conversationId);\n\tconst head = await tx.newestEntry(conversationId, { withHead: true });\n\tconst r = tx.snapshot({ doc: \"rewindable\", conversationId }); // a plain copy: the snapshot outlives this transaction\n\tconst conv = await tx.conversation(conversationId);\n\treturn {\n\t\tsnapshot: {\n\t\t\tnewestManaged,\n\t\t\tnewestBaseline,\n\t\t\tnewestHead: head?.id ?? null,\n\t\t\tsettings: {\n\t\t\t\t...(r.model === undefined ? {} : { model: r.model }),\n\t\t\t\tthinkingLevel: r.thinkingLevel,\n\t\t\t\tselectedTools: [...r.selectedTools],\n\t\t\t\tprofile: r.profile,\n\t\t\t},\n\t\t\tsectionsRev: sections.revision,\n\t\t\ttoolsRev: tools.revision,\n\t\t},\n\t\tcanonical,\n\t\tseed: newestManaged === null ? conv?.sections : undefined, // §8.1: the seed applies while there is no local managed entry\n\t};\n}\n\nexport interface SystemInstructionsHooks {\n\t/** Edit the draft; optionally override the tool loadout (last override wins). A throwing handler's edits are rolled back. */\n\tsystemInstructions(\n\t\tinput: {\n\t\t\tsections: SystemSectionDraft;\n\t\t\tconfig: PreparationSnapshot[\"settings\"];\n\t\t\ttools: readonly AnyToolDeclaration[];\n\t\t},\n\t\tinfo: HookInfo,\n\t\tctx: Context,\n\t): HookResult<{ tools?: readonly AnyToolDeclaration[] }>;\n}\n\n/** Off the line: seed the draft, run handlers, freeze. */\nexport async function prepareDraft(\n\trt: Pick<Runtime<SystemInstructionsHooks>, \"hooks\" | \"tools\">,\n\tsections: SectionRegistry,\n\tcanonical: Canonical,\n\tseed: readonly SectionSeed[] | undefined,\n\tsettings: PreparationSnapshot[\"settings\"],\n\tonReport: (m: string) => void,\n\tctx: Context,\n): Promise<{ desired: Canonical; tools: readonly AnyToolDeclaration[] }> {\n\tconst draft = new Draft(canonical);\n\tfor (const s of seed ?? [])\n\t\t\"remove\" in s ? draft.delete({ key: s.key }) : draft.set({ key: s.key, render: () => \"\" }, s.value);\n\n\tconst defaultTools: AnyToolDeclaration[] = [];\n\tfor (const name of settings.selectedTools) {\n\t\tconst t = rt.tools.get(name);\n\t\tt ? defaultTools.push(t) : onReport(`selected tool ${name} is not registered`);\n\t}\n\tlet tools: readonly AnyToolDeclaration[] = defaultTools;\n\tfor (const binding of rt.hooks.handlers()) {\n\t\tconst before = draft.snapshot();\n\t\ttry {\n\t\t\tconst out = await binding.handlers.systemInstructions?.(\n\t\t\t\t{ sections: draft, config: settings, tools: defaultTools },\n\t\t\t\tbinding.api,\n\t\t\t\tctx,\n\t\t\t);\n\t\t\tif (out?.tools) tools = out.tools;\n\t\t} catch (error) {\n\t\t\tif (ctx.abortSignal?.aborted) throw error;\n\t\t\tdraft.restore(before); // collect / skip: this handler's edits are rolled back\n\t\t\tonReport(String(error));\n\t\t}\n\t}\n\treturn { desired: freeze(draft, canonical, sections.map), tools };\n}\n\n/** On the line, in the `prepared` commit: diff desired against canonical; baseline if a head intervened. */\nexport async function planManagedEntry(\n\ttx: Pick<CoreTx, \"context\">,\n\tconversationId: Id,\n\tsnapshot: PreparationSnapshot,\n\tcanonical: Canonical,\n\tdesired: Canonical,\n\ttools: readonly AnyToolDeclaration[],\n\tnow: number,\n): Promise<{ data: SystemEntryData; model: [] | [Stored<SystemMessage>]; edits?: ContextEdit[] } | undefined> {\n\t// §12.4: no managed history at all → first preparation appends a full baseline; and a usable\n\t// baseline must follow the newest head.\n\tconst needBaseline =\n\t\tsnapshot.newestManaged === null ||\n\t\t(snapshot.newestHead !== null &&\n\t\t\t(snapshot.newestBaseline === null || snapshot.newestHead > snapshot.newestBaseline));\n\tconst toolOf = (t: AnyToolDeclaration) => ({\n\t\tname: t.name,\n\t\tdescription: t.description,\n\t\tparameters: structuredClone(t.parameters) as Stored<SystemMessage>[\"toolsAdded\"] extends (infer X)[] | undefined\n\t\t\t? X extends { parameters: infer PP }\n\t\t\t\t? PP\n\t\t\t\t: never\n\t\t\t: never,\n\t});\n\n\t// Previous effective tools: those declared by the newest managed entry chain (we recompute from canonical's owner: the tail message).\n\tconst { messages } = await tx.context(conversationId);\n\tconst previous = new Map<string, { name: string }>();\n\tfor (const m of messages)\n\t\tif (m.role === \"system\") {\n\t\t\tfor (const t of (m as SystemMessage).toolsRemoved ?? []) previous.delete(t.name);\n\t\t\tfor (const t of (m as SystemMessage).toolsAdded ?? []) previous.set(t.name, t);\n\t\t}\n\n\tif (needBaseline) {\n\t\tconst sections: SectionRecord[] = [...desired].map(([key, s]) => ({\n\t\t\tkey,\n\t\t\taction: \"set\",\n\t\t\tvalue: s.value,\n\t\t\trendered: s.rendered,\n\t\t}));\n\t\tconst content = sections.map((s) => (s.action === \"set\" ? `## ${s.key}\\n${s.rendered}` : \"\")).join(\"\\n\\n\");\n\t\tconst { entries } = await tx.context(conversationId);\n\t\tconst edits: ContextEdit[] = entries\n\t\t\t.filter((e: Entry) => e.kind === \"pi.system\" && e.id > (snapshot.newestHead ?? 0))\n\t\t\t.map((e: Entry) => ({ target: e.id, action: \"omit\" as const }));\n\t\tconst message = {\n\t\t\trole: \"system\",\n\t\t\tcontent,\n\t\t\ttoolsAdded: tools.map(toolOf),\n\t\t\ttimestamp: now,\n\t\t} as Stored<SystemMessage>;\n\t\treturn { data: { baseline: true, sections }, model: [message], ...(edits.length ? { edits } : {}) };\n\t}\n\n\tconst changed: SectionRecord[] = [];\n\tfor (const [key, s] of desired) {\n\t\tconst prev = canonical.get(key);\n\t\tif (!prev || prev.rendered !== s.rendered || JSON.stringify(prev.value) !== JSON.stringify(s.value))\n\t\t\tchanged.push({ key, action: \"set\", value: s.value, rendered: s.rendered });\n\t}\n\tfor (const key of canonical.keys()) if (!desired.has(key)) changed.push({ key, action: \"remove\" });\n\tconst added = tools.filter((t) => !previous.has(t.name));\n\tconst removed = [...previous.values()].filter((p) => !tools.some((t) => t.name === p.name));\n\tif (changed.length === 0 && added.length === 0 && removed.length === 0) return undefined;\n\n\tconst renderChanged = changed.some((s) => s.action === \"remove\" || canonical.get(s.key)?.rendered !== s.rendered);\n\tif (!renderChanged && added.length === 0 && removed.length === 0) return { data: { sections: changed }, model: [] }; // metadata-only delta\n\tconst content = changed\n\t\t.map((s) =>\n\t\t\ts.action === \"set\"\n\t\t\t\t? `The ${s.key} section now reads:\\n${s.rendered}`\n\t\t\t\t: `The ${s.key} section no longer applies.`,\n\t\t)\n\t\t.join(\"\\n\\n\");\n\tconst message = {\n\t\trole: \"system\",\n\t\tcontent,\n\t\t...(added.length ? { toolsAdded: added.map(toolOf) } : {}),\n\t\t...(removed.length ? { toolsRemoved: removed } : {}),\n\t\ttimestamp: now,\n\t} as Stored<SystemMessage>;\n\treturn { data: { sections: changed }, model: [message] };\n}\n\n/** Tools effective in a projected request: fold toolsAdded/toolsRemoved across its SystemMessages. */\nexport function effectiveTools(messages: readonly { role: string }[]): { name: string }[] {\n\tconst tools = new Map<string, { name: string }>();\n\tfor (const m of messages)\n\t\tif (m.role === \"system\") {\n\t\t\tfor (const t of (m as SystemMessage).toolsRemoved ?? []) tools.delete(t.name);\n\t\t\tfor (const t of (m as SystemMessage).toolsAdded ?? []) tools.set(t.name, t);\n\t\t}\n\treturn [...tools.values()];\n}\n\nexport type { RewindableState, Runtime };\n"]}
|