stratagate-dsh 0.3.14 → 0.3.16
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 +680 -665
- package/LICENSE +21 -21
- package/dist/client.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +624 -128
- package/dist/plugin.js.map +1 -1
- package/docs/DSH.md +268 -268
- package/docs/DSH.zh-CN.md +245 -245
- package/docs/benchmarks/issue-128-windows-review.json +104 -104
- package/docs/benchmarks/issue-128-windows.json +103 -103
- package/docs/dreaming-agent.md +45 -45
- package/docs/feedback.md +50 -0
- package/docs/issue-128-lease-cache-review-followup.md +55 -55
- package/docs/issue-128-review-followup.md +58 -58
- package/docs/npm-release.md +52 -52
- package/docs/validation/issue119.md +41 -41
- package/package.json +246 -246
- package/screenshots.json +8 -8
package/dist/plugin.js
CHANGED
|
@@ -5501,6 +5501,7 @@ function agentEventCandidate(content, category, now, threadId) {
|
|
|
5501
5501
|
};
|
|
5502
5502
|
}
|
|
5503
5503
|
var DERIVATION_BACKOFF_MS = 1e3;
|
|
5504
|
+
var GRAPH_PROJECTION_BATCH_SIZE = 8;
|
|
5504
5505
|
function restrictExtractionRelations(temporal, allowedIds) {
|
|
5505
5506
|
const result = { ...temporal };
|
|
5506
5507
|
if (typeof result.sameEventId !== "string" || !allowedIds.has(result.sameEventId)) {
|
|
@@ -6669,6 +6670,18 @@ var StrataGate = class _StrataGate {
|
|
|
6669
6670
|
return this.commitMutation(() => {
|
|
6670
6671
|
const job = [...this.graphProjectionJobs.values()].filter(eligible).sort((left, right) => Number(left.status !== "pending") - Number(right.status !== "pending") || right.priority - left.priority || left.createdAt.localeCompare(right.createdAt))[0];
|
|
6671
6672
|
if (!job) return null;
|
|
6673
|
+
const sourceEventIds = job.sourceEventIds;
|
|
6674
|
+
for (let index = GRAPH_PROJECTION_BATCH_SIZE; index < sourceEventIds.length; index += GRAPH_PROJECTION_BATCH_SIZE) {
|
|
6675
|
+
const id = this.graphIdFactory("gproj");
|
|
6676
|
+
this.graphProjectionJobs.set(id, {
|
|
6677
|
+
...job,
|
|
6678
|
+
id,
|
|
6679
|
+
sourceEventIds: sourceEventIds.slice(index, index + GRAPH_PROJECTION_BATCH_SIZE),
|
|
6680
|
+
nodeIds: [],
|
|
6681
|
+
edgeIds: []
|
|
6682
|
+
});
|
|
6683
|
+
}
|
|
6684
|
+
job.sourceEventIds = sourceEventIds.slice(0, GRAPH_PROJECTION_BATCH_SIZE);
|
|
6672
6685
|
const events = job.sourceEventIds.flatMap((id) => {
|
|
6673
6686
|
const event = this.findEvent(id);
|
|
6674
6687
|
return event ? [event] : [];
|
|
@@ -7554,30 +7567,30 @@ var StrataGate = class _StrataGate {
|
|
|
7554
7567
|
return job;
|
|
7555
7568
|
}
|
|
7556
7569
|
queueGraphProjection(sourceEventIds, priority) {
|
|
7557
|
-
if (!this.graphProjector) return
|
|
7558
|
-
const completed = new Set([...this.graphProjectionJobs.values()].filter((
|
|
7559
|
-
const queued = new Set([...this.graphProjectionJobs.values()].filter((
|
|
7570
|
+
if (!this.graphProjector) return;
|
|
7571
|
+
const completed = new Set([...this.graphProjectionJobs.values()].filter((job) => job.projectorVersion === KNOWLEDGE_GRAPH_PROJECTOR_VERSION && job.status === "completed").flatMap((job) => job.sourceEventIds));
|
|
7572
|
+
const queued = new Set([...this.graphProjectionJobs.values()].filter((job) => job.projectorVersion === KNOWLEDGE_GRAPH_PROJECTOR_VERSION && job.status !== "completed").flatMap((job) => job.sourceEventIds));
|
|
7560
7573
|
const ids2 = [...new Set(sourceEventIds.filter((id) => this.findEvent(id) && !completed.has(id) && !queued.has(id)))];
|
|
7561
|
-
if (ids2.length === 0) return null;
|
|
7562
7574
|
const now = toUtc8Iso(this.now());
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7575
|
+
for (let index = 0; index < ids2.length; index += GRAPH_PROJECTION_BATCH_SIZE) {
|
|
7576
|
+
const job = {
|
|
7577
|
+
id: this.graphIdFactory("gproj"),
|
|
7578
|
+
sourceEventIds: ids2.slice(index, index + GRAPH_PROJECTION_BATCH_SIZE),
|
|
7579
|
+
projectorVersion: KNOWLEDGE_GRAPH_PROJECTOR_VERSION,
|
|
7580
|
+
status: "pending",
|
|
7581
|
+
attempts: 0,
|
|
7582
|
+
priority,
|
|
7583
|
+
nodeIds: [],
|
|
7584
|
+
edgeIds: [],
|
|
7585
|
+
nameProvenanceRecoveryVersion: 1,
|
|
7586
|
+
reason: null,
|
|
7587
|
+
lastError: null,
|
|
7588
|
+
nextRetryAt: null,
|
|
7589
|
+
createdAt: now,
|
|
7590
|
+
updatedAt: now
|
|
7591
|
+
};
|
|
7592
|
+
this.graphProjectionJobs.set(job.id, job);
|
|
7593
|
+
}
|
|
7581
7594
|
}
|
|
7582
7595
|
recoverGraphNameProvenanceFailures() {
|
|
7583
7596
|
for (const job of this.graphProjectionJobs.values()) {
|
|
@@ -7595,8 +7608,8 @@ var StrataGate = class _StrataGate {
|
|
|
7595
7608
|
const score = (event) => (event.status === "active" ? 1e4 : 0) + event.weight.mentionCount * 100 + (event.scope === "project" ? 500 : 0) + (Date.parse(event.temporal.happenedStart ?? event.temporal.mentionedAt ?? event.updatedAt) || 0) / 1e12;
|
|
7596
7609
|
return score(right) - score(left);
|
|
7597
7610
|
});
|
|
7598
|
-
for (let index = 0; index < candidates.length; index +=
|
|
7599
|
-
this.queueGraphProjection(candidates.slice(index, index +
|
|
7611
|
+
for (let index = 0; index < candidates.length; index += GRAPH_PROJECTION_BATCH_SIZE) {
|
|
7612
|
+
this.queueGraphProjection(candidates.slice(index, index + GRAPH_PROJECTION_BATCH_SIZE).map(({ id }) => id), candidates.length - index);
|
|
7600
7613
|
}
|
|
7601
7614
|
}
|
|
7602
7615
|
queueElementProjection(sourceEventIds) {
|
|
@@ -8508,6 +8521,329 @@ function parseJsonResponse(value, requiredKeys = []) {
|
|
|
8508
8521
|
throw new ModelJsonResponseError(void 0, { response: value });
|
|
8509
8522
|
}
|
|
8510
8523
|
|
|
8524
|
+
// src/llm.ts
|
|
8525
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
8526
|
+
|
|
8527
|
+
// src/diagnostics.ts
|
|
8528
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
8529
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
8530
|
+
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
8531
|
+
var DAY = 864e5;
|
|
8532
|
+
var VERSION = (() => {
|
|
8533
|
+
try {
|
|
8534
|
+
return String(createRequire2(import.meta.url)("../package.json").version);
|
|
8535
|
+
} catch {
|
|
8536
|
+
return "unknown";
|
|
8537
|
+
}
|
|
8538
|
+
})();
|
|
8539
|
+
var DIAGNOSTIC_STAGES = ["summarizer", "extractor", "projector", "graphProjector", "topicProjector", "externalMemoryExtractor", "externalMemoryDecider", "profileMaintenance", "dreamingStep", "chat", "ingestion", "autoContext", "directory", "tools", "frontend", "retrieval"];
|
|
8540
|
+
function diagnosticText(value, limit = 1500) {
|
|
8541
|
+
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]$/, "");
|
|
8542
|
+
}
|
|
8543
|
+
function isAbortError(error) {
|
|
8544
|
+
return typeof error === "object" && error !== null && (error.name === "AbortError" || error.code === "ABORT_ERR");
|
|
8545
|
+
}
|
|
8546
|
+
function diagnosticCategory(error) {
|
|
8547
|
+
if (isAbortError(error)) return "cancelled";
|
|
8548
|
+
const text3 = String(error instanceof Error ? error.message : error ?? "");
|
|
8549
|
+
if (/timeout|timed out|超时/i.test(text3)) return "timeout";
|
|
8550
|
+
if (/429|rate.?limit/i.test(text3)) return "rate-limit";
|
|
8551
|
+
if (/401|403|unauthori|forbidden|credential/i.test(text3)) return "authentication";
|
|
8552
|
+
if (/token.*limit|truncat|max-tokens|context.*(window|length|limit)/i.test(text3)) return "token-limit";
|
|
8553
|
+
if (/json|schema|invalid|validation/i.test(text3)) return "validation";
|
|
8554
|
+
if (/sqlite|database|storage|EACCES|ENOSPC|write failed/i.test(text3)) return "storage";
|
|
8555
|
+
if (/abort|cancel/i.test(text3)) return "cancelled";
|
|
8556
|
+
if (/network|fetch|ECONN|ENOTFOUND/i.test(text3)) return "network";
|
|
8557
|
+
return "internal";
|
|
8558
|
+
}
|
|
8559
|
+
var SCHEMA2 = `
|
|
8560
|
+
CREATE TABLE IF NOT EXISTS stratagate_dsh_diagnostic_records (
|
|
8561
|
+
id TEXT PRIMARY KEY, at TEXT NOT NULL, namespace TEXT NOT NULL, record_json TEXT NOT NULL
|
|
8562
|
+
) STRICT;
|
|
8563
|
+
CREATE INDEX IF NOT EXISTS stratagate_dsh_diagnostic_scope ON stratagate_dsh_diagnostic_records(namespace, at);
|
|
8564
|
+
CREATE TABLE IF NOT EXISTS stratagate_dsh_diagnostic_daily (
|
|
8565
|
+
namespace TEXT NOT NULL, day TEXT NOT NULL, stage TEXT NOT NULL, model TEXT NOT NULL,
|
|
8566
|
+
version TEXT NOT NULL, counters_json TEXT NOT NULL,
|
|
8567
|
+
PRIMARY KEY(namespace, day, stage, model, version)
|
|
8568
|
+
) STRICT;
|
|
8569
|
+
CREATE TABLE IF NOT EXISTS stratagate_dsh_diagnostic_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL) STRICT;
|
|
8570
|
+
`;
|
|
8571
|
+
var DiagnosticsRecorder = class {
|
|
8572
|
+
constructor(filename) {
|
|
8573
|
+
this.filename = filename;
|
|
8574
|
+
}
|
|
8575
|
+
filename;
|
|
8576
|
+
database;
|
|
8577
|
+
pending = [];
|
|
8578
|
+
timer;
|
|
8579
|
+
closed = false;
|
|
8580
|
+
dropped = 0;
|
|
8581
|
+
writeFailures = 0;
|
|
8582
|
+
startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8583
|
+
record(scope, counters, options = {}) {
|
|
8584
|
+
if (this.closed) return;
|
|
8585
|
+
const bounded2 = Object.fromEntries(Object.entries(counters).filter(([, n]) => Number.isFinite(n) && n >= 0));
|
|
8586
|
+
this.pending.push({
|
|
8587
|
+
id: `diag_${randomUUID3()}`,
|
|
8588
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8589
|
+
namespace: scope.namespace,
|
|
8590
|
+
stage: scope.stage,
|
|
8591
|
+
model: diagnosticText(options.model ?? "", 160),
|
|
8592
|
+
version: VERSION,
|
|
8593
|
+
counters: bounded2,
|
|
8594
|
+
...scope.taskId ? { taskId: scope.taskId } : {},
|
|
8595
|
+
...options.error !== void 0 ? { category: diagnosticCategory(options.error), detail: diagnosticText(options.error) } : {}
|
|
8596
|
+
});
|
|
8597
|
+
if (this.pending.length > 256) {
|
|
8598
|
+
this.pending.shift();
|
|
8599
|
+
this.dropped++;
|
|
8600
|
+
}
|
|
8601
|
+
if (!this.timer) {
|
|
8602
|
+
this.timer = setTimeout(() => {
|
|
8603
|
+
this.timer = void 0;
|
|
8604
|
+
this.flush();
|
|
8605
|
+
}, 5e3);
|
|
8606
|
+
this.timer.unref?.();
|
|
8607
|
+
}
|
|
8608
|
+
}
|
|
8609
|
+
open() {
|
|
8610
|
+
if (this.database) return this.database;
|
|
8611
|
+
const db = new DatabaseSync2(this.filename);
|
|
8612
|
+
try {
|
|
8613
|
+
db.exec("PRAGMA busy_timeout=0");
|
|
8614
|
+
db.exec(SCHEMA2);
|
|
8615
|
+
db.prepare("INSERT OR IGNORE INTO stratagate_dsh_diagnostic_meta VALUES ('startedAt', ?)").run(this.startedAt);
|
|
8616
|
+
this.database = db;
|
|
8617
|
+
return db;
|
|
8618
|
+
} catch (error) {
|
|
8619
|
+
db.close();
|
|
8620
|
+
throw error;
|
|
8621
|
+
}
|
|
8622
|
+
}
|
|
8623
|
+
flush() {
|
|
8624
|
+
if (!this.pending.length) return;
|
|
8625
|
+
try {
|
|
8626
|
+
const db = this.open();
|
|
8627
|
+
db.exec("BEGIN IMMEDIATE");
|
|
8628
|
+
try {
|
|
8629
|
+
const get = db.prepare("SELECT counters_json FROM stratagate_dsh_diagnostic_daily WHERE namespace=? AND day=? AND stage=? AND model=? AND version=?");
|
|
8630
|
+
const put = db.prepare("INSERT OR REPLACE INTO stratagate_dsh_diagnostic_daily VALUES (?, ?, ?, ?, ?, ?)");
|
|
8631
|
+
const insert = db.prepare("INSERT INTO stratagate_dsh_diagnostic_records VALUES (?, ?, ?, ?)");
|
|
8632
|
+
for (const item of this.pending) {
|
|
8633
|
+
const keys = [item.namespace, item.at.slice(0, 10), item.stage, item.model, item.version];
|
|
8634
|
+
const row = get.get(...keys);
|
|
8635
|
+
const counters = row ? JSON.parse(row.counters_json) : {};
|
|
8636
|
+
for (const [key, value] of Object.entries(item.counters)) counters[key] = (counters[key] ?? 0) + value;
|
|
8637
|
+
put.run(...keys, JSON.stringify(counters));
|
|
8638
|
+
insert.run(item.id, item.at, item.namespace, JSON.stringify(item));
|
|
8639
|
+
}
|
|
8640
|
+
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());
|
|
8641
|
+
db.prepare("DELETE FROM stratagate_dsh_diagnostic_daily WHERE day < ?").run(new Date(Date.now() - 90 * DAY).toISOString().slice(0, 10));
|
|
8642
|
+
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)");
|
|
8643
|
+
db.exec("COMMIT");
|
|
8644
|
+
this.pending = [];
|
|
8645
|
+
} catch (error) {
|
|
8646
|
+
db.exec("ROLLBACK");
|
|
8647
|
+
throw error;
|
|
8648
|
+
}
|
|
8649
|
+
} catch {
|
|
8650
|
+
this.writeFailures++;
|
|
8651
|
+
}
|
|
8652
|
+
}
|
|
8653
|
+
snapshot(namespace, options = {}) {
|
|
8654
|
+
this.flush();
|
|
8655
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8656
|
+
const since = new Date(Date.parse(today) - 6 * DAY).toISOString().slice(0, 10);
|
|
8657
|
+
const totals = {};
|
|
8658
|
+
const stages = {};
|
|
8659
|
+
let startedAt = this.startedAt;
|
|
8660
|
+
let available = false;
|
|
8661
|
+
let rows = [];
|
|
8662
|
+
let records = [];
|
|
8663
|
+
let totalRecords = 0;
|
|
8664
|
+
let corruptRollups = 0;
|
|
8665
|
+
let corruptRecords = 0;
|
|
8666
|
+
let scannedRecords = 0;
|
|
8667
|
+
const offset = Math.max(0, Math.min(2e3, Math.floor(options.offset ?? 0)));
|
|
8668
|
+
const readCounters = (text3) => {
|
|
8669
|
+
try {
|
|
8670
|
+
const value = JSON.parse(text3);
|
|
8671
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid counters");
|
|
8672
|
+
const entries = Object.entries(value);
|
|
8673
|
+
if (entries.some(([, n]) => typeof n !== "number" || !Number.isFinite(n) || n < 0)) throw new Error("Invalid counter value");
|
|
8674
|
+
return Object.fromEntries(entries);
|
|
8675
|
+
} catch {
|
|
8676
|
+
corruptRollups++;
|
|
8677
|
+
return {};
|
|
8678
|
+
}
|
|
8679
|
+
};
|
|
8680
|
+
try {
|
|
8681
|
+
const db = this.open();
|
|
8682
|
+
available = true;
|
|
8683
|
+
startedAt = db.prepare("SELECT value FROM stratagate_dsh_diagnostic_meta WHERE key='startedAt'").get().value;
|
|
8684
|
+
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);
|
|
8685
|
+
const where = options.id ? "namespace=? AND id=?" : "namespace=? AND at>=? AND json_extract(record_json, '$.category') IS NOT NULL";
|
|
8686
|
+
const values = options.id ? [namespace, options.id] : [namespace, since];
|
|
8687
|
+
totalRecords = Number(db.prepare(`SELECT count(*) AS count FROM stratagate_dsh_diagnostic_records WHERE ${where}`).get(...values).count);
|
|
8688
|
+
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);
|
|
8689
|
+
scannedRecords = raw.length;
|
|
8690
|
+
for (const row of raw) {
|
|
8691
|
+
try {
|
|
8692
|
+
const item = JSON.parse(row.record_json);
|
|
8693
|
+
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");
|
|
8694
|
+
records.push({
|
|
8695
|
+
id: item.id,
|
|
8696
|
+
at: item.at,
|
|
8697
|
+
namespace,
|
|
8698
|
+
stage: item.stage,
|
|
8699
|
+
model: diagnosticText(item.model, 160),
|
|
8700
|
+
version: item.version,
|
|
8701
|
+
counters: item.counters,
|
|
8702
|
+
...typeof item.taskId === "string" ? { taskId: item.taskId } : {},
|
|
8703
|
+
...typeof item.category === "string" ? { category: diagnosticText(item.category, 80) } : {},
|
|
8704
|
+
...typeof item.detail === "string" ? { detail: diagnosticText(item.detail) } : {}
|
|
8705
|
+
});
|
|
8706
|
+
} catch {
|
|
8707
|
+
corruptRecords++;
|
|
8708
|
+
}
|
|
8709
|
+
}
|
|
8710
|
+
} catch {
|
|
8711
|
+
available = false;
|
|
8712
|
+
}
|
|
8713
|
+
const parsedRows = rows.slice(0, 2e3).map((row) => ({ ...row, counters: readCounters(row.counters_json) }));
|
|
8714
|
+
for (const row of parsedRows) {
|
|
8715
|
+
const counters = row.counters;
|
|
8716
|
+
const stage = stages[row.stage] ??= {};
|
|
8717
|
+
for (const [key, value] of Object.entries(counters)) {
|
|
8718
|
+
totals[key] = (totals[key] ?? 0) + value;
|
|
8719
|
+
stage[key] = (stage[key] ?? 0) + value;
|
|
8720
|
+
}
|
|
8721
|
+
}
|
|
8722
|
+
const routes = /* @__PURE__ */ new Map();
|
|
8723
|
+
for (const row of parsedRows) {
|
|
8724
|
+
const key = JSON.stringify([row.stage, row.model, row.version]);
|
|
8725
|
+
const route = routes.get(key) ?? { stage: row.stage, model: row.model, version: row.version, counters: {} };
|
|
8726
|
+
for (const [name2, n] of Object.entries(row.counters)) route.counters[name2] = (route.counters[name2] ?? 0) + n;
|
|
8727
|
+
routes.set(key, route);
|
|
8728
|
+
}
|
|
8729
|
+
const rates = Object.fromEntries(Object.entries(stages).map(([stage, counts]) => [stage, {
|
|
8730
|
+
sampledOperations: counts.operations ?? 0,
|
|
8731
|
+
operationFailureRate: counts.operations ? (counts.operationsFailed ?? 0) / counts.operations : null,
|
|
8732
|
+
firstAttemptSuccessRate: counts.operations ? (counts.firstAttemptSucceeded ?? 0) / counts.operations : null,
|
|
8733
|
+
recoveredOperationRate: counts.operations ? (counts.operationsRecovered ?? 0) / counts.operations : null,
|
|
8734
|
+
meanOperationMs: counts.operations ? (counts.operationMs ?? 0) / counts.operations : null,
|
|
8735
|
+
meanModelMs: counts.modelCalls ? (counts.modelMs ?? 0) / counts.modelCalls : null
|
|
8736
|
+
}]));
|
|
8737
|
+
const chatTokens = stages.chat?.totalTokens ?? 0;
|
|
8738
|
+
const backgroundTokens = (totals.totalTokens ?? 0) - chatTokens;
|
|
8739
|
+
const totalsComplete = available && !corruptRollups && !this.dropped && totals.modelCalls && totals.totalTokenCalls === totals.modelCalls && !this.pending.length && rows.length <= 2e3;
|
|
8740
|
+
return {
|
|
8741
|
+
schemaVersion: 1,
|
|
8742
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8743
|
+
since,
|
|
8744
|
+
through: today,
|
|
8745
|
+
timezone: "UTC",
|
|
8746
|
+
startedAt,
|
|
8747
|
+
coverage: {
|
|
8748
|
+
available,
|
|
8749
|
+
corruptRollups,
|
|
8750
|
+
corruptRecords,
|
|
8751
|
+
processStartedAt: this.startedAt,
|
|
8752
|
+
pendingRecords: this.pending.length,
|
|
8753
|
+
droppedRecords: this.dropped,
|
|
8754
|
+
writeFailures: this.writeFailures,
|
|
8755
|
+
rollupTruncated: rows.length > 2e3,
|
|
8756
|
+
historicalBackfill: false,
|
|
8757
|
+
rawRetentionDays: 7,
|
|
8758
|
+
rollupRetentionDays: 90,
|
|
8759
|
+
totalChatCostRatio: null,
|
|
8760
|
+
netSavings: null,
|
|
8761
|
+
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"
|
|
8762
|
+
},
|
|
8763
|
+
totals,
|
|
8764
|
+
stages,
|
|
8765
|
+
rates,
|
|
8766
|
+
observedBackgroundTokenShare: totalsComplete && totals.totalTokens ? backgroundTokens / totals.totalTokens : null,
|
|
8767
|
+
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",
|
|
8768
|
+
routes: [...routes.values()].slice(0, 40),
|
|
8769
|
+
omittedRoutes: Math.max(0, routes.size - 40),
|
|
8770
|
+
totalRecords,
|
|
8771
|
+
nextOffset: offset + scannedRecords < totalRecords ? offset + scannedRecords : null,
|
|
8772
|
+
records: records.map(({ namespace: _namespace, detail, ...record3 }) => ({ ...record3, ...options.details && detail ? { detail } : {} }))
|
|
8773
|
+
};
|
|
8774
|
+
}
|
|
8775
|
+
close() {
|
|
8776
|
+
if (this.closed) return;
|
|
8777
|
+
if (this.timer) clearTimeout(this.timer);
|
|
8778
|
+
this.timer = void 0;
|
|
8779
|
+
this.flush();
|
|
8780
|
+
this.closed = true;
|
|
8781
|
+
try {
|
|
8782
|
+
this.database?.close();
|
|
8783
|
+
} catch {
|
|
8784
|
+
}
|
|
8785
|
+
this.database = void 0;
|
|
8786
|
+
}
|
|
8787
|
+
};
|
|
8788
|
+
async function* observeModelStream(recorder, scope, options, next) {
|
|
8789
|
+
const start = Date.now();
|
|
8790
|
+
let usage;
|
|
8791
|
+
let finished = false;
|
|
8792
|
+
let failure;
|
|
8793
|
+
let cancelled = false;
|
|
8794
|
+
scope.calls = (scope.calls ?? 0) + 1;
|
|
8795
|
+
try {
|
|
8796
|
+
for await (const chunk of next()) {
|
|
8797
|
+
if (chunk.type === "usage") usage = chunk.usage;
|
|
8798
|
+
if (chunk.type === "finish") {
|
|
8799
|
+
finished = true;
|
|
8800
|
+
if (chunk.reason.kind === "error" || chunk.reason.kind === "aborted") {
|
|
8801
|
+
cancelled = chunk.reason.kind === "aborted";
|
|
8802
|
+
failure = cancelled ? Object.assign(new Error(chunk.reason.failure?.message ?? "aborted"), { name: "AbortError" }) : chunk.reason.failure.message;
|
|
8803
|
+
} else if (chunk.reason.kind === "max-tokens") failure = "max-tokens";
|
|
8804
|
+
}
|
|
8805
|
+
yield chunk;
|
|
8806
|
+
}
|
|
8807
|
+
} catch (error) {
|
|
8808
|
+
failure = error;
|
|
8809
|
+
cancelled = isAbortError(error);
|
|
8810
|
+
throw error;
|
|
8811
|
+
} finally {
|
|
8812
|
+
const valid = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0;
|
|
8813
|
+
const known = usage && valid(usage.inputTokens) && valid(usage.outputTokens);
|
|
8814
|
+
const counters = {
|
|
8815
|
+
modelCalls: 1,
|
|
8816
|
+
modelFailed: failure !== void 0 && !cancelled ? 1 : 0,
|
|
8817
|
+
modelCancelled: cancelled || !finished && failure === void 0 ? 1 : 0,
|
|
8818
|
+
modelMs: Date.now() - start,
|
|
8819
|
+
usageCalls: known ? 1 : 0,
|
|
8820
|
+
missingUsageCalls: known ? 0 : 1
|
|
8821
|
+
};
|
|
8822
|
+
if (scope.stage === "chat" && scope.memoryInputEstimate !== void 0) {
|
|
8823
|
+
counters.memoryInputEstimate = scope.memoryInputEstimate;
|
|
8824
|
+
counters.memoryInputEstimateCalls = 1;
|
|
8825
|
+
}
|
|
8826
|
+
if (known && usage) {
|
|
8827
|
+
counters.inputTokens = usage.inputTokens;
|
|
8828
|
+
counters.outputTokens = usage.outputTokens;
|
|
8829
|
+
if (valid(usage.cacheReadTokens)) {
|
|
8830
|
+
counters.cacheReadTokens = usage.cacheReadTokens;
|
|
8831
|
+
counters.cacheReadKnownCalls = 1;
|
|
8832
|
+
}
|
|
8833
|
+
if (valid(usage.cacheWriteTokens)) {
|
|
8834
|
+
counters.cacheWriteTokens = usage.cacheWriteTokens;
|
|
8835
|
+
counters.cacheWriteKnownCalls = 1;
|
|
8836
|
+
}
|
|
8837
|
+
if (valid(usage.reasoningTokens)) counters.reasoningTokens = usage.reasoningTokens;
|
|
8838
|
+
if (valid(usage.totalTokens) || valid(usage.cacheReadTokens) && valid(usage.cacheWriteTokens)) {
|
|
8839
|
+
counters.totalTokens = valid(usage.totalTokens) ? usage.totalTokens : counters.inputTokens + counters.outputTokens + counters.cacheReadTokens + counters.cacheWriteTokens;
|
|
8840
|
+
counters.totalTokenCalls = 1;
|
|
8841
|
+
}
|
|
8842
|
+
}
|
|
8843
|
+
recorder.record(scope, counters, { model: `${options.provider}/${options.model}`, ...failure !== void 0 ? { error: failure } : {} });
|
|
8844
|
+
}
|
|
8845
|
+
}
|
|
8846
|
+
|
|
8511
8847
|
// src/llm.ts
|
|
8512
8848
|
var ELEMENT_TYPES2 = /* @__PURE__ */ new Set(["person", "project", "organization", "tool", "place"]);
|
|
8513
8849
|
var CRITICALITIES = /* @__PURE__ */ new Set(["routine", "preference", "identity", "safety"]);
|
|
@@ -9056,6 +9392,7 @@ function parseTopicProjection(value, context) {
|
|
|
9056
9392
|
return { topics };
|
|
9057
9393
|
}
|
|
9058
9394
|
var TOPIC_OUTPUT_TOKEN_BUDGET = 32768;
|
|
9395
|
+
var GRAPH_OUTPUT_TOKEN_BUDGET = 32768;
|
|
9059
9396
|
var DshModelBridge = class {
|
|
9060
9397
|
constructor(ctx, config, liveStructuredReasoningEffort) {
|
|
9061
9398
|
this.ctx = ctx;
|
|
@@ -9071,6 +9408,16 @@ var DshModelBridge = class {
|
|
|
9071
9408
|
ctx;
|
|
9072
9409
|
config;
|
|
9073
9410
|
liveStructuredReasoningEffort;
|
|
9411
|
+
diagnosticScopes = new AsyncLocalStorage();
|
|
9412
|
+
diagnostics;
|
|
9413
|
+
diagnosticNamespace = () => "@shared";
|
|
9414
|
+
setDiagnostics(recorder, namespace) {
|
|
9415
|
+
this.diagnostics = recorder;
|
|
9416
|
+
this.diagnosticNamespace = namespace;
|
|
9417
|
+
}
|
|
9418
|
+
currentDiagnosticScope() {
|
|
9419
|
+
return this.diagnosticScopes.getStore();
|
|
9420
|
+
}
|
|
9074
9421
|
contextWindows = /* @__PURE__ */ new Map();
|
|
9075
9422
|
sessions = new AsyncLocalStorage();
|
|
9076
9423
|
successfulResponses = [];
|
|
@@ -9103,8 +9450,8 @@ var DshModelBridge = class {
|
|
|
9103
9450
|
run(session, operation) {
|
|
9104
9451
|
return this.sessions.run({ session, sessionId: session.id }, operation);
|
|
9105
9452
|
}
|
|
9106
|
-
runDetached(sessionId, operation, signal) {
|
|
9107
|
-
return this.sessions.run({ sessionId, ...signal ? { signal } : {} }, operation);
|
|
9453
|
+
runDetached(sessionId, operation, signal, namespace) {
|
|
9454
|
+
return this.sessions.run({ sessionId, ...signal ? { signal } : {}, ...namespace ? { namespace } : {} }, operation);
|
|
9108
9455
|
}
|
|
9109
9456
|
dreamingModelOptions() {
|
|
9110
9457
|
return { ...this.resolveRoute(), maxTokens: TOPIC_OUTPUT_TOKEN_BUDGET };
|
|
@@ -9385,12 +9732,47 @@ Use project scope for repository decisions, user scope for stable preferences/id
|
|
|
9385
9732
|
return proposed;
|
|
9386
9733
|
}
|
|
9387
9734
|
async callStructured(kind, system, payload, validate, topicMetadata) {
|
|
9735
|
+
const execution = this.sessions.getStore();
|
|
9736
|
+
const scope = {
|
|
9737
|
+
namespace: execution?.namespace ?? this.diagnosticNamespace(execution?.session, String(execution?.sessionId ?? "")),
|
|
9738
|
+
stage: kind,
|
|
9739
|
+
taskId: `task_${randomUUID4()}`,
|
|
9740
|
+
calls: 0
|
|
9741
|
+
};
|
|
9742
|
+
const start = Date.now();
|
|
9743
|
+
return this.diagnosticScopes.run(scope, async () => {
|
|
9744
|
+
try {
|
|
9745
|
+
const result = await this.callStructuredInner(kind, system, payload, validate, topicMetadata);
|
|
9746
|
+
this.diagnostics?.record(scope, {
|
|
9747
|
+
operations: 1,
|
|
9748
|
+
operationsSucceeded: 1,
|
|
9749
|
+
operationsFailed: 0,
|
|
9750
|
+
operationsRecovered: (scope.calls ?? 0) > 1 ? 1 : 0,
|
|
9751
|
+
firstAttemptSucceeded: (scope.calls ?? 0) === 1 ? 1 : 0,
|
|
9752
|
+
retries: Math.max(0, (scope.calls ?? 0) - 1),
|
|
9753
|
+
operationMs: Date.now() - start
|
|
9754
|
+
});
|
|
9755
|
+
return result;
|
|
9756
|
+
} catch (error) {
|
|
9757
|
+
this.diagnostics?.record(scope, {
|
|
9758
|
+
operations: 1,
|
|
9759
|
+
operationsSucceeded: 0,
|
|
9760
|
+
operationsFailed: 1,
|
|
9761
|
+
retries: Math.max(0, (scope.calls ?? 0) - 1),
|
|
9762
|
+
operationMs: Date.now() - start
|
|
9763
|
+
}, { error });
|
|
9764
|
+
throw error;
|
|
9765
|
+
}
|
|
9766
|
+
});
|
|
9767
|
+
}
|
|
9768
|
+
async callStructuredInner(kind, system, payload, validate, topicMetadata) {
|
|
9388
9769
|
const execution = this.sessions.getStore();
|
|
9389
9770
|
if (!execution) throw new Error("StrataGate model callback ran without an execution context");
|
|
9390
9771
|
const baseRoute = this.resolveRoute(execution.session);
|
|
9391
9772
|
const routeKey = `${baseRoute.provider}\0${baseRoute.model}`;
|
|
9392
9773
|
let useOff = await this.shouldUseOff(baseRoute);
|
|
9393
9774
|
const isTopic = kind === "topicProjector";
|
|
9775
|
+
const isGraph = kind === "graphProjector";
|
|
9394
9776
|
const topicDiagnostics = {
|
|
9395
9777
|
...topicMetadata,
|
|
9396
9778
|
requestedOutputTokens: TOPIC_OUTPUT_TOKEN_BUDGET,
|
|
@@ -9417,7 +9799,7 @@ Use project scope for repository decisions, user scope for stable preferences/id
|
|
|
9417
9799
|
}
|
|
9418
9800
|
}
|
|
9419
9801
|
const message = createUserMessage({
|
|
9420
|
-
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
9802
|
+
content: [{ type: "text", text: JSON.stringify(isGraph ? { ...object(payload), outputTokenBudget: GRAPH_OUTPUT_TOKEN_BUDGET } : payload) }],
|
|
9421
9803
|
source: dshMessageSource()
|
|
9422
9804
|
});
|
|
9423
9805
|
const assembler = new BlockAssembler();
|
|
@@ -9437,7 +9819,7 @@ ${JSON_RETRY_INSTRUCTION}${graphRetryFeedback}${topicRetryFeedback}`,
|
|
|
9437
9819
|
type: "function",
|
|
9438
9820
|
function: { name: STRUCTURED_TOOLS[kind].name }
|
|
9439
9821
|
},
|
|
9440
|
-
maxTokens: kind === "dreamingStep" ? TOPIC_OUTPUT_TOKEN_BUDGET : kind === "profileMaintenance" ? Math.max(this.config.maxOutputTokens, Math.min(12e3, 512 + 2 * Array.from(JSON.stringify(payload)).length)) : isTopic ? TOPIC_OUTPUT_TOKEN_BUDGET : this.config.maxOutputTokens,
|
|
9822
|
+
maxTokens: kind === "dreamingStep" ? TOPIC_OUTPUT_TOKEN_BUDGET : kind === "profileMaintenance" ? Math.max(this.config.maxOutputTokens, Math.min(12e3, 512 + 2 * Array.from(JSON.stringify(payload)).length)) : isTopic ? TOPIC_OUTPUT_TOKEN_BUDGET : isGraph ? GRAPH_OUTPUT_TOKEN_BUDGET : this.config.maxOutputTokens,
|
|
9441
9823
|
sessionId: execution.sessionId,
|
|
9442
9824
|
purpose: "compaction"
|
|
9443
9825
|
};
|
|
@@ -9449,6 +9831,18 @@ ${JSON_RETRY_INSTRUCTION}${graphRetryFeedback}${topicRetryFeedback}`,
|
|
|
9449
9831
|
request.maxTokens = Math.min(TOPIC_OUTPUT_TOKEN_BUDGET, Math.floor(window - input - 1024));
|
|
9450
9832
|
}
|
|
9451
9833
|
}
|
|
9834
|
+
if (isGraph) {
|
|
9835
|
+
const input = estimateTokens(JSON.stringify({ system: request.system, tools: request.tools, messages: request.messages }));
|
|
9836
|
+
const window = this.contextWindows.get(routeKey);
|
|
9837
|
+
if (window !== void 0) {
|
|
9838
|
+
if (window - input - 1024 < 256) throw new Error("Graph input exceeds model context capacity; reduce the source batch");
|
|
9839
|
+
request.maxTokens = Math.min(GRAPH_OUTPUT_TOKEN_BUDGET, Math.floor(window - input - 1024));
|
|
9840
|
+
}
|
|
9841
|
+
request.messages = [{ ...message, content: [{ type: "text", text: JSON.stringify({
|
|
9842
|
+
...object(payload),
|
|
9843
|
+
outputTokenBudget: request.maxTokens
|
|
9844
|
+
}) }] }];
|
|
9845
|
+
}
|
|
9452
9846
|
if (isTopic) {
|
|
9453
9847
|
const estimateInput = () => estimateTokens(JSON.stringify({ system: request.system, tools: request.tools, messages: request.messages }));
|
|
9454
9848
|
let inputTokens = estimateInput();
|
|
@@ -9526,6 +9920,9 @@ ${JSON_RETRY_INSTRUCTION}${graphRetryFeedback}${topicRetryFeedback}`,
|
|
|
9526
9920
|
[finish=${finish.kind}; toolCalls=${calls.length}]`;
|
|
9527
9921
|
lastResponse = responseForError;
|
|
9528
9922
|
try {
|
|
9923
|
+
if (isGraph && finish.kind === "max-tokens") {
|
|
9924
|
+
throw new ModelJsonResponseError("StrataGate Graph output token limit reached", { response: responseForError });
|
|
9925
|
+
}
|
|
9529
9926
|
const expectedTool = STRUCTURED_TOOLS[kind].name;
|
|
9530
9927
|
let parsed;
|
|
9531
9928
|
if (calls.length !== 1 || calls[0]?.name !== expectedTool) {
|
|
@@ -9603,6 +10000,8 @@ Correct these canonical-name provenance fields: ${[...new Set(paths)].slice(0, 2
|
|
|
9603
10000
|
return parsed;
|
|
9604
10001
|
} catch (error) {
|
|
9605
10002
|
if (!(error instanceof ModelJsonResponseError) && !(isTopic && error instanceof TopicProjectionError)) throw error;
|
|
10003
|
+
const scope = this.diagnosticScopes.getStore();
|
|
10004
|
+
if (scope) this.diagnostics?.record(scope, { validationFailures: 1 }, { error });
|
|
9606
10005
|
let retryError = error;
|
|
9607
10006
|
if (isTopic && error instanceof TopicProjectionError) {
|
|
9608
10007
|
const safe = new TopicProjectionError(error.diagnostics.category, error.diagnostics.reason, { ...topicDiagnostics, ...error.diagnostics });
|
|
@@ -9704,7 +10103,9 @@ Correct the previous Topic output using these validation errors: ${JSON.stringif
|
|
|
9704
10103
|
try {
|
|
9705
10104
|
await Promise.race([
|
|
9706
10105
|
(async () => {
|
|
9707
|
-
|
|
10106
|
+
const scope = this.diagnosticScopes.getStore();
|
|
10107
|
+
const stream = this.diagnostics && scope ? observeModelStream(this.diagnostics, scope, timedRequest, () => this.ctx.llm.stream(timedRequest)) : this.ctx.llm.stream(timedRequest);
|
|
10108
|
+
for await (const chunk of stream) assembler.push(chunk);
|
|
9708
10109
|
})(),
|
|
9709
10110
|
timeout,
|
|
9710
10111
|
aborted
|
|
@@ -9746,7 +10147,7 @@ function isOffRejection(error) {
|
|
|
9746
10147
|
}
|
|
9747
10148
|
|
|
9748
10149
|
// src/metadata.ts
|
|
9749
|
-
import { DatabaseSync as
|
|
10150
|
+
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
9750
10151
|
var TOPIC_BOOTSTRAP_WINDOW_MS = 10 * 6e4;
|
|
9751
10152
|
var TOPIC_BOOTSTRAP_WINDOW_CALLS = 2;
|
|
9752
10153
|
var METADATA_SCHEMA = `
|
|
@@ -9769,7 +10170,7 @@ CREATE TABLE IF NOT EXISTS stratagate_dsh_feedback_drafts (
|
|
|
9769
10170
|
) STRICT;
|
|
9770
10171
|
`;
|
|
9771
10172
|
function dropLegacyAgentMemoriesTable(filename) {
|
|
9772
|
-
const database = new
|
|
10173
|
+
const database = new DatabaseSync3(filename);
|
|
9773
10174
|
try {
|
|
9774
10175
|
const legacyTable = database.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'stratagate_dsh_agent_memories'").get();
|
|
9775
10176
|
if (!legacyTable) return;
|
|
@@ -9782,7 +10183,7 @@ function dropLegacyAgentMemoriesTable(filename) {
|
|
|
9782
10183
|
var DshMetadataStore = class {
|
|
9783
10184
|
database;
|
|
9784
10185
|
constructor(filename) {
|
|
9785
|
-
this.database = new
|
|
10186
|
+
this.database = new DatabaseSync3(filename);
|
|
9786
10187
|
this.database.exec(METADATA_SCHEMA);
|
|
9787
10188
|
}
|
|
9788
10189
|
/** Database-wide, durable reservation before any historical model attempt.
|
|
@@ -9912,15 +10313,10 @@ var DshMetadataStore = class {
|
|
|
9912
10313
|
};
|
|
9913
10314
|
|
|
9914
10315
|
// src/runtime.ts
|
|
9915
|
-
import { createHash as createHash3, randomUUID as
|
|
9916
|
-
|
|
9917
|
-
// src/feedback-policy.ts
|
|
9918
|
-
var AGENT_FEEDBACK_ENABLED = false;
|
|
9919
|
-
|
|
9920
|
-
// src/runtime.ts
|
|
10316
|
+
import { createHash as createHash3, randomUUID as randomUUID5 } from "node:crypto";
|
|
9921
10317
|
import { existsSync } from "node:fs";
|
|
9922
10318
|
import { dirname, resolve as resolve2 } from "node:path";
|
|
9923
|
-
import { DatabaseSync as
|
|
10319
|
+
import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
|
|
9924
10320
|
import { createUserMessage as createUserMessage2 } from "@deepseek-ai/dsh-llm";
|
|
9925
10321
|
import { openNativePath } from "@deepseek-ai/dsh-native-command";
|
|
9926
10322
|
import { validateArgs as validateArgs2 } from "@deepseek-ai/dsh-tools";
|
|
@@ -10477,7 +10873,6 @@ function graphProjectionCanRun(job, now = Date.now()) {
|
|
|
10477
10873
|
var AUTO_EVENT_LIMIT = 4;
|
|
10478
10874
|
var AUTO_ELEMENT_LIMIT = 4;
|
|
10479
10875
|
var AUTO_MEMORY_TOKEN_BUDGET = 900;
|
|
10480
|
-
var FEEDBACK_PROMPT_COOLDOWN_MS = 5 * 24 * 60 * 60 * 1e3;
|
|
10481
10876
|
function projectKey(cwd) {
|
|
10482
10877
|
const canonical2 = resolve2(cwd ?? process.cwd()).replaceAll("\\", "/").toLowerCase();
|
|
10483
10878
|
return createHash3("sha256").update(canonical2).digest("hex").slice(0, 20);
|
|
@@ -10560,6 +10955,8 @@ function normalizeFeedbackDraft(input, previous) {
|
|
|
10560
10955
|
expected: replacesStructuredBody ? "" : has("expected") ? feedbackText(input.expected, 1e4) : previous?.expected ?? "",
|
|
10561
10956
|
actual: replacesStructuredBody ? "" : has("actual") ? feedbackText(input.actual, 1e4) : previous?.actual ?? "",
|
|
10562
10957
|
errorContext: replacesStructuredBody ? "" : has("errorContext") ? feedbackText(input.errorContext, 2e4) : previous?.errorContext ?? "",
|
|
10958
|
+
...previous?.aiPrepared ? { aiPrepared: true } : {},
|
|
10959
|
+
...previous?.diagnostics ? { diagnostics: previous.diagnostics } : {},
|
|
10563
10960
|
...bodyMarkdown ? { bodyMarkdown } : {},
|
|
10564
10961
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10565
10962
|
};
|
|
@@ -10583,6 +10980,8 @@ var StrataGateRuntime = class {
|
|
|
10583
10980
|
this.flushNativeSession = flushNativeSession;
|
|
10584
10981
|
this.feedbackOrigin = feedbackOrigin;
|
|
10585
10982
|
this.openPath = openPath;
|
|
10983
|
+
this.diagnostics = new DiagnosticsRecorder(config.database);
|
|
10984
|
+
this.models.setDiagnostics?.(this.diagnostics, (session, sessionId) => session ? this.namespaceFor(session) : this.diagnosticNamespaceForSession(sessionId ?? "") ?? "@shared");
|
|
10586
10985
|
this.blockTurnSize = config.blockTurnSize;
|
|
10587
10986
|
this.blockDecayLambda = config.blockDecayLambda;
|
|
10588
10987
|
this.agentMemoryRetrievalWeight = config.agentMemoryRetrievalWeight ?? 1;
|
|
@@ -10596,6 +10995,9 @@ var StrataGateRuntime = class {
|
|
|
10596
10995
|
flushNativeSession;
|
|
10597
10996
|
feedbackOrigin;
|
|
10598
10997
|
openPath;
|
|
10998
|
+
diagnostics;
|
|
10999
|
+
diagnosticSessionNamespaces = /* @__PURE__ */ new Map();
|
|
11000
|
+
diagnosticMemoryEstimates = /* @__PURE__ */ new Map();
|
|
10599
11001
|
profileStorage;
|
|
10600
11002
|
folder = new TurnFolder();
|
|
10601
11003
|
spaces = /* @__PURE__ */ new Map();
|
|
@@ -10612,11 +11014,10 @@ var StrataGateRuntime = class {
|
|
|
10612
11014
|
externalImportRuns = /* @__PURE__ */ new Map();
|
|
10613
11015
|
dreamingRuns = /* @__PURE__ */ new Map();
|
|
10614
11016
|
dreamingControllers = /* @__PURE__ */ new Map();
|
|
10615
|
-
dreamingOwner =
|
|
11017
|
+
dreamingOwner = randomUUID5();
|
|
10616
11018
|
dreamingHost;
|
|
10617
11019
|
adminJobRetryRuns = /* @__PURE__ */ new Map();
|
|
10618
11020
|
feedbackDrafts = /* @__PURE__ */ new Map();
|
|
10619
|
-
pendingFeedbackSuggestionSessions = /* @__PURE__ */ new Set();
|
|
10620
11021
|
pendingTurns = /* @__PURE__ */ new Map();
|
|
10621
11022
|
drainTimers = /* @__PURE__ */ new Map();
|
|
10622
11023
|
drainBackoffMs = /* @__PURE__ */ new Map();
|
|
@@ -10636,7 +11037,6 @@ var StrataGateRuntime = class {
|
|
|
10636
11037
|
blockTurnSize;
|
|
10637
11038
|
blockDecayLambda;
|
|
10638
11039
|
agentMemoryRetrievalWeight;
|
|
10639
|
-
transientLastFeedbackPromptAt = null;
|
|
10640
11040
|
get agentMemoryEnabled() {
|
|
10641
11041
|
return this.config.agentMemoryEnabled !== false;
|
|
10642
11042
|
}
|
|
@@ -10797,7 +11197,9 @@ var StrataGateRuntime = class {
|
|
|
10797
11197
|
}
|
|
10798
11198
|
}
|
|
10799
11199
|
return resumed2;
|
|
10800
|
-
}
|
|
11200
|
+
},
|
|
11201
|
+
void 0,
|
|
11202
|
+
namespace
|
|
10801
11203
|
);
|
|
10802
11204
|
await this.persistSuccessfulResponses(memory);
|
|
10803
11205
|
const sessionsToSync = /* @__PURE__ */ new Set();
|
|
@@ -11170,6 +11572,12 @@ var StrataGateRuntime = class {
|
|
|
11170
11572
|
}
|
|
11171
11573
|
const memory = await this.space(session);
|
|
11172
11574
|
const assessment = memory.assessRetrieval(input, new Set(batch.refs.keys()));
|
|
11575
|
+
this.diagnostics.record({ namespace: this.namespaceFor(session), stage: "retrieval" }, {
|
|
11576
|
+
assessments: 1,
|
|
11577
|
+
sufficient: assessment.verdict === "sufficient" ? 1 : 0,
|
|
11578
|
+
partial: assessment.verdict === "partial" ? 1 : 0,
|
|
11579
|
+
wrong: assessment.verdict === "wrong" ? 1 : 0
|
|
11580
|
+
});
|
|
11173
11581
|
batch.assessment = assessment;
|
|
11174
11582
|
return {
|
|
11175
11583
|
batchId: batch.id,
|
|
@@ -11486,10 +11894,10 @@ var StrataGateRuntime = class {
|
|
|
11486
11894
|
await Promise.allSettled(this.externalImportRuns.values());
|
|
11487
11895
|
await Promise.allSettled(this.dreamingRuns.values());
|
|
11488
11896
|
await this.dreamingHost?.close();
|
|
11897
|
+
this.diagnostics.close();
|
|
11489
11898
|
await Promise.all(settled.flatMap((result) => result.status === "fulfilled" ? [result.value.close()] : []));
|
|
11490
11899
|
if (this.profileStorage) await this.profileStorage.close();
|
|
11491
11900
|
this.sessionsById.clear();
|
|
11492
|
-
this.pendingFeedbackSuggestionSessions.clear();
|
|
11493
11901
|
if (flushError !== void 0) throw flushError;
|
|
11494
11902
|
}
|
|
11495
11903
|
namespaceFor(session) {
|
|
@@ -11498,10 +11906,75 @@ var StrataGateRuntime = class {
|
|
|
11498
11906
|
if (this.config.namespaceMode === "session") return `${prefix}:session:${String(session.id)}`;
|
|
11499
11907
|
return `${prefix}:project:${projectKey(session.header.cwd)}`;
|
|
11500
11908
|
}
|
|
11909
|
+
trackDiagnosticSession(sessionId, namespace, memoryInputEstimate) {
|
|
11910
|
+
this.diagnosticSessionNamespaces.set(sessionId, namespace);
|
|
11911
|
+
if (memoryInputEstimate !== void 0) this.diagnosticMemoryEstimates.set(sessionId, memoryInputEstimate);
|
|
11912
|
+
if (this.diagnosticSessionNamespaces.size > 256) {
|
|
11913
|
+
const oldest = this.diagnosticSessionNamespaces.keys().next().value;
|
|
11914
|
+
this.diagnosticSessionNamespaces.delete(oldest);
|
|
11915
|
+
this.diagnosticMemoryEstimates.delete(oldest);
|
|
11916
|
+
}
|
|
11917
|
+
}
|
|
11918
|
+
diagnosticMemoryEstimate(sessionId) {
|
|
11919
|
+
return this.diagnosticMemoryEstimates.get(sessionId);
|
|
11920
|
+
}
|
|
11921
|
+
diagnosticNamespaceForSession(sessionId) {
|
|
11922
|
+
const session = this.knownSessions.get(sessionId)?.deref();
|
|
11923
|
+
return session ? this.namespaceFor(session) : this.diagnosticSessionNamespaces.get(sessionId);
|
|
11924
|
+
}
|
|
11925
|
+
async diagnosticReport(namespace, options = {}) {
|
|
11926
|
+
const collected = this.diagnostics.snapshot(namespace, options);
|
|
11927
|
+
const shared = this.diagnostics.snapshot("@shared");
|
|
11928
|
+
const base = { ...collected, sharedOrUnattributed: {
|
|
11929
|
+
stages: shared.stages,
|
|
11930
|
+
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"
|
|
11931
|
+
} };
|
|
11932
|
+
try {
|
|
11933
|
+
const snapshot = await this.adminSnapshot(namespace);
|
|
11934
|
+
if (!snapshot) return { ...base, pipeline: { available: false } };
|
|
11935
|
+
const stages = {
|
|
11936
|
+
summarizer: snapshot.summaryJobs,
|
|
11937
|
+
extractor: snapshot.extractionJobs,
|
|
11938
|
+
graphProjector: snapshot.graphProjectionJobs,
|
|
11939
|
+
topicProjector: (snapshot.memoryTopicState?.jobs ?? []).filter((job) => !job.superseded),
|
|
11940
|
+
externalMemoryImport: snapshot.externalMemoryImportJobs
|
|
11941
|
+
};
|
|
11942
|
+
const pipeline = Object.fromEntries(Object.entries(stages).map(([stage, jobs]) => [stage, {
|
|
11943
|
+
total: jobs.length,
|
|
11944
|
+
failed: jobs.filter((j) => j.status === "failed").length,
|
|
11945
|
+
succeeded: jobs.filter((j) => ["succeeded", "completed"].includes(j.status)).length,
|
|
11946
|
+
skipped: jobs.filter((j) => j.status === "skipped").length,
|
|
11947
|
+
pending: jobs.filter((j) => ["pending", "running", "processing", "extracting", "deciding"].includes(j.status)).length,
|
|
11948
|
+
oldestPendingUpdatedAt: jobs.filter((j) => ["pending", "running", "processing"].includes(j.status)).map((j) => j.updatedAt).sort()[0] ?? null
|
|
11949
|
+
}]));
|
|
11950
|
+
const adoptions = snapshot.usageReceipts.filter((r) => r.createdAt >= collected.since);
|
|
11951
|
+
const adopted = adoptions.filter((r) => r.eventIds.length > 0 || r.elementIds.length > 0);
|
|
11952
|
+
const sampledBlocks = snapshot.blocks.slice(-64);
|
|
11953
|
+
const layerTokenEstimates = Object.fromEntries([0, 1, 2, 3, 4, 5].map((level) => [
|
|
11954
|
+
`L${level}`,
|
|
11955
|
+
sampledBlocks.reduce((sum, block) => sum + estimateTokens(renderBlock(block, level)), 0)
|
|
11956
|
+
]));
|
|
11957
|
+
return { ...base, pipeline: { available: true, stages: pipeline }, benefits: {
|
|
11958
|
+
retrievalReceipts: adoptions.length,
|
|
11959
|
+
adoptionReceipts: adopted.length,
|
|
11960
|
+
adoptedEvents: adopted.reduce((n, r) => n + r.eventIds.length, 0),
|
|
11961
|
+
blocks: snapshot.blocks.length,
|
|
11962
|
+
events: snapshot.events.length,
|
|
11963
|
+
graphNodes: snapshot.graphNodes.length,
|
|
11964
|
+
sampledBlocks: sampledBlocks.length,
|
|
11965
|
+
layerTokenEstimates,
|
|
11966
|
+
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"
|
|
11967
|
+
} };
|
|
11968
|
+
} catch {
|
|
11969
|
+
return { ...base, pipeline: { available: false } };
|
|
11970
|
+
}
|
|
11971
|
+
}
|
|
11501
11972
|
async prepareFeedback(session, input) {
|
|
11502
11973
|
const namespace = this.namespaceFor(session);
|
|
11503
|
-
const previous = this.loadFeedbackDraft(namespace);
|
|
11974
|
+
const previous = input.newDraft ? null : this.loadFeedbackDraft(namespace);
|
|
11504
11975
|
const draft = normalizeFeedbackDraft(input, previous);
|
|
11976
|
+
draft.aiPrepared = true;
|
|
11977
|
+
draft.diagnostics = await this.diagnosticReport(namespace);
|
|
11505
11978
|
this.saveFeedbackDraft(namespace, draft);
|
|
11506
11979
|
const feedbackUrl = feedbackDraftUrl(namespace, this.feedbackOrigin());
|
|
11507
11980
|
return {
|
|
@@ -11510,7 +11983,7 @@ var StrataGateRuntime = class {
|
|
|
11510
11983
|
submitted: false,
|
|
11511
11984
|
namespace,
|
|
11512
11985
|
feedbackUrl,
|
|
11513
|
-
message: `\u53CD\u9988\u8349\u7A3F\u5DF2\
|
|
11986
|
+
message: `\u53CD\u9988\u8349\u7A3F\u5DF2\u4FDD\u5B58\u5728\u672C\u5730\uFF0C\u90AE\u4EF6\u5C1A\u672A\u53D1\u9001\u3002
|
|
11514
11987
|
|
|
11515
11988
|
[\u6253\u5F00\u53CD\u9988\u8349\u7A3F](${feedbackUrl})`
|
|
11516
11989
|
};
|
|
@@ -11615,46 +12088,13 @@ var StrataGateRuntime = class {
|
|
|
11615
12088
|
items.sort((left, right) => String(right.createdAt).localeCompare(String(left.createdAt)));
|
|
11616
12089
|
return { items, total: items.length };
|
|
11617
12090
|
}
|
|
11618
|
-
notePluginError(session,
|
|
11619
|
-
if (
|
|
11620
|
-
|
|
11621
|
-
takeFeedbackSuggestion(session, now = Date.now()) {
|
|
11622
|
-
if (!AGENT_FEEDBACK_ENABLED) return "";
|
|
11623
|
-
const sessionId = String(session.id);
|
|
11624
|
-
if (!this.pendingFeedbackSuggestionSessions.delete(sessionId)) return "";
|
|
11625
|
-
const last = this.lastFeedbackPromptAt();
|
|
11626
|
-
if (last && Number.isFinite(Date.parse(last)) && now - Date.parse(last) < FEEDBACK_PROMPT_COOLDOWN_MS) return "";
|
|
11627
|
-
const promptedAt = new Date(now).toISOString();
|
|
11628
|
-
this.transientLastFeedbackPromptAt = promptedAt;
|
|
11629
|
-
try {
|
|
11630
|
-
if (this.config.database !== ":memory:") {
|
|
11631
|
-
const metadata = new DshMetadataStore(this.config.database);
|
|
11632
|
-
try {
|
|
11633
|
-
metadata.setLastFeedbackPromptAt(promptedAt);
|
|
11634
|
-
} finally {
|
|
11635
|
-
metadata.close();
|
|
11636
|
-
}
|
|
11637
|
-
}
|
|
11638
|
-
} catch (error) {
|
|
11639
|
-
this.onIngestError(error);
|
|
11640
|
-
}
|
|
11641
|
-
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.";
|
|
12091
|
+
notePluginError(session, error, stage = "ingestion") {
|
|
12092
|
+
if (this.closed) return;
|
|
12093
|
+
this.diagnostics.record({ namespace: this.namespaceFor(session), stage }, { errors: 1 }, { error: error ?? "internal failure" });
|
|
11642
12094
|
}
|
|
11643
|
-
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
try {
|
|
11647
|
-
const metadata = new DshMetadataStore(this.config.database);
|
|
11648
|
-
try {
|
|
11649
|
-
this.transientLastFeedbackPromptAt = metadata.lastFeedbackPromptAt();
|
|
11650
|
-
return this.transientLastFeedbackPromptAt;
|
|
11651
|
-
} finally {
|
|
11652
|
-
metadata.close();
|
|
11653
|
-
}
|
|
11654
|
-
} catch (error) {
|
|
11655
|
-
this.onIngestError(error);
|
|
11656
|
-
return null;
|
|
11657
|
-
}
|
|
12095
|
+
// Background failures remain queryable; ordinary retries never add model context.
|
|
12096
|
+
takeFeedbackSuggestion(_session, _now = Date.now()) {
|
|
12097
|
+
return "";
|
|
11658
12098
|
}
|
|
11659
12099
|
loadFeedbackDraft(namespace) {
|
|
11660
12100
|
const cached = this.feedbackDrafts.get(namespace);
|
|
@@ -11664,7 +12104,7 @@ var StrataGateRuntime = class {
|
|
|
11664
12104
|
try {
|
|
11665
12105
|
const value = metadata.feedbackDraft(namespace);
|
|
11666
12106
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
11667
|
-
const draft = normalizeFeedbackDraft(value);
|
|
12107
|
+
const draft = normalizeFeedbackDraft(value, value);
|
|
11668
12108
|
this.feedbackDrafts.set(namespace, draft);
|
|
11669
12109
|
return structuredClone(draft);
|
|
11670
12110
|
} finally {
|
|
@@ -11672,14 +12112,15 @@ var StrataGateRuntime = class {
|
|
|
11672
12112
|
}
|
|
11673
12113
|
}
|
|
11674
12114
|
saveFeedbackDraft(namespace, draft) {
|
|
11675
|
-
this.
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
|
|
11679
|
-
|
|
11680
|
-
|
|
11681
|
-
|
|
12115
|
+
if (this.config.database !== ":memory:") {
|
|
12116
|
+
const metadata = new DshMetadataStore(this.config.database);
|
|
12117
|
+
try {
|
|
12118
|
+
metadata.setFeedbackDraft(namespace, draft);
|
|
12119
|
+
} finally {
|
|
12120
|
+
metadata.close();
|
|
12121
|
+
}
|
|
11682
12122
|
}
|
|
12123
|
+
this.feedbackDrafts.set(namespace, structuredClone(draft));
|
|
11683
12124
|
}
|
|
11684
12125
|
async adminNamespaces() {
|
|
11685
12126
|
if (this.config.database === ":memory:" || !existsSync(this.config.database)) return [];
|
|
@@ -11934,7 +12375,7 @@ var StrataGateRuntime = class {
|
|
|
11934
12375
|
} finally {
|
|
11935
12376
|
if (owned) await memory.close();
|
|
11936
12377
|
}
|
|
11937
|
-
const action = await this.models.runDetached(`dreaming:${run.id}`, () => this.models.dreamingStep(payload), controller.signal);
|
|
12378
|
+
const action = await this.models.runDetached(`dreaming:${run.id}`, () => this.models.dreamingStep(payload), controller.signal, namespace);
|
|
11938
12379
|
if (controller.signal.aborted) return;
|
|
11939
12380
|
const repeated = run.trace.filter((entry) => entry.tool === action.tool && JSON.stringify(entry.args) === JSON.stringify(action.args)).length;
|
|
11940
12381
|
if (repeated >= 3) {
|
|
@@ -12028,7 +12469,7 @@ var StrataGateRuntime = class {
|
|
|
12028
12469
|
}
|
|
12029
12470
|
try {
|
|
12030
12471
|
if (job.status === "extracting") {
|
|
12031
|
-
const recovered = await this.models.runDetached(`admin-import-recovery:${jobId}`, () => this.models.externalMemoryExtractor({ text: job.text, importedAt: job.importedAt }));
|
|
12472
|
+
const recovered = await this.models.runDetached(`admin-import-recovery:${jobId}`, () => this.models.externalMemoryExtractor({ text: job.text, importedAt: job.importedAt }), void 0, namespace);
|
|
12032
12473
|
const responses2 = this.takeSuccessfulResponses();
|
|
12033
12474
|
await this.retryExternalImportWrite(namespace, (memory) => memory.completeExternalMemoryFallback(jobId, recovered));
|
|
12034
12475
|
await this.persistExternalImportResponses(namespace, responses2);
|
|
@@ -12043,7 +12484,7 @@ var StrataGateRuntime = class {
|
|
|
12043
12484
|
decision = await this.models.runDetached(`admin-import:${jobId}`, () => this.models.externalMemoryDecider({
|
|
12044
12485
|
candidate: structuredClone(work.candidate),
|
|
12045
12486
|
matches: structuredClone(work.matches)
|
|
12046
|
-
}));
|
|
12487
|
+
}), void 0, namespace);
|
|
12047
12488
|
responses = this.takeSuccessfulResponses();
|
|
12048
12489
|
}
|
|
12049
12490
|
await this.retryExternalImportWrite(namespace, (memory) => memory.completeNextExternalMemoryImport(
|
|
@@ -12184,7 +12625,7 @@ var StrataGateRuntime = class {
|
|
|
12184
12625
|
const remembered = this.workspaceNames.get(namespace);
|
|
12185
12626
|
if (remembered) return remembered;
|
|
12186
12627
|
if (this.config.database === ":memory:" || !existsSync(this.config.database)) return null;
|
|
12187
|
-
const database = new
|
|
12628
|
+
const database = new DatabaseSync4(this.config.database, { readOnly: true });
|
|
12188
12629
|
try {
|
|
12189
12630
|
if (!database.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'stratagate_dsh_workspaces'").get()) {
|
|
12190
12631
|
return null;
|
|
@@ -12314,7 +12755,7 @@ var StrataGateRuntime = class {
|
|
|
12314
12755
|
if (!this.models.isReady(session)) {
|
|
12315
12756
|
throw new Error("StrataGate model adapter is not ready; retry after DSH finishes registering adapters");
|
|
12316
12757
|
}
|
|
12317
|
-
const result = session && this.namespaceFor(session) === key ? await this.models.run(session, retry) : await this.models.runDetached(threadId, retry);
|
|
12758
|
+
const result = session && this.namespaceFor(session) === key ? await this.models.run(session, retry) : await this.models.runDetached(threadId, retry, void 0, namespace);
|
|
12318
12759
|
await this.persistSuccessfulResponses(memory);
|
|
12319
12760
|
const currentBlock = blockId ? memory.listBlocks().find(({ id: candidateId }) => candidateId === blockId) : void 0;
|
|
12320
12761
|
if (kind !== "graph-projection" && currentBlock?.processingStatus === "ready" && currentBlock.threadId) {
|
|
@@ -12689,6 +13130,12 @@ var StrataGateRuntime = class {
|
|
|
12689
13130
|
}
|
|
12690
13131
|
sessionBatches.set(id, { id, sequence, refs, status: "unresolved" });
|
|
12691
13132
|
this.latestBatchIds.set(key, id);
|
|
13133
|
+
this.diagnostics.record({ namespace: this.namespaceFor(session), stage: "retrieval" }, {
|
|
13134
|
+
batches: 1,
|
|
13135
|
+
emptyBatches: evidence.length === 0 ? 1 : 0,
|
|
13136
|
+
returnedRefs: refs.size,
|
|
13137
|
+
resultTokensEstimate: estimateTokens(JSON.stringify(output))
|
|
13138
|
+
});
|
|
12692
13139
|
return output;
|
|
12693
13140
|
}
|
|
12694
13141
|
requireBatch(session, batchId, operation) {
|
|
@@ -13278,6 +13725,7 @@ ${profile}
|
|
|
13278
13725
|
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");
|
|
13279
13726
|
}
|
|
13280
13727
|
install(scoped, binding) {
|
|
13728
|
+
this.runtime.trackDiagnosticSession(String(binding.agent.id), binding.namespace);
|
|
13281
13729
|
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");
|
|
13282
13730
|
const modelTools = TOOLS.map((tool) => ({
|
|
13283
13731
|
name: tool.name,
|
|
@@ -13536,6 +13984,11 @@ ${profile}
|
|
|
13536
13984
|
|
|
13537
13985
|
// src/tools.ts
|
|
13538
13986
|
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
|
13987
|
+
|
|
13988
|
+
// src/feedback-policy.ts
|
|
13989
|
+
var AGENT_FEEDBACK_ENABLED = true;
|
|
13990
|
+
|
|
13991
|
+
// src/tools.ts
|
|
13539
13992
|
var jsonOutput = {
|
|
13540
13993
|
schema: { type: "json" },
|
|
13541
13994
|
render: (_args, value) => [{
|
|
@@ -13576,17 +14029,19 @@ function registerMemoryTools(ctx, runtime) {
|
|
|
13576
14029
|
}));
|
|
13577
14030
|
if (AGENT_FEEDBACK_ENABLED) ctx.tools.register(defineTool2({
|
|
13578
14031
|
name: "feedback_prepare",
|
|
13579
|
-
description:
|
|
14032
|
+
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",
|
|
13580
14033
|
parameters: {
|
|
13581
|
-
|
|
13582
|
-
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
|
|
14034
|
+
new_draft: { type: "boolean", description: "\u65B0\u95EE\u9898\u4E3A true\uFF1B\u4FEE\u6539\u5DF2\u6709\u8349\u7A3F\u65F6\u7701\u7565\u3002" },
|
|
14035
|
+
title: { type: "string", description: "\u7B80\u77ED\u95EE\u9898\u6807\u9898\u3002" },
|
|
14036
|
+
description: { type: "string", description: "\u5DF2\u77E5\u95EE\u9898\u3001\u5EFA\u8BAE\u6216\u7591\u95EE\u3002" },
|
|
14037
|
+
reproduction: { type: "array", items: { type: "string" }, description: "\u5B9E\u9645\u53D1\u751F\u8FC7\u7684\u590D\u73B0\u6B65\u9AA4\u3002" },
|
|
14038
|
+
expected: { type: "string", description: "\u5DF2\u77E5\u9884\u671F\u7ED3\u679C\u3002" },
|
|
14039
|
+
actual: { type: "string", description: "\u5B9E\u9645\u89C2\u5BDF\u5230\u7684\u7ED3\u679C\u3002" },
|
|
14040
|
+
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" }
|
|
13587
14041
|
},
|
|
13588
14042
|
output: jsonOutput,
|
|
13589
14043
|
execute: async (args, exec) => runtime.prepareFeedback(sessionOf(exec), {
|
|
14044
|
+
...args.new_draft !== void 0 ? { newDraft: args.new_draft } : {},
|
|
13590
14045
|
...args.title !== void 0 ? { title: args.title } : {},
|
|
13591
14046
|
...args.description !== void 0 ? { description: args.description } : {},
|
|
13592
14047
|
...args.reproduction !== void 0 ? { reproduction: args.reproduction } : {},
|
|
@@ -13595,6 +14050,19 @@ function registerMemoryTools(ctx, runtime) {
|
|
|
13595
14050
|
...args.error_context !== void 0 ? { errorContext: args.error_context } : {}
|
|
13596
14051
|
})
|
|
13597
14052
|
}));
|
|
14053
|
+
if (AGENT_FEEDBACK_ENABLED) ctx.tools.register(defineTool2({
|
|
14054
|
+
name: "stratagate_diagnostics",
|
|
14055
|
+
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",
|
|
14056
|
+
parameters: {
|
|
14057
|
+
id: { type: "string", description: "\u6458\u8981\u4E2D\u8FD4\u56DE\u7684\u8BCA\u65AD ID\uFF1B\u63D0\u4F9B\u65F6\u8BFB\u53D6\u8BE5\u6761\u8BE6\u60C5\u3002" },
|
|
14058
|
+
offset: { type: "integer", description: "\u4F7F\u7528\u8FD4\u56DE\u7684 nextOffset \u7EE7\u7EED\u8BFB\u53D6\u8FD1\u671F\u5F02\u5E38\u3002" }
|
|
14059
|
+
},
|
|
14060
|
+
output: jsonOutput,
|
|
14061
|
+
execute: async (args, exec) => runtime.diagnosticReport(runtime.namespaceFor(sessionOf(exec)), {
|
|
14062
|
+
...args.id !== void 0 ? { id: args.id, details: true } : {},
|
|
14063
|
+
...args.offset !== void 0 ? { offset: args.offset } : {}
|
|
14064
|
+
})
|
|
14065
|
+
}));
|
|
13598
14066
|
ctx.tools.register(defineTool2({
|
|
13599
14067
|
name: "memory_list_topics",
|
|
13600
14068
|
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",
|
|
@@ -13773,7 +14241,7 @@ function registerMemoryTools(ctx, runtime) {
|
|
|
13773
14241
|
|
|
13774
14242
|
// src/web.ts
|
|
13775
14243
|
import { createHash as createHash4 } from "node:crypto";
|
|
13776
|
-
import { createRequire as
|
|
14244
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
13777
14245
|
|
|
13778
14246
|
// src/graph-clustering.ts
|
|
13779
14247
|
import createGraph from "ngraph.graph";
|
|
@@ -13887,7 +14355,7 @@ function clusterKnowledgeGraph(rawNodes, rawEdges) {
|
|
|
13887
14355
|
|
|
13888
14356
|
// src/web.ts
|
|
13889
14357
|
var LEGACY_THREAD_ID = "__legacy__";
|
|
13890
|
-
var nodeRequire2 =
|
|
14358
|
+
var nodeRequire2 = createRequire3(import.meta.url);
|
|
13891
14359
|
function currentPluginVersion() {
|
|
13892
14360
|
try {
|
|
13893
14361
|
const value = nodeRequire2("../package.json");
|
|
@@ -14646,7 +15114,8 @@ async function feedback(runtime, req, url) {
|
|
|
14646
15114
|
if (req.method === "GET") {
|
|
14647
15115
|
const namespace2 = url.searchParams.get("namespace")?.trim() ?? "";
|
|
14648
15116
|
if (!namespace2) throw new AdminHttpError(400, "namespace is required");
|
|
14649
|
-
|
|
15117
|
+
const result = runtime.adminFeedbackDraft(namespace2);
|
|
15118
|
+
return { ...result, diagnostics: result.draft?.diagnostics ?? await runtime.diagnosticReport?.(namespace2) };
|
|
14650
15119
|
}
|
|
14651
15120
|
if (req.method !== "PUT") throw new AdminHttpError(405, "StrataGate feedback requires GET or PUT");
|
|
14652
15121
|
let suppliedBody = req.body;
|
|
@@ -15298,6 +15767,19 @@ async function handleAdminRequest(runtime, req, res) {
|
|
|
15298
15767
|
const path = url.pathname.replace(/\/$/, "");
|
|
15299
15768
|
if (path === "/api/stratagate/feedback") {
|
|
15300
15769
|
sendJson(res, 200, await feedback(runtime, req, url));
|
|
15770
|
+
} else if (path === "/api/stratagate/diagnostics") {
|
|
15771
|
+
const namespace = url.searchParams.get("namespace")?.trim() ?? "";
|
|
15772
|
+
if (!namespace) throw new AdminHttpError(400, "namespace is required");
|
|
15773
|
+
if (req.method === "POST") {
|
|
15774
|
+
const category = url.searchParams.get("category") ?? "";
|
|
15775
|
+
if (!["timeout", "network", "request-failed"].includes(category)) throw new AdminHttpError(400, "Unknown frontend diagnostic category");
|
|
15776
|
+
runtime.diagnostics.record({ namespace, stage: "frontend" }, { errors: 1 }, { error: category });
|
|
15777
|
+
sendJson(res, 200, { recorded: true });
|
|
15778
|
+
return;
|
|
15779
|
+
}
|
|
15780
|
+
if (req.method !== "GET") throw new AdminHttpError(405, "StrataGate diagnostics require GET or POST");
|
|
15781
|
+
const id = url.searchParams.get("id") ?? void 0;
|
|
15782
|
+
sendJson(res, 200, await runtime.diagnosticReport(namespace, { ...id ? { id, details: true } : {}, offset: numeric(url.searchParams.get("offset"), 0, 0, 2e3) }));
|
|
15301
15783
|
} else if (path === "/api/stratagate/profile") {
|
|
15302
15784
|
sendJson(res, 200, await persistentProfile(runtime, req), true);
|
|
15303
15785
|
} else if (path === "/api/stratagate/settings") {
|
|
@@ -15464,7 +15946,7 @@ import {
|
|
|
15464
15946
|
writeFile
|
|
15465
15947
|
} from "node:fs/promises";
|
|
15466
15948
|
import { basename, dirname as dirname2, join } from "node:path";
|
|
15467
|
-
import { createHash as createHash5, randomUUID as
|
|
15949
|
+
import { createHash as createHash5, randomUUID as randomUUID6 } from "node:crypto";
|
|
15468
15950
|
import { encodeSeqRanges, KNOWN_SESSION_EVENT_TYPES } from "@deepseek-ai/dsh-session";
|
|
15469
15951
|
var LEGACY_EVENT_TYPE = "stratagate/memory-citations";
|
|
15470
15952
|
var COMPAT_EVENT_TYPE = "feedback/record";
|
|
@@ -15685,7 +16167,7 @@ async function exists(path) {
|
|
|
15685
16167
|
}
|
|
15686
16168
|
async function publishExclusive(path, bytes) {
|
|
15687
16169
|
await mkdir(dirname2(path), { recursive: true });
|
|
15688
|
-
const temporary = join(dirname2(path), `.${basename(path)}.stratagate-${
|
|
16170
|
+
const temporary = join(dirname2(path), `.${basename(path)}.stratagate-${randomUUID6()}.tmp`);
|
|
15689
16171
|
const handle = await open(temporary, "wx", 384);
|
|
15690
16172
|
try {
|
|
15691
16173
|
await handle.writeFile(bytes);
|
|
@@ -15810,15 +16292,8 @@ Memory writing:
|
|
|
15810
16292
|
- 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.
|
|
15811
16293
|
- 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.`;
|
|
15812
16294
|
var FEEDBACK_PROTOCOL = `[StrataGate feedback policy]
|
|
15813
|
-
|
|
15814
|
-
|
|
15815
|
-
- 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.
|
|
15816
|
-
- 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.
|
|
15817
|
-
- 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.
|
|
15818
|
-
- 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.
|
|
15819
|
-
- 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.
|
|
15820
|
-
- 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.
|
|
15821
|
-
- 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.`;
|
|
16295
|
+
\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
|
|
16296
|
+
\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`;
|
|
15822
16297
|
function renderError(error) {
|
|
15823
16298
|
return error instanceof Error ? error.message : String(error);
|
|
15824
16299
|
}
|
|
@@ -15899,27 +16374,48 @@ async function apply(ctx, config) {
|
|
|
15899
16374
|
autoMemory = { name: "stratagate:auto-memory", text: text3 };
|
|
15900
16375
|
} catch (error) {
|
|
15901
16376
|
ctx.logger.warn(`stratagate-memory auto-context failed: ${renderError(error)}`);
|
|
15902
|
-
|
|
16377
|
+
runtime.notePluginError(session, error, "autoContext");
|
|
15903
16378
|
}
|
|
15904
16379
|
try {
|
|
15905
16380
|
const directory = await runtime.buildMemoryDirectory(session);
|
|
15906
16381
|
if (directory) contexts.push({ name: "stratagate:memory-directory", text: directory });
|
|
15907
16382
|
} catch (error) {
|
|
15908
16383
|
ctx.logger.warn(`stratagate-memory directory failed: ${renderError(error)}`);
|
|
15909
|
-
|
|
16384
|
+
runtime.notePluginError(session, error, "directory");
|
|
15910
16385
|
}
|
|
15911
16386
|
if (autoMemory) contexts.push(autoMemory);
|
|
15912
|
-
const
|
|
15913
|
-
|
|
16387
|
+
const toolSchemas = ctx.tools.schemas(context.agent).filter(({ name: name2 }) => name2.startsWith("memory_") || name2 === "feedback_prepare" || name2 === "stratagate_diagnostics");
|
|
16388
|
+
runtime.trackDiagnosticSession(String(session.id), runtime.namespaceFor(session), estimateTokens(JSON.stringify({
|
|
16389
|
+
sections: assembled.sections.filter(({ name: name2 }) => name2.startsWith("tool:stratagate-")),
|
|
16390
|
+
contexts: contexts.filter(({ name: name2 }) => name2.startsWith("stratagate:")),
|
|
16391
|
+
tools: toolSchemas
|
|
16392
|
+
})));
|
|
15914
16393
|
return { ...assembled, contexts };
|
|
15915
16394
|
});
|
|
15916
16395
|
installRetrievalFinalization(ctx, runtime);
|
|
15917
16396
|
registerMemoryTools(ctx, runtime);
|
|
15918
|
-
ctx.on("
|
|
15919
|
-
if (
|
|
15920
|
-
|
|
15921
|
-
|
|
16397
|
+
ctx.on("llm/stream", async function* (options, next) {
|
|
16398
|
+
if (models.currentDiagnosticScope()) {
|
|
16399
|
+
yield* next();
|
|
16400
|
+
return;
|
|
15922
16401
|
}
|
|
16402
|
+
const namespace = runtime.diagnosticNamespaceForSession(String(options.sessionId ?? ""));
|
|
16403
|
+
if (!namespace || options.purpose) {
|
|
16404
|
+
yield* next();
|
|
16405
|
+
return;
|
|
16406
|
+
}
|
|
16407
|
+
const stage = String(options.sessionId).startsWith("stratagate-dreaming:") ? "dreamingStep" : "chat";
|
|
16408
|
+
const memoryInputEstimate = runtime.diagnosticMemoryEstimate(String(options.sessionId));
|
|
16409
|
+
yield* observeModelStream(runtime.diagnostics, { namespace, stage, ...memoryInputEstimate !== void 0 ? { memoryInputEstimate } : {} }, options, next);
|
|
16410
|
+
});
|
|
16411
|
+
ctx.on("tools/result", (exec, result) => {
|
|
16412
|
+
if (!exec.agent || !(exec.name === "feedback_prepare" || exec.name === "stratagate_diagnostics" || exec.name.startsWith("memory_"))) return;
|
|
16413
|
+
const namespace = runtime.namespaceFor(exec.agent.session);
|
|
16414
|
+
runtime.diagnostics.record(
|
|
16415
|
+
{ namespace, stage: "tools" },
|
|
16416
|
+
{ toolCalls: 1, toolFailures: result.isError ? 1 : 0 },
|
|
16417
|
+
result.isError ? { error: result.error.message } : {}
|
|
16418
|
+
);
|
|
15923
16419
|
});
|
|
15924
16420
|
const disposeAdminRoutes = registerAdminRoutes(ctx, runtime);
|
|
15925
16421
|
ctx.on("session/event", (session, event) => runtime.acceptEvent(session, event));
|