@dsh-cc/memory 0.5.0

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.
Files changed (53) hide show
  1. package/LICENSE +201 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +158 -0
  4. package/README.zh.md +125 -0
  5. package/lib/index.d.ts +75 -0
  6. package/lib/index.d.ts.map +1 -0
  7. package/lib/index.js +91 -0
  8. package/lib/index.js.map +1 -0
  9. package/lib/invariant.d.ts +16 -0
  10. package/lib/invariant.d.ts.map +1 -0
  11. package/lib/invariant.js +22 -0
  12. package/lib/invariant.js.map +1 -0
  13. package/lib/parser.d.ts +30 -0
  14. package/lib/parser.d.ts.map +1 -0
  15. package/lib/parser.js +96 -0
  16. package/lib/parser.js.map +1 -0
  17. package/lib/paths.d.ts +98 -0
  18. package/lib/paths.d.ts.map +1 -0
  19. package/lib/paths.js +236 -0
  20. package/lib/paths.js.map +1 -0
  21. package/lib/recall.d.ts +91 -0
  22. package/lib/recall.d.ts.map +1 -0
  23. package/lib/recall.js +253 -0
  24. package/lib/recall.js.map +1 -0
  25. package/lib/save.d.ts +53 -0
  26. package/lib/save.d.ts.map +1 -0
  27. package/lib/save.js +180 -0
  28. package/lib/save.js.map +1 -0
  29. package/lib/scan.d.ts +29 -0
  30. package/lib/scan.d.ts.map +1 -0
  31. package/lib/scan.js +70 -0
  32. package/lib/scan.js.map +1 -0
  33. package/lib/section.d.ts +129 -0
  34. package/lib/section.d.ts.map +1 -0
  35. package/lib/section.js +353 -0
  36. package/lib/section.js.map +1 -0
  37. package/lib/team.d.ts +90 -0
  38. package/lib/team.d.ts.map +1 -0
  39. package/lib/team.js +167 -0
  40. package/lib/team.js.map +1 -0
  41. package/lib/truncate.d.ts +35 -0
  42. package/lib/truncate.d.ts.map +1 -0
  43. package/lib/truncate.js +52 -0
  44. package/lib/truncate.js.map +1 -0
  45. package/lib/types.d.ts +34 -0
  46. package/lib/types.d.ts.map +1 -0
  47. package/lib/types.js +18 -0
  48. package/lib/types.js.map +1 -0
  49. package/lib/writeback.d.ts +85 -0
  50. package/lib/writeback.d.ts.map +1 -0
  51. package/lib/writeback.js +121 -0
  52. package/lib/writeback.js.map +1 -0
  53. package/package.json +65 -0
