@bunshin-cc/bunshin 0.4.5 → 0.4.7
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/bin.js +109 -31
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -183,12 +183,13 @@ function renderIndex(lessons) {
|
|
|
183
183
|
}
|
|
184
184
|
return lines.join("\n") + "\n";
|
|
185
185
|
}
|
|
186
|
-
var DEFAULT_CONFIG, EMPTY_SESSION, Store;
|
|
186
|
+
var RETIRED_DEFAULT_MODELS, DEFAULT_CONFIG, EMPTY_SESSION, Store;
|
|
187
187
|
var init_store = __esm({
|
|
188
188
|
"src/store.ts"() {
|
|
189
189
|
"use strict";
|
|
190
190
|
init_frontmatter();
|
|
191
191
|
init_util();
|
|
192
|
+
RETIRED_DEFAULT_MODELS = /* @__PURE__ */ new Set(["claude-fable-5-1"]);
|
|
192
193
|
DEFAULT_CONFIG = {
|
|
193
194
|
orgId: "local",
|
|
194
195
|
userId: process.env.USER || "me",
|
|
@@ -199,7 +200,7 @@ var init_store = __esm({
|
|
|
199
200
|
apiUrl: "",
|
|
200
201
|
scope: "repo",
|
|
201
202
|
harness: "claude-code",
|
|
202
|
-
model: "claude-
|
|
203
|
+
model: "claude-opus-5-5",
|
|
203
204
|
gateModel: "claude-haiku-4-5-20251001",
|
|
204
205
|
backend: "auto",
|
|
205
206
|
recall: { enabled: true, maxLessons: 4, hookBudgetMs: 3500, useMothership: true },
|
|
@@ -267,6 +268,8 @@ var init_store = __esm({
|
|
|
267
268
|
recall: { ...DEFAULT_CONFIG.recall, ...raw.recall ?? {} },
|
|
268
269
|
reflect: { ...DEFAULT_CONFIG.reflect, ...raw.reflect ?? {} }
|
|
269
270
|
};
|
|
271
|
+
if (RETIRED_DEFAULT_MODELS.has(merged.model)) merged.model = DEFAULT_CONFIG.model;
|
|
272
|
+
if (process.env.BUNSHIN_MODEL) merged.model = process.env.BUNSHIN_MODEL;
|
|
270
273
|
const harness = process.env.BUNSHIN_HARNESS;
|
|
271
274
|
if (harness === "claude-code" || harness === "codex" || harness === "pi" || harness === "other") merged.harness = harness;
|
|
272
275
|
if (!merged.apiKey && merged.credentialFile) {
|
|
@@ -431,9 +434,11 @@ var init_store = __esm({
|
|
|
431
434
|
function emptyStats() {
|
|
432
435
|
return { served: 0, loaded: 0, helped: 0, hurt: 0, byContext: {} };
|
|
433
436
|
}
|
|
437
|
+
var LEARNING_SIGNALS;
|
|
434
438
|
var init_types = __esm({
|
|
435
439
|
"../core/src/v2/types.ts"() {
|
|
436
440
|
"use strict";
|
|
441
|
+
LEARNING_SIGNALS = ["steering", "environment", "knowledge", "capability", "approach"];
|
|
437
442
|
}
|
|
438
443
|
});
|
|
439
444
|
|
|
@@ -1521,7 +1526,8 @@ function renderSection(s, trigger, opts = {}) {
|
|
|
1521
1526
|
const label2 = s.kind === "guardrail" ? "GUARDRAIL" : s.kind.toUpperCase();
|
|
1522
1527
|
const src = sourceLabel(s);
|
|
1523
1528
|
const why = trigger ? `_Why you are seeing this: ${trigger}. Id: ${s.id}_` : `_Id: ${s.id}_`;
|
|
1524
|
-
const
|
|
1529
|
+
const trial = s.localTrial?.length ? [`_Includes ${s.localTrial.length === 1 ? "an edit" : `${s.localTrial.length} edits`} learned on this machine and not yet reviewed: treat ${s.localTrial.length === 1 ? "it" : "them"} as provisional._`] : [];
|
|
1530
|
+
const head = [`### ${label2} (${src}): ${s.title}`, why, ...trial];
|
|
1525
1531
|
const max = opts.maxChars ?? 6e3;
|
|
1526
1532
|
if (s.skill && opts.deployed) {
|
|
1527
1533
|
const part2 = opts.anchor ? (s.outline ?? []).find((h) => h.anchor === opts.anchor) : void 0;
|
|
@@ -1726,9 +1732,20 @@ Lessons already taken from it. Never propose these again, nor a rewording of the
|
|
|
1726
1732
|
${lessons}
|
|
1727
1733
|
`;
|
|
1728
1734
|
}
|
|
1735
|
+
function stampLesson(op, signal, at) {
|
|
1736
|
+
const day = at.slice(0, 10);
|
|
1737
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(day)) return op;
|
|
1738
|
+
const recheck = signal === "environment" ? `; recheck after ${new Date(Date.parse(day) + ENVIRONMENT_RECHECK_DAYS * 864e5).toISOString().slice(0, 10)}` : "";
|
|
1739
|
+
const stamp = `_(learned ${day}${signal ? ` from ${SIGNAL_WORDS[signal]}` : ""}${recheck})_`;
|
|
1740
|
+
if (op.op === "append") return /_\(learned \d{4}-/.test(op.text) ? op : { ...op, text: `${op.text.trimEnd()} ${stamp}` };
|
|
1741
|
+
if (op.op === "create") return /_\(learned \d{4}-/.test(op.section.body) ? op : { ...op, section: { ...op.section, body: `${op.section.body.trimEnd()}
|
|
1742
|
+
|
|
1743
|
+
${stamp}` } };
|
|
1744
|
+
return op;
|
|
1745
|
+
}
|
|
1729
1746
|
function summarizeOp(op) {
|
|
1730
1747
|
const clip2 = (s) => {
|
|
1731
|
-
const one = s.replace(/\s+/g, " ").trim();
|
|
1748
|
+
const one = s.replace(/\s*_\(learned \d{4}-\d{2}-\d{2}[^)]*\)_/g, "").replace(/\s+/g, " ").trim();
|
|
1732
1749
|
return one.length > 100 ? `${one.slice(0, 97)}\u2026` : one;
|
|
1733
1750
|
};
|
|
1734
1751
|
switch (op.op) {
|
|
@@ -1783,8 +1800,14 @@ Capture only what would change how a future agent acts, and is recorded nowhere
|
|
|
1783
1800
|
b. the environment corrected the agent (a command, test, API, motion or grasp failed, then
|
|
1784
1801
|
another approach worked): record the trap AND what worked;
|
|
1785
1802
|
c. knowledge owned by another team surfaced (a process, policy or manual step);
|
|
1786
|
-
d. a capability worked for the first time, or a task was done unusually efficiently
|
|
1803
|
+
d. a capability worked for the first time, or a task was done unusually efficiently;
|
|
1804
|
+
e. looking back over the whole session, the approach itself was the problem (it took many
|
|
1805
|
+
rounds of fixes, it was over-built, it verified too late) and a different way of working
|
|
1806
|
+
would have avoided it. This has no direct ground truth: say what you would do differently
|
|
1807
|
+
next time, as generally as it truly holds, and where it does not hold.
|
|
1787
1808
|
"Nothing new" is the expected outcome for most sessions. Never invent a lesson.
|
|
1809
|
+
Label each suggestion with its "signal": a \u2192 "steering", b \u2192 "environment", c \u2192 "knowledge",
|
|
1810
|
+
d \u2192 "capability", e \u2192 "approach".
|
|
1788
1811
|
|
|
1789
1812
|
## Where it goes
|
|
1790
1813
|
|
|
@@ -1797,7 +1820,10 @@ ${index}
|
|
|
1797
1820
|
Already captured this session (do not repeat): ${input.captured.length ? input.captured.join(", ") : "none"}
|
|
1798
1821
|
|
|
1799
1822
|
Layers you may target: ${input.layers.join(", ")}.
|
|
1800
|
-
|
|
1823
|
+
${input.profileId ? `- How THIS person works, prefers or wants things done (a steering or approach lesson about them,
|
|
1824
|
+
not about the task) \u2192 op "append" to their profile ${input.profileId}, anchor "how-i-work".
|
|
1825
|
+
A lesson for anyone doing the task belongs in the task's document instead.
|
|
1826
|
+
` : ""}- Knowledge about one repo that its team owns \u2192 that repo's section (repo:... ids).
|
|
1801
1827
|
- Cross-repo facts, another team's rules, non-code processes \u2192 a Bunshin section at the right layer.
|
|
1802
1828
|
- If it only holds in some contexts, use op "append" with a "condition" (e.g. "objects over 50 g").
|
|
1803
1829
|
${robot ? `- Values that belong to THIS robot or cell (calibration, pixel columns, colour thresholds under this
|
|
@@ -1824,7 +1850,8 @@ At most ${max} suggestions. Schema:
|
|
|
1824
1850
|
"paths"?: string[], "entities"?: string[], "skills"?: string[]}}
|
|
1825
1851
|
| {"op": "param", "key": string, "value": string|number|boolean}
|
|
1826
1852
|
| {"op": "situation", "text": string},
|
|
1827
|
-
"rationale": string, "urgency": "normal"|"urgent"
|
|
1853
|
+
"rationale": string, "urgency": "normal"|"urgent",
|
|
1854
|
+
"signal": "steering"|"environment"|"knowledge"|"capability"|"approach"}]}`;
|
|
1828
1855
|
}
|
|
1829
1856
|
function extractJson(text2) {
|
|
1830
1857
|
const fenced = text2.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
@@ -1900,7 +1927,8 @@ function parseReflection(raw, opts = { layers: [] }) {
|
|
|
1900
1927
|
target: { ...sectionId ? { sectionId } : {}, ...layer ? { layer } : {} },
|
|
1901
1928
|
op,
|
|
1902
1929
|
rationale: clean(it.rationale) || "captured from session",
|
|
1903
|
-
urgency: it.urgency === "urgent" ? "urgent" : "normal"
|
|
1930
|
+
urgency: it.urgency === "urgent" ? "urgent" : "normal",
|
|
1931
|
+
...LEARNING_SIGNALS.includes(it.signal) ? { signal: it.signal } : {}
|
|
1904
1932
|
});
|
|
1905
1933
|
if (out.length >= (opts.max ?? 4)) break;
|
|
1906
1934
|
}
|
|
@@ -1913,8 +1941,9 @@ function toSuggestion(p, base) {
|
|
|
1913
1941
|
contextId: base.contextId,
|
|
1914
1942
|
authorUserId: base.authorUserId,
|
|
1915
1943
|
target: p.target,
|
|
1916
|
-
op: p.op,
|
|
1944
|
+
op: stampLesson(p.op, p.signal, base.createdAt),
|
|
1917
1945
|
rationale: p.rationale,
|
|
1946
|
+
...p.signal ? { signal: p.signal } : {},
|
|
1918
1947
|
evidenceEpisodeIds: base.episodeId ? [base.episodeId] : [],
|
|
1919
1948
|
trial: { uses: 0, successes: 0, failures: 0 },
|
|
1920
1949
|
origin: base.origin,
|
|
@@ -1923,12 +1952,21 @@ function toSuggestion(p, base) {
|
|
|
1923
1952
|
createdAt: base.createdAt
|
|
1924
1953
|
};
|
|
1925
1954
|
}
|
|
1926
|
-
var REFLECT_MARKER, REFLECT_SCHEMA, KINDS, anchorOf, clean, strList;
|
|
1955
|
+
var REFLECT_MARKER, ENVIRONMENT_RECHECK_DAYS, SIGNAL_WORDS, REFLECT_SCHEMA, KINDS, anchorOf, clean, strList;
|
|
1927
1956
|
var init_reflect = __esm({
|
|
1928
1957
|
"../core/src/v2/reflect.ts"() {
|
|
1929
1958
|
"use strict";
|
|
1930
1959
|
init_redact();
|
|
1960
|
+
init_types();
|
|
1931
1961
|
REFLECT_MARKER = "BUNSHIN:reflect";
|
|
1962
|
+
ENVIRONMENT_RECHECK_DAYS = 90;
|
|
1963
|
+
SIGNAL_WORDS = {
|
|
1964
|
+
steering: "a person's correction",
|
|
1965
|
+
environment: "the environment",
|
|
1966
|
+
knowledge: "another team's knowledge",
|
|
1967
|
+
capability: "a first success",
|
|
1968
|
+
approach: "reflection on the approach"
|
|
1969
|
+
};
|
|
1932
1970
|
REFLECT_SCHEMA = {
|
|
1933
1971
|
type: "object",
|
|
1934
1972
|
additionalProperties: false,
|
|
@@ -1944,7 +1982,8 @@ var init_reflect = __esm({
|
|
|
1944
1982
|
target: { type: "object", properties: { sectionId: { type: "string" }, layer: { type: "string" } } },
|
|
1945
1983
|
op: { type: "object" },
|
|
1946
1984
|
rationale: { type: "string" },
|
|
1947
|
-
urgency: { type: "string", enum: ["normal", "urgent"] }
|
|
1985
|
+
urgency: { type: "string", enum: ["normal", "urgent"] },
|
|
1986
|
+
signal: { type: "string", enum: ["steering", "environment", "knowledge", "capability", "approach"] }
|
|
1948
1987
|
}
|
|
1949
1988
|
}
|
|
1950
1989
|
}
|
|
@@ -2003,6 +2042,14 @@ var init_research = __esm({
|
|
|
2003
2042
|
}
|
|
2004
2043
|
});
|
|
2005
2044
|
|
|
2045
|
+
// ../core/src/v2/profile.ts
|
|
2046
|
+
var init_profile = __esm({
|
|
2047
|
+
"../core/src/v2/profile.ts"() {
|
|
2048
|
+
"use strict";
|
|
2049
|
+
init_types();
|
|
2050
|
+
}
|
|
2051
|
+
});
|
|
2052
|
+
|
|
2006
2053
|
// ../core/src/v2/index.ts
|
|
2007
2054
|
var init_v2 = __esm({
|
|
2008
2055
|
"../core/src/v2/index.ts"() {
|
|
@@ -2019,6 +2066,7 @@ var init_v2 = __esm({
|
|
|
2019
2066
|
init_reconcile();
|
|
2020
2067
|
init_release();
|
|
2021
2068
|
init_research();
|
|
2069
|
+
init_profile();
|
|
2022
2070
|
}
|
|
2023
2071
|
});
|
|
2024
2072
|
|
|
@@ -2682,7 +2730,7 @@ function planDeploy(bundle, p, harnesses) {
|
|
|
2682
2730
|
if (!prev || (LAYER_RANK[layerKind(s.layer)] ?? 0) > (LAYER_RANK[layerKind(prev.layer)] ?? 0)) byName.set(s.skill.name, s);
|
|
2683
2731
|
}
|
|
2684
2732
|
const skills = [...byName.values()].sort((a, b) => a.skill.name.localeCompare(b.skill.name));
|
|
2685
|
-
const instructions = active.filter((s) => s.delivery === "always" && !s.skill).sort((a, b) => (a.packPath ?? a.title).localeCompare(b.packPath ?? b.title));
|
|
2733
|
+
const instructions = active.filter((s) => s.delivery === "always" && !s.skill && !s.profileOf).sort((a, b) => (a.packPath ?? a.title).localeCompare(b.packPath ?? b.title));
|
|
2686
2734
|
const plan = { docs: /* @__PURE__ */ new Map(), instructions, skills };
|
|
2687
2735
|
const roots = [...harnesses.has("claude-code") ? [p.claudeSkills] : [], ...harnesses.has("codex") ? [p.codexSkills] : []];
|
|
2688
2736
|
for (const s of skills) {
|
|
@@ -3197,13 +3245,25 @@ function baselineOf(bundle) {
|
|
|
3197
3245
|
}
|
|
3198
3246
|
function renderInstructions(bundle) {
|
|
3199
3247
|
const docs = instructionDocs(bundle);
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3248
|
+
const profiles = docs.filter((d) => d.profileOf);
|
|
3249
|
+
const standing = docs.filter((d) => !d.profileOf);
|
|
3250
|
+
const parts = [];
|
|
3251
|
+
if (profiles.length) {
|
|
3252
|
+
parts.push(
|
|
3253
|
+
["## Who you work for (Bunshin profile)", "Bunshin keeps this current from their sessions and corrections, and tells you when it changes.", "", ...profiles.map((d) => d.body.trim())].join("\n")
|
|
3254
|
+
);
|
|
3255
|
+
}
|
|
3256
|
+
if (standing.length) {
|
|
3257
|
+
parts.push(
|
|
3258
|
+
[
|
|
3259
|
+
`## Standing instructions (your organization, from Bunshin ${lib(bundle?.libraryVersion)})`,
|
|
3260
|
+
"Follow these as you would CLAUDE.md. Bunshin re-delivers them after /clear and compaction, and tells you when they change.",
|
|
3261
|
+
"",
|
|
3262
|
+
...standing.map((d) => d.body.trim())
|
|
3263
|
+
].join("\n")
|
|
3264
|
+
);
|
|
3265
|
+
}
|
|
3266
|
+
return parts.join("\n\n");
|
|
3207
3267
|
}
|
|
3208
3268
|
function lineDiff(before, after, max = MAX_DIFF_LINES) {
|
|
3209
3269
|
const a = before.split("\n");
|
|
@@ -3237,11 +3297,11 @@ function changesSince(base, bundle, skillPath) {
|
|
|
3237
3297
|
const old = base.instructions[d.id];
|
|
3238
3298
|
if (old === d.body) continue;
|
|
3239
3299
|
if (old === void 0) {
|
|
3240
|
-
lines.push(`New standing instructions ("${d.title}"):`, d.body.trim(), "");
|
|
3300
|
+
lines.push(d.profileOf ? `The profile of the person you work for ("${d.title}"):` : `New standing instructions ("${d.title}"):`, d.body.trim(), "");
|
|
3241
3301
|
continue;
|
|
3242
3302
|
}
|
|
3243
3303
|
const diff = lineDiff(old, d.body);
|
|
3244
|
-
if (diff.length) lines.push(`Standing instructions changed ("${d.title}"); follow the new text:`, ...diff, "");
|
|
3304
|
+
if (diff.length) lines.push(d.profileOf ? `The profile of the person you work for changed ("${d.title}"):` : `Standing instructions changed ("${d.title}"); follow the new text:`, ...diff, "");
|
|
3245
3305
|
}
|
|
3246
3306
|
for (const id of Object.keys(base.instructions)) if (!now.some((d) => d.id === id)) lines.push(`Standing instructions withdrawn (${id}): stop following them.`, "");
|
|
3247
3307
|
const skillLines = [];
|
|
@@ -3707,13 +3767,13 @@ function applyOverlays(sections, overlays, ctx) {
|
|
|
3707
3767
|
if (!ACTIVE_OVERLAY.has(o.status) || o.kind !== "local-section") continue;
|
|
3708
3768
|
if (o.op.op === "create") {
|
|
3709
3769
|
const id = o.sectionId || localSectionId(o.suggestionId);
|
|
3710
|
-
sections.set(id, draftToSection(id, o.op.section, ctx, ownLayer(ctx), o.appliedAt));
|
|
3770
|
+
sections.set(id, { ...draftToSection(id, o.op.section, ctx, ownLayer(ctx), o.appliedAt), localTrial: [o.suggestionId] });
|
|
3711
3771
|
continue;
|
|
3712
3772
|
}
|
|
3713
3773
|
const base = o.sectionId ? sections.get(o.sectionId) : void 0;
|
|
3714
3774
|
if (!base) continue;
|
|
3715
3775
|
const res = applyOpToBody(base.body, o.op);
|
|
3716
|
-
if (res.ok && res.text !== base.body) sections.set(base.id, { ...base, body: res.text, updatedAt: o.appliedAt });
|
|
3776
|
+
if (res.ok && res.text !== base.body) sections.set(base.id, { ...base, body: res.text, updatedAt: o.appliedAt, localTrial: [...base.localTrial ?? [], o.suggestionId] });
|
|
3717
3777
|
}
|
|
3718
3778
|
}
|
|
3719
3779
|
function localView(v2, config, cwd, opts = {}) {
|
|
@@ -4382,9 +4442,9 @@ function episodeIdFor(contextId, sessionId) {
|
|
|
4382
4442
|
return `e_${createHash2("sha256").update(`${contextId}
|
|
4383
4443
|
${sessionId}`).digest("hex").slice(0, 16)}`;
|
|
4384
4444
|
}
|
|
4385
|
-
function runClaudeFork(sessionId, prompt, { cwd, timeoutMs = FORK_TIMEOUT_MS } = {}) {
|
|
4445
|
+
function runClaudeFork(sessionId, prompt, { cwd, model, timeoutMs = FORK_TIMEOUT_MS } = {}) {
|
|
4386
4446
|
const bin = process.env.BUNSHIN_CLAUDE_BIN || "claude";
|
|
4387
|
-
const args = ["-p", "--resume", sessionId, "--fork-session", "--output-format", "json", prompt];
|
|
4447
|
+
const args = ["-p", "--resume", sessionId, "--fork-session", "--output-format", "json", ...model ? ["--model", model] : [], prompt];
|
|
4388
4448
|
return new Promise((resolve) => {
|
|
4389
4449
|
let out = "";
|
|
4390
4450
|
let err = "";
|
|
@@ -4482,20 +4542,25 @@ async function runReflectionV2(store, opts) {
|
|
|
4482
4542
|
const episodeId = episodeIdFor(view.ctx.id, opts.sessionId);
|
|
4483
4543
|
const prior = session.suggestionIds.map((id) => v2.readSuggestion(id)).filter((s) => !!s);
|
|
4484
4544
|
const captured = [.../* @__PURE__ */ new Set([...session.captured, ...prior.map((s) => s.target.sectionId ?? localSectionId(s.id))])];
|
|
4485
|
-
const
|
|
4545
|
+
const profile = view.sections.find((s) => s.profileOf && s.profileOf === config.userId && s.status === "active");
|
|
4546
|
+
const index = [
|
|
4547
|
+
...profile ? [{ id: profile.id, kind: profile.kind, layer: profile.layer, title: profile.title, when: "how the person you work for works", ...profile.outline?.length ? { outline: profile.outline } : {} }] : [],
|
|
4548
|
+
...reflectionIndex(view, [...session.loaded, ...session.pushed, ...session.served], session.task, opts.focus, humanTurnsOf(session.transcriptPath)).filter((s) => s.id !== profile?.id)
|
|
4549
|
+
];
|
|
4486
4550
|
const harness = session.harness ?? config.harness;
|
|
4487
4551
|
const facts = readFacts(session.transcriptPath);
|
|
4488
4552
|
const turns = facts?.turns.length ?? 0;
|
|
4489
4553
|
const from = reflectCursor(session, turns);
|
|
4490
4554
|
const lessons = [.../* @__PURE__ */ new Set([...prior.map(lessonLine), ...session.serverLessons ?? []])].slice(0, 40);
|
|
4491
4555
|
const earlier = from > 0 || lessons.length ? { ...from > 0 && facts ? { from: anchorAt(facts, from) } : {}, lessons } : void 0;
|
|
4492
|
-
const promptBase = { contextKind: view.ctx.kind, layers: view.layers, index, captured, ...opts.focus ? { focus: opts.focus } : {}, ...earlier ? { earlier } : {} };
|
|
4556
|
+
const promptBase = { contextKind: view.ctx.kind, layers: view.layers, index, captured, ...opts.focus ? { focus: opts.focus } : {}, ...earlier ? { earlier } : {}, ...profile ? { profileId: profile.id } : {} };
|
|
4493
4557
|
let raw = null;
|
|
4494
4558
|
if (harness === "claude-code") {
|
|
4495
|
-
const fork = await runClaudeFork(opts.sessionId, buildReflectPrompt(promptBase), { cwd: session.cwd });
|
|
4559
|
+
const fork = await runClaudeFork(opts.sessionId, buildReflectPrompt(promptBase), { cwd: session.cwd, model: config.model });
|
|
4496
4560
|
v2.log("v2-reflect-fork", {
|
|
4497
4561
|
session: opts.sessionId,
|
|
4498
4562
|
ok: fork.ok,
|
|
4563
|
+
model: config.model,
|
|
4499
4564
|
cache: true,
|
|
4500
4565
|
cache_read_input_tokens: fork.usage?.cache_read_input_tokens ?? null,
|
|
4501
4566
|
cache_creation_input_tokens: fork.usage?.cache_creation_input_tokens ?? null,
|
|
@@ -4784,6 +4849,13 @@ var init_uicmd = __esm({
|
|
|
4784
4849
|
// src/v2/hooks.ts
|
|
4785
4850
|
import fs14 from "node:fs";
|
|
4786
4851
|
import path11 from "node:path";
|
|
4852
|
+
function inContext(s) {
|
|
4853
|
+
return s.inContext ?? [...s.loaded, ...s.pushed];
|
|
4854
|
+
}
|
|
4855
|
+
function markInContext(s, ...ids) {
|
|
4856
|
+
s.inContext = s.inContext ?? [...s.loaded, ...s.pushed];
|
|
4857
|
+
addUnique(s.inContext, ...ids);
|
|
4858
|
+
}
|
|
4787
4859
|
function touch(v2, ctx, patch = () => {
|
|
4788
4860
|
}) {
|
|
4789
4861
|
const id = ctx.input.session_id || "no-session";
|
|
@@ -4852,6 +4924,7 @@ function liveSummary(text2) {
|
|
|
4852
4924
|
for (const m of text2.matchAll(/- `([^`]+)` updated \((v\d+ → v\d+)\)/g)) items.push(`${m[1]} ${m[2]}`);
|
|
4853
4925
|
for (const m of text2.matchAll(/- `([^`]+)` was retired/g)) items.push(`${m[1]} retired`);
|
|
4854
4926
|
if (/Standing instructions (changed|withdrawn)|New standing instructions/.test(text2)) items.push("standing instructions changed");
|
|
4927
|
+
if (/The profile of the person you work for/.test(text2)) items.push("your profile");
|
|
4855
4928
|
return `library updated${range ? ` (${range[2]})` : ""}: ${items.join(", ") || "changes delivered to the agent"}`;
|
|
4856
4929
|
}
|
|
4857
4930
|
async function dispatch(event, ctx) {
|
|
@@ -4996,7 +5069,7 @@ async function onPrompt(ctx) {
|
|
|
4996
5069
|
if (!prompt.trim()) return withLive({});
|
|
4997
5070
|
const config = ctx.store.config();
|
|
4998
5071
|
const view = localView(v2, config, ctx.cwd);
|
|
4999
|
-
const injected =
|
|
5072
|
+
const injected = inContext(session);
|
|
5000
5073
|
const res = auto(view.sections, view.reader, prompt, { exclude: injected });
|
|
5001
5074
|
const remote = await remoteAuto(ctx, prompt, injected);
|
|
5002
5075
|
if (remote) {
|
|
@@ -5016,6 +5089,7 @@ async function onPrompt(ctx) {
|
|
|
5016
5089
|
v2.updateSession(session.sessionId, ctx.cwd, (s) => {
|
|
5017
5090
|
addUnique(s.served, sec.id);
|
|
5018
5091
|
addUnique(s.loaded, sec.id);
|
|
5092
|
+
markInContext(s, sec.id);
|
|
5019
5093
|
});
|
|
5020
5094
|
v2.log("v2-auto", { session: session.sessionId, section: sec.id, reason: res.reason });
|
|
5021
5095
|
updateFeed(v2, session.sessionId, (f) => {
|
|
@@ -5069,13 +5143,14 @@ function onPreToolUse(ctx) {
|
|
|
5069
5143
|
const paths = raw.map((p) => relativeToRoot(view.root, p, ctx.cwd)).filter((p) => !!p);
|
|
5070
5144
|
const text2 = [session.task, session.lastPrompt].filter(Boolean).join("\n");
|
|
5071
5145
|
if (!paths.length && !text2) return withLive({});
|
|
5072
|
-
const seen =
|
|
5146
|
+
const seen = new Set(inContext(session));
|
|
5073
5147
|
const hits = push(view.sections, view.reader, { paths, text: text2 }).filter((h) => !seen.has(h.section.id)).slice(0, MAX_PUSH);
|
|
5074
5148
|
if (!hits.length) return withLive({});
|
|
5075
5149
|
const ids = hits.map((h) => h.section.id);
|
|
5076
5150
|
v2.updateSession(session.sessionId, ctx.cwd, (s) => {
|
|
5077
5151
|
addUnique(s.pushed, ...ids);
|
|
5078
5152
|
addUnique(s.loaded, ...ids);
|
|
5153
|
+
markInContext(s, ...ids);
|
|
5079
5154
|
addUnique(s.served, ...ids);
|
|
5080
5155
|
});
|
|
5081
5156
|
v2.log("v2-push", { session: session.sessionId, tool: ctx.input.tool_name, hits: hits.map((h) => `${h.section.id} ${h.trigger}`) });
|
|
@@ -5278,7 +5353,10 @@ function onSessionEnd(ctx) {
|
|
|
5278
5353
|
function onPreCompact(ctx) {
|
|
5279
5354
|
const v2 = new V2Store(ctx.store);
|
|
5280
5355
|
const config = ctx.store.config();
|
|
5281
|
-
const session = touch(v2, ctx)
|
|
5356
|
+
const session = touch(v2, ctx, (s) => {
|
|
5357
|
+
s.inContext = [];
|
|
5358
|
+
s.hinted = [];
|
|
5359
|
+
});
|
|
5282
5360
|
if (!config.reflect.enabled) return {};
|
|
5283
5361
|
const scan = scanTranscript(ctx.input.transcript_path ?? session.transcriptPath);
|
|
5284
5362
|
const from = reflectCursor(session, scan.facts.turns.length);
|