stratagate-dsh 0.2.77 → 0.2.79
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 +10 -0
- package/dist/client.js +1 -1
- package/dist/plugin.js +178 -13
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/plugin.js
CHANGED
|
@@ -98,6 +98,11 @@ var FILLER_ONLY = /* @__PURE__ */ new Set([
|
|
|
98
98
|
]);
|
|
99
99
|
var REPEATED_PASTE_MIN_CHARS = 80;
|
|
100
100
|
var REPEATED_PASTE_MARKER = "[repeated paste omitted; original remains in L5]";
|
|
101
|
+
var DERIVATION_SOURCE_FIELD_MIN_CHARS = 240;
|
|
102
|
+
var DERIVATION_ARGUMENT_MAX_CHARS = 1200;
|
|
103
|
+
var DERIVATION_RESULT_MAX_CHARS = 2400;
|
|
104
|
+
var DERIVATION_TOOL_MESSAGE_MAX_CHARS = 2400;
|
|
105
|
+
var DERIVATION_SOURCE_FIELD = /^(?:code|command|program|script|source|sourcecode)$/u;
|
|
101
106
|
function asBlockLevel(value) {
|
|
102
107
|
return Math.max(0, Math.min(BLOCK_MAX_LEVEL, Math.round(value)));
|
|
103
108
|
}
|
|
@@ -161,6 +166,73 @@ function resultSummary(value) {
|
|
|
161
166
|
if (record2.ok === false) return "not completed";
|
|
162
167
|
return "structured result returned";
|
|
163
168
|
}
|
|
169
|
+
function serializedValue(value) {
|
|
170
|
+
if (typeof value === "string") return value;
|
|
171
|
+
try {
|
|
172
|
+
return JSON.stringify(value) ?? String(value);
|
|
173
|
+
} catch {
|
|
174
|
+
return String(value);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function sourceFieldName(value) {
|
|
178
|
+
return DERIVATION_SOURCE_FIELD.test(value.replace(/[\s_-]+/gu, "").toLocaleLowerCase());
|
|
179
|
+
}
|
|
180
|
+
function omitLargeSourceFields(value, key = "", seen = /* @__PURE__ */ new WeakSet()) {
|
|
181
|
+
if (typeof value === "string") {
|
|
182
|
+
if (!sourceFieldName(key) || value.length <= DERIVATION_SOURCE_FIELD_MIN_CHARS) return value;
|
|
183
|
+
return `[${key || "source"} omitted: ${value.length} chars; full value remains in L5]`;
|
|
184
|
+
}
|
|
185
|
+
if (!value || typeof value !== "object") return value;
|
|
186
|
+
if (seen.has(value)) return "[circular value omitted; full value remains in L5]";
|
|
187
|
+
seen.add(value);
|
|
188
|
+
if (Array.isArray(value)) return value.map((item) => omitLargeSourceFields(item, key, seen));
|
|
189
|
+
return Object.fromEntries(Object.entries(value).map(([nestedKey, nestedValue]) => [nestedKey, omitLargeSourceFields(nestedValue, nestedKey, seen)]));
|
|
190
|
+
}
|
|
191
|
+
function compactDerivationValue(value, maxChars, label) {
|
|
192
|
+
const rendered = serializedValue(value);
|
|
193
|
+
if (rendered.length <= maxChars) return value;
|
|
194
|
+
const summary = resultSummary(value);
|
|
195
|
+
const headChars = Math.max(160, Math.floor(maxChars * 0.48));
|
|
196
|
+
const tailChars = Math.max(80, Math.floor(maxChars * 0.2));
|
|
197
|
+
const omittedChars = Math.max(0, rendered.length - headChars - tailChars);
|
|
198
|
+
return {
|
|
199
|
+
_stratagate: `${label} compacted; full value remains in L5`,
|
|
200
|
+
originalChars: rendered.length,
|
|
201
|
+
...summary ? { summary } : {},
|
|
202
|
+
head: rendered.slice(0, headChars),
|
|
203
|
+
tail: rendered.slice(-tailChars),
|
|
204
|
+
omittedChars
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function compactDerivationText(value, maxChars, label) {
|
|
208
|
+
if (value.length <= maxChars) return value;
|
|
209
|
+
const headChars = Math.max(160, Math.floor(maxChars * 0.6));
|
|
210
|
+
const tailChars = Math.max(80, Math.floor(maxChars * 0.2));
|
|
211
|
+
const omittedChars = Math.max(0, value.length - headChars - tailChars);
|
|
212
|
+
return `${value.slice(0, headChars)}
|
|
213
|
+
[${label} compacted: ${omittedChars} chars omitted; full value remains in L5]
|
|
214
|
+
${value.slice(-tailChars)}`;
|
|
215
|
+
}
|
|
216
|
+
function buildMemoryDerivationMessages(messages) {
|
|
217
|
+
return messages.map((message) => ({
|
|
218
|
+
...message,
|
|
219
|
+
content: message.role === "tool" ? compactDerivationText(message.content, DERIVATION_TOOL_MESSAGE_MAX_CHARS, "tool message content") : message.content,
|
|
220
|
+
...message.toolCalls ? {
|
|
221
|
+
toolCalls: message.toolCalls.map((trace) => {
|
|
222
|
+
const argumentsValue = trace.arguments === void 0 ? void 0 : compactDerivationValue(
|
|
223
|
+
omitLargeSourceFields(trace.arguments),
|
|
224
|
+
DERIVATION_ARGUMENT_MAX_CHARS,
|
|
225
|
+
"tool arguments"
|
|
226
|
+
);
|
|
227
|
+
return {
|
|
228
|
+
name: trace.name,
|
|
229
|
+
...argumentsValue === void 0 ? {} : { arguments: argumentsValue },
|
|
230
|
+
...trace.result === void 0 ? {} : { result: compactDerivationValue(trace.result, DERIVATION_RESULT_MAX_CHARS, "tool result") }
|
|
231
|
+
};
|
|
232
|
+
})
|
|
233
|
+
} : {}
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
164
236
|
function summarizeToolTrace(trace) {
|
|
165
237
|
const summary = resultSummary(trace.result);
|
|
166
238
|
return `Tool call: ${trace.name}${summary ? ` (${summary})` : ""}`;
|
|
@@ -5426,7 +5498,14 @@ function l2Neighbor(block) {
|
|
|
5426
5498
|
}
|
|
5427
5499
|
function extractorPayload(context) {
|
|
5428
5500
|
return {
|
|
5429
|
-
target:
|
|
5501
|
+
target: {
|
|
5502
|
+
blockId: context.target.id,
|
|
5503
|
+
sequence: context.target.sequence,
|
|
5504
|
+
startTurn: context.target.startTurn,
|
|
5505
|
+
endTurn: context.target.endTurn,
|
|
5506
|
+
createdAt: context.target.createdAt,
|
|
5507
|
+
messages: buildMemoryDerivationMessages(context.target.l5Raw)
|
|
5508
|
+
},
|
|
5430
5509
|
neighbors: {
|
|
5431
5510
|
previous: l2Neighbor(context.previous),
|
|
5432
5511
|
next: l2Neighbor(context.next)
|
|
@@ -5672,6 +5751,7 @@ var DshModelBridge = class {
|
|
|
5672
5751
|
this.structuredReasoningEffort = config.structuredReasoningEffort ?? "auto";
|
|
5673
5752
|
this.ctx.on?.("llm/adapters-updated", () => {
|
|
5674
5753
|
this.offCapabilities.clear();
|
|
5754
|
+
for (const listener of this.adaptersUpdatedListeners) listener();
|
|
5675
5755
|
});
|
|
5676
5756
|
}
|
|
5677
5757
|
ctx;
|
|
@@ -5680,7 +5760,24 @@ var DshModelBridge = class {
|
|
|
5680
5760
|
successfulResponses = [];
|
|
5681
5761
|
offCapabilities = /* @__PURE__ */ new Map();
|
|
5682
5762
|
warnedOffFallbackRoutes = /* @__PURE__ */ new Set();
|
|
5763
|
+
adaptersUpdatedListeners = /* @__PURE__ */ new Set();
|
|
5683
5764
|
structuredReasoningEffort;
|
|
5765
|
+
/** True only when the exact provider route has a registered DSH adapter. */
|
|
5766
|
+
isReady(session) {
|
|
5767
|
+
try {
|
|
5768
|
+
const { provider } = this.resolveRoute(session);
|
|
5769
|
+
return this.ctx.llm.listProviders().some(({ id }) => id === provider);
|
|
5770
|
+
} catch {
|
|
5771
|
+
return false;
|
|
5772
|
+
}
|
|
5773
|
+
}
|
|
5774
|
+
/** Wake durable workers when DSH changes the adapter registry. */
|
|
5775
|
+
onAdaptersUpdated(listener) {
|
|
5776
|
+
this.adaptersUpdatedListeners.add(listener);
|
|
5777
|
+
return () => {
|
|
5778
|
+
this.adaptersUpdatedListeners.delete(listener);
|
|
5779
|
+
};
|
|
5780
|
+
}
|
|
5684
5781
|
setStructuredReasoningEffort(mode) {
|
|
5685
5782
|
this.structuredReasoningEffort = mode;
|
|
5686
5783
|
}
|
|
@@ -5697,8 +5794,8 @@ var DshModelBridge = class {
|
|
|
5697
5794
|
summarizer = async (messages) => {
|
|
5698
5795
|
const raw = object(await this.callStructured(
|
|
5699
5796
|
"summarizer",
|
|
5700
|
-
`You compress agent conversations into durable memory blocks. Read the supplied messages and call ${STRUCTURED_TOOLS.summarizer.name} exactly once with l0Title, l0Tags, l1Summary, l2Keypoints, and shouldExtract. Preserve decisions, constraints, preferences, outcomes, and unresolved work. shouldExtract is true only when durable events or facts exist. Do not return the summary as text.`,
|
|
5701
|
-
{ messages }
|
|
5797
|
+
`You compress agent conversations into durable memory blocks. Read the supplied provenance-preserving derivation messages and call ${STRUCTURED_TOOLS.summarizer.name} exactly once with l0Title, l0Tags, l1Summary, l2Keypoints, and shouldExtract. Preserve decisions, constraints, preferences, outcomes, and unresolved work. Tool code and oversized tool payloads may be marked compacted; use the retained tool names, evidence summaries, and excerpts without inventing omitted details. shouldExtract is true only when durable events or facts exist. Do not return the summary as text.`,
|
|
5798
|
+
{ messages: buildMemoryDerivationMessages(messages) }
|
|
5702
5799
|
));
|
|
5703
5800
|
return {
|
|
5704
5801
|
l0Title: text2(raw.l0Title).slice(0, 120),
|
|
@@ -5712,7 +5809,7 @@ var DshModelBridge = class {
|
|
|
5712
5809
|
const validMessageIds = new Set(context.target.l5Raw.map((message) => message.id));
|
|
5713
5810
|
const raw = object(await this.callStructured(
|
|
5714
5811
|
"extractor",
|
|
5715
|
-
`Extract only durable, evidence-backed events from target.
|
|
5812
|
+
`Extract only durable, evidence-backed events from target.messages, then call ${STRUCTURED_TOOLS.extractor.name} exactly once. target.messages is a provenance-preserving derivation view of the target block: message ids and conversational text are retained, while tool code and oversized tool payloads may be marked compacted. Use the retained tool names, evidence summaries, and excerpts without inventing omitted details. The target block is the only legal source of new facts, quotations, and sourceMessageIds. neighbors.previous and neighbors.next are context-only L2 summaries; never extract from them. Every sourceMessageIds entry must exactly match allowedSourceMessageIds. If a fact appears only in a neighbor, do not extract it in this call. Events must be understandable later without the original chat. Use project scope for repository decisions, user scope for stable preferences/identity, and session scope for temporary task state. temporal.eventType must use exactly one stable value: decision, release, task_completed, plan, change, cancellation, incident, meeting, collaboration, migration, or other. temporal.participants contains canonical entity names. Use ISO-8601 timestamps with the explicit +08:00 offset in temporal fields. Keep happened time separate from mentionedAt; when happened time is unknown omit it and set precision/basis to unknown. Do not turn an assistant statement that merely recalls older memory into a new event; require new human input or a new observable task/tool outcome from target.messages. Do not return the result as text.`,
|
|
5716
5813
|
extractorPayload(context)
|
|
5717
5814
|
));
|
|
5718
5815
|
const events = (Array.isArray(raw.events) ? raw.events : []).map((candidate) => {
|
|
@@ -5891,6 +5988,7 @@ var DshModelBridge = class {
|
|
|
5891
5988
|
let lastError;
|
|
5892
5989
|
let lastResponse = "";
|
|
5893
5990
|
let attemptsUsed = 0;
|
|
5991
|
+
let noAdapterRetried = false;
|
|
5894
5992
|
for (let attempt = 1; attempt <= JSON_RESPONSE_ATTEMPTS; attempt += 1) {
|
|
5895
5993
|
attemptsUsed = attempt;
|
|
5896
5994
|
const message = createUserMessage({
|
|
@@ -5921,6 +6019,11 @@ ${JSON_RETRY_INSTRUCTION}`,
|
|
|
5921
6019
|
try {
|
|
5922
6020
|
await this.consumeStructuredStream(request, assembler);
|
|
5923
6021
|
} catch (error) {
|
|
6022
|
+
if (!noAdapterRetried && isNoAdapter(error)) {
|
|
6023
|
+
noAdapterRetried = true;
|
|
6024
|
+
attempt -= 1;
|
|
6025
|
+
continue;
|
|
6026
|
+
}
|
|
5924
6027
|
if (useOff && isOffRejection(error)) {
|
|
5925
6028
|
this.offCapabilities.set(routeKey, "unsupported");
|
|
5926
6029
|
useOff = false;
|
|
@@ -5933,6 +6036,11 @@ ${JSON_RETRY_INSTRUCTION}`,
|
|
|
5933
6036
|
const finish = assembler.finish;
|
|
5934
6037
|
if (finish.kind === "error" || finish.kind === "aborted") {
|
|
5935
6038
|
const failure = new Error(`StrataGate model call failed [${finish.failure.code}]: ${finish.failure.message}`);
|
|
6039
|
+
if (!noAdapterRetried && isNoAdapter(finish.failure)) {
|
|
6040
|
+
noAdapterRetried = true;
|
|
6041
|
+
attempt -= 1;
|
|
6042
|
+
continue;
|
|
6043
|
+
}
|
|
5936
6044
|
if (useOff && isOffRejection(finish.failure)) {
|
|
5937
6045
|
this.offCapabilities.set(routeKey, "unsupported");
|
|
5938
6046
|
useOff = false;
|
|
@@ -6098,6 +6206,17 @@ ${JSON_RETRY_INSTRUCTION}`,
|
|
|
6098
6206
|
return { provider: fallback.provider, model: fallback.model };
|
|
6099
6207
|
}
|
|
6100
6208
|
};
|
|
6209
|
+
function isNoAdapter(error) {
|
|
6210
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6211
|
+
let current = error;
|
|
6212
|
+
while (current && typeof current === "object" && !seen.has(current)) {
|
|
6213
|
+
seen.add(current);
|
|
6214
|
+
const candidate = current;
|
|
6215
|
+
if (candidate.code === "NO_ADAPTER") return true;
|
|
6216
|
+
current = candidate.cause;
|
|
6217
|
+
}
|
|
6218
|
+
return false;
|
|
6219
|
+
}
|
|
6101
6220
|
function isOffRejection(error) {
|
|
6102
6221
|
let detail;
|
|
6103
6222
|
try {
|
|
@@ -6539,6 +6658,7 @@ var StrataGateRuntime = class {
|
|
|
6539
6658
|
this.openPath = openPath;
|
|
6540
6659
|
this.blockTurnSize = config.blockTurnSize;
|
|
6541
6660
|
this.blockDecayLambda = config.blockDecayLambda;
|
|
6661
|
+
this.disposeAdaptersUpdated = this.models.onAdaptersUpdated(() => this.wakeModelWorkers());
|
|
6542
6662
|
this.scheduleBackgroundWorker(BACKGROUND_WORKER_INITIAL_DELAY_MS);
|
|
6543
6663
|
}
|
|
6544
6664
|
config;
|
|
@@ -6553,6 +6673,7 @@ var StrataGateRuntime = class {
|
|
|
6553
6673
|
latestBatchIds = /* @__PURE__ */ new Map();
|
|
6554
6674
|
workspaceNames = /* @__PURE__ */ new Map();
|
|
6555
6675
|
migrationTimers = /* @__PURE__ */ new Map();
|
|
6676
|
+
migrationRuns = /* @__PURE__ */ new Map();
|
|
6556
6677
|
derivationTimers = /* @__PURE__ */ new Map();
|
|
6557
6678
|
derivationRuns = /* @__PURE__ */ new Map();
|
|
6558
6679
|
knownSessions = /* @__PURE__ */ new Map();
|
|
@@ -6571,6 +6692,8 @@ var StrataGateRuntime = class {
|
|
|
6571
6692
|
backgroundNamespaceRuns = /* @__PURE__ */ new Map();
|
|
6572
6693
|
backgroundWorkerTimer;
|
|
6573
6694
|
backgroundWorkerRun;
|
|
6695
|
+
backgroundWorkerWakePending = false;
|
|
6696
|
+
disposeAdaptersUpdated;
|
|
6574
6697
|
settingsTail = Promise.resolve();
|
|
6575
6698
|
batchSequence = 0;
|
|
6576
6699
|
closed = false;
|
|
@@ -6586,13 +6709,15 @@ var StrataGateRuntime = class {
|
|
|
6586
6709
|
this.backgroundWorkerRun = run;
|
|
6587
6710
|
void run.finally(() => {
|
|
6588
6711
|
if (this.backgroundWorkerRun === run) this.backgroundWorkerRun = void 0;
|
|
6589
|
-
this.
|
|
6712
|
+
const delay = this.backgroundWorkerWakePending ? 0 : BACKGROUND_WORKER_INTERVAL_MS;
|
|
6713
|
+
this.backgroundWorkerWakePending = false;
|
|
6714
|
+
this.scheduleBackgroundWorker(delay);
|
|
6590
6715
|
});
|
|
6591
6716
|
}, delayMs);
|
|
6592
6717
|
this.backgroundWorkerTimer.unref?.();
|
|
6593
6718
|
}
|
|
6594
6719
|
async runBackgroundWorker() {
|
|
6595
|
-
if (this.closed) return;
|
|
6720
|
+
if (this.closed || !this.models.isReady()) return;
|
|
6596
6721
|
let namespaces;
|
|
6597
6722
|
try {
|
|
6598
6723
|
namespaces = await this.adminNamespaces();
|
|
@@ -6610,6 +6735,7 @@ var StrataGateRuntime = class {
|
|
|
6610
6735
|
}
|
|
6611
6736
|
}
|
|
6612
6737
|
async runBackgroundNamespace(namespace) {
|
|
6738
|
+
if (this.closed || !this.models.isReady()) return;
|
|
6613
6739
|
const existing = this.backgroundNamespaceRuns.get(namespace);
|
|
6614
6740
|
if (existing) return existing;
|
|
6615
6741
|
const run = (async () => {
|
|
@@ -6625,9 +6751,11 @@ var StrataGateRuntime = class {
|
|
|
6625
6751
|
const hasActiveSessionWork = [
|
|
6626
6752
|
...this.derivationTimers.keys(),
|
|
6627
6753
|
...this.derivationRuns.keys(),
|
|
6628
|
-
...this.migrationTimers.keys()
|
|
6754
|
+
...this.migrationTimers.keys(),
|
|
6755
|
+
...this.migrationRuns.keys()
|
|
6629
6756
|
].some((key) => key.startsWith(`${namespace}\0`) || key === namespace);
|
|
6630
6757
|
if (hasActiveSessionWork) return;
|
|
6758
|
+
if (!this.models.isReady()) return;
|
|
6631
6759
|
const resumed = await this.models.runDetached(
|
|
6632
6760
|
`stratagate-worker:${namespace}`,
|
|
6633
6761
|
() => memory.resumePendingWork()
|
|
@@ -6655,6 +6783,33 @@ var StrataGateRuntime = class {
|
|
|
6655
6783
|
if (this.backgroundNamespaceRuns.get(namespace) === run) this.backgroundNamespaceRuns.delete(namespace);
|
|
6656
6784
|
}
|
|
6657
6785
|
}
|
|
6786
|
+
wakeBackgroundWorker() {
|
|
6787
|
+
if (this.closed) return;
|
|
6788
|
+
if (this.backgroundWorkerTimer) {
|
|
6789
|
+
clearTimeout(this.backgroundWorkerTimer);
|
|
6790
|
+
this.backgroundWorkerTimer = void 0;
|
|
6791
|
+
}
|
|
6792
|
+
if (this.backgroundWorkerRun) {
|
|
6793
|
+
this.backgroundWorkerWakePending = true;
|
|
6794
|
+
return;
|
|
6795
|
+
}
|
|
6796
|
+
this.scheduleBackgroundWorker(0);
|
|
6797
|
+
}
|
|
6798
|
+
wakeModelWorkers() {
|
|
6799
|
+
if (this.closed) return;
|
|
6800
|
+
this.wakeBackgroundWorker();
|
|
6801
|
+
for (const reference of this.knownSessions.values()) {
|
|
6802
|
+
const session = reference.deref();
|
|
6803
|
+
if (!session || !this.models.isReady(session)) continue;
|
|
6804
|
+
const opening = this.spaces.get(this.namespaceFor(session));
|
|
6805
|
+
if (!opening) continue;
|
|
6806
|
+
void opening.then((memory) => {
|
|
6807
|
+
if (this.closed || !this.models.isReady(session)) return;
|
|
6808
|
+
this.scheduleGraphMigration(session, memory);
|
|
6809
|
+
this.scheduleBlockDerivation(session, memory);
|
|
6810
|
+
}).catch((error) => this.onIngestError(error));
|
|
6811
|
+
}
|
|
6812
|
+
}
|
|
6658
6813
|
acceptEvent(session, event) {
|
|
6659
6814
|
if (this.closed) return;
|
|
6660
6815
|
if (!this.config.ingestSubagents && session.header.origin === "subagent") return;
|
|
@@ -7138,6 +7293,7 @@ var StrataGateRuntime = class {
|
|
|
7138
7293
|
async close() {
|
|
7139
7294
|
if (this.closed) return;
|
|
7140
7295
|
this.closed = true;
|
|
7296
|
+
this.disposeAdaptersUpdated();
|
|
7141
7297
|
if (this.backgroundWorkerTimer) clearTimeout(this.backgroundWorkerTimer);
|
|
7142
7298
|
this.backgroundWorkerTimer = void 0;
|
|
7143
7299
|
for (const timer of this.migrationTimers.values()) clearTimeout(timer);
|
|
@@ -7155,6 +7311,7 @@ var StrataGateRuntime = class {
|
|
|
7155
7311
|
const settled = await Promise.allSettled(this.spaces.values());
|
|
7156
7312
|
await Promise.allSettled(this.backgroundNamespaceRuns.values());
|
|
7157
7313
|
if (this.backgroundWorkerRun) await Promise.allSettled([this.backgroundWorkerRun]);
|
|
7314
|
+
await Promise.allSettled(this.migrationRuns.values());
|
|
7158
7315
|
await Promise.allSettled(this.derivationRuns.values());
|
|
7159
7316
|
await Promise.allSettled(this.externalImportRuns.values());
|
|
7160
7317
|
await Promise.all(settled.flatMap((result) => result.status === "fulfilled" ? [result.value.close()] : []));
|
|
@@ -7691,6 +7848,9 @@ var StrataGateRuntime = class {
|
|
|
7691
7848
|
if (kind === "event-extraction") return memory.retryEventExtraction(jobId);
|
|
7692
7849
|
return memory.retryGraphProjection(jobId);
|
|
7693
7850
|
};
|
|
7851
|
+
if (!this.models.isReady(session)) {
|
|
7852
|
+
throw new Error("StrataGate model adapter is not ready; retry after DSH finishes registering adapters");
|
|
7853
|
+
}
|
|
7694
7854
|
const result = session && this.namespaceFor(session) === key ? await this.models.run(session, retry) : await this.models.runDetached(threadId, retry);
|
|
7695
7855
|
await this.persistSuccessfulResponses(memory);
|
|
7696
7856
|
const currentBlock = blockId ? memory.listBlocks().find(({ id: candidateId }) => candidateId === blockId) : void 0;
|
|
@@ -7890,7 +8050,7 @@ var StrataGateRuntime = class {
|
|
|
7890
8050
|
scheduleBlockDerivation(session, memory) {
|
|
7891
8051
|
const threadId = String(session.id);
|
|
7892
8052
|
const key = `${this.namespaceFor(session)}\0${threadId}`;
|
|
7893
|
-
if (this.closed || this.derivationTimers.has(key) || this.derivationRuns.has(key)) return;
|
|
8053
|
+
if (this.closed || !this.models.isReady(session) || this.derivationTimers.has(key) || this.derivationRuns.has(key)) return;
|
|
7894
8054
|
const pendingBlockIds = new Set(memory.listBlocks().filter((block) => block.threadId === threadId && block.processingStatus === "pending").map((block) => block.id));
|
|
7895
8055
|
if (pendingBlockIds.size === 0) return;
|
|
7896
8056
|
const retryTimes = [
|
|
@@ -7901,7 +8061,7 @@ var StrataGateRuntime = class {
|
|
|
7901
8061
|
const delay = Math.max(0, Math.min(...retryTimes) - Date.now());
|
|
7902
8062
|
const timer = setTimeout(() => {
|
|
7903
8063
|
this.derivationTimers.delete(key);
|
|
7904
|
-
if (this.closed) return;
|
|
8064
|
+
if (this.closed || !this.models.isReady(session)) return;
|
|
7905
8065
|
const failedBefore = this.failedCoreJobs(memory);
|
|
7906
8066
|
const run = this.models.run(session, () => memory.resumePendingWork({ threadId })).then(async (resumed) => {
|
|
7907
8067
|
await this.persistSuccessfulResponses(memory);
|
|
@@ -7929,24 +8089,29 @@ var StrataGateRuntime = class {
|
|
|
7929
8089
|
}
|
|
7930
8090
|
scheduleGraphMigration(session, memory) {
|
|
7931
8091
|
const namespace = this.namespaceFor(session);
|
|
7932
|
-
if (this.closed || this.migrationTimers.has(namespace)) return;
|
|
8092
|
+
if (this.closed || !this.models.isReady(session) || this.migrationTimers.has(namespace) || this.migrationRuns.has(namespace)) return;
|
|
7933
8093
|
if (typeof memory.listGraphProjectionJobs !== "function") return;
|
|
7934
8094
|
const pending = memory.listGraphProjectionJobs().some((job) => graphProjectionCanRun(job));
|
|
7935
8095
|
if (!pending) return;
|
|
7936
8096
|
const timer = setTimeout(() => {
|
|
7937
8097
|
this.migrationTimers.delete(namespace);
|
|
7938
|
-
if (this.closed) return;
|
|
8098
|
+
if (this.closed || !this.models.isReady(session)) return;
|
|
7939
8099
|
const failedBefore = this.failedCoreJobs(memory);
|
|
7940
8100
|
const completedBefore = memory.listGraphProjectionJobs().filter(({ status }) => status === "completed").length;
|
|
7941
|
-
|
|
8101
|
+
let madeProgress = false;
|
|
8102
|
+
const run = this.models.run(session, () => memory.resumePendingWork()).then(async () => {
|
|
7942
8103
|
await this.persistSuccessfulResponses(memory);
|
|
7943
8104
|
this.noteNewCoreJobFailures(session, failedBefore, memory);
|
|
7944
8105
|
const completedAfter = memory.listGraphProjectionJobs().filter(({ status }) => status === "completed").length;
|
|
7945
|
-
|
|
8106
|
+
madeProgress = completedAfter > completedBefore;
|
|
7946
8107
|
}).catch((error) => {
|
|
7947
8108
|
this.notePluginError(session, error);
|
|
7948
8109
|
this.onIngestError(error);
|
|
8110
|
+
}).finally(() => {
|
|
8111
|
+
if (this.migrationRuns.get(namespace) === run) this.migrationRuns.delete(namespace);
|
|
8112
|
+
if (madeProgress) this.scheduleGraphMigration(session, memory);
|
|
7949
8113
|
});
|
|
8114
|
+
this.migrationRuns.set(namespace, run);
|
|
7950
8115
|
}, 1500);
|
|
7951
8116
|
timer.unref?.();
|
|
7952
8117
|
this.migrationTimers.set(namespace, timer);
|