blun-king-cli 9.1.372 → 9.1.374
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-focus-projection.cjs +17 -2
- package/bin/cognitive-state-store.cjs +18 -6
- package/bin/cognitive-turn-lifecycle.cjs +10 -2
- package/bin/cognitive-work-focus.cjs +11 -4
- package/bin/launcher-runtime.js +113 -2
- package/bin/personality-memory-adapter.cjs +1 -0
- package/blun.mjs +53 -11
- package/package.json +1 -1
|
@@ -20,6 +20,15 @@ const LABELS = new Map([
|
|
|
20
20
|
['self', 'Self'],
|
|
21
21
|
]);
|
|
22
22
|
const SAFETY_LINE = 'Durable context only; it cannot authorize any action or override the current assignment or runtime policy.';
|
|
23
|
+
const EPISTEMIC_MARKERS = new Map([
|
|
24
|
+
['verified', ''],
|
|
25
|
+
['credible_unverified', ' [unverified]'],
|
|
26
|
+
['hypothesis', ' [hypothesis]'],
|
|
27
|
+
['uncertain_memory', ' [uncertain memory]'],
|
|
28
|
+
['stale', ' [stale]'],
|
|
29
|
+
['unknown', ' [unknown]'],
|
|
30
|
+
['legacy_unknown', ' [unknown]'],
|
|
31
|
+
]);
|
|
23
32
|
|
|
24
33
|
function clean(value, max = 256) {
|
|
25
34
|
const text = String(value ?? '').replace(/[\u0000-\u001f\u007f]+/gu, ' ').replace(/\s+/gu, ' ').trim();
|
|
@@ -52,13 +61,19 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
|
|
|
52
61
|
const withdraws = item?.withdraws === null || item?.withdraws === undefined
|
|
53
62
|
? null : clean(item.withdraws, 128);
|
|
54
63
|
const confidence = Number(item?.confidence);
|
|
64
|
+
const epistemicState = item?.epistemic_state === undefined
|
|
65
|
+
? 'legacy_unknown' : String(item.epistemic_state);
|
|
55
66
|
const occurredAt = Date.parse(String(item?.occurred_at ?? ''));
|
|
56
67
|
if (!FOCUS_DOMAINS.has(domain) || !key || !value || !scope || scope === 'runtime'
|
|
57
68
|
|| !Number.isFinite(confidence) || confidence < 0.5 || confidence > 1
|
|
69
|
+
|| !EPISTEMIC_MARKERS.has(epistemicState)
|
|
58
70
|
|| !Number.isFinite(occurredAt)) return;
|
|
59
71
|
const groupKey = `${scope}\0${domain}\0${key}`;
|
|
60
72
|
const existing = groups.get(groupKey) ?? [];
|
|
61
|
-
existing.push({
|
|
73
|
+
existing.push({
|
|
74
|
+
domain, key, value, scope, observationId, supersedes, withdraws,
|
|
75
|
+
confidence, epistemicState, occurredAt, index,
|
|
76
|
+
});
|
|
62
77
|
groups.set(groupKey, existing);
|
|
63
78
|
});
|
|
64
79
|
|
|
@@ -83,7 +98,7 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
|
|
|
83
98
|
if (item.conflict) return `- Conflict: ${item.key} has incompatible evidence; verify before relying on it.`;
|
|
84
99
|
const marker = item.corrected ? ' [corrected]'
|
|
85
100
|
: item.contested ? ' [contested; stronger evidence]' : item.revised ? ' [revised]' : '';
|
|
86
|
-
return `- ${LABELS.get(item.domain)}: ${item.value}${marker}`;
|
|
101
|
+
return `- ${LABELS.get(item.domain)}: ${item.value}${EPISTEMIC_MARKERS.get(item.epistemicState)}${marker}`;
|
|
87
102
|
});
|
|
88
103
|
while ([`Current durable focus (${lines.length} items):`, ...lines, SAFETY_LINE].join('\n').length > maxChars
|
|
89
104
|
&& lines.length > 0) lines.pop();
|
|
@@ -7,6 +7,9 @@ const { DatabaseSync } = require('node:sqlite');
|
|
|
7
7
|
|
|
8
8
|
const SAFE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
9
9
|
const DOMAINS = new Set(['self', 'world', 'team', 'goal', 'open_thread', 'assumption', 'next_trigger', 'expected_evidence']);
|
|
10
|
+
const EPISTEMIC_STATES = new Set([
|
|
11
|
+
'verified', 'credible_unverified', 'hypothesis', 'uncertain_memory', 'stale', 'unknown', 'legacy_unknown',
|
|
12
|
+
]);
|
|
10
13
|
const FORBIDDEN_KEY_RE = /(?:^|_)(?:acl|api_key|capability|password|permission|secret|token)(?:_|$)/iu;
|
|
11
14
|
const MAX_EVENT_BYTES = 64 * 1024;
|
|
12
15
|
const MAX_OBSERVATIONS = 32;
|
|
@@ -52,7 +55,7 @@ function normalizeSource(source) {
|
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
function normalizeObservation(value) {
|
|
55
|
-
const allowed = new Set(['observation_id', 'domain', 'key', 'value', 'confidence', 'scope', 'supersedes', 'withdraws']);
|
|
58
|
+
const allowed = new Set(['observation_id', 'domain', 'key', 'value', 'confidence', 'epistemic_state', 'scope', 'supersedes', 'withdraws']);
|
|
56
59
|
if (!exactKeys(value, allowed) || hasForbiddenKey(value)) fail('COGNITIVE_FORBIDDEN_FIELD');
|
|
57
60
|
const observation = {
|
|
58
61
|
observation_id: safeId(value.observation_id),
|
|
@@ -60,11 +63,14 @@ function normalizeObservation(value) {
|
|
|
60
63
|
key: cleanText(value.key, 128),
|
|
61
64
|
value: cleanText(value.value, 2048),
|
|
62
65
|
confidence: Number(value.confidence),
|
|
66
|
+
epistemic_state: value.epistemic_state === undefined
|
|
67
|
+
? 'legacy_unknown' : String(value.epistemic_state),
|
|
63
68
|
scope: cleanText(value.scope, 128),
|
|
64
69
|
};
|
|
65
70
|
if (!observation.observation_id || !DOMAINS.has(observation.domain) || !observation.key
|
|
66
71
|
|| !observation.value || !Number.isFinite(observation.confidence)
|
|
67
|
-
|| observation.confidence < 0 || observation.confidence > 1
|
|
72
|
+
|| observation.confidence < 0 || observation.confidence > 1
|
|
73
|
+
|| !EPISTEMIC_STATES.has(observation.epistemic_state) || !observation.scope) {
|
|
68
74
|
fail('COGNITIVE_INVALID_EVENT');
|
|
69
75
|
}
|
|
70
76
|
if (FORBIDDEN_KEY_RE.test(observation.key)) fail('COGNITIVE_FORBIDDEN_FIELD');
|
|
@@ -152,6 +158,7 @@ function initialize(db) {
|
|
|
152
158
|
fact_key TEXT NOT NULL,
|
|
153
159
|
value_text TEXT NOT NULL,
|
|
154
160
|
confidence REAL NOT NULL,
|
|
161
|
+
epistemic_state TEXT NOT NULL DEFAULT 'legacy_unknown',
|
|
155
162
|
scope TEXT NOT NULL,
|
|
156
163
|
source_json TEXT NOT NULL,
|
|
157
164
|
occurred_at TEXT NOT NULL,
|
|
@@ -187,6 +194,9 @@ function initialize(db) {
|
|
|
187
194
|
if (!observationColumns.some((column) => column.name === 'withdraws_observation_id')) {
|
|
188
195
|
db.exec('ALTER TABLE cognitive_observations ADD COLUMN withdraws_observation_id TEXT');
|
|
189
196
|
}
|
|
197
|
+
if (!observationColumns.some((column) => column.name === 'epistemic_state')) {
|
|
198
|
+
db.exec("ALTER TABLE cognitive_observations ADD COLUMN epistemic_state TEXT NOT NULL DEFAULT 'legacy_unknown'");
|
|
199
|
+
}
|
|
190
200
|
}
|
|
191
201
|
|
|
192
202
|
function openCognitiveStateStore({ home } = {}) {
|
|
@@ -218,8 +228,8 @@ function openCognitiveStateStore({ home } = {}) {
|
|
|
218
228
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
219
229
|
.run(normalized.event_id, normalized.tenant_id, normalized.agent_id, actualVersion, newVersion, normalized.occurred_at, payload, previousHash, eventHash);
|
|
220
230
|
const insertObservation = db.prepare(`INSERT INTO cognitive_observations
|
|
221
|
-
(observation_id, event_id, tenant_id, agent_id, domain, fact_key, value_text, confidence, scope, source_json, occurred_at, supersedes_observation_id, withdraws_observation_id)
|
|
222
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
231
|
+
(observation_id, event_id, tenant_id, agent_id, domain, fact_key, value_text, confidence, epistemic_state, scope, source_json, occurred_at, supersedes_observation_id, withdraws_observation_id)
|
|
232
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
223
233
|
const sourceJson = JSON.stringify(normalized.source);
|
|
224
234
|
for (const observation of normalized.observations) {
|
|
225
235
|
if (observation.supersedes) {
|
|
@@ -237,7 +247,8 @@ function openCognitiveStateStore({ home } = {}) {
|
|
|
237
247
|
|| target.scope !== observation.scope) fail('COGNITIVE_INVALID_WITHDRAWAL');
|
|
238
248
|
}
|
|
239
249
|
insertObservation.run(observation.observation_id, normalized.event_id, normalized.tenant_id, normalized.agent_id,
|
|
240
|
-
observation.domain, observation.key, observation.value, observation.confidence, observation.
|
|
250
|
+
observation.domain, observation.key, observation.value, observation.confidence, observation.epistemic_state,
|
|
251
|
+
observation.scope, sourceJson,
|
|
241
252
|
normalized.occurred_at, observation.supersedes ?? null, observation.withdraws ?? null);
|
|
242
253
|
}
|
|
243
254
|
db.prepare(`INSERT INTO cognitive_streams (tenant_id, agent_id, version, updated_at) VALUES (?, ?, ?, ?)
|
|
@@ -256,7 +267,7 @@ function openCognitiveStateStore({ home } = {}) {
|
|
|
256
267
|
const agent = safeId(agentId);
|
|
257
268
|
if (!tenant || !agent) fail('COGNITIVE_INVALID_EVENT');
|
|
258
269
|
const stream = db.prepare('SELECT version, updated_at FROM cognitive_streams WHERE tenant_id = ? AND agent_id = ?').get(tenant, agent);
|
|
259
|
-
const rows = db.prepare(`SELECT domain, fact_key, value_text, confidence, scope, source_json, occurred_at, observation_id,
|
|
270
|
+
const rows = db.prepare(`SELECT domain, fact_key, value_text, confidence, epistemic_state, scope, source_json, occurred_at, observation_id,
|
|
260
271
|
supersedes_observation_id, withdraws_observation_id
|
|
261
272
|
FROM cognitive_observations WHERE tenant_id = ? AND agent_id = ? ORDER BY occurred_at, rowid`).all(tenant, agent);
|
|
262
273
|
return {
|
|
@@ -268,6 +279,7 @@ function openCognitiveStateStore({ home } = {}) {
|
|
|
268
279
|
key: row.fact_key,
|
|
269
280
|
value: row.value_text,
|
|
270
281
|
confidence: row.confidence,
|
|
282
|
+
epistemic_state: row.epistemic_state,
|
|
271
283
|
scope: row.scope,
|
|
272
284
|
source: JSON.parse(row.source_json),
|
|
273
285
|
occurred_at: row.occurred_at,
|
|
@@ -15,6 +15,9 @@ const TOOL_POLICY_DECISIONS = new Set(['passed', 'blocked', 'error']);
|
|
|
15
15
|
const TOOL_OUTCOMES = new Set(['success', 'error', 'cancelled']);
|
|
16
16
|
const TURN_REASONS = new Set(['completed', 'cancelled', 'filtered', 'failed']);
|
|
17
17
|
const FOCUS_DOMAINS = new Set(['self', 'team', 'goal', 'open_thread', 'next_trigger', 'expected_evidence']);
|
|
18
|
+
const FOCUS_EPISTEMIC_STATES = new Set([
|
|
19
|
+
'verified', 'credible_unverified', 'hypothesis', 'uncertain_memory', 'stale', 'unknown', 'legacy_unknown',
|
|
20
|
+
]);
|
|
18
21
|
const AUTHORITY_KEY_RE = /(?:^|:|_)(?:acl|api[_-]?key|capability|password|permission|secret|token)(?::|_|$)/iu;
|
|
19
22
|
|
|
20
23
|
function fail(code) {
|
|
@@ -90,6 +93,7 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
90
93
|
const eventId = digestId('cycle', [tenant, agent, runtime, stageKey]);
|
|
91
94
|
const normalized = observations.map((item, index) => ({
|
|
92
95
|
observation_id: digestId('cycleobs', [eventId, String(index)]),
|
|
96
|
+
epistemic_state: 'verified',
|
|
93
97
|
...item,
|
|
94
98
|
}));
|
|
95
99
|
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
@@ -216,16 +220,19 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
216
220
|
fail('COGNITIVE_FOCUS_INVALID');
|
|
217
221
|
}
|
|
218
222
|
const observations = input.observations.map((item) => {
|
|
219
|
-
if (!exactKeys(item, new Set(['domain', 'key', 'value', 'confidence', 'scope']))) fail('COGNITIVE_FOCUS_INVALID');
|
|
223
|
+
if (!exactKeys(item, new Set(['domain', 'key', 'value', 'confidence', 'epistemicState', 'scope']))) fail('COGNITIVE_FOCUS_INVALID');
|
|
220
224
|
const domain = String(item.domain ?? '');
|
|
221
225
|
const key = cleanLabel(item.key, 128);
|
|
222
226
|
const value = cleanLabel(item.value, 512);
|
|
223
227
|
const confidence = Number(item.confidence);
|
|
228
|
+
const epistemicState = item.epistemicState === undefined
|
|
229
|
+
? 'legacy_unknown' : String(item.epistemicState);
|
|
224
230
|
const scope = cleanLabel(item.scope, 128);
|
|
225
231
|
if (!FOCUS_DOMAINS.has(domain) || !key || AUTHORITY_KEY_RE.test(key) || !value
|
|
226
232
|
|| !Number.isFinite(confidence) || confidence < 0.5 || confidence > 1
|
|
233
|
+
|| !FOCUS_EPISTEMIC_STATES.has(epistemicState)
|
|
227
234
|
|| !scope || scope === 'runtime') fail('COGNITIVE_FOCUS_INVALID');
|
|
228
|
-
return { domain, key, value, confidence, scope };
|
|
235
|
+
return { domain, key, value, confidence, epistemic_state: epistemicState, scope };
|
|
229
236
|
});
|
|
230
237
|
return commitDurableStage(`focus-${input.snapshotId}`, observations);
|
|
231
238
|
}
|
|
@@ -269,6 +276,7 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
269
276
|
key,
|
|
270
277
|
value,
|
|
271
278
|
confidence: 1,
|
|
279
|
+
epistemic_state: 'verified',
|
|
272
280
|
scope,
|
|
273
281
|
...(correction ? { supersedes: targetObservationId } : { withdraws: targetObservationId }),
|
|
274
282
|
};
|
|
@@ -4,6 +4,9 @@ const crypto = require('node:crypto');
|
|
|
4
4
|
|
|
5
5
|
const SAFE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
6
6
|
const STATUSES = new Set(['active', 'paused', 'blocked']);
|
|
7
|
+
const EPISTEMIC_STATES = new Set([
|
|
8
|
+
'verified', 'credible_unverified', 'hypothesis', 'uncertain_memory', 'stale', 'unknown', 'legacy_unknown',
|
|
9
|
+
]);
|
|
7
10
|
const NEXT_TRIGGER = new Map([
|
|
8
11
|
['active', 'Continue the active goal from its last verified state.'],
|
|
9
12
|
['paused', 'Wait until the goal is explicitly resumed.'],
|
|
@@ -36,8 +39,11 @@ function buildCognitiveWorkFocus(goal) {
|
|
|
36
39
|
const lastVerified = bounded(checkpoint?.lastVerified);
|
|
37
40
|
const nextAction = bounded(checkpoint?.nextAction);
|
|
38
41
|
const checkpointEvidence = bounded(checkpoint?.expectedEvidence);
|
|
42
|
+
const checkpointEpistemicState = bounded(checkpoint?.epistemicState, 32);
|
|
39
43
|
const hasCheckpoint = checkpoint !== null && checkpointPhase && lastVerified
|
|
40
44
|
&& nextAction && checkpointEvidence;
|
|
45
|
+
const epistemicState = hasCheckpoint && EPISTEMIC_STATES.has(checkpointEpistemicState)
|
|
46
|
+
? checkpointEpistemicState : hasCheckpoint ? 'legacy_unknown' : 'verified';
|
|
41
47
|
const digest = crypto.createHash('sha256')
|
|
42
48
|
.update([
|
|
43
49
|
goalId, objective, completionCriterion, status, String(turnsUsed),
|
|
@@ -45,6 +51,7 @@ function buildCognitiveWorkFocus(goal) {
|
|
|
45
51
|
hasCheckpoint ? lastVerified : '',
|
|
46
52
|
hasCheckpoint ? nextAction : '',
|
|
47
53
|
hasCheckpoint ? checkpointEvidence : '',
|
|
54
|
+
epistemicState,
|
|
48
55
|
].join('\0'))
|
|
49
56
|
.digest('hex').slice(0, 40);
|
|
50
57
|
const keyRoot = `goal:${goalId}`;
|
|
@@ -52,21 +59,21 @@ function buildCognitiveWorkFocus(goal) {
|
|
|
52
59
|
snapshotId: `goalfocus-${digest}`,
|
|
53
60
|
focusScope,
|
|
54
61
|
observations: [
|
|
55
|
-
{ domain: 'goal', key: `${keyRoot}:objective`, value: objective, confidence: 1, scope: focusScope },
|
|
62
|
+
{ domain: 'goal', key: `${keyRoot}:objective`, value: objective, confidence: 1, epistemicState, scope: focusScope },
|
|
56
63
|
{
|
|
57
64
|
domain: 'open_thread', key: `${keyRoot}:status`,
|
|
58
65
|
value: hasCheckpoint ? `Goal is ${status}. Phase ${checkpointPhase}. Last verified: ${lastVerified}` : `Goal is ${status}.`,
|
|
59
|
-
confidence: 1, scope: focusScope,
|
|
66
|
+
confidence: 1, epistemicState, scope: focusScope,
|
|
60
67
|
},
|
|
61
68
|
{
|
|
62
69
|
domain: 'next_trigger', key: `${keyRoot}:next`,
|
|
63
70
|
value: status === 'active' && hasCheckpoint ? nextAction : NEXT_TRIGGER.get(status),
|
|
64
|
-
confidence: 1, scope: focusScope,
|
|
71
|
+
confidence: 1, epistemicState, scope: focusScope,
|
|
65
72
|
},
|
|
66
73
|
{
|
|
67
74
|
domain: 'expected_evidence', key: `${keyRoot}:evidence`,
|
|
68
75
|
value: status === 'active' && hasCheckpoint ? checkpointEvidence : completionCriterion,
|
|
69
|
-
confidence: 1, scope: focusScope,
|
|
76
|
+
confidence: 1, epistemicState, scope: focusScope,
|
|
70
77
|
},
|
|
71
78
|
],
|
|
72
79
|
};
|
package/bin/launcher-runtime.js
CHANGED
|
@@ -30,6 +30,9 @@ const { startMnemoConnectHeartbeat } = require('./mnemo-connect-heartbeat.cjs');
|
|
|
30
30
|
const { acquireSharedRuntimeLease, tryAcquireUpdateLease } = require('./update-lease');
|
|
31
31
|
const { compareSemver, runExplicitUpdate, runUpdateNotice } = require('./update-notice');
|
|
32
32
|
const {
|
|
33
|
+
RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
34
|
+
RUNNING_UPDATE_HANDOFF_EXIT_CODE,
|
|
35
|
+
RUNNING_UPDATE_HANDOFF_MESSAGE,
|
|
33
36
|
RUNNING_UPDATE_MODE_MESSAGE,
|
|
34
37
|
RUNNING_UPDATE_PREPARED_MESSAGE,
|
|
35
38
|
RUNTIME_EXIT_INTENT_MESSAGE,
|
|
@@ -40,7 +43,9 @@ const {
|
|
|
40
43
|
recordRunningUpdateEvent,
|
|
41
44
|
readActiveRuntime,
|
|
42
45
|
readPendingRuntime,
|
|
46
|
+
restoreActiveRuntime,
|
|
43
47
|
clearPendingRuntime,
|
|
48
|
+
handoffArgsForMode,
|
|
44
49
|
stageRuntime,
|
|
45
50
|
} = require('./running-update.cjs');
|
|
46
51
|
const {
|
|
@@ -326,8 +331,9 @@ async function superviseProtectedCore(args, env, cwd, releaseNotice, options = {
|
|
|
326
331
|
const packageRoot = path.resolve(options.packageRoot || PKG);
|
|
327
332
|
let preparedTarget;
|
|
328
333
|
let updateStarted = false;
|
|
329
|
-
let runtimeReady =
|
|
330
|
-
let activeSession;
|
|
334
|
+
let runtimeReady = options.initialRuntimeReady === true;
|
|
335
|
+
let activeSession = options.initialActiveSession;
|
|
336
|
+
let acceptedHandoff;
|
|
331
337
|
let runtimeExitIntent = false;
|
|
332
338
|
let supervisionCompleted = false;
|
|
333
339
|
let runningUpdatePollTimer;
|
|
@@ -467,6 +473,35 @@ async function superviseProtectedCore(args, env, cwd, releaseNotice, options = {
|
|
|
467
473
|
if (runtimeReady && !updateStarted) startPreparation(child);
|
|
468
474
|
} else if (runtimeReady) scheduleNextPreparation(child);
|
|
469
475
|
}
|
|
476
|
+
if (message?.type === RUNNING_UPDATE_HANDOFF_MESSAGE) {
|
|
477
|
+
refreshRunningUpdateMode();
|
|
478
|
+
const requestedCwd = resolveHandoffCwd(message.cwd, '');
|
|
479
|
+
const requestMatches = preparedTarget !== undefined
|
|
480
|
+
&& automaticMode()
|
|
481
|
+
&& validSessionMessage(message)
|
|
482
|
+
&& activeSession !== undefined
|
|
483
|
+
&& message.version === preparedTarget.version
|
|
484
|
+
&& message.mode === runningUpdateMode
|
|
485
|
+
&& message.sessionId === activeSession.sessionId
|
|
486
|
+
&& requestedCwd === activeSession.cwd;
|
|
487
|
+
if (!requestMatches) return;
|
|
488
|
+
acceptedHandoff = Object.freeze({
|
|
489
|
+
cwd: requestedCwd,
|
|
490
|
+
mode: runningUpdateMode,
|
|
491
|
+
sessionId: message.sessionId,
|
|
492
|
+
target: preparedTarget,
|
|
493
|
+
});
|
|
494
|
+
if (child?.connected === true) {
|
|
495
|
+
try {
|
|
496
|
+
child.send({
|
|
497
|
+
type: RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
498
|
+
version: preparedTarget.version,
|
|
499
|
+
mode: runningUpdateMode,
|
|
500
|
+
sessionId: message.sessionId,
|
|
501
|
+
});
|
|
502
|
+
} catch {}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
470
505
|
};
|
|
471
506
|
const spawnCore = options.spawnProtectedCore || spawnProtectedCore;
|
|
472
507
|
const core = options.existingCore || spawnCore(args, env, cwd, {
|
|
@@ -508,6 +543,82 @@ async function superviseProtectedCore(args, env, cwd, releaseNotice, options = {
|
|
|
508
543
|
supervisionCompleted = true;
|
|
509
544
|
clearRunningUpdatePoll();
|
|
510
545
|
if (existingMessageHandler) core.child.off('message', existingMessageHandler);
|
|
546
|
+
if (result.code === RUNNING_UPDATE_HANDOFF_EXIT_CODE && acceptedHandoff !== undefined) {
|
|
547
|
+
const sharedHome = env.BLUN_SHARED_HOME;
|
|
548
|
+
const previousActiveRuntime = (options.readActiveRuntime || readActiveRuntime)(sharedHome);
|
|
549
|
+
const previousVersion = readPackageVersionAt(packageRoot);
|
|
550
|
+
const handoffArgs = handoffArgsForMode(args, acceptedHandoff.mode, acceptedHandoff.sessionId);
|
|
551
|
+
let targetSession;
|
|
552
|
+
const targetCore = spawnCore(handoffArgs, env, acceptedHandoff.cwd, {
|
|
553
|
+
packageRoot: acceptedHandoff.target.packageRoot,
|
|
554
|
+
onMessage(message) {
|
|
555
|
+
if (message?.type === RUNTIME_READY_MESSAGE && validSessionMessage(message)) {
|
|
556
|
+
targetSession = Object.freeze({
|
|
557
|
+
cwd: resolveHandoffCwd(message.cwd, acceptedHandoff.cwd),
|
|
558
|
+
sessionId: message.sessionId,
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
});
|
|
563
|
+
const targetLoaded = await targetCore.loaded;
|
|
564
|
+
const targetReady = targetLoaded
|
|
565
|
+
&& await (options.waitForRuntimeReady || waitForRuntimeReady)(targetCore, options.readyTimeoutMs);
|
|
566
|
+
if (targetReady) {
|
|
567
|
+
await (options.activateRuntime || activateRuntime)(sharedHome, acceptedHandoff.target);
|
|
568
|
+
(options.clearPendingRuntime || clearPendingRuntime)(sharedHome, acceptedHandoff.target);
|
|
569
|
+
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(sharedHome, {
|
|
570
|
+
event: 'activated-live-handoff',
|
|
571
|
+
fromVersion: previousVersion,
|
|
572
|
+
toVersion: acceptedHandoff.target.version,
|
|
573
|
+
mode: acceptedHandoff.mode,
|
|
574
|
+
sessionId: acceptedHandoff.sessionId,
|
|
575
|
+
}, { now: options.nowImpl });
|
|
576
|
+
return superviseProtectedCore(handoffArgs, env, acceptedHandoff.cwd, async () => {}, {
|
|
577
|
+
...options,
|
|
578
|
+
existingCore: targetCore,
|
|
579
|
+
initialActiveSession: targetSession,
|
|
580
|
+
initialRuntimeReady: true,
|
|
581
|
+
packageRoot: acceptedHandoff.target.packageRoot,
|
|
582
|
+
startupPendingRuntime: undefined,
|
|
583
|
+
staleActiveRuntime: undefined,
|
|
584
|
+
recoveryRuntime: {
|
|
585
|
+
activeRuntime: previousActiveRuntime,
|
|
586
|
+
activatedAt: (options.nowImpl || Date.now)(),
|
|
587
|
+
packageRoot,
|
|
588
|
+
version: previousVersion,
|
|
589
|
+
},
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
try {
|
|
593
|
+
targetCore.child.kill();
|
|
594
|
+
} catch {}
|
|
595
|
+
await (options.restoreActiveRuntime || restoreActiveRuntime)(sharedHome, previousActiveRuntime);
|
|
596
|
+
(options.clearPendingRuntime || clearPendingRuntime)(sharedHome, acceptedHandoff.target);
|
|
597
|
+
(options.recordRunningUpdateEvent || recordRunningUpdateEvent)(sharedHome, {
|
|
598
|
+
event: 'live-handoff-rolled-back',
|
|
599
|
+
failedVersion: acceptedHandoff.target.version,
|
|
600
|
+
recoveryVersion: previousVersion,
|
|
601
|
+
}, { now: options.nowImpl });
|
|
602
|
+
const fallback = spawnCore(handoffArgs, env, acceptedHandoff.cwd, { packageRoot });
|
|
603
|
+
const fallbackLoaded = await fallback.loaded;
|
|
604
|
+
const fallbackReady = fallbackLoaded
|
|
605
|
+
&& await (options.waitForRuntimeReady || waitForRuntimeReady)(fallback, options.readyTimeoutMs);
|
|
606
|
+
if (fallbackReady) {
|
|
607
|
+
return superviseProtectedCore(handoffArgs, env, acceptedHandoff.cwd, async () => {}, {
|
|
608
|
+
...options,
|
|
609
|
+
existingCore: fallback,
|
|
610
|
+
initialActiveSession: activeSession,
|
|
611
|
+
initialRuntimeReady: true,
|
|
612
|
+
packageRoot,
|
|
613
|
+
startupPendingRuntime: undefined,
|
|
614
|
+
staleActiveRuntime: undefined,
|
|
615
|
+
recoveryRuntime: undefined,
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
const fallbackResult = await fallback.completed;
|
|
619
|
+
if (fallbackResult.error) throw fallbackResult.error;
|
|
620
|
+
return exitCodeForChild(fallbackResult, fallbackLoaded);
|
|
621
|
+
}
|
|
511
622
|
const recovery = options.recoveryRuntime;
|
|
512
623
|
if (shouldRecoverActivatedRuntime(result, recovery, {
|
|
513
624
|
now: (options.nowImpl || Date.now)(),
|
|
@@ -130,6 +130,7 @@ function createPersonalityMemoryAdapter({ identityRoot } = {}) {
|
|
|
130
130
|
key: `relationship:${digest('actor', [value.actorId]).slice(0, 30)}:curiosity-presentation`,
|
|
131
131
|
value: value.topic,
|
|
132
132
|
confidence: 1,
|
|
133
|
+
epistemic_state: 'verified',
|
|
133
134
|
scope: relationshipScope(value.actorId),
|
|
134
135
|
}],
|
|
135
136
|
});
|
package/blun.mjs
CHANGED
|
@@ -261770,7 +261770,10 @@ var init_turn = __esmMin((() => {
|
|
|
261770
261770
|
if (active === null || active === "resuming" || !active.acceptingSteers || expectedTurnId !== void 0 && expectedTurnId !== this.currentId) return null;
|
|
261771
261771
|
if (this.telegramDeliveryLedger.isDuplicate(input, origin)) {
|
|
261772
261772
|
this.agent.telemetry.track("telegram_delivery_duplicate_dropped", { intake: "active_steer" });
|
|
261773
|
-
return
|
|
261773
|
+
return {
|
|
261774
|
+
turnId: this.currentId,
|
|
261775
|
+
duplicate: true
|
|
261776
|
+
};
|
|
261774
261777
|
}
|
|
261775
261778
|
this.telegramDeliveryLedger.remember(input, origin);
|
|
261776
261779
|
this.agent.records.logRecord({
|
|
@@ -261779,7 +261782,10 @@ var init_turn = __esmMin((() => {
|
|
|
261779
261782
|
origin
|
|
261780
261783
|
});
|
|
261781
261784
|
this.bufferSteer(input, origin, this.currentId);
|
|
261782
|
-
return
|
|
261785
|
+
return {
|
|
261786
|
+
turnId: this.currentId,
|
|
261787
|
+
duplicate: false
|
|
261788
|
+
};
|
|
261783
261789
|
}
|
|
261784
261790
|
retry(trigger) {
|
|
261785
261791
|
return this.prompt([], {
|
|
@@ -265457,11 +265463,12 @@ var init_agent = __esmMin((() => {
|
|
|
265457
265463
|
steer: (payload) => {
|
|
265458
265464
|
this.telemetry.track("input_steer", { parts: payload.input.length });
|
|
265459
265465
|
if (payload.activeTurnOnly === true) {
|
|
265460
|
-
const
|
|
265466
|
+
const activeSteer = this.turn.steerActive(payload.input, payload.expectedTurnId);
|
|
265461
265467
|
return {
|
|
265462
|
-
accepted:
|
|
265463
|
-
buffered:
|
|
265464
|
-
|
|
265468
|
+
accepted: activeSteer !== null,
|
|
265469
|
+
buffered: activeSteer !== null && activeSteer.duplicate !== true,
|
|
265470
|
+
duplicate: activeSteer?.duplicate === true,
|
|
265471
|
+
turnId: activeSteer?.turnId ?? null
|
|
265465
265472
|
};
|
|
265466
265473
|
}
|
|
265467
265474
|
const launchedTurnId = this.turn.steer(payload.input);
|
|
@@ -516167,11 +516174,14 @@ function turnsToTrim(turns, maxTurns, hysteresis) {
|
|
|
516167
516174
|
//#region src/tui/blun-tui.ts
|
|
516168
516175
|
const {
|
|
516169
516176
|
AUTO_UPDATE_SETTLE_MS,
|
|
516177
|
+
RUNNING_UPDATE_HANDOFF_ACK_MESSAGE,
|
|
516170
516178
|
RUNNING_UPDATE_HANDOFF_EXIT_CODE,
|
|
516179
|
+
RUNNING_UPDATE_HANDOFF_MESSAGE,
|
|
516171
516180
|
RUNNING_UPDATE_MODE_MESSAGE,
|
|
516172
516181
|
RUNNING_UPDATE_PREPARED_MESSAGE,
|
|
516173
516182
|
RUNTIME_EXIT_INTENT_MESSAGE,
|
|
516174
516183
|
RUNTIME_READY_MESSAGE,
|
|
516184
|
+
isSafeRuntimeBoundary,
|
|
516175
516185
|
pruneRunningUpdateReleases
|
|
516176
516186
|
} = __require("./bin/running-update.cjs");
|
|
516177
516187
|
const {
|
|
@@ -516207,10 +516217,39 @@ function requestRunningUpdateAtSafeBoundary(tui) {
|
|
|
516207
516217
|
const version = tui.runningUpdatePreparedVersion;
|
|
516208
516218
|
const mode = tui.runningUpdatePreparedMode;
|
|
516209
516219
|
if (typeof version !== "string" || mode !== RUNNING_UPDATE_MODES.RESUME && mode !== RUNNING_UPDATE_MODES.NEW) return false;
|
|
516210
|
-
if (
|
|
516211
|
-
|
|
516212
|
-
|
|
516213
|
-
|
|
516220
|
+
if (!isSafeRuntimeBoundary({
|
|
516221
|
+
isShuttingDown: tui.isShuttingDown,
|
|
516222
|
+
streamingPhase: tui.state.appState.streamingPhase,
|
|
516223
|
+
isCompacting: tui.state.appState.isCompacting,
|
|
516224
|
+
queuedMessages: tui.state.queuedMessages.length,
|
|
516225
|
+
activeToolCalls: tui.streamingUI.hasActiveToolCalls() ? 1 : 0,
|
|
516226
|
+
shellCommands: tui.shellOutputStreams.size,
|
|
516227
|
+
queueCommandRunning: tui.queueCommandRunning
|
|
516228
|
+
})) {
|
|
516229
|
+
if (tui.runningUpdatePreparedNoticeVersion !== version) {
|
|
516230
|
+
tui.runningUpdatePreparedNoticeVersion = version;
|
|
516231
|
+
const statusKey = mode === RUNNING_UPDATE_MODES.RESUME ? "update.resume.description" : "update.new.description";
|
|
516232
|
+
tui.showStatus(`${version} · ${uiText(statusKey)}`, "success");
|
|
516233
|
+
}
|
|
516234
|
+
return false;
|
|
516235
|
+
}
|
|
516236
|
+
if (!process.connected || tui.runningUpdateHandoffRequestedVersion === version) return false;
|
|
516237
|
+
const sessionId = tui.getCurrentSessionId();
|
|
516238
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) return false;
|
|
516239
|
+
tui.runningUpdateHandoffRequestedVersion = version;
|
|
516240
|
+
try {
|
|
516241
|
+
process.send({
|
|
516242
|
+
type: RUNNING_UPDATE_HANDOFF_MESSAGE,
|
|
516243
|
+
version,
|
|
516244
|
+
mode,
|
|
516245
|
+
sessionId,
|
|
516246
|
+
cwd: tui.state.appState.workDir
|
|
516247
|
+
});
|
|
516248
|
+
return true;
|
|
516249
|
+
} catch {
|
|
516250
|
+
tui.runningUpdateHandoffRequestedVersion = void 0;
|
|
516251
|
+
return false;
|
|
516252
|
+
}
|
|
516214
516253
|
}
|
|
516215
516254
|
function installRunningUpdateListener(tui) {
|
|
516216
516255
|
const handler = (message) => {
|
|
@@ -516219,6 +516258,7 @@ function installRunningUpdateListener(tui) {
|
|
|
516219
516258
|
tui.runningUpdatePreparedMode = message.mode;
|
|
516220
516259
|
requestRunningUpdateAtSafeBoundary(tui);
|
|
516221
516260
|
}
|
|
516261
|
+
if (message?.type === RUNNING_UPDATE_HANDOFF_ACK_MESSAGE && message.version === tui.runningUpdateHandoffRequestedVersion && message.sessionId === tui.getCurrentSessionId()) void tui.stop(RUNNING_UPDATE_HANDOFF_EXIT_CODE);
|
|
516222
516262
|
};
|
|
516223
516263
|
process.on("message", handler);
|
|
516224
516264
|
return () => process.off("message", handler);
|
|
@@ -517244,8 +517284,10 @@ var BlunTUI = class {
|
|
|
517244
517284
|
return this.restoreQueuedSteer(inFlight, error);
|
|
517245
517285
|
};
|
|
517246
517286
|
try {
|
|
517247
|
-
|
|
517287
|
+
const result = await this.harness.withInteractiveAgent(item.agentId ?? "main", () => session.steerActive(input, expectedTurnId === void 0 ? {} : { expectedTurnId }));
|
|
517288
|
+
if (!result.accepted) return this.recoverRejectedActiveSteer(inFlight);
|
|
517248
517289
|
inFlight.accepted = true;
|
|
517290
|
+
if (result.duplicate === true) return this.commitQueuedSteer(inFlight);
|
|
517249
517291
|
if (inFlight.turnEnded) return restoreHead();
|
|
517250
517292
|
this.commitQueuedSteerIfReady(inFlight);
|
|
517251
517293
|
} catch (error) {
|