@alanzhao/dsh-memory-lite 0.1.1
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/LICENSE +21 -0
- package/README.md +112 -0
- package/cordis.patch.yml +9 -0
- package/lib/catalog.d.ts +35 -0
- package/lib/catalog.js +145 -0
- package/lib/catalog.js.map +1 -0
- package/lib/client.js +631 -0
- package/lib/config.d.ts +133 -0
- package/lib/config.js +173 -0
- package/lib/config.js.map +1 -0
- package/lib/extract/checkpoint.d.ts +60 -0
- package/lib/extract/checkpoint.js +42 -0
- package/lib/extract/checkpoint.js.map +1 -0
- package/lib/extract/decision.d.ts +36 -0
- package/lib/extract/decision.js +118 -0
- package/lib/extract/decision.js.map +1 -0
- package/lib/extract/digest.d.ts +12 -0
- package/lib/extract/digest.js +25 -0
- package/lib/extract/digest.js.map +1 -0
- package/lib/extract/index.d.ts +52 -0
- package/lib/extract/index.js +489 -0
- package/lib/extract/index.js.map +1 -0
- package/lib/extract/prompt.d.ts +20 -0
- package/lib/extract/prompt.js +63 -0
- package/lib/extract/prompt.js.map +1 -0
- package/lib/extract/triggers.d.ts +15 -0
- package/lib/extract/triggers.js +26 -0
- package/lib/extract/triggers.js.map +1 -0
- package/lib/extract/window.d.ts +48 -0
- package/lib/extract/window.js +110 -0
- package/lib/extract/window.js.map +1 -0
- package/lib/index.d.ts +29 -0
- package/lib/index.js +92 -0
- package/lib/index.js.map +1 -0
- package/lib/inject.d.ts +45 -0
- package/lib/inject.js +102 -0
- package/lib/inject.js.map +1 -0
- package/lib/memory-store.d.ts +147 -0
- package/lib/memory-store.js +494 -0
- package/lib/memory-store.js.map +1 -0
- package/lib/path.d.ts +24 -0
- package/lib/path.js +54 -0
- package/lib/path.js.map +1 -0
- package/lib/peer.d.ts +16 -0
- package/lib/peer.js +38 -0
- package/lib/peer.js.map +1 -0
- package/lib/status.d.ts +44 -0
- package/lib/status.js +42 -0
- package/lib/status.js.map +1 -0
- package/lib/tool-utils.d.ts +25 -0
- package/lib/tool-utils.js +16 -0
- package/lib/tool-utils.js.map +1 -0
- package/lib/tools/forget-memory.d.ts +9 -0
- package/lib/tools/forget-memory.js +39 -0
- package/lib/tools/forget-memory.js.map +1 -0
- package/lib/tools/read-memory.d.ts +8 -0
- package/lib/tools/read-memory.js +41 -0
- package/lib/tools/read-memory.js.map +1 -0
- package/lib/tools/remember.d.ts +9 -0
- package/lib/tools/remember.js +65 -0
- package/lib/tools/remember.js.map +1 -0
- package/lib/tools/search-memory.d.ts +8 -0
- package/lib/tools/search-memory.js +49 -0
- package/lib/tools/search-memory.js.map +1 -0
- package/lib/tools/update-memory.d.ts +9 -0
- package/lib/tools/update-memory.js +46 -0
- package/lib/tools/update-memory.js.map +1 -0
- package/lib/types.d.ts +35 -0
- package/lib/types.js +7 -0
- package/lib/types.js.map +1 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-memory-light contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# dsh-memory-lite
|
|
2
|
+
|
|
3
|
+
Lightweight, zero-dependency long-term memory for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness). Memories are plain Markdown files under a configurable root; the plugin injects an L0 memory catalog into each session and exposes five model-facing tools.
|
|
4
|
+
|
|
5
|
+
Design: [《Light Memory for DSH 设计方案》](https://github.com/deepseek-ai/deepseek-harness) v7 (2026-08-25). Implementation spec: [IMPLEMENTATION.md](IMPLEMENTATION.md).
|
|
6
|
+
|
|
7
|
+
> **Status: Phase 1-3 implemented.** Explicit capture (remember / update / forget), L0 catalog injection, search and read (Phase 1); implicit background extraction (Phase 2, window + idle triggers active, turn/flush triggers shipped but off by config); and read-only cross-peer sharing (Phase 3) are built and live-tested. Not yet built: `forget_memory` approval, `## Related` auto-maintenance, CLI/MCP (Phase 4).
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
Install into a profile and add it to that profile's bundle list:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
dsh plugin --profile web add @alanzhao/dsh-memory-lite
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
or, for a local checkout, add a linked dependency and bundle:
|
|
18
|
+
|
|
19
|
+
```jsonc
|
|
20
|
+
// $DSH_HOME/profiles/web/package.json
|
|
21
|
+
{
|
|
22
|
+
"dependencies": { "@alanzhao/dsh-memory-lite": "^0.1.1" },
|
|
23
|
+
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@alanzhao/dsh-memory-lite"] } }
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The bundle inserts the plugin row without configuration; defaults apply immediately.
|
|
28
|
+
|
|
29
|
+
## Configuration
|
|
30
|
+
|
|
31
|
+
All settings are edited in the **settings panel** (Settings → memory-lite). They persist to the harness settings document (`~/.dsh/settings.yaml`, section `dsh-memory-lite:`) and most take effect **immediately** — no restart, no YAML editing. The header indicator and extraction behavior react live.
|
|
32
|
+
|
|
33
|
+
The plugin row in `cordis.patch.yml` carries **no configuration** (mount only); a row config, if present, acts as the deployment base layer under the settings document (settings values win). The full schema, with defaults, lives in [src/config.ts](src/config.ts):
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
- id: memory-lite
|
|
37
|
+
name: @alanzhao/dsh-memory-lite
|
|
38
|
+
# config: # optional deployment defaults; settings override
|
|
39
|
+
# root: '~/.agent-memory'
|
|
40
|
+
# defaultPeer: dsh-web
|
|
41
|
+
# extraction:
|
|
42
|
+
# mode: incremental
|
|
43
|
+
# turnStoppingTrigger: false
|
|
44
|
+
# flushTrigger: false
|
|
45
|
+
# sharing:
|
|
46
|
+
# enabled: true
|
|
47
|
+
# mounts:
|
|
48
|
+
# - name: dsh-test
|
|
49
|
+
# peer: dsh-test-72572e8b
|
|
50
|
+
# subpath: ''
|
|
51
|
+
# readonly: true
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Effect timing:
|
|
55
|
+
|
|
56
|
+
- **Live** (apply on save): `extraction.*`, `index.maxTokens`, `defaultPeer`, `workspacePeers.*`, `ui.headerOrder` (after a refresh for the slot order).
|
|
57
|
+
- **Restart** (persisted, apply on next boot): `root`, `sharing.*` — `MemoryStore` pins them at construction; the panel labels them accordingly.
|
|
58
|
+
|
|
59
|
+
## Tools
|
|
60
|
+
|
|
61
|
+
| Tool | Purpose |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `read_memory` | Read the full text of one memory file (exact path from the catalog). |
|
|
64
|
+
| `search_memory` | Line search across the session peer's memory files. |
|
|
65
|
+
| `remember` | Create or append a memory — call ONLY when the user explicitly asks to remember. |
|
|
66
|
+
| `update_memory` | Replace a memory's current content; the previous content moves to `## History` (ADD-only). |
|
|
67
|
+
| `forget_memory` | Soft-delete a memory into `<root>/.trash/`. |
|
|
68
|
+
|
|
69
|
+
### Memory file layout
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
~/.agent-memory/
|
|
73
|
+
├── peers/{peer}/
|
|
74
|
+
│ ├── memories/
|
|
75
|
+
│ │ ├── _index.md # L0 index (generated; human-editable)
|
|
76
|
+
│ │ ├── preferences/ entities/ events/ experiences/
|
|
77
|
+
│ │ │ └── {slug}.md # L1 full text
|
|
78
|
+
│ └── sessions/ # extraction checkpoint + audit ({session-id}.json) and extraction.log
|
|
79
|
+
└── .trash/ # soft-deleted memories (root/.trash/<date>/)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Each memory file uses `## Current` / `## History` / `## Related` sections; updates archive, never destroy. The four categories are retrieval paths for the model: preferences (always relevant), entities (mentioned knowledge), events (time-related), experiences (task lessons).
|
|
83
|
+
|
|
84
|
+
## How it works
|
|
85
|
+
|
|
86
|
+
- **L0 catalog injection** (`agent/pre-step` waterfall, copied from `@deepseek-ai/dsh-tool-skill`): the peer's `_index.md` is rendered into one durable `user/message` with a typed `memory-catalog` source and re-published when the index changes or compaction moves it off the visible surface. A fresh empty index publishes nothing (unless sharing mounts are enabled — then only the `## shared` hint is published). Subagent sessions get no catalog.
|
|
87
|
+
- **Peer isolation**: each session's cwd derives its peer name (sanitized basename + short hash); cwd-less sessions fall back to `defaultPeer`.
|
|
88
|
+
- **Path safety**: every file access goes through a containment boundary — relative paths only, `..` / absolute / symlink escapes rejected at the executor.
|
|
89
|
+
- **Implicit extraction** (Phase 2): once `windowTurns` (default 20) new surface messages accumulate — or after `idleTimeoutMin` (default 30 min) of idle — a background run feeds the new window to the LLM and applies a create/merge/update/skip decision (dedup against existing memories), then advances a per-session checkpoint and rolling digest. Turn-boundary and flush triggers are shipped but disabled by config (cost); subagent sessions are never extracted. Audit trails live in `peers/{peer}/sessions/`.
|
|
90
|
+
- **Cross-peer sharing** (Phase 3): `sharing.mounts` expose another peer's memories read-only at `shared/<name>/...`; `search_memory` covers shared mounts and results keep the `shared/<name>` prefix. Shared entries stay out of the local catalog.
|
|
91
|
+
- **Concurrent writes**: all mutations run through a serial queue with atomic tmp+rename replacement.
|
|
92
|
+
- **Header status indicator** (browser half, `lib/client.js`): a compact "memory-lite" capsule in the session-header utilities row, left of the built-in "Session log" download button (position via `ui.headerOrder`, editable in the settings panel). The dot polls the `/memory-status` RPC channel every 10s — green (last extraction run ok), red (last run failed or the plugin is unreachable), gray (extraction mode off / explicit_only). No data yet is green.
|
|
93
|
+
|
|
94
|
+
## Model Experience
|
|
95
|
+
|
|
96
|
+
- **Per step**: the 5 tool schemas are injected into every model request (~300–800 tokens).
|
|
97
|
+
- **Per session**: the L0 catalog is one durable surface message (resident; re-sent only after compaction or an index change, capped at `index.maxTokens`, default 1200 — ~1000 tokens with the current memory count, near-zero incremental cost with KV cache).
|
|
98
|
+
- **Per explicit remember**: one tool call; the index rebuild is free (no LLM).
|
|
99
|
+
|
|
100
|
+
## Development
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
npm install # project-local .npm-cache avoids a root-owned npm cache
|
|
104
|
+
npm run build # tsc -> lib/
|
|
105
|
+
npm test # node:test + tsx; includes a real Loader boot smoke
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The Loader boot test (`tests/boot.test.ts`) boots a real `cordis.yml` through the Cordis Loader with the services the plugin needs and asserts all five tools register; it requires `npm run build` first (it loads the built `lib/`).
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# dsh-memory-lite bundle layer.
|
|
2
|
+
#
|
|
3
|
+
# The row is inserted without configuration so a fresh install stays inert
|
|
4
|
+
# (defaults apply): memory root ~/.agent-memory, default peer dsh-web.
|
|
5
|
+
# Override this row (same id) in your profile's cordis.patch.yml with the
|
|
6
|
+
# config documented in README.md.
|
|
7
|
+
- insert:
|
|
8
|
+
- id: memory-lite
|
|
9
|
+
name: @alanzhao/dsh-memory-lite
|
package/lib/catalog.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L0 catalog rendering, digest, and session-history tracking. The pattern is
|
|
3
|
+
* copied from `@deepseek-ai/dsh-tool-skill` (the verified reference).
|
|
4
|
+
* @module dsh-memory-lite/src/catalog
|
|
5
|
+
*/
|
|
6
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
7
|
+
import type { UserMessage } from '@deepseek-ai/dsh-session';
|
|
8
|
+
import type { IndexEntry } from './types.js';
|
|
9
|
+
/** Catalog identity over the entry list (not the prose); stable across renders. */
|
|
10
|
+
export declare function digestIndexEntries(entries: readonly IndexEntry[]): string;
|
|
11
|
+
/** One shared-mount notice rendered into the catalog; not an index entry. */
|
|
12
|
+
export interface SharedMountNotice {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly peer: string;
|
|
15
|
+
readonly readonly: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** The catalog message for this session's first publication. */
|
|
18
|
+
export declare function renderCatalogMessage(entries: readonly IndexEntry[], peer: string, sharedMounts?: readonly SharedMountNotice[]): UserMessage;
|
|
19
|
+
/** The catalog message when the index changed and an older catalog is still visible. */
|
|
20
|
+
export declare function renderCatalogUpdate(entries: readonly IndexEntry[], peer: string, sharedMounts?: readonly SharedMountNotice[]): UserMessage;
|
|
21
|
+
/** Entries of one durable catalog message, or undefined when the record is unusable. */
|
|
22
|
+
export declare function readCatalogEntries(source: unknown): readonly IndexEntry[] | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The latest memory-catalog message this session published and whether its
|
|
25
|
+
* digest is still on the visible surface (compaction may have moved it off).
|
|
26
|
+
*/
|
|
27
|
+
export declare function catalogHistory(agent: Agent): {
|
|
28
|
+
visibleDigest?: string;
|
|
29
|
+
published: boolean;
|
|
30
|
+
};
|
|
31
|
+
/** The memory-catalog message already in the entering batch, if any. */
|
|
32
|
+
export declare function catalogMessage(messages: readonly UserMessage[]): {
|
|
33
|
+
message: UserMessage;
|
|
34
|
+
entries: readonly IndexEntry[];
|
|
35
|
+
} | undefined;
|
package/lib/catalog.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L0 catalog rendering, digest, and session-history tracking. The pattern is
|
|
3
|
+
* copied from `@deepseek-ai/dsh-tool-skill` (the verified reference).
|
|
4
|
+
* @module dsh-memory-lite/src/catalog
|
|
5
|
+
*/
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
7
|
+
import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
8
|
+
/** Catalog identity over the entry list (not the prose); stable across renders. */
|
|
9
|
+
export function digestIndexEntries(entries) {
|
|
10
|
+
const canonical = [...entries]
|
|
11
|
+
.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0))
|
|
12
|
+
.map(entry => JSON.stringify([entry.category, entry.path, entry.summary]))
|
|
13
|
+
.join('\n');
|
|
14
|
+
return createHash('sha256').update(canonical).digest('hex');
|
|
15
|
+
}
|
|
16
|
+
const GUIDANCE = 'You have long-term memory tools (read_memory / search_memory / remember / update_memory / forget_memory). ' +
|
|
17
|
+
'Call remember only when the user explicitly asks to remember something; do not decide on your own. ' +
|
|
18
|
+
'To load the full text of a memory, call read_memory with the exact path from this index.';
|
|
19
|
+
/** The shared-mount section of the catalog (empty when no mounts). */
|
|
20
|
+
function renderSharedMounts(mounts) {
|
|
21
|
+
if (mounts.length === 0)
|
|
22
|
+
return [];
|
|
23
|
+
return [
|
|
24
|
+
'',
|
|
25
|
+
'## shared',
|
|
26
|
+
...mounts.map(mount => `- shared/${mount.name}/: read-only mirror of peer '${mount.peer}'. The full index is not preloaded — find content with search_memory, then read_memory for the full text.`),
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
/** The catalog message for this session's first publication. */
|
|
30
|
+
export function renderCatalogMessage(entries, peer, sharedMounts = []) {
|
|
31
|
+
return createUserMessage({
|
|
32
|
+
content: [{
|
|
33
|
+
type: 'text',
|
|
34
|
+
text: [
|
|
35
|
+
'<system-reminder>',
|
|
36
|
+
`This is your long-term memory index for the ${peer} project. It lists what you have memorized, one line per memory.`,
|
|
37
|
+
'The full text of any memory is NOT loaded until you call read_memory — use the exact path from this index.',
|
|
38
|
+
...renderSections(entries),
|
|
39
|
+
...renderSharedMounts(sharedMounts),
|
|
40
|
+
'',
|
|
41
|
+
GUIDANCE,
|
|
42
|
+
'</system-reminder>',
|
|
43
|
+
].join('\n'),
|
|
44
|
+
}],
|
|
45
|
+
source: { kind: 'memory-catalog', form: 'catalog', entries },
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** The catalog message when the index changed and an older catalog is still visible. */
|
|
49
|
+
export function renderCatalogUpdate(entries, peer, sharedMounts = []) {
|
|
50
|
+
return createUserMessage({
|
|
51
|
+
content: [{
|
|
52
|
+
type: 'text',
|
|
53
|
+
text: [
|
|
54
|
+
'<system-reminder>',
|
|
55
|
+
`The memory catalog for ${peer} changed. This complete catalog replaces every earlier memory catalog in this session:`,
|
|
56
|
+
...renderSections(entries),
|
|
57
|
+
...renderSharedMounts(sharedMounts),
|
|
58
|
+
'',
|
|
59
|
+
GUIDANCE,
|
|
60
|
+
'</system-reminder>',
|
|
61
|
+
].join('\n'),
|
|
62
|
+
}],
|
|
63
|
+
source: { kind: 'memory-catalog', form: 'catalog', update: true, entries },
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/** Entries of one durable catalog message, or undefined when the record is unusable. */
|
|
67
|
+
export function readCatalogEntries(source) {
|
|
68
|
+
const entries = source.entries;
|
|
69
|
+
if (!Array.isArray(entries))
|
|
70
|
+
return undefined;
|
|
71
|
+
const readable = [];
|
|
72
|
+
for (const entry of entries) {
|
|
73
|
+
if (typeof entry !== 'object' || entry === null)
|
|
74
|
+
return undefined;
|
|
75
|
+
const { category, path, summary } = entry;
|
|
76
|
+
if (typeof category !== 'string' || category === '' || typeof path !== 'string' || path === '' || typeof summary !== 'string') {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
readable.push({ category, path, summary });
|
|
80
|
+
}
|
|
81
|
+
return readable;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The latest memory-catalog message this session published and whether its
|
|
85
|
+
* digest is still on the visible surface (compaction may have moved it off).
|
|
86
|
+
*/
|
|
87
|
+
export function catalogHistory(agent) {
|
|
88
|
+
const visible = new Set(agent.session.surface.nodes);
|
|
89
|
+
const events = agent.session.events;
|
|
90
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
91
|
+
// The loop bound proves the read-only event view contains this index.
|
|
92
|
+
const event = events[index];
|
|
93
|
+
if (event.type !== 'user/message')
|
|
94
|
+
continue;
|
|
95
|
+
const source = event.data.source;
|
|
96
|
+
if (typeof source !== 'object' || source === null || source.kind !== 'memory-catalog')
|
|
97
|
+
continue;
|
|
98
|
+
const entries = readCatalogEntries(source);
|
|
99
|
+
if (entries === undefined)
|
|
100
|
+
continue;
|
|
101
|
+
if (visible.has(event.seq))
|
|
102
|
+
return { visibleDigest: digestIndexEntries(entries), published: true };
|
|
103
|
+
return { published: true };
|
|
104
|
+
}
|
|
105
|
+
return { published: false };
|
|
106
|
+
}
|
|
107
|
+
/** The memory-catalog message already in the entering batch, if any. */
|
|
108
|
+
export function catalogMessage(messages) {
|
|
109
|
+
for (const message of messages) {
|
|
110
|
+
// A message without a stamped source (created before the loop or by hand)
|
|
111
|
+
// is not this plugin's catalog; treat it like any other message.
|
|
112
|
+
const source = message.source;
|
|
113
|
+
if (typeof source !== 'object' || source === null || source.kind !== 'memory-catalog')
|
|
114
|
+
continue;
|
|
115
|
+
const entries = readCatalogEntries(source);
|
|
116
|
+
if (entries !== undefined)
|
|
117
|
+
return { message, entries };
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
/** Category-section lines with per-category relevance hints. */
|
|
122
|
+
function renderSections(entries) {
|
|
123
|
+
const hints = {
|
|
124
|
+
preferences: ' (always relevant)',
|
|
125
|
+
entities: ' (relevant when mentioned)',
|
|
126
|
+
events: ' (relevant for time queries)',
|
|
127
|
+
experiences: ' (relevant for similar tasks)',
|
|
128
|
+
};
|
|
129
|
+
const lines = [];
|
|
130
|
+
let lastCategory;
|
|
131
|
+
for (const entry of entries) {
|
|
132
|
+
if (entry.category !== lastCategory) {
|
|
133
|
+
lines.push('');
|
|
134
|
+
lines.push(`## ${entry.category}${hints[entry.category] ?? ''}`);
|
|
135
|
+
lastCategory = entry.category;
|
|
136
|
+
}
|
|
137
|
+
lines.push(`- ${escapeCatalogText(entry.path)}: ${escapeCatalogText(entry.summary)}`);
|
|
138
|
+
}
|
|
139
|
+
return lines;
|
|
140
|
+
}
|
|
141
|
+
/** Escape catalog text for the pseudo-XML framing (applied at render, never stored). */
|
|
142
|
+
function escapeCatalogText(text) {
|
|
143
|
+
return text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|