stratagate-dsh 0.3.12 → 0.3.14

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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dsh-host-resolution.ts","../src/bootstrap.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\r\nimport { createRequire, registerHooks } from 'node:module'\r\nimport { dirname, isAbsolute, join, relative } from 'node:path'\r\nimport { fileURLToPath, pathToFileURL } from 'node:url'\r\n\r\nconst HOST_PACKAGES = [\r\n '@deepseek-ai/cordis',\r\n '@deepseek-ai/dsh-agent-default-model',\r\n '@deepseek-ai/dsh-client-ui-conversation',\r\n '@deepseek-ai/dsh-llm',\r\n '@deepseek-ai/dsh-native-command',\r\n '@deepseek-ai/dsh-session',\r\n '@deepseek-ai/dsh-session-format',\r\n '@deepseek-ai/dsh-session-format-catalog',\r\n '@deepseek-ai/dsh-session-format-v0-to-v1',\r\n '@deepseek-ai/dsh-settings',\r\n '@deepseek-ai/dsh-system-prompt',\r\n '@deepseek-ai/dsh-tools',\r\n '@deepseek-ai/schemastery',\r\n] as const\r\n\r\nconst installedHooks = Symbol.for('stratagate.dsh-host-resolution.v1')\r\n\r\nfunction isWithin(path: string, root: string): boolean {\r\n const child = relative(root, path)\r\n return child === '' || (!child.startsWith('..') && !isAbsolute(child))\r\n}\r\n\r\nfunction profileDirectory(start: string): string | undefined {\r\n let directory = start\r\n for (;;) {\r\n const manifestPath = join(directory, 'package.json')\r\n if (existsSync(manifestPath)) {\r\n try {\r\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as { dsh?: { profile?: unknown } }\r\n if (manifest.dsh?.profile && typeof manifest.dsh.profile === 'object') return directory\r\n } catch {}\r\n }\r\n const parent = dirname(directory)\r\n if (parent === directory) return undefined\r\n directory = parent\r\n }\r\n}\r\n\r\nfunction hostPackage(specifier: string): boolean {\r\n return HOST_PACKAGES.some((name) => specifier === name || specifier.startsWith(`${name}/`))\r\n}\r\n\r\n/**\r\n * Force only StrataGate's DSH imports through the installation-owned fallback\r\n * created by DSH. The hook neither deletes nor rewrites the profile's package\r\n * tree, and imports belonging to the host or other plugins are untouched.\r\n */\r\nexport function installDshHostResolution(moduleUrl: string): boolean {\r\n const packageDirectory = dirname(dirname(fileURLToPath(moduleUrl)))\r\n const profile = profileDirectory(packageDirectory)\r\n if (!profile) return false\r\n\r\n const globalState = globalThis as typeof globalThis & { [installedHooks]?: Set<string> }\r\n const installed = globalState[installedHooks] ??= new Set<string>()\r\n const key = `${profile}\\u0000${packageDirectory}`\r\n if (installed.has(key)) return true\r\n\r\n const fallbackModules = join(dirname(profile), 'node_modules')\r\n const hostRequire = createRequire(join(fallbackModules, '.stratagate-host-resolution.cjs'))\r\n registerHooks({\r\n resolve(specifier, context, nextResolve) {\r\n const parent = context.parentURL?.startsWith('file:') ? fileURLToPath(context.parentURL) : undefined\r\n if (!hostPackage(specifier) || !parent || !isWithin(parent, packageDirectory)) {\r\n return nextResolve(specifier, context)\r\n }\r\n try {\r\n return { url: pathToFileURL(hostRequire.resolve(specifier)).href, shortCircuit: true }\r\n } catch (cause) {\r\n if (specifier === '@deepseek-ai/dsh-session-format-v0-to-v1'\r\n || specifier === '@deepseek-ai/dsh-session-format-catalog') {\r\n return nextResolve(specifier, context)\r\n }\r\n throw new Error(\r\n `StrataGate cannot resolve host-provided DSH package ${JSON.stringify(specifier)} from ${fallbackModules}. `\r\n + 'Start StrataGate through the DSH profile launcher so the host can prepare its module fallback.',\r\n { cause },\r\n )\r\n }\r\n },\r\n })\r\n installed.add(key)\r\n return true\r\n}\r\n","import { installDshHostResolution } from './dsh-host-resolution.js'\n\n// DSH prepares its installation-owned module fallback before it imports a\n// profile bundle. Install the narrowly-scoped resolver first, then load the\n// implementation so stale profile-local peers cannot win ESM resolution.\ninstallDshHostResolution(import.meta.url)\n\n// This file and src/index.ts are separate tsup entries. The runtime path is\n// intentionally external so the implementation is instantiated only after\n// the resolver above is active.\n// @ts-expect-error dist/plugin.js is emitted from src/index.ts during build.\nconst plugin = await import('./plugin.js') as typeof import('./index.js')\n\nexport const name = plugin.name\nexport const inject = plugin.inject\nexport const STRATAGATE_SETTINGS_NAMESPACE = plugin.STRATAGATE_SETTINGS_NAMESPACE\nexport const Config = plugin.Config\nexport const apply = plugin.apply\nexport type PluginConfig = import('./index.js').PluginConfig\n"],"mappings":";AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,eAAe,qBAAqB;AAC7C,SAAS,SAAS,YAAY,MAAM,gBAAgB;AACpD,SAAS,eAAe,qBAAqB;AAE7C,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB,uBAAO,IAAI,mCAAmC;AAErE,SAAS,SAAS,MAAc,MAAuB;AACrD,QAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,SAAO,UAAU,MAAO,CAAC,MAAM,WAAW,IAAI,KAAK,CAAC,WAAW,KAAK;AACtE;AAEA,SAAS,iBAAiB,OAAmC;AAC3D,MAAI,YAAY;AAChB,aAAS;AACP,UAAM,eAAe,KAAK,WAAW,cAAc;AACnD,QAAI,WAAW,YAAY,GAAG;AAC5B,UAAI;AACF,cAAM,WAAW,KAAK,MAAM,aAAa,cAAc,MAAM,CAAC;AAC9D,YAAI,SAAS,KAAK,WAAW,OAAO,SAAS,IAAI,YAAY,SAAU,QAAO;AAAA,MAChF,QAAQ;AAAA,MAAC;AAAA,IACX;AACA,UAAM,SAAS,QAAQ,SAAS;AAChC,QAAI,WAAW,UAAW,QAAO;AACjC,gBAAY;AAAA,EACd;AACF;AAEA,SAAS,YAAY,WAA4B;AAC/C,SAAO,cAAc,KAAK,CAACA,UAAS,cAAcA,SAAQ,UAAU,WAAW,GAAGA,KAAI,GAAG,CAAC;AAC5F;AAOO,SAAS,yBAAyB,WAA4B;AACnE,QAAM,mBAAmB,QAAQ,QAAQ,cAAc,SAAS,CAAC,CAAC;AAClE,QAAM,UAAU,iBAAiB,gBAAgB;AACjD,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,cAAc;AACpB,QAAM,YAAY,YAAY,cAAc,MAAM,oBAAI,IAAY;AAClE,QAAM,MAAM,GAAG,OAAO,KAAS,gBAAgB;AAC/C,MAAI,UAAU,IAAI,GAAG,EAAG,QAAO;AAE/B,QAAM,kBAAkB,KAAK,QAAQ,OAAO,GAAG,cAAc;AAC7D,QAAM,cAAc,cAAc,KAAK,iBAAiB,iCAAiC,CAAC;AAC1F,gBAAc;AAAA,IACZ,QAAQ,WAAW,SAAS,aAAa;AACvC,YAAM,SAAS,QAAQ,WAAW,WAAW,OAAO,IAAI,cAAc,QAAQ,SAAS,IAAI;AAC3F,UAAI,CAAC,YAAY,SAAS,KAAK,CAAC,UAAU,CAAC,SAAS,QAAQ,gBAAgB,GAAG;AAC7E,eAAO,YAAY,WAAW,OAAO;AAAA,MACvC;AACA,UAAI;AACF,eAAO,EAAE,KAAK,cAAc,YAAY,QAAQ,SAAS,CAAC,EAAE,MAAM,cAAc,KAAK;AAAA,MACvF,SAAS,OAAO;AACd,YAAI,cAAc,8CACb,cAAc,2CAA2C;AAC5D,iBAAO,YAAY,WAAW,OAAO;AAAA,QACvC;AACA,cAAM,IAAI;AAAA,UACR,uDAAuD,KAAK,UAAU,SAAS,CAAC,SAAS,eAAe;AAAA,UAExG,EAAE,MAAM;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACD,YAAU,IAAI,GAAG;AACjB,SAAO;AACT;;;ACnFA,yBAAyB,YAAY,GAAG;AAMxC,IAAM,SAAS,MAAM,OAAO,aAAa;AAElC,IAAM,OAAO,OAAO;AACpB,IAAM,SAAS,OAAO;AACtB,IAAM,gCAAgC,OAAO;AAC7C,IAAM,SAAS,OAAO;AACtB,IAAM,QAAQ,OAAO;","names":["name"]}
1
+ {"version":3,"sources":["../src/dsh-host-resolution.ts","../src/bootstrap.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\r\nimport { createRequire, registerHooks } from 'node:module'\r\nimport { dirname, isAbsolute, join, relative } from 'node:path'\r\nimport { fileURLToPath, pathToFileURL } from 'node:url'\r\n\r\nconst HOST_PACKAGES = [\r\n '@deepseek-ai/cordis',\r\n '@deepseek-ai/dsh-agent-default-model',\r\n '@deepseek-ai/dsh-client-ui-conversation',\r\n '@deepseek-ai/dsh-llm',\r\n '@deepseek-ai/dsh-native-command',\r\n '@deepseek-ai/dsh-session',\r\n '@deepseek-ai/dsh-session-format',\r\n '@deepseek-ai/dsh-session-format-catalog',\r\n '@deepseek-ai/dsh-session-format-v0-to-v1',\r\n '@deepseek-ai/dsh-settings',\r\n '@deepseek-ai/dsh-system-prompt',\r\n '@deepseek-ai/dsh-tools',\r\n '@deepseek-ai/schemastery',\r\n] as const\r\n\r\nconst installedHooks = Symbol.for('stratagate.dsh-host-resolution.v1')\r\n\r\nfunction isWithin(path: string, root: string): boolean {\r\n const child = relative(root, path)\r\n return child === '' || (!child.startsWith('..') && !isAbsolute(child))\r\n}\r\n\r\nfunction profileDirectory(start: string): string | undefined {\r\n let directory = start\r\n for (;;) {\r\n const manifestPath = join(directory, 'package.json')\r\n if (existsSync(manifestPath)) {\r\n try {\r\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as { dsh?: { profile?: unknown } }\r\n if (manifest.dsh?.profile && typeof manifest.dsh.profile === 'object') return directory\r\n } catch {}\r\n }\r\n const parent = dirname(directory)\r\n if (parent === directory) return undefined\r\n directory = parent\r\n }\r\n}\r\n\r\nfunction hostPackage(specifier: string): boolean {\r\n return HOST_PACKAGES.some((name) => specifier === name || specifier.startsWith(`${name}/`))\r\n}\r\n\r\n/**\r\n * Force only StrataGate's DSH imports through the installation-owned fallback\r\n * created by DSH. The hook neither deletes nor rewrites the profile's package\r\n * tree, and imports belonging to the host or other plugins are untouched.\r\n */\r\nexport function installDshHostResolution(moduleUrl: string): boolean {\r\n const packageDirectory = dirname(dirname(fileURLToPath(moduleUrl)))\r\n const profile = profileDirectory(packageDirectory)\r\n if (!profile) return false\r\n\r\n const globalState = globalThis as typeof globalThis & { [installedHooks]?: Set<string> }\r\n const installed = globalState[installedHooks] ??= new Set<string>()\r\n const key = `${profile}\\u0000${packageDirectory}`\r\n if (installed.has(key)) return true\r\n\r\n const fallbackModules = join(dirname(profile), 'node_modules')\r\n const hostRequire = createRequire(join(fallbackModules, '.stratagate-host-resolution.cjs'))\r\n registerHooks({\r\n resolve(specifier, context, nextResolve) {\r\n const parent = context.parentURL?.startsWith('file:') ? fileURLToPath(context.parentURL) : undefined\r\n if (!hostPackage(specifier) || !parent || !isWithin(parent, packageDirectory)) {\r\n return nextResolve(specifier, context)\r\n }\r\n try {\r\n return { url: pathToFileURL(hostRequire.resolve(specifier)).href, shortCircuit: true }\r\n } catch (cause) {\r\n if (specifier === '@deepseek-ai/dsh-session-format-v0-to-v1'\r\n || specifier === '@deepseek-ai/dsh-session-format-catalog') {\r\n return nextResolve(specifier, context)\r\n }\r\n throw new Error(\r\n `StrataGate cannot resolve host-provided DSH package ${JSON.stringify(specifier)} from ${fallbackModules}. `\r\n + 'Start StrataGate through the DSH profile launcher so the host can prepare its module fallback.',\r\n { cause },\r\n )\r\n }\r\n },\r\n })\r\n installed.add(key)\r\n return true\r\n}\r\n","import { installDshHostResolution } from './dsh-host-resolution.js'\r\n\r\n// DSH prepares its installation-owned module fallback before it imports a\r\n// profile bundle. Install the narrowly-scoped resolver first, then load the\r\n// implementation so stale profile-local peers cannot win ESM resolution.\r\ninstallDshHostResolution(import.meta.url)\r\n\r\n// This file and src/index.ts are separate tsup entries. The runtime path is\r\n// intentionally external so the implementation is instantiated only after\r\n// the resolver above is active.\r\n// @ts-expect-error dist/plugin.js is emitted from src/index.ts during build.\r\nconst plugin = await import('./plugin.js') as typeof import('./index.js')\r\n\r\nexport const name = plugin.name\r\nexport const inject = plugin.inject\r\nexport const STRATAGATE_SETTINGS_NAMESPACE = plugin.STRATAGATE_SETTINGS_NAMESPACE\r\nexport const Config = plugin.Config\r\nexport const apply = plugin.apply\r\nexport type PluginConfig = import('./index.js').PluginConfig\r\n"],"mappings":";AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,eAAe,qBAAqB;AAC7C,SAAS,SAAS,YAAY,MAAM,gBAAgB;AACpD,SAAS,eAAe,qBAAqB;AAE7C,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB,uBAAO,IAAI,mCAAmC;AAErE,SAAS,SAAS,MAAc,MAAuB;AACrD,QAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,SAAO,UAAU,MAAO,CAAC,MAAM,WAAW,IAAI,KAAK,CAAC,WAAW,KAAK;AACtE;AAEA,SAAS,iBAAiB,OAAmC;AAC3D,MAAI,YAAY;AAChB,aAAS;AACP,UAAM,eAAe,KAAK,WAAW,cAAc;AACnD,QAAI,WAAW,YAAY,GAAG;AAC5B,UAAI;AACF,cAAM,WAAW,KAAK,MAAM,aAAa,cAAc,MAAM,CAAC;AAC9D,YAAI,SAAS,KAAK,WAAW,OAAO,SAAS,IAAI,YAAY,SAAU,QAAO;AAAA,MAChF,QAAQ;AAAA,MAAC;AAAA,IACX;AACA,UAAM,SAAS,QAAQ,SAAS;AAChC,QAAI,WAAW,UAAW,QAAO;AACjC,gBAAY;AAAA,EACd;AACF;AAEA,SAAS,YAAY,WAA4B;AAC/C,SAAO,cAAc,KAAK,CAACA,UAAS,cAAcA,SAAQ,UAAU,WAAW,GAAGA,KAAI,GAAG,CAAC;AAC5F;AAOO,SAAS,yBAAyB,WAA4B;AACnE,QAAM,mBAAmB,QAAQ,QAAQ,cAAc,SAAS,CAAC,CAAC;AAClE,QAAM,UAAU,iBAAiB,gBAAgB;AACjD,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,cAAc;AACpB,QAAM,YAAY,YAAY,cAAc,MAAM,oBAAI,IAAY;AAClE,QAAM,MAAM,GAAG,OAAO,KAAS,gBAAgB;AAC/C,MAAI,UAAU,IAAI,GAAG,EAAG,QAAO;AAE/B,QAAM,kBAAkB,KAAK,QAAQ,OAAO,GAAG,cAAc;AAC7D,QAAM,cAAc,cAAc,KAAK,iBAAiB,iCAAiC,CAAC;AAC1F,gBAAc;AAAA,IACZ,QAAQ,WAAW,SAAS,aAAa;AACvC,YAAM,SAAS,QAAQ,WAAW,WAAW,OAAO,IAAI,cAAc,QAAQ,SAAS,IAAI;AAC3F,UAAI,CAAC,YAAY,SAAS,KAAK,CAAC,UAAU,CAAC,SAAS,QAAQ,gBAAgB,GAAG;AAC7E,eAAO,YAAY,WAAW,OAAO;AAAA,MACvC;AACA,UAAI;AACF,eAAO,EAAE,KAAK,cAAc,YAAY,QAAQ,SAAS,CAAC,EAAE,MAAM,cAAc,KAAK;AAAA,MACvF,SAAS,OAAO;AACd,YAAI,cAAc,8CACb,cAAc,2CAA2C;AAC5D,iBAAO,YAAY,WAAW,OAAO;AAAA,QACvC;AACA,cAAM,IAAI;AAAA,UACR,uDAAuD,KAAK,UAAU,SAAS,CAAC,SAAS,eAAe;AAAA,UAExG,EAAE,MAAM;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACD,YAAU,IAAI,GAAG;AACjB,SAAO;AACT;;;ACnFA,yBAAyB,YAAY,GAAG;AAMxC,IAAM,SAAS,MAAM,OAAO,aAAa;AAElC,IAAM,OAAO,OAAO;AACpB,IAAM,SAAS,OAAO;AACtB,IAAM,gCAAgC,OAAO;AAC7C,IAAM,SAAS,OAAO;AACtB,IAAM,QAAQ,OAAO;","names":["name"]}
package/dist/plugin.js CHANGED
@@ -1689,6 +1689,7 @@ var PROFILE_FIELDS = {
1689
1689
  persistentNotes: { label: "Persistent notes", maxLength: 1200 }
1690
1690
  };
