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/CHANGELOG.md +665 -656
- package/LICENSE +21 -21
- package/dist/client.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +18 -42
- package/dist/plugin.js.map +1 -1
- package/docs/DSH.md +268 -268
- package/docs/DSH.zh-CN.md +245 -245
- package/docs/benchmarks/issue-128-windows-review.json +104 -104
- package/docs/benchmarks/issue-128-windows.json +103 -103
- package/docs/dreaming-agent.md +45 -45
- package/docs/issue-128-lease-cache-review-followup.md +55 -55
- package/docs/issue-128-review-followup.md +58 -58
- package/docs/npm-release.md +52 -0
- package/docs/validation/issue119.md +41 -41
- package/package.json +246 -246
- package/screenshots.json +8 -8
- package/docs/validation/first-login-graph-warning-20261013/render-comparison.json +0 -58
- package/docs/validation/first-login-graph-warning-20261013/tests.after.json +0 -1
- package/docs/validation/issue119-after.json +0 -30
- package/docs/validation/issue119-before.json +0 -94
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
|
-
|
|
1718
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
|
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
|
|
11893
|
-
else if (action === "resume" && id) command = { kind: "resume", id, owner: this.dreamingOwner
|
|
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
|
-
|
|
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
|
-
|
|
15356
|
-
|
|
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") {
|