package/lib/scan.js ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Directory scan over a memdir through the optional `ctx.fs` seam: list topic
3
+ * files, parse their frontmatter, and read the always-loaded entrypoint. Used
4
+ * by the system-prompt section index and by recall.
5
+ * @module @dsh-cc/memory/scan
6
+ */
7
+ import { parseMemoryFile } from "./parser.js";
8
+ import { ENTRYPOINT_NAME } from "./truncate.js";
9
+ /**
10
+ * Scan a memory directory for its entrypoint and topic files.
11
+ * A missing directory or entrypoint is not an error — the caller renders an
12
+ * empty section. Files are read with the caller's cancellation signal; the
13
+ * result contains only topics whose frontmatter parsed successfully.
14
+ * @param fs - the contiguous filesystem seam.
15
+ * @param dir - the memory directory to scan.
16
+ * @param signal - optional cancellation for the underlying fs reads.
17
+ * @returns the observed directory state, never throwing for absent files.
18
+ */
19
+ export async function scanMemoryDirectory(fs, dir, signal) {
20
+ const topics = [];
21
+ let entrypoint;
22
+ let entries;
23
+ try {
24
+ const target = signal !== undefined
25
+ ? await fs.resolve(dir, { signal })
26
+ : await fs.resolve(dir);
27
+ entries = await fs.listDir(target, signal);
28
+ }
29
+ catch {
30
+ // Missing or unreadable memory directory: treat as empty.
31
+ return { dir, entrypoint: undefined, topics };
32
+ }
33
+ for (const entry of entries) {
34
+ if (entry.type !== 'file')
35
+ continue;
36
+ if (entry.name === ENTRYPOINT_NAME) {
37
+ entrypoint = await readOptionalText(fs, entry.target, signal);
38
+ continue;
39
+ }
40
+ if (!entry.name.endsWith('.md'))
41
+ continue;
42
+ const raw = await readOptionalText(fs, entry.target, signal);
43
+ if (raw === undefined)
44
+ continue;
45
+ const parsed = parseMemoryFile(raw);
46
+ if (parsed === undefined)
47
+ continue;
48
+ topics.push({ path: entry.target.displayPath, filename: entry.name, frontmatter: parsed.frontmatter });
49
+ }
50
+ topics.sort((a, b) => a.filename.localeCompare(b.filename));
51
+ return { dir, entrypoint, topics };
52
+ }
53
+ async function readOptionalText(fs, target, signal) {
54
+ try {
55
+ return await fs.readText(target, signal);
56
+ }
57
+ catch (error) {
58
+ if (isNotFound(error))
59
+ return undefined;
60
+ throw error;
61
+ }
62
+ }
63
+ function isNotFound(error) {
64
+ return typeof error === 'object' && error !== null
65
+ && 'code' in error
66
+ && (error.code === 'FS_NOT_FOUND'
67
+ || error.code === 'FS_NOT_DIRECTORY'
68
+ || error.code === 'ENOENT');
69
+ }
70
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAa/C;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,EAAc,EACd,GAAW,EACX,MAAoB;IAEpB,MAAM,MAAM,GAAuB,EAAE,CAAA;IACrC,IAAI,UAA8B,CAAA;IAClC,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,KAAK,SAAS;YACjC,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC;YACnC,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACzB,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;QAC1D,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;IAC/C,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,SAAQ;QACnC,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACnC,UAAU,GAAG,MAAM,gBAAgB,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAC7D,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,SAAQ;QACzC,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC5D,IAAI,GAAG,KAAK,SAAS;YAAE,SAAQ;QAC/B,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,MAAM,KAAK,SAAS;YAAE,SAAQ;QAClC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAA;IACxG,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC3D,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,CAAA;AACpC,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,EAAc,EACd,MAAgB,EAChB,MAAoB;IAEpB,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,SAAS,CAAA;QACvC,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;WAC7C,MAAM,IAAI,KAAK;WACf,CAAE,KAAiB,CAAC,IAAI,KAAK,cAAc;eACxC,KAAiB,CAAC,IAAI,KAAK,kBAAkB;eAC7C,KAA2B,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAA;AACxD,CAAC"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * The `memory` system-prompt section: save-channel guidance plus one layer
3
+ * per memory scope — the workspace-private directory, the global directory,
4
+ * and (when `teamEnabled`) the workspace's team directory. Plugins mount once
5
+ * on the root context, so a single global section serves every agent: the
6
+ * text callback receives the assembling agent through `AssembleContext.scope`
7
+ * (the agent loop passes `scope: agent`) and renders that agent's workspace
8
+ * layer. Delegated children (`delegationDepth > 0`) render an empty string so
9
+ * the section drops out of the child prompt. Directory scans run in the
10
+ * background through `ctx.fs`; rendered per-layer fragments are cached and
11
+ * `system-prompt/change` fires only when a fragment actually changed. The
12
+ * section always renders for a top-level agent (a memoryless layer shows a
13
+ * placeholder) so the save guidance never disappears.
14
+ * @module @dsh-cc/memory/section
15
+ */
16
+ import type { Context } from '@deepseek-ai/cordis';
17
+ import type { Agent } from '@deepseek-ai/dsh-agent';
18
+ import type { MemoryDirectoryState } from './scan.ts';
19
+ /** Default order slot for the memory section (before tool guidance). */
20
+ export declare const MEMORY_SECTION_ORDER = 90;
21
+ /** The section's unique name. */
22
+ export declare const MEMORY_SECTION_NAME = "memory";
23
+ /** A memory layer surfaced in the section. */
24
+ export interface MemoryLayer {
25
+ /** Scope tag shown in the combined index. */
26
+ scope: 'workspace' | 'global' | 'team';
27
+ /** Heading label for the layer's entrypoint block. */
28
+ label: string;
29
+ /** The layer's directory. */
30
+ dir: string;
31
+ /** The last scanned state, or `undefined` while the first scan is pending. */
32
+ state: MemoryDirectoryState | undefined;
33
+ }
34
+ /**
35
+ * Owner of the cached `memory` section text. Holds one scanned state per
36
+ * memory directory so the synchronous section provider can compose the text,
37
+ * and refreshes states from disk.
38
+ */
39
+ export declare class MemorySection {
40
+ private readonly ctx;
41
+ private readonly home;
42
+ private readonly states;
43
+ private readonly fragments;
44
+ private readonly refreshers;
45
+ private readonly teamEnabled;
46
+ /**
47
+ * Create a cache holder bounded to a memory home.
48
+ * @param ctx - the host context whose `fs` seam and `system-prompt/change`
49
+ * channel drive refresh.
50
+ * @param home - the memory home: the global layer's directory, and the root
51
+ * under which each workspace's private directory lives (`projects/<slug>`).
52
+ * @param options - when `teamEnabled` is set, each workspace also surfaces
53
+ * its shared team directory (`<workspaceDir>/team`).
54
+ */
55
+ constructor(ctx: Context, home: string, options?: {
56
+ teamEnabled?: boolean;
57
+ });
58
+ /** Register the `memory` section, its assemble-waterfall reconciliation,
59
+ * and start the global layer's first scan.
60
+ *
61
+ * The waterfall listener removes the first-assembly placeholder jitter:
62
+ * `systemPrompt.assemble()` runs BEFORE the agent pre-step, so the section
63
+ * text callback cannot await the directory scans — but the waterfall can.
64
+ * After the base assembly, a scope with unscanned layers joins the
65
+ * in-flight `refresh(agent)` (bounded by {@linkcode READINESS_BUDGET_MS};
66
+ * per-directory refreshers self-deduplicate, so this is the same promise
67
+ * the background scan already started) and re-renders the section with the
68
+ * same render function the section callback uses, so the first assembly
69
+ * already carries the scanned text and no later request sees a different
70
+ * prefix. Timeout or failure keeps the placeholder; the scan lands on a
71
+ * later assembly through `system-prompt/change`. */
72
+ start(): void;
73
+ /**
74
+ * The layers an agent's section renders: its workspace directory plus the
75
+ * global directory, and the workspace's team directory when enabled.
76
+ */
77
+ private layersFor;
78
+ /** Compose the section text for the agent behind an assemble scope. */
79
+ private render;
80
+ /**
81
+ * Re-scan the global directory plus the agent's workspace (and team)
82
+ * directories. Overlapping scans of one directory share a single background
83
+ * promise. Emits `system-prompt/change` only when a rendered fragment
84
+ * actually changed, so an unchanged disk does not churn reassembly.
85
+ * @param agent - whose workspace layers to refresh; omitted = global only.
86
+ */
87
+ refresh(agent?: Agent): Promise<void>;
88
+ private refreshDir;
89
+ private scanDir;
90
+ }
91
+ /**
92
+ * The save-channel guidance every memory section carries. It names the ONLY
93
+ * working save path: direct write/edit calls aimed at a memory directory are
94
+ * fenced by the fs sandbox (memory directories live outside every session
95
+ * workspace), so the model must call `memory_save` instead. Without this line
96
+ * a memoryless session presents no guidance at all and the model falls back
97
+ * to its Claude Code prior (`~/.claude/projects/<slug>/memory/`), whose
98
+ * writes fail the same fence.
99
+ * @param workspaceDir - the workspace memory directory, when known.
100
+ * @param globalDir - the global memory directory.
101
+ * @returns the guidance lines.
102
+ */
103
+ export declare function saveGuidance(workspaceDir: string | undefined, globalDir: string): string[];
104
+ /**
105
+ * Render the memory section from the observed layers (workspace + global).
106
+ * The section is ALWAYS present (even with no memories) so the save guidance
107
+ * is stable model-visible context; an unscanned or empty layer renders a
108
+ * placeholder entrypoint body.
109
+ * @param globalDir - the global memory directory.
110
+ * @param workspaceDir - this workspace's private memory directory.
111
+ * @param globalState - the scanned global state, if available.
112
+ * @param workspaceState - the scanned workspace state, if available.
113
+ * @returns the rendered section.
114
+ */
115
+ export declare function renderMemorySection(globalDir: string, workspaceDir: string, globalState?: MemoryDirectoryState, workspaceState?: MemoryDirectoryState): string;
116
+ /**
117
+ * Render the combined section with the workspace's team layer added.
118
+ * @param globalDir - the global memory directory.
119
+ * @param workspaceDir - this workspace's private memory directory.
120
+ * @param teamDir - this workspace's shared team directory.
121
+ * @param globalState - the scanned global state, if available.
122
+ * @param workspaceState - the scanned workspace state, if available.
123
+ * @param teamState - the scanned team state, if available.
124
+ * @returns the rendered section.
125
+ */
126
+ export declare function renderTeamMemorySection(globalDir: string, workspaceDir: string, teamDir: string, globalState?: MemoryDirectoryState, workspaceState?: MemoryDirectoryState, teamState?: MemoryDirectoryState): string;
127
+ /** Compose the full section text from the observed layers. */
128
+ export declare function renderLayers(layers: readonly MemoryLayer[]): string;
129
+ //# sourceMappingURL=section.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"section.d.ts","sourceRoot":"","sources":["../src/section.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAInD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAIrD,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC,iCAAiC;AACjC,eAAO,MAAM,mBAAmB,WAAW,CAAA;AAwB3C,8CAA8C;AAC9C,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,KAAK,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAA;IACtC,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,8EAA8E;IAC9E,KAAK,EAAE,oBAAoB,GAAG,SAAS,CAAA;CACxC;AAcD;;;;GAIG;AACH,qBAAa,aAAa;IAgBtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAhBvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;IACtD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAErC;;;;;;;;OAQG;gBAEgB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,EAC7B,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAO;IAKzC;;;;;;;;;;;;;wDAaoD;IACpD,KAAK,IAAI,IAAI;IA8Bb;;;OAGG;IACH,OAAO,CAAC,SAAS;IA6BjB,uEAAuE;IACvE,OAAO,CAAC,MAAM;IAgBd;;;;;;OAMG;IACG,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3C,OAAO,CAAC,UAAU;YAcJ,OAAO;CAatB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAU1F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,WAAW,CAAC,EAAE,oBAAoB,EAClC,cAAc,CAAC,EAAE,oBAAoB,GACpC,MAAM,CAKR;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,oBAAoB,EAClC,cAAc,CAAC,EAAE,oBAAoB,EACrC,SAAS,CAAC,EAAE,oBAAoB,GAC/B,MAAM,CAMR;AAWD,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CA+BnE"}
package/lib/section.js ADDED
@@ -0,0 +1,353 @@
1
+ /**
2
+ * The `memory` system-prompt section: save-channel guidance plus one layer
3
+ * per memory scope — the workspace-private directory, the global directory,
4
+ * and (when `teamEnabled`) the workspace's team directory. Plugins mount once
5
+ * on the root context, so a single global section serves every agent: the
6
+ * text callback receives the assembling agent through `AssembleContext.scope`
7
+ * (the agent loop passes `scope: agent`) and renders that agent's workspace
8
+ * layer. Delegated children (`delegationDepth > 0`) render an empty string so
9
+ * the section drops out of the child prompt. Directory scans run in the
10
+ * background through `ctx.fs`; rendered per-layer fragments are cached and
11
+ * `system-prompt/change` fires only when a fragment actually changed. The
12
+ * section always renders for a top-level agent (a memoryless layer shows a
13
+ * placeholder) so the save guidance never disappears.
14
+ * @module @dsh-cc/memory/section
15
+ */
16
+ import { delegationDepthOf } from '@deepseek-ai/dsh-subagent';
17
+ import { ENTRYPOINT_NAME, truncateEntrypointContent } from "./truncate.js";
18
+ import { scanMemoryDirectory } from "./scan.js";
19
+ import { cwdOf, resolveWorkspaceMemoryDir } from "./paths.js";
20
+ import { resolveTeamMemoryRoot } from "./team.js";
21
+ /** Default order slot for the memory section (before tool guidance). */
22
+ export const MEMORY_SECTION_ORDER = 90;
23
+ /** The section's unique name. */
24
+ export const MEMORY_SECTION_NAME = 'memory';
25
+ /**
26
+ * How long the assemble waterfall may wait for a workspace's in-flight first
27
+ * scan before giving up and shipping the placeholder. Bounded so a slow or
28
+ * wedged scan delays the first request by at most this much; the background
29
+ * `system-prompt/change` path remains the fallback.
30
+ */
31
+ const READINESS_BUDGET_MS = 500;
32
+ /**
33
+ * Join `promise`, but reject after `ms` milliseconds either way. The loser
34
+ * keeps running in the background (its eventual rejection is contained); the
35
+ * caller gets a rejection to degrade on.
36
+ */
37
+ function withinBudget(promise, ms) {
38
+ let timer;
39
+ const budget = new Promise((_resolve, reject) => {
40
+ timer = setTimeout(() => reject(new Error(`readiness budget of ${ms}ms expired`)), ms);
41
+ });
42
+ budget.catch(() => { });
43
+ return Promise.race([promise, budget]).finally(() => clearTimeout(timer));
44
+ }
45
+ /**
46
+ * Extract the assembling agent from an `AssembleContext`. The agent loop
47
+ * assembles with `scope: agent` (a runtime contract; `ScopeKey` is opaque),
48
+ * so the scope IS the agent whenever a session drives the assembly.
49
+ */
50
+ function agentFromScope(scope) {
51
+ if (typeof scope === 'object' && scope !== null && 'session' in scope) {
52
+ return scope;
53
+ }
54
+ return undefined;
55
+ }
56
+ /**
57
+ * Owner of the cached `memory` section text. Holds one scanned state per
58
+ * memory directory so the synchronous section provider can compose the text,
59
+ * and refreshes states from disk.
60
+ */
61
+ export class MemorySection {
62
+ ctx;
63
+ home;
64
+ states = new Map();
65
+ fragments = new Map();
66
+ refreshers = new Map();
67
+ teamEnabled;
68
+ /**
69
+ * Create a cache holder bounded to a memory home.
70
+ * @param ctx - the host context whose `fs` seam and `system-prompt/change`
71
+ * channel drive refresh.
72
+ * @param home - the memory home: the global layer's directory, and the root
73
+ * under which each workspace's private directory lives (`projects/<slug>`).
74
+ * @param options - when `teamEnabled` is set, each workspace also surfaces
75
+ * its shared team directory (`<workspaceDir>/team`).
76
+ */
77
+ constructor(ctx, home, options = {}) {
78
+ this.ctx = ctx;
79
+ this.home = home;
80
+ this.teamEnabled = options.teamEnabled ?? false;
81
+ }
82
+ /** Register the `memory` section, its assemble-waterfall reconciliation,
83
+ * and start the global layer's first scan.
84
+ *
85
+ * The waterfall listener removes the first-assembly placeholder jitter:
86
+ * `systemPrompt.assemble()` runs BEFORE the agent pre-step, so the section
87
+ * text callback cannot await the directory scans — but the waterfall can.
88
+ * After the base assembly, a scope with unscanned layers joins the
89
+ * in-flight `refresh(agent)` (bounded by {@linkcode READINESS_BUDGET_MS};
90
+ * per-directory refreshers self-deduplicate, so this is the same promise
91
+ * the background scan already started) and re-renders the section with the
92
+ * same render function the section callback uses, so the first assembly
93
+ * already carries the scanned text and no later request sees a different
94
+ * prefix. Timeout or failure keeps the placeholder; the scan lands on a
95
+ * later assembly through `system-prompt/change`. */
96
+ start() {
97
+ this.ctx.systemPrompt.section({
98
+ name: MEMORY_SECTION_NAME,
99
+ order: MEMORY_SECTION_ORDER,
100
+ text: (context) => this.render(context.scope),
101
+ });
102
+ this.ctx.on('system-prompt/assemble', async (_assembly, context, next) => {
103
+ const result = await next();
104
+ const agent = agentFromScope(context.scope);
105
+ if (agent === undefined)
106
+ return result;
107
+ if (!isTopLevel(agent))
108
+ return result;
109
+ if (!this.layersFor(agent).some(layer => layer.state === undefined))
110
+ return result;
111
+ try {
112
+ await withinBudget(this.refresh(agent), READINESS_BUDGET_MS);
113
+ }
114
+ catch (error) {
115
+ this.ctx.logger.warn(`memory: first-assembly scan did not land within ${READINESS_BUDGET_MS}ms: ${String(error)}; keeping the placeholder`);
116
+ return result;
117
+ }
118
+ return {
119
+ ...result,
120
+ sections: result.sections.map(section => section.name === MEMORY_SECTION_NAME
121
+ ? { ...section, text: this.render(agent) }
122
+ : section),
123
+ };
124
+ });
125
+ void this.refresh();
126
+ }
127
+ /**
128
+ * The layers an agent's section renders: its workspace directory plus the
129
+ * global directory, and the workspace's team directory when enabled.
130
+ */
131
+ layersFor(agent) {
132
+ const layers = [];
133
+ if (agent !== undefined) {
134
+ const workspaceDir = resolveWorkspaceMemoryDir(this.home, cwdOf(agent));
135
+ layers.push({
136
+ scope: 'workspace',
137
+ label: 'this workspace',
138
+ dir: workspaceDir,
139
+ state: this.states.get(workspaceDir),
140
+ });
141
+ if (this.teamEnabled) {
142
+ const teamDir = resolveTeamMemoryRoot(workspaceDir);
143
+ layers.push({
144
+ scope: 'team',
145
+ label: 'team',
146
+ dir: teamDir,
147
+ state: this.states.get(teamDir),
148
+ });
149
+ }
150
+ }
151
+ layers.push({
152
+ scope: 'global',
153
+ label: 'global',
154
+ dir: this.home,
155
+ state: this.states.get(this.home),
156
+ });
157
+ return layers;
158
+ }
159
+ /** Compose the section text for the agent behind an assemble scope. */
160
+ render(scope) {
161
+ const agent = agentFromScope(scope);
162
+ // Delegated children start fresh (CC Task isolation). The parent prompt
163
+ // must pass any facts the child needs; dumping MEMORY.md into every
164
+ // subagent is the token cost this mute removes. Fail closed: a throw
165
+ // from reading depth treats the agent as a child.
166
+ if (agent !== undefined && !isTopLevel(agent))
167
+ return '';
168
+ if (agent !== undefined) {
169
+ // First assembly for this workspace: render placeholders now and scan
170
+ // its directories in the background so the next step sees real content.
171
+ const unknown = this.layersFor(agent).some(layer => layer.state === undefined);
172
+ if (unknown)
173
+ void this.refresh(agent);
174
+ }
175
+ return renderLayers(this.layersFor(agent));
176
+ }
177
+ /**
178
+ * Re-scan the global directory plus the agent's workspace (and team)
179
+ * directories. Overlapping scans of one directory share a single background
180
+ * promise. Emits `system-prompt/change` only when a rendered fragment
181
+ * actually changed, so an unchanged disk does not churn reassembly.
182
+ * @param agent - whose workspace layers to refresh; omitted = global only.
183
+ */
184
+ async refresh(agent) {
185
+ const dirs = this.layersFor(agent).map(layer => layer.dir);
186
+ const scans = dirs.map(dir => this.refreshDir(dir));
187
+ await Promise.all(scans);
188
+ }
189
+ refreshDir(dir) {
190
+ const previous = this.refreshers.get(dir);
191
+ if (previous !== undefined) {
192
+ previous.catch(() => { });
193
+ return previous;
194
+ }
195
+ const current = this.scanDir(dir);
196
+ this.refreshers.set(dir, current);
197
+ void current.finally(() => {
198
+ if (this.refreshers.get(dir) === current)
199
+ this.refreshers.delete(dir);
200
+ });
201
+ return current;
202
+ }
203
+ async scanDir(dir) {
204
+ const fileSystem = this.ctx.get('fs');
205
+ if (fileSystem === undefined)
206
+ return;
207
+ const state = await scanMemoryDirectory(fileSystem, dir);
208
+ const fragment = renderLayerFragment({ scope: 'global', label: '', dir, state });
209
+ if (fragment === this.fragments.get(dir)) {
210
+ this.states.set(dir, state);
211
+ return;
212
+ }
213
+ this.states.set(dir, state);
214
+ this.fragments.set(dir, fragment);
215
+ this.ctx.emit('system-prompt/change');
216
+ }
217
+ }
218
+ /**
219
+ * The save-channel guidance every memory section carries. It names the ONLY
220
+ * working save path: direct write/edit calls aimed at a memory directory are
221
+ * fenced by the fs sandbox (memory directories live outside every session
222
+ * workspace), so the model must call `memory_save` instead. Without this line
223
+ * a memoryless session presents no guidance at all and the model falls back
224
+ * to its Claude Code prior (`~/.claude/projects/<slug>/memory/`), whose
225
+ * writes fail the same fence.
226
+ * @param workspaceDir - the workspace memory directory, when known.
227
+ * @param globalDir - the global memory directory.
228
+ * @returns the guidance lines.
229
+ */
230
+ export function saveGuidance(workspaceDir, globalDir) {
231
+ const target = workspaceDir !== undefined
232
+ ? `this workspace's directory (\`${workspaceDir}\`)`
233
+ : 'the current workspace\'s directory';
234
+ return [
235
+ `To save a durable fact, call the \`memory_save\` tool — it writes the topic file and updates ${ENTRYPOINT_NAME} for you. `
236
+ + `By default the memory lands in ${target}, visible only to sessions of this workspace; `
237
+ + `pass \`scope: "global"\` for facts useful across ALL workspaces (saved to \`${globalDir}\`).`,
238
+ 'Never write or edit files under a memory directory directly: the sandbox fences writes outside the session workspace, so direct writes always fail.',
239
+ ];
240
+ }
241
+ /**
242
+ * Render the memory section from the observed layers (workspace + global).
243
+ * The section is ALWAYS present (even with no memories) so the save guidance
244
+ * is stable model-visible context; an unscanned or empty layer renders a
245
+ * placeholder entrypoint body.
246
+ * @param globalDir - the global memory directory.
247
+ * @param workspaceDir - this workspace's private memory directory.
248
+ * @param globalState - the scanned global state, if available.
249
+ * @param workspaceState - the scanned workspace state, if available.
250
+ * @returns the rendered section.
251
+ */
252
+ export function renderMemorySection(globalDir, workspaceDir, globalState, workspaceState) {
253
+ return renderLayers([
254
+ { scope: 'workspace', label: 'this workspace', dir: workspaceDir, state: workspaceState },
255
+ { scope: 'global', label: 'global', dir: globalDir, state: globalState },
256
+ ]);
257
+ }
258
+ /**
259
+ * Render the combined section with the workspace's team layer added.
260
+ * @param globalDir - the global memory directory.
261
+ * @param workspaceDir - this workspace's private memory directory.
262
+ * @param teamDir - this workspace's shared team directory.
263
+ * @param globalState - the scanned global state, if available.
264
+ * @param workspaceState - the scanned workspace state, if available.
265
+ * @param teamState - the scanned team state, if available.
266
+ * @returns the rendered section.
267
+ */
268
+ export function renderTeamMemorySection(globalDir, workspaceDir, teamDir, globalState, workspaceState, teamState) {
269
+ return renderLayers([
270
+ { scope: 'workspace', label: 'this workspace', dir: workspaceDir, state: workspaceState },
271
+ { scope: 'team', label: 'team', dir: teamDir, state: teamState },
272
+ { scope: 'global', label: 'global', dir: globalDir, state: globalState },
273
+ ]);
274
+ }
275
+ /** Render one layer's entrypoint block (heading + truncated body). */
276
+ function renderLayerFragment(layer) {
277
+ const entry = layer.state?.entrypoint?.trim();
278
+ const body = entry !== undefined && entry.length > 0
279
+ ? truncateEntrypointContent(entry).content
280
+ : '(no memories yet)';
281
+ return `## ${ENTRYPOINT_NAME} (${layer.label})\n\n${body}`;
282
+ }
283
+ /** Compose the full section text from the observed layers. */
284
+ export function renderLayers(layers) {
285
+ const workspace = layers.find(layer => layer.scope === 'workspace');
286
+ const global = layers.find(layer => layer.scope === 'global');
287
+ const team = layers.find(layer => layer.scope === 'team');
288
+ const globalDir = global?.dir ?? '';
289
+ const lines = [
290
+ '# Memory',
291
+ '',
292
+ 'You have a persistent, file-based memory system. Use it to recall context across conversations and to save durable facts.',
293
+ '',
294
+ 'There are two scope levels:',
295
+ `- workspace: memories private to the current workspace${workspace !== undefined ? `, stored at \`${workspace.dir}\`` : ''}.`,
296
+ `- global: memories shared by every workspace${global !== undefined ? `, stored at \`${global.dir}\`` : ''}.`,
297
+ ];
298
+ if (team !== undefined) {
299
+ lines.push(`- team: memories shared with and contributed by all users of this project, stored at \`${team.dir}\`.`);
300
+ }
301
+ lines.push('', 'Each directory keeps its own index and topic files. Save each memory to the directory matching its scope; never write memory content directly into a MEMORY.md.', '', ...saveGuidance(workspace?.dir, globalDir), '');
302
+ const ordered = [workspace, team, global].filter((layer) => layer !== undefined);
303
+ lines.push(ordered.map(layer => renderLayerFragment(layer)).join('\n\n'));
304
+ const index = renderCombinedIndex(ordered);
305
+ if (index.length > 0)
306
+ lines.push('', ...index);
307
+ const search = renderSearch(ordered);
308
+ if (search.length > 0)
309
+ lines.push('', ...search);
310
+ return lines.join('\n');
311
+ }
312
+ /** A combined topic index with each layer's scope tagged, sorted by filename. */
313
+ function renderCombinedIndex(layers) {
314
+ const combined = layers.flatMap(layer => (layer.state?.topics ?? []).map(topic => ({ ...topic, scope: layer.scope })));
315
+ if (combined.length === 0)
316
+ return [];
317
+ combined.sort((a, b) => a.filename.localeCompare(b.filename));
318
+ const lines = combined.map((topic) => {
319
+ const type = topic.frontmatter.type === undefined ? '' : ` [${topic.frontmatter.type}]`;
320
+ return `- [${escapeLinkText(topic.frontmatter.name)}](${topic.filename}) — ${topic.frontmatter.description} (${topic.scope})${type}`;
321
+ });
322
+ return ['## Memory index', '', ...lines];
323
+ }
324
+ function renderSearch(layers) {
325
+ const populated = layers.filter(layer => (layer.state?.topics.length ?? 0) > 0);
326
+ if (populated.length === 0)
327
+ return [];
328
+ const dirs = populated.map(layer => `${layer.dir}/`).join(' ');
329
+ return [
330
+ '## Searching past context',
331
+ 'When a MEMORY.md entry is not enough, search topic files and the transcript log with narrow terms (error messages, file paths, function names):',
332
+ '```',
333
+ `grep -rn "<search term>" ${dirs} --include="*.md"`,
334
+ '```',
335
+ ];
336
+ }
337
+ function escapeLinkText(name) {
338
+ return name.replace(/[\\[\]]/g, '\\$&');
339
+ }
340
+ /**
341
+ * Whether an assembling agent is top-level (not a delegated subagent).
342
+ * Fail closed: any throw from reading depth treats the agent as a child so
343
+ * the section never dumps MEMORY.md into a mis-stamped child.
344
+ */
345
+ function isTopLevel(agent) {
346
+ try {
347
+ return delegationDepthOf(agent) === 0;
348
+ }
349
+ catch {
350
+ return false;
351
+ }
352
+ }
353
+ //# sourceMappingURL=section.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"section.js","sourceRoot":"","sources":["../src/section.ts"],"names":[],"mappings":"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"}