1691
1691
  var PROFILE_PROTECTED_SHORT_FIELDS = ["userPreferredName", "assistantPreferredName", "preferredLanguage", "reasoningLanguage", "defaultLocation", "homeCity", "currentCity"];
1692
+ var PROFILE_MAINTAINABLE_FIELDS = Object.keys(PROFILE_FIELDS).filter((field) => !PROFILE_PROTECTED_SHORT_FIELDS.includes(field));
1692
1693
  var PROFILE_TOTAL_MAX_LENGTH = 6e3;
1693
1694
  var PROFILE_MAINTENANCE_INTERVAL_MS = 24 * 60 * 60 * 1e3;
1694
1695
  var PROFILE_MAINTENANCE_TOTAL_THRESHOLD = 4800;
@@ -1714,8 +1715,9 @@ function validateProfile(profile) {
1714
1715
  function profileMaintenanceDue(profile, timeBasisAt, now = Date.now()) {
1715
1716
  const lengths = Object.keys(PROFILE_FIELDS).map((field) => ({ field, length: profileLength(profile[field]) }));
1716
1717
  const total = lengths.reduce((sum, item) => sum + item.length, 0);
1717
- if (total === 0) return false;
1718
- return timeBasisAt !== null && now - Date.parse(timeBasisAt) >= PROFILE_MAINTENANCE_INTERVAL_MS || total >= PROFILE_MAINTENANCE_TOTAL_THRESHOLD || lengths.some(({ field, length }) => length >= PROFILE_FIELDS[field].maxLength * 0.8);
1718
+ const maintainableLengths = lengths.filter(({ field }) => PROFILE_MAINTAINABLE_FIELDS.includes(field));
1719
+ if (!maintainableLengths.some(({ length }) => length > 0)) return false;
1720
+ return timeBasisAt !== null && now - Date.parse(timeBasisAt) >= PROFILE_MAINTENANCE_INTERVAL_MS || total >= PROFILE_MAINTENANCE_TOTAL_THRESHOLD || maintainableLengths.some(({ field, length }) => length >= PROFILE_FIELDS[field].maxLength * 0.8);
1719
1721
  }
1720
1722
  function renderPersistentProfile(profile) {
1721
1723
  const lines = Object.keys(PROFILE_FIELDS).filter((field) => profile[field].length > 0).map((field) => `${PROFILE_FIELDS[field].label}: ${profile[field]}`);
@@ -2304,7 +2306,6 @@ function updateDreaming(state, events, command, now) {
2304
2306
  let run = state.dreaming;
2305
2307
  if (command.kind === "start") {
2306
2308
  if (run && ["running", "pausing", "paused"].includes(run.status)) throw new Error("A Dreaming run already exists; resume or terminate it");
2307
- if (command.tokenLimit !== void 0 && (!Number.isSafeInteger(command.tokenLimit) || command.tokenLimit <= 0)) throw new Error("Invalid token boundary");
2308
2309
  const topics = state.topics.filter((t) => !t.invalidated && t.sourceEventIds.length && t.sourceEventIds.every((id) => sources2.has(id)));
2309
2310
  const units = topics.flatMap((topic2) => {
2310
2311
  const ids2 = topic2.sourceEventIds.filter((id) => sources2.has(id));
@@ -2343,7 +2344,7 @@ function updateDreaming(state, events, command, now) {
2343
2344
  changedBatches: 0,
2344
2345
  readOffsets: {},
2345
2346
  idleCalls: 0,
2346
- tokenLimit: command.tokenLimit ?? null,
2347
+ tokenLimit: null,
2347
2348
  activity: "\u6B63\u5728\u8BFB\u53D6\u76EE\u5F55",
2348
2349
  reason: null,
2349
2350
  createdAt: now,
@@ -2373,11 +2374,8 @@ function updateDreaming(state, events, command, now) {
2373
2374
  if (command.kind === "resume") {
2374
2375
  const expired = !!run.leaseUntil && Date.parse(run.leaseUntil) <= Date.parse(now);
2375
2376
  if (run.status !== "paused" && !(expired && ["running", "pausing"].includes(run.status))) throw new Error("Dreaming is not paused");
2376
- if (command.tokenLimit !== void 0) {
2377
- if (!Number.isSafeInteger(command.tokenLimit) || command.tokenLimit <= run.estimatedTokens) throw new Error("Token boundary must exceed consumed estimate");
2378
- run.tokenLimit = command.tokenLimit;
2379
- }
2380
2377
  if (run.policyVersion !== DREAMING_POLICY_VERSION) throw new Error("Dreaming policy changed; terminate this run and start again");
2378
+ run.tokenLimit = null;
2381
2379
  run.status = "running";
2382
2380
  run.owner = command.owner;
2383
2381
  run.epoch++;
@@ -4283,7 +4281,9 @@ var SqliteStorage = class _SqliteStorage {
4283
4281
  if (failed?.input_json === JSON.stringify(profile) && now < Date.parse(failed.next_retry_at)) return false;
4284
4282
  const state = this.getProfileMaintenanceState();
4285
4283
  if (!profileMaintenanceDue(profile, state?.lastSucceededAt ?? this.getProfileMaintenanceStartedAt(), now)) return false;
4286
- return !state || now - Date.parse(state.lastSucceededAt) >= 24 * 60 * 60 * 1e3 || state.inputJson !== JSON.stringify(profile);
4284
+ if (!state) return true;
4285
+ const maintained = JSON.parse(state.inputJson);
4286
+ return PROFILE_MAINTAINABLE_FIELDS.some((field) => maintained[field] !== profile[field]);
4287
4287
  }
4288
4288
  writeProfileField(field, oldValue, newValue, source, sourceMessageId, now = (/* @__PURE__ */ new Date()).toISOString()) {
4289
4289
  this.database.prepare("INSERT INTO persistent_profile (field, value) VALUES (?, ?) ON CONFLICT (field) DO UPDATE SET value = excluded.value").run(field, newValue);
@@ -10438,9 +10438,7 @@ function dreamingPayload(memory, run) {
10438
10438
  lastWriteFailure: lastWriteFailure ?? null,
10439
10439
  retrievedEvidenceIds: Object.keys(run.evidenceVersions).slice(-100),
10440
10440
  totalRetrievedEvidence: Object.keys(run.evidenceVersions).length,
10441
- recentTools,
10442
- estimatedTokensConsumed: run.estimatedTokens,
10443
- tokenBoundary: run.tokenLimit
10441
+ recentTools
10444
10442
  };
10445
10443
  }
10446
10444
  function dreamingEstimatedTokens(payload, action) {
@@ -10449,19 +10447,19 @@ function dreamingEstimatedTokens(payload, action) {
10449
10447
  function dreamingStatus(run) {
10450
10448
  if (!run) return null;
10451
10449
  const interrupted = ["running", "pausing"].includes(run.status) && !!run.leaseUntil && Date.parse(run.leaseUntil) <= Date.now();
10450
+ const legacyBoundary = run.status === "paused" && run.tokenLimit != null && /消耗边界/.test(run.reason ?? "");
10452
10451
  return {
10453
10452
  id: run.id,
10454
10453
  sessionId: run.sessionId ?? null,
10455
10454
  status: interrupted ? "paused" : run.status,
10456
10455
  scope: run.scope,
10457
10456
  activity: interrupted ? "\u5DF2\u6682\u505C" : run.activity,
10458
- reason: interrupted ? "\u4E0A\u6B21\u8FD0\u884C\u5DF2\u4E2D\u65AD\uFF0C\u53EF\u4EE5\u7EE7\u7EED" : run.reason,
10457
+ reason: interrupted ? "\u4E0A\u6B21\u8FD0\u884C\u5DF2\u4E2D\u65AD\uFF0C\u53EF\u4EE5\u7EE7\u7EED" : legacyBoundary ? "\u4E0A\u6B21\u6574\u7406\u5DF2\u6682\u505C\uFF0C\u53EF\u4EE5\u7EE7\u7EED\uFF1B\u5DF2\u5B8C\u6210\u7684\u4FEE\u6539\u5DF2\u4FDD\u5B58\u3002" : run.reason,
10459
10458
  completed: run.cursor,
10460
10459
  total: run.units.length,
10461
10460
  changedBatches: run.changedBatches,
10462
10461
  calls: run.calls,
10463
10462
  estimatedTokens: run.estimatedTokens,
10464
- tokenLimit: run.tokenLimit,
10465
10463
  updatedAt: run.updatedAt
10466
10464
  };
10467
10465
  }
@@ -11883,14 +11881,14 @@ var StrataGateRuntime = class {
11883
11881
  const run = await this.dreamingRun(namespace, id);
11884
11882
  return { sessionId: await this.dreamingHost.open(namespace, run) };
11885
11883
  }
11886
- async adminDreamingControl(namespace, action, id, tokenLimit) {
11884
+ async adminDreamingControl(namespace, action, id) {
11887
11885
  if (this.closed) throw new Error("Runtime is closed");
11888
11886
  if ((action === "start" || action === "resume") && [...this.dreamingRuns.keys()].some((key) => key !== namespace)) {
11889
11887
  throw new Error("\u53E6\u4E00\u4E2A\u8BB0\u5FC6\u7A7A\u95F4\u6B63\u5728 Dreaming\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210\u6216\u5148\u6682\u505C\u5B83");
11890
11888
  }
11891
11889
  let command;
11892
- if (action === "start") command = { kind: "start", owner: this.dreamingOwner, ...tokenLimit !== void 0 ? { tokenLimit } : {} };
11893
- else if (action === "resume" && id) command = { kind: "resume", id, owner: this.dreamingOwner, ...tokenLimit !== void 0 ? { tokenLimit } : {} };
11890
+ if (action === "start") command = { kind: "start", owner: this.dreamingOwner };
11891
+ else if (action === "resume" && id) command = { kind: "resume", id, owner: this.dreamingOwner };
11894
11892
  else if ((action === "pause" || action === "terminate") && id) command = { kind: action, id };
11895
11893
  else throw new Error("Invalid Dreaming control");
11896
11894
  const run = await this.retryExternalImportWrite(namespace, (memory) => memory.dreaming(command.kind === "start" && this.agentMemoryRetrievalWeight <= 0 ? { ...command, allowedEventIds: memory.listEvents().filter((event) => event.status !== "forgotten" && event.status !== "archived").map((event) => event.id) } : command));
@@ -11936,10 +11934,6 @@ var StrataGateRuntime = class {
11936
11934
  } finally {
11937
11935
  if (owned) await memory.close();
11938
11936
  }
11939
- if (run.tokenLimit !== null && run.estimatedTokens + estimateTokens(JSON.stringify(payload)) + 256 > run.tokenLimit) {
11940
- await mutate({ kind: "suspend", ...claim, reason: "\u5DF2\u8FBE\u5230\u672C\u8F6E token \u6D88\u8017\u8FB9\u754C\uFF0C\u8FDB\u5EA6\u5DF2\u4FDD\u5B58\uFF1B\u63D0\u9AD8\u8FB9\u754C\u540E\u53EF\u4EE5\u7EE7\u7EED\uFF08\u6D88\u8017\u4E3A\u4F30\u7B97\uFF09" });
11941
- return;
11942
- }
11943
11937
  const action = await this.models.runDetached(`dreaming:${run.id}`, () => this.models.dreamingStep(payload), controller.signal);
11944
11938
  if (controller.signal.aborted) return;
11945
11939
  const repeated = run.trace.filter((entry) => entry.tool === action.tool && JSON.stringify(entry.args) === JSON.stringify(action.args)).length;
@@ -13397,19 +13391,7 @@ ${profile}
13397
13391
  });
13398
13392
  scoped.on("agent/request", async (_payload, next) => {
13399
13393
  const config = await next();
13400
- const run = await this.runtime.dreamingRun(binding.namespace, binding.id);
13401
- const input = estimateTokens(JSON.stringify({ messages: [
13402
- ...binding.agent.session.deriveMessages(),
13403
- ...binding.pendingMessages ?? [],
13404
- { role: "system", content: [{ type: "text", text: this.systemPrompt() }] }
13405
- ], tools: modelTools })) + 1024;
13406
- if (run.tokenLimit !== null && run.estimatedTokens + input + 256 > run.tokenLimit) {
13407
- this.keepDirections(binding, binding.pendingMessages ?? []);
13408
- if (run.status !== "completed") await this.runtime.dreamingMutate(binding.namespace, run, { kind: "suspend", reason: "\u5DF2\u8FBE\u5230\u672C\u8F6E\u6D88\u8017\u8FB9\u754C\uFF0C\u8FDB\u5EA6\u5DF2\u4FDD\u5B58\uFF1B\u63D0\u9AD8\u8FB9\u754C\u540E\u53EF\u4EE5\u7EE7\u7EED\uFF08\u6D88\u8017\u4E3A\u4F30\u7B97\uFF09" });
13409
- throw new Error("Dreaming consumption boundary reached");
13410
- }
13411
- const remaining = run.tokenLimit === null ? RESPONSE_TOKEN_LIMIT : run.tokenLimit - run.estimatedTokens - input;
13412
- return { ...config, maxTokens: Math.min(RESPONSE_TOKEN_LIMIT, remaining) };
13394
+ return { ...config, maxTokens: RESPONSE_TOKEN_LIMIT };
13413
13395
  });
13414
13396
  const runtime = this.runtime;
13415
13397
  scoped.on("llm/stream", async function* (options, next) {
@@ -13420,10 +13402,6 @@ ${profile}
13420
13402
  await binding.accounting;
13421
13403
  const run = await runtime.dreamingRun(binding.namespace, binding.id);
13422
13404
  const input = estimateTokens(JSON.stringify({ messages: options.messages, tools: options.tools ?? [] }));
13423
- if (run.tokenLimit !== null && run.estimatedTokens + input + (options.maxTokens ?? 32768) > run.tokenLimit) {
13424
- if (run.status !== "completed") await runtime.dreamingMutate(binding.namespace, run, { kind: "suspend", reason: "\u5B9E\u9645\u6A21\u578B\u8BF7\u6C42\u8FBE\u5230\u672C\u8F6E\u6D88\u8017\u8FB9\u754C\uFF0C\u8FDB\u5EA6\u5DF2\u4FDD\u5B58\uFF08\u6D88\u8017\u4E3A\u4F30\u7B97\uFF09" });
13425
- throw new Error("Dreaming consumption boundary reached before model dispatch");
13426
- }
13427
13405
  const saved = await runtime.dreamingMutate(binding.namespace, run, { kind: "model-step", estimatedTokens: input });
13428
13406
  if (saved.status !== "running" && saved.status !== "completed") throw new Error("Dreaming paused at safe boundary");
13429
13407
  binding.pendingMessages = [];
@@ -15352,10 +15330,8 @@ async function handleAdminRequest(runtime, req, res) {
15352
15330
  sendJson(res, 200, await runtime.adminDreamingSession(namespace, id));
15353
15331
  return;
15354
15332
  }
15355
- const rawLimit = url.searchParams.get("tokenLimit");
15356
- const tokenLimit = rawLimit === null || rawLimit === "" ? void 0 : Number(rawLimit);
15357
- if (!["start", "pause", "resume", "terminate"].includes(action) || action !== "start" && !id || tokenLimit !== void 0 && (!Number.isSafeInteger(tokenLimit) || tokenLimit <= 0)) throw new AdminHttpError(400, "Invalid Dreaming control");
15358
- sendJson(res, 200, await runtime.adminDreamingControl(namespace, action, id, tokenLimit));
15333
+ if (!["start", "pause", "resume", "terminate"].includes(action) || action !== "start" && !id) throw new AdminHttpError(400, "Invalid Dreaming control");
15334
+ sendJson(res, 200, await runtime.adminDreamingControl(namespace, action, id));
15359
15335
  } else throw new AdminHttpError(405, "Dreaming requires GET or POST");
15360
15336
  } else if (path === "/api/stratagate/import") {
15361
15337
  if (req.method === "GET") {