stratagate-dsh 0.2.16 → 0.2.19
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 +17 -0
- package/README.md +9 -4
- package/cordis.patch.yml +1 -0
- package/dist/client.js +89 -52
- package/dist/index.d.ts +1 -0
- package/dist/index.js +307 -43
- package/dist/index.js.map +1 -1
- package/docs/README.zh-CN.md +9 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ var Config = z.object({
|
|
|
11
11
|
namespacePrefix: z.string().default("dsh"),
|
|
12
12
|
globalNamespace: z.string().default("global"),
|
|
13
13
|
blockTurnSize: z.natural().min(1).default(6),
|
|
14
|
+
blockDecayLambda: z.number().step(0.05).min(0).default(0.3).description("Block \u8870\u51CF\u7CFB\u6570 \u03BB").comment("\u9ED8\u8BA4 0.3\uFF1B\u6570\u5B57\u8D8A\u5C0F\uFF0C\u8BB0\u5FC6\u9057\u5FD8\u8D8A\u6162\uFF0C\u6D88\u8017 token \u8D8A\u591A\uFF0C\u4E0D\u5EFA\u8BAE\u5927\u4E8E 0.4\u3002"),
|
|
14
15
|
ingestSubagents: z.boolean().default(false),
|
|
15
16
|
provider: z.string(),
|
|
16
17
|
model: z.string(),
|
|
@@ -32,6 +33,7 @@ function resolveConfig(config) {
|
|
|
32
33
|
namespacePrefix,
|
|
33
34
|
globalNamespace,
|
|
34
35
|
blockTurnSize: Math.max(1, Math.floor(config.blockTurnSize ?? 6)),
|
|
36
|
+
blockDecayLambda: Math.max(0, config.blockDecayLambda ?? 0.3),
|
|
35
37
|
ingestSubagents: config.ingestSubagents ?? false,
|
|
36
38
|
...provider && model ? { provider, model } : {},
|
|
37
39
|
maxOutputTokens: Math.max(256, Math.floor(config.maxOutputTokens ?? 1e4))
|
|
@@ -46,7 +48,7 @@ import { parameterSchemaSpecToJsonSchema, validateArgs } from "@deepseek-ai/dsh-
|
|
|
46
48
|
// ../../src/blocks.ts
|
|
47
49
|
var DEFAULT_BLOCK_TURN_SIZE = 12;
|
|
48
50
|
var BLOCK_MAX_LEVEL = 5;
|
|
49
|
-
var BLOCK_DECAY_LAMBDA = 0.
|
|
51
|
+
var BLOCK_DECAY_LAMBDA = 0.3;
|
|
50
52
|
var FILLER_ONLY = /* @__PURE__ */ new Set([
|
|
51
53
|
"ok",
|
|
52
54
|
"okay",
|
|
@@ -80,11 +82,11 @@ var REPEATED_PASTE_MARKER = "[repeated paste omitted; original remains in L5]";
|
|
|
80
82
|
function asBlockLevel(value) {
|
|
81
83
|
return Math.max(0, Math.min(BLOCK_MAX_LEVEL, Math.round(value)));
|
|
82
84
|
}
|
|
83
|
-
function getBlockWeight(
|
|
84
|
-
return Math.exp(-
|
|
85
|
+
function getBlockWeight(anchorBlockPosition, latestBlockPosition, lambda = BLOCK_DECAY_LAMBDA) {
|
|
86
|
+
return Math.exp(-lambda * Math.max(0, latestBlockPosition - anchorBlockPosition));
|
|
85
87
|
}
|
|
86
|
-
function getDecayedBlockLevel(anchorLevel,
|
|
87
|
-
const weight = getBlockWeight(
|
|
88
|
+
function getDecayedBlockLevel(anchorLevel, anchorBlockPosition, latestBlockPosition, lambda = BLOCK_DECAY_LAMBDA) {
|
|
89
|
+
const weight = getBlockWeight(anchorBlockPosition, latestBlockPosition, lambda);
|
|
88
90
|
const droppedLevels = weight > 0.7 ? 0 : weight > 0.5 ? 1 : weight > 0.3 ? 2 : weight > 0.15 ? 3 : weight > 0.08 ? 4 : 5;
|
|
89
91
|
return asBlockLevel(anchorLevel - droppedLevels);
|
|
90
92
|
}
|
|
@@ -358,7 +360,7 @@ function rrfRank(rankings) {
|
|
|
358
360
|
}
|
|
359
361
|
|
|
360
362
|
// ../../src/storage.ts
|
|
361
|
-
var STRATAGATE_STORAGE_SCHEMA_VERSION =
|
|
363
|
+
var STRATAGATE_STORAGE_SCHEMA_VERSION = 6;
|
|
362
364
|
var StorageConflictError = class extends Error {
|
|
363
365
|
constructor(namespace, expectedRevision, actualRevision) {
|
|
364
366
|
super(`Storage revision conflict for ${namespace}: expected ${expectedRevision}, found ${actualRevision ?? "missing"}`);
|
|
@@ -374,6 +376,13 @@ var StorageConflictError = class extends Error {
|
|
|
374
376
|
function cloneSnapshot(snapshot) {
|
|
375
377
|
return structuredClone(snapshot);
|
|
376
378
|
}
|
|
379
|
+
function migrateLegacyBlocks(blocks) {
|
|
380
|
+
return blocks.map((block) => {
|
|
381
|
+
const { pointerAnchorTurn, ...current } = block;
|
|
382
|
+
const position = blocks.filter((candidate) => candidate.threadId === block.threadId && candidate.endTurn <= pointerAnchorTurn).length;
|
|
383
|
+
return { ...current, pointerAnchorBlockPosition: Math.max(1, position) };
|
|
384
|
+
});
|
|
385
|
+
}
|
|
377
386
|
function normalizeSnapshot(value) {
|
|
378
387
|
if (!value || typeof value !== "object") throw new TypeError("Invalid StrataGate snapshot: expected an object");
|
|
379
388
|
const schemaVersion = value.schemaVersion;
|
|
@@ -383,26 +392,45 @@ function normalizeSnapshot(value) {
|
|
|
383
392
|
snapshot = {
|
|
384
393
|
...structuredClone(legacy),
|
|
385
394
|
schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION,
|
|
395
|
+
blockDecayLambda: BLOCK_DECAY_LAMBDA,
|
|
396
|
+
blocks: migrateLegacyBlocks(legacy.blocks),
|
|
386
397
|
elements: [],
|
|
387
398
|
elementProjectionJobs: [],
|
|
388
399
|
usageReceipts: Array.isArray(legacy.usageReceipts) ? legacy.usageReceipts.map((receipt) => ({ ...receipt, elementIds: [] })) : [],
|
|
389
400
|
ingestionReceipts: []
|
|
390
401
|
};
|
|
391
402
|
} else if (schemaVersion === 2) {
|
|
403
|
+
const legacy = value;
|
|
392
404
|
snapshot = {
|
|
393
|
-
...structuredClone(
|
|
405
|
+
...structuredClone(legacy),
|
|
394
406
|
schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION,
|
|
407
|
+
blockDecayLambda: BLOCK_DECAY_LAMBDA,
|
|
408
|
+
blocks: migrateLegacyBlocks(legacy.blocks),
|
|
395
409
|
ingestionReceipts: []
|
|
396
410
|
};
|
|
397
411
|
} else if (schemaVersion === 3) {
|
|
412
|
+
const legacy = value;
|
|
398
413
|
snapshot = {
|
|
399
|
-
...structuredClone(
|
|
400
|
-
schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION
|
|
414
|
+
...structuredClone(legacy),
|
|
415
|
+
schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION,
|
|
416
|
+
blockDecayLambda: BLOCK_DECAY_LAMBDA,
|
|
417
|
+
blocks: migrateLegacyBlocks(legacy.blocks)
|
|
401
418
|
};
|
|
402
419
|
} else if (schemaVersion === 4) {
|
|
420
|
+
const legacy = value;
|
|
421
|
+
snapshot = {
|
|
422
|
+
...structuredClone(legacy),
|
|
423
|
+
schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION,
|
|
424
|
+
blockDecayLambda: BLOCK_DECAY_LAMBDA,
|
|
425
|
+
blocks: migrateLegacyBlocks(legacy.blocks)
|
|
426
|
+
};
|
|
427
|
+
} else if (schemaVersion === 5) {
|
|
428
|
+
const legacy = value;
|
|
403
429
|
snapshot = {
|
|
404
|
-
...structuredClone(
|
|
405
|
-
schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION
|
|
430
|
+
...structuredClone(legacy),
|
|
431
|
+
schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION,
|
|
432
|
+
blockDecayLambda: BLOCK_DECAY_LAMBDA,
|
|
433
|
+
blocks: migrateLegacyBlocks(legacy.blocks)
|
|
406
434
|
};
|
|
407
435
|
} else if (schemaVersion === STRATAGATE_STORAGE_SCHEMA_VERSION) {
|
|
408
436
|
snapshot = structuredClone(value);
|
|
@@ -415,10 +443,18 @@ function normalizeSnapshot(value) {
|
|
|
415
443
|
if (!Number.isSafeInteger(snapshot.blockTurnSize) || (snapshot.blockTurnSize ?? 0) < 1) {
|
|
416
444
|
throw new TypeError("Invalid StrataGate snapshot: blockTurnSize must be a positive integer");
|
|
417
445
|
}
|
|
446
|
+
if (!Number.isFinite(snapshot.blockDecayLambda) || snapshot.blockDecayLambda < 0) {
|
|
447
|
+
throw new TypeError("Invalid StrataGate snapshot: blockDecayLambda must be a non-negative finite number");
|
|
448
|
+
}
|
|
418
449
|
for (const key of ["openTail", "blocks", "events", "elements", "extractionJobs", "elementProjectionJobs", "usageReceipts", "ingestionReceipts"]) {
|
|
419
450
|
if (!Array.isArray(snapshot[key])) throw new TypeError(`Invalid StrataGate snapshot: ${key} must be an array`);
|
|
420
451
|
}
|
|
421
452
|
if (!Array.isArray(snapshot.successfulModelResponses)) snapshot.successfulModelResponses = [];
|
|
453
|
+
for (const block of snapshot.blocks) {
|
|
454
|
+
if (!Number.isSafeInteger(block.pointerAnchorBlockPosition) || block.pointerAnchorBlockPosition < 1) {
|
|
455
|
+
throw new TypeError("Invalid StrataGate snapshot: pointerAnchorBlockPosition must be a positive integer");
|
|
456
|
+
}
|
|
457
|
+
}
|
|
422
458
|
if (snapshot.successfulModelResponses.length > 5) {
|
|
423
459
|
snapshot.successfulModelResponses = snapshot.successfulModelResponses.slice(-5);
|
|
424
460
|
}
|
|
@@ -592,6 +628,7 @@ CREATE TABLE IF NOT EXISTS memory_spaces (
|
|
|
592
628
|
revision INTEGER NOT NULL,
|
|
593
629
|
current_turn INTEGER NOT NULL,
|
|
594
630
|
block_turn_size INTEGER NOT NULL,
|
|
631
|
+
block_decay_lambda REAL NOT NULL,
|
|
595
632
|
created_at TEXT NOT NULL,
|
|
596
633
|
updated_at TEXT NOT NULL
|
|
597
634
|
) STRICT;
|
|
@@ -613,7 +650,7 @@ CREATE TABLE IF NOT EXISTS blocks (
|
|
|
613
650
|
l4_readable TEXT NOT NULL,
|
|
614
651
|
pointer_current_level INTEGER NOT NULL,
|
|
615
652
|
pointer_anchor_level INTEGER NOT NULL,
|
|
616
|
-
|
|
653
|
+
pointer_anchor_block_position INTEGER NOT NULL,
|
|
617
654
|
last_lifted_at TEXT,
|
|
618
655
|
PRIMARY KEY (namespace, id),
|
|
619
656
|
UNIQUE (namespace, sequence),
|
|
@@ -831,7 +868,7 @@ var SqliteStorage = class {
|
|
|
831
868
|
this.assertOpen();
|
|
832
869
|
const key = nonEmptyNamespace(namespace);
|
|
833
870
|
const space = this.database.prepare(`
|
|
834
|
-
SELECT schema_version, revision, current_turn, block_turn_size
|
|
871
|
+
SELECT schema_version, revision, current_turn, block_turn_size, block_decay_lambda
|
|
835
872
|
FROM memory_spaces WHERE namespace = ?
|
|
836
873
|
`).get(key);
|
|
837
874
|
if (!space) return null;
|
|
@@ -880,7 +917,7 @@ var SqliteStorage = class {
|
|
|
880
917
|
l5Raw: messagesByBlock.get(row.id) ?? [],
|
|
881
918
|
pointerCurrentLevel: row.pointer_current_level,
|
|
882
919
|
pointerAnchorLevel: row.pointer_anchor_level,
|
|
883
|
-
|
|
920
|
+
pointerAnchorBlockPosition: row.pointer_anchor_block_position,
|
|
884
921
|
lastLiftedAt: row.last_lifted_at
|
|
885
922
|
}));
|
|
886
923
|
const sourceRows = this.database.prepare(`
|
|
@@ -1047,6 +1084,7 @@ var SqliteStorage = class {
|
|
|
1047
1084
|
schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION,
|
|
1048
1085
|
currentTurn: space.current_turn,
|
|
1049
1086
|
blockTurnSize: space.block_turn_size,
|
|
1087
|
+
blockDecayLambda: space.block_decay_lambda,
|
|
1050
1088
|
openTail,
|
|
1051
1089
|
blocks,
|
|
1052
1090
|
events,
|
|
@@ -1085,27 +1123,29 @@ var SqliteStorage = class {
|
|
|
1085
1123
|
if (current) {
|
|
1086
1124
|
this.database.prepare(`
|
|
1087
1125
|
UPDATE memory_spaces
|
|
1088
|
-
SET schema_version = ?, revision = ?, current_turn = ?, block_turn_size = ?, updated_at = ?
|
|
1126
|
+
SET schema_version = ?, revision = ?, current_turn = ?, block_turn_size = ?, block_decay_lambda = ?, updated_at = ?
|
|
1089
1127
|
WHERE namespace = ?
|
|
1090
1128
|
`).run(
|
|
1091
1129
|
snapshot.schemaVersion,
|
|
1092
1130
|
nextRevision,
|
|
1093
1131
|
snapshot.currentTurn,
|
|
1094
1132
|
snapshot.blockTurnSize,
|
|
1133
|
+
snapshot.blockDecayLambda,
|
|
1095
1134
|
updatedAt,
|
|
1096
1135
|
namespace
|
|
1097
1136
|
);
|
|
1098
1137
|
} else {
|
|
1099
1138
|
this.database.prepare(`
|
|
1100
1139
|
INSERT INTO memory_spaces (
|
|
1101
|
-
namespace, schema_version, revision, current_turn, block_turn_size, created_at, updated_at
|
|
1102
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
1140
|
+
namespace, schema_version, revision, current_turn, block_turn_size, block_decay_lambda, created_at, updated_at
|
|
1141
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
1103
1142
|
`).run(
|
|
1104
1143
|
namespace,
|
|
1105
1144
|
snapshot.schemaVersion,
|
|
1106
1145
|
nextRevision,
|
|
1107
1146
|
snapshot.currentTurn,
|
|
1108
1147
|
snapshot.blockTurnSize,
|
|
1148
|
+
snapshot.blockDecayLambda,
|
|
1109
1149
|
updatedAt,
|
|
1110
1150
|
updatedAt
|
|
1111
1151
|
);
|
|
@@ -1114,7 +1154,7 @@ var SqliteStorage = class {
|
|
|
1114
1154
|
INSERT INTO blocks (
|
|
1115
1155
|
namespace, id, thread_id, sequence, start_turn, end_turn, created_at, should_extract,
|
|
1116
1156
|
l0_title, l0_tags_json, l1_summary, l2_keypoints_json, l3_condensed, l4_readable,
|
|
1117
|
-
pointer_current_level, pointer_anchor_level,
|
|
1157
|
+
pointer_current_level, pointer_anchor_level, pointer_anchor_block_position, last_lifted_at
|
|
1118
1158
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1119
1159
|
ON CONFLICT (namespace, id) DO UPDATE SET
|
|
1120
1160
|
thread_id = excluded.thread_id,
|
|
@@ -1131,7 +1171,7 @@ var SqliteStorage = class {
|
|
|
1131
1171
|
l4_readable = excluded.l4_readable,
|
|
1132
1172
|
pointer_current_level = excluded.pointer_current_level,
|
|
1133
1173
|
pointer_anchor_level = excluded.pointer_anchor_level,
|
|
1134
|
-
|
|
1174
|
+
pointer_anchor_block_position = excluded.pointer_anchor_block_position,
|
|
1135
1175
|
last_lifted_at = excluded.last_lifted_at
|
|
1136
1176
|
`);
|
|
1137
1177
|
for (const block of snapshot.blocks) {
|
|
@@ -1152,7 +1192,7 @@ var SqliteStorage = class {
|
|
|
1152
1192
|
block.l4Readable,
|
|
1153
1193
|
block.pointerCurrentLevel,
|
|
1154
1194
|
block.pointerAnchorLevel,
|
|
1155
|
-
block.
|
|
1195
|
+
block.pointerAnchorBlockPosition,
|
|
1156
1196
|
block.lastLiftedAt
|
|
1157
1197
|
);
|
|
1158
1198
|
}
|
|
@@ -1422,8 +1462,9 @@ var SqliteStorage = class {
|
|
|
1422
1462
|
this.database.exec(THREAD_INDEXES);
|
|
1423
1463
|
this.database.exec(`PRAGMA user_version = ${STRATAGATE_STORAGE_SCHEMA_VERSION}`);
|
|
1424
1464
|
});
|
|
1425
|
-
} else if (version === 1 || version === 2 || version === 3 || version === 4) {
|
|
1465
|
+
} else if (version === 1 || version === 2 || version === 3 || version === 4 || version === 5) {
|
|
1426
1466
|
this.immediateTransaction(() => {
|
|
1467
|
+
this.database.exec(SCHEMA);
|
|
1427
1468
|
if (version === 1) {
|
|
1428
1469
|
const receiptColumns2 = this.database.prepare("PRAGMA table_info('usage_receipts')").all();
|
|
1429
1470
|
if (!receiptColumns2.some(({ name: name2 }) => name2 === "element_ids_json")) {
|
|
@@ -1434,11 +1475,26 @@ var SqliteStorage = class {
|
|
|
1434
1475
|
if (!receiptColumns.some(({ name: name2 }) => name2 === "audit_json")) {
|
|
1435
1476
|
this.database.exec("ALTER TABLE usage_receipts ADD COLUMN audit_json TEXT NOT NULL DEFAULT '{}'");
|
|
1436
1477
|
}
|
|
1437
|
-
this.database.
|
|
1478
|
+
const spaceColumns = this.database.prepare("PRAGMA table_info('memory_spaces')").all();
|
|
1479
|
+
if (!spaceColumns.some(({ name: name2 }) => name2 === "block_decay_lambda")) {
|
|
1480
|
+
this.database.exec("ALTER TABLE memory_spaces ADD COLUMN block_decay_lambda REAL NOT NULL DEFAULT 0.3");
|
|
1481
|
+
}
|
|
1438
1482
|
const blockColumns = this.database.prepare("PRAGMA table_info('blocks')").all();
|
|
1439
1483
|
if (!blockColumns.some(({ name: name2 }) => name2 === "thread_id")) {
|
|
1440
1484
|
this.database.exec("ALTER TABLE blocks ADD COLUMN thread_id TEXT");
|
|
1441
1485
|
}
|
|
1486
|
+
if (!blockColumns.some(({ name: name2 }) => name2 === "pointer_anchor_block_position")) {
|
|
1487
|
+
this.database.exec("ALTER TABLE blocks RENAME COLUMN pointer_anchor_turn TO pointer_anchor_block_position");
|
|
1488
|
+
this.database.exec(`
|
|
1489
|
+
UPDATE blocks AS target
|
|
1490
|
+
SET pointer_anchor_block_position = MAX(1, (
|
|
1491
|
+
SELECT COUNT(*) FROM blocks AS candidate
|
|
1492
|
+
WHERE candidate.namespace = target.namespace
|
|
1493
|
+
AND candidate.thread_id IS target.thread_id
|
|
1494
|
+
AND candidate.end_turn <= target.pointer_anchor_block_position
|
|
1495
|
+
))
|
|
1496
|
+
`);
|
|
1497
|
+
}
|
|
1442
1498
|
const messageColumns = this.database.prepare("PRAGMA table_info('messages')").all();
|
|
1443
1499
|
if (!messageColumns.some(({ name: name2 }) => name2 === "thread_id")) {
|
|
1444
1500
|
this.database.exec("ALTER TABLE messages ADD COLUMN thread_id TEXT");
|
|
@@ -1526,6 +1582,7 @@ function errorMessage(error) {
|
|
|
1526
1582
|
var STRATAGATE_CONSTRUCTOR_TOKEN = /* @__PURE__ */ Symbol("StrataGate constructor");
|
|
1527
1583
|
var StrataGate = class _StrataGate {
|
|
1528
1584
|
blockTurnSize;
|
|
1585
|
+
blockDecayLambdaValue;
|
|
1529
1586
|
summarizer;
|
|
1530
1587
|
extractor;
|
|
1531
1588
|
elementProjector;
|
|
@@ -1551,6 +1608,11 @@ var StrataGate = class _StrataGate {
|
|
|
1551
1608
|
throw new TypeError("Use StrataGate.open() for SQLite or StrataGate.inMemory() for explicit ephemeral storage");
|
|
1552
1609
|
}
|
|
1553
1610
|
this.blockTurnSize = Math.max(1, Math.floor(options.blockTurnSize ?? DEFAULT_BLOCK_TURN_SIZE));
|
|
1611
|
+
const blockDecayLambda = options.blockDecayLambda ?? BLOCK_DECAY_LAMBDA;
|
|
1612
|
+
if (!Number.isFinite(blockDecayLambda) || blockDecayLambda < 0) {
|
|
1613
|
+
throw new TypeError("blockDecayLambda must be a non-negative finite number");
|
|
1614
|
+
}
|
|
1615
|
+
this.blockDecayLambdaValue = blockDecayLambda;
|
|
1554
1616
|
this.summarizer = options.summarizer;
|
|
1555
1617
|
this.extractor = options.extractor;
|
|
1556
1618
|
this.elementProjector = options.elementProjector;
|
|
@@ -1573,6 +1635,7 @@ var StrataGate = class _StrataGate {
|
|
|
1573
1635
|
storage,
|
|
1574
1636
|
namespace: options.namespace,
|
|
1575
1637
|
...options.blockTurnSize !== void 0 ? { blockTurnSize: options.blockTurnSize } : {},
|
|
1638
|
+
...options.blockDecayLambda !== void 0 ? { blockDecayLambda: options.blockDecayLambda } : {},
|
|
1576
1639
|
...options.summarizer ? { summarizer: options.summarizer } : {},
|
|
1577
1640
|
...options.extractor ? { extractor: options.extractor } : {},
|
|
1578
1641
|
...options.elementProjector ? { elementProjector: options.elementProjector } : {},
|
|
@@ -1591,17 +1654,32 @@ var StrataGate = class _StrataGate {
|
|
|
1591
1654
|
const loaded = await options.storage.load(namespace);
|
|
1592
1655
|
const loadedSnapshot = loaded ? normalizeSnapshot(loaded.snapshot) : null;
|
|
1593
1656
|
let loadedRevision = loaded?.revision ?? 0;
|
|
1594
|
-
if (loaded &&
|
|
1595
|
-
|
|
1596
|
-
if (
|
|
1597
|
-
|
|
1598
|
-
loadedSnapshot.blockTurnSize
|
|
1599
|
-
|
|
1657
|
+
if (loaded && loadedSnapshot) {
|
|
1658
|
+
let settingsChanged = false;
|
|
1659
|
+
if (options.blockTurnSize !== void 0) {
|
|
1660
|
+
const requested = Math.max(1, Math.floor(options.blockTurnSize));
|
|
1661
|
+
if (requested !== loadedSnapshot.blockTurnSize) {
|
|
1662
|
+
loadedSnapshot.blockTurnSize = requested;
|
|
1663
|
+
settingsChanged = true;
|
|
1664
|
+
}
|
|
1600
1665
|
}
|
|
1666
|
+
if (options.blockDecayLambda !== void 0) {
|
|
1667
|
+
const requested = options.blockDecayLambda;
|
|
1668
|
+
if (!Number.isFinite(requested) || requested < 0) {
|
|
1669
|
+
throw new TypeError("blockDecayLambda must be a non-negative finite number");
|
|
1670
|
+
}
|
|
1671
|
+
if (requested !== loadedSnapshot.blockDecayLambda) {
|
|
1672
|
+
loadedSnapshot.blockDecayLambda = requested;
|
|
1673
|
+
settingsChanged = true;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
if (settingsChanged) loadedRevision = await options.storage.save(namespace, loadedSnapshot, loadedRevision);
|
|
1601
1677
|
}
|
|
1602
1678
|
const memoryOptions = {};
|
|
1603
1679
|
if (loadedSnapshot) memoryOptions.blockTurnSize = loadedSnapshot.blockTurnSize;
|
|
1604
1680
|
else if (options.blockTurnSize !== void 0) memoryOptions.blockTurnSize = options.blockTurnSize;
|
|
1681
|
+
if (loadedSnapshot) memoryOptions.blockDecayLambda = loadedSnapshot.blockDecayLambda;
|
|
1682
|
+
else if (options.blockDecayLambda !== void 0) memoryOptions.blockDecayLambda = options.blockDecayLambda;
|
|
1605
1683
|
if (options.summarizer) memoryOptions.summarizer = options.summarizer;
|
|
1606
1684
|
if (options.extractor) memoryOptions.extractor = options.extractor;
|
|
1607
1685
|
if (options.elementProjector) memoryOptions.elementProjector = options.elementProjector;
|
|
@@ -1653,6 +1731,18 @@ var StrataGate = class _StrataGate {
|
|
|
1653
1731
|
get storageRevision() {
|
|
1654
1732
|
return this.revision;
|
|
1655
1733
|
}
|
|
1734
|
+
get blockDecayLambda() {
|
|
1735
|
+
return this.blockDecayLambdaValue;
|
|
1736
|
+
}
|
|
1737
|
+
async setBlockDecayLambda(value) {
|
|
1738
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
1739
|
+
throw new TypeError("blockDecayLambda must be a non-negative finite number");
|
|
1740
|
+
}
|
|
1741
|
+
if (value === this.blockDecayLambdaValue) return;
|
|
1742
|
+
await this.commitMutation(() => {
|
|
1743
|
+
this.blockDecayLambdaValue = value;
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1656
1746
|
listBlocks() {
|
|
1657
1747
|
return this.blocks;
|
|
1658
1748
|
}
|
|
@@ -1695,6 +1785,7 @@ var StrataGate = class _StrataGate {
|
|
|
1695
1785
|
schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION,
|
|
1696
1786
|
currentTurn: this.currentTurn,
|
|
1697
1787
|
blockTurnSize: this.blockTurnSize,
|
|
1788
|
+
blockDecayLambda: this.blockDecayLambda,
|
|
1698
1789
|
openTail: this.openTail,
|
|
1699
1790
|
blocks: this.blocks,
|
|
1700
1791
|
events: this.events,
|
|
@@ -1995,13 +2086,22 @@ var StrataGate = class _StrataGate {
|
|
|
1995
2086
|
getBlockContext(threadId) {
|
|
1996
2087
|
const blocks = threadId === void 0 ? this.blocks : this.blocks.filter((block) => block.threadId === threadId);
|
|
1997
2088
|
return blocks.map((block) => {
|
|
1998
|
-
const
|
|
1999
|
-
const
|
|
2089
|
+
const threadBlocks = this.threadBlocks(block.threadId);
|
|
2090
|
+
const latestBlockPosition = threadBlocks.length;
|
|
2091
|
+
const blockPosition = threadBlocks.indexOf(block) + 1;
|
|
2092
|
+
const age = Math.max(0, latestBlockPosition - blockPosition);
|
|
2093
|
+
const level = getDecayedBlockLevel(
|
|
2094
|
+
block.pointerAnchorLevel,
|
|
2095
|
+
block.pointerAnchorBlockPosition,
|
|
2096
|
+
latestBlockPosition,
|
|
2097
|
+
this.blockDecayLambda
|
|
2098
|
+
);
|
|
2000
2099
|
block.pointerCurrentLevel = level;
|
|
2001
2100
|
return {
|
|
2002
2101
|
id: block.id,
|
|
2003
2102
|
...block.threadId ? { threadId: block.threadId } : {},
|
|
2004
2103
|
turnRange: [block.startTurn, block.endTurn],
|
|
2104
|
+
age,
|
|
2005
2105
|
level,
|
|
2006
2106
|
label: blockLevelLabel(level),
|
|
2007
2107
|
content: renderBlock(block, level)
|
|
@@ -2012,17 +2112,24 @@ var StrataGate = class _StrataGate {
|
|
|
2012
2112
|
return this.commitMutation(() => {
|
|
2013
2113
|
const block = this.blocks.find((candidate) => candidate.id === id);
|
|
2014
2114
|
if (!block) throw new Error(`Unknown block: ${id}`);
|
|
2015
|
-
const
|
|
2016
|
-
const
|
|
2115
|
+
const latestBlockPosition = this.threadBlocks(block.threadId).length;
|
|
2116
|
+
const blockPosition = this.threadBlocks(block.threadId).indexOf(block) + 1;
|
|
2117
|
+
const current = getDecayedBlockLevel(
|
|
2118
|
+
block.pointerAnchorLevel,
|
|
2119
|
+
block.pointerAnchorBlockPosition,
|
|
2120
|
+
latestBlockPosition,
|
|
2121
|
+
this.blockDecayLambda
|
|
2122
|
+
);
|
|
2017
2123
|
const level = normalizeBlockLevel(target, current);
|
|
2018
2124
|
block.pointerCurrentLevel = level;
|
|
2019
2125
|
block.pointerAnchorLevel = level;
|
|
2020
|
-
block.
|
|
2126
|
+
block.pointerAnchorBlockPosition = latestBlockPosition;
|
|
2021
2127
|
block.lastLiftedAt = toUtc8Iso(this.now());
|
|
2022
2128
|
return {
|
|
2023
2129
|
id: block.id,
|
|
2024
2130
|
...block.threadId ? { threadId: block.threadId } : {},
|
|
2025
2131
|
turnRange: [block.startTurn, block.endTurn],
|
|
2132
|
+
age: Math.max(0, latestBlockPosition - blockPosition),
|
|
2026
2133
|
level,
|
|
2027
2134
|
label: blockLevelLabel(level),
|
|
2028
2135
|
content: renderBlock(block, level)
|
|
@@ -2221,7 +2328,9 @@ var StrataGate = class _StrataGate {
|
|
|
2221
2328
|
const generated = this.summarizer ? await this.summarizer(raw) : defaultSummary(raw);
|
|
2222
2329
|
const deterministic = deterministicBlockLayers(raw);
|
|
2223
2330
|
const sequence = this.blocks.length + 1;
|
|
2224
|
-
const
|
|
2331
|
+
const threadBlocks = this.threadBlocks(threadId);
|
|
2332
|
+
const previous = threadBlocks.at(-1);
|
|
2333
|
+
const blockPosition = threadBlocks.length + 1;
|
|
2225
2334
|
const startTurn = previous ? previous.endTurn + 1 : 1;
|
|
2226
2335
|
const endTurn = startTurn + this.blockTurnSize - 1;
|
|
2227
2336
|
return this.commitMutation(() => {
|
|
@@ -2244,7 +2353,7 @@ var StrataGate = class _StrataGate {
|
|
|
2244
2353
|
...deterministic,
|
|
2245
2354
|
pointerCurrentLevel: 5,
|
|
2246
2355
|
pointerAnchorLevel: 5,
|
|
2247
|
-
|
|
2356
|
+
pointerAnchorBlockPosition: blockPosition,
|
|
2248
2357
|
lastLiftedAt: null
|
|
2249
2358
|
};
|
|
2250
2359
|
const sealedIds = new Set(raw.map((message) => message.id));
|
|
@@ -2381,6 +2490,7 @@ var StrataGate = class _StrataGate {
|
|
|
2381
2490
|
throw new Error(`Snapshot blockTurnSize ${normalized.blockTurnSize} does not match ${this.blockTurnSize}`);
|
|
2382
2491
|
}
|
|
2383
2492
|
const copy = cloneSnapshot(normalized);
|
|
2493
|
+
this.blockDecayLambdaValue = copy.blockDecayLambda;
|
|
2384
2494
|
this.currentTurn = copy.currentTurn;
|
|
2385
2495
|
this.openTail.splice(0, this.openTail.length, ...copy.openTail);
|
|
2386
2496
|
this.blocks.splice(0, this.blocks.length, ...copy.blocks);
|
|
@@ -3051,6 +3161,60 @@ var TurnFolder = class {
|
|
|
3051
3161
|
}
|
|
3052
3162
|
};
|
|
3053
3163
|
|
|
3164
|
+
// src/metadata.ts
|
|
3165
|
+
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
3166
|
+
var METADATA_SCHEMA = `
|
|
3167
|
+
CREATE TABLE IF NOT EXISTS stratagate_dsh_settings (
|
|
3168
|
+
key TEXT PRIMARY KEY,
|
|
3169
|
+
value TEXT NOT NULL,
|
|
3170
|
+
updated_at TEXT NOT NULL
|
|
3171
|
+
) STRICT;
|
|
3172
|
+
|
|
3173
|
+
CREATE TABLE IF NOT EXISTS stratagate_dsh_workspaces (
|
|
3174
|
+
namespace TEXT PRIMARY KEY,
|
|
3175
|
+
display_name TEXT NOT NULL,
|
|
3176
|
+
updated_at TEXT NOT NULL
|
|
3177
|
+
) STRICT;
|
|
3178
|
+
`;
|
|
3179
|
+
var DshMetadataStore = class {
|
|
3180
|
+
database;
|
|
3181
|
+
constructor(filename) {
|
|
3182
|
+
this.database = new DatabaseSync2(filename);
|
|
3183
|
+
this.database.exec(METADATA_SCHEMA);
|
|
3184
|
+
}
|
|
3185
|
+
blockDecayLambda() {
|
|
3186
|
+
const row = this.database.prepare("SELECT value FROM stratagate_dsh_settings WHERE key = 'blockDecayLambda'").get();
|
|
3187
|
+
const value = Number(row?.value);
|
|
3188
|
+
return Number.isFinite(value) && value >= 0 ? value : null;
|
|
3189
|
+
}
|
|
3190
|
+
setBlockDecayLambda(value) {
|
|
3191
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
3192
|
+
throw new TypeError("blockDecayLambda must be a non-negative finite number");
|
|
3193
|
+
}
|
|
3194
|
+
this.database.prepare(`
|
|
3195
|
+
INSERT INTO stratagate_dsh_settings (key, value, updated_at)
|
|
3196
|
+
VALUES ('blockDecayLambda', ?, ?)
|
|
3197
|
+
ON CONFLICT (key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at
|
|
3198
|
+
`).run(String(value), (/* @__PURE__ */ new Date()).toISOString());
|
|
3199
|
+
}
|
|
3200
|
+
workspaceName(namespace) {
|
|
3201
|
+
const row = this.database.prepare("SELECT display_name FROM stratagate_dsh_workspaces WHERE namespace = ?").get(namespace);
|
|
3202
|
+
return row?.display_name ?? null;
|
|
3203
|
+
}
|
|
3204
|
+
rememberWorkspace(namespace, displayName) {
|
|
3205
|
+
const name2 = displayName.trim();
|
|
3206
|
+
if (!namespace.trim() || !name2) return;
|
|
3207
|
+
this.database.prepare(`
|
|
3208
|
+
INSERT INTO stratagate_dsh_workspaces (namespace, display_name, updated_at)
|
|
3209
|
+
VALUES (?, ?, ?)
|
|
3210
|
+
ON CONFLICT (namespace) DO UPDATE SET display_name = excluded.display_name, updated_at = excluded.updated_at
|
|
3211
|
+
`).run(namespace, name2, (/* @__PURE__ */ new Date()).toISOString());
|
|
3212
|
+
}
|
|
3213
|
+
close() {
|
|
3214
|
+
this.database.close();
|
|
3215
|
+
}
|
|
3216
|
+
};
|
|
3217
|
+
|
|
3054
3218
|
// src/runtime.ts
|
|
3055
3219
|
var AUTO_EVENT_LIMIT = 4;
|
|
3056
3220
|
var AUTO_ELEMENT_LIMIT = 4;
|
|
@@ -3059,12 +3223,17 @@ function projectKey(cwd) {
|
|
|
3059
3223
|
const canonical = resolve(cwd ?? process.cwd()).replaceAll("\\", "/").toLowerCase();
|
|
3060
3224
|
return createHash("sha256").update(canonical).digest("hex").slice(0, 20);
|
|
3061
3225
|
}
|
|
3226
|
+
function workspaceDisplayName(cwd) {
|
|
3227
|
+
const canonical = (cwd ?? process.cwd()).replace(/[\\/]+$/, "");
|
|
3228
|
+
return canonical.split(/[\\/]/).at(-1) || "\u5F53\u524D\u5DE5\u4F5C\u533A";
|
|
3229
|
+
}
|
|
3062
3230
|
var StrataGateRuntime = class {
|
|
3063
3231
|
constructor(config, models, onIngestError = () => {
|
|
3064
3232
|
}) {
|
|
3065
3233
|
this.config = config;
|
|
3066
3234
|
this.models = models;
|
|
3067
3235
|
this.onIngestError = onIngestError;
|
|
3236
|
+
this.blockDecayLambda = config.blockDecayLambda;
|
|
3068
3237
|
}
|
|
3069
3238
|
config;
|
|
3070
3239
|
models;
|
|
@@ -3074,10 +3243,13 @@ var StrataGateRuntime = class {
|
|
|
3074
3243
|
batches = /* @__PURE__ */ new Map();
|
|
3075
3244
|
adopted = /* @__PURE__ */ new Map();
|
|
3076
3245
|
pendingUse = /* @__PURE__ */ new Set();
|
|
3246
|
+
workspaceNames = /* @__PURE__ */ new Map();
|
|
3077
3247
|
ingestTail = Promise.resolve();
|
|
3248
|
+
settingsTail = Promise.resolve();
|
|
3078
3249
|
batchSequence = 0;
|
|
3079
3250
|
closed = false;
|
|
3080
3251
|
ingestError;
|
|
3252
|
+
blockDecayLambda;
|
|
3081
3253
|
acceptEvent(session, event) {
|
|
3082
3254
|
if (this.closed) return;
|
|
3083
3255
|
if (!this.config.ingestSubagents && session.header.origin === "subagent") return;
|
|
@@ -3298,16 +3470,23 @@ var StrataGateRuntime = class {
|
|
|
3298
3470
|
await storage.close();
|
|
3299
3471
|
}
|
|
3300
3472
|
}
|
|
3301
|
-
async
|
|
3473
|
+
async syncConfiguredSettings() {
|
|
3302
3474
|
if (this.config.database === ":memory:" || !existsSync(this.config.database)) return;
|
|
3475
|
+
const metadata = new DshMetadataStore(this.config.database);
|
|
3476
|
+
try {
|
|
3477
|
+
this.blockDecayLambda = metadata.blockDecayLambda() ?? this.config.blockDecayLambda;
|
|
3478
|
+
} finally {
|
|
3479
|
+
metadata.close();
|
|
3480
|
+
}
|
|
3303
3481
|
const storage = new SqliteStorage({ filename: this.config.database });
|
|
3304
3482
|
try {
|
|
3305
3483
|
for (const namespace of storage.listNamespaces()) {
|
|
3306
3484
|
const loaded = await storage.load(namespace);
|
|
3307
|
-
if (!loaded || loaded.snapshot.blockTurnSize === this.config.blockTurnSize) continue;
|
|
3485
|
+
if (!loaded || loaded.snapshot.blockTurnSize === this.config.blockTurnSize && loaded.snapshot.blockDecayLambda === this.blockDecayLambda) continue;
|
|
3308
3486
|
await storage.save(namespace, {
|
|
3309
3487
|
...loaded.snapshot,
|
|
3310
|
-
blockTurnSize: this.config.blockTurnSize
|
|
3488
|
+
blockTurnSize: this.config.blockTurnSize,
|
|
3489
|
+
blockDecayLambda: this.blockDecayLambda
|
|
3311
3490
|
}, loaded.revision);
|
|
3312
3491
|
}
|
|
3313
3492
|
} finally {
|
|
@@ -3325,14 +3504,70 @@ var StrataGateRuntime = class {
|
|
|
3325
3504
|
await storage.close();
|
|
3326
3505
|
}
|
|
3327
3506
|
}
|
|
3507
|
+
adminWorkspaceName(namespace) {
|
|
3508
|
+
const remembered = this.workspaceNames.get(namespace);
|
|
3509
|
+
if (remembered) return remembered;
|
|
3510
|
+
if (this.config.database === ":memory:" || !existsSync(this.config.database)) return null;
|
|
3511
|
+
const metadata = new DshMetadataStore(this.config.database);
|
|
3512
|
+
try {
|
|
3513
|
+
return metadata.workspaceName(namespace);
|
|
3514
|
+
} finally {
|
|
3515
|
+
metadata.close();
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
async adminSetBlockDecayLambda(value) {
|
|
3519
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
3520
|
+
throw new TypeError("blockDecayLambda must be a non-negative finite number");
|
|
3521
|
+
}
|
|
3522
|
+
const update = this.settingsTail.catch(() => {
|
|
3523
|
+
}).then(() => this.applyBlockDecayLambda(value));
|
|
3524
|
+
this.settingsTail = update.then(() => {
|
|
3525
|
+
}, () => {
|
|
3526
|
+
});
|
|
3527
|
+
await update;
|
|
3528
|
+
return value;
|
|
3529
|
+
}
|
|
3530
|
+
async applyBlockDecayLambda(value) {
|
|
3531
|
+
await this.flush();
|
|
3532
|
+
this.blockDecayLambda = value;
|
|
3533
|
+
if (this.config.database !== ":memory:") {
|
|
3534
|
+
const metadata = new DshMetadataStore(this.config.database);
|
|
3535
|
+
try {
|
|
3536
|
+
metadata.setBlockDecayLambda(value);
|
|
3537
|
+
} finally {
|
|
3538
|
+
metadata.close();
|
|
3539
|
+
}
|
|
3540
|
+
}
|
|
3541
|
+
const openNamespaces = /* @__PURE__ */ new Set();
|
|
3542
|
+
for (const [namespace, opening] of this.spaces) {
|
|
3543
|
+
const memory = await opening;
|
|
3544
|
+
await memory.setBlockDecayLambda(value);
|
|
3545
|
+
openNamespaces.add(namespace);
|
|
3546
|
+
}
|
|
3547
|
+
if (this.config.database !== ":memory:" && existsSync(this.config.database)) {
|
|
3548
|
+
const storage = new SqliteStorage({ filename: this.config.database });
|
|
3549
|
+
try {
|
|
3550
|
+
for (const namespace of storage.listNamespaces()) {
|
|
3551
|
+
if (openNamespaces.has(namespace)) continue;
|
|
3552
|
+
const loaded = await storage.load(namespace);
|
|
3553
|
+
if (!loaded || loaded.snapshot.blockDecayLambda === value) continue;
|
|
3554
|
+
await storage.save(namespace, { ...loaded.snapshot, blockDecayLambda: value }, loaded.revision);
|
|
3555
|
+
}
|
|
3556
|
+
} finally {
|
|
3557
|
+
await storage.close();
|
|
3558
|
+
}
|
|
3559
|
+
}
|
|
3560
|
+
}
|
|
3328
3561
|
space(session) {
|
|
3329
3562
|
const namespace = this.namespaceFor(session);
|
|
3563
|
+
this.rememberWorkspace(namespace, session.header.cwd);
|
|
3330
3564
|
let opening = this.spaces.get(namespace);
|
|
3331
3565
|
if (!opening) {
|
|
3332
3566
|
opening = StrataGate.open({
|
|
3333
3567
|
database: this.config.database,
|
|
3334
3568
|
namespace,
|
|
3335
3569
|
blockTurnSize: this.config.blockTurnSize,
|
|
3570
|
+
blockDecayLambda: this.blockDecayLambda,
|
|
3336
3571
|
summarizer: this.models.summarizer,
|
|
3337
3572
|
extractor: this.models.extractor,
|
|
3338
3573
|
elementProjector: this.models.projector
|
|
@@ -3357,6 +3592,21 @@ var StrataGateRuntime = class {
|
|
|
3357
3592
|
}
|
|
3358
3593
|
return opening;
|
|
3359
3594
|
}
|
|
3595
|
+
rememberWorkspace(namespace, cwd) {
|
|
3596
|
+
const name2 = workspaceDisplayName(cwd);
|
|
3597
|
+
this.workspaceNames.set(namespace, name2);
|
|
3598
|
+
if (this.config.database === ":memory:") return;
|
|
3599
|
+
try {
|
|
3600
|
+
const metadata = new DshMetadataStore(this.config.database);
|
|
3601
|
+
try {
|
|
3602
|
+
metadata.rememberWorkspace(namespace, name2);
|
|
3603
|
+
} finally {
|
|
3604
|
+
metadata.close();
|
|
3605
|
+
}
|
|
3606
|
+
} catch (error) {
|
|
3607
|
+
this.onIngestError(error);
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3360
3610
|
async persistSuccessfulResponses(memory) {
|
|
3361
3611
|
if (typeof this.models.takeSuccessfulResponses !== "function") return;
|
|
3362
3612
|
const responses = this.models.takeSuccessfulResponses();
|
|
@@ -3413,7 +3663,7 @@ function renderMessages(messages) {
|
|
|
3413
3663
|
function renderBlocks2(blocks) {
|
|
3414
3664
|
if (blocks.length === 0) return "(no sealed blocks)";
|
|
3415
3665
|
return blocks.map((block) => [
|
|
3416
|
-
`block ${block.id} | turns ${block.turnRange[0]}-${block.turnRange[1]} | L${block.level}`,
|
|
3666
|
+
`block ${block.id} | turns ${block.turnRange[0]}-${block.turnRange[1]} | age ${block.age} | L${block.level}`,
|
|
3417
3667
|
block.content
|
|
3418
3668
|
].join("\n")).join("\n\n");
|
|
3419
3669
|
}
|
|
@@ -3787,15 +4037,18 @@ async function overview(runtime) {
|
|
|
3787
4037
|
].sort();
|
|
3788
4038
|
rows.push({
|
|
3789
4039
|
namespace,
|
|
4040
|
+
workspaceName: runtime.adminWorkspaceName(namespace) ?? "\u5F53\u524D\u5DE5\u4F5C\u533A",
|
|
3790
4041
|
schemaVersion: snapshot.schemaVersion,
|
|
3791
4042
|
currentTurn: snapshot.currentTurn,
|
|
3792
4043
|
blockTurnSize: snapshot.blockTurnSize,
|
|
4044
|
+
blockDecayLambda: snapshot.blockDecayLambda,
|
|
3793
4045
|
blocks: snapshot.blocks.length,
|
|
3794
4046
|
openTailMessages: snapshot.openTail.length,
|
|
3795
4047
|
events: snapshot.events.length,
|
|
3796
4048
|
activeEvents: snapshot.events.filter(({ status }) => status === "active").length,
|
|
3797
4049
|
elements: snapshot.elements.length,
|
|
3798
4050
|
usageReceipts: snapshot.usageReceipts.length,
|
|
4051
|
+
memoryUseCount: snapshot.usageReceipts.filter((receipt) => receipt.eventIds.length > 0 || receipt.elementIds.length > 0).length,
|
|
3799
4052
|
failedJobs,
|
|
3800
4053
|
processingJobs,
|
|
3801
4054
|
failedJobDetails,
|
|
@@ -3803,7 +4056,15 @@ async function overview(runtime) {
|
|
|
3803
4056
|
lastActivityAt: timestamps.at(-1) ?? null
|
|
3804
4057
|
});
|
|
3805
4058
|
}
|
|
3806
|
-
return { readonly: true, namespaces: rows };
|
|
4059
|
+
return { readonly: true, settingsWritable: true, namespaces: rows };
|
|
4060
|
+
}
|
|
4061
|
+
async function updateSettings(runtime, url) {
|
|
4062
|
+
const raw = url.searchParams.get("blockDecayLambda")?.trim() ?? "";
|
|
4063
|
+
const value = Number(raw);
|
|
4064
|
+
if (!raw || !Number.isFinite(value) || value < 0) {
|
|
4065
|
+
throw new AdminHttpError(400, "blockDecayLambda must be a non-negative finite number");
|
|
4066
|
+
}
|
|
4067
|
+
return { blockDecayLambda: await runtime.adminSetBlockDecayLambda(value) };
|
|
3807
4068
|
}
|
|
3808
4069
|
async function memories(runtime, url) {
|
|
3809
4070
|
const namespace = url.searchParams.get("namespace")?.trim() ?? "";
|
|
@@ -3928,10 +4189,13 @@ async function audit(runtime, url) {
|
|
|
3928
4189
|
}
|
|
3929
4190
|
async function handleAdminRequest(runtime, req, res) {
|
|
3930
4191
|
try {
|
|
3931
|
-
if (req.method !== "GET") throw new AdminHttpError(405, "StrataGate Memory UI is read-only");
|
|
3932
4192
|
const url = new URL(req.url ?? "/", "http://localhost");
|
|
3933
4193
|
const path = url.pathname.replace(/\/$/, "");
|
|
3934
|
-
if (path === "/api/stratagate/
|
|
4194
|
+
if (path === "/api/stratagate/settings") {
|
|
4195
|
+
if (req.method !== "PATCH") throw new AdminHttpError(405, "StrataGate settings require PATCH");
|
|
4196
|
+
sendJson(res, 200, await updateSettings(runtime, url));
|
|
4197
|
+
} else if (req.method !== "GET") throw new AdminHttpError(405, "StrataGate memory data is read-only");
|
|
4198
|
+
else if (path === "/api/stratagate/overview") sendJson(res, 200, await overview(runtime));
|
|
3935
4199
|
else if (path === "/api/stratagate/memories") sendJson(res, 200, await memories(runtime, url));
|
|
3936
4200
|
else if (path === "/api/stratagate/sources") sendJson(res, 200, await sources(runtime, url));
|
|
3937
4201
|
else if (path === "/api/stratagate/audit") sendJson(res, 200, await audit(runtime, url));
|
|
@@ -3974,7 +4238,7 @@ async function apply(ctx, config) {
|
|
|
3974
4238
|
const runtime = new StrataGateRuntime(resolved, models, (error) => {
|
|
3975
4239
|
ctx.logger.error(`stratagate-memory ingestion failed: ${renderError(error)}`);
|
|
3976
4240
|
});
|
|
3977
|
-
await runtime.
|
|
4241
|
+
await runtime.syncConfiguredSettings();
|
|
3978
4242
|
ctx.systemPrompt.section({ name: "tool:stratagate-memory", order: 113, text: MEMORY_PROTOCOL });
|
|
3979
4243
|
ctx.on("system-prompt/assemble", async (_assembly, context, next) => {
|
|
3980
4244
|
const assembled = await next();
|