stratagate-dsh 0.2.70 → 0.2.72

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/dist/plugin.js CHANGED
@@ -1314,7 +1314,7 @@ function normalizeRetrievalAssessment(input, batchEvidenceRefs) {
1314
1314
  }
1315
1315
 
1316
1316
  // packages/core/src/storage.ts
1317
- var STRATAGATE_STORAGE_SCHEMA_VERSION = 10;
1317
+ var STRATAGATE_STORAGE_SCHEMA_VERSION = 11;
1318
1318
  var KNOWLEDGE_GRAPH_PROJECTOR_VERSION = 1;
1319
1319
  var DERIVATION_MAX_ATTEMPTS = 3;
1320
1320
  var StorageConflictError = class extends Error {
@@ -1449,6 +1449,11 @@ function normalizeSnapshot(value) {
1449
1449
  schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION,
1450
1450
  externalMemoryImportJobs: []
1451
1451
  };
1452
+ } else if (schemaVersion === 10) {
1453
+ snapshot = {
1454
+ ...structuredClone(value),
1455
+ schemaVersion: STRATAGATE_STORAGE_SCHEMA_VERSION
1456
+ };
1452
1457
  } else if (schemaVersion === STRATAGATE_STORAGE_SCHEMA_VERSION) {
1453
1458
  snapshot = structuredClone(value);
1454
1459
  } else {
@@ -1471,8 +1476,16 @@ function normalizeSnapshot(value) {
1471
1476
  for (const job of snapshot.graphProjectionJobs) {
1472
1477
  if (job.nextRetryAt === void 0) job.nextRetryAt = null;
1473
1478
  }
1479
+ const sourceBlockMap = new Map(snapshot.blocks.map((block) => [block.id, block]));
1474
1480
  for (const event of snapshot.events) {
1475
1481
  event.temporal = { ...event.temporal, eventType: normalizeStandardEventType(event.temporal.eventType) };
1482
+ if (event.formedTurn === void 0) {
1483
+ const sourceBlock = sourceBlockMap.get(event.sourceBlockId);
1484
+ const reliableSource = sourceBlock && !sourceBlock.threadId?.startsWith("external-import:") && Number.isSafeInteger(sourceBlock.endTurn) && sourceBlock.endTurn >= 0;
1485
+ if (reliableSource) event.formedTurn = sourceBlock.endTurn;
1486
+ } else if (!Number.isSafeInteger(event.formedTurn) || event.formedTurn < 0) {
1487
+ throw new TypeError("Invalid StrataGate snapshot: Event formedTurn must be a non-negative integer");
1488
+ }
1476
1489
  }
1477
1490
  for (const block of snapshot.blocks) {
1478
1491
  if (block.processingStatus !== "pending" && block.processingStatus !== "ready") {
@@ -1719,6 +1732,7 @@ CREATE TABLE IF NOT EXISTS events (
1719
1732
  tags_json TEXT NOT NULL,
1720
1733
  quotes_json TEXT NOT NULL,
1721
1734
  source_block_id TEXT NOT NULL,
1735
+ formed_turn INTEGER,
1722
1736
  temporal_json TEXT NOT NULL,
1723
1737
  scope TEXT NOT NULL,
1724
1738
  criticality TEXT NOT NULL,
@@ -2024,6 +2038,7 @@ var SqliteStorage = class {
2024
2038
  quotes: parseJson(row.quotes_json, "events.quotes_json"),
2025
2039
  sourceMessageIds: sourcesByEvent.get(row.id) ?? [],
2026
2040
  sourceBlockId: row.source_block_id,
2041
+ ...row.formed_turn === null ? {} : { formedTurn: row.formed_turn },
2027
2042
  temporal: (() => {
2028
2043
  const temporal = parseJson(row.temporal_json, "events.temporal_json");
2029
2044
  return { ...temporal, eventType: normalizeStandardEventType(temporal.eventType) };
@@ -2334,10 +2349,10 @@ var SqliteStorage = class {
2334
2349
  const insertEvent = this.database.prepare(`
2335
2350
  INSERT INTO events (
2336
2351
  namespace, id, position, title, summary, narrative, tags_json, quotes_json, source_block_id,
2337
- temporal_json, scope, criticality, confidence, status, superseded_by,
2352
+ formed_turn, temporal_json, scope, criticality, confidence, status, superseded_by,
2338
2353
  mention_count, last_adopted_turn, last_retrieved_at, pinned, floor_weight, forced_cap,
2339
2354
  created_at, updated_at
2340
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2355
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2341
2356
  ON CONFLICT (namespace, id) DO UPDATE SET
2342
2357
  position = excluded.position,
2343
2358
  title = excluded.title,
@@ -2346,6 +2361,7 @@ var SqliteStorage = class {
2346
2361
  tags_json = excluded.tags_json,
2347
2362
  quotes_json = excluded.quotes_json,
2348
2363
  source_block_id = excluded.source_block_id,
2364
+ formed_turn = excluded.formed_turn,
2349
2365
  temporal_json = excluded.temporal_json,
2350
2366
  scope = excluded.scope,
2351
2367
  criticality = excluded.criticality,
@@ -2376,6 +2392,7 @@ var SqliteStorage = class {
2376
2392
  JSON.stringify(event.tags),
2377
2393
  JSON.stringify(event.quotes),
2378
2394
  event.sourceBlockId,
2395
+ event.formedTurn ?? null,
2379
2396
  JSON.stringify(event.temporal),
2380
2397
  event.scope,
2381
2398
  event.criticality,
@@ -2644,6 +2661,23 @@ var SqliteStorage = class {
2644
2661
  if (!blockColumns.some(({ name: name2 }) => name2 === "processing_status")) {
2645
2662
  this.database.exec("ALTER TABLE blocks ADD COLUMN processing_status TEXT NOT NULL DEFAULT 'ready' CHECK (processing_status IN ('pending', 'ready'))");
2646
2663
  }
2664
+ const eventColumns = this.database.prepare("PRAGMA table_info('events')").all();
2665
+ if (!eventColumns.some(({ name: name2 }) => name2 === "formed_turn")) {
2666
+ this.database.exec("ALTER TABLE events ADD COLUMN formed_turn INTEGER");
2667
+ }
2668
+ this.database.exec(`
2669
+ UPDATE events
2670
+ SET formed_turn = (
2671
+ SELECT blocks.end_turn FROM blocks
2672
+ WHERE blocks.namespace = events.namespace AND blocks.id = events.source_block_id
2673
+ )
2674
+ WHERE formed_turn IS NULL AND EXISTS (
2675
+ SELECT 1 FROM blocks
2676
+ WHERE blocks.namespace = events.namespace
2677
+ AND blocks.id = events.source_block_id
2678
+ AND (blocks.thread_id IS NULL OR blocks.thread_id NOT LIKE 'external-import:%')
2679
+ )
2680
+ `);
2647
2681
  const extractionColumns = this.database.prepare("PRAGMA table_info('extraction_jobs')").all();
2648
2682
  if (!extractionColumns.some(({ name: name2 }) => name2 === "next_retry_at")) {
2649
2683
  this.database.exec("ALTER TABLE extraction_jobs ADD COLUMN next_retry_at TEXT");
@@ -4059,8 +4093,10 @@ var StrataGate = class _StrataGate {
4059
4093
  const sourceMessageIds = requestedRefs.length > 0 ? requestedRefs : sourceBlock.l5Raw.map((message) => message.id);
4060
4094
  const now = toUtc8Iso(this.now());
4061
4095
  const criticality = input.criticality ?? "routine";
4096
+ const formedTurn = sourceBlock.threadId?.startsWith("external-import:") ? this.currentTurn : sourceBlock.endTurn;
4062
4097
  const event = {
4063
4098
  id: input.id ?? this.idFactory("evt"),
4099
+ formedTurn,
4064
4100
  title: input.title.trim(),
4065
4101
  summary: input.summary.trim(),
4066
4102
  narrative: input.narrative?.trim() || input.summary.trim(),
@@ -4079,7 +4115,7 @@ var StrataGate = class _StrataGate {
4079
4115
  supersededBy: null,
4080
4116
  weight: {
4081
4117
  mentionCount: 1,
4082
- lastAdoptedTurn: this.currentTurn,
4118
+ lastAdoptedTurn: formedTurn,
4083
4119
  lastRetrievedAt: null,
4084
4120
  pinned: false,
4085
4121
  floorWeight: criticalityFloor(criticality),
@@ -5631,6 +5667,20 @@ var SUPPORTED_RUNTIME_FAMILIES = [
5631
5667
  "@deepseek-ai/dsh-tools": "0.1.5-rc.2",
5632
5668
  "@deepseek-ai/schemastery": "3.18.2"
5633
5669
  }
5670
+ },
5671
+ {
5672
+ cli: "0.1.6-alpha.1",
5673
+ versions: {
5674
+ "@deepseek-ai/cordis": "4.0.2",
5675
+ "@deepseek-ai/dsh-agent-default-model": "0.1.6-alpha.1",
5676
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.6-alpha.1",
5677
+ "@deepseek-ai/dsh-llm": "0.1.6-alpha.1",
5678
+ "@deepseek-ai/dsh-session": "0.1.6-alpha.1",
5679
+ "@deepseek-ai/dsh-settings": "0.1.6-alpha.1",
5680
+ "@deepseek-ai/dsh-system-prompt": "0.1.6-alpha.1",
5681
+ "@deepseek-ai/dsh-tools": "0.1.6-alpha.1",
5682
+ "@deepseek-ai/schemastery": "3.18.2"
5683
+ }
5634
5684
  }
5635
5685
  ];
5636
5686
  function installedVersion(packageName) {
@@ -5653,7 +5703,7 @@ function classifyDshRuntime(packageVersions) {
5653
5703
  if (family) return { cliVersion: family.cli, packageVersions };
5654
5704
  const found = RUNTIME_PACKAGES.map((name2) => `${name2}@${packageVersions[name2]}`).join(", ");
5655
5705
  throw new Error(
5656
- `StrataGate cannot start because this DSH profile resolves an unsupported or mixed core runtime. Resolved: ${found}. Supported tested hosts are @deepseek-ai/dsh@0.1.2-rc.1 (internal DSH packages 0.1.2-rc.1) and @deepseek-ai/dsh@0.1.5-rc.1 (its real dependency tree uses internal DSH packages 0.1.5-rc.2). Reinstall or update stratagate-dsh through \`dsh plugin --profile <name> add <package>\` so the host supplies its peers.`
5706
+ `StrataGate cannot start because this DSH profile resolves an unsupported or mixed core runtime. Resolved: ${found}. Supported tested hosts are @deepseek-ai/dsh@0.1.2-rc.1 (internal DSH packages 0.1.2-rc.1) and @deepseek-ai/dsh@0.1.5-rc.1 (its real dependency tree uses internal DSH packages 0.1.5-rc.2), and @deepseek-ai/dsh@0.1.6-alpha.1 (internal DSH packages 0.1.6-alpha.1). Reinstall or update stratagate-dsh through \`dsh plugin --profile <name> add <package>\` so the host supplies its peers.`
5657
5707
  );
5658
5708
  }
5659
5709
  function assertCompatibleDshRuntime() {
@@ -7983,7 +8033,8 @@ function appendWeightSegment(points, event, fromTurn, toTurn, mentionCount) {
7983
8033
  if (toTurn < fromTurn) return;
7984
8034
  if (toTurn === fromTurn) return;
7985
8035
  const span = toTurn - fromTurn;
7986
- const step = Math.max(1, Math.ceil(span / 32));
8036
+ const samples = Math.min(256, Math.max(12, Math.ceil(span * 12)));
8037
+ const step = span / samples;
7987
8038
  for (let turn = fromTurn; turn < toTurn; turn += step) {
7988
8039
  points.push({ turn, weight: sampledEventWeight(event, turn, fromTurn, mentionCount), kind: "sample" });
7989
8040
  }
@@ -7991,65 +8042,116 @@ function appendWeightSegment(points, event, fromTurn, toTurn, mentionCount) {
7991
8042
  }
7992
8043
  function eventWeightTrajectory(snapshot, event) {
7993
8044
  const currentTurn = snapshot.currentTurn;
8045
+ const formedTurn = Number.isSafeInteger(event.formedTurn) && event.formedTurn >= 0 ? event.formedTurn : null;
8046
+ const sourceBlock = snapshot.blocks.find(({ id }) => id === event.sourceBlockId);
8047
+ const sourceBlockEndTurn = Number.isSafeInteger(sourceBlock?.endTurn) && sourceBlock.endTurn >= 0 ? sourceBlock.endTurn : null;
7994
8048
  const effectiveAdoptions = Math.max(0, event.weight.mentionCount - 1);
7995
8049
  const adoptionReceipts = snapshot.usageReceipts.filter(({ eventIds }) => eventIds.includes(event.id));
7996
8050
  const adoptionTurns = adoptionReceipts.map(({ audit: audit2 }) => audit2?.turn).filter((turn) => Number.isSafeInteger(turn) && turn >= 0).sort((left, right) => left - right);
7997
- const historyComplete = adoptionReceipts.length === effectiveAdoptions && adoptionTurns.length === adoptionReceipts.length && (effectiveAdoptions === 0 || adoptionTurns.at(-1) === event.weight.lastAdoptedTurn);
8051
+ const confirmedAdoptionTurns = [...adoptionTurns];
8052
+ if (effectiveAdoptions > 0 && Number.isSafeInteger(event.weight.lastAdoptedTurn) && event.weight.lastAdoptedTurn >= 0) {
8053
+ confirmedAdoptionTurns.push(event.weight.lastAdoptedTurn);
8054
+ }
8055
+ confirmedAdoptionTurns.sort((left, right) => left - right);
8056
+ const groupedAdoptions = [...new Set(confirmedAdoptionTurns)].map((turn) => ({
8057
+ turn,
8058
+ adoptionCount: Math.max(1, adoptionTurns.filter((value) => value === turn).length)
8059
+ }));
8060
+ const earliestKnownAdoptionTurn = groupedAdoptions[0]?.turn ?? null;
8061
+ const trajectoryStartTurn = formedTurn ?? sourceBlockEndTurn ?? earliestKnownAdoptionTurn ?? currentTurn;
8062
+ const formationTurnSource = formedTurn !== null ? "formedTurn" : sourceBlockEndTurn !== null ? "sourceBlock" : null;
8063
+ const historyComplete = adoptionReceipts.length === effectiveAdoptions && adoptionTurns.length === adoptionReceipts.length && (effectiveAdoptions === 0 || adoptionTurns.at(-1) === event.weight.lastAdoptedTurn) && adoptionTurns.every((turn) => turn >= trajectoryStartTurn) && (effectiveAdoptions > 0 || event.weight.lastAdoptedTurn === trajectoryStartTurn);
8064
+ const adoptionHistoryComplete = adoptionReceipts.length === effectiveAdoptions && adoptionReceipts.every((receipt) => Boolean(receipt.createdAt) && Number.isFinite(Date.parse(receipt.createdAt)) && Boolean(receipt.audit?.sessionId?.trim()) && Number.isSafeInteger(receipt.audit?.turn) && receipt.audit.turn >= 0) && (formedTurn === null || adoptionReceipts.every((receipt) => receipt.audit.turn >= formedTurn));
8065
+ const adoptionHistory = adoptionReceipts.filter((receipt) => Boolean(receipt.createdAt) && Number.isFinite(Date.parse(receipt.createdAt)) && Boolean(receipt.audit?.sessionId?.trim()) && Number.isSafeInteger(receipt.audit?.turn) && receipt.audit.turn >= 0 && (formedTurn === null || receipt.audit.turn >= formedTurn)).map((receipt) => ({
8066
+ receiptId: receipt.id,
8067
+ createdAt: receipt.createdAt,
8068
+ sessionId: receipt.audit.sessionId,
8069
+ turn: receipt.audit.turn,
8070
+ ...formedTurn === null ? {} : { relativeTurn: receipt.audit.turn - formedTurn },
8071
+ evidenceRefs: receipt.audit?.evidenceRefs ?? []
8072
+ })).sort((left, right) => left.turn - right.turn || left.createdAt.localeCompare(right.createdAt));
7998
8073
  const canInterpolate = event.status !== "forgotten" && event.status !== "archived" && event.weight.forcedCap === null && !event.weight.pinned;
7999
- const points = [];
8000
- if (canInterpolate && effectiveAdoptions === 0) {
8001
- appendWeightSegment(points, event, event.weight.lastAdoptedTurn, currentTurn, 1);
8002
- if (points.length > 0) {
8003
- const first = points[0];
8004
- points[0] = { turn: first.turn, weight: first.weight, kind: "creation", label: "\u521B\u5EFA" };
8005
- }
8006
- } else if (canInterpolate && historyComplete && adoptionTurns.length > 0) {
8007
- let anchorTurn = adoptionTurns[0];
8008
- let mentionCount = 2;
8009
- points.push({ turn: anchorTurn, weight: 1, kind: "adoption", label: "\u91C7\u7528" });
8010
- for (const [index, turn] of adoptionTurns.slice(1).entries()) {
8011
- appendWeightSegment(points, event, anchorTurn, turn, mentionCount);
8012
- points.push({ turn, weight: 1, kind: "adoption", label: index === adoptionTurns.length - 2 ? "\u518D\u6B21\u91C7\u7528" : "\u91C7\u7528" });
8074
+ const segments = [];
8075
+ const originPoint = formationTurnSource ? { turn: trajectoryStartTurn, weight: 1, kind: "creation", label: formationTurnSource === "formedTurn" ? "\u5F62\u6210" : "\u6765\u6E90" } : null;
8076
+ if (canInterpolate && historyComplete && originPoint) {
8077
+ const lifecycle = [originPoint];
8078
+ let anchorTurn = trajectoryStartTurn;
8079
+ let mentionCount = 1;
8080
+ for (const { turn, adoptionCount } of groupedAdoptions) {
8081
+ if (turn < trajectoryStartTurn || turn > currentTurn) continue;
8082
+ appendWeightSegment(lifecycle, event, anchorTurn, turn, mentionCount);
8083
+ lifecycle.push({ turn, weight: 1, kind: "adoption", adoptionCount, label: adoptionCount > 1 ? `\u91C7\u7EB3 \xD7${adoptionCount}` : "\u91C7\u7EB3" });
8013
8084
  anchorTurn = turn;
8014
- mentionCount += 1;
8085
+ mentionCount += adoptionCount;
8015
8086
  }
8016
- appendWeightSegment(points, event, anchorTurn, currentTurn, mentionCount);
8087
+ appendWeightSegment(lifecycle, event, anchorTurn, currentTurn, mentionCount);
8088
+ segments.push({ certainty: "known", points: lifecycle });
8017
8089
  } else if (canInterpolate) {
8018
- appendWeightSegment(points, event, event.weight.lastAdoptedTurn, currentTurn, event.weight.mentionCount);
8019
- if (effectiveAdoptions > 0 && points.length > 0) {
8020
- const first = points[0];
8021
- points[0] = { turn: first.turn, weight: first.weight, kind: "adoption", label: "\u6700\u8FD1\u91C7\u7528" };
8022
- }
8090
+ let anchorPoint = originPoint;
8091
+ let mentionCount = 1;
8092
+ const visibleAdoptions = groupedAdoptions.filter(({ turn }) => turn >= trajectoryStartTurn && turn <= currentTurn);
8093
+ for (const { turn, adoptionCount } of visibleAdoptions) {
8094
+ if (anchorPoint && turn > anchorPoint.turn) {
8095
+ const incomplete = [anchorPoint];
8096
+ appendWeightSegment(incomplete, event, anchorPoint.turn, turn, mentionCount);
8097
+ incomplete.push({ turn, weight: 1, kind: "adoption", adoptionCount, label: adoptionCount > 1 ? `\u91C7\u7EB3 \xD7${adoptionCount}` : "\u91C7\u7EB3" });
8098
+ segments.push({ certainty: "incomplete", points: incomplete });
8099
+ } else {
8100
+ segments.push({ certainty: "known", points: [{ turn, weight: 1, kind: "adoption", adoptionCount, label: adoptionCount > 1 ? `\u91C7\u7EB3 \xD7${adoptionCount}` : "\u91C7\u7EB3" }] });
8101
+ }
8102
+ anchorPoint = { turn, weight: 1, kind: "adoption", adoptionCount, label: adoptionCount > 1 ? `\u91C7\u7EB3 \xD7${adoptionCount}` : "\u91C7\u7EB3" };
8103
+ mentionCount += adoptionCount;
8104
+ }
8105
+ if (anchorPoint && anchorPoint.turn <= currentTurn) {
8106
+ const latestIsReliable = effectiveAdoptions > 0 && anchorPoint.turn === event.weight.lastAdoptedTurn && visibleAdoptions.at(-1)?.turn === event.weight.lastAdoptedTurn;
8107
+ const tail = [anchorPoint];
8108
+ appendWeightSegment(tail, event, anchorPoint.turn, currentTurn, latestIsReliable ? event.weight.mentionCount : mentionCount);
8109
+ if (tail.length > 1) segments.push({ certainty: latestIsReliable ? "known" : "incomplete", points: tail });
8110
+ } else if (originPoint && originPoint.turn <= currentTurn) {
8111
+ const tail = [originPoint];
8112
+ appendWeightSegment(tail, event, originPoint.turn, currentTurn, 1);
8113
+ if (tail.length > 1) segments.push({ certainty: historyComplete ? "known" : "incomplete", points: tail });
8114
+ else segments.push({ certainty: "known", points: [originPoint] });
8115
+ }
8116
+ } else if (originPoint) {
8117
+ segments.push({ certainty: "known", points: [originPoint] });
8023
8118
  }
8024
8119
  const currentWeight = memoryWeightAt(event, currentTurn);
8025
- if (points.length === 0 || points.at(-1)?.turn !== currentTurn) {
8026
- points.push({ turn: currentTurn, weight: currentWeight, kind: "current", label: "\u5F53\u524D" });
8027
- } else if (points.at(-1)?.kind === "creation" || points.at(-1)?.kind === "adoption") {
8028
- points[points.length - 1] = {
8029
- ...points[points.length - 1],
8030
- weight: currentWeight,
8031
- label: `${points[points.length - 1].label} \xB7 \u5F53\u524D`
8032
- };
8120
+ const lastSegment = segments.at(-1);
8121
+ if (!lastSegment || lastSegment.points.at(-1)?.turn !== currentTurn) {
8122
+ segments.push({ certainty: "known", points: [{ turn: currentTurn, weight: currentWeight, kind: "current", label: "\u5F53\u524D" }] });
8123
+ } else if (lastSegment.points.at(-1)?.kind === "sample") {
8124
+ lastSegment.points[lastSegment.points.length - 1] = { ...lastSegment.points[lastSegment.points.length - 1], weight: currentWeight, kind: "current", label: "\u5F53\u524D" };
8033
8125
  } else {
8034
- points[points.length - 1] = { ...points[points.length - 1], weight: currentWeight, kind: "current", label: "\u5F53\u524D" };
8126
+ segments.push({ certainty: "known", points: [{ turn: currentTurn, weight: currentWeight, kind: "current", label: "\u5F53\u524D" }] });
8035
8127
  }
8128
+ const points = segments.flatMap(({ points: segmentPoints }) => segmentPoints);
8036
8129
  return {
8037
8130
  scale: "conversation_turn",
8131
+ formedTurn,
8132
+ trajectoryStartTurn,
8133
+ formationTurnSource,
8038
8134
  currentTurn,
8039
8135
  currentWeight,
8040
8136
  effectiveAdoptions,
8137
+ floorWeight: event.weight.floorWeight,
8138
+ criticality: event.criticality,
8041
8139
  latestAdoptionTurn: effectiveAdoptions > 0 ? event.weight.lastAdoptedTurn : null,
8042
8140
  turnsSinceLatestAdoption: effectiveAdoptions > 0 ? Math.max(0, currentTurn - event.weight.lastAdoptedTurn) : null,
8043
8141
  lastRetrievedAt: event.weight.lastRetrievedAt,
8044
8142
  recordedAdoptionTurns: adoptionTurns,
8045
8143
  historyComplete,
8144
+ adoptionHistoryComplete,
8145
+ adoptionHistory,
8146
+ segments,
8046
8147
  points,
8047
- note: !canInterpolate ? "\u56FA\u5B9A\u3001\u5C01\u5B58\u6216\u72B6\u6001\u4E0A\u9650\u7684\u53D8\u66F4\u8F6E\u6B21\u6CA1\u6709\u5386\u53F2\u8BB0\u5F55\uFF0C\u56E0\u6B64\u4EC5\u663E\u793A\u5F53\u524D\u771F\u5B9E\u6743\u91CD\u3002" : effectiveAdoptions > 0 && !historyComplete ? "\u90E8\u5206\u65E9\u671F\u91C7\u7528\u8BB0\u5F55\u7F3A\u5C11\u8F6E\u6B21\uFF1B\u66F2\u7EBF\u4EC5\u4ECE\u6700\u8FD1\u4E00\u6B21\u53EF\u786E\u8BA4\u7684\u5F3A\u5316\u5F00\u59CB\u3002" : effectiveAdoptions > 0 ? "\u91C7\u7528\u8F6E\u6B21\u6765\u81EA\u4F7F\u7528\u56DE\u6267\uFF1B\u521B\u5EFA\u8F6E\u6B21\u672A\u5355\u72EC\u4FDD\u5B58\uFF0C\u56E0\u6B64\u4E0D\u63A8\u6D4B\u521B\u5EFA\u8282\u70B9\u3002" : "\u5C1A\u672A\u53D1\u751F\u6709\u6548\u91C7\u7528\uFF1B\u521B\u5EFA\u951A\u70B9\u6765\u81EA Event \u5F53\u524D\u6743\u91CD\u72B6\u6001\u3002"
8148
+ note: !canInterpolate ? "\u56FA\u5B9A\u3001\u5C01\u5B58\u6216\u72B6\u6001\u4E0A\u9650\u7684\u53D8\u66F4\u8F6E\u6B21\u6CA1\u6709\u5386\u53F2\u8BB0\u5F55\uFF0C\u56E0\u6B64\u4EC5\u663E\u793A\u5F53\u524D\u771F\u5B9E\u6743\u91CD\u3002" : !historyComplete ? "\u65E7\u7248\u672C\u672A\u8BB0\u5F55\u90E8\u5206\u91C7\u7EB3\u7684\u5177\u4F53\u8F6E\u6B21\uFF1B\u786E\u5B9A\u8282\u70B9\u4E0E\u533A\u95F4\u7167\u5E38\u663E\u793A\uFF0C\u7F3A\u5931\u533A\u95F4\u4EC5\u4F5C\u8D8B\u52BF\u8FDE\u63A5\u3002" : effectiveAdoptions > 0 ? "\u91C7\u7EB3\u8F6E\u6B21\u6765\u81EA\u771F\u5B9E\u4F7F\u7528\u56DE\u6267\u3002" : "\u5C1A\u672A\u88AB Agent \u91C7\u7EB3\u3002"
8048
8149
  };
8049
8150
  }
8050
8151
  function eventSummary(event, snapshot) {
8051
8152
  return {
8052
8153
  id: event.id,
8154
+ formedTurn: event.formedTurn,
8053
8155
  title: event.title,
8054
8156
  summary: event.summary,
8055
8157
  narrative: event.narrative,
@@ -8509,15 +8611,32 @@ async function memories(runtime, url) {
8509
8611
  const offset = numeric(url.searchParams.get("offset"), 0, 0, Number.MAX_SAFE_INTEGER);
8510
8612
  const limit = numeric(url.searchParams.get("limit"), 100, 1, 200);
8511
8613
  let values;
8512
- if (kind === "events") values = [...snapshot.events].sort((left, right) => {
8513
- const time = (event) => event.temporal.happenedStart ?? event.temporal.happenedEnd ?? event.temporal.mentionedAt ?? event.createdAt;
8514
- return time(right).localeCompare(time(left));
8515
- }).map((event) => ({
8516
- ...eventSummary(event, snapshot),
8517
- relatedNodes: snapshot.graphNodes.filter(({ id, sourceEventIds }) => sourceEventIds.includes(event.id) || (event.temporal.participantNodeIds ?? []).includes(id)).map(({ id, name: name2, type }) => ({ id, name: name2, type })),
8518
- relatedElements: snapshot.elements.filter(({ sourceEventIds }) => sourceEventIds.includes(event.id)).map(({ id, name: name2 }) => ({ id, name: name2 }))
8519
- }));
8520
- else if (kind === "graph") {
8614
+ if (kind === "events") {
8615
+ const timeline = url.searchParams.get("timeline") === "true";
8616
+ const timeFilter = url.searchParams.get("time")?.trim() ?? "";
8617
+ const participant = url.searchParams.get("participant")?.trim() ?? "";
8618
+ const eventType = url.searchParams.get("eventType")?.trim() ?? "";
8619
+ const eventStatus = url.searchParams.get("eventStatus")?.trim() ?? "";
8620
+ const now = /* @__PURE__ */ new Date();
8621
+ const weekAgo = now.getTime() - 7 * 864e5;
8622
+ const occurrence = (event) => {
8623
+ const happened = event.temporal.happenedStart ?? event.temporal.happenedEnd;
8624
+ return { value: happened ?? event.temporal.mentionedAt ?? event.createdAt, known: Boolean(happened) };
8625
+ };
8626
+ values = [...snapshot.events].sort((left, right) => occurrence(right).value.localeCompare(occurrence(left).value)).filter((event) => !timeline || event.status !== "forgotten" && event.status !== "archived").filter((event) => !eventType || event.temporal.eventType === eventType).filter((event) => !eventStatus || event.temporal.status === eventStatus).filter((event) => !participant || (event.temporal.participantNodeIds ?? []).includes(participant)).filter((event) => {
8627
+ if (!timeFilter) return true;
8628
+ const info = occurrence(event);
8629
+ if (timeFilter === "unknown") return !info.known;
8630
+ const time = Date.parse(info.value);
8631
+ if (timeFilter === "today") return Number.isFinite(time) && new Date(time).toDateString() === now.toDateString();
8632
+ if (timeFilter === "week") return Number.isFinite(time) && time >= weekAgo;
8633
+ return true;
8634
+ }).map((event) => ({
8635
+ ...eventSummary(event, snapshot),
8636
+ relatedNodes: snapshot.graphNodes.filter(({ id }) => (event.temporal.participantNodeIds ?? []).includes(id)).map(({ id, name: name2, type, aliases }) => ({ id, name: name2, type, aliases })),
8637
+ relatedElements: snapshot.elements.filter(({ sourceEventIds }) => sourceEventIds.includes(event.id)).map(({ id, name: name2 }) => ({ id, name: name2 }))
8638
+ }));
8639
+ } else if (kind === "graph") {
8521
8640
  const eventMap = new Map(snapshot.events.map((event) => [event.id, event]));
8522
8641
  return {
8523
8642
  namespace,
@@ -8705,6 +8824,9 @@ async function sources(runtime, url) {
8705
8824
  return {
8706
8825
  namespace,
8707
8826
  events: events.map((event) => eventSummary(event, eventId ? snapshot : void 0)),
8827
+ ...eventId ? {
8828
+ relatedNodes: snapshot.graphNodes.filter(({ id }) => events[0]?.temporal.participantNodeIds?.includes(id)).map(({ id, name: name2, type, aliases }) => ({ id, name: name2, type, aliases }))
8829
+ } : {},
8708
8830
  elements: elements.map(elementSummary),
8709
8831
  blocks: events.map((event) => snapshot.blocks.find(({ id }) => id === event.sourceBlockId)).filter((block) => Boolean(block)).map((block) => ({ id: block.id, title: block.l0Title, createdAt: block.createdAt })),
8710
8832
  messages: sourceMessages(snapshot, ids)
@@ -9264,7 +9386,7 @@ async function apply(ctx, config) {
9264
9386
  throw new Error(`StrataGate could not safely migrate legacy citation events: ${detail}`);
9265
9387
  }
9266
9388
  if (legacyMigration.migrated > 0) {
9267
- ctx.logger.info(`stratagate-memory prepared ${legacyMigration.migrated} legacy Session generation(s) for DSH 0.1.5`);
9389
+ ctx.logger.info(`stratagate-memory prepared ${legacyMigration.migrated} legacy Session generation(s) for DSH ${compatibility.cliVersion}`);
9268
9390
  }
9269
9391
  await mkdir2(dirname3(resolved.database), { recursive: true });
9270
9392
  const models = new DshModelBridge(ctx, resolved);