stratagate-dsh 0.2.83 → 0.2.86
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 +16 -0
- package/README.md +4 -1
- package/README.zh-CN.md +6 -1
- package/dist/client.js +3 -3
- package/dist/index.d.ts +35 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +35 -1
- package/dist/plugin.js +368 -169
- package/dist/plugin.js.map +1 -1
- package/dist/repair-profile.js +1 -0
- package/dist/repair-profile.js.map +1 -1
- package/docs/DSH.md +4 -2
- package/docs/DSH.zh-CN.md +4 -2
- package/docs/assets/short-term-memory-explainer-en.gif +0 -0
- package/docs/assets/short-term-memory-explainer-zh.gif +0 -0
- package/package.json +31 -30
package/dist/plugin.js
CHANGED
|
@@ -11,6 +11,9 @@ var StructuredReasoningEffortSettings = z.object({
|
|
|
11
11
|
showShortTermStatus: z.boolean().default(true).description("\u663E\u793A\u77ED\u671F\u8BB0\u5FC6\u5757\u72B6\u6001").comment("\u63A7\u5236\u77ED\u671F\u8BB0\u5FC6\u5757\u8FDB\u5EA6\u3001Block \u5C01\u5B58\u4E0E\u6574\u7406\u72B6\u6001\u7684\u804A\u5929\u5185\u63D0\u793A\uFF1B\u540E\u53F0\u5904\u7406\u4E0D\u53D7\u5F71\u54CD\u3002"),
|
|
12
12
|
showRetrievalStatus: z.boolean().default(true).description("\u663E\u793A\u8BB0\u5FC6\u68C0\u7D22\u72B6\u6001").comment("\u63A7\u5236\u68C0\u7D22\u6B21\u6570\u3001\u8FD4\u56DE\u6570\u91CF\u548C\u8BB0\u5FC6\u91C7\u7528\u4FE1\u606F\u7684\u804A\u5929\u5185\u63D0\u793A\uFF1B\u68C0\u7D22\u4E0E\u91C7\u7528\u4E0D\u53D7\u5F71\u54CD\u3002")
|
|
13
13
|
});
|
|
14
|
+
function volatileIfSupported(schema) {
|
|
15
|
+
return schema.volatile?.() ?? schema;
|
|
16
|
+
}
|
|
14
17
|
var Config = z.object({
|
|
15
18
|
database: z.string().required(),
|
|
16
19
|
sessionRoot: z.string(),
|
|
@@ -24,11 +27,17 @@ var Config = z.object({
|
|
|
24
27
|
model: z.string(),
|
|
25
28
|
maxOutputTokens: z.natural().min(256).default(2048),
|
|
26
29
|
structuredTaskTimeoutMs: z.natural().min(1e3).default(12e4),
|
|
27
|
-
structuredReasoningEffort: z.union(["auto", "force-off"]).default("auto"),
|
|
28
|
-
showStrataGateStatus: z.boolean().default(true),
|
|
29
|
-
showShortTermStatus: z.boolean().default(true),
|
|
30
|
-
showRetrievalStatus: z.boolean().default(true)
|
|
30
|
+
structuredReasoningEffort: volatileIfSupported(z.union(["auto", "force-off"]).default("auto")),
|
|
31
|
+
showStrataGateStatus: volatileIfSupported(z.boolean().default(true)),
|
|
32
|
+
showShortTermStatus: volatileIfSupported(z.boolean().default(true)),
|
|
33
|
+
showRetrievalStatus: volatileIfSupported(z.boolean().default(true))
|
|
31
34
|
});
|
|
35
|
+
function liveConfigValue(value) {
|
|
36
|
+
return value && typeof value === "object" && "get" in value && typeof value.get === "function" ? value.get() : value;
|
|
37
|
+
}
|
|
38
|
+
function isLiveConfigValue(value) {
|
|
39
|
+
return value !== null && typeof value === "object" && "get" in value && typeof value.get === "function";
|
|
40
|
+
}
|
|
32
41
|
function resolveConfig(config) {
|
|
33
42
|
const database = config.database?.trim() ?? "";
|
|
34
43
|
const sessionRoot = config.sessionRoot?.trim();
|
|
@@ -52,10 +61,10 @@ function resolveConfig(config) {
|
|
|
52
61
|
...provider && model ? { provider, model } : {},
|
|
53
62
|
maxOutputTokens: Math.max(256, Math.floor(config.maxOutputTokens ?? 2048)),
|
|
54
63
|
structuredTaskTimeoutMs: Math.max(1e3, Math.floor(config.structuredTaskTimeoutMs ?? 12e4)),
|
|
55
|
-
structuredReasoningEffort: config.structuredReasoningEffort ?? "auto",
|
|
56
|
-
showStrataGateStatus: config.showStrataGateStatus ?? true,
|
|
57
|
-
showShortTermStatus: config.showShortTermStatus ?? true,
|
|
58
|
-
showRetrievalStatus: config.showRetrievalStatus ?? true
|
|
64
|
+
structuredReasoningEffort: liveConfigValue(config.structuredReasoningEffort) ?? "auto",
|
|
65
|
+
showStrataGateStatus: liveConfigValue(config.showStrataGateStatus) ?? true,
|
|
66
|
+
showShortTermStatus: liveConfigValue(config.showShortTermStatus) ?? true,
|
|
67
|
+
showRetrievalStatus: liveConfigValue(config.showRetrievalStatus) ?? true
|
|
59
68
|
};
|
|
60
69
|
}
|
|
61
70
|
|
|
@@ -5573,6 +5582,125 @@ var StrataGate = class _StrataGate {
|
|
|
5573
5582
|
}
|
|
5574
5583
|
};
|
|
5575
5584
|
|
|
5585
|
+
// src/dsh-compatibility.ts
|
|
5586
|
+
import { readFileSync } from "node:fs";
|
|
5587
|
+
import { createRequire } from "node:module";
|
|
5588
|
+
var nodeRequire = createRequire(import.meta.url);
|
|
5589
|
+
var RUNTIME_PACKAGES = [
|
|
5590
|
+
"@deepseek-ai/cordis",
|
|
5591
|
+
"@deepseek-ai/dsh-agent-default-model",
|
|
5592
|
+
"@deepseek-ai/dsh-client-ui-conversation",
|
|
5593
|
+
"@deepseek-ai/dsh-llm",
|
|
5594
|
+
"@deepseek-ai/dsh-native-command",
|
|
5595
|
+
"@deepseek-ai/dsh-session",
|
|
5596
|
+
"@deepseek-ai/dsh-settings",
|
|
5597
|
+
"@deepseek-ai/dsh-system-prompt",
|
|
5598
|
+
"@deepseek-ai/dsh-tools",
|
|
5599
|
+
"@deepseek-ai/schemastery"
|
|
5600
|
+
];
|
|
5601
|
+
var SUPPORTED_RUNTIME_FAMILIES = [
|
|
5602
|
+
{
|
|
5603
|
+
cli: "0.1.2-rc.1",
|
|
5604
|
+
versions: {
|
|
5605
|
+
"@deepseek-ai/cordis": "4.0.2",
|
|
5606
|
+
"@deepseek-ai/dsh-agent-default-model": "0.1.2-rc.1",
|
|
5607
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1",
|
|
5608
|
+
"@deepseek-ai/dsh-llm": "0.1.2-rc.1",
|
|
5609
|
+
"@deepseek-ai/dsh-native-command": "0.1.2-rc.1",
|
|
5610
|
+
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
5611
|
+
"@deepseek-ai/dsh-settings": "0.1.2-rc.1",
|
|
5612
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
|
|
5613
|
+
"@deepseek-ai/dsh-tools": "0.1.2-rc.1",
|
|
5614
|
+
"@deepseek-ai/schemastery": "3.18.2"
|
|
5615
|
+
}
|
|
5616
|
+
},
|
|
5617
|
+
{
|
|
5618
|
+
cli: "0.1.5-rc.1",
|
|
5619
|
+
versions: {
|
|
5620
|
+
"@deepseek-ai/cordis": "4.0.2",
|
|
5621
|
+
"@deepseek-ai/dsh-agent-default-model": "0.1.5-rc.2",
|
|
5622
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
|
|
5623
|
+
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
5624
|
+
"@deepseek-ai/dsh-native-command": "0.1.5-rc.2",
|
|
5625
|
+
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
5626
|
+
"@deepseek-ai/dsh-settings": "0.1.5-rc.2",
|
|
5627
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
|
|
5628
|
+
"@deepseek-ai/dsh-tools": "0.1.5-rc.2",
|
|
5629
|
+
"@deepseek-ai/schemastery": "3.18.2"
|
|
5630
|
+
}
|
|
5631
|
+
},
|
|
5632
|
+
{
|
|
5633
|
+
cli: "0.1.6-alpha.1",
|
|
5634
|
+
versions: {
|
|
5635
|
+
"@deepseek-ai/cordis": "4.0.2",
|
|
5636
|
+
"@deepseek-ai/dsh-agent-default-model": "0.1.6-alpha.1",
|
|
5637
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.6-alpha.1",
|
|
5638
|
+
"@deepseek-ai/dsh-llm": "0.1.6-alpha.1",
|
|
5639
|
+
"@deepseek-ai/dsh-native-command": "0.1.6-alpha.1",
|
|
5640
|
+
"@deepseek-ai/dsh-session": "0.1.6-alpha.1",
|
|
5641
|
+
"@deepseek-ai/dsh-settings": "0.1.6-alpha.1",
|
|
5642
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.6-alpha.1",
|
|
5643
|
+
"@deepseek-ai/dsh-tools": "0.1.6-alpha.1",
|
|
5644
|
+
"@deepseek-ai/schemastery": "3.18.2"
|
|
5645
|
+
}
|
|
5646
|
+
},
|
|
5647
|
+
{
|
|
5648
|
+
cli: "0.1.7-rc.1",
|
|
5649
|
+
versions: {
|
|
5650
|
+
"@deepseek-ai/cordis": "4.0.4",
|
|
5651
|
+
"@deepseek-ai/dsh-agent-default-model": "0.1.7-rc.1",
|
|
5652
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.1",
|
|
5653
|
+
"@deepseek-ai/dsh-llm": "0.1.7-rc.1",
|
|
5654
|
+
"@deepseek-ai/dsh-native-command": "0.1.7-rc.1",
|
|
5655
|
+
"@deepseek-ai/dsh-session": "0.1.7-rc.1",
|
|
5656
|
+
"@deepseek-ai/dsh-settings": "0.1.7-rc.1",
|
|
5657
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.7-rc.1",
|
|
5658
|
+
"@deepseek-ai/dsh-tools": "0.1.7-rc.1",
|
|
5659
|
+
"@deepseek-ai/schemastery": "3.18.4"
|
|
5660
|
+
}
|
|
5661
|
+
}
|
|
5662
|
+
];
|
|
5663
|
+
var STRATAGATE_MESSAGE_SOURCE_KIND = "plugin:stratagate-memory";
|
|
5664
|
+
function buildDshMessageSource(version, form) {
|
|
5665
|
+
const source = version === "0.1.7-rc.1" ? { kind: STRATAGATE_MESSAGE_SOURCE_KIND } : { kind: "plugin", plugin: "stratagate-memory" };
|
|
5666
|
+
return form ? { ...source, form } : source;
|
|
5667
|
+
}
|
|
5668
|
+
function installedVersion(packageName) {
|
|
5669
|
+
try {
|
|
5670
|
+
const manifestPath = nodeRequire.resolve(`${packageName}/package.json`);
|
|
5671
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
5672
|
+
if (typeof manifest.version === "string" && manifest.version.length > 0) return manifest.version;
|
|
5673
|
+
} catch {
|
|
5674
|
+
}
|
|
5675
|
+
return "<missing>";
|
|
5676
|
+
}
|
|
5677
|
+
function buildDshReplaceSurfaceOp(version, start, end) {
|
|
5678
|
+
return version === "0.1.2-rc.1" ? { op: "replace", start, end } : { op: "replace", startSeq: start, endSeq: end };
|
|
5679
|
+
}
|
|
5680
|
+
function dshReplaceSurfaceOp(start, end) {
|
|
5681
|
+
return buildDshReplaceSurfaceOp(installedVersion("@deepseek-ai/dsh-session"), start, end);
|
|
5682
|
+
}
|
|
5683
|
+
function dshMessageSource(form) {
|
|
5684
|
+
return buildDshMessageSource(installedVersion("@deepseek-ai/dsh-session"), form);
|
|
5685
|
+
}
|
|
5686
|
+
function isStrataGateMessageSource(source) {
|
|
5687
|
+
if (!source || typeof source !== "object") return false;
|
|
5688
|
+
const value = source;
|
|
5689
|
+
return value.kind === STRATAGATE_MESSAGE_SOURCE_KIND || value.kind === "plugin" && value.plugin === "stratagate-memory";
|
|
5690
|
+
}
|
|
5691
|
+
function classifyDshRuntime(packageVersions) {
|
|
5692
|
+
const family = SUPPORTED_RUNTIME_FAMILIES.find(({ versions }) => RUNTIME_PACKAGES.every((name2) => packageVersions[name2] === versions[name2]));
|
|
5693
|
+
if (family) return { cliVersion: family.cli, packageVersions };
|
|
5694
|
+
const found = RUNTIME_PACKAGES.map((name2) => `${name2}@${packageVersions[name2]}`).join(", ");
|
|
5695
|
+
throw new Error(
|
|
5696
|
+
`StrataGate cannot start because this DSH profile resolves an unsupported or mixed core runtime. Resolved: ${found}. Supported tested hosts are @deepseek-ai/dsh@0.1.2-rc.1 (internal DSH packages 0.1.2-rc.1) and @deepseek-ai/dsh@0.1.5-rc.1 (its real dependency tree uses internal DSH packages 0.1.5-rc.2), and @deepseek-ai/dsh@0.1.6-alpha.1 (internal DSH packages 0.1.6-alpha.1), and @deepseek-ai/dsh@0.1.7-rc.1 (internal DSH packages 0.1.7-rc.1). Reinstall or update stratagate-dsh through \`dsh plugin --profile <name> add <package>\` so the host supplies its peers.`
|
|
5697
|
+
);
|
|
5698
|
+
}
|
|
5699
|
+
function assertCompatibleDshRuntime() {
|
|
5700
|
+
const packageVersions = Object.fromEntries(RUNTIME_PACKAGES.map((name2) => [name2, installedVersion(name2)]));
|
|
5701
|
+
return classifyDshRuntime(packageVersions);
|
|
5702
|
+
}
|
|
5703
|
+
|
|
5576
5704
|
// src/json-response.ts
|
|
5577
5705
|
var RESPONSE_PREVIEW_LIMIT = 500;
|
|
5578
5706
|
function truncateResponsePreview(value) {
|
|
@@ -5755,12 +5883,26 @@ var STRUCTURED_FIELDS = {
|
|
|
5755
5883
|
var STRING_ARRAY = { type: "array", items: { type: "string" } };
|
|
5756
5884
|
var OPEN_OBJECT = { type: "object", additionalProperties: true };
|
|
5757
5885
|
var SUMMARIZER_PARAMETERS = {
|
|
5758
|
-
l0Title: { type: "string", required: true },
|
|
5759
|
-
l0Tags: { ...STRING_ARRAY, required: true },
|
|
5760
|
-
l1Summary: { type: "string", required: true },
|
|
5761
|
-
l2Keypoints: { ...STRING_ARRAY, required: true },
|
|
5762
|
-
shouldExtract: { type: "boolean", required: true }
|
|
5886
|
+
l0Title: { type: "string", description: "L0: a short phrase naming the Block's central subject for quick recognition; do not turn it into a sentence-length summary.", required: true },
|
|
5887
|
+
l0Tags: { ...STRING_ARRAY, description: "L0: a few distinctive topical labels (usually 2-5) for rapid recognition of the Block, such as named people, projects, organizations, tools, technical topics, or specific task concepts; omit generic labels such as discussion, conversation, problem, or task.", required: true },
|
|
5888
|
+
l1Summary: { type: "string", description: "L1: a compact, self-contained overview of what happened across the Block, its conclusions or results, significant state changes, and key unresolved work; richer than L0 but still quick to read.", required: true },
|
|
5889
|
+
l2Keypoints: { ...STRING_ARRAY, description: "L2: specific, self-contained points needed to recover context later. Make each point mostly atomic: one decision, constraint, preference, fact, result, failure reason, or open item. Add detail beyond L1 without splitting or repeating its sentences.", required: true },
|
|
5890
|
+
shouldExtract: { type: "boolean", description: "High-recall pre-screen for Event extraction, not the final Event decision. True when this Block clearly contains or may reasonably contain a long-term Event; when uncertain, use true so the Event Extractor can decide. False only when it clearly lacks lasting value, such as greetings, repeated confirmations, or disposable process noise. Mere presence of a fact is not sufficient.", required: true }
|
|
5763
5891
|
};
|
|
5892
|
+
var SUMMARIZER_SYSTEM_PROMPT = `You are the Block Summarizer in StrataGate's memory pipeline. Compress one sealed conversation Block, typically about six turns, from the supplied provenance-preserving derivation messages into L0-L2 layered memory and decide whether it warrants later Event extraction. You are a background model, not the main Agent; you have no other conversation context. L5 retains the complete original source, while L3/L4 are produced separately. Your L0-L2 may later replace detailed chat in the Agent's context, so preserve what future work needs without inventing missing context.
|
|
5893
|
+
|
|
5894
|
+
L0 -> L1 -> L2 are progressively higher-resolution views of the same history, not three independent or repetitive summaries:
|
|
5895
|
+
- L0: l0Title is a short subject phrase for rapid recognition, ideally under about 60 characters; l0Tags are a few distinctive topical labels for rapid recognition, usually 2-5. Prefer named people, projects, organizations, tools, technical topics, and specific task concepts. Avoid generic tags such as discussion, conversation, problem, or task.
|
|
5896
|
+
- L1: l1Summary is a compact, self-contained overview of the whole Block: what happened, conclusions or results, meaningful state changes, and key unresolved work. Usually 1-3 sentences; do not retell the conversation turn by turn.
|
|
5897
|
+
- L2: l2Keypoints retain concrete details needed to resume work. Usually 3-8 concise points when there is enough substance, fewer for a thin Block. Each point should stand alone and express mainly one decision, constraint, preference, fact, result, significant failure reason, or open item. Be more specific than L1; do not merely split L1 into repeated sentences.
|
|
5898
|
+
|
|
5899
|
+
Prioritize important decisions, constraints, user preferences, final outcomes, significant failure causes, and unresolved work; then task-relevant process details. Omit repetition, greetings, and disposable execution noise. Do not discard a constraint or conclusion that would change how later work is understood just to shorten the output.
|
|
5900
|
+
|
|
5901
|
+
Keep provenance and uncertainty. Distinguish what the user stated or decided, what the assistant only proposed or suspected, and what a tool actually observed. Do not promote an assistant hypothesis or a recollection of older memory into a verified fact or new outcome. Preserve uncertainty about timing, causes, status, results, and relationships. Ordinary user/assistant text is retained, but large tool arguments or results may be compacted; use only retained tool names, evidence summaries, and excerpts, and never guess omitted payload details.
|
|
5902
|
+
|
|
5903
|
+
shouldExtract is a high-recall pre-screen, not the final Event decision. If it is false, Event extraction is skipped entirely; if true, the Event Extractor makes the final evidence-based decision. Set true when this Block clearly contains or may reasonably contain a long-term Event, such as a decision, stable preference, material project change, meaningful task result, important failure and possible cause, future-useful fact, or open item worth tracking. When uncertain whether a plausible candidate has lasting value, choose true and let the Event Extractor decide. Set false only when the Block clearly lacks such value, for example greetings, repeated confirmations, or disposable execution noise. Do not set true merely because some fact appears; an unsupported assistant suggestion or recap of older memory alone does not establish a new Event candidate.
|
|
5904
|
+
|
|
5905
|
+
Call stratagate_summarize_block exactly once with l0Title, l0Tags, l1Summary, l2Keypoints, and shouldExtract. Do not return the summary as ordinary text.`;
|
|
5764
5906
|
var EVENT_ITEM = {
|
|
5765
5907
|
type: "object",
|
|
5766
5908
|
additionalProperties: false,
|
|
@@ -5890,7 +6032,7 @@ var PROFILE_MAINTENANCE_PARAMETERS = Object.fromEntries(
|
|
|
5890
6032
|
var STRUCTURED_TOOLS = {
|
|
5891
6033
|
summarizer: {
|
|
5892
6034
|
name: "stratagate_summarize_block",
|
|
5893
|
-
description: "Submit the
|
|
6035
|
+
description: "Submit the L0-L2 layered compression of one sealed StrataGate conversation Block and decide whether it should proceed to Event extraction.",
|
|
5894
6036
|
parameters: SUMMARIZER_PARAMETERS
|
|
5895
6037
|
},
|
|
5896
6038
|
extractor: {
|
|
@@ -5980,9 +6122,10 @@ function compactGraphProjectionContext(context) {
|
|
|
5980
6122
|
};
|
|
5981
6123
|
}
|
|
5982
6124
|
var DshModelBridge = class {
|
|
5983
|
-
constructor(ctx, config) {
|
|
6125
|
+
constructor(ctx, config, liveStructuredReasoningEffort) {
|
|
5984
6126
|
this.ctx = ctx;
|
|
5985
6127
|
this.config = config;
|
|
6128
|
+
this.liveStructuredReasoningEffort = liveStructuredReasoningEffort;
|
|
5986
6129
|
this.structuredReasoningEffort = config.structuredReasoningEffort ?? "auto";
|
|
5987
6130
|
this.ctx.on?.("llm/adapters-updated", () => {
|
|
5988
6131
|
this.offCapabilities.clear();
|
|
@@ -5991,6 +6134,7 @@ var DshModelBridge = class {
|
|
|
5991
6134
|
}
|
|
5992
6135
|
ctx;
|
|
5993
6136
|
config;
|
|
6137
|
+
liveStructuredReasoningEffort;
|
|
5994
6138
|
sessions = new AsyncLocalStorage();
|
|
5995
6139
|
successfulResponses = [];
|
|
5996
6140
|
offCapabilities = /* @__PURE__ */ new Map();
|
|
@@ -6016,6 +6160,9 @@ var DshModelBridge = class {
|
|
|
6016
6160
|
setStructuredReasoningEffort(mode) {
|
|
6017
6161
|
this.structuredReasoningEffort = mode;
|
|
6018
6162
|
}
|
|
6163
|
+
currentStructuredReasoningEffort() {
|
|
6164
|
+
return this.liveStructuredReasoningEffort?.() ?? this.structuredReasoningEffort;
|
|
6165
|
+
}
|
|
6019
6166
|
run(session, operation) {
|
|
6020
6167
|
return this.sessions.run({ session, sessionId: session.id }, operation);
|
|
6021
6168
|
}
|
|
@@ -6029,7 +6176,7 @@ var DshModelBridge = class {
|
|
|
6029
6176
|
summarizer = async (messages) => {
|
|
6030
6177
|
const raw = object(await this.callStructured(
|
|
6031
6178
|
"summarizer",
|
|
6032
|
-
|
|
6179
|
+
SUMMARIZER_SYSTEM_PROMPT,
|
|
6033
6180
|
{ messages: buildMemoryDerivationMessages(messages) }
|
|
6034
6181
|
));
|
|
6035
6182
|
return {
|
|
@@ -6244,7 +6391,7 @@ var DshModelBridge = class {
|
|
|
6244
6391
|
attemptsUsed = attempt;
|
|
6245
6392
|
const message = createUserMessage({
|
|
6246
6393
|
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
6247
|
-
source:
|
|
6394
|
+
source: dshMessageSource()
|
|
6248
6395
|
});
|
|
6249
6396
|
const assembler = new BlockAssembler();
|
|
6250
6397
|
const request = {
|
|
@@ -6378,14 +6525,14 @@ ${JSON_RETRY_INSTRUCTION}`,
|
|
|
6378
6525
|
const key = `${route.provider}\0${route.model}`;
|
|
6379
6526
|
const cached = this.offCapabilities.get(key);
|
|
6380
6527
|
if (cached) {
|
|
6381
|
-
if (cached === "unsupported" && this.
|
|
6528
|
+
if (cached === "unsupported" && this.currentStructuredReasoningEffort() === "force-off") {
|
|
6382
6529
|
this.warnOffFallbackOnce(key, `${route.provider}/${route.model} does not support reasoningEffort=off; using the model default`);
|
|
6383
6530
|
}
|
|
6384
6531
|
return cached === "supported";
|
|
6385
6532
|
}
|
|
6386
6533
|
if (typeof this.ctx.llm.resolveModelInfo !== "function") {
|
|
6387
6534
|
this.offCapabilities.set(key, "unsupported");
|
|
6388
|
-
if (this.
|
|
6535
|
+
if (this.currentStructuredReasoningEffort() === "force-off") {
|
|
6389
6536
|
this.warnOffFallbackOnce(key, `${route.provider}/${route.model} capabilities are unavailable; using the model default`);
|
|
6390
6537
|
}
|
|
6391
6538
|
return false;
|
|
@@ -6404,16 +6551,16 @@ ${JSON_RETRY_INSTRUCTION}`,
|
|
|
6404
6551
|
timer.unref?.();
|
|
6405
6552
|
})
|
|
6406
6553
|
]);
|
|
6407
|
-
if (!info.reasoning) return this.
|
|
6554
|
+
if (!info.reasoning) return this.currentStructuredReasoningEffort() === "force-off";
|
|
6408
6555
|
const supported = info.reasoning.efforts.some(({ id }) => String(id) === "off");
|
|
6409
6556
|
this.offCapabilities.set(key, supported ? "supported" : "unsupported");
|
|
6410
|
-
if (!supported && this.
|
|
6557
|
+
if (!supported && this.currentStructuredReasoningEffort() === "force-off") {
|
|
6411
6558
|
this.warnOffFallbackOnce(key, `${route.provider}/${route.model} does not support reasoningEffort=off; using the model default`);
|
|
6412
6559
|
}
|
|
6413
6560
|
return supported;
|
|
6414
6561
|
} catch {
|
|
6415
6562
|
this.offCapabilities.set(key, "unsupported");
|
|
6416
|
-
if (this.
|
|
6563
|
+
if (this.currentStructuredReasoningEffort() === "force-off") {
|
|
6417
6564
|
this.warnOffFallbackOnce(key, `${route.provider}/${route.model} capability lookup failed; using the model default`);
|
|
6418
6565
|
}
|
|
6419
6566
|
return false;
|
|
@@ -6502,13 +6649,14 @@ function renderBlocks(blocks) {
|
|
|
6502
6649
|
break;
|
|
6503
6650
|
case "tool-call":
|
|
6504
6651
|
break;
|
|
6505
|
-
|
|
6506
|
-
const
|
|
6507
|
-
if (
|
|
6652
|
+
default: {
|
|
6653
|
+
const legacy = block;
|
|
6654
|
+
if (legacy.type === "tool-result" && legacy.content) {
|
|
6655
|
+
const nested = renderBlocks(legacy.content);
|
|
6656
|
+
if (nested) output.push(nested);
|
|
6657
|
+
}
|
|
6508
6658
|
break;
|
|
6509
6659
|
}
|
|
6510
|
-
default:
|
|
6511
|
-
break;
|
|
6512
6660
|
}
|
|
6513
6661
|
}
|
|
6514
6662
|
return output.join("\n").trim();
|
|
@@ -6560,6 +6708,7 @@ var TurnFolder = class {
|
|
|
6560
6708
|
return null;
|
|
6561
6709
|
}
|
|
6562
6710
|
case "tool/result": {
|
|
6711
|
+
if (event.surfaceOp && event.surfaceOp !== "append") return null;
|
|
6563
6712
|
const callId = String(event.data.message.source.callId);
|
|
6564
6713
|
const pending = this.pending(sessionId, event.data.turn);
|
|
6565
6714
|
if (pending.ignoredTools.has(callId)) return null;
|
|
@@ -6604,93 +6753,6 @@ var TurnFolder = class {
|
|
|
6604
6753
|
}
|
|
6605
6754
|
};
|
|
6606
6755
|
|
|
6607
|
-
// src/dsh-compatibility.ts
|
|
6608
|
-
import { readFileSync } from "node:fs";
|
|
6609
|
-
import { createRequire } from "node:module";
|
|
6610
|
-
var nodeRequire = createRequire(import.meta.url);
|
|
6611
|
-
var RUNTIME_PACKAGES = [
|
|
6612
|
-
"@deepseek-ai/cordis",
|
|
6613
|
-
"@deepseek-ai/dsh-agent-default-model",
|
|
6614
|
-
"@deepseek-ai/dsh-client-ui-conversation",
|
|
6615
|
-
"@deepseek-ai/dsh-llm",
|
|
6616
|
-
"@deepseek-ai/dsh-session",
|
|
6617
|
-
"@deepseek-ai/dsh-settings",
|
|
6618
|
-
"@deepseek-ai/dsh-system-prompt",
|
|
6619
|
-
"@deepseek-ai/dsh-tools",
|
|
6620
|
-
"@deepseek-ai/schemastery"
|
|
6621
|
-
];
|
|
6622
|
-
var SUPPORTED_RUNTIME_FAMILIES = [
|
|
6623
|
-
{
|
|
6624
|
-
cli: "0.1.2-rc.1",
|
|
6625
|
-
versions: {
|
|
6626
|
-
"@deepseek-ai/cordis": "4.0.2",
|
|
6627
|
-
"@deepseek-ai/dsh-agent-default-model": "0.1.2-rc.1",
|
|
6628
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1",
|
|
6629
|
-
"@deepseek-ai/dsh-llm": "0.1.2-rc.1",
|
|
6630
|
-
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
6631
|
-
"@deepseek-ai/dsh-settings": "0.1.2-rc.1",
|
|
6632
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
|
|
6633
|
-
"@deepseek-ai/dsh-tools": "0.1.2-rc.1",
|
|
6634
|
-
"@deepseek-ai/schemastery": "3.18.2"
|
|
6635
|
-
}
|
|
6636
|
-
},
|
|
6637
|
-
{
|
|
6638
|
-
cli: "0.1.5-rc.1",
|
|
6639
|
-
versions: {
|
|
6640
|
-
"@deepseek-ai/cordis": "4.0.2",
|
|
6641
|
-
"@deepseek-ai/dsh-agent-default-model": "0.1.5-rc.2",
|
|
6642
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
|
|
6643
|
-
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
6644
|
-
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
6645
|
-
"@deepseek-ai/dsh-settings": "0.1.5-rc.2",
|
|
6646
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
|
|
6647
|
-
"@deepseek-ai/dsh-tools": "0.1.5-rc.2",
|
|
6648
|
-
"@deepseek-ai/schemastery": "3.18.2"
|
|
6649
|
-
}
|
|
6650
|
-
},
|
|
6651
|
-
{
|
|
6652
|
-
cli: "0.1.6-alpha.1",
|
|
6653
|
-
versions: {
|
|
6654
|
-
"@deepseek-ai/cordis": "4.0.2",
|
|
6655
|
-
"@deepseek-ai/dsh-agent-default-model": "0.1.6-alpha.1",
|
|
6656
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.6-alpha.1",
|
|
6657
|
-
"@deepseek-ai/dsh-llm": "0.1.6-alpha.1",
|
|
6658
|
-
"@deepseek-ai/dsh-session": "0.1.6-alpha.1",
|
|
6659
|
-
"@deepseek-ai/dsh-settings": "0.1.6-alpha.1",
|
|
6660
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.6-alpha.1",
|
|
6661
|
-
"@deepseek-ai/dsh-tools": "0.1.6-alpha.1",
|
|
6662
|
-
"@deepseek-ai/schemastery": "3.18.2"
|
|
6663
|
-
}
|
|
6664
|
-
}
|
|
6665
|
-
];
|
|
6666
|
-
function installedVersion(packageName) {
|
|
6667
|
-
try {
|
|
6668
|
-
const manifestPath = nodeRequire.resolve(`${packageName}/package.json`);
|
|
6669
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
6670
|
-
if (typeof manifest.version === "string" && manifest.version.length > 0) return manifest.version;
|
|
6671
|
-
} catch {
|
|
6672
|
-
}
|
|
6673
|
-
return "<missing>";
|
|
6674
|
-
}
|
|
6675
|
-
function buildDshReplaceSurfaceOp(version, start, end) {
|
|
6676
|
-
return version === "0.1.2-rc.1" ? { op: "replace", start, end } : { op: "replace", startSeq: start, endSeq: end };
|
|
6677
|
-
}
|
|
6678
|
-
function dshReplaceSurfaceOp(start, end) {
|
|
6679
|
-
return buildDshReplaceSurfaceOp(installedVersion("@deepseek-ai/dsh-session"), start, end);
|
|
6680
|
-
}
|
|
6681
|
-
function classifyDshRuntime(packageVersions) {
|
|
6682
|
-
const family = SUPPORTED_RUNTIME_FAMILIES.find(({ versions }) => RUNTIME_PACKAGES.every((name2) => packageVersions[name2] === versions[name2]));
|
|
6683
|
-
if (family) return { cliVersion: family.cli, packageVersions };
|
|
6684
|
-
const found = RUNTIME_PACKAGES.map((name2) => `${name2}@${packageVersions[name2]}`).join(", ");
|
|
6685
|
-
throw new Error(
|
|
6686
|
-
`StrataGate cannot start because this DSH profile resolves an unsupported or mixed core runtime. Resolved: ${found}. Supported tested hosts are @deepseek-ai/dsh@0.1.2-rc.1 (internal DSH packages 0.1.2-rc.1) and @deepseek-ai/dsh@0.1.5-rc.1 (its real dependency tree uses internal DSH packages 0.1.5-rc.2), and @deepseek-ai/dsh@0.1.6-alpha.1 (internal DSH packages 0.1.6-alpha.1). Reinstall or update stratagate-dsh through \`dsh plugin --profile <name> add <package>\` so the host supplies its peers.`
|
|
6687
|
-
);
|
|
6688
|
-
}
|
|
6689
|
-
function assertCompatibleDshRuntime() {
|
|
6690
|
-
const packageVersions = Object.fromEntries(RUNTIME_PACKAGES.map((name2) => [name2, installedVersion(name2)]));
|
|
6691
|
-
return classifyDshRuntime(packageVersions);
|
|
6692
|
-
}
|
|
6693
|
-
|
|
6694
6756
|
// src/metadata.ts
|
|
6695
6757
|
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
6696
6758
|
var METADATA_SCHEMA = `
|
|
@@ -6804,7 +6866,6 @@ function graphProjectionCanRun(job, now = Date.now()) {
|
|
|
6804
6866
|
var AUTO_EVENT_LIMIT = 4;
|
|
6805
6867
|
var AUTO_ELEMENT_LIMIT = 4;
|
|
6806
6868
|
var AUTO_MEMORY_TOKEN_BUDGET = 900;
|
|
6807
|
-
var COMPACTION_SOURCE_PLUGIN = "stratagate-memory";
|
|
6808
6869
|
var FEEDBACK_PROMPT_COOLDOWN_MS = 5 * 24 * 60 * 60 * 1e3;
|
|
6809
6870
|
function projectKey(cwd) {
|
|
6810
6871
|
const canonical = resolve(cwd ?? process.cwd()).replaceAll("\\", "/").toLowerCase();
|
|
@@ -7469,7 +7530,7 @@ var StrataGateRuntime = class {
|
|
|
7469
7530
|
const memory = await this.space(session);
|
|
7470
7531
|
const threadId = String(session.id);
|
|
7471
7532
|
const blockContexts = memory.getBlockContext(threadId);
|
|
7472
|
-
if (this.syncDecayedBlockSurface(session, blockContexts)) {
|
|
7533
|
+
if (this.syncDecayedBlockSurface(session, memory, blockContexts)) {
|
|
7473
7534
|
await this.flushNativeSession(session);
|
|
7474
7535
|
}
|
|
7475
7536
|
const openTail = memory.listOpenTail(threadId);
|
|
@@ -7512,32 +7573,54 @@ var StrataGateRuntime = class {
|
|
|
7512
7573
|
* while deriveMessages() sees only this compressed checkpoint.
|
|
7513
7574
|
*/
|
|
7514
7575
|
replaceSealedSurface(session, block, context, endTurn) {
|
|
7515
|
-
|
|
7576
|
+
if (endTurn === null || hostCompactionActive(session)) return false;
|
|
7577
|
+
const sourceEventSeqs = sealedSurfaceSeqs(session, endTurn, block);
|
|
7578
|
+
if (!sourceEventSeqs) return false;
|
|
7516
7579
|
const start = sourceEventSeqs[0];
|
|
7517
7580
|
const end = sourceEventSeqs.at(-1);
|
|
7518
|
-
if (start === void 0 || end === void 0)
|
|
7519
|
-
|
|
7520
|
-
|
|
7581
|
+
if (start === void 0 || end === void 0) return false;
|
|
7582
|
+
const selected = selectCompressedBlockSurface(session, sourceEventSeqs, block, context);
|
|
7583
|
+
if (!selected) return false;
|
|
7521
7584
|
session.append("user/message", createUserMessage2({
|
|
7522
|
-
content: [{ type: "text", text:
|
|
7523
|
-
source:
|
|
7585
|
+
content: [{ type: "text", text: selected }],
|
|
7586
|
+
source: dshMessageSource()
|
|
7524
7587
|
}), {
|
|
7525
7588
|
surfaceOp: dshReplaceSurfaceOp(start, end),
|
|
7526
7589
|
sourceEventSeqs
|
|
7527
7590
|
});
|
|
7591
|
+
return true;
|
|
7528
7592
|
}
|
|
7529
7593
|
/** Keep each native Block checkpoint synchronized with its current decay pointer. */
|
|
7530
|
-
syncDecayedBlockSurface(session, contexts) {
|
|
7594
|
+
syncDecayedBlockSurface(session, memory, contexts) {
|
|
7595
|
+
if (hostCompactionActive(session)) return false;
|
|
7531
7596
|
const current = currentBlockSurfaceMessages(session);
|
|
7597
|
+
const blocks = new Map(memory.listBlocks().map((block) => [block.id, block]));
|
|
7598
|
+
const checkpointLimit = surfaceCheckpointLimit(session);
|
|
7532
7599
|
let changed = false;
|
|
7533
7600
|
for (const context of contexts) {
|
|
7534
7601
|
const node = current.get(context.id);
|
|
7535
7602
|
if (!node) continue;
|
|
7536
|
-
const
|
|
7603
|
+
const currentLevel = Number(node.text.match(/^Level: L([0-5]) /mu)?.[1] ?? -1);
|
|
7604
|
+
const currentTokens = surfaceCheckpointTokens(node.text);
|
|
7605
|
+
const sourceTokens = originalCheckpointSourceTokens(session, node.seq);
|
|
7606
|
+
const violatesLimit = currentTokens > checkpointLimit || sourceTokens !== null && !worthwhileSurfaceReduction(sourceTokens, currentTokens);
|
|
7607
|
+
if (context.level >= currentLevel && currentLevel >= 0 && !violatesLimit) continue;
|
|
7608
|
+
const block = blocks.get(context.id);
|
|
7609
|
+
if (!block) continue;
|
|
7610
|
+
const highestLevel = currentLevel >= 0 ? Math.min(context.level, currentLevel) : context.level;
|
|
7611
|
+
const text3 = selectCompressedBlockSurfaceText(
|
|
7612
|
+
node.text,
|
|
7613
|
+
context,
|
|
7614
|
+
block,
|
|
7615
|
+
highestLevel,
|
|
7616
|
+
sourceTokens,
|
|
7617
|
+
checkpointLimit
|
|
7618
|
+
);
|
|
7619
|
+
if (!text3) continue;
|
|
7537
7620
|
if (node.text === text3) continue;
|
|
7538
7621
|
session.append("user/message", createUserMessage2({
|
|
7539
7622
|
content: [{ type: "text", text: text3 }],
|
|
7540
|
-
source:
|
|
7623
|
+
source: dshMessageSource()
|
|
7541
7624
|
}), {
|
|
7542
7625
|
surfaceOp: dshReplaceSurfaceOp(node.seq, node.seq),
|
|
7543
7626
|
sourceEventSeqs: [node.seq]
|
|
@@ -7548,6 +7631,7 @@ var StrataGateRuntime = class {
|
|
|
7548
7631
|
}
|
|
7549
7632
|
/** Finish native-surface replacement when an admin retry ran without the target session loaded. */
|
|
7550
7633
|
async syncPendingRetrySurface(session, memory) {
|
|
7634
|
+
if (hostCompactionActive(session)) return;
|
|
7551
7635
|
const namespace = this.namespaceFor(session);
|
|
7552
7636
|
const threadId = String(session.id);
|
|
7553
7637
|
const pending = [...this.pendingSurfaceSync.entries()].filter(([, item]) => item.namespace === namespace);
|
|
@@ -7564,9 +7648,8 @@ var StrataGateRuntime = class {
|
|
|
7564
7648
|
const context = contexts.get(blockId);
|
|
7565
7649
|
if (!block || block.processingStatus !== "ready" || !context) continue;
|
|
7566
7650
|
try {
|
|
7567
|
-
this.replaceSealedSurface(session, block, context, dshTurnAtBlockEnd(session, block));
|
|
7651
|
+
changed = this.replaceSealedSurface(session, block, context, dshTurnAtBlockEnd(session, block)) || changed;
|
|
7568
7652
|
this.pendingSurfaceSync.delete(key);
|
|
7569
|
-
changed = true;
|
|
7570
7653
|
} catch (error) {
|
|
7571
7654
|
this.onIngestError(error);
|
|
7572
7655
|
}
|
|
@@ -8272,7 +8355,9 @@ var StrataGateRuntime = class {
|
|
|
8272
8355
|
try {
|
|
8273
8356
|
await memory2.resumePendingWork({ deferDerivation: true, threadId: String(session.id) });
|
|
8274
8357
|
const contexts = memory2.getBlockContext(String(session.id));
|
|
8275
|
-
this.syncDecayedBlockSurface(session, contexts)
|
|
8358
|
+
if (this.syncDecayedBlockSurface(session, memory2, contexts)) {
|
|
8359
|
+
await this.flushNativeSession(session);
|
|
8360
|
+
}
|
|
8276
8361
|
} finally {
|
|
8277
8362
|
await this.persistSuccessfulResponses(memory2);
|
|
8278
8363
|
}
|
|
@@ -8368,14 +8453,22 @@ var StrataGateRuntime = class {
|
|
|
8368
8453
|
await this.persistSuccessfulResponses(memory);
|
|
8369
8454
|
this.noteNewCoreJobFailures(session, failedBefore, memory);
|
|
8370
8455
|
const contexts = memory.getBlockContext(threadId);
|
|
8456
|
+
let changed = false;
|
|
8371
8457
|
for (const block of resumed.readyBlocks) {
|
|
8372
8458
|
if (block.threadId !== threadId) continue;
|
|
8373
8459
|
const context = contexts.find(({ id }) => id === block.id);
|
|
8374
8460
|
if (!context) throw new Error(`Missing context for ready StrataGate block ${block.id}`);
|
|
8375
|
-
|
|
8461
|
+
if (hostCompactionActive(session)) {
|
|
8462
|
+
this.pendingSurfaceSync.set(`${this.namespaceFor(session)}\0${block.id}`, {
|
|
8463
|
+
namespace: this.namespaceFor(session),
|
|
8464
|
+
blockId: block.id
|
|
8465
|
+
});
|
|
8466
|
+
continue;
|
|
8467
|
+
}
|
|
8468
|
+
changed = this.replaceSealedSurface(session, block, context, dshTurnAtBlockEnd(session, block)) || changed;
|
|
8376
8469
|
}
|
|
8377
|
-
|
|
8378
|
-
if (
|
|
8470
|
+
changed = this.syncDecayedBlockSurface(session, memory, contexts) || changed;
|
|
8471
|
+
if (changed) await this.flushNativeSession(session);
|
|
8379
8472
|
}).catch((error) => {
|
|
8380
8473
|
this.notePluginError(session, error);
|
|
8381
8474
|
this.onIngestError(error);
|
|
@@ -8537,8 +8630,11 @@ function renderContent(content) {
|
|
|
8537
8630
|
output.push(block.text.trim());
|
|
8538
8631
|
} else if (block.type === "image") {
|
|
8539
8632
|
output.push("[image]");
|
|
8540
|
-
} else
|
|
8541
|
-
|
|
8633
|
+
} else {
|
|
8634
|
+
const legacy = block;
|
|
8635
|
+
if (legacy.type === "tool-result" && Array.isArray(legacy.content)) {
|
|
8636
|
+
output.push(renderContent(legacy.content));
|
|
8637
|
+
}
|
|
8542
8638
|
}
|
|
8543
8639
|
}
|
|
8544
8640
|
return output.filter(Boolean).join("\n");
|
|
@@ -8566,11 +8662,10 @@ function dshTurnAtBlockEnd(session, block) {
|
|
|
8566
8662
|
const event = events[index];
|
|
8567
8663
|
if (event?.type === "turn/end" && event.time === blockEnd) return event.data.turn;
|
|
8568
8664
|
}
|
|
8569
|
-
|
|
8665
|
+
return null;
|
|
8570
8666
|
}
|
|
8571
|
-
function sealedSurfaceSeqs(session, endTurn,
|
|
8667
|
+
function sealedSurfaceSeqs(session, endTurn, block) {
|
|
8572
8668
|
const currentSurface = [...session.surface.nodes];
|
|
8573
|
-
const currentSet = new Set(currentSurface);
|
|
8574
8669
|
const completed = [];
|
|
8575
8670
|
let open2;
|
|
8576
8671
|
const events = session.snapshotEvents();
|
|
@@ -8585,30 +8680,122 @@ function sealedSurfaceSeqs(session, endTurn, turnCount) {
|
|
|
8585
8680
|
if (hasHumanMessage && event.data.turn <= endTurn) {
|
|
8586
8681
|
completed.push({
|
|
8587
8682
|
turn: event.data.turn,
|
|
8683
|
+
endTime: event.time,
|
|
8588
8684
|
start: open2.start,
|
|
8589
8685
|
end: event.seq,
|
|
8590
|
-
nodes: currentSurface.filter((seq) =>
|
|
8686
|
+
nodes: currentSurface.filter((seq) => {
|
|
8687
|
+
if (seq > open2.start && seq < event.seq) return true;
|
|
8688
|
+
const current = session.eventAt(seq);
|
|
8689
|
+
return current?.type === "tool/result" && current.surfaceOp !== "append" && current.sourceEventSeqs?.some((source) => source > open2.start && source < event.seq);
|
|
8690
|
+
})
|
|
8591
8691
|
});
|
|
8592
8692
|
}
|
|
8593
8693
|
open2 = void 0;
|
|
8594
8694
|
}
|
|
8695
|
+
const sourceTimes = block.l5Raw.filter((message) => message.role === "user").map((message) => Date.parse(message.createdAt));
|
|
8696
|
+
const turnCount = block.endTurn - block.startTurn + 1;
|
|
8595
8697
|
const selected = completed.slice(-turnCount);
|
|
8596
|
-
if (selected.length !== turnCount || selected.at(-1)?.turn !== endTurn)
|
|
8597
|
-
|
|
8598
|
-
|
|
8698
|
+
if (selected.length !== turnCount || selected.at(-1)?.turn !== endTurn || sourceTimes.length !== turnCount || selected.some((turn, index) => turn.endTime !== sourceTimes[index])) return null;
|
|
8699
|
+
const firstTurn = selected[0];
|
|
8700
|
+
const lastTurn = selected.at(-1);
|
|
8701
|
+
if (events.some((event) => {
|
|
8702
|
+
const hostEvent = event;
|
|
8703
|
+
return hostEvent.type === "compaction/summary" && hostEvent.data.shadowedSeqs?.some((seq) => seq >= firstTurn.start && seq <= lastTurn.end);
|
|
8704
|
+
})) return null;
|
|
8599
8705
|
const emptyTurn = selected.find((turn) => turn.nodes.length === 0);
|
|
8600
|
-
if (emptyTurn)
|
|
8601
|
-
throw new Error(`Cannot compact DSH turn ${emptyTurn.turn}: its original messages are no longer on the surface`);
|
|
8602
|
-
}
|
|
8706
|
+
if (emptyTurn) return null;
|
|
8603
8707
|
const start = selected[0].nodes[0];
|
|
8604
8708
|
const end = selected.at(-1).nodes.at(-1);
|
|
8605
8709
|
const startIndex = currentSurface.indexOf(start);
|
|
8606
8710
|
const endIndex = currentSurface.indexOf(end);
|
|
8607
|
-
if (startIndex < 0 || endIndex < startIndex)
|
|
8608
|
-
throw new Error(`Cannot identify a contiguous DSH surface range ending at turn ${endTurn}`);
|
|
8609
|
-
}
|
|
8711
|
+
if (startIndex < 0 || endIndex < startIndex) return null;
|
|
8610
8712
|
return currentSurface.slice(startIndex, endIndex + 1);
|
|
8611
8713
|
}
|
|
8714
|
+
function hostCompactionActive(session) {
|
|
8715
|
+
let lastBoundary;
|
|
8716
|
+
let lastSeed;
|
|
8717
|
+
for (let seq = session.seq - 1; seq >= 0; seq -= 1) {
|
|
8718
|
+
const event = session.eventAt(seq);
|
|
8719
|
+
if (!event) continue;
|
|
8720
|
+
if (lastSeed === void 0 && event.type === "session/end-seed") lastSeed = seq;
|
|
8721
|
+
if (!lastBoundary && (String(event.type) === "compaction/start" || String(event.type) === "compaction/end")) lastBoundary = event;
|
|
8722
|
+
if (lastSeed !== void 0 && lastBoundary) break;
|
|
8723
|
+
}
|
|
8724
|
+
return lastBoundary?.type === "compaction/start" && (lastSeed === void 0 || lastBoundary.seq > lastSeed);
|
|
8725
|
+
}
|
|
8726
|
+
var SURFACE_MIN_SAVED_TOKENS = 32;
|
|
8727
|
+
var SURFACE_MAX_REPLACEMENT_RATIO = 0.9;
|
|
8728
|
+
var SURFACE_MAX_WINDOW_FRACTION = 0.04;
|
|
8729
|
+
var SURFACE_CHECKPOINT_CEILING_TOKENS = 4096;
|
|
8730
|
+
function surfaceCheckpointLimit(session) {
|
|
8731
|
+
const window = typeof session.requestContext === "function" ? session.requestContext()?.contextWindow : void 0;
|
|
8732
|
+
return typeof window === "number" && Number.isInteger(window) && window > 0 ? Math.max(1, Math.min(SURFACE_CHECKPOINT_CEILING_TOKENS, Math.floor(window * SURFACE_MAX_WINDOW_FRACTION))) : SURFACE_CHECKPOINT_CEILING_TOKENS;
|
|
8733
|
+
}
|
|
8734
|
+
function surfaceCheckpointTokens(text3) {
|
|
8735
|
+
return estimateTokens(JSON.stringify(createUserMessage2({
|
|
8736
|
+
content: [{ type: "text", text: text3 }],
|
|
8737
|
+
source: dshMessageSource()
|
|
8738
|
+
})));
|
|
8739
|
+
}
|
|
8740
|
+
function originalCheckpointSourceTokens(session, seq) {
|
|
8741
|
+
const visited = /* @__PURE__ */ new Set();
|
|
8742
|
+
const visit = (sourceSeq) => {
|
|
8743
|
+
if (visited.has(sourceSeq)) return null;
|
|
8744
|
+
visited.add(sourceSeq);
|
|
8745
|
+
const event = session.eventAt(sourceSeq);
|
|
8746
|
+
if (!event) return null;
|
|
8747
|
+
if (event.type === "user/message" && isStrataGateMessageSource(event.data.source)) {
|
|
8748
|
+
const sources2 = event.sourceEventSeqs;
|
|
8749
|
+
if (!sources2?.length) return null;
|
|
8750
|
+
let total = 0;
|
|
8751
|
+
for (const source of sources2) {
|
|
8752
|
+
const tokens = visit(source);
|
|
8753
|
+
if (tokens === null) return null;
|
|
8754
|
+
total += tokens;
|
|
8755
|
+
}
|
|
8756
|
+
return total;
|
|
8757
|
+
}
|
|
8758
|
+
const message = session.deriveEventMessage(event);
|
|
8759
|
+
return message ? estimateTokens(JSON.stringify(message)) : null;
|
|
8760
|
+
};
|
|
8761
|
+
return visit(seq);
|
|
8762
|
+
}
|
|
8763
|
+
function worthwhileSurfaceReduction(before, after) {
|
|
8764
|
+
return before - after >= SURFACE_MIN_SAVED_TOKENS && after <= before * SURFACE_MAX_REPLACEMENT_RATIO;
|
|
8765
|
+
}
|
|
8766
|
+
function selectCompressedBlockSurfaceText(currentText, context, block, highestLevel, sourceTokens, checkpointLimit) {
|
|
8767
|
+
const before = surfaceCheckpointTokens(currentText);
|
|
8768
|
+
for (let level = highestLevel; level >= 0; level -= 1) {
|
|
8769
|
+
const candidate = renderBlockSurfaceMessage({
|
|
8770
|
+
...context,
|
|
8771
|
+
level,
|
|
8772
|
+
label: blockLevelLabel(level),
|
|
8773
|
+
content: level === context.level ? context.content : renderBlock(block, level)
|
|
8774
|
+
});
|
|
8775
|
+
const tokens = surfaceCheckpointTokens(candidate);
|
|
8776
|
+
if (tokens <= checkpointLimit && worthwhileSurfaceReduction(before, tokens) && (sourceTokens === null || worthwhileSurfaceReduction(sourceTokens, tokens))) return candidate;
|
|
8777
|
+
}
|
|
8778
|
+
return null;
|
|
8779
|
+
}
|
|
8780
|
+
function selectCompressedBlockSurface(session, sourceSeqs, block, context) {
|
|
8781
|
+
const before = sourceSeqs.reduce((sum, seq) => {
|
|
8782
|
+
const event = session.eventAt(seq);
|
|
8783
|
+
const message = event && session.deriveEventMessage(event);
|
|
8784
|
+
return sum + (message ? estimateTokens(JSON.stringify(message)) : 0);
|
|
8785
|
+
}, 0);
|
|
8786
|
+
const checkpointLimit = surfaceCheckpointLimit(session);
|
|
8787
|
+
for (let level = context.level; level >= 0; level -= 1) {
|
|
8788
|
+
const candidate = renderBlockSurfaceMessage({
|
|
8789
|
+
...context,
|
|
8790
|
+
level,
|
|
8791
|
+
label: blockLevelLabel(level),
|
|
8792
|
+
content: level === context.level ? context.content : renderBlock(block, level)
|
|
8793
|
+
});
|
|
8794
|
+
const tokens = surfaceCheckpointTokens(candidate);
|
|
8795
|
+
if (tokens <= checkpointLimit && worthwhileSurfaceReduction(before, tokens)) return candidate;
|
|
8796
|
+
}
|
|
8797
|
+
return null;
|
|
8798
|
+
}
|
|
8612
8799
|
function renderBlockSurfaceMessage(context) {
|
|
8613
8800
|
return [
|
|
8614
8801
|
"[StrataGate conversation block]",
|
|
@@ -8709,7 +8896,7 @@ function currentBlockSurfaceMessages(session) {
|
|
|
8709
8896
|
if (!session.surface?.nodes) return blocks;
|
|
8710
8897
|
for (const seq of session.surface.nodes) {
|
|
8711
8898
|
const event = session.eventAt(seq);
|
|
8712
|
-
if (event?.type !== "user/message" || event.data.source
|
|
8899
|
+
if (event?.type !== "user/message" || !isStrataGateMessageSource(event.data.source)) continue;
|
|
8713
8900
|
const text3 = event.data.content.flatMap((block) => block.type === "text" ? [block.text] : []).join("\n");
|
|
8714
8901
|
const blockId = text3.match(/^\[StrataGate conversation block\]\nBlock: ([^\n]+)/u)?.[1] ?? text3.match(/^\[StrataGate compressed conversation\]\nBlock ([^;\n]+);/u)?.[1];
|
|
8715
8902
|
if (blockId) blocks.set(blockId, { seq, text: text3 });
|
|
@@ -10376,7 +10563,7 @@ import {
|
|
|
10376
10563
|
} from "node:fs/promises";
|
|
10377
10564
|
import { basename, dirname as dirname2, join } from "node:path";
|
|
10378
10565
|
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
10379
|
-
import { encodeSeqRanges } from "@deepseek-ai/dsh-session";
|
|
10566
|
+
import { encodeSeqRanges, KNOWN_SESSION_EVENT_TYPES } from "@deepseek-ai/dsh-session";
|
|
10380
10567
|
var LEGACY_EVENT_TYPE = "stratagate/memory-citations";
|
|
10381
10568
|
var COMPAT_EVENT_TYPE = "feedback/record";
|
|
10382
10569
|
var ZSTD_MAGIC = 4247762216;
|
|
@@ -10530,12 +10717,24 @@ function prepareLegacyCitationGeneration(sourceBytes, compression, modules) {
|
|
|
10530
10717
|
if (decodedCut !== migratedCut) throw new Error("StrataGate compatibility migration changed the inherited Session cut");
|
|
10531
10718
|
const physicalHeader = { ...headerValue, version: 1 };
|
|
10532
10719
|
modules.releasedV1SessionFormatCodec.decodeHeader(physicalHeader);
|
|
10533
|
-
const
|
|
10534
|
-
|
|
10535
|
-
|
|
10536
|
-
|
|
10537
|
-
|
|
10538
|
-
|
|
10720
|
+
const v1 = modules.releasedV1SessionFormatCodec.createDecoder(physicalHeader, "strict");
|
|
10721
|
+
const v1Events = [];
|
|
10722
|
+
const v1Context = {
|
|
10723
|
+
emitEvent(event) {
|
|
10724
|
+
v1Events.push(event);
|
|
10725
|
+
},
|
|
10726
|
+
emitRun(run) {
|
|
10727
|
+
for (const event of run.expand()) v1Events.push(event);
|
|
10728
|
+
}
|
|
10729
|
+
};
|
|
10730
|
+
for (const row of outputRows) v1.decodeRow(row, v1Context);
|
|
10731
|
+
const v1Cut = v1.finish(v1Context);
|
|
10732
|
+
if (v1Cut !== decodedCut) throw new Error("StrataGate compatibility migration changed the inherited Session cut");
|
|
10733
|
+
const current = modules.restoreReleasedV1Artifact({
|
|
10734
|
+
header: v1.header,
|
|
10735
|
+
inheritedEventCount: v1Cut,
|
|
10736
|
+
events: v1Events
|
|
10737
|
+
}, KNOWN_SESSION_EVENT_TYPES);
|
|
10539
10738
|
return {
|
|
10540
10739
|
bytes: encodeGeneration(physicalHeader, outputRows, compression),
|
|
10541
10740
|
citationSeqs,
|
|
@@ -10544,15 +10743,12 @@ function prepareLegacyCitationGeneration(sourceBytes, compression, modules) {
|
|
|
10544
10743
|
}
|
|
10545
10744
|
async function loadMigrationModules() {
|
|
10546
10745
|
try {
|
|
10547
|
-
const
|
|
10548
|
-
import("@deepseek-ai/dsh-session-format-v0-to-v1"),
|
|
10549
|
-
import("@deepseek-ai/dsh-session-format-catalog")
|
|
10550
|
-
]);
|
|
10746
|
+
const edge = await import("@deepseek-ai/dsh-session-format-v0-to-v1");
|
|
10551
10747
|
return {
|
|
10552
10748
|
releasedV0SessionFormatCodec: edge.releasedV0SessionFormatCodec,
|
|
10553
10749
|
releasedV1SessionFormatCodec: edge.releasedV1SessionFormatCodec,
|
|
10554
10750
|
sessionFormatV0ToV1: edge.sessionFormatV0ToV1,
|
|
10555
|
-
|
|
10751
|
+
restoreReleasedV1Artifact: edge.restoreReleasedV1Artifact
|
|
10556
10752
|
};
|
|
10557
10753
|
} catch (error) {
|
|
10558
10754
|
if (error?.code === "ERR_MODULE_NOT_FOUND") return void 0;
|
|
@@ -10714,7 +10910,11 @@ async function apply(ctx, config) {
|
|
|
10714
10910
|
ctx.logger.info(`stratagate-memory prepared ${legacyMigration.migrated} legacy Session generation(s) for DSH ${compatibility.cliVersion}`);
|
|
10715
10911
|
}
|
|
10716
10912
|
await mkdir2(dirname3(resolved.database), { recursive: true });
|
|
10717
|
-
const models = new DshModelBridge(
|
|
10913
|
+
const models = new DshModelBridge(
|
|
10914
|
+
ctx,
|
|
10915
|
+
resolved,
|
|
10916
|
+
isLiveConfigValue(config.structuredReasoningEffort) ? () => liveConfigValue(config.structuredReasoningEffort) ?? "auto" : void 0
|
|
10917
|
+
);
|
|
10718
10918
|
const runtime = new StrataGateRuntime(resolved, models, (error) => {
|
|
10719
10919
|
ctx.logger.error(`stratagate-memory ingestion failed: ${renderError(error)}`);
|
|
10720
10920
|
}, async (session) => {
|
|
@@ -10729,18 +10929,17 @@ async function apply(ctx, config) {
|
|
|
10729
10929
|
};
|
|
10730
10930
|
let effortSource = () => effortEntry;
|
|
10731
10931
|
ctx.inject(["settings"], (settingsCtx) => {
|
|
10732
|
-
settingsCtx.settings
|
|
10733
|
-
|
|
10734
|
-
STRATAGATE_SETTINGS_NAMESPACE,
|
|
10735
|
-
StructuredReasoningEffortSettings,
|
|
10736
|
-
effortEntry,
|
|
10737
|
-
{
|
|
10932
|
+
const settings = settingsCtx.settings;
|
|
10933
|
+
if (settings.installSection) {
|
|
10934
|
+
settings.installSection(ctx, STRATAGATE_SETTINGS_NAMESPACE, StructuredReasoningEffortSettings, effortEntry, {
|
|
10738
10935
|
setSource: (current) => {
|
|
10739
10936
|
effortSource = current;
|
|
10740
10937
|
},
|
|
10741
10938
|
onChange: () => models.setStructuredReasoningEffort(effortSource().structuredReasoningEffort)
|
|
10742
|
-
}
|
|
10743
|
-
)
|
|
10939
|
+
});
|
|
10940
|
+
} else if (settings.configure) {
|
|
10941
|
+
settingsCtx.effect(() => settings.configure({ auto: false }, ctx.fiber));
|
|
10942
|
+
}
|
|
10744
10943
|
});
|
|
10745
10944
|
ctx.systemPrompt.section({ name: "tool:stratagate-memory", order: 113, text: MEMORY_PROTOCOL });
|
|
10746
10945
|
ctx.systemPrompt.section({ name: "tool:stratagate-feedback", order: 114, text: FEEDBACK_PROTOCOL });
|
|
@@ -10774,7 +10973,7 @@ async function apply(ctx, config) {
|
|
|
10774
10973
|
type: "text",
|
|
10775
10974
|
text: `StrataGate retrieval batches are still unresolved: ${runtime.pendingBatchIds(agent.session).join(", ")}. Before ending this turn, close each one with memory_record_use using its batch_id and evidence_refs set to exactly the refs from that batch used in the answer, or [] if none were used.`
|
|
10776
10975
|
}],
|
|
10777
|
-
source:
|
|
10976
|
+
source: dshMessageSource("instructions")
|
|
10778
10977
|
}));
|
|
10779
10978
|
});
|
|
10780
10979
|
registerMemoryTools(ctx, runtime);
|