@agenr/skeln-plugin 2026.6.2 → 2026.6.3

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  formatTargetSelectorFromParams
3
- } from "./chunk-LDJN7CVU.js";
3
+ } from "./chunk-U74RE3L7.js";
4
4
 
5
5
  // src/adapters/openclaw/transcript/parser.ts
6
6
  import { createHash } from "crypto";
@@ -28,7 +28,7 @@ import {
28
28
  parseExpiry,
29
29
  parseRecallMode,
30
30
  storeDurablesDetailed
31
- } from "./chunk-LDJN7CVU.js";
31
+ } from "./chunk-U74RE3L7.js";
32
32
  import {
33
33
  containsAgenrMemoryContext,
34
34
  createSessionStartRepository,
@@ -768,6 +768,17 @@ function buildSessionEndSourceRef(source) {
768
768
  return `${SESSION_END_SOURCE_REF_PREFIX}${source.trim()}`;
769
769
  }
770
770
 
771
+ // src/adapters/shared/light-dream-trigger-deps.ts
772
+ function buildLightDreamTriggerDeps(services) {
773
+ return {
774
+ port: services.dreaming,
775
+ dbPath: services.config.dbPath,
776
+ config: services.agenrConfig,
777
+ embedding: services.embedding,
778
+ ...services.claimExtraction ? { createClaimExtractionLlm: () => services.claimExtraction.llm } : {}
779
+ };
780
+ }
781
+
771
782
  // src/app/dreaming/background-triggers.ts
772
783
  var MINUTE_MS = 60 * 1e3;
773
784
  async function maybeRunLightDream(input, deps) {
@@ -852,6 +863,36 @@ function hasEvidence(scan) {
852
863
  return scan.episodesSinceLastRun > 0 || scan.ingestFilesSinceLastRun > 0 || scan.durablesCreatedSinceLastRun > 0;
853
864
  }
854
865
 
866
+ // src/adapters/shared/post-session-light-dream.ts
867
+ async function runPostSessionLightDream(params) {
868
+ const contextSuffix = params.sessionContext ? ` for ${params.sessionContext}` : "";
869
+ try {
870
+ const result = await maybeRunLightDream({ trigger: "post_session" }, params.deps);
871
+ if (result.status === "ran") {
872
+ params.logger.info(`[agenr] ${params.scope} light dream completed${contextSuffix} run=${result.result.runId}`);
873
+ return;
874
+ }
875
+ if (result.reason === "run_in_progress" || result.reason === "episode_write_in_progress") {
876
+ params.logger.info(`[agenr] ${params.scope} light dream skipped${contextSuffix} reason=${result.reason}`);
877
+ return;
878
+ }
879
+ params.logger.debug?.(`[agenr] ${params.scope} light dream skipped${contextSuffix} reason=${result.reason}`);
880
+ } catch (error) {
881
+ params.logger.warn(`[agenr] ${params.scope} light dream failed${contextSuffix}: ${formatErrorMessage(error)}`);
882
+ }
883
+ }
884
+
885
+ // src/adapters/shared/guarded-post-session-episode-capture.ts
886
+ async function runGuardedPostSessionEpisodeCapture(params) {
887
+ await withEpisodeWriteGuard({ port: params.services.dreaming, dbPath: params.services.config.dbPath }, params.writeEpisode);
888
+ await runPostSessionLightDream({
889
+ deps: buildLightDreamTriggerDeps(params.services),
890
+ logger: params.logger,
891
+ scope: params.scope,
892
+ sessionContext: params.sessionContext
893
+ });
894
+ }
895
+
855
896
  // src/adapters/plugin-runtime/claim-extraction.ts
856
897
  async function buildClaimExtractionRuntime(config, resolveLlm) {
857
898
  const claimExtractionConfig = resolveClaimExtractionConfig(config);
@@ -2042,6 +2083,12 @@ async function createHostMemoryServices(featureFlags, options = {}) {
2042
2083
  };
2043
2084
  }
2044
2085
 
2086
+ // src/adapters/shared/shutdown-episode-threshold.ts
2087
+ var HOST_SHUTDOWN_EPISODE_ACTIVITY_THRESHOLD = {
2088
+ minMaterialTurns: 8,
2089
+ minDurationMs: 20 * 60 * 1e3
2090
+ };
2091
+
2045
2092
  // src/adapters/shared/bounded-episode-embedding.ts
2046
2093
  var EPISODE_EMBEDDING_RACE_TIMEOUT = /* @__PURE__ */ Symbol("episode-embedding-race-timeout");
2047
2094
  var EPISODE_EMBEDDING_MIN_HEADROOM_MS = 5e3;
@@ -2982,6 +3029,7 @@ export {
2982
3029
  isPluginEpisodeWriteEnabled,
2983
3030
  resolveAgenrFeatureFlags,
2984
3031
  resolveCompactionPromptContext,
3032
+ HOST_SHUTDOWN_EPISODE_ACTIVITY_THRESHOLD,
2985
3033
  embedEpisodeSummaryWithinBudget,
2986
3034
  EPISODE_SUMMARY_TIMEOUT_MS,
2987
3035
  writeBoundedSingleTranscriptEpisode,
@@ -2989,7 +3037,9 @@ export {
2989
3037
  buildSessionFileSourceRef,
2990
3038
  buildCompactionSourceRef,
2991
3039
  buildSessionEndSourceRef,
3040
+ buildLightDreamTriggerDeps,
2992
3041
  maybeRunLightDream,
3042
+ runGuardedPostSessionEpisodeCapture,
2993
3043
  buildClaimExtractionRuntime,
2994
3044
  createClaimExtractionFromAgenrConfig,
2995
3045
  createEmbedQuery,
@@ -343,64 +343,6 @@ function sanitizeFetchToolParams(params) {
343
343
  };
344
344
  }
345
345
 
346
- // src/app/episode-ingest/activity-threshold.ts
347
- function resolveEpisodeActivityEligibility(materialTurns, startedAt, endedAt, threshold) {
348
- const durationMs = resolveTranscriptDurationMs(startedAt, endedAt);
349
- if (materialTurns >= threshold.minMaterialTurns || durationMs >= threshold.minDurationMs) {
350
- return {
351
- eligible: true,
352
- materialTurns,
353
- durationMs
354
- };
355
- }
356
- return {
357
- eligible: false,
358
- reason: "below_activity_threshold",
359
- materialTurns,
360
- durationMs
361
- };
362
- }
363
- function resolveTranscriptDurationMs(startedAt, endedAt) {
364
- if (!startedAt || !endedAt) {
365
- return 0;
366
- }
367
- const started = Date.parse(startedAt);
368
- const ended = Date.parse(endedAt);
369
- return Number.isFinite(started) && Number.isFinite(ended) && ended > started ? ended - started : 0;
370
- }
371
-
372
- // src/core/episode/transcript-render.ts
373
- var MIN_EPISODE_MESSAGES = 4;
374
- var MAX_EPISODE_TRANSCRIPT_CHARS = 14e3;
375
- function countMaterialTranscriptTurns(messages) {
376
- return messages.filter((message) => message.text.trim().length > 0).length;
377
- }
378
- function renderTranscript(messages) {
379
- return messages.map((message) => `${message.role === "user" ? "User" : "Assistant"}: ${message.text.trim()}`).join("\n");
380
- }
381
- function capEpisodeTranscript(transcript, maxChars) {
382
- if (transcript.length <= maxChars) {
383
- return transcript;
384
- }
385
- const omissionMarker = "\n\n[Earlier middle transcript omitted for brevity]\n\n";
386
- const headBudget = Math.max(0, Math.floor((maxChars - omissionMarker.length) * 0.35));
387
- const tailBudget = Math.max(0, maxChars - omissionMarker.length - headBudget);
388
- const head = trimToBoundary(transcript.slice(0, headBudget), false);
389
- const tail = trimToBoundary(transcript.slice(-tailBudget), true);
390
- return `${head}${omissionMarker}${tail}`.trim();
391
- }
392
- function trimToBoundary(value, fromStart) {
393
- if (value.length === 0) {
394
- return value;
395
- }
396
- if (fromStart) {
397
- const boundary = value.search(/\s/u);
398
- return boundary >= 0 ? value.slice(boundary).trimStart() : value.trim();
399
- }
400
- const reversedBoundary = value.trimEnd().search(/\s\S*$/u);
401
- return reversedBoundary >= 0 ? value.slice(0, reversedBoundary).trimEnd() : value.trim();
402
- }
403
-
404
346
  // src/app/episode-ingest/single-transcript.ts
405
347
  function createSingleTranscriptDiscoveryPort(filePath) {
406
348
  return {
@@ -693,6 +635,66 @@ async function generateEpisodeSummary(transcript, llm) {
693
635
 
694
636
  // src/app/episode-ingest/service/preflight.ts
695
637
  import path from "path";
638
+
639
+ // src/app/episode-ingest/activity-threshold.ts
640
+ function resolveEpisodeActivityEligibility(materialTurns, startedAt, endedAt, threshold) {
641
+ const durationMs = resolveTranscriptDurationMs(startedAt, endedAt);
642
+ if (materialTurns >= threshold.minMaterialTurns || durationMs >= threshold.minDurationMs) {
643
+ return {
644
+ eligible: true,
645
+ materialTurns,
646
+ durationMs
647
+ };
648
+ }
649
+ return {
650
+ eligible: false,
651
+ reason: "below_activity_threshold",
652
+ materialTurns,
653
+ durationMs
654
+ };
655
+ }
656
+ function resolveTranscriptDurationMs(startedAt, endedAt) {
657
+ if (!startedAt || !endedAt) {
658
+ return 0;
659
+ }
660
+ const started = Date.parse(startedAt);
661
+ const ended = Date.parse(endedAt);
662
+ return Number.isFinite(started) && Number.isFinite(ended) && ended > started ? ended - started : 0;
663
+ }
664
+
665
+ // src/core/episode/transcript-render.ts
666
+ var MIN_EPISODE_MESSAGES = 4;
667
+ var MAX_EPISODE_TRANSCRIPT_CHARS = 14e3;
668
+ function countMaterialTranscriptTurns(messages) {
669
+ return messages.filter((message) => message.text.trim().length > 0).length;
670
+ }
671
+ function renderTranscript(messages) {
672
+ return messages.map((message) => `${message.role === "user" ? "User" : "Assistant"}: ${message.text.trim()}`).join("\n");
673
+ }
674
+ function capEpisodeTranscript(transcript, maxChars) {
675
+ if (transcript.length <= maxChars) {
676
+ return transcript;
677
+ }
678
+ const omissionMarker = "\n\n[Earlier middle transcript omitted for brevity]\n\n";
679
+ const headBudget = Math.max(0, Math.floor((maxChars - omissionMarker.length) * 0.35));
680
+ const tailBudget = Math.max(0, maxChars - omissionMarker.length - headBudget);
681
+ const head = trimToBoundary(transcript.slice(0, headBudget), false);
682
+ const tail = trimToBoundary(transcript.slice(-tailBudget), true);
683
+ return `${head}${omissionMarker}${tail}`.trim();
684
+ }
685
+ function trimToBoundary(value, fromStart) {
686
+ if (value.length === 0) {
687
+ return value;
688
+ }
689
+ if (fromStart) {
690
+ const boundary = value.search(/\s/u);
691
+ return boundary >= 0 ? value.slice(boundary).trimStart() : value.trim();
692
+ }
693
+ const reversedBoundary = value.trimEnd().search(/\s\S*$/u);
694
+ return reversedBoundary >= 0 ? value.slice(0, reversedBoundary).trimEnd() : value.trim();
695
+ }
696
+
697
+ // src/app/episode-ingest/service/preflight.ts
696
698
  var ACTIVE_SESSION_WINDOW_MS = 5 * 60 * 1e3;
697
699
  async function prepareEpisodeIngest(targetPath, ports, options = {}) {
698
700
  const files = await ports.files.discoverFiles(targetPath);
package/dist/index.js CHANGED
@@ -6,10 +6,12 @@ import {
6
6
  import {
7
7
  EPISODE_SUMMARY_TIMEOUT_MS,
8
8
  FETCH_TOOL_PARAMETERS,
9
+ HOST_SHUTDOWN_EPISODE_ACTIVITY_THRESHOLD,
9
10
  RECALL_TOOL_PARAMETERS,
10
11
  STORE_TOOL_PARAMETERS,
11
12
  UPDATE_TOOL_PARAMETERS,
12
13
  buildCompactionSourceRef,
14
+ buildLightDreamTriggerDeps,
13
15
  buildRecallToolServices,
14
16
  buildSessionFileSourceRef,
15
17
  composeHostPluginServices,
@@ -42,12 +44,13 @@ import {
42
44
  resolveWorkingContextGate,
43
45
  routeSessionMemoryTriggerSafely,
44
46
  runFetchMemoryTool,
47
+ runGuardedPostSessionEpisodeCapture,
45
48
  runRecallMemoryTool,
46
49
  runStoreMemoryTool,
47
50
  runUpdateMemoryTool,
48
51
  scheduleGuardedEpisodeWrite,
49
52
  writeBoundedSingleTranscriptEpisode
50
- } from "./chunk-NBS62ES5.js";
53
+ } from "./chunk-SIY3JA7T.js";
51
54
  import "./chunk-OJSIZDZD.js";
52
55
  import {
53
56
  WORKING_CANDIDATE_PROMOTION_STATUSES,
@@ -68,7 +71,7 @@ import {
68
71
  formatTargetSelector,
69
72
  sanitizeFetchToolParams,
70
73
  sanitizeUpdateToolParams
71
- } from "./chunk-LDJN7CVU.js";
74
+ } from "./chunk-U74RE3L7.js";
72
75
  import {
73
76
  formatAgenrBeforeTurnRecall,
74
77
  runBeforeTurn,
@@ -81,9 +84,7 @@ import {
81
84
  resolveModel
82
85
  } from "./chunk-5TIP2EPP.js";
83
86
  import "./chunk-GAERET5Q.js";
84
- import {
85
- withEpisodeWriteGuard
86
- } from "./chunk-SOQW7356.js";
87
+ import "./chunk-SOQW7356.js";
87
88
  import {
88
89
  isRecord,
89
90
  readOptionalFiniteNumber,
@@ -614,10 +615,6 @@ function resolveSessionFile(context) {
614
615
 
615
616
  // src/adapters/skeln/episode/episode-writer.ts
616
617
  var SKELN_EPISODE_GENERATOR_VERSION = "skeln-episodic-summary-v1";
617
- var SKELN_PHASE4_SHUTDOWN_EPISODE_ACTIVITY_THRESHOLD = {
618
- minMaterialTurns: 8,
619
- minDurationMs: 20 * 60 * 1e3
620
- };
621
618
  async function writeSkelnShutdownEpisode(params) {
622
619
  await writeSkelnBoundedSessionEpisode({
623
620
  target: params.target,
@@ -625,7 +622,7 @@ async function writeSkelnShutdownEpisode(params) {
625
622
  logger: params.logger,
626
623
  actionLabel: "skeln shutdown episode write",
627
624
  genVersion: SKELN_EPISODE_GENERATOR_VERSION,
628
- activityThreshold: SKELN_PHASE4_SHUTDOWN_EPISODE_ACTIVITY_THRESHOLD,
625
+ activityThreshold: HOST_SHUTDOWN_EPISODE_ACTIVITY_THRESHOLD,
629
626
  buildSourceRef: (sessionFile) => sessionFile,
630
627
  logContext: `session=${params.target.sessionId} key=skeln:${params.target.sessionId}`,
631
628
  skipDetails: `session=${params.target.sessionId}`
@@ -1114,7 +1111,7 @@ function buildSkelnSessionShutdownEpisodeWork(params) {
1114
1111
  }
1115
1112
  function scheduleSkelnSessionShutdownEpisodeWrite(params) {
1116
1113
  const work = buildSkelnSessionShutdownEpisodeWork(params);
1117
- if (params.event.reason === "quit" && params.event.deferWork) {
1114
+ if (params.event.deferWork) {
1118
1115
  params.event.deferWork(work);
1119
1116
  return Promise.resolve();
1120
1117
  }
@@ -1140,30 +1137,12 @@ async function writeScopedSkelnShutdownEpisode(servicesPromise, target, logger)
1140
1137
  if (!isPluginEpisodeWriteEnabled(services.skelnConfig.memoryPolicy)) {
1141
1138
  return;
1142
1139
  }
1143
- await withEpisodeWriteGuard({ port: services.dreaming, dbPath: services.config.dbPath }, async () => writeSkelnShutdownEpisode({ target, services, logger }));
1144
- await runSkelnPostSessionLightDream(services, logger);
1145
- }
1146
- async function runSkelnPostSessionLightDream(services, logger) {
1147
- const log = logger ?? console;
1148
- try {
1149
- const result = await maybeRunLightDream(
1150
- { trigger: "post_session" },
1151
- {
1152
- port: services.dreaming,
1153
- dbPath: services.config.dbPath,
1154
- config: services.agenrConfig,
1155
- embedding: services.embedding,
1156
- ...services.claimExtraction ? { createClaimExtractionLlm: () => services.claimExtraction.llm } : {}
1157
- }
1158
- );
1159
- if (result.status === "ran") {
1160
- log.info(`[agenr] skeln shutdown light dream completed run=${result.result.runId}`);
1161
- } else if (result.reason === "run_in_progress" || result.reason === "episode_write_in_progress") {
1162
- log.info(`[agenr] skeln shutdown light dream skipped reason=${result.reason}`);
1163
- }
1164
- } catch (error) {
1165
- log.warn(`[agenr] skeln shutdown light dream failed: ${formatErrorMessage(error)}`);
1166
- }
1140
+ await runGuardedPostSessionEpisodeCapture({
1141
+ services,
1142
+ writeEpisode: () => writeSkelnShutdownEpisode({ target, services, logger }),
1143
+ logger: logger ?? console,
1144
+ scope: "skeln shutdown"
1145
+ });
1167
1146
  }
1168
1147
 
1169
1148
  // src/app/features/capabilities.ts
@@ -1644,16 +1623,7 @@ function triggerSkelnImportanceLightDream(services, status) {
1644
1623
  if (status !== "stored") {
1645
1624
  return;
1646
1625
  }
1647
- void maybeRunLightDream(
1648
- { trigger: "importance" },
1649
- {
1650
- port: services.dreaming,
1651
- dbPath: services.config.dbPath,
1652
- config: services.agenrConfig,
1653
- embedding: services.embedding,
1654
- ...services.claimExtraction ? { createClaimExtractionLlm: () => services.claimExtraction.llm } : {}
1655
- }
1656
- ).then((result) => {
1626
+ void maybeRunLightDream({ trigger: "importance" }, buildLightDreamTriggerDeps(services)).then((result) => {
1657
1627
  if (result.status === "ran") {
1658
1628
  console.info(`[agenr] skeln importance light dream completed run=${result.result.runId}`);
1659
1629
  } else if (result.reason === "run_in_progress" || result.reason === "episode_write_in_progress") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenr/skeln-plugin",
3
- "version": "2026.6.2",
3
+ "version": "2026.6.3",
4
4
  "description": "agenr memory plugin for Skeln",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",