@psiclawops/hypercompositor 0.8.3 → 0.8.5
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/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +103 -21
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -136,6 +136,32 @@ export declare function resolveEffectiveBudget(args: {
|
|
|
136
136
|
budget: number;
|
|
137
137
|
source: string;
|
|
138
138
|
};
|
|
139
|
+
export interface ModelIdentity {
|
|
140
|
+
rawModel: string | null;
|
|
141
|
+
modelKey: string | null;
|
|
142
|
+
provider: string | null;
|
|
143
|
+
modelId: string | null;
|
|
144
|
+
}
|
|
145
|
+
export declare function resolveModelIdentity(model?: string): ModelIdentity;
|
|
146
|
+
export declare function diffModelState(previous: {
|
|
147
|
+
model?: string;
|
|
148
|
+
modelKey?: string | null;
|
|
149
|
+
provider?: string | null;
|
|
150
|
+
modelId?: string | null;
|
|
151
|
+
tokenBudget?: number;
|
|
152
|
+
} | null | undefined, current: {
|
|
153
|
+
model?: string;
|
|
154
|
+
tokenBudget?: number;
|
|
155
|
+
}): {
|
|
156
|
+
previousIdentity: ModelIdentity;
|
|
157
|
+
currentIdentity: ModelIdentity;
|
|
158
|
+
modelChanged: boolean;
|
|
159
|
+
providerChanged: boolean;
|
|
160
|
+
modelIdChanged: boolean;
|
|
161
|
+
budgetChanged: boolean;
|
|
162
|
+
budgetDownshift: boolean;
|
|
163
|
+
budgetUplift: boolean;
|
|
164
|
+
};
|
|
139
165
|
/**
|
|
140
166
|
* Bust the assembly cache for a specific agent+session.
|
|
141
167
|
* Call this after writing to identity files (SOUL.md, IDENTITY.md, TOOLS.md,
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -400,6 +400,48 @@ export function resolveEffectiveBudget(args) {
|
|
|
400
400
|
source: 'fallback contextWindowSize',
|
|
401
401
|
};
|
|
402
402
|
}
|
|
403
|
+
export function resolveModelIdentity(model) {
|
|
404
|
+
const modelKey = normalizeModelKey(model);
|
|
405
|
+
if (!modelKey) {
|
|
406
|
+
return {
|
|
407
|
+
rawModel: model ?? null,
|
|
408
|
+
modelKey: null,
|
|
409
|
+
provider: null,
|
|
410
|
+
modelId: null,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
const slash = modelKey.indexOf('/');
|
|
414
|
+
return {
|
|
415
|
+
rawModel: model ?? null,
|
|
416
|
+
modelKey,
|
|
417
|
+
provider: slash > 0 ? modelKey.slice(0, slash) : null,
|
|
418
|
+
modelId: slash > 0 && slash < modelKey.length - 1 ? modelKey.slice(slash + 1) : modelKey,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
export function diffModelState(previous, current) {
|
|
422
|
+
const previousIdentity = previous?.modelKey || previous?.provider || previous?.modelId
|
|
423
|
+
? {
|
|
424
|
+
rawModel: previous.model ?? null,
|
|
425
|
+
modelKey: previous.modelKey ?? normalizeModelKey(previous.model),
|
|
426
|
+
provider: previous.provider ?? resolveModelIdentity(previous.model).provider,
|
|
427
|
+
modelId: previous.modelId ?? resolveModelIdentity(previous.model).modelId,
|
|
428
|
+
}
|
|
429
|
+
: resolveModelIdentity(previous?.model);
|
|
430
|
+
const currentIdentity = resolveModelIdentity(current.model);
|
|
431
|
+
const previousBudget = previous?.tokenBudget;
|
|
432
|
+
const currentBudget = current.tokenBudget;
|
|
433
|
+
const budgetChanged = previousBudget != null && currentBudget != null && previousBudget !== currentBudget;
|
|
434
|
+
return {
|
|
435
|
+
previousIdentity,
|
|
436
|
+
currentIdentity,
|
|
437
|
+
modelChanged: previousIdentity.modelKey !== currentIdentity.modelKey,
|
|
438
|
+
providerChanged: previousIdentity.provider !== currentIdentity.provider,
|
|
439
|
+
modelIdChanged: previousIdentity.modelId !== currentIdentity.modelId,
|
|
440
|
+
budgetChanged,
|
|
441
|
+
budgetDownshift: previousBudget != null && currentBudget != null && currentBudget < previousBudget,
|
|
442
|
+
budgetUplift: previousBudget != null && currentBudget != null && currentBudget > previousBudget,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
403
445
|
function normalizeModelKey(model) {
|
|
404
446
|
if (!model)
|
|
405
447
|
return null;
|
|
@@ -723,6 +765,31 @@ function extractTextFromInboundContent(content) {
|
|
|
723
765
|
.map(part => part.text ?? '')
|
|
724
766
|
.join('\n');
|
|
725
767
|
}
|
|
768
|
+
function resolveAssistantTokenCount(msg, runtimeContext) {
|
|
769
|
+
const usage = msg.usage;
|
|
770
|
+
if (usage && typeof usage === 'object') {
|
|
771
|
+
const candidates = [
|
|
772
|
+
usage.total,
|
|
773
|
+
usage.totalTokens,
|
|
774
|
+
usage.total_tokens,
|
|
775
|
+
usage.output,
|
|
776
|
+
usage.outputTokens,
|
|
777
|
+
usage.output_tokens,
|
|
778
|
+
usage.completionTokens,
|
|
779
|
+
usage.completion_tokens,
|
|
780
|
+
];
|
|
781
|
+
for (const candidate of candidates) {
|
|
782
|
+
if (typeof candidate === 'number' && Number.isFinite(candidate) && candidate > 0) {
|
|
783
|
+
return Math.floor(candidate);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
const runtimeTokenCount = runtimeContext?.currentTokenCount;
|
|
788
|
+
if (typeof runtimeTokenCount === 'number' && Number.isFinite(runtimeTokenCount) && runtimeTokenCount > 0) {
|
|
789
|
+
return Math.floor(runtimeTokenCount);
|
|
790
|
+
}
|
|
791
|
+
return undefined;
|
|
792
|
+
}
|
|
726
793
|
function collectNeutralToolPairStats(messages) {
|
|
727
794
|
const callIds = new Set();
|
|
728
795
|
const resultIds = new Set();
|
|
@@ -1291,10 +1358,10 @@ function createHyperMemEngine() {
|
|
|
1291
1358
|
// Non-fatal: missing files are silently skipped.
|
|
1292
1359
|
let identityBlock;
|
|
1293
1360
|
try {
|
|
1294
|
-
// Council agents live at workspace
|
|
1361
|
+
// Council agents live at workspace/<agentId>/
|
|
1295
1362
|
// Other agents at workspace/<agentId>/ — try council path first
|
|
1296
1363
|
const homedir = os.homedir();
|
|
1297
|
-
const councilPath = path.join(homedir, '.openclaw', 'workspace
|
|
1364
|
+
const councilPath = path.join(homedir, '.openclaw', 'workspace', agentId);
|
|
1298
1365
|
const workspacePath = path.join(homedir, '.openclaw', 'workspace', agentId);
|
|
1299
1366
|
let wsPath = councilPath;
|
|
1300
1367
|
try {
|
|
@@ -1326,7 +1393,7 @@ function createHyperMemEngine() {
|
|
|
1326
1393
|
let _wsPathForSeed;
|
|
1327
1394
|
try {
|
|
1328
1395
|
const homedir2 = os.homedir();
|
|
1329
|
-
const councilPath2 = path.join(homedir2, '.openclaw', 'workspace
|
|
1396
|
+
const councilPath2 = path.join(homedir2, '.openclaw', 'workspace', agentId);
|
|
1330
1397
|
const workspacePath2 = path.join(homedir2, '.openclaw', 'workspace', agentId);
|
|
1331
1398
|
try {
|
|
1332
1399
|
await fs.access(councilPath2);
|
|
@@ -1361,7 +1428,7 @@ function createHyperMemEngine() {
|
|
|
1361
1428
|
// Post-warm pressure check: if messages.db had accumulated history,
|
|
1362
1429
|
// warm() may have loaded the session straight to 80%+. Pre-trim now
|
|
1363
1430
|
// so the first turn has headroom instead of starting saturated.
|
|
1364
|
-
// This is the "restart at 98%" failure mode reported by
|
|
1431
|
+
// This is the "restart at 98%" failure mode reported by Eve 2026-04-05:
|
|
1365
1432
|
// JSONL truncation + Redis flush isn't enough if messages.db is still full
|
|
1366
1433
|
// and warm() reloads it. Trim here closes the loop.
|
|
1367
1434
|
try {
|
|
@@ -2063,23 +2130,32 @@ function createHyperMemEngine() {
|
|
|
2063
2130
|
console.warn('[hypermem-plugin] assemble: Redis trim failed (non-fatal):', trimErr.message);
|
|
2064
2131
|
}
|
|
2065
2132
|
// ── Budget downshift: proactive reshape pass ───────────────────────────────────────
|
|
2066
|
-
//
|
|
2067
|
-
//
|
|
2068
|
-
//
|
|
2069
|
-
//
|
|
2070
|
-
//
|
|
2071
|
-
//
|
|
2072
|
-
//
|
|
2073
|
-
// Bug fix: previously read from getWindow() which is always null here
|
|
2074
|
-
// (afterTurn invalidates it every turn). Also fixed: was doing setWindow()
|
|
2075
|
-
// then invalidateWindow() which is a write-then-delete no-op. Now reads
|
|
2076
|
-
// from history list and writes back via replaceHistory().
|
|
2133
|
+
// Detect provider/model identity changes as well as raw budget changes.
|
|
2134
|
+
// Provider routing matters operationally because the same model family can
|
|
2135
|
+
// land on a different effective context window, for example Copilot Sonnet
|
|
2136
|
+
// vs direct Anthropic Sonnet. Only budget downshifts trigger the demoted
|
|
2137
|
+
// reshape guard, but verbose logs now show provider/model swaps even when
|
|
2138
|
+
// the effective budget stays flat or increases.
|
|
2077
2139
|
let lastState = null;
|
|
2078
2140
|
try {
|
|
2079
2141
|
lastState = await hm.cache.getModelState(agentId, sk);
|
|
2080
2142
|
const DOWNSHIFT_THRESHOLD = 0.10;
|
|
2081
|
-
const
|
|
2082
|
-
|
|
2143
|
+
const modelDelta = diffModelState(lastState, {
|
|
2144
|
+
model,
|
|
2145
|
+
tokenBudget: effectiveBudget,
|
|
2146
|
+
});
|
|
2147
|
+
const downshiftFraction = lastState?.tokenBudget
|
|
2148
|
+
? (lastState.tokenBudget - effectiveBudget) / lastState.tokenBudget
|
|
2149
|
+
: 0;
|
|
2150
|
+
const isDownshift = modelDelta.budgetDownshift && downshiftFraction > DOWNSHIFT_THRESHOLD;
|
|
2151
|
+
if (lastState && (modelDelta.modelChanged || modelDelta.budgetChanged)) {
|
|
2152
|
+
verboseLog(`[hypermem-plugin] model state change: ` +
|
|
2153
|
+
`prev=${modelDelta.previousIdentity.modelKey ?? 'unknown'} ` +
|
|
2154
|
+
`next=${modelDelta.currentIdentity.modelKey ?? 'unknown'} ` +
|
|
2155
|
+
`providerChanged=${modelDelta.providerChanged} ` +
|
|
2156
|
+
`modelIdChanged=${modelDelta.modelIdChanged} ` +
|
|
2157
|
+
`budget=${lastState.tokenBudget}->${effectiveBudget}`);
|
|
2158
|
+
}
|
|
2083
2159
|
if (isDownshift && !_deferToolPruning) {
|
|
2084
2160
|
// Sprint 2.2a: demote reshape to guard telemetry.
|
|
2085
2161
|
//
|
|
@@ -2244,8 +2320,12 @@ ${replayRecovery.emittedText}`
|
|
|
2244
2320
|
await persistReplayRecoveryState(hm, agentId, sk, replayRecovery.nextState);
|
|
2245
2321
|
// Update model state for downshift detection on next turn
|
|
2246
2322
|
try {
|
|
2323
|
+
const modelIdentity = resolveModelIdentity(model);
|
|
2247
2324
|
await hm.cache.setModelState(agentId, sk, {
|
|
2248
2325
|
model: model ?? 'unknown',
|
|
2326
|
+
modelKey: modelIdentity.modelKey ?? undefined,
|
|
2327
|
+
provider: modelIdentity.provider ?? undefined,
|
|
2328
|
+
modelId: modelIdentity.modelId ?? undefined,
|
|
2249
2329
|
tokenBudget: effectiveBudget,
|
|
2250
2330
|
composedAt: new Date().toISOString(),
|
|
2251
2331
|
historyDepth,
|
|
@@ -2481,7 +2561,7 @@ ${replayRecovery.emittedText}`
|
|
|
2481
2561
|
* it never calls ingest() or ingestBatch(). So we must ingest the new
|
|
2482
2562
|
* messages here, using messages.slice(prePromptMessageCount).
|
|
2483
2563
|
*/
|
|
2484
|
-
async afterTurn({ sessionId, sessionKey, messages, prePromptMessageCount, isHeartbeat }) {
|
|
2564
|
+
async afterTurn({ sessionId, sessionKey, messages, prePromptMessageCount, isHeartbeat, runtimeContext }) {
|
|
2485
2565
|
if (isHeartbeat)
|
|
2486
2566
|
return;
|
|
2487
2567
|
try {
|
|
@@ -2523,7 +2603,9 @@ ${replayRecovery.emittedText}`
|
|
|
2523
2603
|
await hm.recordUserMessage(agentId, sk, stripMessageMetadata(neutral.textContent ?? ''));
|
|
2524
2604
|
}
|
|
2525
2605
|
else {
|
|
2526
|
-
await hm.recordAssistantMessage(agentId, sk, neutral
|
|
2606
|
+
await hm.recordAssistantMessage(agentId, sk, neutral, {
|
|
2607
|
+
tokenCount: neutral.role === 'assistant' ? resolveAssistantTokenCount(m, runtimeContext) : undefined,
|
|
2608
|
+
});
|
|
2527
2609
|
}
|
|
2528
2610
|
}
|
|
2529
2611
|
// P3.1: Topic detection on the inbound user message
|
|
@@ -2583,7 +2665,7 @@ ${replayRecovery.emittedText}`
|
|
|
2583
2665
|
// gradient-compressed window to budget before writing to Redis. Without
|
|
2584
2666
|
// this, afterTurn writes up to 250 messages regardless of budget, causing
|
|
2585
2667
|
// trimHistoryToTokenBudget to fire and trim ~200 messages on every
|
|
2586
|
-
// subsequent assemble() — the churn loop seen in
|
|
2668
|
+
// subsequent assemble() — the churn loop seen in Eve's logs.
|
|
2587
2669
|
if (hm.cache.isConnected) {
|
|
2588
2670
|
try {
|
|
2589
2671
|
const modelState = await hm.cache.getModelState(agentId, sk);
|
|
@@ -2607,7 +2689,7 @@ ${replayRecovery.emittedText}`
|
|
|
2607
2689
|
// If a session just finished a turn at >80% pressure, the NEXT turn's
|
|
2608
2690
|
// incoming tool results (parallel web searches, large exec output, etc.)
|
|
2609
2691
|
// will hit a window with no headroom — the ingestion wave failure mode
|
|
2610
|
-
// (reported by
|
|
2692
|
+
// (reported by Eve, 2026-04-05). Pre-trim here so the tool-loop
|
|
2611
2693
|
// assemble() path starts the next turn with meaningful space.
|
|
2612
2694
|
//
|
|
2613
2695
|
// Uses modelState.tokenBudget if cached; skips if unavailable (non-fatal).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@psiclawops/hypercompositor",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "HyperCompositor
|
|
3
|
+
"version": "0.8.5",
|
|
4
|
+
"description": "HyperCompositor — context engine plugin for OpenClaw",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"openclaw": {
|
|
19
19
|
"plugin": {
|
|
20
20
|
"id": "hypercompositor",
|
|
21
|
-
"name": "HyperCompositor
|
|
21
|
+
"name": "HyperCompositor — Context Engine",
|
|
22
22
|
"kind": "context-engine"
|
|
23
23
|
},
|
|
24
24
|
"extensions": [
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"typecheck": "tsc --noEmit"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@psiclawops/hypermem": "file:.."
|
|
41
|
+
"@psiclawops/hypermem": "file:..",
|
|
42
|
+
"zod": "^4.0.0"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"openclaw": "*",
|
|
45
|
-
"typescript": "^5.4.0"
|
|
46
|
-
"zod": "^4.0.0"
|
|
46
|
+
"typescript": "^5.4.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"openclaw": "*"
|