dsh-live-compact 1.1.0 → 1.1.2

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/shell.js CHANGED
@@ -3,15 +3,19 @@
3
3
  * Thin entry. This file must evaluate even when the engine cannot load.
4
4
  * A throw here leaves stock disabled and /compact waiting.
5
5
  *
6
- * 配置预先检查失败时不构造引擎,也不再构造原版,避免报错被盖成「服务已被注册」。
7
- * On a preflight failure, construct neither engine. Stock would register and hide the real error.
6
+ * 预检查只解析配置,校验交给实际引擎;构造失败时释放本次注册,不重试原版盖掉报错。
7
+ * Resolve config before construction; let the engine validate it and preserve its actual error.
8
8
  */
9
+ import { loadBase, loadCompaction, loadSchema } from "./adapter.js";
10
+ import { configSchema, engineConfig } from "./settings.js";
11
+ import { installPresetGate } from "./gate.js";
9
12
 
10
13
  let Engine = null;
11
14
  let Stock = null;
12
15
  let CompactionEngine = null;
13
16
  let ManualCompactionError = null;
14
17
  let loadError = null;
18
+ let Schema = null;
15
19
 
16
20
  if (process.env.SPINE_ENGINE_FAIL === "import") {
17
21
  loadError = new Error("spine: engine import refused");
@@ -25,7 +29,7 @@ if (process.env.SPINE_ENGINE_FAIL === "import") {
25
29
  }
26
30
 
27
31
  try {
28
- const compaction = await import("@deepseek-ai/dsh-compaction");
32
+ const compaction = await loadCompaction();
29
33
  CompactionEngine = compaction.CompactionEngine;
30
34
  ManualCompactionError = compaction.ManualCompactionError;
31
35
  } catch (error) {
@@ -33,38 +37,41 @@ try {
33
37
  }
34
38
 
35
39
  try {
36
- const stock = await import("@deepseek-ai/dsh-compaction-basic");
40
+ const stock = await loadBase();
37
41
  Stock = stock.BasicCompactionEngine;
38
42
  } catch (error) {
39
43
  if (!loadError) loadError = error instanceof Error ? error : new Error(String(error));
40
44
  }
41
45
 
46
+ // 官方设置界面按这份 schema 自动生成表单。拿不到 schemastery 就退回 stock 的 schema。
47
+ try {
48
+ const schema = await loadSchema();
49
+ Schema = configSchema(schema.default, Stock?.Config);
50
+ } catch {
51
+ Schema = null;
52
+ }
53
+
42
54
  function reasonText(error) {
43
55
  return error instanceof Error ? error.message : String(error);
44
56
  }
45
57
 
46
58
  export function preflightConfig(config = {}) {
47
- if (!config || typeof config !== "object") return;
48
- const threshold = config.thresholdRatio;
49
- if (typeof threshold !== "number") return;
50
- if (config.retainTokens !== undefined) return;
51
- const ratio = config.retainRatio ?? 0.16;
52
- if (ratio >= threshold) {
53
- throw new Error(`BasicCompactionConfig: retainRatio (${ratio}) must be less than the resolved thresholdRatio (${threshold})`);
54
- }
59
+ return engineConfig(config);
55
60
  }
56
61
 
57
- function releaseCompaction(ctx) {
62
+ function compactionRecord(ctx) {
63
+ const key = ctx?.[Symbol.for("cordis.isolate")]?.compaction;
64
+ return key === undefined ? undefined : ctx?.reflect?.store?.[key];
65
+ }
66
+
67
+ function releaseCompaction(ctx, previous) {
58
68
  const store = ctx?.reflect?.store;
59
- if (!store) return false;
60
- const keys = [...Object.getOwnPropertySymbols(store), ...Object.keys(store)];
61
- for (const key of keys) {
62
- if (store[key]?.name !== "compaction") continue;
63
- delete store[key];
64
- if (ctx.fiber?.store) delete ctx.fiber.store.compaction;
65
- return true;
66
- }
67
- return false;
69
+ const key = ctx?.[Symbol.for("cordis.isolate")]?.compaction;
70
+ const current = compactionRecord(ctx);
71
+ if (!current || current === previous || current.fiber !== ctx.fiber) return false;
72
+ delete store[key];
73
+ if (ctx.fiber?.store?.compaction === current) delete ctx.fiber.store.compaction;
74
+ return true;
68
75
  }
69
76
 
70
77
  function visibleTakeover(ctx, reason) {
@@ -97,15 +104,18 @@ const UnavailableCompaction = CompactionEngine
97
104
 
98
105
  export default class LiveCompactEntry {
99
106
  static inject = ["llm", "tokenMeter", "sessions"];
100
- static Config = Stock?.Config || Engine?.Config;
107
+ static Config = Schema || Stock?.Config || Engine?.Config;
101
108
 
102
109
  constructor(ctx, config) {
110
+ installPresetGate(ctx, config);
111
+ const previousCompaction = compactionRecord(ctx);
103
112
  let cause = loadError;
113
+ let resolvedConfig;
104
114
  let skipStock = process.env.SPINE_ENGINE_FAIL === "construct";
105
115
  if (skipStock) cause = new Error("spine: constructor refused");
106
116
  if (!loadError && !skipStock) {
107
117
  try {
108
- preflightConfig(config);
118
+ resolvedConfig = preflightConfig(config);
109
119
  } catch (error) {
110
120
  cause = error instanceof Error ? error : new Error(String(error));
111
121
  skipStock = true;
@@ -113,10 +123,10 @@ export default class LiveCompactEntry {
113
123
  }
114
124
  if (!loadError && !skipStock && Engine) {
115
125
  try {
116
- return new Engine(ctx, config);
126
+ return new Engine(ctx, config, resolvedConfig);
117
127
  } catch (error) {
118
128
  cause = error instanceof Error ? error : new Error(String(error));
119
- releaseCompaction(ctx);
129
+ releaseCompaction(ctx, previousCompaction);
120
130
  skipStock = true;
121
131
  }
122
132
  }
@@ -124,10 +134,10 @@ export default class LiveCompactEntry {
124
134
  if (!skipStock && process.env.SPINE_STOCK_FAIL !== "1" && Stock) {
125
135
  try {
126
136
  visibleTakeover(ctx, `这一轮用原版压缩。${reasonText(cause)}`);
127
- return new Stock(ctx, config);
137
+ return new Stock(ctx, engineConfig(config));
128
138
  } catch (error) {
129
139
  cause = error instanceof Error ? error : new Error(String(error));
130
- releaseCompaction(ctx);
140
+ releaseCompaction(ctx, previousCompaction);
131
141
  }
132
142
  }
133
143
  visibleTakeover(ctx, reasonText(cause));