stratagate-dsh 0.2.33 → 0.2.35
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 +205 -193
- package/LICENSE +21 -21
- package/README.md +182 -164
- package/cordis.patch.yml +13 -13
- package/dist/client.d.ts +1 -1
- package/dist/index.js +150 -22
- package/dist/index.js.map +1 -1
- package/docs/README.zh-CN.md +179 -164
- package/package.json +153 -153
package/dist/index.js
CHANGED
|
@@ -3254,6 +3254,11 @@ var StrataGate = class _StrataGate {
|
|
|
3254
3254
|
}
|
|
3255
3255
|
return hits;
|
|
3256
3256
|
}
|
|
3257
|
+
/**
|
|
3258
|
+
* Return decayed block views. Passing a threadId limits the result to that
|
|
3259
|
+
* conversation; omitting it intentionally returns every thread in this
|
|
3260
|
+
* StrataGate namespace (never another namespace).
|
|
3261
|
+
*/
|
|
3257
3262
|
getBlockContext(threadId) {
|
|
3258
3263
|
const blocks = threadId === void 0 ? this.blocks : this.blocks.filter((block) => block.threadId === threadId);
|
|
3259
3264
|
return blocks.map((block) => {
|
|
@@ -3474,6 +3479,16 @@ var StrataGate = class _StrataGate {
|
|
|
3474
3479
|
}
|
|
3475
3480
|
async searchGraphNodes(query, limit = 8) {
|
|
3476
3481
|
const candidates = this.graphNodes.filter((node) => node.status === "active" || node.status === "disputed");
|
|
3482
|
+
const queryTokens = [...new Set(searchTokens(query))];
|
|
3483
|
+
const fieldValues = (node) => [
|
|
3484
|
+
["name", node.name],
|
|
3485
|
+
["aliases", node.aliases.join(" ")],
|
|
3486
|
+
["tags", (node.tags ?? []).join(" ")],
|
|
3487
|
+
["type", node.type],
|
|
3488
|
+
["currentState", node.currentState],
|
|
3489
|
+
["facts", node.facts.map((fact) => `${fact.key} ${Array.isArray(fact.value) ? fact.value.join(" ") : fact.value}`).join(" ")],
|
|
3490
|
+
["relations", this.graphEdges.filter((edge) => edge.fromNodeId === node.id || edge.toNodeId === node.id).map(({ relation }) => relation).join(" ")]
|
|
3491
|
+
];
|
|
3477
3492
|
const ranked = bm25Rank(candidates, query, (node) => weightedSearchTokens([
|
|
3478
3493
|
[node.name, 6],
|
|
3479
3494
|
[node.aliases.join(" "), 5],
|
|
@@ -3482,9 +3497,28 @@ var StrataGate = class _StrataGate {
|
|
|
3482
3497
|
[node.currentState, 4],
|
|
3483
3498
|
[node.facts.map((fact) => `${fact.key} ${Array.isArray(fact.value) ? fact.value.join(" ") : fact.value}`).join(" "), 4],
|
|
3484
3499
|
[this.graphEdges.filter((edge) => edge.fromNodeId === node.id || edge.toNodeId === node.id).map(({ relation }) => relation).join(" "), 3]
|
|
3485
|
-
])).
|
|
3500
|
+
])).filter(({ item }) => {
|
|
3501
|
+
const fields = fieldValues(item);
|
|
3502
|
+
const matches = fields.filter(([, value]) => {
|
|
3503
|
+
const haystack = new Set(searchTokens(value));
|
|
3504
|
+
return queryTokens.some((token) => haystack.has(token));
|
|
3505
|
+
}).map(([field]) => field);
|
|
3506
|
+
if (!matches.some((field) => field !== "relations")) return false;
|
|
3507
|
+
return matches.some((field) => field !== "relations");
|
|
3508
|
+
}).slice(0, Math.max(1, Math.min(20, limit)));
|
|
3486
3509
|
if (searchTokens(query).length > 0 && ranked.length === 0) return [];
|
|
3487
|
-
return ranked.map(({ item: node, score }) =>
|
|
3510
|
+
return ranked.map(({ item: node, score }) => {
|
|
3511
|
+
const matchedFields = fieldValues(node).filter(([, value]) => {
|
|
3512
|
+
const haystack = new Set(searchTokens(value));
|
|
3513
|
+
return queryTokens.some((token) => haystack.has(token));
|
|
3514
|
+
}).map(([field]) => field);
|
|
3515
|
+
return {
|
|
3516
|
+
node,
|
|
3517
|
+
score,
|
|
3518
|
+
matchedFields,
|
|
3519
|
+
matchReason: `Lexical match in ${matchedFields.join(", ") || "indexed fields"}; score is ranking-only.`
|
|
3520
|
+
};
|
|
3521
|
+
});
|
|
3488
3522
|
}
|
|
3489
3523
|
requireGraphProjectionJob(id) {
|
|
3490
3524
|
const job = this.graphProjectionJobs.get(id);
|
|
@@ -4713,7 +4747,7 @@ var StrataGateRuntime = class {
|
|
|
4713
4747
|
return this.batch(session, results.map(({ event }) => ({
|
|
4714
4748
|
ref: `event:${event.id}`,
|
|
4715
4749
|
target: { eventIds: [event.id], elementIds: [] }
|
|
4716
|
-
})), results);
|
|
4750
|
+
})), results.map(({ event, score }) => compactEvent(event, score)));
|
|
4717
4751
|
}
|
|
4718
4752
|
async searchElements(session, query, options = {}) {
|
|
4719
4753
|
await this.flush();
|
|
@@ -4721,23 +4755,53 @@ var StrataGateRuntime = class {
|
|
|
4721
4755
|
return this.batch(session, results.map((result) => ({
|
|
4722
4756
|
ref: `element:${result.elementId}:fact:${result.id}`,
|
|
4723
4757
|
target: { eventIds: [], elementIds: [result.elementId] }
|
|
4724
|
-
})), results)
|
|
4758
|
+
})), results.map((result) => ({
|
|
4759
|
+
id: result.id,
|
|
4760
|
+
elementId: result.elementId,
|
|
4761
|
+
name: result.name,
|
|
4762
|
+
type: result.type,
|
|
4763
|
+
factKey: result.fact.key,
|
|
4764
|
+
value: Array.isArray(result.fact.value) ? result.fact.value.join(", ") : result.fact.value,
|
|
4765
|
+
validFrom: result.fact.validFrom,
|
|
4766
|
+
validTo: result.fact.validTo,
|
|
4767
|
+
rankScore: result.score,
|
|
4768
|
+
scoreMeaning: "Ranking-only BM25/RRF score; not confidence or factual accuracy."
|
|
4769
|
+
})));
|
|
4725
4770
|
}
|
|
4726
|
-
async searchRaw(session, query, limit) {
|
|
4771
|
+
async searchRaw(session, query, limit, scope = "namespace") {
|
|
4727
4772
|
await this.flush();
|
|
4728
|
-
const
|
|
4773
|
+
const memory = await this.space(session);
|
|
4774
|
+
const threadId = String(session.id);
|
|
4775
|
+
const results = memory.searchRawMemory(query, scope === "namespace" ? limit : Number.MAX_SAFE_INTEGER).filter((result) => scope === "namespace" || result.message.threadId === threadId || result.message.threadId === void 0).slice(0, limit);
|
|
4729
4776
|
return this.batch(session, results.map((result, index) => ({
|
|
4730
4777
|
ref: `raw:${result.blockId}:${result.message.id}:${index}`,
|
|
4731
4778
|
target: { eventIds: [], elementIds: [] }
|
|
4732
|
-
})), results);
|
|
4779
|
+
})), results.map(compactRawHit), { scope, namespace: this.namespaceFor(session), threadId });
|
|
4733
4780
|
}
|
|
4734
|
-
async blocks(session) {
|
|
4781
|
+
async blocks(session, scope = "session") {
|
|
4735
4782
|
await this.flush();
|
|
4736
|
-
const
|
|
4783
|
+
const memory = await this.space(session);
|
|
4784
|
+
const threadId = String(session.id);
|
|
4785
|
+
const snapshot = memory.exportSnapshot();
|
|
4786
|
+
const namespaceBlockCount = snapshot.blocks.length;
|
|
4787
|
+
const namespaceThreadIds = [...new Set(snapshot.blocks.map((block) => block.threadId).filter((value) => Boolean(value)))];
|
|
4788
|
+
const openTailCount = snapshot.openTail.filter((message) => scope === "namespace" || message.threadId === threadId || message.threadId === void 0).length;
|
|
4789
|
+
const results = scope === "namespace" ? memory.getBlockContext() : memory.getBlockContext().filter((block) => block.threadId === threadId || block.threadId === void 0);
|
|
4790
|
+
const emptyReason = results.length > 0 ? null : namespaceBlockCount === 0 ? openTailCount > 0 ? "open_tail_pending" : "no_blocks_in_namespace" : openTailCount > 0 ? "open_tail_pending" : "blocks_exist_in_other_threads";
|
|
4791
|
+
const status = {
|
|
4792
|
+
scope,
|
|
4793
|
+
namespace: this.namespaceFor(session),
|
|
4794
|
+
threadId,
|
|
4795
|
+
blockCount: results.length,
|
|
4796
|
+
namespaceBlockCount,
|
|
4797
|
+
namespaceThreadIds,
|
|
4798
|
+
openTailCount,
|
|
4799
|
+
emptyReason
|
|
4800
|
+
};
|
|
4737
4801
|
return this.batch(session, results.map((result) => ({
|
|
4738
4802
|
ref: `block:${result.id}:level:${result.level}`,
|
|
4739
4803
|
target: { eventIds: [], elementIds: [] }
|
|
4740
|
-
})), results);
|
|
4804
|
+
})), results, status);
|
|
4741
4805
|
}
|
|
4742
4806
|
async expandBlock(session, id, target) {
|
|
4743
4807
|
await this.flush();
|
|
@@ -5220,7 +5284,7 @@ var StrataGateRuntime = class {
|
|
|
5220
5284
|
return this.batch(session, results.map(({ node }) => ({
|
|
5221
5285
|
ref: `graph-node:${node.id}`,
|
|
5222
5286
|
target: { eventIds: node.sourceEventIds, elementIds: [] }
|
|
5223
|
-
})), results);
|
|
5287
|
+
})), results.map(({ node, score, matchedFields, matchReason }) => compactGraphNode(node, score, matchedFields, matchReason)));
|
|
5224
5288
|
}
|
|
5225
5289
|
async expandGraphNode(session, id) {
|
|
5226
5290
|
await this.flush();
|
|
@@ -5274,7 +5338,7 @@ var StrataGateRuntime = class {
|
|
|
5274
5338
|
const responses = this.models.takeSuccessfulResponses();
|
|
5275
5339
|
if (responses.length > 0) await memory.recordSuccessfulModelResponses(responses);
|
|
5276
5340
|
}
|
|
5277
|
-
batch(session, evidence, results) {
|
|
5341
|
+
batch(session, evidence, results, metadata = {}) {
|
|
5278
5342
|
const id = `batch_${++this.batchSequence}`;
|
|
5279
5343
|
const refs = new Map(evidence.map(({ ref, target }) => [ref, target]));
|
|
5280
5344
|
const key = String(session.id);
|
|
@@ -5285,7 +5349,7 @@ var StrataGateRuntime = class {
|
|
|
5285
5349
|
}
|
|
5286
5350
|
sessionBatches.set(id, { id, refs, status: "unresolved" });
|
|
5287
5351
|
this.latestBatchIds.set(key, id);
|
|
5288
|
-
return { batchId: id, evidenceRefs: [...refs.keys()], results };
|
|
5352
|
+
return { batchId: id, evidenceRefs: [...refs.keys()], results, ...metadata };
|
|
5289
5353
|
}
|
|
5290
5354
|
requireBatch(session, batchId, operation) {
|
|
5291
5355
|
const key = String(session.id);
|
|
@@ -5420,6 +5484,67 @@ function renderBlockSurfaceMessage(context) {
|
|
|
5420
5484
|
context.content
|
|
5421
5485
|
].join("\n");
|
|
5422
5486
|
}
|
|
5487
|
+
function compactTemporal(event) {
|
|
5488
|
+
const temporal = event.temporal;
|
|
5489
|
+
return Object.fromEntries(Object.entries({
|
|
5490
|
+
mentionedAt: temporal.mentionedAt,
|
|
5491
|
+
happenedStart: temporal.happenedStart,
|
|
5492
|
+
happenedEnd: temporal.happenedEnd,
|
|
5493
|
+
precision: temporal.precision,
|
|
5494
|
+
status: temporal.status,
|
|
5495
|
+
eventType: temporal.eventType
|
|
5496
|
+
}).filter(([, value]) => value !== void 0));
|
|
5497
|
+
}
|
|
5498
|
+
function compactText2(value, limit = 800) {
|
|
5499
|
+
return value.replace(/\s+/gu, " ").trim().slice(0, limit);
|
|
5500
|
+
}
|
|
5501
|
+
function compactEvent(event, score) {
|
|
5502
|
+
return {
|
|
5503
|
+
id: event.id,
|
|
5504
|
+
title: compactText2(event.title, 240),
|
|
5505
|
+
summary: compactText2(event.summary),
|
|
5506
|
+
sourceTime: event.temporal.happenedStart ?? event.temporal.mentionedAt ?? event.createdAt,
|
|
5507
|
+
temporal: compactTemporal(event),
|
|
5508
|
+
sourceBlockId: event.sourceBlockId,
|
|
5509
|
+
status: event.status,
|
|
5510
|
+
scope: event.scope,
|
|
5511
|
+
criticality: event.criticality,
|
|
5512
|
+
rankScore: score,
|
|
5513
|
+
scoreMeaning: "Ranking-only BM25/RRF score; not confidence, probability, or factual accuracy."
|
|
5514
|
+
};
|
|
5515
|
+
}
|
|
5516
|
+
function compactGraphNode(node, score, matchedFields, matchReason) {
|
|
5517
|
+
return {
|
|
5518
|
+
id: node.id,
|
|
5519
|
+
name: node.name,
|
|
5520
|
+
type: node.type,
|
|
5521
|
+
aliases: node.aliases.map((alias) => compactText2(alias, 160)),
|
|
5522
|
+
currentState: compactText2(node.currentState, 500),
|
|
5523
|
+
status: node.status,
|
|
5524
|
+
rankScore: score,
|
|
5525
|
+
...matchedFields ? { matchedFields } : {},
|
|
5526
|
+
...matchReason ? { matchReason } : {},
|
|
5527
|
+
scoreMeaning: "Ranking-only BM25/RRF score; not confidence, probability, or factual accuracy."
|
|
5528
|
+
};
|
|
5529
|
+
}
|
|
5530
|
+
function compactRawHit(result) {
|
|
5531
|
+
const message = {
|
|
5532
|
+
id: result.message.id,
|
|
5533
|
+
role: result.message.role,
|
|
5534
|
+
content: compactText2(result.message.content, 500),
|
|
5535
|
+
createdAt: result.message.createdAt,
|
|
5536
|
+
...result.message.threadId ? { threadId: result.message.threadId } : {}
|
|
5537
|
+
};
|
|
5538
|
+
return {
|
|
5539
|
+
id: result.message.id,
|
|
5540
|
+
blockId: result.blockId,
|
|
5541
|
+
turnRange: result.turnRange,
|
|
5542
|
+
message,
|
|
5543
|
+
sourceTime: result.message.createdAt,
|
|
5544
|
+
...result.message.threadId ? { threadId: result.message.threadId } : {},
|
|
5545
|
+
detailHint: "Use memory_expand_block with blockId for complete block/source details."
|
|
5546
|
+
};
|
|
5547
|
+
}
|
|
5423
5548
|
function currentBlockSurfaceMessages(session) {
|
|
5424
5549
|
const blocks = /* @__PURE__ */ new Map();
|
|
5425
5550
|
if (!session.surface?.nodes) return blocks;
|
|
@@ -5564,7 +5689,7 @@ function sessionOf(exec) {
|
|
|
5564
5689
|
function registerMemoryTools(ctx, runtime) {
|
|
5565
5690
|
ctx.tools.register(defineTool({
|
|
5566
5691
|
name: "memory_search_events",
|
|
5567
|
-
description: "Search durable StrataGate event memories. Returns a
|
|
5692
|
+
description: "Search durable StrataGate event memories. Returns a compact batch of event cards (id, title, summary, time, and evidence refs); call memory_expand_event for narrative/quotes/source messages. rankScore is BM25/RRF ordering only, never confidence or factual accuracy. Pass batchId to memory_assess before relying on evidence.",
|
|
5568
5693
|
parameters: {
|
|
5569
5694
|
query: { type: "string", required: true, description: "What historical decision, event, preference, or outcome to find." },
|
|
5570
5695
|
limit: { type: "integer", description: "Maximum results, 1-20." },
|
|
@@ -5582,7 +5707,7 @@ function registerMemoryTools(ctx, runtime) {
|
|
|
5582
5707
|
}));
|
|
5583
5708
|
ctx.tools.register(defineTool({
|
|
5584
5709
|
name: "memory_search_graph",
|
|
5585
|
-
description: "Search the current Event-backed Knowledge Graph for people, projects, organizations, tools, places, facts, and relations. Returns
|
|
5710
|
+
description: "Search the current Event-backed Knowledge Graph for people, projects, organizations, tools, places, facts, and relations. Returns compact node cards with matchedFields/matchReason; call memory_expand_graph_node for complete facts and edges. rankScore is BM25/RRF ordering only, never confidence or factual accuracy. Results are independently assessable.",
|
|
5586
5711
|
parameters: {
|
|
5587
5712
|
query: { type: "string", required: true },
|
|
5588
5713
|
limit: { type: "integer", description: "Maximum results, 1-20." }
|
|
@@ -5599,7 +5724,7 @@ function registerMemoryTools(ctx, runtime) {
|
|
|
5599
5724
|
}));
|
|
5600
5725
|
ctx.tools.register(defineTool({
|
|
5601
5726
|
name: "memory_search_elements",
|
|
5602
|
-
description: "Deprecated compatibility search for legacy Element-card data. Prefer memory_search_graph.",
|
|
5727
|
+
description: "Deprecated compatibility search for legacy Element-card data. Returns compact fact hits; rankScore is BM25/RRF ordering only, never confidence or factual accuracy. Prefer memory_search_graph.",
|
|
5603
5728
|
parameters: {
|
|
5604
5729
|
query: { type: "string", required: true },
|
|
5605
5730
|
limit: { type: "integer" },
|
|
@@ -5615,20 +5740,23 @@ function registerMemoryTools(ctx, runtime) {
|
|
|
5615
5740
|
}));
|
|
5616
5741
|
ctx.tools.register(defineTool({
|
|
5617
5742
|
name: "memory_search_raw",
|
|
5618
|
-
description: "Search
|
|
5743
|
+
description: "Search archived messages when summarized memories are insufficient. Returns compact raw hits (message id, blockId, excerpt, role, and time); use memory_expand_block with blockId for complete source details. By default searches the whole current namespace; use scope=session for the active thread. Returns evidence refs and batchId for assessment.",
|
|
5619
5744
|
parameters: {
|
|
5620
5745
|
query: { type: "string", required: true },
|
|
5621
|
-
limit: { type: "integer" }
|
|
5746
|
+
limit: { type: "integer" },
|
|
5747
|
+
scope: { type: "string", enum: ["namespace", "session"], description: "Search range. Defaults to namespace for compatibility with historical raw search behavior." }
|
|
5622
5748
|
},
|
|
5623
5749
|
output: jsonOutput,
|
|
5624
|
-
execute: async (args, exec) => runtime.searchRaw(sessionOf(exec), args.query, args.limit)
|
|
5750
|
+
execute: async (args, exec) => runtime.searchRaw(sessionOf(exec), args.query, args.limit, args.scope)
|
|
5625
5751
|
}));
|
|
5626
5752
|
ctx.tools.register(defineTool({
|
|
5627
5753
|
name: "memory_get_blocks",
|
|
5628
|
-
description: "List decayed conversation-block summaries and their current detail levels.
|
|
5629
|
-
parameters: {
|
|
5754
|
+
description: "List decayed conversation-block summaries and their current detail levels. Defaults to the active session only; use scope=namespace to inspect every thread in the current namespace. The response always reports scope, namespace, threadId, counts, and a machine-readable emptyReason when no blocks match.",
|
|
5755
|
+
parameters: {
|
|
5756
|
+
scope: { type: "string", enum: ["session", "namespace"], description: "Query range. Defaults to session to preserve existing isolation behavior." }
|
|
5757
|
+
},
|
|
5630
5758
|
output: jsonOutput,
|
|
5631
|
-
execute: async (
|
|
5759
|
+
execute: async (args, exec) => runtime.blocks(sessionOf(exec), args.scope)
|
|
5632
5760
|
}));
|
|
5633
5761
|
ctx.tools.register(defineTool({
|
|
5634
5762
|
name: "memory_expand_block",
|