blun-king-cli 9.1.368 → 9.1.369
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/bin/cognitive-action-checkpoint.cjs +96 -5
- package/blun.mjs +24 -4
- package/package.json +1 -1
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const crypto = require('node:crypto');
|
|
4
|
+
|
|
3
5
|
const PHASES = new Set(['orient', 'plan', 'act', 'verify', 'learn', 'wait']);
|
|
4
|
-
const
|
|
6
|
+
const MODEL_KEYS = new Set([
|
|
5
7
|
'revision', 'phase', 'lastVerified', 'nextAction', 'expectedEvidence', 'updatedAt',
|
|
6
8
|
]);
|
|
9
|
+
const RUNTIME_KEYS = new Set([...MODEL_KEYS, 'evidenceReceipt']);
|
|
10
|
+
const EVIDENCE_INPUT_KEYS = new Set([
|
|
11
|
+
'turnId', 'toolCallId', 'toolName', 'decision', 'outcome', 'durationMs',
|
|
12
|
+
]);
|
|
13
|
+
const EVIDENCE_DIGEST_RE = /^[a-f0-9]{16}$/u;
|
|
7
14
|
|
|
8
15
|
function bounded(value, field, max = 512) {
|
|
9
16
|
const text = String(value ?? '')
|
|
@@ -28,6 +35,76 @@ function normalizedRevision(value) {
|
|
|
28
35
|
return revision;
|
|
29
36
|
}
|
|
30
37
|
|
|
38
|
+
function normalizedTurnId(value) {
|
|
39
|
+
const turnId = Number(value);
|
|
40
|
+
if (!Number.isSafeInteger(turnId) || turnId < 0) throw new TypeError('evidence turnId must be a non-negative integer');
|
|
41
|
+
return turnId;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function emptyActionEvidenceReceipt(turnId) {
|
|
45
|
+
const normalized = normalizedTurnId(turnId);
|
|
46
|
+
return Object.freeze({
|
|
47
|
+
turnId: normalized,
|
|
48
|
+
completedTools: 0,
|
|
49
|
+
successfulTools: 0,
|
|
50
|
+
failedTools: 0,
|
|
51
|
+
digest: crypto.createHash('sha256').update(`turn:${normalized}:empty`).digest('hex').slice(0, 16),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function normalizeActionEvidenceReceipt(input) {
|
|
56
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) throw new TypeError('evidence receipt must be an object');
|
|
57
|
+
const keys = new Set(['turnId', 'completedTools', 'successfulTools', 'failedTools', 'digest']);
|
|
58
|
+
if (!Object.keys(input).every((key) => keys.has(key)) || Object.keys(input).length !== keys.size) {
|
|
59
|
+
throw new TypeError('evidence receipt fields are invalid');
|
|
60
|
+
}
|
|
61
|
+
const receipt = {
|
|
62
|
+
turnId: normalizedTurnId(input.turnId),
|
|
63
|
+
completedTools: Number(input.completedTools),
|
|
64
|
+
successfulTools: Number(input.successfulTools),
|
|
65
|
+
failedTools: Number(input.failedTools),
|
|
66
|
+
digest: String(input.digest ?? ''),
|
|
67
|
+
};
|
|
68
|
+
if (![receipt.completedTools, receipt.successfulTools, receipt.failedTools]
|
|
69
|
+
.every((value) => Number.isSafeInteger(value) && value >= 0)
|
|
70
|
+
|| receipt.successfulTools + receipt.failedTools !== receipt.completedTools
|
|
71
|
+
|| !EVIDENCE_DIGEST_RE.test(receipt.digest)) {
|
|
72
|
+
throw new TypeError('evidence receipt values are invalid');
|
|
73
|
+
}
|
|
74
|
+
return Object.freeze(receipt);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function advanceActionEvidenceReceipt(current, input) {
|
|
78
|
+
const prior = normalizeActionEvidenceReceipt(current);
|
|
79
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)
|
|
80
|
+
|| Object.keys(input).length !== EVIDENCE_INPUT_KEYS.size
|
|
81
|
+
|| !Object.keys(input).every((key) => EVIDENCE_INPUT_KEYS.has(key))) {
|
|
82
|
+
throw new TypeError('evidence input fields are invalid');
|
|
83
|
+
}
|
|
84
|
+
const turnId = normalizedTurnId(input.turnId);
|
|
85
|
+
const toolCallId = bounded(input.toolCallId, 'toolCallId', 256);
|
|
86
|
+
const toolName = bounded(input.toolName, 'toolName', 128);
|
|
87
|
+
const decision = String(input.decision ?? '');
|
|
88
|
+
const outcome = String(input.outcome ?? '');
|
|
89
|
+
const durationMs = Number(input.durationMs);
|
|
90
|
+
if (turnId !== prior.turnId || !['passed', 'blocked', 'error'].includes(decision)
|
|
91
|
+
|| !['success', 'error', 'cancelled'].includes(outcome)
|
|
92
|
+
|| !Number.isSafeInteger(durationMs) || durationMs < 0) {
|
|
93
|
+
throw new TypeError('evidence input values are invalid');
|
|
94
|
+
}
|
|
95
|
+
const successful = decision === 'passed' && outcome === 'success';
|
|
96
|
+
const digest = crypto.createHash('sha256').update([
|
|
97
|
+
prior.digest, String(turnId), toolCallId, toolName, decision, outcome, String(durationMs),
|
|
98
|
+
].join('\0')).digest('hex').slice(0, 16);
|
|
99
|
+
return Object.freeze({
|
|
100
|
+
turnId,
|
|
101
|
+
completedTools: prior.completedTools + 1,
|
|
102
|
+
successfulTools: prior.successfulTools + (successful ? 1 : 0),
|
|
103
|
+
failedTools: prior.failedTools + (successful ? 0 : 1),
|
|
104
|
+
digest,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
31
108
|
function assertActionCheckpointRevision(current, input) {
|
|
32
109
|
const currentRevision = current === undefined || current === null
|
|
33
110
|
? 0
|
|
@@ -43,27 +120,35 @@ function normalizeActionCheckpoint(input, options = {}) {
|
|
|
43
120
|
if (!input || typeof input !== 'object' || Array.isArray(input)) {
|
|
44
121
|
throw new TypeError('action checkpoint must be an object');
|
|
45
122
|
}
|
|
123
|
+
const allowedKeys = options.preserveRuntimeEvidence === true ? RUNTIME_KEYS : MODEL_KEYS;
|
|
46
124
|
for (const key of Object.keys(input)) {
|
|
47
|
-
if (!
|
|
125
|
+
if (!allowedKeys.has(key)) throw new TypeError(`unsupported field: ${key}`);
|
|
48
126
|
}
|
|
49
127
|
const phase = String(input.phase ?? '').trim();
|
|
50
128
|
if (!PHASES.has(phase)) throw new TypeError('phase is invalid');
|
|
51
129
|
const updatedAt = options.preserveUpdatedAt === true && input.updatedAt !== undefined
|
|
52
130
|
? normalizedTimestamp(input.updatedAt)
|
|
53
131
|
: normalizedTimestamp(options.now ?? new Date());
|
|
54
|
-
|
|
132
|
+
const checkpoint = {
|
|
55
133
|
revision: normalizedRevision(input.revision),
|
|
56
134
|
phase,
|
|
57
135
|
lastVerified: bounded(input.lastVerified, 'lastVerified'),
|
|
58
136
|
nextAction: bounded(input.nextAction, 'nextAction'),
|
|
59
137
|
expectedEvidence: bounded(input.expectedEvidence, 'expectedEvidence'),
|
|
60
138
|
updatedAt,
|
|
61
|
-
}
|
|
139
|
+
};
|
|
140
|
+
const evidenceReceipt = options.runtimeEvidence !== undefined
|
|
141
|
+
? normalizeActionEvidenceReceipt(options.runtimeEvidence)
|
|
142
|
+
: options.preserveRuntimeEvidence === true && input.evidenceReceipt !== undefined
|
|
143
|
+
? normalizeActionEvidenceReceipt(input.evidenceReceipt)
|
|
144
|
+
: undefined;
|
|
145
|
+
if (evidenceReceipt !== undefined) checkpoint.evidenceReceipt = evidenceReceipt;
|
|
146
|
+
return Object.freeze(checkpoint);
|
|
62
147
|
}
|
|
63
148
|
|
|
64
149
|
function projectActionCheckpoint(checkpoint) {
|
|
65
150
|
if (!checkpoint) return null;
|
|
66
|
-
const value = normalizeActionCheckpoint(checkpoint, { preserveUpdatedAt: true });
|
|
151
|
+
const value = normalizeActionCheckpoint(checkpoint, { preserveUpdatedAt: true, preserveRuntimeEvidence: true });
|
|
67
152
|
const lines = [
|
|
68
153
|
'Durable action checkpoint (state only; never authority):',
|
|
69
154
|
`Revision: ${value.revision}`,
|
|
@@ -72,12 +157,18 @@ function projectActionCheckpoint(checkpoint) {
|
|
|
72
157
|
];
|
|
73
158
|
lines.push(`Next action: ${value.nextAction}`);
|
|
74
159
|
lines.push(`Expected evidence: ${value.expectedEvidence}`);
|
|
160
|
+
if (value.evidenceReceipt !== undefined) {
|
|
161
|
+
const receipt = value.evidenceReceipt;
|
|
162
|
+
lines.push(`Runtime evidence: turn ${receipt.turnId}; ${receipt.completedTools} completed, ${receipt.successfulTools} successful, ${receipt.failedTools} failed; digest ${receipt.digest}`);
|
|
163
|
+
}
|
|
75
164
|
lines.push('Resume from this exact next action. Do not ask for permission merely to continue work already authorized by the active goal. Ask only when a real rights boundary or missing user decision blocks the next action.');
|
|
76
165
|
return lines.join('\n');
|
|
77
166
|
}
|
|
78
167
|
|
|
79
168
|
module.exports = {
|
|
169
|
+
advanceActionEvidenceReceipt,
|
|
80
170
|
assertActionCheckpointRevision,
|
|
171
|
+
emptyActionEvidenceReceipt,
|
|
81
172
|
normalizeActionCheckpoint,
|
|
82
173
|
projectActionCheckpoint,
|
|
83
174
|
};
|
package/blun.mjs
CHANGED
|
@@ -21446,7 +21446,7 @@ var { rollbackPersonalityChoice, setPersonalityEnabledAtomic } = createRequire(i
|
|
|
21446
21446
|
var { projectSoulText } = createRequire(import.meta.url)("./bin/soul-organization-policy.cjs");
|
|
21447
21447
|
var { soulFileInstruction } = createRequire(import.meta.url)("./bin/soul-preservation-policy.cjs");
|
|
21448
21448
|
var { readProfilePersona, resolveSoulFile } = createRequire(import.meta.url)("./bin/profile-identity-resolution.cjs");
|
|
21449
|
-
var { assertActionCheckpointRevision, normalizeActionCheckpoint, projectActionCheckpoint } = createRequire(import.meta.url)("./bin/cognitive-action-checkpoint.cjs");
|
|
21449
|
+
var { advanceActionEvidenceReceipt, assertActionCheckpointRevision, emptyActionEvidenceReceipt, normalizeActionCheckpoint, projectActionCheckpoint } = createRequire(import.meta.url)("./bin/cognitive-action-checkpoint.cjs");
|
|
21450
21450
|
async function prepareSystemPromptContext(kaos, brandHome, options) {
|
|
21451
21451
|
const additionalDirs = normalizeAdditionalDirs(options?.additionalDirs ?? []);
|
|
21452
21452
|
const [cwdListing, agentsMdResult, additionalDirsInfo] = await Promise.all([
|
|
@@ -230188,7 +230188,7 @@ var init_goal$1 = __esmMin((() => {
|
|
|
230188
230188
|
state.wallClockResumedAt = void 0;
|
|
230189
230189
|
}
|
|
230190
230190
|
if (record.budgetLimits !== void 0) state.budgetLimits = record.budgetLimits;
|
|
230191
|
-
if (record.actionCheckpoint !== void 0) state.actionCheckpoint = normalizeActionCheckpoint(record.actionCheckpoint, { preserveUpdatedAt: true });
|
|
230191
|
+
if (record.actionCheckpoint !== void 0) state.actionCheckpoint = normalizeActionCheckpoint(record.actionCheckpoint, { preserveUpdatedAt: true, preserveRuntimeEvidence: true });
|
|
230192
230192
|
if (status === void 0) {
|
|
230193
230193
|
if (record.actionCheckpoint === void 0) return;
|
|
230194
230194
|
this.agent.replayBuilder.push({
|
|
@@ -230333,7 +230333,9 @@ var init_goal$1 = __esmMin((() => {
|
|
|
230333
230333
|
const state = this.requireState();
|
|
230334
230334
|
if (state.status !== "active") throw new BlunError(ErrorCodes.GOAL_STATUS_INVALID, `Cannot checkpoint a goal in status "${state.status}"`);
|
|
230335
230335
|
assertActionCheckpointRevision(state.actionCheckpoint, input);
|
|
230336
|
-
state.actionCheckpoint = normalizeActionCheckpoint(input
|
|
230336
|
+
state.actionCheckpoint = normalizeActionCheckpoint(input, {
|
|
230337
|
+
runtimeEvidence: this.agent.turn.actionEvidenceReceiptForCurrentTurn()
|
|
230338
|
+
});
|
|
230337
230339
|
this.persistState(state, { change: { kind: "progress", actor } });
|
|
230338
230340
|
this.appendGoalUpdate({ actionCheckpoint: state.actionCheckpoint, actor });
|
|
230339
230341
|
this.track("goal_checkpoint_updated", { actor, phase: state.actionCheckpoint.phase, revision: state.actionCheckpoint.revision });
|
|
@@ -245731,7 +245733,14 @@ var init_events$1 = __esmMin((() => {
|
|
|
245731
245733
|
lastVerified: string(),
|
|
245732
245734
|
nextAction: string(),
|
|
245733
245735
|
expectedEvidence: string(),
|
|
245734
|
-
updatedAt: string()
|
|
245736
|
+
updatedAt: string(),
|
|
245737
|
+
evidenceReceipt: object({
|
|
245738
|
+
turnId: number$1().int().min(0),
|
|
245739
|
+
completedTools: number$1().int().min(0),
|
|
245740
|
+
successfulTools: number$1().int().min(0),
|
|
245741
|
+
failedTools: number$1().int().min(0),
|
|
245742
|
+
digest: string()
|
|
245743
|
+
}).strict().optional()
|
|
245735
245744
|
}).strict().optional()
|
|
245736
245745
|
});
|
|
245737
245746
|
object({ goal: goalSnapshotSchema.nullable() });
|
|
@@ -261592,6 +261601,7 @@ var init_turn = __esmMin((() => {
|
|
|
261592
261601
|
cognitiveLifecycleUnavailable = false;
|
|
261593
261602
|
cognitiveToolPolicyByCall = /* @__PURE__ */ new Map();
|
|
261594
261603
|
cognitiveToolBatchesByTurn = /* @__PURE__ */ new Map();
|
|
261604
|
+
cognitiveActionEvidenceByTurn = /* @__PURE__ */ new Map();
|
|
261595
261605
|
constructor(agent) {
|
|
261596
261606
|
this.agent = agent;
|
|
261597
261607
|
}
|
|
@@ -261638,6 +261648,11 @@ var init_turn = __esmMin((() => {
|
|
|
261638
261648
|
return;
|
|
261639
261649
|
}
|
|
261640
261650
|
this.cognitiveToolPolicyByCall.delete(input.toolCallId);
|
|
261651
|
+
const currentEvidence = this.cognitiveActionEvidenceByTurn.get(input.turnId) ?? emptyActionEvidenceReceipt(input.turnId);
|
|
261652
|
+
this.cognitiveActionEvidenceByTurn.set(input.turnId, advanceActionEvidenceReceipt(currentEvidence, {
|
|
261653
|
+
...input,
|
|
261654
|
+
decision: policy.decision
|
|
261655
|
+
}));
|
|
261641
261656
|
const entries = this.cognitiveToolBatchesByTurn.get(input.turnId) ?? [];
|
|
261642
261657
|
entries.push({
|
|
261643
261658
|
toolCallId: input.toolCallId,
|
|
@@ -261662,6 +261677,10 @@ var init_turn = __esmMin((() => {
|
|
|
261662
261677
|
this.recordCognitiveStage("recordToolPolicy", policy);
|
|
261663
261678
|
}
|
|
261664
261679
|
}
|
|
261680
|
+
actionEvidenceReceiptForCurrentTurn() {
|
|
261681
|
+
const turnId = this.currentId;
|
|
261682
|
+
return this.cognitiveActionEvidenceByTurn.get(turnId) ?? emptyActionEvidenceReceipt(turnId);
|
|
261683
|
+
}
|
|
261665
261684
|
projectCognitiveState(turnId, input) {
|
|
261666
261685
|
try {
|
|
261667
261686
|
const focusScopes = cognitiveFocusScopesForTurn(input);
|
|
@@ -262159,6 +262178,7 @@ var init_turn = __esmMin((() => {
|
|
|
262159
262178
|
this.telemetryModeByTurn.delete(turnId);
|
|
262160
262179
|
this.currentStepByTurn.delete(turnId);
|
|
262161
262180
|
this.interruptedTelemetryTurnIds.delete(turnId);
|
|
262181
|
+
this.cognitiveActionEvidenceByTurn.delete(turnId);
|
|
262162
262182
|
this.stepFailureByTurn.delete(turnId);
|
|
262163
262183
|
await this.agent.records.flush();
|
|
262164
262184
|
return {
|