stratagate-dsh 0.3.15 → 0.3.17
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 +14 -0
- package/dist/client.js +7 -7
- package/dist/plugin.js +601 -192
- package/dist/plugin.js.map +1 -1
- package/docs/DSH.md +6 -2
- package/docs/DSH.zh-CN.md +5 -3
- package/docs/feedback.md +50 -0
- package/package.json +16 -13
package/dist/plugin.js
CHANGED
|
@@ -8241,6 +8241,7 @@ var StrataGate = class _StrataGate {
|
|
|
8241
8241
|
// src/dsh-compatibility.ts
|
|
8242
8242
|
import { readFileSync } from "node:fs";
|
|
8243
8243
|
import { createRequire } from "node:module";
|
|
8244
|
+
import { satisfies } from "semver";
|
|
8244
8245
|
var nodeRequire = createRequire(import.meta.url);
|
|
8245
8246
|
var CORE_RUNTIME_PACKAGES = [
|
|
8246
8247
|
"@deepseek-ai/cordis",
|
|
@@ -8260,93 +8261,26 @@ var SESSION_FORMAT_PACKAGES = [
|
|
|
8260
8261
|
"@deepseek-ai/dsh-session-format-v0-to-v1"
|
|
8261
8262
|
];
|
|
8262
8263
|
var RUNTIME_PACKAGES = [...CORE_RUNTIME_PACKAGES, ...SESSION_FORMAT_PACKAGES];
|
|
8263
|
-
var SUPPORTED_RUNTIME_FAMILIES = [
|
|
8264
|
-
{
|
|
8265
|
-
cli: "0.1.2-rc.1",
|
|
8266
|
-
versions: {
|
|
8267
|
-
"@deepseek-ai/cordis": "4.0.2",
|
|
8268
|
-
"@deepseek-ai/dsh-agent-default-model": "0.1.2-rc.1",
|
|
8269
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1",
|
|
8270
|
-
"@deepseek-ai/dsh-llm": "0.1.2-rc.1",
|
|
8271
|
-
"@deepseek-ai/dsh-native-command": "0.1.2-rc.1",
|
|
8272
|
-
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
8273
|
-
"@deepseek-ai/dsh-settings": "0.1.2-rc.1",
|
|
8274
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
|
|
8275
|
-
"@deepseek-ai/dsh-tools": "0.1.2-rc.1",
|
|
8276
|
-
"@deepseek-ai/schemastery": "3.18.2"
|
|
8277
|
-
}
|
|
8278
|
-
},
|
|
8279
|
-
{
|
|
8280
|
-
cli: "0.1.5-rc.1",
|
|
8281
|
-
versions: {
|
|
8282
|
-
"@deepseek-ai/cordis": "4.0.2",
|
|
8283
|
-
"@deepseek-ai/dsh-agent-default-model": "0.1.5-rc.2",
|
|
8284
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
|
|
8285
|
-
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
8286
|
-
"@deepseek-ai/dsh-native-command": "0.1.5-rc.2",
|
|
8287
|
-
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
8288
|
-
"@deepseek-ai/dsh-settings": "0.1.5-rc.2",
|
|
8289
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
|
|
8290
|
-
"@deepseek-ai/dsh-tools": "0.1.5-rc.2",
|
|
8291
|
-
"@deepseek-ai/schemastery": "3.18.2"
|
|
8292
|
-
}
|
|
8293
|
-
},
|
|
8294
|
-
{
|
|
8295
|
-
cli: "0.1.6-alpha.1",
|
|
8296
|
-
versions: {
|
|
8297
|
-
"@deepseek-ai/cordis": "4.0.2",
|
|
8298
|
-
"@deepseek-ai/dsh-agent-default-model": "0.1.6-alpha.1",
|
|
8299
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.6-alpha.1",
|
|
8300
|
-
"@deepseek-ai/dsh-llm": "0.1.6-alpha.1",
|
|
8301
|
-
"@deepseek-ai/dsh-native-command": "0.1.6-alpha.1",
|
|
8302
|
-
"@deepseek-ai/dsh-session": "0.1.6-alpha.1",
|
|
8303
|
-
"@deepseek-ai/dsh-settings": "0.1.6-alpha.1",
|
|
8304
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.6-alpha.1",
|
|
8305
|
-
"@deepseek-ai/dsh-tools": "0.1.6-alpha.1",
|
|
8306
|
-
"@deepseek-ai/schemastery": "3.18.2"
|
|
8307
|
-
}
|
|
8308
|
-
},
|
|
8309
|
-
{
|
|
8310
|
-
cli: "0.1.7-rc.1",
|
|
8311
|
-
versions: {
|
|
8312
|
-
"@deepseek-ai/cordis": "4.0.4",
|
|
8313
|
-
"@deepseek-ai/dsh-agent-default-model": "0.1.7-rc.1",
|
|
8314
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.1",
|
|
8315
|
-
"@deepseek-ai/dsh-llm": "0.1.7-rc.1",
|
|
8316
|
-
"@deepseek-ai/dsh-native-command": "0.1.7-rc.1",
|
|
8317
|
-
"@deepseek-ai/dsh-session": "0.1.7-rc.1",
|
|
8318
|
-
"@deepseek-ai/dsh-settings": "0.1.7-rc.1",
|
|
8319
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.7-rc.1",
|
|
8320
|
-
"@deepseek-ai/dsh-tools": "0.1.7-rc.1",
|
|
8321
|
-
"@deepseek-ai/schemastery": "3.18.4"
|
|
8322
|
-
}
|
|
8323
|
-
},
|
|
8324
|
-
{
|
|
8325
|
-
cli: "0.1.7-rc.2",
|
|
8326
|
-
versions: {
|
|
8327
|
-
"@deepseek-ai/cordis": "4.0.4",
|
|
8328
|
-
"@deepseek-ai/dsh-agent-default-model": "0.1.7-rc.2",
|
|
8329
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2",
|
|
8330
|
-
"@deepseek-ai/dsh-llm": "0.1.7-rc.2",
|
|
8331
|
-
"@deepseek-ai/dsh-native-command": "0.1.7-rc.2",
|
|
8332
|
-
"@deepseek-ai/dsh-session": "0.1.7-rc.2",
|
|
8333
|
-
"@deepseek-ai/dsh-settings": "0.1.7-rc.2",
|
|
8334
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.7-rc.2",
|
|
8335
|
-
"@deepseek-ai/dsh-tools": "0.1.7-rc.2",
|
|
8336
|
-
"@deepseek-ai/schemastery": "3.18.4"
|
|
8337
|
-
}
|
|
8338
|
-
}
|
|
8339
|
-
];
|
|
8340
8264
|
var STRATAGATE_MESSAGE_SOURCE_KIND = "plugin:stratagate-memory";
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8265
|
+
var DSH_RUNTIME_RANGE = "0.1.2-rc.1 || >=0.1.5-rc.2 <0.3.0-0";
|
|
8266
|
+
var MODERN_API_RANGE = ">=0.1.7-rc.1";
|
|
8267
|
+
var SESSION_FORMAT_RUNTIME_RANGE = ">=0.2.0-0";
|
|
8268
|
+
var SEMVER_OPTIONS = { includePrerelease: true };
|
|
8269
|
+
function assertDshMethods(scope, value, methods) {
|
|
8270
|
+
const target = value;
|
|
8271
|
+
const missing = methods.filter((method) => typeof target?.[method] !== "function");
|
|
8272
|
+
if (missing.length) {
|
|
8273
|
+
throw new Error(`StrataGate cannot use this DSH host: missing required interface ${missing.map((method) => `${scope}.${method}`).join(", ")}. Use a compatible host or plugin version.`);
|
|
8274
|
+
}
|
|
8275
|
+
}
|
|
8276
|
+
function assertDshHostContract(ctx) {
|
|
8277
|
+
assertDshMethods("tools", ctx.tools, ["register", "get"]);
|
|
8278
|
+
assertDshMethods("systemPrompt", ctx.systemPrompt, ["section"]);
|
|
8279
|
+
assertDshMethods("llm", ctx.llm, ["stream", "listProviders"]);
|
|
8280
|
+
assertDshMethods("agentDefaultModel", ctx.agentDefaultModel, ["currentSelection"]);
|
|
8347
8281
|
}
|
|
8348
8282
|
function buildDshMessageSource(version, form) {
|
|
8349
|
-
const source =
|
|
8283
|
+
const source = satisfies(version, MODERN_API_RANGE, SEMVER_OPTIONS) ? { kind: STRATAGATE_MESSAGE_SOURCE_KIND } : { kind: "plugin", plugin: "stratagate-memory" };
|
|
8350
8284
|
return form ? { ...source, form } : source;
|
|
8351
8285
|
}
|
|
8352
8286
|
function installedVersion(packageName) {
|
|
@@ -8377,17 +8311,17 @@ function isCompatiblePatch(version, major, minor, minimumPatch) {
|
|
|
8377
8311
|
return !!match && Number(match[1]) === major && Number(match[2]) === minor && Number(match[3]) >= minimumPatch;
|
|
8378
8312
|
}
|
|
8379
8313
|
function classifyDshRuntime(packageVersions) {
|
|
8380
|
-
const family = SUPPORTED_RUNTIME_FAMILIES.find(({ versions }) => CORE_RUNTIME_PACKAGES.every((name2) => packageVersions[name2] === versions[name2]));
|
|
8381
|
-
if (family) return { cliVersion: family.cli, packageVersions };
|
|
8382
8314
|
const dshVersion = packageVersions["@deepseek-ai/dsh-session"];
|
|
8383
8315
|
const sameDshFamily = CORE_RUNTIME_PACKAGES.filter((name2) => name2.startsWith("@deepseek-ai/dsh-")).every((name2) => packageVersions[name2] === dshVersion);
|
|
8384
|
-
const sameSessionFormatFamily = !
|
|
8385
|
-
|
|
8386
|
-
|
|
8316
|
+
const sameSessionFormatFamily = !satisfies(dshVersion, SESSION_FORMAT_RUNTIME_RANGE, SEMVER_OPTIONS) || SESSION_FORMAT_PACKAGES.every((name2) => packageVersions[name2] === dshVersion);
|
|
8317
|
+
const modernApi = satisfies(dshVersion, MODERN_API_RANGE, SEMVER_OPTIONS);
|
|
8318
|
+
const compatibleVendors = modernApi ? isCompatiblePatch(packageVersions["@deepseek-ai/cordis"], 4, 0, 4) && isCompatiblePatch(packageVersions["@deepseek-ai/schemastery"], 3, 18, 4) : packageVersions["@deepseek-ai/cordis"] === "4.0.2" && packageVersions["@deepseek-ai/schemastery"] === "3.18.2";
|
|
8319
|
+
if (satisfies(dshVersion, DSH_RUNTIME_RANGE, SEMVER_OPTIONS) && sameDshFamily && sameSessionFormatFamily && compatibleVendors) {
|
|
8320
|
+
return { cliVersion: dshVersion === "0.1.5-rc.2" ? "0.1.5-rc.1" : dshVersion, packageVersions };
|
|
8387
8321
|
}
|
|
8388
8322
|
const found = RUNTIME_PACKAGES.map((name2) => `${name2}@${packageVersions[name2]}`).join(", ");
|
|
8389
8323
|
throw new Error(
|
|
8390
|
-
`StrataGate cannot start because this DSH profile resolves an unsupported or mixed core runtime. Resolved: ${found}. Supported
|
|
8324
|
+
`StrataGate cannot start because this DSH profile resolves an unsupported or mixed core runtime. Resolved: ${found}. Supported DSH versions: ${DSH_RUNTIME_RANGE} (including prereleases). Core DSH packages must share one version; DSH 0.2.0 and later also require matching Session Format packages. Modern hosts require Cordis 4.0.x from 4.0.4 and Schemastery 3.18.x from 3.18.4; older hosts use 4.0.2 and 3.18.2. Reinstall or update stratagate-dsh through \`dsh plugin --profile <name> add <package>\` so the host supplies its peers.`
|
|
8391
8325
|
);
|
|
8392
8326
|
}
|
|
8393
8327
|
function assertCompatibleDshRuntime() {
|
|
@@ -8521,6 +8455,329 @@ function parseJsonResponse(value, requiredKeys = []) {
|
|
|
8521
8455
|
throw new ModelJsonResponseError(void 0, { response: value });
|
|
8522
8456
|
}
|
|
8523
8457
|
|
|
8458
|
+
// src/llm.ts
|
|
8459
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
8460
|
+
|
|
8461
|
+
// src/diagnostics.ts
|
|
8462
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
8463
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
8464
|
+
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
8465
|
+
var DAY = 864e5;
|
|
8466
|
+
var VERSION = (() => {
|
|
8467
|
+
try {
|
|
8468
|
+
return String(createRequire2(import.meta.url)("../package.json").version);
|
|
8469
|
+
} catch {
|
|
8470
|
+
return "unknown";
|
|
8471
|
+
}
|
|
8472
|
+
})();
|
|
8473
|
+
var DIAGNOSTIC_STAGES = ["summarizer", "extractor", "projector", "graphProjector", "topicProjector", "externalMemoryExtractor", "externalMemoryDecider", "profileMaintenance", "dreamingStep", "chat", "ingestion", "autoContext", "directory", "tools", "frontend", "retrieval"];
|
|
8474
|
+
function diagnosticText(value, limit = 1500) {
|
|
8475
|
+
return String(value instanceof Error ? value.message : value ?? "").slice(0, 8e3).split(/\nRaw response(?: preview| \(full\))/i)[0].replace(/\b(?:sk[-_]|gh[opasu]_|github_pat_)[A-Za-z0-9_-]{8,}\b/g, "[credential]").replace(/(["']?\b(?:api[_-]?key|token|password|passwd|secret|authorization|access[_-]?token|refresh[_-]?token)["']?\s*[:=]\s*)(["'])([\s\S]*?)\2/gi, "$1[credential]").replace(/\b(?:Bearer|Basic|Token)\s+[^\s,;}]+/gi, "[credential]").replace(/\b(?:api[_-]?key|token|password|passwd|secret|authorization)\s*[:=]\s*[^\s,;}]+/gi, "[credential]").replace(/https?:\/\/[^\s<>"']+/gi, "[url]").replace(/[A-Z]:[\\/][^\s"'<>]+/gi, "[path]").replace(/[\w.+-]+@[\w.-]+\.[a-z]{2,}/gi, "[email]").replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f]/g, "").slice(0, limit).replace(/[\uD800-\uDBFF]$/, "");
|
|
8476
|
+
}
|
|
8477
|
+
function isAbortError(error) {
|
|
8478
|
+
return typeof error === "object" && error !== null && (error.name === "AbortError" || error.code === "ABORT_ERR");
|
|
8479
|
+
}
|
|
8480
|
+
function diagnosticCategory(error) {
|
|
8481
|
+
if (isAbortError(error)) return "cancelled";
|
|
8482
|
+
const text3 = String(error instanceof Error ? error.message : error ?? "");
|
|
8483
|
+
if (/timeout|timed out|超时/i.test(text3)) return "timeout";
|
|
8484
|
+
if (/429|rate.?limit/i.test(text3)) return "rate-limit";
|
|
8485
|
+
if (/401|403|unauthori|forbidden|credential/i.test(text3)) return "authentication";
|
|
8486
|
+
if (/token.*limit|truncat|max-tokens|context.*(window|length|limit)/i.test(text3)) return "token-limit";
|
|
8487
|
+
if (/json|schema|invalid|validation/i.test(text3)) return "validation";
|
|
8488
|
+
if (/sqlite|database|storage|EACCES|ENOSPC|write failed/i.test(text3)) return "storage";
|
|
8489
|
+
if (/abort|cancel/i.test(text3)) return "cancelled";
|
|
8490
|
+
if (/network|fetch|ECONN|ENOTFOUND/i.test(text3)) return "network";
|
|
8491
|
+
return "internal";
|
|
8492
|
+
}
|
|
8493
|
+
var SCHEMA2 = `
|
|
8494
|
+
CREATE TABLE IF NOT EXISTS stratagate_dsh_diagnostic_records (
|
|
8495
|
+
id TEXT PRIMARY KEY, at TEXT NOT NULL, namespace TEXT NOT NULL, record_json TEXT NOT NULL
|
|
8496
|
+
) STRICT;
|
|
8497
|
+
CREATE INDEX IF NOT EXISTS stratagate_dsh_diagnostic_scope ON stratagate_dsh_diagnostic_records(namespace, at);
|
|
8498
|
+
CREATE TABLE IF NOT EXISTS stratagate_dsh_diagnostic_daily (
|
|
8499
|
+
namespace TEXT NOT NULL, day TEXT NOT NULL, stage TEXT NOT NULL, model TEXT NOT NULL,
|
|
8500
|
+
version TEXT NOT NULL, counters_json TEXT NOT NULL,
|
|
8501
|
+
PRIMARY KEY(namespace, day, stage, model, version)
|
|
8502
|
+
) STRICT;
|
|
8503
|
+
CREATE TABLE IF NOT EXISTS stratagate_dsh_diagnostic_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL) STRICT;
|
|
8504
|
+
`;
|
|
8505
|
+
var DiagnosticsRecorder = class {
|
|
8506
|
+
constructor(filename) {
|
|
8507
|
+
this.filename = filename;
|
|
8508
|
+
}
|
|
8509
|
+
filename;
|
|
8510
|
+
database;
|
|
8511
|
+
pending = [];
|
|
8512
|
+
timer;
|
|
8513
|
+
closed = false;
|
|
8514
|
+
dropped = 0;
|
|
8515
|
+
writeFailures = 0;
|
|
8516
|
+
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8517
|
+
record(scope, counters, options = {}) {
|
|
8518
|
+
if (this.closed) return;
|
|
8519
|
+
const bounded2 = Object.fromEntries(Object.entries(counters).filter(([, n]) => Number.isFinite(n) && n >= 0));
|
|
8520
|
+
this.pending.push({
|
|
8521
|
+
id: `diag_${randomUUID3()}`,
|
|
8522
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8523
|
+
namespace: scope.namespace,
|
|
8524
|
+
stage: scope.stage,
|
|
8525
|
+
model: diagnosticText(options.model ?? "", 160),
|
|
8526
|
+
version: VERSION,
|
|
8527
|
+
counters: bounded2,
|
|
8528
|
+
...scope.taskId ? { taskId: scope.taskId } : {},
|
|
8529
|
+
...options.error !== void 0 ? { category: diagnosticCategory(options.error), detail: diagnosticText(options.error) } : {}
|
|
8530
|
+
});
|
|
8531
|
+
if (this.pending.length > 256) {
|
|
8532
|
+
this.pending.shift();
|
|
8533
|
+
this.dropped++;
|
|
8534
|
+
}
|
|
8535
|
+
if (!this.timer) {
|
|
8536
|
+
this.timer = setTimeout(() => {
|
|
8537
|
+
this.timer = void 0;
|
|
8538
|
+
this.flush();
|
|
8539
|
+
}, 5e3);
|
|
8540
|
+
this.timer.unref?.();
|
|
8541
|
+
}
|
|
8542
|
+
}
|
|
8543
|
+
open() {
|
|
8544
|
+
if (this.database) return this.database;
|
|
8545
|
+
const db = new DatabaseSync2(this.filename);
|
|
8546
|
+
try {
|
|
8547
|
+
db.exec("PRAGMA busy_timeout=0");
|
|
8548
|
+
db.exec(SCHEMA2);
|
|
8549
|
+
db.prepare("INSERT OR IGNORE INTO stratagate_dsh_diagnostic_meta VALUES ('startedAt', ?)").run(this.startedAt);
|
|
8550
|
+
this.database = db;
|
|
8551
|
+
return db;
|
|
8552
|
+
} catch (error) {
|
|
8553
|
+
db.close();
|
|
8554
|
+
throw error;
|
|
8555
|
+
}
|
|
8556
|
+
}
|
|
8557
|
+
flush() {
|
|
8558
|
+
if (!this.pending.length) return;
|
|
8559
|
+
try {
|
|
8560
|
+
const db = this.open();
|
|
8561
|
+
db.exec("BEGIN IMMEDIATE");
|
|
8562
|
+
try {
|
|
8563
|
+
const get = db.prepare("SELECT counters_json FROM stratagate_dsh_diagnostic_daily WHERE namespace=? AND day=? AND stage=? AND model=? AND version=?");
|
|
8564
|
+
const put = db.prepare("INSERT OR REPLACE INTO stratagate_dsh_diagnostic_daily VALUES (?, ?, ?, ?, ?, ?)");
|
|
8565
|
+
const insert = db.prepare("INSERT INTO stratagate_dsh_diagnostic_records VALUES (?, ?, ?, ?)");
|
|
8566
|
+
for (const item of this.pending) {
|
|
8567
|
+
const keys = [item.namespace, item.at.slice(0, 10), item.stage, item.model, item.version];
|
|
8568
|
+
const row = get.get(...keys);
|
|
8569
|
+
const counters = row ? JSON.parse(row.counters_json) : {};
|
|
8570
|
+
for (const [key, value] of Object.entries(item.counters)) counters[key] = (counters[key] ?? 0) + value;
|
|
8571
|
+
put.run(...keys, JSON.stringify(counters));
|
|
8572
|
+
insert.run(item.id, item.at, item.namespace, JSON.stringify(item));
|
|
8573
|
+
}
|
|
8574
|
+
db.prepare("DELETE FROM stratagate_dsh_diagnostic_records WHERE at < ? OR id NOT IN (SELECT id FROM stratagate_dsh_diagnostic_records ORDER BY at DESC, id DESC LIMIT 2000)").run(new Date(Date.now() - 7 * DAY).toISOString());
|
|
8575
|
+
db.prepare("DELETE FROM stratagate_dsh_diagnostic_daily WHERE day < ?").run(new Date(Date.now() - 90 * DAY).toISOString().slice(0, 10));
|
|
8576
|
+
db.exec("DELETE FROM stratagate_dsh_diagnostic_daily WHERE rowid NOT IN (SELECT rowid FROM stratagate_dsh_diagnostic_daily ORDER BY day DESC LIMIT 10000)");
|
|
8577
|
+
db.exec("COMMIT");
|
|
8578
|
+
this.pending = [];
|
|
8579
|
+
} catch (error) {
|
|
8580
|
+
db.exec("ROLLBACK");
|
|
8581
|
+
throw error;
|
|
8582
|
+
}
|
|
8583
|
+
} catch {
|
|
8584
|
+
this.writeFailures++;
|
|
8585
|
+
}
|
|
8586
|
+
}
|
|
8587
|
+
snapshot(namespace, options = {}) {
|
|
8588
|
+
this.flush();
|
|
8589
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8590
|
+
const since = new Date(Date.parse(today) - 6 * DAY).toISOString().slice(0, 10);
|
|
8591
|
+
const totals = {};
|
|
8592
|
+
const stages = {};
|
|
8593
|
+
let startedAt = this.startedAt;
|
|
8594
|
+
let available = false;
|
|
8595
|
+
let rows = [];
|
|
8596
|
+
let records = [];
|
|
8597
|
+
let totalRecords = 0;
|
|
8598
|
+
let corruptRollups = 0;
|
|
8599
|
+
let corruptRecords = 0;
|
|
8600
|
+
let scannedRecords = 0;
|
|
8601
|
+
const offset = Math.max(0, Math.min(2e3, Math.floor(options.offset ?? 0)));
|
|
8602
|
+
const readCounters = (text3) => {
|
|
8603
|
+
try {
|
|
8604
|
+
const value = JSON.parse(text3);
|
|
8605
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid counters");
|
|
8606
|
+
const entries = Object.entries(value);
|
|
8607
|
+
if (entries.some(([, n]) => typeof n !== "number" || !Number.isFinite(n) || n < 0)) throw new Error("Invalid counter value");
|
|
8608
|
+
return Object.fromEntries(entries);
|
|
8609
|
+
} catch {
|
|
8610
|
+
corruptRollups++;
|
|
8611
|
+
return {};
|
|
8612
|
+
}
|
|
8613
|
+
};
|
|
8614
|
+
try {
|
|
8615
|
+
const db = this.open();
|
|
8616
|
+
available = true;
|
|
8617
|
+
startedAt = db.prepare("SELECT value FROM stratagate_dsh_diagnostic_meta WHERE key='startedAt'").get().value;
|
|
8618
|
+
rows = db.prepare("SELECT day, stage, model, version, counters_json FROM stratagate_dsh_diagnostic_daily WHERE namespace=? AND day>=? ORDER BY day, stage, model, version LIMIT 2001").all(namespace, since);
|
|
8619
|
+
const where = options.id ? "namespace=? AND id=?" : "namespace=? AND at>=? AND json_extract(record_json, '$.category') IS NOT NULL";
|
|
8620
|
+
const values = options.id ? [namespace, options.id] : [namespace, since];
|
|
8621
|
+
totalRecords = Number(db.prepare(`SELECT count(*) AS count FROM stratagate_dsh_diagnostic_records WHERE ${where}`).get(...values).count);
|
|
8622
|
+
const raw = db.prepare(`SELECT record_json FROM stratagate_dsh_diagnostic_records WHERE ${where} ORDER BY at DESC, id DESC LIMIT 20 OFFSET ?`).all(...values, offset);
|
|
8623
|
+
scannedRecords = raw.length;
|
|
8624
|
+
for (const row of raw) {
|
|
8625
|
+
try {
|
|
8626
|
+
const item = JSON.parse(row.record_json);
|
|
8627
|
+
if (!item || item.namespace !== namespace || !DIAGNOSTIC_STAGES.includes(item.stage) || ["id", "at", "model", "version"].some((key) => typeof item[key] !== "string") || !item.counters || typeof item.counters !== "object" || Array.isArray(item.counters) || Object.values(item.counters).some((n) => typeof n !== "number" || !Number.isFinite(n) || n < 0)) throw new Error("Invalid diagnostic record");
|
|
8628
|
+
records.push({
|
|
8629
|
+
id: item.id,
|
|
8630
|
+
at: item.at,
|
|
8631
|
+
namespace,
|
|
8632
|
+
stage: item.stage,
|
|
8633
|
+
model: diagnosticText(item.model, 160),
|
|
8634
|
+
version: item.version,
|
|
8635
|
+
counters: item.counters,
|
|
8636
|
+
...typeof item.taskId === "string" ? { taskId: item.taskId } : {},
|
|
8637
|
+
...typeof item.category === "string" ? { category: diagnosticText(item.category, 80) } : {},
|
|
8638
|
+
...typeof item.detail === "string" ? { detail: diagnosticText(item.detail) } : {}
|
|
8639
|
+
});
|
|
8640
|
+
} catch {
|
|
8641
|
+
corruptRecords++;
|
|
8642
|
+
}
|
|
8643
|
+
}
|
|
8644
|
+
} catch {
|
|
8645
|
+
available = false;
|
|
8646
|
+
}
|
|
8647
|
+
const parsedRows = rows.slice(0, 2e3).map((row) => ({ ...row, counters: readCounters(row.counters_json) }));
|
|
8648
|
+
for (const row of parsedRows) {
|
|
8649
|
+
const counters = row.counters;
|
|
8650
|
+
const stage = stages[row.stage] ??= {};
|
|
8651
|
+
for (const [key, value] of Object.entries(counters)) {
|
|
8652
|
+
totals[key] = (totals[key] ?? 0) + value;
|
|
8653
|
+
stage[key] = (stage[key] ?? 0) + value;
|
|
8654
|
+
}
|
|
8655
|
+
}
|
|
8656
|
+
const routes = /* @__PURE__ */ new Map();
|
|
8657
|
+
for (const row of parsedRows) {
|
|
8658
|
+
const key = JSON.stringify([row.stage, row.model, row.version]);
|
|
8659
|
+
const route = routes.get(key) ?? { stage: row.stage, model: row.model, version: row.version, counters: {} };
|
|
8660
|
+
for (const [name2, n] of Object.entries(row.counters)) route.counters[name2] = (route.counters[name2] ?? 0) + n;
|
|
8661
|
+
routes.set(key, route);
|
|
8662
|
+
}
|
|
8663
|
+
const rates = Object.fromEntries(Object.entries(stages).map(([stage, counts]) => [stage, {
|
|
8664
|
+
sampledOperations: counts.operations ?? 0,
|
|
8665
|
+
operationFailureRate: counts.operations ? (counts.operationsFailed ?? 0) / counts.operations : null,
|
|
8666
|
+
firstAttemptSuccessRate: counts.operations ? (counts.firstAttemptSucceeded ?? 0) / counts.operations : null,
|
|
8667
|
+
recoveredOperationRate: counts.operations ? (counts.operationsRecovered ?? 0) / counts.operations : null,
|
|
8668
|
+
meanOperationMs: counts.operations ? (counts.operationMs ?? 0) / counts.operations : null,
|
|
8669
|
+
meanModelMs: counts.modelCalls ? (counts.modelMs ?? 0) / counts.modelCalls : null
|
|
8670
|
+
}]));
|
|
8671
|
+
const chatTokens = stages.chat?.totalTokens ?? 0;
|
|
8672
|
+
const backgroundTokens = (totals.totalTokens ?? 0) - chatTokens;
|
|
8673
|
+
const totalsComplete = available && !corruptRollups && !this.dropped && totals.modelCalls && totals.totalTokenCalls === totals.modelCalls && !this.pending.length && rows.length <= 2e3;
|
|
8674
|
+
return {
|
|
8675
|
+
schemaVersion: 1,
|
|
8676
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8677
|
+
since,
|
|
8678
|
+
through: today,
|
|
8679
|
+
timezone: "UTC",
|
|
8680
|
+
startedAt,
|
|
8681
|
+
coverage: {
|
|
8682
|
+
available,
|
|
8683
|
+
corruptRollups,
|
|
8684
|
+
corruptRecords,
|
|
8685
|
+
processStartedAt: this.startedAt,
|
|
8686
|
+
pendingRecords: this.pending.length,
|
|
8687
|
+
droppedRecords: this.dropped,
|
|
8688
|
+
writeFailures: this.writeFailures,
|
|
8689
|
+
rollupTruncated: rows.length > 2e3,
|
|
8690
|
+
historicalBackfill: false,
|
|
8691
|
+
rawRetentionDays: 7,
|
|
8692
|
+
rollupRetentionDays: 90,
|
|
8693
|
+
totalChatCostRatio: null,
|
|
8694
|
+
netSavings: null,
|
|
8695
|
+
note: "\u7EDF\u8BA1\u4ECE\u91C7\u96C6\u542F\u7528\u540E\u5F00\u59CB\uFF1BToken \u4E3A\u9002\u914D\u5668\u62A5\u544A\u503C\uFF0C\u7F3A\u5931\u53E6\u8BA1\uFF1BmemoryInputEstimate \u4EC5\u4F30\u7B97\u5E38\u9A7B\u89C4\u5219\u3001\u5DE5\u5177\u5B9A\u4E49\u3001\u753B\u50CF\u548C\u81EA\u52A8\u4E0A\u4E0B\u6587\uFF0C\u5C1A\u672A\u5B8C\u6574\u5F52\u56E0\u5386\u53F2\u5DE5\u5177\u7ED3\u679C\u53CA\u5206\u5C42\u5BF9\u8BDD\u3002\u51C0\u6536\u76CA\u4E0E\u8D39\u7528\u5360\u6BD4\u5F85\u6D4B\u3002\u4E3B\u804A\u5929\u8986\u76D6\u5DF2\u89C2\u6D4B\u8BF7\u6C42\uFF0C\u65E0\u6CD5\u8BC1\u660E\u8D26\u5355\u5B8C\u6574\u3002"
|
|
8696
|
+
},
|
|
8697
|
+
totals,
|
|
8698
|
+
stages,
|
|
8699
|
+
rates,
|
|
8700
|
+
observedBackgroundTokenShare: totalsComplete && totals.totalTokens ? backgroundTokens / totals.totalTokens : null,
|
|
8701
|
+
definitions: "operations=\u4E00\u6B21\u8BB0\u5FC6\u6A21\u578B\u64CD\u4F5C\uFF08\u542B\u5185\u90E8\u91CD\u8BD5\uFF09\uFF1BmodelCalls=\u6D41\u5F0F\u8BF7\u6C42\u5C1D\u8BD5\uFF1Bpipeline=\u73B0\u5B58\u6301\u4E45\u4EFB\u52A1\u72B6\u6001\u3002\u540E\u53F0Token\u5360\u6BD4\u4EC5\u9488\u5BF9\u5F53\u524D\u7A7A\u95F4\u5DF2\u89C2\u6D4B\u8BF7\u6C42\uFF0C\u5E38\u9A7B\u8F93\u5165\u4F30\u7B97\u5355\u5217\uFF0C\u8D39\u7528\u4E0E\u51C0\u6536\u76CA\u672A\u6D4B\u3002",
|
|
8702
|
+
routes: [...routes.values()].slice(0, 40),
|
|
8703
|
+
omittedRoutes: Math.max(0, routes.size - 40),
|
|
8704
|
+
totalRecords,
|
|
8705
|
+
nextOffset: offset + scannedRecords < totalRecords ? offset + scannedRecords : null,
|
|
8706
|
+
records: records.map(({ namespace: _namespace, detail, ...record3 }) => ({ ...record3, ...options.details && detail ? { detail } : {} }))
|
|
8707
|
+
};
|
|
8708
|
+
}
|
|
8709
|
+
close() {
|
|
8710
|
+
if (this.closed) return;
|
|
8711
|
+
if (this.timer) clearTimeout(this.timer);
|
|
8712
|
+
this.timer = void 0;
|
|
8713
|
+
this.flush();
|
|
8714
|
+
this.closed = true;
|
|
8715
|
+
try {
|
|
8716
|
+
this.database?.close();
|
|
8717
|
+
} catch {
|
|
8718
|
+
}
|
|
8719
|
+
this.database = void 0;
|
|
8720
|
+
}
|
|
8721
|
+
};
|
|
8722
|
+
async function* observeModelStream(recorder, scope, options, next) {
|
|
8723
|
+
const start = Date.now();
|
|
8724
|
+
let usage;
|
|
8725
|
+
let finished = false;
|
|
8726
|
+
let failure;
|
|
8727
|
+
let cancelled = false;
|
|
8728
|
+
scope.calls = (scope.calls ?? 0) + 1;
|
|
8729
|
+
try {
|
|
8730
|
+
for await (const chunk of next()) {
|
|
8731
|
+
if (chunk.type === "usage") usage = chunk.usage;
|
|
8732
|
+
if (chunk.type === "finish") {
|
|
8733
|
+
finished = true;
|
|
8734
|
+
if (chunk.reason.kind === "error" || chunk.reason.kind === "aborted") {
|
|
8735
|
+
cancelled = chunk.reason.kind === "aborted";
|
|
8736
|
+
failure = cancelled ? Object.assign(new Error(chunk.reason.failure?.message ?? "aborted"), { name: "AbortError" }) : chunk.reason.failure.message;
|
|
8737
|
+
} else if (chunk.reason.kind === "max-tokens") failure = "max-tokens";
|
|
8738
|
+
}
|
|
8739
|
+
yield chunk;
|
|
8740
|
+
}
|
|
8741
|
+
} catch (error) {
|
|
8742
|
+
failure = error;
|
|
8743
|
+
cancelled = isAbortError(error);
|
|
8744
|
+
throw error;
|
|
8745
|
+
} finally {
|
|
8746
|
+
const valid = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0;
|
|
8747
|
+
const known = usage && valid(usage.inputTokens) && valid(usage.outputTokens);
|
|
8748
|
+
const counters = {
|
|
8749
|
+
modelCalls: 1,
|
|
8750
|
+
modelFailed: failure !== void 0 && !cancelled ? 1 : 0,
|
|
8751
|
+
modelCancelled: cancelled || !finished && failure === void 0 ? 1 : 0,
|
|
8752
|
+
modelMs: Date.now() - start,
|
|
8753
|
+
usageCalls: known ? 1 : 0,
|
|
8754
|
+
missingUsageCalls: known ? 0 : 1
|
|
8755
|
+
};
|
|
8756
|
+
if (scope.stage === "chat" && scope.memoryInputEstimate !== void 0) {
|
|
8757
|
+
counters.memoryInputEstimate = scope.memoryInputEstimate;
|
|
8758
|
+
counters.memoryInputEstimateCalls = 1;
|
|
8759
|
+
}
|
|
8760
|
+
if (known && usage) {
|
|
8761
|
+
counters.inputTokens = usage.inputTokens;
|
|
8762
|
+
counters.outputTokens = usage.outputTokens;
|
|
8763
|
+
if (valid(usage.cacheReadTokens)) {
|
|
8764
|
+
counters.cacheReadTokens = usage.cacheReadTokens;
|
|
8765
|
+
counters.cacheReadKnownCalls = 1;
|
|
8766
|
+
}
|
|
8767
|
+
if (valid(usage.cacheWriteTokens)) {
|
|
8768
|
+
counters.cacheWriteTokens = usage.cacheWriteTokens;
|
|
8769
|
+
counters.cacheWriteKnownCalls = 1;
|
|
8770
|
+
}
|
|
8771
|
+
if (valid(usage.reasoningTokens)) counters.reasoningTokens = usage.reasoningTokens;
|
|
8772
|
+
if (valid(usage.totalTokens) || valid(usage.cacheReadTokens) && valid(usage.cacheWriteTokens)) {
|
|
8773
|
+
counters.totalTokens = valid(usage.totalTokens) ? usage.totalTokens : counters.inputTokens + counters.outputTokens + counters.cacheReadTokens + counters.cacheWriteTokens;
|
|
8774
|
+
counters.totalTokenCalls = 1;
|
|
8775
|
+
}
|
|
8776
|
+
}
|
|
8777
|
+
recorder.record(scope, counters, { model: `${options.provider}/${options.model}`, ...failure !== void 0 ? { error: failure } : {} });
|
|
8778
|
+
}
|
|
8779
|
+
}
|
|
8780
|
+
|
|
8524
8781
|
// src/llm.ts
|
|
8525
8782
|
var ELEMENT_TYPES2 = /* @__PURE__ */ new Set(["person", "project", "organization", "tool", "place"]);
|
|
8526
8783
|
var CRITICALITIES = /* @__PURE__ */ new Set(["routine", "preference", "identity", "safety"]);
|
|
@@ -9085,6 +9342,16 @@ var DshModelBridge = class {
|
|
|
9085
9342
|
ctx;
|
|
9086
9343
|
config;
|
|
9087
9344
|
liveStructuredReasoningEffort;
|
|
9345
|
+
diagnosticScopes = new AsyncLocalStorage();
|
|
9346
|
+
diagnostics;
|
|
9347
|
+
diagnosticNamespace = () => "@shared";
|
|
9348
|
+
setDiagnostics(recorder, namespace) {
|
|
9349
|
+
this.diagnostics = recorder;
|
|
9350
|
+
this.diagnosticNamespace = namespace;
|
|
9351
|
+
}
|
|
9352
|
+
currentDiagnosticScope() {
|
|
9353
|
+
return this.diagnosticScopes.getStore();
|
|
9354
|
+
}
|
|
9088
9355
|
contextWindows = /* @__PURE__ */ new Map();
|
|
9089
9356
|
sessions = new AsyncLocalStorage();
|
|
9090
9357
|
successfulResponses = [];
|
|
@@ -9117,8 +9384,8 @@ var DshModelBridge = class {
|
|
|
9117
9384
|
run(session, operation) {
|
|
9118
9385
|
return this.sessions.run({ session, sessionId: session.id }, operation);
|
|
9119
9386
|
}
|
|
9120
|
-
runDetached(sessionId, operation, signal) {
|
|
9121
|
-
return this.sessions.run({ sessionId, ...signal ? { signal } : {} }, operation);
|
|
9387
|
+
runDetached(sessionId, operation, signal, namespace) {
|
|
9388
|
+
return this.sessions.run({ sessionId, ...signal ? { signal } : {}, ...namespace ? { namespace } : {} }, operation);
|
|
9122
9389
|
}
|
|
9123
9390
|
dreamingModelOptions() {
|
|
9124
9391
|
return { ...this.resolveRoute(), maxTokens: TOPIC_OUTPUT_TOKEN_BUDGET };
|
|
@@ -9399,6 +9666,40 @@ Use project scope for repository decisions, user scope for stable preferences/id
|
|
|
9399
9666
|
return proposed;
|
|
9400
9667
|
}
|
|
9401
9668
|
async callStructured(kind, system, payload, validate, topicMetadata) {
|
|
9669
|
+
const execution = this.sessions.getStore();
|
|
9670
|
+
const scope = {
|
|
9671
|
+
namespace: execution?.namespace ?? this.diagnosticNamespace(execution?.session, String(execution?.sessionId ?? "")),
|
|
9672
|
+
stage: kind,
|
|
9673
|
+
taskId: `task_${randomUUID4()}`,
|
|
9674
|
+
calls: 0
|
|
9675
|
+
};
|
|
9676
|
+
const start = Date.now();
|
|
9677
|
+
return this.diagnosticScopes.run(scope, async () => {
|
|
9678
|
+
try {
|
|
9679
|
+
const result = await this.callStructuredInner(kind, system, payload, validate, topicMetadata);
|
|
9680
|
+
this.diagnostics?.record(scope, {
|
|
9681
|
+
operations: 1,
|
|
9682
|
+
operationsSucceeded: 1,
|
|
9683
|
+
operationsFailed: 0,
|
|
9684
|
+
operationsRecovered: (scope.calls ?? 0) > 1 ? 1 : 0,
|
|
9685
|
+
firstAttemptSucceeded: (scope.calls ?? 0) === 1 ? 1 : 0,
|
|
9686
|
+
retries: Math.max(0, (scope.calls ?? 0) - 1),
|
|
9687
|
+
operationMs: Date.now() - start
|
|
9688
|
+
});
|
|
9689
|
+
return result;
|
|
9690
|
+
} catch (error) {
|
|
9691
|
+
this.diagnostics?.record(scope, {
|
|
9692
|
+
operations: 1,
|
|
9693
|
+
operationsSucceeded: 0,
|
|
9694
|
+
operationsFailed: 1,
|
|
9695
|
+
retries: Math.max(0, (scope.calls ?? 0) - 1),
|
|
9696
|
+
operationMs: Date.now() - start
|
|
9697
|
+
}, { error });
|
|
9698
|
+
throw error;
|
|
9699
|
+
}
|
|
9700
|
+
});
|
|
9701
|
+
}
|
|
9702
|
+
async callStructuredInner(kind, system, payload, validate, topicMetadata) {
|
|
9402
9703
|
const execution = this.sessions.getStore();
|
|
9403
9704
|
if (!execution) throw new Error("StrataGate model callback ran without an execution context");
|
|
9404
9705
|
const baseRoute = this.resolveRoute(execution.session);
|
|
@@ -9633,6 +9934,8 @@ Correct these canonical-name provenance fields: ${[...new Set(paths)].slice(0, 2
|
|
|
9633
9934
|
return parsed;
|
|
9634
9935
|
} catch (error) {
|
|
9635
9936
|
if (!(error instanceof ModelJsonResponseError) && !(isTopic && error instanceof TopicProjectionError)) throw error;
|
|
9937
|
+
const scope = this.diagnosticScopes.getStore();
|
|
9938
|
+
if (scope) this.diagnostics?.record(scope, { validationFailures: 1 }, { error });
|
|
9636
9939
|
let retryError = error;
|
|
9637
9940
|
if (isTopic && error instanceof TopicProjectionError) {
|
|
9638
9941
|
const safe = new TopicProjectionError(error.diagnostics.category, error.diagnostics.reason, { ...topicDiagnostics, ...error.diagnostics });
|
|
@@ -9734,7 +10037,9 @@ Correct the previous Topic output using these validation errors: ${JSON.stringif
|
|
|
9734
10037
|
try {
|
|
9735
10038
|
await Promise.race([
|
|
9736
10039
|
(async () => {
|
|
9737
|
-
|
|
10040
|
+
const scope = this.diagnosticScopes.getStore();
|
|
10041
|
+
const stream = this.diagnostics && scope ? observeModelStream(this.diagnostics, scope, timedRequest, () => this.ctx.llm.stream(timedRequest)) : this.ctx.llm.stream(timedRequest);
|
|
10042
|
+
for await (const chunk of stream) assembler.push(chunk);
|
|
9738
10043
|
})(),
|
|
9739
10044
|
timeout,
|
|
9740
10045
|
aborted
|
|
@@ -9776,7 +10081,7 @@ function isOffRejection(error) {
|
|
|
9776
10081
|
}
|
|
9777
10082
|
|
|
9778
10083
|
// src/metadata.ts
|
|
9779
|
-
import { DatabaseSync as
|
|
10084
|
+
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
9780
10085
|
var TOPIC_BOOTSTRAP_WINDOW_MS = 10 * 6e4;
|
|
9781
10086
|
var TOPIC_BOOTSTRAP_WINDOW_CALLS = 2;
|
|
9782
10087
|
var METADATA_SCHEMA = `
|
|
@@ -9799,7 +10104,7 @@ CREATE TABLE IF NOT EXISTS stratagate_dsh_feedback_drafts (
|
|
|
9799
10104
|
) STRICT;
|
|
9800
10105
|
`;
|
|
9801
10106
|
function dropLegacyAgentMemoriesTable(filename) {
|
|
9802
|
-
const database = new
|
|
10107
|
+
const database = new DatabaseSync3(filename);
|
|
9803
10108
|
try {
|
|
9804
10109
|
const legacyTable = database.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'stratagate_dsh_agent_memories'").get();
|
|
9805
10110
|
if (!legacyTable) return;
|
|
@@ -9812,7 +10117,7 @@ function dropLegacyAgentMemoriesTable(filename) {
|
|
|
9812
10117
|
var DshMetadataStore = class {
|
|
9813
10118
|
database;
|
|
9814
10119
|
constructor(filename) {
|
|
9815
|
-
this.database = new
|
|
10120
|
+
this.database = new DatabaseSync3(filename);
|
|
9816
10121
|
this.database.exec(METADATA_SCHEMA);
|
|
9817
10122
|
}
|
|
9818
10123
|
/** Database-wide, durable reservation before any historical model attempt.
|
|
@@ -9942,15 +10247,10 @@ var DshMetadataStore = class {
|
|
|
9942
10247
|
};
|
|
9943
10248
|
|
|
9944
10249
|
// src/runtime.ts
|
|
9945
|
-
import { createHash as createHash3, randomUUID as
|
|
9946
|
-
|
|
9947
|
-
// src/feedback-policy.ts
|
|
9948
|
-
var AGENT_FEEDBACK_ENABLED = false;
|
|
9949
|
-
|
|
9950
|
-
// src/runtime.ts
|
|
10250
|
+
import { createHash as createHash3, randomUUID as randomUUID5 } from "node:crypto";
|
|
9951
10251
|
import { existsSync } from "node:fs";
|
|
9952
10252
|
import { dirname, resolve as resolve2 } from "node:path";
|
|
9953
|
-
import { DatabaseSync as
|
|
10253
|
+
import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
|
|
9954
10254
|
import { createUserMessage as createUserMessage2 } from "@deepseek-ai/dsh-llm";
|
|
9955
10255
|
import { openNativePath } from "@deepseek-ai/dsh-native-command";
|
|
9956
10256
|
import { validateArgs as validateArgs2 } from "@deepseek-ai/dsh-tools";
|
|
@@ -10507,7 +10807,6 @@ function graphProjectionCanRun(job, now = Date.now()) {
|
|
|
10507
10807
|
var AUTO_EVENT_LIMIT = 4;
|
|
10508
10808
|
var AUTO_ELEMENT_LIMIT = 4;
|
|
10509
10809
|
var AUTO_MEMORY_TOKEN_BUDGET = 900;
|
|
10510
|
-
var FEEDBACK_PROMPT_COOLDOWN_MS = 5 * 24 * 60 * 60 * 1e3;
|
|
10511
10810
|
function projectKey(cwd) {
|
|
10512
10811
|
const canonical2 = resolve2(cwd ?? process.cwd()).replaceAll("\\", "/").toLowerCase();
|
|
10513
10812
|
return createHash3("sha256").update(canonical2).digest("hex").slice(0, 20);
|
|
@@ -10590,6 +10889,8 @@ function normalizeFeedbackDraft(input, previous) {
|
|
|
10590
10889
|
expected: replacesStructuredBody ? "" : has("expected") ? feedbackText(input.expected, 1e4) : previous?.expected ?? "",
|
|
10591
10890
|
actual: replacesStructuredBody ? "" : has("actual") ? feedbackText(input.actual, 1e4) : previous?.actual ?? "",
|
|
10592
10891
|
errorContext: replacesStructuredBody ? "" : has("errorContext") ? feedbackText(input.errorContext, 2e4) : previous?.errorContext ?? "",
|
|
10892
|
+
...previous?.aiPrepared ? { aiPrepared: true } : {},
|
|
10893
|
+
...previous?.diagnostics ? { diagnostics: previous.diagnostics } : {},
|
|
10593
10894
|
...bodyMarkdown ? { bodyMarkdown } : {},
|
|
10594
10895
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10595
10896
|
};
|
|
@@ -10613,6 +10914,8 @@ var StrataGateRuntime = class {
|
|
|
10613
10914
|
this.flushNativeSession = flushNativeSession;
|
|
10614
10915
|
this.feedbackOrigin = feedbackOrigin;
|
|
10615
10916
|
this.openPath = openPath;
|
|
10917
|
+
this.diagnostics = new DiagnosticsRecorder(config.database);
|
|
10918
|
+
this.models.setDiagnostics?.(this.diagnostics, (session, sessionId) => session ? this.namespaceFor(session) : this.diagnosticNamespaceForSession(sessionId ?? "") ?? "@shared");
|
|
10616
10919
|
this.blockTurnSize = config.blockTurnSize;
|
|
10617
10920
|
this.blockDecayLambda = config.blockDecayLambda;
|
|
10618
10921
|
this.agentMemoryRetrievalWeight = config.agentMemoryRetrievalWeight ?? 1;
|
|
@@ -10626,6 +10929,9 @@ var StrataGateRuntime = class {
|
|
|
10626
10929
|
flushNativeSession;
|
|
10627
10930
|
feedbackOrigin;
|
|
10628
10931
|
openPath;
|
|
10932
|
+
diagnostics;
|
|
10933
|
+
diagnosticSessionNamespaces = /* @__PURE__ */ new Map();
|
|
10934
|
+
diagnosticMemoryEstimates = /* @__PURE__ */ new Map();
|
|
10629
10935
|
profileStorage;
|
|
10630
10936
|
folder = new TurnFolder();
|
|
10631
10937
|
spaces = /* @__PURE__ */ new Map();
|
|
@@ -10642,11 +10948,10 @@ var StrataGateRuntime = class {
|
|
|
10642
10948
|
externalImportRuns = /* @__PURE__ */ new Map();
|
|
10643
10949
|
dreamingRuns = /* @__PURE__ */ new Map();
|
|
10644
10950
|
dreamingControllers = /* @__PURE__ */ new Map();
|
|
10645
|
-
dreamingOwner =
|
|
10951
|
+
dreamingOwner = randomUUID5();
|
|
10646
10952
|
dreamingHost;
|
|
10647
10953
|
adminJobRetryRuns = /* @__PURE__ */ new Map();
|
|
10648
10954
|
feedbackDrafts = /* @__PURE__ */ new Map();
|
|
10649
|
-
pendingFeedbackSuggestionSessions = /* @__PURE__ */ new Set();
|
|
10650
10955
|
pendingTurns = /* @__PURE__ */ new Map();
|
|
10651
10956
|
drainTimers = /* @__PURE__ */ new Map();
|
|
10652
10957
|
drainBackoffMs = /* @__PURE__ */ new Map();
|
|
@@ -10666,7 +10971,6 @@ var StrataGateRuntime = class {
|
|
|
10666
10971
|
blockTurnSize;
|
|
10667
10972
|
blockDecayLambda;
|
|
10668
10973
|
agentMemoryRetrievalWeight;
|
|
10669
|
-
transientLastFeedbackPromptAt = null;
|
|
10670
10974
|
get agentMemoryEnabled() {
|
|
10671
10975
|
return this.config.agentMemoryEnabled !== false;
|
|
10672
10976
|
}
|
|
@@ -10827,7 +11131,9 @@ var StrataGateRuntime = class {
|
|
|
10827
11131
|
}
|
|
10828
11132
|
}
|
|
10829
11133
|
return resumed2;
|
|
10830
|
-
}
|
|
11134
|
+
},
|
|
11135
|
+
void 0,
|
|
11136
|
+
namespace
|
|
10831
11137
|
);
|
|
10832
11138
|
await this.persistSuccessfulResponses(memory);
|
|
10833
11139
|
const sessionsToSync = /* @__PURE__ */ new Set();
|
|
@@ -11200,6 +11506,12 @@ var StrataGateRuntime = class {
|
|
|
11200
11506
|
}
|
|
11201
11507
|
const memory = await this.space(session);
|
|
11202
11508
|
const assessment = memory.assessRetrieval(input, new Set(batch.refs.keys()));
|
|
11509
|
+
this.diagnostics.record({ namespace: this.namespaceFor(session), stage: "retrieval" }, {
|
|
11510
|
+
assessments: 1,
|
|
11511
|
+
sufficient: assessment.verdict === "sufficient" ? 1 : 0,
|
|
11512
|
+
partial: assessment.verdict === "partial" ? 1 : 0,
|
|
11513
|
+
wrong: assessment.verdict === "wrong" ? 1 : 0
|
|
11514
|
+
});
|
|
11203
11515
|
batch.assessment = assessment;
|
|
11204
11516
|
return {
|
|
11205
11517
|
batchId: batch.id,
|
|
@@ -11516,10 +11828,10 @@ var StrataGateRuntime = class {
|
|
|
11516
11828
|
await Promise.allSettled(this.externalImportRuns.values());
|
|
11517
11829
|
await Promise.allSettled(this.dreamingRuns.values());
|
|
11518
11830
|
await this.dreamingHost?.close();
|
|
11831
|
+
this.diagnostics.close();
|
|
11519
11832
|
await Promise.all(settled.flatMap((result) => result.status === "fulfilled" ? [result.value.close()] : []));
|
|
11520
11833
|
if (this.profileStorage) await this.profileStorage.close();
|
|
11521
11834
|
this.sessionsById.clear();
|
|
11522
|
-
this.pendingFeedbackSuggestionSessions.clear();
|
|
11523
11835
|
if (flushError !== void 0) throw flushError;
|
|
11524
11836
|
}
|
|
11525
11837
|
namespaceFor(session) {
|
|
@@ -11528,10 +11840,75 @@ var StrataGateRuntime = class {
|
|
|
11528
11840
|
if (this.config.namespaceMode === "session") return `${prefix}:session:${String(session.id)}`;
|
|
11529
11841
|
return `${prefix}:project:${projectKey(session.header.cwd)}`;
|
|
11530
11842
|
}
|
|
11843
|
+
trackDiagnosticSession(sessionId, namespace, memoryInputEstimate) {
|
|
11844
|
+
this.diagnosticSessionNamespaces.set(sessionId, namespace);
|
|
11845
|
+
if (memoryInputEstimate !== void 0) this.diagnosticMemoryEstimates.set(sessionId, memoryInputEstimate);
|
|
11846
|
+
if (this.diagnosticSessionNamespaces.size > 256) {
|
|
11847
|
+
const oldest = this.diagnosticSessionNamespaces.keys().next().value;
|
|
11848
|
+
this.diagnosticSessionNamespaces.delete(oldest);
|
|
11849
|
+
this.diagnosticMemoryEstimates.delete(oldest);
|
|
11850
|
+
}
|
|
11851
|
+
}
|
|
11852
|
+
diagnosticMemoryEstimate(sessionId) {
|
|
11853
|
+
return this.diagnosticMemoryEstimates.get(sessionId);
|
|
11854
|
+
}
|
|
11855
|
+
diagnosticNamespaceForSession(sessionId) {
|
|
11856
|
+
const session = this.knownSessions.get(sessionId)?.deref();
|
|
11857
|
+
return session ? this.namespaceFor(session) : this.diagnosticSessionNamespaces.get(sessionId);
|
|
11858
|
+
}
|
|
11859
|
+
async diagnosticReport(namespace, options = {}) {
|
|
11860
|
+
const collected = this.diagnostics.snapshot(namespace, options);
|
|
11861
|
+
const shared = this.diagnostics.snapshot("@shared");
|
|
11862
|
+
const base = { ...collected, sharedOrUnattributed: {
|
|
11863
|
+
stages: shared.stages,
|
|
11864
|
+
note: "\u6570\u636E\u5E93\u5171\u4EAB\u753B\u50CF\u7EF4\u62A4\u6216\u65E0\u6CD5\u5F52\u5C5E\u7684\u6A21\u578B\u64CD\u4F5C\uFF0C\u5355\u5217\u5C55\u793A\uFF0C\u672A\u5206\u644A\u5230\u5F53\u524D\u5DE5\u4F5C\u533A\u3002"
|
|
11865
|
+
} };
|
|
11866
|
+
try {
|
|
11867
|
+
const snapshot = await this.adminSnapshot(namespace);
|
|
11868
|
+
if (!snapshot) return { ...base, pipeline: { available: false } };
|
|
11869
|
+
const stages = {
|
|
11870
|
+
summarizer: snapshot.summaryJobs,
|
|
11871
|
+
extractor: snapshot.extractionJobs,
|
|
11872
|
+
graphProjector: snapshot.graphProjectionJobs,
|
|
11873
|
+
topicProjector: (snapshot.memoryTopicState?.jobs ?? []).filter((job) => !job.superseded),
|
|
11874
|
+
externalMemoryImport: snapshot.externalMemoryImportJobs
|
|
11875
|
+
};
|
|
11876
|
+
const pipeline = Object.fromEntries(Object.entries(stages).map(([stage, jobs]) => [stage, {
|
|
11877
|
+
total: jobs.length,
|
|
11878
|
+
failed: jobs.filter((j) => j.status === "failed").length,
|
|
11879
|
+
succeeded: jobs.filter((j) => ["succeeded", "completed"].includes(j.status)).length,
|
|
11880
|
+
skipped: jobs.filter((j) => j.status === "skipped").length,
|
|
11881
|
+
pending: jobs.filter((j) => ["pending", "running", "processing", "extracting", "deciding"].includes(j.status)).length,
|
|
11882
|
+
oldestPendingUpdatedAt: jobs.filter((j) => ["pending", "running", "processing"].includes(j.status)).map((j) => j.updatedAt).sort()[0] ?? null
|
|
11883
|
+
}]));
|
|
11884
|
+
const adoptions = snapshot.usageReceipts.filter((r) => r.createdAt >= collected.since);
|
|
11885
|
+
const adopted = adoptions.filter((r) => r.eventIds.length > 0 || r.elementIds.length > 0);
|
|
11886
|
+
const sampledBlocks = snapshot.blocks.slice(-64);
|
|
11887
|
+
const layerTokenEstimates = Object.fromEntries([0, 1, 2, 3, 4, 5].map((level) => [
|
|
11888
|
+
`L${level}`,
|
|
11889
|
+
sampledBlocks.reduce((sum, block) => sum + estimateTokens(renderBlock(block, level)), 0)
|
|
11890
|
+
]));
|
|
11891
|
+
return { ...base, pipeline: { available: true, stages: pipeline }, benefits: {
|
|
11892
|
+
retrievalReceipts: adoptions.length,
|
|
11893
|
+
adoptionReceipts: adopted.length,
|
|
11894
|
+
adoptedEvents: adopted.reduce((n, r) => n + r.eventIds.length, 0),
|
|
11895
|
+
blocks: snapshot.blocks.length,
|
|
11896
|
+
events: snapshot.events.length,
|
|
11897
|
+
graphNodes: snapshot.graphNodes.length,
|
|
11898
|
+
sampledBlocks: sampledBlocks.length,
|
|
11899
|
+
layerTokenEstimates,
|
|
11900
|
+
note: "\u5206\u5C42Token\u4E3A\u6700\u8FD1\u6700\u591A64\u4E2A\u5B58\u50A8\u5757\u7684\u5185\u5BB9\u4F53\u79EF\u4F30\u7B97\uFF0C\u5404\u4F1A\u8BDD\u5B9E\u9645\u5C42\u7EA7\u4E0D\u540C\uFF1B\u91C7\u7528\u6B21\u6570\u4E0E\u5185\u5BB9\u538B\u7F29\u6BD4\u4F8B\u4E0D\u7B49\u4E8E\u7B54\u6848\u8D28\u91CF\u6216\u8D26\u5355\u51C0\u6536\u76CA\u3002"
|
|
11901
|
+
} };
|
|
11902
|
+
} catch {
|
|
11903
|
+
return { ...base, pipeline: { available: false } };
|
|
11904
|
+
}
|
|
11905
|
+
}
|
|
11531
11906
|
async prepareFeedback(session, input) {
|
|
11532
11907
|
const namespace = this.namespaceFor(session);
|
|
11533
|
-
const previous = this.loadFeedbackDraft(namespace);
|
|
11908
|
+
const previous = input.newDraft ? null : this.loadFeedbackDraft(namespace);
|
|
11534
11909
|
const draft = normalizeFeedbackDraft(input, previous);
|
|
11910
|
+
draft.aiPrepared = true;
|
|
11911
|
+
draft.diagnostics = await this.diagnosticReport(namespace);
|
|
11535
11912
|
this.saveFeedbackDraft(namespace, draft);
|
|
11536
11913
|
const feedbackUrl = feedbackDraftUrl(namespace, this.feedbackOrigin());
|
|
11537
11914
|
return {
|
|
@@ -11540,7 +11917,7 @@ var StrataGateRuntime = class {
|
|
|
11540
11917
|
submitted: false,
|
|
11541
11918
|
namespace,
|
|
11542
11919
|
feedbackUrl,
|
|
11543
|
-
message: `\u53CD\u9988\u8349\u7A3F\u5DF2\
|
|
11920
|
+
message: `\u53CD\u9988\u8349\u7A3F\u5DF2\u4FDD\u5B58\u5728\u672C\u5730\uFF0C\u90AE\u4EF6\u5C1A\u672A\u53D1\u9001\u3002
|
|
11544
11921
|
|
|
11545
11922
|
[\u6253\u5F00\u53CD\u9988\u8349\u7A3F](${feedbackUrl})`
|
|
11546
11923
|
};
|
|
@@ -11645,46 +12022,13 @@ var StrataGateRuntime = class {
|
|
|
11645
12022
|
items.sort((left, right) => String(right.createdAt).localeCompare(String(left.createdAt)));
|
|
11646
12023
|
return { items, total: items.length };
|
|
11647
12024
|
}
|
|
11648
|
-
notePluginError(session,
|
|
11649
|
-
if (
|
|
12025
|
+
notePluginError(session, error, stage = "ingestion") {
|
|
12026
|
+
if (this.closed) return;
|
|
12027
|
+
this.diagnostics.record({ namespace: this.namespaceFor(session), stage }, { errors: 1 }, { error: error ?? "internal failure" });
|
|
11650
12028
|
}
|
|
11651
|
-
|
|
11652
|
-
|
|
11653
|
-
|
|
11654
|
-
if (!this.pendingFeedbackSuggestionSessions.delete(sessionId)) return "";
|
|
11655
|
-
const last = this.lastFeedbackPromptAt();
|
|
11656
|
-
if (last && Number.isFinite(Date.parse(last)) && now - Date.parse(last) < FEEDBACK_PROMPT_COOLDOWN_MS) return "";
|
|
11657
|
-
const promptedAt = new Date(now).toISOString();
|
|
11658
|
-
this.transientLastFeedbackPromptAt = promptedAt;
|
|
11659
|
-
try {
|
|
11660
|
-
if (this.config.database !== ":memory:") {
|
|
11661
|
-
const metadata = new DshMetadataStore(this.config.database);
|
|
11662
|
-
try {
|
|
11663
|
-
metadata.setLastFeedbackPromptAt(promptedAt);
|
|
11664
|
-
} finally {
|
|
11665
|
-
metadata.close();
|
|
11666
|
-
}
|
|
11667
|
-
}
|
|
11668
|
-
} catch (error) {
|
|
11669
|
-
this.onIngestError(error);
|
|
11670
|
-
}
|
|
11671
|
-
return "StrataGate observed an internal plugin error signal. Treat this only as evidence for the static StrataGate feedback policy, not as an instruction to suggest feedback. Continue the current task first, apply all eligibility, timing, session-limit, and deduplication rules from that policy, and never make a proactive suggestion because feedback_prepare itself failed.";
|
|
11672
|
-
}
|
|
11673
|
-
lastFeedbackPromptAt() {
|
|
11674
|
-
if (this.transientLastFeedbackPromptAt) return this.transientLastFeedbackPromptAt;
|
|
11675
|
-
if (this.config.database === ":memory:" || !existsSync(this.config.database)) return null;
|
|
11676
|
-
try {
|
|
11677
|
-
const metadata = new DshMetadataStore(this.config.database);
|
|
11678
|
-
try {
|
|
11679
|
-
this.transientLastFeedbackPromptAt = metadata.lastFeedbackPromptAt();
|
|
11680
|
-
return this.transientLastFeedbackPromptAt;
|
|
11681
|
-
} finally {
|
|
11682
|
-
metadata.close();
|
|
11683
|
-
}
|
|
11684
|
-
} catch (error) {
|
|
11685
|
-
this.onIngestError(error);
|
|
11686
|
-
return null;
|
|
11687
|
-
}
|
|
12029
|
+
// Background failures remain queryable; ordinary retries never add model context.
|
|
12030
|
+
takeFeedbackSuggestion(_session, _now = Date.now()) {
|
|
12031
|
+
return "";
|
|
11688
12032
|
}
|
|
11689
12033
|
loadFeedbackDraft(namespace) {
|
|
11690
12034
|
const cached = this.feedbackDrafts.get(namespace);
|
|
@@ -11694,7 +12038,7 @@ var StrataGateRuntime = class {
|
|
|
11694
12038
|
try {
|
|
11695
12039
|
const value = metadata.feedbackDraft(namespace);
|
|
11696
12040
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
11697
|
-
const draft = normalizeFeedbackDraft(value);
|
|
12041
|
+
const draft = normalizeFeedbackDraft(value, value);
|
|
11698
12042
|
this.feedbackDrafts.set(namespace, draft);
|
|
11699
12043
|
return structuredClone(draft);
|
|
11700
12044
|
} finally {
|
|
@@ -11702,14 +12046,15 @@ var StrataGateRuntime = class {
|
|
|
11702
12046
|
}
|
|
11703
12047
|
}
|
|
11704
12048
|
saveFeedbackDraft(namespace, draft) {
|
|
11705
|
-
this.
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
12049
|
+
if (this.config.database !== ":memory:") {
|
|
12050
|
+
const metadata = new DshMetadataStore(this.config.database);
|
|
12051
|
+
try {
|
|
12052
|
+
metadata.setFeedbackDraft(namespace, draft);
|
|
12053
|
+
} finally {
|
|
12054
|
+
metadata.close();
|
|
12055
|
+
}
|
|
11712
12056
|
}
|
|
12057
|
+
this.feedbackDrafts.set(namespace, structuredClone(draft));
|
|
11713
12058
|
}
|
|
11714
12059
|
async adminNamespaces() {
|
|
11715
12060
|
if (this.config.database === ":memory:" || !existsSync(this.config.database)) return [];
|
|
@@ -11964,7 +12309,7 @@ var StrataGateRuntime = class {
|
|
|
11964
12309
|
} finally {
|
|
11965
12310
|
if (owned) await memory.close();
|
|
11966
12311
|
}
|
|
11967
|
-
const action = await this.models.runDetached(`dreaming:${run.id}`, () => this.models.dreamingStep(payload), controller.signal);
|
|
12312
|
+
const action = await this.models.runDetached(`dreaming:${run.id}`, () => this.models.dreamingStep(payload), controller.signal, namespace);
|
|
11968
12313
|
if (controller.signal.aborted) return;
|
|
11969
12314
|
const repeated = run.trace.filter((entry) => entry.tool === action.tool && JSON.stringify(entry.args) === JSON.stringify(action.args)).length;
|
|
11970
12315
|
if (repeated >= 3) {
|
|
@@ -12058,7 +12403,7 @@ var StrataGateRuntime = class {
|
|
|
12058
12403
|
}
|
|
12059
12404
|
try {
|
|
12060
12405
|
if (job.status === "extracting") {
|
|
12061
|
-
const recovered = await this.models.runDetached(`admin-import-recovery:${jobId}`, () => this.models.externalMemoryExtractor({ text: job.text, importedAt: job.importedAt }));
|
|
12406
|
+
const recovered = await this.models.runDetached(`admin-import-recovery:${jobId}`, () => this.models.externalMemoryExtractor({ text: job.text, importedAt: job.importedAt }), void 0, namespace);
|
|
12062
12407
|
const responses2 = this.takeSuccessfulResponses();
|
|
12063
12408
|
await this.retryExternalImportWrite(namespace, (memory) => memory.completeExternalMemoryFallback(jobId, recovered));
|
|
12064
12409
|
await this.persistExternalImportResponses(namespace, responses2);
|
|
@@ -12073,7 +12418,7 @@ var StrataGateRuntime = class {
|
|
|
12073
12418
|
decision = await this.models.runDetached(`admin-import:${jobId}`, () => this.models.externalMemoryDecider({
|
|
12074
12419
|
candidate: structuredClone(work.candidate),
|
|
12075
12420
|
matches: structuredClone(work.matches)
|
|
12076
|
-
}));
|
|
12421
|
+
}), void 0, namespace);
|
|
12077
12422
|
responses = this.takeSuccessfulResponses();
|
|
12078
12423
|
}
|
|
12079
12424
|
await this.retryExternalImportWrite(namespace, (memory) => memory.completeNextExternalMemoryImport(
|
|
@@ -12214,7 +12559,7 @@ var StrataGateRuntime = class {
|
|
|
12214
12559
|
const remembered = this.workspaceNames.get(namespace);
|
|
12215
12560
|
if (remembered) return remembered;
|
|
12216
12561
|
if (this.config.database === ":memory:" || !existsSync(this.config.database)) return null;
|
|
12217
|
-
const database = new
|
|
12562
|
+
const database = new DatabaseSync4(this.config.database, { readOnly: true });
|
|
12218
12563
|
try {
|
|
12219
12564
|
if (!database.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'stratagate_dsh_workspaces'").get()) {
|
|
12220
12565
|
return null;
|
|
@@ -12344,7 +12689,7 @@ var StrataGateRuntime = class {
|
|
|
12344
12689
|
if (!this.models.isReady(session)) {
|
|
12345
12690
|
throw new Error("StrataGate model adapter is not ready; retry after DSH finishes registering adapters");
|
|
12346
12691
|
}
|
|
12347
|
-
const result = session && this.namespaceFor(session) === key ? await this.models.run(session, retry) : await this.models.runDetached(threadId, retry);
|
|
12692
|
+
const result = session && this.namespaceFor(session) === key ? await this.models.run(session, retry) : await this.models.runDetached(threadId, retry, void 0, namespace);
|
|
12348
12693
|
await this.persistSuccessfulResponses(memory);
|
|
12349
12694
|
const currentBlock = blockId ? memory.listBlocks().find(({ id: candidateId }) => candidateId === blockId) : void 0;
|
|
12350
12695
|
if (kind !== "graph-projection" && currentBlock?.processingStatus === "ready" && currentBlock.threadId) {
|
|
@@ -12719,6 +13064,12 @@ var StrataGateRuntime = class {
|
|
|
12719
13064
|
}
|
|
12720
13065
|
sessionBatches.set(id, { id, sequence, refs, status: "unresolved" });
|
|
12721
13066
|
this.latestBatchIds.set(key, id);
|
|
13067
|
+
this.diagnostics.record({ namespace: this.namespaceFor(session), stage: "retrieval" }, {
|
|
13068
|
+
batches: 1,
|
|
13069
|
+
emptyBatches: evidence.length === 0 ? 1 : 0,
|
|
13070
|
+
returnedRefs: refs.size,
|
|
13071
|
+
resultTokensEstimate: estimateTokens(JSON.stringify(output))
|
|
13072
|
+
});
|
|
12722
13073
|
return output;
|
|
12723
13074
|
}
|
|
12724
13075
|
requireBatch(session, batchId, operation) {
|
|
@@ -13308,6 +13659,7 @@ ${profile}
|
|
|
13308
13659
|
throw new Error("\u672A\u627E\u5230\u672C\u76EE\u5F55\u6240\u5C5E\u4F1A\u8BDD\u7684\u5DE5\u4F5C\u533A\u8DEF\u5F84\uFF0C\u8BF7\u5148\u6253\u5F00\u8BE5\u5DE5\u4F5C\u533A\u7684\u666E\u901A\u4F1A\u8BDD\u540E\u91CD\u8BD5");
|
|
13309
13660
|
}
|
|
13310
13661
|
install(scoped, binding) {
|
|
13662
|
+
this.runtime.trackDiagnosticSession(String(binding.agent.id), binding.namespace);
|
|
13311
13663
|
if (typeof scoped.tools.restrict !== "function" || typeof scoped.tools.guard !== "function" || typeof DshTools.parameterSchemaSpecToJsonSchema !== "function" || !binding.agent.session.surface?.nodes || typeof binding.agent.whenIdle !== "function") throw new Error("\u5F53\u524D DSH \u7F3A\u5C11\u5B89\u5168\u7684 Dreaming Agent \u63A5\u53E3\uFF0C\u8BF7\u5347\u7EA7\u5BBF\u4E3B\u540E\u91CD\u8BD5");
|
|
13312
13664
|
const modelTools = TOOLS.map((tool) => ({
|
|
13313
13665
|
name: tool.name,
|
|
@@ -13566,6 +13918,11 @@ ${profile}
|
|
|
13566
13918
|
|
|
13567
13919
|
// src/tools.ts
|
|
13568
13920
|
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
|
13921
|
+
|
|
13922
|
+
// src/feedback-policy.ts
|
|
13923
|
+
var AGENT_FEEDBACK_ENABLED = true;
|
|
13924
|
+
|
|
13925
|
+
// src/tools.ts
|
|
13569
13926
|
var jsonOutput = {
|
|
13570
13927
|
schema: { type: "json" },
|
|
13571
13928
|
render: (_args, value) => [{
|
|
@@ -13606,17 +13963,19 @@ function registerMemoryTools(ctx, runtime) {
|
|
|
13606
13963
|
}));
|
|
13607
13964
|
if (AGENT_FEEDBACK_ENABLED) ctx.tools.register(defineTool2({
|
|
13608
13965
|
name: "feedback_prepare",
|
|
13609
|
-
description:
|
|
13966
|
+
description: "This tool is provided by the StrataGate plugin. \u6574\u7406 StrataGate \u63D2\u4EF6\u7684\u6545\u969C\u3001\u4F7F\u7528\u7591\u95EE\u548C\u6539\u8FDB\u5EFA\u8BAE\uFF0C\u751F\u6210\u672C\u5730\u90AE\u4EF6\u53CD\u9988\u8349\u7A3F\u5E76\u81EA\u52A8\u9644\u5E26\u8FD0\u884C\u6458\u8981\u3002\u7528\u6237\u76F4\u63A5\u8981\u6C42\u53EF\u8C03\u7528\uFF1B\u4E3B\u52A8\u5EFA\u8BAE\u987B\u5148\u83B7\u540C\u610F\u3002\u4F9D\u636E\u5F53\u524D\u4F1A\u8BDD\u4E8B\u5B9E\u586B\u5199\uFF0C\u672A\u77E5\u7559\u7A7A\uFF0C\u53BB\u9664\u51ED\u636E\u3002\u7701\u7565\u5B57\u6BB5\u4FDD\u7559\u539F\u503C\uFF0C\u7A7A\u5B57\u7B26\u4E32\u6216\u7A7A\u6570\u7EC4\u6E05\u7A7A\uFF1B\u65B0\u95EE\u9898\u4F20 new_draft=true\u3002\u6210\u529F\u540E\u8BF4\u660E\u8349\u7A3F\u5728\u672C\u5730\u3001\u90AE\u4EF6\u5C1A\u672A\u53D1\u9001\uFF0C\u5E76\u5C06 feedbackUrl \u663E\u793A\u4E3A\u201C\u6253\u5F00\u53CD\u9988\u8349\u7A3F\u201D\u94FE\u63A5\uFF0C\u4F9B\u7528\u6237\u68C0\u67E5\u540E\u624B\u52A8\u53D1\u90AE\u4EF6\u3002",
|
|
13610
13967
|
parameters: {
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13968
|
+
new_draft: { type: "boolean", description: "\u65B0\u95EE\u9898\u4E3A true\uFF1B\u4FEE\u6539\u5DF2\u6709\u8349\u7A3F\u65F6\u7701\u7565\u3002" },
|
|
13969
|
+
title: { type: "string", description: "\u7B80\u77ED\u95EE\u9898\u6807\u9898\u3002" },
|
|
13970
|
+
description: { type: "string", description: "\u5DF2\u77E5\u95EE\u9898\u3001\u5EFA\u8BAE\u6216\u7591\u95EE\u3002" },
|
|
13971
|
+
reproduction: { type: "array", items: { type: "string" }, description: "\u5B9E\u9645\u53D1\u751F\u8FC7\u7684\u590D\u73B0\u6B65\u9AA4\u3002" },
|
|
13972
|
+
expected: { type: "string", description: "\u5DF2\u77E5\u9884\u671F\u7ED3\u679C\u3002" },
|
|
13973
|
+
actual: { type: "string", description: "\u5B9E\u9645\u89C2\u5BDF\u5230\u7684\u7ED3\u679C\u3002" },
|
|
13974
|
+
error_context: { type: "string", description: "\u5F53\u524D\u4F1A\u8BDD\u7684\u76F8\u5173\u9519\u8BEF\uFF1B\u672C\u5730\u8BCA\u65AD\u7531\u7A0B\u5E8F\u81EA\u52A8\u8865\u5145\u3002" }
|
|
13617
13975
|
},
|
|
13618
13976
|
output: jsonOutput,
|
|
13619
13977
|
execute: async (args, exec) => runtime.prepareFeedback(sessionOf(exec), {
|
|
13978
|
+
...args.new_draft !== void 0 ? { newDraft: args.new_draft } : {},
|
|
13620
13979
|
...args.title !== void 0 ? { title: args.title } : {},
|
|
13621
13980
|
...args.description !== void 0 ? { description: args.description } : {},
|
|
13622
13981
|
...args.reproduction !== void 0 ? { reproduction: args.reproduction } : {},
|
|
@@ -13625,6 +13984,19 @@ function registerMemoryTools(ctx, runtime) {
|
|
|
13625
13984
|
...args.error_context !== void 0 ? { errorContext: args.error_context } : {}
|
|
13626
13985
|
})
|
|
13627
13986
|
}));
|
|
13987
|
+
if (AGENT_FEEDBACK_ENABLED) ctx.tools.register(defineTool2({
|
|
13988
|
+
name: "stratagate_diagnostics",
|
|
13989
|
+
description: "This tool is provided by the StrataGate plugin. \u53EA\u8BFB\u67E5\u8BE2 StrataGate \u63D2\u4EF6\u5F53\u524D\u8BB0\u5FC6\u7A7A\u95F4\u7684\u8FD0\u884C\u8BCA\u65AD\uFF1A\u8FD1\u671F\u5931\u8D25\u3001\u4EFB\u52A1\u72B6\u6001\u3001\u8017\u65F6\u3001Token \u7528\u91CF\u4E0E\u91C7\u96C6\u8986\u76D6\u5EA6\u3002\u9ED8\u8BA4\u7ED9\u6458\u8981\uFF1B\u7528\u8FD4\u56DE\u7684\u8BCA\u65AD id \u8BFB\u53D6\u8131\u654F\u9519\u8BEF\u8BE6\u60C5\uFF0Coffset \u5206\u9875\u3002\u7528\u4E8E\u6392\u67E5\u6216\u56DE\u5E94\u7528\u6237\u7591\u95EE\uFF1B\u53CD\u9988\u8349\u7A3F\u4F1A\u81EA\u52A8\u9644\u5E26\u6458\u8981\u3002",
|
|
13990
|
+
parameters: {
|
|
13991
|
+
id: { type: "string", description: "\u6458\u8981\u4E2D\u8FD4\u56DE\u7684\u8BCA\u65AD ID\uFF1B\u63D0\u4F9B\u65F6\u8BFB\u53D6\u8BE5\u6761\u8BE6\u60C5\u3002" },
|
|
13992
|
+
offset: { type: "integer", description: "\u4F7F\u7528\u8FD4\u56DE\u7684 nextOffset \u7EE7\u7EED\u8BFB\u53D6\u8FD1\u671F\u5F02\u5E38\u3002" }
|
|
13993
|
+
},
|
|
13994
|
+
output: jsonOutput,
|
|
13995
|
+
execute: async (args, exec) => runtime.diagnosticReport(runtime.namespaceFor(sessionOf(exec)), {
|
|
13996
|
+
...args.id !== void 0 ? { id: args.id, details: true } : {},
|
|
13997
|
+
...args.offset !== void 0 ? { offset: args.offset } : {}
|
|
13998
|
+
})
|
|
13999
|
+
}));
|
|
13628
14000
|
ctx.tools.register(defineTool2({
|
|
13629
14001
|
name: "memory_list_topics",
|
|
13630
14002
|
description: "This tool is provided by the StrataGate plugin. \u6D4F\u89C8\u5F53\u524D\u8BB0\u5FC6\u7A7A\u95F4\u7684\u4E3B\u9898\u76EE\u5F55\u3002\u53EF\u6309\u5206\u7C7B\u5206\u9875\uFF0C\u6216\u7528 query \u67E5\u4E3B\u9898\u540D\u79F0\u53CA\u7B80\u4ECB\u3002\u672A\u6574\u7406\u7684\u4E8B\u4EF6\u4E5F\u6709\u5165\u53E3\u3002\u76EE\u5F55\u4EC5\u4F9B\u5BFC\u822A\uFF0C\u4E0D\u521B\u5EFA\u8BC1\u636E\u6279\u6B21\uFF0C\u4E0D\u5F3A\u5316\u8BB0\u5FC6\uFF1B\u9700\u8981\u4E3B\u9898\u8109\u7EDC\u65F6\u8C03\u7528 memory_expand_topic\uFF1B\u9700\u8981\u4E8B\u5B9E\u8BC1\u636E\u53EF\u76F4\u63A5 memory_search_events(topic_id)\uFF0C\u5E76\u8BC4\u4F30\u6765\u6E90\u4E8B\u4EF6\u3002",
|
|
@@ -13803,7 +14175,7 @@ function registerMemoryTools(ctx, runtime) {
|
|
|
13803
14175
|
|
|
13804
14176
|
// src/web.ts
|
|
13805
14177
|
import { createHash as createHash4 } from "node:crypto";
|
|
13806
|
-
import { createRequire as
|
|
14178
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
13807
14179
|
|
|
13808
14180
|
// src/graph-clustering.ts
|
|
13809
14181
|
import createGraph from "ngraph.graph";
|
|
@@ -13917,7 +14289,7 @@ function clusterKnowledgeGraph(rawNodes, rawEdges) {
|
|
|
13917
14289
|
|
|
13918
14290
|
// src/web.ts
|
|
13919
14291
|
var LEGACY_THREAD_ID = "__legacy__";
|
|
13920
|
-
var nodeRequire2 =
|
|
14292
|
+
var nodeRequire2 = createRequire3(import.meta.url);
|
|
13921
14293
|
function currentPluginVersion() {
|
|
13922
14294
|
try {
|
|
13923
14295
|
const value = nodeRequire2("../package.json");
|
|
@@ -14676,7 +15048,8 @@ async function feedback(runtime, req, url) {
|
|
|
14676
15048
|
if (req.method === "GET") {
|
|
14677
15049
|
const namespace2 = url.searchParams.get("namespace")?.trim() ?? "";
|
|
14678
15050
|
if (!namespace2) throw new AdminHttpError(400, "namespace is required");
|
|
14679
|
-
|
|
15051
|
+
const result = runtime.adminFeedbackDraft(namespace2);
|
|
15052
|
+
return { ...result, diagnostics: result.draft?.diagnostics ?? await runtime.diagnosticReport?.(namespace2) };
|
|
14680
15053
|
}
|
|
14681
15054
|
if (req.method !== "PUT") throw new AdminHttpError(405, "StrataGate feedback requires GET or PUT");
|
|
14682
15055
|
let suppliedBody = req.body;
|
|
@@ -15328,6 +15701,19 @@ async function handleAdminRequest(runtime, req, res) {
|
|
|
15328
15701
|
const path = url.pathname.replace(/\/$/, "");
|
|
15329
15702
|
if (path === "/api/stratagate/feedback") {
|
|
15330
15703
|
sendJson(res, 200, await feedback(runtime, req, url));
|
|
15704
|
+
} else if (path === "/api/stratagate/diagnostics") {
|
|
15705
|
+
const namespace = url.searchParams.get("namespace")?.trim() ?? "";
|
|
15706
|
+
if (!namespace) throw new AdminHttpError(400, "namespace is required");
|
|
15707
|
+
if (req.method === "POST") {
|
|
15708
|
+
const category = url.searchParams.get("category") ?? "";
|
|
15709
|
+
if (!["timeout", "network", "request-failed"].includes(category)) throw new AdminHttpError(400, "Unknown frontend diagnostic category");
|
|
15710
|
+
runtime.diagnostics.record({ namespace, stage: "frontend" }, { errors: 1 }, { error: category });
|
|
15711
|
+
sendJson(res, 200, { recorded: true });
|
|
15712
|
+
return;
|
|
15713
|
+
}
|
|
15714
|
+
if (req.method !== "GET") throw new AdminHttpError(405, "StrataGate diagnostics require GET or POST");
|
|
15715
|
+
const id = url.searchParams.get("id") ?? void 0;
|
|
15716
|
+
sendJson(res, 200, await runtime.diagnosticReport(namespace, { ...id ? { id, details: true } : {}, offset: numeric(url.searchParams.get("offset"), 0, 0, 2e3) }));
|
|
15331
15717
|
} else if (path === "/api/stratagate/profile") {
|
|
15332
15718
|
sendJson(res, 200, await persistentProfile(runtime, req), true);
|
|
15333
15719
|
} else if (path === "/api/stratagate/settings") {
|
|
@@ -15494,7 +15880,7 @@ import {
|
|
|
15494
15880
|
writeFile
|
|
15495
15881
|
} from "node:fs/promises";
|
|
15496
15882
|
import { basename, dirname as dirname2, join } from "node:path";
|
|
15497
|
-
import { createHash as createHash5, randomUUID as
|
|
15883
|
+
import { createHash as createHash5, randomUUID as randomUUID6 } from "node:crypto";
|
|
15498
15884
|
import { encodeSeqRanges, KNOWN_SESSION_EVENT_TYPES } from "@deepseek-ai/dsh-session";
|
|
15499
15885
|
var LEGACY_EVENT_TYPE = "stratagate/memory-citations";
|
|
15500
15886
|
var COMPAT_EVENT_TYPE = "feedback/record";
|
|
@@ -15504,6 +15890,13 @@ var V0_ZSTD = "session.jsonl.zstd";
|
|
|
15504
15890
|
var V1_PLAIN = "session.v1.jsonl";
|
|
15505
15891
|
var V1_ZSTD = "session.v1.jsonl.zstd";
|
|
15506
15892
|
var RECEIPT_FILENAME = "stratagate-legacy-citations-v1.json";
|
|
15893
|
+
function assertDshMigrationContract(value) {
|
|
15894
|
+
const modules = value;
|
|
15895
|
+
assertDshMethods("releasedV0SessionFormatCodec", modules?.releasedV0SessionFormatCodec, ["createDecoder"]);
|
|
15896
|
+
assertDshMethods("releasedV1SessionFormatCodec", modules?.releasedV1SessionFormatCodec, ["decodeHeader", "createDecoder"]);
|
|
15897
|
+
assertDshMethods("sessionFormatV0ToV1", modules?.sessionFormatV0ToV1, ["migrateHeader", "createStage", "validateTargetHeader"]);
|
|
15898
|
+
assertDshMethods("sessionFormat", modules, ["restoreReleasedV1Artifact"]);
|
|
15899
|
+
}
|
|
15507
15900
|
function errorText(error) {
|
|
15508
15901
|
return error instanceof Error ? error.message : String(error);
|
|
15509
15902
|
}
|
|
@@ -15676,6 +16069,7 @@ function prepareLegacyCitationGeneration(sourceBytes, compression, modules) {
|
|
|
15676
16069
|
async function loadMigrationModules() {
|
|
15677
16070
|
try {
|
|
15678
16071
|
const edge = await import("@deepseek-ai/dsh-session-format-v0-to-v1");
|
|
16072
|
+
assertDshMigrationContract(edge);
|
|
15679
16073
|
return {
|
|
15680
16074
|
releasedV0SessionFormatCodec: edge.releasedV0SessionFormatCodec,
|
|
15681
16075
|
releasedV1SessionFormatCodec: edge.releasedV1SessionFormatCodec,
|
|
@@ -15715,7 +16109,7 @@ async function exists(path) {
|
|
|
15715
16109
|
}
|
|
15716
16110
|
async function publishExclusive(path, bytes) {
|
|
15717
16111
|
await mkdir(dirname2(path), { recursive: true });
|
|
15718
|
-
const temporary = join(dirname2(path), `.${basename(path)}.stratagate-${
|
|
16112
|
+
const temporary = join(dirname2(path), `.${basename(path)}.stratagate-${randomUUID6()}.tmp`);
|
|
15719
16113
|
const handle = await open(temporary, "wx", 384);
|
|
15720
16114
|
try {
|
|
15721
16115
|
await handle.writeFile(bytes);
|
|
@@ -15840,15 +16234,8 @@ Memory writing:
|
|
|
15840
16234
|
- Current city (currentCity) also belongs in the always-on Profile. Travel or business-trip location can be temporary while its saved value persists across sessions until the user updates or clears it; do not expire it automatically. A user request to remember their current trip city belongs here, not in retrieval-dependent memory_remember. Future trip plans, completed trips, and historical locations do not establish current whereabouts. Never copy currentCity into defaultLocation or homeCity. For local tasks use an explicit task location first, otherwise currentCity when set, then defaultLocation. Follow the same Profile consent rule for updates and clearing.
|
|
15841
16235
|
- Use memory_remember for durable project facts, past decisions, corrections, experiences, and context-specific preferences. Record one self-contained, grounded fact per call, with necessary project, time, and scope. Never record speculation, secrets, credentials, or transient task state.`;
|
|
15842
16236
|
var FEEDBACK_PROTOCOL = `[StrataGate feedback policy]
|
|
15843
|
-
|
|
15844
|
-
|
|
15845
|
-
- Consider proactively suggesting a feedback draft only when the current conversation contains a clear error signal: a tool call threw or returned an error; a result is clearly contrary to expectations and the user expresses confusion or dissatisfaction; or the same problem remains after the user retries it. Normal use, casual conversation, general complaints, and suspected problems without clear error evidence are not eligible.
|
|
15846
|
-
- An eligible error does not require a suggestion. Suggest only when the problem remains unresolved, recurs, or materially interferes with the user's task. Do not suggest for a minor failure that recovered automatically without affecting the task.
|
|
15847
|
-
- Always troubleshoot, solve the current problem, or offer a workaround first. If it cannot be solved, explain the blocker first. Only at the end of that turn may you add one unobtrusive sentence in the user's language, such as: "\u5982\u679C\u4F60\u613F\u610F\uFF0C\u6211\u53EF\u4EE5\u628A\u8FD9\u6B21\u5F02\u5E38\u6574\u7406\u6210\u53CD\u9988\u8349\u7A3F\uFF0C\u4F9B\u4F60\u68C0\u67E5\u540E\u81EA\u884C\u63D0\u4EA4\u3002" Do not use a popup, heading, interactive-question tool, or interruption for the suggestion.
|
|
15848
|
-
- Across the entire current conversation, make at most one proactive feedback suggestion in total, across all namespaces and problems. The suggestion consumes this allowance as soon as it is sent, whether the user accepts, declines, or does not reply. Use the conversation history to remember this; do not expose internal tracking or claim a cross-conversation, daily, or persistent limit.
|
|
15849
|
-
- A user's direct request to create or revise feedback is not a proactive suggestion, does not consume that allowance, and is not restricted by it. Necessary clarification for that request is also allowed. If the user says they are not interested, stop immediately and do not ask again.
|
|
15850
|
-
- Deduplicate a problem by namespace plus its substantive characteristics; changed wording or another retry does not make it a new problem. Never proactively suggest feedback for a problem that was already proactively suggested or already has a draft. A draft created at the user's request still makes that problem ineligible for a later proactive suggestion.
|
|
15851
|
-
- After a proactive suggestion, call feedback_prepare only if the user explicitly agrees. A direct request to create feedback is already authorization, so do not ask again. A failure of feedback_prepare itself must never trigger another proactive feedback suggestion.`;
|
|
16237
|
+
\u9488\u5BF9 StrataGate \u63D2\u4EF6\u7684\u6545\u969C\u3001\u4F7F\u7528\u7591\u95EE\u548C\u6539\u8FDB\u5EFA\u8BAE\uFF0C\u7528\u6237\u8981\u6C42\u65F6\u7528 feedback_prepare \u751F\u6210\u672C\u5730\u90AE\u4EF6\u53CD\u9988\u8349\u7A3F\u3002\u9700\u8981\u8FD0\u884C\u8BC1\u636E\u65F6\u7528 stratagate_diagnostics\uFF0C\u8349\u7A3F\u4F1A\u81EA\u52A8\u9644\u5E26\u672C\u5730\u8BCA\u65AD\u6458\u8981\u4F9B\u7528\u6237\u68C0\u67E5\u3002
|
|
16238
|
+
\u4EC5\u5728\u5F53\u524D\u4F1A\u8BDD\u5DF2\u6709\u660E\u786E\u7684 StrataGate \u9519\u8BEF\u8BC1\u636E\uFF0C\u4E14\u95EE\u9898\u6301\u7EED\u5F71\u54CD\u5F53\u524D\u4EFB\u52A1\u65F6\uFF0C\u5148\u5904\u7406\u95EE\u9898\uFF0C\u518D\u4E8E\u56DE\u590D\u672B\u5C3E\u8F7B\u58F0\u5EFA\u8BAE\u6574\u7406\u53CD\u9988\u3002\u6574\u4E2A\u4F1A\u8BDD\u6700\u591A\u4E3B\u52A8\u5EFA\u8BAE\u4E00\u6B21\uFF1B\u7528\u6237\u660E\u786E\u540C\u610F\u540E\u8C03\u7528\u3002\u7528\u6237\u76F4\u63A5\u8981\u6C42\u53EF\u76F4\u63A5\u6267\u884C\uFF1B\u62D2\u7EDD\u6216\u672A\u56DE\u5E94\u5C31\u7ED3\u675F\u5EFA\u8BAE\u3002\u6309\u8BB0\u5FC6\u7A7A\u95F4\u4E0E\u5B9E\u8D28\u95EE\u9898\u53BB\u91CD\u3002\u666E\u901A\u540E\u53F0\u91CD\u8BD5\u4FDD\u6301\u5B89\u9759\uFF1B\u53CD\u9988\u5DE5\u5177\u81EA\u8EAB\u5931\u8D25\u7EE7\u7EED\u539F\u4EFB\u52A1\u3002`;
|
|
15852
16239
|
function renderError(error) {
|
|
15853
16240
|
return error instanceof Error ? error.message : String(error);
|
|
15854
16241
|
}
|
|
@@ -15858,6 +16245,7 @@ function feedbackWebOrigin(ctx) {
|
|
|
15858
16245
|
}
|
|
15859
16246
|
async function apply(ctx, config) {
|
|
15860
16247
|
const compatibility = assertCompatibleDshRuntime();
|
|
16248
|
+
assertDshHostContract(ctx);
|
|
15861
16249
|
const resolved = resolveConfig(config);
|
|
15862
16250
|
const legacyMigration = await migrateLegacyCitationSessions(resolved.sessionRoot);
|
|
15863
16251
|
if (legacyMigration.failures.length > 0) {
|
|
@@ -15929,27 +16317,48 @@ async function apply(ctx, config) {
|
|
|
15929
16317
|
autoMemory = { name: "stratagate:auto-memory", text: text3 };
|
|
15930
16318
|
} catch (error) {
|
|
15931
16319
|
ctx.logger.warn(`stratagate-memory auto-context failed: ${renderError(error)}`);
|
|
15932
|
-
|
|
16320
|
+
runtime.notePluginError(session, error, "autoContext");
|
|
15933
16321
|
}
|
|
15934
16322
|
try {
|
|
15935
16323
|
const directory = await runtime.buildMemoryDirectory(session);
|
|
15936
16324
|
if (directory) contexts.push({ name: "stratagate:memory-directory", text: directory });
|
|
15937
16325
|
} catch (error) {
|
|
15938
16326
|
ctx.logger.warn(`stratagate-memory directory failed: ${renderError(error)}`);
|
|
15939
|
-
|
|
16327
|
+
runtime.notePluginError(session, error, "directory");
|
|
15940
16328
|
}
|
|
15941
16329
|
if (autoMemory) contexts.push(autoMemory);
|
|
15942
|
-
const
|
|
15943
|
-
|
|
16330
|
+
const toolSchemas = ctx.tools.schemas(context.agent).filter(({ name: name2 }) => name2.startsWith("memory_") || name2 === "feedback_prepare" || name2 === "stratagate_diagnostics");
|
|
16331
|
+
runtime.trackDiagnosticSession(String(session.id), runtime.namespaceFor(session), estimateTokens(JSON.stringify({
|
|
16332
|
+
sections: assembled.sections.filter(({ name: name2 }) => name2.startsWith("tool:stratagate-")),
|
|
16333
|
+
contexts: contexts.filter(({ name: name2 }) => name2.startsWith("stratagate:")),
|
|
16334
|
+
tools: toolSchemas
|
|
16335
|
+
})));
|
|
15944
16336
|
return { ...assembled, contexts };
|
|
15945
16337
|
});
|
|
15946
16338
|
installRetrievalFinalization(ctx, runtime);
|
|
15947
16339
|
registerMemoryTools(ctx, runtime);
|
|
15948
|
-
ctx.on("
|
|
15949
|
-
if (
|
|
15950
|
-
|
|
15951
|
-
|
|
16340
|
+
ctx.on("llm/stream", async function* (options, next) {
|
|
16341
|
+
if (models.currentDiagnosticScope()) {
|
|
16342
|
+
yield* next();
|
|
16343
|
+
return;
|
|
16344
|
+
}
|
|
16345
|
+
const namespace = runtime.diagnosticNamespaceForSession(String(options.sessionId ?? ""));
|
|
16346
|
+
if (!namespace || options.purpose) {
|
|
16347
|
+
yield* next();
|
|
16348
|
+
return;
|
|
15952
16349
|
}
|
|
16350
|
+
const stage = String(options.sessionId).startsWith("stratagate-dreaming:") ? "dreamingStep" : "chat";
|
|
16351
|
+
const memoryInputEstimate = runtime.diagnosticMemoryEstimate(String(options.sessionId));
|
|
16352
|
+
yield* observeModelStream(runtime.diagnostics, { namespace, stage, ...memoryInputEstimate !== void 0 ? { memoryInputEstimate } : {} }, options, next);
|
|
16353
|
+
});
|
|
16354
|
+
ctx.on("tools/result", (exec, result) => {
|
|
16355
|
+
if (!exec.agent || !(exec.name === "feedback_prepare" || exec.name === "stratagate_diagnostics" || exec.name.startsWith("memory_"))) return;
|
|
16356
|
+
const namespace = runtime.namespaceFor(exec.agent.session);
|
|
16357
|
+
runtime.diagnostics.record(
|
|
16358
|
+
{ namespace, stage: "tools" },
|
|
16359
|
+
{ toolCalls: 1, toolFailures: result.isError ? 1 : 0 },
|
|
16360
|
+
result.isError ? { error: result.error.message } : {}
|
|
16361
|
+
);
|
|
15953
16362
|
});
|
|
15954
16363
|
const disposeAdminRoutes = registerAdminRoutes(ctx, runtime);
|
|
15955
16364
|
ctx.on("session/event", (session, event) => runtime.acceptEvent(session, event));
|