@martian-engineering/lossless-claw 0.2.4 → 0.2.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/index.ts +20 -1
- package/package.json +1 -1
- package/src/engine.ts +12 -7
package/index.ts
CHANGED
|
@@ -43,6 +43,7 @@ type PluginEnvSnapshot = {
|
|
|
43
43
|
lcmSummaryModel: string;
|
|
44
44
|
lcmSummaryProvider: string;
|
|
45
45
|
openclawProvider: string;
|
|
46
|
+
openclawDefaultModel: string;
|
|
46
47
|
agentDir: string;
|
|
47
48
|
home: string;
|
|
48
49
|
};
|
|
@@ -62,11 +63,27 @@ function snapshotPluginEnv(env: NodeJS.ProcessEnv = process.env): PluginEnvSnaps
|
|
|
62
63
|
lcmSummaryModel: env.LCM_SUMMARY_MODEL?.trim() ?? "",
|
|
63
64
|
lcmSummaryProvider: env.LCM_SUMMARY_PROVIDER?.trim() ?? "",
|
|
64
65
|
openclawProvider: env.OPENCLAW_PROVIDER?.trim() ?? "",
|
|
66
|
+
openclawDefaultModel: "",
|
|
65
67
|
agentDir: env.OPENCLAW_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim() || "",
|
|
66
68
|
home: env.HOME?.trim() ?? "",
|
|
67
69
|
};
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
/** Read OpenClaw's configured default model from the validated runtime config. */
|
|
73
|
+
function readDefaultModelFromConfig(config: unknown): string {
|
|
74
|
+
if (!config || typeof config !== "object") {
|
|
75
|
+
return "";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const model = (config as { agents?: { defaults?: { model?: unknown } } }).agents?.defaults?.model;
|
|
79
|
+
if (typeof model === "string") {
|
|
80
|
+
return model.trim();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const primary = (model as { primary?: unknown } | undefined)?.primary;
|
|
84
|
+
return typeof primary === "string" ? primary.trim() : "";
|
|
85
|
+
}
|
|
86
|
+
|
|
70
87
|
/** Resolve common provider API keys from environment. */
|
|
71
88
|
function resolveApiKey(provider: string, readEnv: ReadEnvFn): string | undefined {
|
|
72
89
|
const keyMap: Record<string, string[]> = {
|
|
@@ -596,6 +613,7 @@ function readLatestAssistantReply(messages: unknown[]): string | undefined {
|
|
|
596
613
|
/** Construct LCM dependencies from plugin API/runtime surfaces. */
|
|
597
614
|
function createLcmDependencies(api: OpenClawPluginApi): LcmDependencies {
|
|
598
615
|
const envSnapshot = snapshotPluginEnv();
|
|
616
|
+
envSnapshot.openclawDefaultModel = readDefaultModelFromConfig(api.config);
|
|
599
617
|
const readEnv: ReadEnvFn = (key) => process.env[key];
|
|
600
618
|
const pluginConfig =
|
|
601
619
|
api.pluginConfig && typeof api.pluginConfig === "object" && !Array.isArray(api.pluginConfig)
|
|
@@ -789,7 +807,8 @@ function createLcmDependencies(api: OpenClawPluginApi): LcmDependencies {
|
|
|
789
807
|
}
|
|
790
808
|
},
|
|
791
809
|
resolveModel: (modelRef, providerHint) => {
|
|
792
|
-
const raw =
|
|
810
|
+
const raw =
|
|
811
|
+
(modelRef?.trim() || envSnapshot.lcmSummaryModel || envSnapshot.openclawDefaultModel).trim();
|
|
793
812
|
if (!raw) {
|
|
794
813
|
throw new Error("No model configured for LCM summarization.");
|
|
795
814
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@martian-engineering/lossless-claw",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Lossless Context Management plugin for OpenClaw — DAG-based conversation summarization with incremental compaction",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
package/src/engine.ts
CHANGED
|
@@ -1509,6 +1509,10 @@ export class LcmContextEngine implements ContextEngine {
|
|
|
1509
1509
|
observedTokens !== undefined
|
|
1510
1510
|
? await this.compaction.evaluate(conversationId, tokenBudget, observedTokens)
|
|
1511
1511
|
: await this.compaction.evaluate(conversationId, tokenBudget);
|
|
1512
|
+
const targetTokens =
|
|
1513
|
+
params.compactionTarget === "threshold" ? decision.threshold : tokenBudget;
|
|
1514
|
+
const liveContextStillExceedsTarget =
|
|
1515
|
+
observedTokens !== undefined && observedTokens >= targetTokens;
|
|
1512
1516
|
|
|
1513
1517
|
if (!forceCompaction && !decision.shouldCompact) {
|
|
1514
1518
|
return {
|
|
@@ -1533,27 +1537,28 @@ export class LcmContextEngine implements ContextEngine {
|
|
|
1533
1537
|
});
|
|
1534
1538
|
|
|
1535
1539
|
return {
|
|
1536
|
-
ok:
|
|
1540
|
+
ok: sweepResult.actionTaken || !liveContextStillExceedsTarget,
|
|
1537
1541
|
compacted: sweepResult.actionTaken,
|
|
1538
1542
|
reason: sweepResult.actionTaken
|
|
1539
1543
|
? "compacted"
|
|
1540
1544
|
: manualCompactionRequested
|
|
1541
1545
|
? "nothing to compact"
|
|
1542
|
-
:
|
|
1546
|
+
: liveContextStillExceedsTarget
|
|
1547
|
+
? "live context still exceeds target"
|
|
1548
|
+
: "already under target",
|
|
1543
1549
|
result: {
|
|
1544
1550
|
tokensBefore: decision.currentTokens,
|
|
1545
1551
|
tokensAfter: sweepResult.tokensAfter,
|
|
1546
1552
|
details: {
|
|
1547
1553
|
rounds: sweepResult.actionTaken ? 1 : 0,
|
|
1548
|
-
targetTokens
|
|
1549
|
-
params.compactionTarget === "threshold" ? decision.threshold : tokenBudget,
|
|
1554
|
+
targetTokens,
|
|
1550
1555
|
},
|
|
1551
1556
|
},
|
|
1552
1557
|
};
|
|
1553
1558
|
}
|
|
1554
1559
|
|
|
1555
1560
|
// When forced, use the token budget as target
|
|
1556
|
-
const
|
|
1561
|
+
const convergenceTargetTokens = forceCompaction
|
|
1557
1562
|
? tokenBudget
|
|
1558
1563
|
: params.compactionTarget === "threshold"
|
|
1559
1564
|
? decision.threshold
|
|
@@ -1562,7 +1567,7 @@ export class LcmContextEngine implements ContextEngine {
|
|
|
1562
1567
|
const compactResult = await this.compaction.compactUntilUnder({
|
|
1563
1568
|
conversationId,
|
|
1564
1569
|
tokenBudget,
|
|
1565
|
-
targetTokens,
|
|
1570
|
+
targetTokens: convergenceTargetTokens,
|
|
1566
1571
|
...(observedTokens !== undefined ? { currentTokens: observedTokens } : {}),
|
|
1567
1572
|
summarize,
|
|
1568
1573
|
});
|
|
@@ -1581,7 +1586,7 @@ export class LcmContextEngine implements ContextEngine {
|
|
|
1581
1586
|
tokensAfter: compactResult.finalTokens,
|
|
1582
1587
|
details: {
|
|
1583
1588
|
rounds: compactResult.rounds,
|
|
1584
|
-
targetTokens,
|
|
1589
|
+
targetTokens: convergenceTargetTokens,
|
|
1585
1590
|
},
|
|
1586
1591
|
},
|
|
1587
1592
|
};
|