blun-king-cli 9.1.358 → 9.1.360
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.
|
@@ -36,6 +36,7 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
|
|
|
36
36
|
if (scopes === null || !Number.isSafeInteger(maxItems) || maxItems < 1 || maxItems > 8
|
|
37
37
|
|| !Number.isSafeInteger(maxChars) || maxChars < 320 || maxChars > 1600
|
|
38
38
|
|| !Array.isArray(state?.observations)) return null;
|
|
39
|
+
if (scopes.length === 0) return null;
|
|
39
40
|
|
|
40
41
|
const groups = new Map();
|
|
41
42
|
state.observations.forEach((item, index) => {
|
|
@@ -48,7 +49,7 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
|
|
|
48
49
|
if (!FOCUS_DOMAINS.has(domain) || !key || !value || !scope || scope === 'runtime'
|
|
49
50
|
|| !Number.isFinite(confidence) || confidence < 0.5 || confidence > 1
|
|
50
51
|
|| !Number.isFinite(occurredAt)) return;
|
|
51
|
-
const groupKey = `${domain}\0${key}`;
|
|
52
|
+
const groupKey = `${scope}\0${domain}\0${key}`;
|
|
52
53
|
const existing = groups.get(groupKey) ?? [];
|
|
53
54
|
existing.push({ domain, key, value, scope, confidence, occurredAt, index });
|
|
54
55
|
groups.set(groupKey, existing);
|
|
@@ -58,12 +59,12 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
|
|
|
58
59
|
for (const entries of groups.values()) {
|
|
59
60
|
entries.sort((left, right) => left.occurredAt - right.occurredAt || left.index - right.index);
|
|
60
61
|
const latest = entries.at(-1);
|
|
62
|
+
if (!scopes.includes(latest.scope)) continue;
|
|
61
63
|
const revised = entries.some((item) => item.value !== latest.value);
|
|
62
|
-
const scopeScore = scopes.includes(latest.scope) ? 100 : 0;
|
|
63
64
|
ranked.push({
|
|
64
65
|
...latest,
|
|
65
66
|
revised,
|
|
66
|
-
score:
|
|
67
|
+
score: DOMAIN_WEIGHTS.get(latest.domain) + latest.confidence * 10,
|
|
67
68
|
});
|
|
68
69
|
}
|
|
69
70
|
ranked.sort((left, right) => right.score - left.score
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const CHANNEL_RE = /<channel\b([^>]*)>[\s\S]*?<\/channel>/giu;
|
|
4
|
+
const TELEGRAM_SOURCE_RE = /\bsource\s*=\s*["']telegram["']/iu;
|
|
5
|
+
const CHAT_ID_RE = /\bchat_id\s*=\s*["'](-?\d+)["']/iu;
|
|
6
|
+
const USER_ID_RE = /\buser_id\s*=\s*["'](\d+)["']/iu;
|
|
7
|
+
const DM_MARKER_RE = /^#?\s*\[tg\s+dm\b[^\]]*\bchat_id\s*=\s*(\d+)[^\]]*\]/gimu;
|
|
8
|
+
|
|
9
|
+
function inputText(input) {
|
|
10
|
+
if (!Array.isArray(input)) return '';
|
|
11
|
+
return input
|
|
12
|
+
.filter((part) => part?.type === 'text' && typeof part.text === 'string')
|
|
13
|
+
.map((part) => part.text)
|
|
14
|
+
.join('\n');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function relationshipScope(subjectId) {
|
|
18
|
+
return `relationship:telegram-${subjectId}:private`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function cognitiveFocusScopesForTurn(input) {
|
|
22
|
+
const text = inputText(input);
|
|
23
|
+
if (!text) return [];
|
|
24
|
+
const scopes = [];
|
|
25
|
+
for (const match of text.matchAll(CHANNEL_RE)) {
|
|
26
|
+
const attributes = match[1] ?? '';
|
|
27
|
+
if (!TELEGRAM_SOURCE_RE.test(attributes)) continue;
|
|
28
|
+
const chatId = CHAT_ID_RE.exec(attributes)?.[1];
|
|
29
|
+
if (!chatId || chatId.startsWith('-')) continue;
|
|
30
|
+
const subjectId = USER_ID_RE.exec(attributes)?.[1] ?? chatId;
|
|
31
|
+
scopes.push(relationshipScope(subjectId));
|
|
32
|
+
}
|
|
33
|
+
for (const match of text.matchAll(DM_MARKER_RE)) scopes.push(relationshipScope(match[1]));
|
|
34
|
+
return [...new Set(scopes)].slice(0, 8);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = { cognitiveFocusScopesForTurn };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const crypto = require('node:crypto');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const path = require('node:path');
|
|
4
6
|
const { openCognitiveStateStore } = require('./cognitive-state-store.cjs');
|
|
5
7
|
const { buildCognitiveContextProjection } = require('./cognitive-context-projection.cjs');
|
|
6
8
|
const { buildCognitiveFocusProjection } = require('./cognitive-focus-projection.cjs');
|
|
@@ -45,6 +47,25 @@ function digestId(prefix, values) {
|
|
|
45
47
|
return `${prefix}-${digest}`;
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
function identityFromManifest(home) {
|
|
51
|
+
const root = fs.realpathSync(path.resolve(String(home ?? '')));
|
|
52
|
+
const identityRoot = path.join(root, 'identity');
|
|
53
|
+
const manifestPath = path.join(identityRoot, 'manifest.json');
|
|
54
|
+
try {
|
|
55
|
+
const identityStat = fs.lstatSync(identityRoot);
|
|
56
|
+
const manifestStat = fs.lstatSync(manifestPath);
|
|
57
|
+
if (!identityStat.isDirectory() || identityStat.isSymbolicLink()
|
|
58
|
+
|| !manifestStat.isFile() || manifestStat.isSymbolicLink() || manifestStat.size > 64 * 1024) return null;
|
|
59
|
+
if (fs.realpathSync(identityRoot) !== identityRoot || fs.realpathSync(manifestPath) !== manifestPath) return null;
|
|
60
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
61
|
+
const tenantId = safeId(manifest?.tenant_id);
|
|
62
|
+
const agentId = safeId(manifest?.active_agent_id);
|
|
63
|
+
return manifest?.version === 1 && tenantId && agentId ? { tenantId, agentId } : null;
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
48
69
|
function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now = () => new Date().toISOString() } = {}) {
|
|
49
70
|
const tenant = safeId(tenantId);
|
|
50
71
|
const agent = safeId(agentId);
|
|
@@ -97,6 +118,50 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
97
118
|
fail('COGNITIVE_VERSION_CONFLICT');
|
|
98
119
|
}
|
|
99
120
|
|
|
121
|
+
function commitDurableStage(stageKey, observations) {
|
|
122
|
+
if (stageResults.has(stageKey)) return { ...stageResults.get(stageKey), idempotent: true };
|
|
123
|
+
const eventId = digestId('durable', [tenant, agent, stageKey]);
|
|
124
|
+
if (store.hasEvent(eventId)) {
|
|
125
|
+
const result = { idempotent: true };
|
|
126
|
+
stageResults.set(stageKey, result);
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
const occurredAt = stageTime(`durable:${stageKey}`);
|
|
130
|
+
const normalized = observations.map((item, index) => ({
|
|
131
|
+
observation_id: digestId('durableobs', [eventId, String(index)]),
|
|
132
|
+
...item,
|
|
133
|
+
}));
|
|
134
|
+
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
135
|
+
if (store.hasEvent(eventId)) {
|
|
136
|
+
const result = { idempotent: true };
|
|
137
|
+
stageResults.set(stageKey, result);
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
const expectedVersion = store.read({ tenantId: tenant, agentId: agent }).version;
|
|
141
|
+
try {
|
|
142
|
+
const result = store.commit({
|
|
143
|
+
tenantId: tenant,
|
|
144
|
+
agentId: agent,
|
|
145
|
+
eventId,
|
|
146
|
+
expectedVersion,
|
|
147
|
+
occurredAt,
|
|
148
|
+
source: {
|
|
149
|
+
provider: 'runtime',
|
|
150
|
+
actor_id: agent,
|
|
151
|
+
context_id: 'durable-focus',
|
|
152
|
+
message_id: stageKey,
|
|
153
|
+
},
|
|
154
|
+
observations: normalized,
|
|
155
|
+
});
|
|
156
|
+
stageResults.set(stageKey, result);
|
|
157
|
+
return result;
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (error?.code !== 'COGNITIVE_VERSION_CONFLICT' || attempt === 3) throw error;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
fail('COGNITIVE_VERSION_CONFLICT');
|
|
163
|
+
}
|
|
164
|
+
|
|
100
165
|
function startTurn(input) {
|
|
101
166
|
if (!exactKeys(input, new Set(['turnId', 'originKind']))) fail('COGNITIVE_LIFECYCLE_INVALID');
|
|
102
167
|
const turnId = safeTurnId(input.turnId);
|
|
@@ -162,7 +227,7 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
162
227
|
|| !scope || scope === 'runtime') fail('COGNITIVE_FOCUS_INVALID');
|
|
163
228
|
return { domain, key, value, confidence, scope };
|
|
164
229
|
});
|
|
165
|
-
return
|
|
230
|
+
return commitDurableStage(`focus-${input.snapshotId}`, observations);
|
|
166
231
|
}
|
|
167
232
|
|
|
168
233
|
function toolFields(input, allowedKeys) {
|
|
@@ -281,14 +346,25 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
281
346
|
};
|
|
282
347
|
}
|
|
283
348
|
|
|
284
|
-
function createRuntimeCognitiveTurnLifecycle({ home, agentName, runtimeId, now } = {}) {
|
|
349
|
+
function createRuntimeCognitiveTurnLifecycle({ home, agentName, tenantId, agentId, runtimeId, now } = {}) {
|
|
285
350
|
const resolvedHome = String(home ?? '').trim();
|
|
286
351
|
const resolvedAgent = String(agentName ?? '').trim();
|
|
287
352
|
if (!resolvedHome || !resolvedAgent) fail('COGNITIVE_LIFECYCLE_INVALID');
|
|
353
|
+
const explicitTenant = tenantId === undefined ? '' : safeId(tenantId);
|
|
354
|
+
const explicitAgent = agentId === undefined ? '' : safeId(agentId);
|
|
355
|
+
if ((tenantId !== undefined && !explicitTenant) || (agentId !== undefined && !explicitAgent)) {
|
|
356
|
+
fail('COGNITIVE_LIFECYCLE_INVALID');
|
|
357
|
+
}
|
|
358
|
+
const manifestIdentity = identityFromManifest(resolvedHome);
|
|
359
|
+
const identity = {
|
|
360
|
+
tenantId: explicitTenant || manifestIdentity?.tenantId || '',
|
|
361
|
+
agentId: explicitAgent || manifestIdentity?.agentId || '',
|
|
362
|
+
};
|
|
363
|
+
const hasSharedIdentity = Boolean(identity.tenantId && identity.agentId);
|
|
288
364
|
return createCognitiveTurnLifecycle({
|
|
289
365
|
home: resolvedHome,
|
|
290
|
-
tenantId: digestId('home', [resolvedHome.toLowerCase()]),
|
|
291
|
-
agentId: digestId('agent', [resolvedAgent.toLowerCase()]),
|
|
366
|
+
tenantId: hasSharedIdentity ? identity.tenantId : digestId('home', [resolvedHome.toLowerCase()]),
|
|
367
|
+
agentId: hasSharedIdentity ? identity.agentId : digestId('agent', [resolvedAgent.toLowerCase()]),
|
|
292
368
|
runtimeId,
|
|
293
369
|
now,
|
|
294
370
|
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('node:crypto');
|
|
4
|
+
|
|
5
|
+
const SAFE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
6
|
+
const STATUSES = new Set(['active', 'paused', 'blocked']);
|
|
7
|
+
const NEXT_TRIGGER = new Map([
|
|
8
|
+
['active', 'Continue the active goal from its last verified state.'],
|
|
9
|
+
['paused', 'Wait until the goal is explicitly resumed.'],
|
|
10
|
+
['blocked', 'Resolve the current blocker before continuing.'],
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
function bounded(value, max = 512) {
|
|
14
|
+
const text = String(value ?? '').replace(/[\u0000-\u001f\u007f]+/gu, ' ').replace(/\s+/gu, ' ').trim();
|
|
15
|
+
if (!text) return '';
|
|
16
|
+
return text.length <= max ? text : `${text.slice(0, max - 3).trimEnd()}...`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function buildCognitiveWorkFocus(goal) {
|
|
20
|
+
if (!goal || typeof goal !== 'object' || Array.isArray(goal)) return null;
|
|
21
|
+
const goalId = String(goal.goalId ?? '').trim();
|
|
22
|
+
const objective = bounded(goal.objective);
|
|
23
|
+
const completionCriterion = bounded(goal.completionCriterion)
|
|
24
|
+
|| 'Goal completion must be supported by verified evidence.';
|
|
25
|
+
const status = String(goal.status ?? '');
|
|
26
|
+
const turnsUsed = Number(goal.turnsUsed);
|
|
27
|
+
if (!SAFE_ID_RE.test(goalId) || !objective || !STATUSES.has(status)
|
|
28
|
+
|| !Number.isSafeInteger(turnsUsed) || turnsUsed < 0) return null;
|
|
29
|
+
|
|
30
|
+
const focusScope = `goal:${goalId}`;
|
|
31
|
+
if (!SAFE_ID_RE.test(focusScope)) return null;
|
|
32
|
+
const digest = crypto.createHash('sha256')
|
|
33
|
+
.update([goalId, objective, completionCriterion, status, String(turnsUsed)].join('\0'))
|
|
34
|
+
.digest('hex').slice(0, 40);
|
|
35
|
+
const keyRoot = `goal:${goalId}`;
|
|
36
|
+
return {
|
|
37
|
+
snapshotId: `goalfocus-${digest}`,
|
|
38
|
+
focusScope,
|
|
39
|
+
observations: [
|
|
40
|
+
{ domain: 'goal', key: `${keyRoot}:objective`, value: objective, confidence: 1, scope: focusScope },
|
|
41
|
+
{ domain: 'open_thread', key: `${keyRoot}:status`, value: `Goal is ${status}.`, confidence: 1, scope: focusScope },
|
|
42
|
+
{ domain: 'next_trigger', key: `${keyRoot}:next`, value: NEXT_TRIGGER.get(status), confidence: 1, scope: focusScope },
|
|
43
|
+
{ domain: 'expected_evidence', key: `${keyRoot}:evidence`, value: completionCriterion, confidence: 1, scope: focusScope },
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = { buildCognitiveWorkFocus };
|
package/blun.mjs
CHANGED
|
@@ -261464,7 +261464,7 @@ function toolResultText(result) {
|
|
|
261464
261464
|
function abandonedToolResultOutput(ended) {
|
|
261465
261465
|
return `Tool call did not complete: ${ended.reason === "cancelled" ? "the turn was cancelled" : ended.reason === "failed" ? `the turn failed${ended.error !== void 0 ? ` (${ended.error.message})` : ""}` : "the turn ended"} before its result was recorded. Do not assume the tool completed successfully.`;
|
|
261466
261466
|
}
|
|
261467
|
-
var BLUN_CORE_TOOL_NAMES, BLUN_LEAN_TOOL_NAMES, BLUN_ATTACHMENT_MARKER_RE, BLUN_TELEGRAM_OUTBOUND_TOOL_RE, BLUN_TELEGRAM_CHANNEL_RE, BLUN_TOOL_BUDGET_RATIO, createDeferredToolLoader, mediaGenerationToolNamesForText, rememberDeferredToolAfterNotFound, toolSchemaBudgetTokens, projectRecurringCronHistory, TelegramDeliveryLedger, createRuntimeCognitiveTurnLifecycle, buildAttentionQueueItem, LLM_NOT_SET_MESSAGE, GOAL_CONTINUATION_ORIGIN, GOAL_COMPLETION_REMINDER_NAME, GOAL_BLOCKED_REMINDER_NAME, GOAL_RATE_LIMIT_PAUSE_REASON, GOAL_PROVIDER_CONNECTION_PAUSE_PREFIX, GOAL_PROVIDER_AUTH_PAUSE_PREFIX, GOAL_PROVIDER_API_PAUSE_PREFIX, GOAL_MODEL_CONFIG_PAUSE_PREFIX, GOAL_RUNTIME_PAUSE_PREFIX, GOAL_PROVIDER_FILTERED_PAUSE_REASON, GOAL_CONTINUATION_PROMPT, TurnFlow;
|
|
261467
|
+
var BLUN_CORE_TOOL_NAMES, BLUN_LEAN_TOOL_NAMES, BLUN_ATTACHMENT_MARKER_RE, BLUN_TELEGRAM_OUTBOUND_TOOL_RE, BLUN_TELEGRAM_CHANNEL_RE, BLUN_TOOL_BUDGET_RATIO, createDeferredToolLoader, mediaGenerationToolNamesForText, rememberDeferredToolAfterNotFound, toolSchemaBudgetTokens, projectRecurringCronHistory, TelegramDeliveryLedger, createRuntimeCognitiveTurnLifecycle, cognitiveFocusScopesForTurn, buildCognitiveWorkFocus, buildAttentionQueueItem, LLM_NOT_SET_MESSAGE, GOAL_CONTINUATION_ORIGIN, GOAL_COMPLETION_REMINDER_NAME, GOAL_BLOCKED_REMINDER_NAME, GOAL_RATE_LIMIT_PAUSE_REASON, GOAL_PROVIDER_CONNECTION_PAUSE_PREFIX, GOAL_PROVIDER_AUTH_PAUSE_PREFIX, GOAL_PROVIDER_API_PAUSE_PREFIX, GOAL_MODEL_CONFIG_PAUSE_PREFIX, GOAL_RUNTIME_PAUSE_PREFIX, GOAL_PROVIDER_FILTERED_PAUSE_REASON, GOAL_CONTINUATION_PROMPT, TurnFlow;
|
|
261468
261468
|
var init_turn = __esmMin((() => {
|
|
261469
261469
|
init_dist$4();
|
|
261470
261470
|
init_src$4();
|
|
@@ -261485,6 +261485,8 @@ var init_turn = __esmMin((() => {
|
|
|
261485
261485
|
({ projectRecurringCronHistory } = createRequire(import.meta.url)("./bin/recurring-cron-history-policy.cjs"));
|
|
261486
261486
|
({ TelegramDeliveryLedger } = createRequire(import.meta.url)("./bin/repeated-user-message-projection.cjs"));
|
|
261487
261487
|
({ createRuntimeCognitiveTurnLifecycle } = createRequire(import.meta.url)("./bin/cognitive-turn-lifecycle.cjs"));
|
|
261488
|
+
({ cognitiveFocusScopesForTurn } = createRequire(import.meta.url)("./bin/cognitive-focus-scope.cjs"));
|
|
261489
|
+
({ buildCognitiveWorkFocus } = createRequire(import.meta.url)("./bin/cognitive-work-focus.cjs"));
|
|
261488
261490
|
({ buildAttentionQueueItem } = createRequire(import.meta.url)("./bin/cognitive-attention-delivery.cjs"));
|
|
261489
261491
|
BLUN_LEAN_TOOL_NAMES = new Set(BLUN_CORE_TOOL_NAMES);
|
|
261490
261492
|
BLUN_ATTACHMENT_MARKER_RE = /\b(?:attachment_file_id|telegram-anhang|telegram attachment)\b/i;
|
|
@@ -261568,7 +261570,9 @@ var init_turn = __esmMin((() => {
|
|
|
261568
261570
|
try {
|
|
261569
261571
|
this.cognitiveLifecycle = createRuntimeCognitiveTurnLifecycle({
|
|
261570
261572
|
home,
|
|
261571
|
-
agentName: this.agent.activeProfile?.name ?? this.agent.type
|
|
261573
|
+
agentName: this.agent.activeProfile?.name ?? this.agent.type,
|
|
261574
|
+
tenantId: process.env.BLUN_IDENTITY_TENANT_ID,
|
|
261575
|
+
agentId: process.env.BLUN_AGENT_ID
|
|
261572
261576
|
});
|
|
261573
261577
|
return this.cognitiveLifecycle;
|
|
261574
261578
|
} catch (error) {
|
|
@@ -261618,9 +261622,19 @@ var init_turn = __esmMin((() => {
|
|
|
261618
261622
|
this.recordCognitiveStage("recordToolPolicy", policy);
|
|
261619
261623
|
}
|
|
261620
261624
|
}
|
|
261621
|
-
projectCognitiveState(turnId) {
|
|
261625
|
+
projectCognitiveState(turnId, input) {
|
|
261622
261626
|
try {
|
|
261623
|
-
|
|
261627
|
+
const focusScopes = cognitiveFocusScopesForTurn(input);
|
|
261628
|
+
const lifecycle = this.getCognitiveLifecycle();
|
|
261629
|
+
const workFocus = buildCognitiveWorkFocus(this.agent.goal.getGoal().goal);
|
|
261630
|
+
if (workFocus !== null) {
|
|
261631
|
+
lifecycle?.recordFocusSnapshot({
|
|
261632
|
+
snapshotId: workFocus.snapshotId,
|
|
261633
|
+
observations: workFocus.observations
|
|
261634
|
+
});
|
|
261635
|
+
focusScopes.unshift(workFocus.focusScope);
|
|
261636
|
+
}
|
|
261637
|
+
return lifecycle?.projectForTurn({ turnId, focusScopes }) ?? null;
|
|
261624
261638
|
} catch (error) {
|
|
261625
261639
|
this.agent.telemetry.track("cognitive_lifecycle_error", { stage: "projectForTurn", error_type: error?.code ?? error?.name ?? "Error" });
|
|
261626
261640
|
return null;
|
|
@@ -262178,7 +262192,7 @@ var init_turn = __esmMin((() => {
|
|
|
262178
262192
|
if (blunTurnNeedsInitialMcp(input, origin)) await this.agent.mcp?.waitForInitialLoad(signal);
|
|
262179
262193
|
const personalMemoryRecall = await this.agent.injection.injectPersonalMemoryForTurn(turnId, input, origin, signal);
|
|
262180
262194
|
await this.agent.injection.injectGoal();
|
|
262181
|
-
const cognitiveProjection = this.projectCognitiveState(turnId);
|
|
262195
|
+
const cognitiveProjection = this.projectCognitiveState(turnId, input);
|
|
262182
262196
|
if (cognitiveProjection !== null) this.agent.context.appendSystemReminder(cognitiveProjection, {
|
|
262183
262197
|
kind: "injection",
|
|
262184
262198
|
variant: "cognitive_continuity"
|