@asermax/tachikoma 2.0.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.
- package/README.md +64 -0
- package/dist/agent/adapter.d.ts +8 -0
- package/dist/agent/adapter.js +86 -0
- package/dist/agent/adapter.js.map +1 -0
- package/dist/agent/manager.d.ts +35 -0
- package/dist/agent/manager.js +76 -0
- package/dist/agent/manager.js.map +1 -0
- package/dist/agent/models.d.ts +46 -0
- package/dist/agent/models.js +96 -0
- package/dist/agent/models.js.map +1 -0
- package/dist/agent/side-run.d.ts +42 -0
- package/dist/agent/side-run.js +83 -0
- package/dist/agent/side-run.js.map +1 -0
- package/dist/app.d.ts +5 -0
- package/dist/app.js +79 -0
- package/dist/app.js.map +1 -0
- package/dist/channels/types.d.ts +37 -0
- package/dist/channels/types.js +5 -0
- package/dist/channels/types.js.map +1 -0
- package/dist/config/default-template.d.ts +1 -0
- package/dist/config/default-template.js +49 -0
- package/dist/config/default-template.js.map +1 -0
- package/dist/config/load.d.ts +8 -0
- package/dist/config/load.js +28 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/parse.d.ts +5 -0
- package/dist/config/parse.js +18 -0
- package/dist/config/parse.js.map +1 -0
- package/dist/config/schema.d.ts +29 -0
- package/dist/config/schema.js +35 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/coordinator.d.ts +54 -0
- package/dist/coordinator.js +344 -0
- package/dist/coordinator.js.map +1 -0
- package/dist/db/core-schema.d.ts +250 -0
- package/dist/db/core-schema.js +19 -0
- package/dist/db/core-schema.js.map +1 -0
- package/dist/db/index.d.ts +8 -0
- package/dist/db/index.js +16 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +4 -0
- package/dist/db/schema.js +7 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/state.d.ts +10 -0
- package/dist/db/state.js +36 -0
- package/dist/db/state.js.map +1 -0
- package/dist/domain/agent-events.d.ts +26 -0
- package/dist/domain/agent-events.js +2 -0
- package/dist/domain/agent-events.js.map +1 -0
- package/dist/domain/message.d.ts +25 -0
- package/dist/domain/message.js +17 -0
- package/dist/domain/message.js.map +1 -0
- package/dist/events.d.ts +9 -0
- package/dist/events.js +27 -0
- package/dist/events.js.map +1 -0
- package/dist/extensions/api.d.ts +118 -0
- package/dist/extensions/api.js +7 -0
- package/dist/extensions/api.js.map +1 -0
- package/dist/extensions/boundary/detector.d.ts +20 -0
- package/dist/extensions/boundary/detector.js +57 -0
- package/dist/extensions/boundary/detector.js.map +1 -0
- package/dist/extensions/boundary/idle.d.ts +10 -0
- package/dist/extensions/boundary/idle.js +28 -0
- package/dist/extensions/boundary/idle.js.map +1 -0
- package/dist/extensions/boundary/index.d.ts +12 -0
- package/dist/extensions/boundary/index.js +65 -0
- package/dist/extensions/boundary/index.js.map +1 -0
- package/dist/extensions/boundary/summary.d.ts +5 -0
- package/dist/extensions/boundary/summary.js +33 -0
- package/dist/extensions/boundary/summary.js.map +1 -0
- package/dist/extensions/commands/index.d.ts +7 -0
- package/dist/extensions/commands/index.js +21 -0
- package/dist/extensions/commands/index.js.map +1 -0
- package/dist/extensions/context/index.d.ts +7 -0
- package/dist/extensions/context/index.js +65 -0
- package/dist/extensions/context/index.js.map +1 -0
- package/dist/extensions/context/processor.d.ts +27 -0
- package/dist/extensions/context/processor.js +228 -0
- package/dist/extensions/context/processor.js.map +1 -0
- package/dist/extensions/detached-processes/index.d.ts +12 -0
- package/dist/extensions/detached-processes/index.js +51 -0
- package/dist/extensions/detached-processes/index.js.map +1 -0
- package/dist/extensions/detached-processes/limits.d.ts +27 -0
- package/dist/extensions/detached-processes/limits.js +55 -0
- package/dist/extensions/detached-processes/limits.js.map +1 -0
- package/dist/extensions/detached-processes/output.d.ts +2 -0
- package/dist/extensions/detached-processes/output.js +26 -0
- package/dist/extensions/detached-processes/output.js.map +1 -0
- package/dist/extensions/detached-processes/reconcile.d.ts +31 -0
- package/dist/extensions/detached-processes/reconcile.js +71 -0
- package/dist/extensions/detached-processes/reconcile.js.map +1 -0
- package/dist/extensions/detached-processes/repository.d.ts +33 -0
- package/dist/extensions/detached-processes/repository.js +62 -0
- package/dist/extensions/detached-processes/repository.js.map +1 -0
- package/dist/extensions/detached-processes/schema.d.ts +252 -0
- package/dist/extensions/detached-processes/schema.js +23 -0
- package/dist/extensions/detached-processes/schema.js.map +1 -0
- package/dist/extensions/detached-processes/spawn.d.ts +40 -0
- package/dist/extensions/detached-processes/spawn.js +137 -0
- package/dist/extensions/detached-processes/spawn.js.map +1 -0
- package/dist/extensions/detached-processes/tools.d.ts +41 -0
- package/dist/extensions/detached-processes/tools.js +243 -0
- package/dist/extensions/detached-processes/tools.js.map +1 -0
- package/dist/extensions/detached-processes/watcher.d.ts +7 -0
- package/dist/extensions/detached-processes/watcher.js +19 -0
- package/dist/extensions/detached-processes/watcher.js.map +1 -0
- package/dist/extensions/external/index.d.ts +11 -0
- package/dist/extensions/external/index.js +40 -0
- package/dist/extensions/external/index.js.map +1 -0
- package/dist/extensions/external/installs.d.ts +39 -0
- package/dist/extensions/external/installs.js +98 -0
- package/dist/extensions/external/installs.js.map +1 -0
- package/dist/extensions/external/loader.d.ts +19 -0
- package/dist/extensions/external/loader.js +70 -0
- package/dist/extensions/external/loader.js.map +1 -0
- package/dist/extensions/external/tools.d.ts +17 -0
- package/dist/extensions/external/tools.js +112 -0
- package/dist/extensions/external/tools.js.map +1 -0
- package/dist/extensions/git/commit.d.ts +19 -0
- package/dist/extensions/git/commit.js +44 -0
- package/dist/extensions/git/commit.js.map +1 -0
- package/dist/extensions/git/git.d.ts +11 -0
- package/dist/extensions/git/git.js +29 -0
- package/dist/extensions/git/git.js.map +1 -0
- package/dist/extensions/git/hooks.d.ts +10 -0
- package/dist/extensions/git/hooks.js +88 -0
- package/dist/extensions/git/hooks.js.map +1 -0
- package/dist/extensions/git/index.d.ts +11 -0
- package/dist/extensions/git/index.js +28 -0
- package/dist/extensions/git/index.js.map +1 -0
- package/dist/extensions/git/processor.d.ts +13 -0
- package/dist/extensions/git/processor.js +52 -0
- package/dist/extensions/git/processor.js.map +1 -0
- package/dist/extensions/git/sync.d.ts +44 -0
- package/dist/extensions/git/sync.js +189 -0
- package/dist/extensions/git/sync.js.map +1 -0
- package/dist/extensions/git/tools.d.ts +21 -0
- package/dist/extensions/git/tools.js +101 -0
- package/dist/extensions/git/tools.js.map +1 -0
- package/dist/extensions/host.d.ts +31 -0
- package/dist/extensions/host.js +75 -0
- package/dist/extensions/host.js.map +1 -0
- package/dist/extensions/index.d.ts +3 -0
- package/dist/extensions/index.js +32 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/memory/archive.d.ts +8 -0
- package/dist/extensions/memory/archive.js +46 -0
- package/dist/extensions/memory/archive.js.map +1 -0
- package/dist/extensions/memory/dates.d.ts +2 -0
- package/dist/extensions/memory/dates.js +7 -0
- package/dist/extensions/memory/dates.js.map +1 -0
- package/dist/extensions/memory/extraction.d.ts +17 -0
- package/dist/extensions/memory/extraction.js +218 -0
- package/dist/extensions/memory/extraction.js.map +1 -0
- package/dist/extensions/memory/index.d.ts +20 -0
- package/dist/extensions/memory/index.js +67 -0
- package/dist/extensions/memory/index.js.map +1 -0
- package/dist/extensions/memory/indexes.d.ts +14 -0
- package/dist/extensions/memory/indexes.js +64 -0
- package/dist/extensions/memory/indexes.js.map +1 -0
- package/dist/extensions/memory/layout.d.ts +20 -0
- package/dist/extensions/memory/layout.js +79 -0
- package/dist/extensions/memory/layout.js.map +1 -0
- package/dist/extensions/memory/maintenance.d.ts +21 -0
- package/dist/extensions/memory/maintenance.js +357 -0
- package/dist/extensions/memory/maintenance.js.map +1 -0
- package/dist/extensions/memory/prompts.d.ts +8 -0
- package/dist/extensions/memory/prompts.js +125 -0
- package/dist/extensions/memory/prompts.js.map +1 -0
- package/dist/extensions/memory/transcript.d.ts +18 -0
- package/dist/extensions/memory/transcript.js +79 -0
- package/dist/extensions/memory/transcript.js.map +1 -0
- package/dist/extensions/notifications/format.d.ts +5 -0
- package/dist/extensions/notifications/format.js +17 -0
- package/dist/extensions/notifications/format.js.map +1 -0
- package/dist/extensions/notifications/index.d.ts +13 -0
- package/dist/extensions/notifications/index.js +29 -0
- package/dist/extensions/notifications/index.js.map +1 -0
- package/dist/extensions/notifications/payload.d.ts +22 -0
- package/dist/extensions/notifications/payload.js +29 -0
- package/dist/extensions/notifications/payload.js.map +1 -0
- package/dist/extensions/notifications/router.d.ts +29 -0
- package/dist/extensions/notifications/router.js +55 -0
- package/dist/extensions/notifications/router.js.map +1 -0
- package/dist/extensions/notifications/tools.d.ts +12 -0
- package/dist/extensions/notifications/tools.js +41 -0
- package/dist/extensions/notifications/tools.js.map +1 -0
- package/dist/extensions/projects/context-provider.d.ts +9 -0
- package/dist/extensions/projects/context-provider.js +37 -0
- package/dist/extensions/projects/context-provider.js.map +1 -0
- package/dist/extensions/projects/git.d.ts +28 -0
- package/dist/extensions/projects/git.js +91 -0
- package/dist/extensions/projects/git.js.map +1 -0
- package/dist/extensions/projects/hooks.d.ts +7 -0
- package/dist/extensions/projects/hooks.js +42 -0
- package/dist/extensions/projects/hooks.js.map +1 -0
- package/dist/extensions/projects/index.d.ts +11 -0
- package/dist/extensions/projects/index.js +30 -0
- package/dist/extensions/projects/index.js.map +1 -0
- package/dist/extensions/projects/processor.d.ts +13 -0
- package/dist/extensions/projects/processor.js +63 -0
- package/dist/extensions/projects/processor.js.map +1 -0
- package/dist/extensions/projects/tools.d.ts +21 -0
- package/dist/extensions/projects/tools.js +118 -0
- package/dist/extensions/projects/tools.js.map +1 -0
- package/dist/extensions/registrations.d.ts +21 -0
- package/dist/extensions/registrations.js +12 -0
- package/dist/extensions/registrations.js.map +1 -0
- package/dist/extensions/repl/index.d.ts +2 -0
- package/dist/extensions/repl/index.js +85 -0
- package/dist/extensions/repl/index.js.map +1 -0
- package/dist/extensions/skills/agents.d.ts +17 -0
- package/dist/extensions/skills/agents.js +77 -0
- package/dist/extensions/skills/agents.js.map +1 -0
- package/dist/extensions/skills/delegate.d.ts +22 -0
- package/dist/extensions/skills/delegate.js +54 -0
- package/dist/extensions/skills/delegate.js.map +1 -0
- package/dist/extensions/skills/index.d.ts +11 -0
- package/dist/extensions/skills/index.js +43 -0
- package/dist/extensions/skills/index.js.map +1 -0
- package/dist/extensions/skills/reload.d.ts +8 -0
- package/dist/extensions/skills/reload.js +38 -0
- package/dist/extensions/skills/reload.js.map +1 -0
- package/dist/extensions/tasks/executor.d.ts +43 -0
- package/dist/extensions/tasks/executor.js +179 -0
- package/dist/extensions/tasks/executor.js.map +1 -0
- package/dist/extensions/tasks/expiration.d.ts +12 -0
- package/dist/extensions/tasks/expiration.js +17 -0
- package/dist/extensions/tasks/expiration.js.map +1 -0
- package/dist/extensions/tasks/generation.d.ts +14 -0
- package/dist/extensions/tasks/generation.js +70 -0
- package/dist/extensions/tasks/generation.js.map +1 -0
- package/dist/extensions/tasks/index.d.ts +14 -0
- package/dist/extensions/tasks/index.js +75 -0
- package/dist/extensions/tasks/index.js.map +1 -0
- package/dist/extensions/tasks/repository.d.ts +53 -0
- package/dist/extensions/tasks/repository.js +147 -0
- package/dist/extensions/tasks/repository.js.map +1 -0
- package/dist/extensions/tasks/schedule.d.ts +13 -0
- package/dist/extensions/tasks/schedule.js +32 -0
- package/dist/extensions/tasks/schedule.js.map +1 -0
- package/dist/extensions/tasks/schema.d.ts +423 -0
- package/dist/extensions/tasks/schema.js +45 -0
- package/dist/extensions/tasks/schema.js.map +1 -0
- package/dist/extensions/tasks/session-delivery.d.ts +18 -0
- package/dist/extensions/tasks/session-delivery.js +39 -0
- package/dist/extensions/tasks/session-delivery.js.map +1 -0
- package/dist/extensions/tasks/tools.d.ts +38 -0
- package/dist/extensions/tasks/tools.js +181 -0
- package/dist/extensions/tasks/tools.js.map +1 -0
- package/dist/extensions/telegram/buttons.d.ts +14 -0
- package/dist/extensions/telegram/buttons.js +49 -0
- package/dist/extensions/telegram/buttons.js.map +1 -0
- package/dist/extensions/telegram/channel.d.ts +39 -0
- package/dist/extensions/telegram/channel.js +201 -0
- package/dist/extensions/telegram/channel.js.map +1 -0
- package/dist/extensions/telegram/chunking.d.ts +7 -0
- package/dist/extensions/telegram/chunking.js +67 -0
- package/dist/extensions/telegram/chunking.js.map +1 -0
- package/dist/extensions/telegram/inbound.d.ts +7 -0
- package/dist/extensions/telegram/inbound.js +29 -0
- package/dist/extensions/telegram/inbound.js.map +1 -0
- package/dist/extensions/telegram/index.d.ts +13 -0
- package/dist/extensions/telegram/index.js +67 -0
- package/dist/extensions/telegram/index.js.map +1 -0
- package/dist/extensions/telegram/media.d.ts +39 -0
- package/dist/extensions/telegram/media.js +223 -0
- package/dist/extensions/telegram/media.js.map +1 -0
- package/dist/extensions/telegram/mutex.d.ts +9 -0
- package/dist/extensions/telegram/mutex.js +14 -0
- package/dist/extensions/telegram/mutex.js.map +1 -0
- package/dist/extensions/telegram/sending.d.ts +48 -0
- package/dist/extensions/telegram/sending.js +119 -0
- package/dist/extensions/telegram/sending.js.map +1 -0
- package/dist/extensions/telegram/streaming.d.ts +46 -0
- package/dist/extensions/telegram/streaming.js +140 -0
- package/dist/extensions/telegram/streaming.js.map +1 -0
- package/dist/extensions/telegram/tools.d.ts +80 -0
- package/dist/extensions/telegram/tools.js +232 -0
- package/dist/extensions/telegram/tools.js.map +1 -0
- package/dist/extensions/workflows/cleanup.d.ts +10 -0
- package/dist/extensions/workflows/cleanup.js +38 -0
- package/dist/extensions/workflows/cleanup.js.map +1 -0
- package/dist/extensions/workflows/index.d.ts +11 -0
- package/dist/extensions/workflows/index.js +42 -0
- package/dist/extensions/workflows/index.js.map +1 -0
- package/dist/extensions/workflows/loader.d.ts +27 -0
- package/dist/extensions/workflows/loader.js +90 -0
- package/dist/extensions/workflows/loader.js.map +1 -0
- package/dist/extensions/workflows/model.d.ts +19 -0
- package/dist/extensions/workflows/model.js +7 -0
- package/dist/extensions/workflows/model.js.map +1 -0
- package/dist/extensions/workflows/repository.d.ts +24 -0
- package/dist/extensions/workflows/repository.js +61 -0
- package/dist/extensions/workflows/repository.js.map +1 -0
- package/dist/extensions/workflows/schema.d.ts +193 -0
- package/dist/extensions/workflows/schema.js +20 -0
- package/dist/extensions/workflows/schema.js.map +1 -0
- package/dist/extensions/workflows/tools.d.ts +27 -0
- package/dist/extensions/workflows/tools.js +285 -0
- package/dist/extensions/workflows/tools.js.map +1 -0
- package/dist/log.d.ts +8 -0
- package/dist/log.js +15 -0
- package/dist/log.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +27 -0
- package/dist/main.js.map +1 -0
- package/dist/migration/ask.d.ts +8 -0
- package/dist/migration/ask.js +24 -0
- package/dist/migration/ask.js.map +1 -0
- package/dist/migration/config.d.ts +10 -0
- package/dist/migration/config.js +122 -0
- package/dist/migration/config.js.map +1 -0
- package/dist/migration/context.d.ts +3 -0
- package/dist/migration/context.js +24 -0
- package/dist/migration/context.js.map +1 -0
- package/dist/migration/database.d.ts +8 -0
- package/dist/migration/database.js +51 -0
- package/dist/migration/database.js.map +1 -0
- package/dist/migration/fs.d.ts +1 -0
- package/dist/migration/fs.js +11 -0
- package/dist/migration/fs.js.map +1 -0
- package/dist/migration/index.d.ts +11 -0
- package/dist/migration/index.js +28 -0
- package/dist/migration/index.js.map +1 -0
- package/dist/migration/skills.d.ts +19 -0
- package/dist/migration/skills.js +77 -0
- package/dist/migration/skills.js.map +1 -0
- package/dist/scheduler.d.ts +17 -0
- package/dist/scheduler.js +53 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/sessions/registry.d.ts +15 -0
- package/dist/sessions/registry.js +42 -0
- package/dist/sessions/registry.js.map +1 -0
- package/dist/workspace.d.ts +13 -0
- package/dist/workspace.js +32 -0
- package/dist/workspace.js.map +1 -0
- package/drizzle/0000_init.sql +19 -0
- package/drizzle/0001_extensions.sql +63 -0
- package/drizzle/meta/0000_snapshot.json +134 -0
- package/drizzle/meta/0001_snapshot.json +526 -0
- package/drizzle/meta/_journal.json +20 -0
- package/package.json +63 -0
- package/skills/skill-authoring/SKILL.md +168 -0
- package/skills/workflow-authoring/SKILL.md +251 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { readdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { MEMORY_FILE_TOOLS } from "./extraction.js";
|
|
4
|
+
import { fileExists, MEMORY_STORES, storeDir, sweepEmptyMarkdown, } from "./layout.js";
|
|
5
|
+
import { INDEX_LIGHT_MAINTENANCE_SECTION, STORE_PURPOSE_SECTION, scopeSection } from "./prompts.js";
|
|
6
|
+
const episodicMaintenancePrompt = ({ recentDays, weeklyThresholdMonths, monthlyThresholdMonths, }) => `You are a memory maintenance agent performing episodic memory consolidation.
|
|
7
|
+
|
|
8
|
+
## Directory
|
|
9
|
+
|
|
10
|
+
\`$WORKSPACE/memories/episodic/\`
|
|
11
|
+
|
|
12
|
+
## Pre-check
|
|
13
|
+
|
|
14
|
+
If the directory is empty or contains no \`.md\` files, stop immediately — nothing to maintain.
|
|
15
|
+
|
|
16
|
+
## File Handling
|
|
17
|
+
|
|
18
|
+
- Skip empty (0-byte) or malformed files — do not attempt to process them.
|
|
19
|
+
- Only process files with \`.md\` extension.
|
|
20
|
+
- If a file's content looks truncated or garbled, skip it.
|
|
21
|
+
|
|
22
|
+
## Time Tiers
|
|
23
|
+
|
|
24
|
+
Categorize every non-skipped file by its date (extracted from filename \`YYYY-MM-DD.md\` or from \`YYYY-WNN.md\` / \`YYYY-MM.md\` summary files):
|
|
25
|
+
|
|
26
|
+
### Tier 1: Recent (last ${recentDays} days) — Clean only
|
|
27
|
+
|
|
28
|
+
- **Goal**: Reduce verbosity without losing substance.
|
|
29
|
+
- Remove repeated information that appears identically across entries.
|
|
30
|
+
- Remove excessive implementation detail (file lists, step-by-step code changes, routine activity status).
|
|
31
|
+
- Preserve: outcomes, decisions, new information, significant events.
|
|
32
|
+
- **NEVER delete files or remove substantive content from this tier.**
|
|
33
|
+
- If an entry is already clean and concise, leave it unchanged.
|
|
34
|
+
|
|
35
|
+
### Tier 2: Weekly consolidation (${recentDays} days – ${weeklyThresholdMonths} months) — Weekly summaries
|
|
36
|
+
|
|
37
|
+
- Group daily files by ISO week (e.g., files from 2026-04-13 through 2026-04-19 all belong to week 2026-W15).
|
|
38
|
+
- For each group, create a weekly summary file named \`YYYY-WNN.md\` (e.g., \`2026-W15.md\`).
|
|
39
|
+
- The summary should capture the high-level narrative and significant events of that week — decisions, outcomes, notable activities.
|
|
40
|
+
- Discard: routine implementation details, file change lists, repetitive status updates, step-by-step technical minutiae.
|
|
41
|
+
- If a weekly summary \`YYYY-WNN.md\` already exists from a previous run, merge new content into it — do not overwrite.
|
|
42
|
+
- After successful consolidation, delete the original daily files that were consolidated.
|
|
43
|
+
- Partial groups (e.g., only 2 days in a week) are consolidated into a single summary for that period.
|
|
44
|
+
|
|
45
|
+
### Tier 3: Monthly consolidation (${weeklyThresholdMonths} months – ${monthlyThresholdMonths} months) — Monthly summaries
|
|
46
|
+
|
|
47
|
+
- Group all files (daily or weekly) by month.
|
|
48
|
+
- For each group, create a monthly summary file named \`YYYY-MM.md\` (e.g., \`2026-04.md\`).
|
|
49
|
+
- The summary should capture the most significant themes and events of that month at a high level.
|
|
50
|
+
- Discard: all routine detail — keep only notable outcomes, key decisions, and significant changes.
|
|
51
|
+
- If a monthly summary \`YYYY-MM.md\` already exists from a previous run, merge new content into it — do not overwrite.
|
|
52
|
+
- After successful consolidation, delete the original files.
|
|
53
|
+
- Partial months are consolidated into a single summary.
|
|
54
|
+
|
|
55
|
+
### Tier 4: Older than ${monthlyThresholdMonths} months — Delete
|
|
56
|
+
|
|
57
|
+
- Delete all files older than ${monthlyThresholdMonths} months.
|
|
58
|
+
- These entries have been through monthly consolidation already — anything remaining at this age is beyond the retention window.
|
|
59
|
+
|
|
60
|
+
## Idempotency
|
|
61
|
+
|
|
62
|
+
Before acting, check whether the work has already been done:
|
|
63
|
+
- If a weekly/monthly summary already exists and covers the files in its range, do not recreate it.
|
|
64
|
+
- If daily files in Tier 1 are already clean and concise, do not re-edit.
|
|
65
|
+
- If no files need processing, exit with no changes.`;
|
|
66
|
+
const FACTS_MAINTENANCE_PROMPT = `You are a memory maintenance agent performing facts memory cleanup.
|
|
67
|
+
|
|
68
|
+
## Directory
|
|
69
|
+
|
|
70
|
+
\`$WORKSPACE/memories/facts/\`
|
|
71
|
+
|
|
72
|
+
## Pre-check
|
|
73
|
+
|
|
74
|
+
If the directory is empty or contains no \`.md\` files, stop immediately — nothing to maintain.
|
|
75
|
+
|
|
76
|
+
## File Handling
|
|
77
|
+
|
|
78
|
+
- Skip empty (0-byte) or malformed files — do not attempt to process them.
|
|
79
|
+
- Only process files with \`.md\` extension.
|
|
80
|
+
|
|
81
|
+
## Evaluation Criteria
|
|
82
|
+
|
|
83
|
+
Read all fact files and evaluate each for three issues:
|
|
84
|
+
|
|
85
|
+
### Staleness
|
|
86
|
+
|
|
87
|
+
An entry is stale when it describes a state that is no longer accurate:
|
|
88
|
+
- References to past dates or completed projects (e.g., "currently working on X" when X shipped months ago).
|
|
89
|
+
- Information contradicted by newer entries.
|
|
90
|
+
- Technical details that reference outdated tools, versions, or configurations.
|
|
91
|
+
|
|
92
|
+
For stale entries:
|
|
93
|
+
- If the entry has a newer, accurate replacement: remove the stale version.
|
|
94
|
+
- If the entry can be updated to reflect current state: edit it.
|
|
95
|
+
- If the entry describes a completed event with no ongoing relevance: remove it.
|
|
96
|
+
|
|
97
|
+
### Redundancy
|
|
98
|
+
|
|
99
|
+
Same information stated in different files:
|
|
100
|
+
- Keep the most complete and well-organized version.
|
|
101
|
+
- Remove the duplicate entries.
|
|
102
|
+
|
|
103
|
+
### Overlap
|
|
104
|
+
|
|
105
|
+
Related topics split across multiple files:
|
|
106
|
+
- When files cover overlapping subject areas, merge them into a single consolidated file.
|
|
107
|
+
- Choose the best filename from the originals, or create a more descriptive one.
|
|
108
|
+
- Remove the original files after merging.
|
|
109
|
+
|
|
110
|
+
#### Cluster Consolidation
|
|
111
|
+
|
|
112
|
+
Beyond pairwise overlap, look for clusters of many small files that fragment a single broad topic into per-incident, per-bug, or per-date entries — this is the main driver of facts directory bloat:
|
|
113
|
+
|
|
114
|
+
- List all files in \`$WORKSPACE/memories/facts/\` and group them by shared prefix or core topic (project, system, tool, or domain).
|
|
115
|
+
- When 3 or more files share the same prefix or core topic, treat them as a cluster and consolidate aggressively:
|
|
116
|
+
- Merge all of the cluster's content into a single broad-topic file named \`<project>.md\`, \`<system>.md\`, \`<tool>.md\`, or \`<domain>.md\` — the same broad-topic convention used at extraction time.
|
|
117
|
+
- If a broad-topic file already exists in the cluster, merge the others into it. Otherwise, pick a broad name and create the consolidated file.
|
|
118
|
+
- Delete the original narrow files after merging.
|
|
119
|
+
- Generic examples of clusters to consolidate (patterns, not literal names): files matching \`<project>-<bug-description>-<YYYY-MM-DD>.md\`, \`<project>-patch-<issue-id>.md\`, \`<system>-<incident>-<date>.md\`, \`<topic>-session-<date>.md\` — all of these should fold into the broad \`<project>.md\`, \`<system>.md\`, or \`<topic>.md\` file.
|
|
120
|
+
- Preserve substantive content during the merge; deduplicate restated information and discard incidental detail that does not belong in stable reference facts.
|
|
121
|
+
|
|
122
|
+
### Size Enforcement
|
|
123
|
+
|
|
124
|
+
Flag any file exceeding 40 lines for consolidation:
|
|
125
|
+
- If a file exceeds 40 lines, it likely contains implementation details or narrative that belongs in project docs or episodic memory rather than stable reference facts
|
|
126
|
+
- Prune implementation details and transient information
|
|
127
|
+
- Consolidate related entries within the file to eliminate restatement
|
|
128
|
+
|
|
129
|
+
### Context File Overlap
|
|
130
|
+
|
|
131
|
+
Check whether facts are already covered by the context files at the workspace root:
|
|
132
|
+
- Read \`$WORKSPACE/USER.md\` and \`$WORKSPACE/AGENTS.md\` for the same topic
|
|
133
|
+
- If a context file already captures the information, trim the facts file to a brief reference (e.g., "See USER.md for details about X")
|
|
134
|
+
- Context files are more authoritative for their respective categories; facts should supplement, not duplicate
|
|
135
|
+
|
|
136
|
+
## Deletion
|
|
137
|
+
|
|
138
|
+
- If a fact file is entirely obsolete (all entries stale, no useful content), delete it.
|
|
139
|
+
- Do NOT delete files that contain any useful or current information.
|
|
140
|
+
|
|
141
|
+
## Idempotency
|
|
142
|
+
|
|
143
|
+
The goal is to leave the store materially smaller and more consolidated than you found it. Treat absence of exact duplicates as insufficient grounds for skipping — semantic overlap and per-incident granularity are also valid triggers for action.
|
|
144
|
+
|
|
145
|
+
### Consolidate narrow per-incident files into broader topic files
|
|
146
|
+
|
|
147
|
+
When you see multiple narrow files about the same subject (per-date, per-incident, per-PR, per-bug), merge them into a single broader topic file. Example: \`<project>-bug-<YYYY-MM-DD>.md\`, \`<project>-process.md\`, and \`<project>-rollout-notes.md\` should all be folded into \`<project>.md\`. Keep the most durable, generally-useful information; discard the incident-specific noise. Delete the merged-from files after consolidation.
|
|
148
|
+
|
|
149
|
+
### Aggressively prune resolved incidents
|
|
150
|
+
|
|
151
|
+
Files whose content carries headers like "Status: Completed", "Status: Merged", "Status: Resolved", or "Status: Fixed" describe one-time events — that content belongs in episodic memory, not facts. Delete these files outright. If a fact file mixes durable content with a resolved-incident section, strip the resolved section and keep the rest.
|
|
152
|
+
|
|
153
|
+
If no changes are needed, exit with no changes.`;
|
|
154
|
+
const PREFERENCES_MAINTENANCE_PROMPT = `You are a memory maintenance agent performing preferences memory cleanup.
|
|
155
|
+
|
|
156
|
+
## Directory
|
|
157
|
+
|
|
158
|
+
\`$WORKSPACE/memories/preferences/\`
|
|
159
|
+
|
|
160
|
+
## Pre-check
|
|
161
|
+
|
|
162
|
+
If the directory is empty or contains no \`.md\` files, stop immediately — nothing to maintain.
|
|
163
|
+
|
|
164
|
+
## File Handling
|
|
165
|
+
|
|
166
|
+
- Skip empty (0-byte) or malformed files — do not attempt to process them.
|
|
167
|
+
- Only process files with \`.md\` extension.
|
|
168
|
+
|
|
169
|
+
## Evaluation Criteria
|
|
170
|
+
|
|
171
|
+
Read all preference files and evaluate each for these issues:
|
|
172
|
+
|
|
173
|
+
### Redundancy
|
|
174
|
+
|
|
175
|
+
Same preference stated multiple times across or within files:
|
|
176
|
+
- Keep the most complete and well-organized version.
|
|
177
|
+
- Remove the duplicate entries.
|
|
178
|
+
|
|
179
|
+
### Overlap
|
|
180
|
+
|
|
181
|
+
Related preferences split across multiple files:
|
|
182
|
+
- When files cover overlapping topics (e.g., coding style preferences split across "python-style.md" and "code-formatting.md"), merge them into a single consolidated file.
|
|
183
|
+
- Choose the best filename from the originals, or create a more descriptive one.
|
|
184
|
+
- Remove the original files after merging.
|
|
185
|
+
|
|
186
|
+
#### Cluster Consolidation
|
|
187
|
+
|
|
188
|
+
Beyond pairwise overlap, look for clusters of many small files that fragment a single broad preference topic into per-occasion, per-feedback, or per-date entries — this is the main driver of preferences directory bloat:
|
|
189
|
+
|
|
190
|
+
- List all files in \`$WORKSPACE/memories/preferences/\` and group them by shared prefix or core topic (style, workflow, communication, tooling, project, system, or domain).
|
|
191
|
+
- When 3 or more files share the same prefix or core topic, treat them as a cluster and consolidate aggressively:
|
|
192
|
+
- Merge all of the cluster's content into a single broad-topic file named \`<topic-area>-style.md\`, \`<topic-area>-workflow.md\`, \`<domain>.md\`, or \`<project>.md\` — the same broad-topic convention used at extraction time.
|
|
193
|
+
- If a broad-topic file already exists in the cluster, merge the others into it. Otherwise, pick a broad name and create the consolidated file.
|
|
194
|
+
- Delete the original narrow files after merging.
|
|
195
|
+
- Generic examples of clusters to consolidate (patterns, not literal names): files matching \`<topic-area>-feedback-<YYYY-MM-DD>.md\`, \`<project>-preference-<issue-id>.md\`, \`<topic-area>-session-<date>.md\`, \`<one-off>-incident-<date>.md\` — all of these should fold into the broad \`<topic-area>-style.md\`, \`<topic-area>-workflow.md\`, or \`<topic>.md\` file.
|
|
196
|
+
- Preserve substantive content during the merge; deduplicate restated preferences and keep only one clear statement per preference.
|
|
197
|
+
|
|
198
|
+
### Misclassification
|
|
199
|
+
|
|
200
|
+
Content that belongs in facts memory, not preferences:
|
|
201
|
+
- Read each file and ask: "Does this describe a subjective choice (preference) or reference information (fact)?"
|
|
202
|
+
- If the file describes how something works, technical specifications, financial structures, system configurations, or procedural workflows → it is misclassified
|
|
203
|
+
- For misclassified files: delete the preferences file. The facts extraction processor will pick the content up on the next relevant conversation.
|
|
204
|
+
|
|
205
|
+
### Size Enforcement
|
|
206
|
+
|
|
207
|
+
Flag any file exceeding 30 lines for consolidation or pruning:
|
|
208
|
+
- If a file exceeds 30 lines, it likely contains reference information that belongs in facts, or multiple preferences that could be expressed more concisely
|
|
209
|
+
- Prune redundant statements within the file
|
|
210
|
+
- If the excess is factual content, treat as misclassification (see above)
|
|
211
|
+
|
|
212
|
+
### Cross-Store Overlap with Facts
|
|
213
|
+
|
|
214
|
+
Check \`$WORKSPACE/memories/facts/\` for files covering the same topic:
|
|
215
|
+
- If a facts file already covers the topic, the preferences file should only contain genuinely subjective aspects (how the user wants things done) — not the factual details already captured in facts
|
|
216
|
+
- If a preferences file contains only factual content that a facts file already covers, delete the preferences file — it serves no purpose
|
|
217
|
+
|
|
218
|
+
## Deletion
|
|
219
|
+
|
|
220
|
+
- If a preference file is entirely superseded (its preferences are all present in a newer, more complete file), delete it.
|
|
221
|
+
- If a preference file describes preferences the user no longer holds (e.g., contradicted by a newer entry), remove only the outdated entries — or delete the file if it becomes empty.
|
|
222
|
+
- Do NOT delete files that contain any current, unique preferences.
|
|
223
|
+
|
|
224
|
+
## Idempotency
|
|
225
|
+
|
|
226
|
+
Treat absence of exact duplicates as insufficient grounds for skipping — semantic overlap and split topics are also triggers for action. Actively re-apply the Evaluation Criteria and Deletion sections above: merge overlapping files even when they aren't word-for-word duplicates, and remove reversed or superseded preferences even when they aren't explicitly contradicted in a newer file.
|
|
227
|
+
|
|
228
|
+
If no changes are needed, exit with no changes.`;
|
|
229
|
+
const heavyIndexRebuildSection = (store) => `## Memory Index Rebuild (full)
|
|
230
|
+
|
|
231
|
+
Rebuild the MEMORY.md index file in \`$WORKSPACE/memories/${store}/\` from scratch:
|
|
232
|
+
|
|
233
|
+
1. **List all files**: find all \`.md\` files in \`$WORKSPACE/memories/${store}/\` (exclude \`MEMORY.md\` itself).
|
|
234
|
+
|
|
235
|
+
2. **If the directory is empty** (no \`.md\` files besides MEMORY.md): write MEMORY.md with only the header \`# Memory Index\` and stop — no further steps needed.
|
|
236
|
+
|
|
237
|
+
3. **Describe every file**: read each file and produce a concise one-line description (under 80 characters) that captures the file's topic and scope. Focus on WHAT the file contains, not its history.
|
|
238
|
+
|
|
239
|
+
4. **Analyze for structural improvements**:
|
|
240
|
+
- If multiple files have very similar content (same topic/domain), consider merging them into a single file with a broad name.
|
|
241
|
+
- If a file's name doesn't match its content (e.g., date-based name for general content), rename it: write the content to the new name, then empty the old file.
|
|
242
|
+
- If files are fragmented (many small files about the same thing), consolidate into fewer, broader files.
|
|
243
|
+
|
|
244
|
+
5. **Write MEMORY.md from scratch** with:
|
|
245
|
+
- Header: \`# Memory Index\`
|
|
246
|
+
- One entry per current file in format: \`[Human-readable Name](./filename.md): One-line description\`
|
|
247
|
+
- Entries listed in alphabetical order by filename
|
|
248
|
+
|
|
249
|
+
### Entry Format
|
|
250
|
+
|
|
251
|
+
\`\`\`
|
|
252
|
+
[Topic Name](./topic-slug.md): One-line description of what this file contains
|
|
253
|
+
\`\`\`
|
|
254
|
+
|
|
255
|
+
- The name in brackets is a human-readable topic name (Title Case)
|
|
256
|
+
- The path is a relative markdown link starting with \`./\`
|
|
257
|
+
- The description is one line, under 80 characters
|
|
258
|
+
- Separate the link and description with \`: \` (colon + space)`;
|
|
259
|
+
const CONTRADICTION_DETECTION_SECTION = `## Cross-Store Contradiction Detection
|
|
260
|
+
|
|
261
|
+
When reviewing files in this store, check for contradictions against other stores:
|
|
262
|
+
|
|
263
|
+
1. Read the files listed in the cross-store visibility section above
|
|
264
|
+
2. Compare their content against the files you're maintaining in this store
|
|
265
|
+
3. If you find contradictory information:
|
|
266
|
+
- Determine which store is more authoritative per the authority hierarchy (Facts > Context)
|
|
267
|
+
- If this store is LESS authoritative: update or remove the contradicting entry in this store to match the more authoritative source
|
|
268
|
+
- If this store is MORE authoritative: leave this store's entry unchanged (the other store's maintenance tick will handle it)
|
|
269
|
+
4. When information in this store duplicates detail from a more authoritative store: trim this store's entry to a brief pointer (e.g., "See memories/facts/X.md for details")`;
|
|
270
|
+
const STORE_LABELS = {
|
|
271
|
+
episodic: "Episodic Files",
|
|
272
|
+
facts: "Facts Files",
|
|
273
|
+
preferences: "Preferences Files",
|
|
274
|
+
};
|
|
275
|
+
const CONTEXT_FILE_NAMES = ["SOUL.md", "USER.md", "AGENTS.md"];
|
|
276
|
+
/** Names-only listing of the other stores so the maintenance agent can reconcile across them. */
|
|
277
|
+
export const buildCrossStoreManifest = async (workspaceRoot, current) => {
|
|
278
|
+
const sections = [];
|
|
279
|
+
for (const store of MEMORY_STORES) {
|
|
280
|
+
if (store === current)
|
|
281
|
+
continue;
|
|
282
|
+
let files;
|
|
283
|
+
try {
|
|
284
|
+
files = (await readdir(storeDir(workspaceRoot, store)))
|
|
285
|
+
.filter((name) => name.endsWith(".md"))
|
|
286
|
+
.sort();
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
if (files.length === 0)
|
|
292
|
+
continue;
|
|
293
|
+
sections.push([
|
|
294
|
+
`### ${STORE_LABELS[store]}`,
|
|
295
|
+
"",
|
|
296
|
+
...files.map((name) => `- \`memories/${store}/${name}\``),
|
|
297
|
+
].join("\n"));
|
|
298
|
+
}
|
|
299
|
+
const contextFiles = [];
|
|
300
|
+
for (const name of CONTEXT_FILE_NAMES) {
|
|
301
|
+
if (await fileExists(join(workspaceRoot, name)))
|
|
302
|
+
contextFiles.push(name);
|
|
303
|
+
}
|
|
304
|
+
if (contextFiles.length > 0) {
|
|
305
|
+
sections.push([
|
|
306
|
+
"### Context Files",
|
|
307
|
+
"",
|
|
308
|
+
...contextFiles.map((name) => `- \`${name}\` (workspace root)`),
|
|
309
|
+
].join("\n"));
|
|
310
|
+
}
|
|
311
|
+
if (sections.length === 0)
|
|
312
|
+
return null;
|
|
313
|
+
return [
|
|
314
|
+
"## Cross-Store Visibility",
|
|
315
|
+
"",
|
|
316
|
+
"Files in other information stores (names and paths only, not content):",
|
|
317
|
+
"",
|
|
318
|
+
sections.join("\n\n"),
|
|
319
|
+
"",
|
|
320
|
+
"If a section in this store duplicates or contradicts content in a listed file, reconcile per the authority hierarchy in your instructions.",
|
|
321
|
+
].join("\n");
|
|
322
|
+
};
|
|
323
|
+
const basePrompt = (store, settings) => {
|
|
324
|
+
if (store === "episodic")
|
|
325
|
+
return episodicMaintenancePrompt(settings);
|
|
326
|
+
if (store === "facts")
|
|
327
|
+
return FACTS_MAINTENANCE_PROMPT;
|
|
328
|
+
return PREFERENCES_MAINTENANCE_PROMPT;
|
|
329
|
+
};
|
|
330
|
+
export const maintenanceSystemPrompt = async (store, { workspaceRoot, settings, now }) => {
|
|
331
|
+
const parts = [basePrompt(store, settings)];
|
|
332
|
+
// Day-of-week dispatch: weekdays keep the index consistent cheaply,
|
|
333
|
+
// Sunday rebuilds it from scratch with fresh descriptions.
|
|
334
|
+
if (store !== "episodic") {
|
|
335
|
+
const isSunday = (now?.() ?? new Date()).getDay() === 0;
|
|
336
|
+
parts.push(isSunday ? heavyIndexRebuildSection(store) : INDEX_LIGHT_MAINTENANCE_SECTION);
|
|
337
|
+
}
|
|
338
|
+
parts.push(STORE_PURPOSE_SECTION);
|
|
339
|
+
const manifest = await buildCrossStoreManifest(workspaceRoot, store);
|
|
340
|
+
if (manifest != null)
|
|
341
|
+
parts.push(manifest);
|
|
342
|
+
parts.push(CONTRADICTION_DETECTION_SECTION, scopeSection(store));
|
|
343
|
+
return parts.join("\n\n").replaceAll("$WORKSPACE", workspaceRoot);
|
|
344
|
+
};
|
|
345
|
+
/** Daily maintenance pass over one memory store: consolidate, prune, keep indexes in sync. */
|
|
346
|
+
export const runMaintenanceTick = async (store, deps) => {
|
|
347
|
+
deps.log.info({ store }, "memory maintenance tick started");
|
|
348
|
+
await deps.side.run({
|
|
349
|
+
tools: MEMORY_FILE_TOOLS,
|
|
350
|
+
system: await maintenanceSystemPrompt(store, deps),
|
|
351
|
+
prompt: "Perform the maintenance pass now, following your instructions.",
|
|
352
|
+
tier: "processor",
|
|
353
|
+
});
|
|
354
|
+
await sweepEmptyMarkdown(storeDir(deps.workspaceRoot, store), deps.log);
|
|
355
|
+
deps.log.info({ store }, "memory maintenance tick completed");
|
|
356
|
+
};
|
|
357
|
+
//# sourceMappingURL=maintenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../../src/extensions/memory/maintenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MemoryStore } from "./layout.ts";
|
|
2
|
+
export declare const STORE_PURPOSE_SECTION = "## Store Purpose Definitions\n\nEach information store serves a distinct purpose. Use these definitions to route information correctly:\n\n- **Memory facts** (`memories/facts/`): Stable reference information \u2014 project state, technical decisions, configuration, people, system architecture. Most authoritative store for reference information.\n- **Memory preferences** (`memories/preferences/`): Subjective choices with rationale \u2014 how the user wants things done, with context about why.\n- **Memory episodic** (`memories/episodic/`): Date-stamped summaries of what happened \u2014 events, outcomes, and decisions tied to a specific day.\n- **Context files** (workspace root): Concise summaries and pointers \u2014 personality (SOUL.md), user identity (USER.md), behavioral guidance (AGENTS.md). Context should reference facts rather than inlining their content.\n\nAuthority order: Memory facts > Context files. When information appears in multiple stores, the more authoritative source is correct. Context files should contain summaries and pointers, not detailed operational content.";
|
|
3
|
+
export declare const CLASSIFICATION_EXAMPLES_SECTION = "## Classification Examples\n\nUse these examples to route information correctly between facts and preferences.\n\n### IS a preference (subjective choice about HOW the user wants things done):\n- \"I prefer concise commit messages over detailed ones\" \u2192 style preference\n- \"Always run tests before pushing\" \u2192 workflow preference\n- \"Use dark theme for code editors\" \u2192 tooling preference\n- \"I like getting a summary first, then details on request\" \u2192 communication style preference\n- \"Prefer smaller, focused PRs over large ones\" \u2192 workflow preference\n\n### NOT a preference (describes HOW SOMETHING WORKS \u2014 belongs in facts or project docs):\n- \"The payment gateway has a 2% processing fee\" \u2192 financial reference data \u2192 facts\n- \"The reconciliation process runs nightly at 3am\" \u2192 financial reference data \u2192 facts\n- \"Environment variable FOO must be set to BAR for the service to start\" \u2192 technical specification \u2192 facts\n- \"The SDK has a 200K token context window\" \u2192 technical specification \u2192 facts\n- \"The API rate limit is 100 requests per minute\" \u2192 technical specification \u2192 facts\n- \"The cleanup procedure involves stopping the service, clearing /tmp, and restarting\" \u2192 procedural workflow \u2192 facts\n- \"We configured nginx to proxy /api to port 8080\" \u2192 system configuration record \u2192 facts\n- \"The deployment uses blue-green strategy with health checks\" \u2192 system configuration record \u2192 facts\n\n### IS a fact (stable reference information that stays true across conversations):\n- \"The CI pipeline runs on GitHub Actions\" \u2192 infrastructure fact\n- \"User X is the team lead for project Y\" \u2192 organizational fact\n- \"The database uses PostgreSQL 16 with async replication\" \u2192 technical fact\n- \"The API rate limit is 100 requests per minute\" \u2192 technical fact\n\n### NOT a fact (belongs in episodic memory or project docs):\n- \"We debugged the payment timeout issue on 2026-05-10\" \u2192 one-time event \u2192 episodic\n- \"The full architecture of system X is...\" \u2192 too long for facts \u2192 project docs";
|
|
4
|
+
export declare const CONTEXT_DEDUP_SECTION = "## Context File Deduplication\n\nBefore creating any new memory file, check whether the information is already covered in the foundational context files at the workspace root. These files are maintained as the authoritative source for certain categories of information.\n\n1. Read the context files:\n - `$WORKSPACE/AGENTS.md` \u2014 operational guidelines and workflow preferences\n - `$WORKSPACE/USER.md` \u2014 stable identity and high-level project awareness\n - `$WORKSPACE/SOUL.md` \u2014 personality and communication style\n\n2. For each piece of information you're about to write:\n - If the SAME information is already in one of these files, do NOT create a memory file for it \u2014 the context file is the source of truth\n - If a context file partially covers the topic but the conversation adds genuinely new details not found there, you MAY create a file \u2014 but only for the new information, not a restatement of what's already in the context file\n - If no context file covers the topic, proceed normally\n\nThis check prevents duplicating information across the memory system and the context files, which would create confusion about which is authoritative.";
|
|
5
|
+
export declare const WORKSPACE_VALIDATION_SECTION = "## Workspace Validation\n\nBefore writing a memory that contains claims about workspace state \u2014 file paths, project structure, configuration values, implementation details \u2014 validate each claim against the actual workspace:\n\n1. Identify verifiable claims in the memory you're about to write:\n - References to specific files or directories (do they exist? contain what's claimed?)\n - Configuration values (does the config file actually say that?)\n - Project state (is the project actually in that state?)\n\n2. Verify each claim directly: read the relevant file(s) or grep for the referenced content.\n\n3. Only include claims you could verify:\n - If a claim turns out to be false, omit it\n - If ALL claims are invalid, do not create the file\n\nDo NOT validate: subjective information, preferences, general knowledge, conversation summaries, personal details \u2014 only verifiable claims about workspace state.";
|
|
6
|
+
export declare const INDEX_UPDATE_SECTION = "## Memory Index\n\nWhen you create, modify, or delete a memory file, you MUST also update MEMORY.md in the same directory to keep the index in sync.\n\n### Entry Format\n\nEach entry in MEMORY.md follows this format:\n\n```\n[Human-readable Name](./filename.md): One-line description of contents\n```\n\n### Rules\n\n- **CREATE** a new file: add a new entry with an appropriate description\n- **MODIFY** a file: update the description if the topic, focus, or scope meaningfully changed\n- **DELETE** a file: remove the corresponding entry\n- Always preserve the `# Memory Index` header\n- Keep descriptions concise \u2014 one line, under 80 characters\n- The name in brackets should be a human-readable topic name (Title Case)\n\n### Example Entries\n\n```\n# Memory Index\n\n[API Design](./api-design.md): API architecture decisions and endpoint patterns\n[Work Info](./work-info.md): Job details, team structure, and work schedule\n[Tech Stack](./tech-stack.md): Primary languages, frameworks, and tools used\n```";
|
|
7
|
+
export declare const INDEX_LIGHT_MAINTENANCE_SECTION = "## Memory Index Consistency\n\nVerify index consistency between MEMORY.md and actual files in the directory.\n\n### Steps\n\n1. **List all files**: list all `.md` files in the directory (excluding `MEMORY.md` itself) using the ls or find tool.\n2. **Read MEMORY.md**: Parse the existing index entries.\n3. **Add missing entries**: For files that exist in the directory but have no entry in MEMORY.md, add a placeholder entry:\n ```\n [Topic](./filename.md): Description pending update\n ```\n4. **Remove stale entries**: For entries in MEMORY.md that reference files that no longer exist, remove those entries.\n5. **Preserve existing descriptions**: Do NOT regenerate or modify existing descriptions \u2014 leave them unchanged even if stale. Description regeneration is handled by the weekly full rebuild.\n\n### Rules\n\n- Always preserve the `# Memory Index` header.\n- When you create, modify, or delete memory files during this maintenance run, also update MEMORY.md per the standard index update rules (add new entries, update descriptions on meaningful changes, remove entries for deleted files).\n- The consistency check runs in addition to your normal maintenance tasks.";
|
|
8
|
+
export declare const scopeSection: (store: MemoryStore) => string;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
export const STORE_PURPOSE_SECTION = `## Store Purpose Definitions
|
|
2
|
+
|
|
3
|
+
Each information store serves a distinct purpose. Use these definitions to route information correctly:
|
|
4
|
+
|
|
5
|
+
- **Memory facts** (\`memories/facts/\`): Stable reference information — project state, technical decisions, configuration, people, system architecture. Most authoritative store for reference information.
|
|
6
|
+
- **Memory preferences** (\`memories/preferences/\`): Subjective choices with rationale — how the user wants things done, with context about why.
|
|
7
|
+
- **Memory episodic** (\`memories/episodic/\`): Date-stamped summaries of what happened — events, outcomes, and decisions tied to a specific day.
|
|
8
|
+
- **Context files** (workspace root): Concise summaries and pointers — personality (SOUL.md), user identity (USER.md), behavioral guidance (AGENTS.md). Context should reference facts rather than inlining their content.
|
|
9
|
+
|
|
10
|
+
Authority order: Memory facts > Context files. When information appears in multiple stores, the more authoritative source is correct. Context files should contain summaries and pointers, not detailed operational content.`;
|
|
11
|
+
export const CLASSIFICATION_EXAMPLES_SECTION = `## Classification Examples
|
|
12
|
+
|
|
13
|
+
Use these examples to route information correctly between facts and preferences.
|
|
14
|
+
|
|
15
|
+
### IS a preference (subjective choice about HOW the user wants things done):
|
|
16
|
+
- "I prefer concise commit messages over detailed ones" → style preference
|
|
17
|
+
- "Always run tests before pushing" → workflow preference
|
|
18
|
+
- "Use dark theme for code editors" → tooling preference
|
|
19
|
+
- "I like getting a summary first, then details on request" → communication style preference
|
|
20
|
+
- "Prefer smaller, focused PRs over large ones" → workflow preference
|
|
21
|
+
|
|
22
|
+
### NOT a preference (describes HOW SOMETHING WORKS — belongs in facts or project docs):
|
|
23
|
+
- "The payment gateway has a 2% processing fee" → financial reference data → facts
|
|
24
|
+
- "The reconciliation process runs nightly at 3am" → financial reference data → facts
|
|
25
|
+
- "Environment variable FOO must be set to BAR for the service to start" → technical specification → facts
|
|
26
|
+
- "The SDK has a 200K token context window" → technical specification → facts
|
|
27
|
+
- "The API rate limit is 100 requests per minute" → technical specification → facts
|
|
28
|
+
- "The cleanup procedure involves stopping the service, clearing /tmp, and restarting" → procedural workflow → facts
|
|
29
|
+
- "We configured nginx to proxy /api to port 8080" → system configuration record → facts
|
|
30
|
+
- "The deployment uses blue-green strategy with health checks" → system configuration record → facts
|
|
31
|
+
|
|
32
|
+
### IS a fact (stable reference information that stays true across conversations):
|
|
33
|
+
- "The CI pipeline runs on GitHub Actions" → infrastructure fact
|
|
34
|
+
- "User X is the team lead for project Y" → organizational fact
|
|
35
|
+
- "The database uses PostgreSQL 16 with async replication" → technical fact
|
|
36
|
+
- "The API rate limit is 100 requests per minute" → technical fact
|
|
37
|
+
|
|
38
|
+
### NOT a fact (belongs in episodic memory or project docs):
|
|
39
|
+
- "We debugged the payment timeout issue on 2026-05-10" → one-time event → episodic
|
|
40
|
+
- "The full architecture of system X is..." → too long for facts → project docs`;
|
|
41
|
+
export const CONTEXT_DEDUP_SECTION = `## Context File Deduplication
|
|
42
|
+
|
|
43
|
+
Before creating any new memory file, check whether the information is already covered in the foundational context files at the workspace root. These files are maintained as the authoritative source for certain categories of information.
|
|
44
|
+
|
|
45
|
+
1. Read the context files:
|
|
46
|
+
- \`$WORKSPACE/AGENTS.md\` — operational guidelines and workflow preferences
|
|
47
|
+
- \`$WORKSPACE/USER.md\` — stable identity and high-level project awareness
|
|
48
|
+
- \`$WORKSPACE/SOUL.md\` — personality and communication style
|
|
49
|
+
|
|
50
|
+
2. For each piece of information you're about to write:
|
|
51
|
+
- If the SAME information is already in one of these files, do NOT create a memory file for it — the context file is the source of truth
|
|
52
|
+
- If a context file partially covers the topic but the conversation adds genuinely new details not found there, you MAY create a file — but only for the new information, not a restatement of what's already in the context file
|
|
53
|
+
- If no context file covers the topic, proceed normally
|
|
54
|
+
|
|
55
|
+
This check prevents duplicating information across the memory system and the context files, which would create confusion about which is authoritative.`;
|
|
56
|
+
export const WORKSPACE_VALIDATION_SECTION = `## Workspace Validation
|
|
57
|
+
|
|
58
|
+
Before writing a memory that contains claims about workspace state — file paths, project structure, configuration values, implementation details — validate each claim against the actual workspace:
|
|
59
|
+
|
|
60
|
+
1. Identify verifiable claims in the memory you're about to write:
|
|
61
|
+
- References to specific files or directories (do they exist? contain what's claimed?)
|
|
62
|
+
- Configuration values (does the config file actually say that?)
|
|
63
|
+
- Project state (is the project actually in that state?)
|
|
64
|
+
|
|
65
|
+
2. Verify each claim directly: read the relevant file(s) or grep for the referenced content.
|
|
66
|
+
|
|
67
|
+
3. Only include claims you could verify:
|
|
68
|
+
- If a claim turns out to be false, omit it
|
|
69
|
+
- If ALL claims are invalid, do not create the file
|
|
70
|
+
|
|
71
|
+
Do NOT validate: subjective information, preferences, general knowledge, conversation summaries, personal details — only verifiable claims about workspace state.`;
|
|
72
|
+
export const INDEX_UPDATE_SECTION = `## Memory Index
|
|
73
|
+
|
|
74
|
+
When you create, modify, or delete a memory file, you MUST also update MEMORY.md in the same directory to keep the index in sync.
|
|
75
|
+
|
|
76
|
+
### Entry Format
|
|
77
|
+
|
|
78
|
+
Each entry in MEMORY.md follows this format:
|
|
79
|
+
|
|
80
|
+
\`\`\`
|
|
81
|
+
[Human-readable Name](./filename.md): One-line description of contents
|
|
82
|
+
\`\`\`
|
|
83
|
+
|
|
84
|
+
### Rules
|
|
85
|
+
|
|
86
|
+
- **CREATE** a new file: add a new entry with an appropriate description
|
|
87
|
+
- **MODIFY** a file: update the description if the topic, focus, or scope meaningfully changed
|
|
88
|
+
- **DELETE** a file: remove the corresponding entry
|
|
89
|
+
- Always preserve the \`# Memory Index\` header
|
|
90
|
+
- Keep descriptions concise — one line, under 80 characters
|
|
91
|
+
- The name in brackets should be a human-readable topic name (Title Case)
|
|
92
|
+
|
|
93
|
+
### Example Entries
|
|
94
|
+
|
|
95
|
+
\`\`\`
|
|
96
|
+
# Memory Index
|
|
97
|
+
|
|
98
|
+
[API Design](./api-design.md): API architecture decisions and endpoint patterns
|
|
99
|
+
[Work Info](./work-info.md): Job details, team structure, and work schedule
|
|
100
|
+
[Tech Stack](./tech-stack.md): Primary languages, frameworks, and tools used
|
|
101
|
+
\`\`\``;
|
|
102
|
+
export const INDEX_LIGHT_MAINTENANCE_SECTION = `## Memory Index Consistency
|
|
103
|
+
|
|
104
|
+
Verify index consistency between MEMORY.md and actual files in the directory.
|
|
105
|
+
|
|
106
|
+
### Steps
|
|
107
|
+
|
|
108
|
+
1. **List all files**: list all \`.md\` files in the directory (excluding \`MEMORY.md\` itself) using the ls or find tool.
|
|
109
|
+
2. **Read MEMORY.md**: Parse the existing index entries.
|
|
110
|
+
3. **Add missing entries**: For files that exist in the directory but have no entry in MEMORY.md, add a placeholder entry:
|
|
111
|
+
\`\`\`
|
|
112
|
+
[Topic](./filename.md): Description pending update
|
|
113
|
+
\`\`\`
|
|
114
|
+
4. **Remove stale entries**: For entries in MEMORY.md that reference files that no longer exist, remove those entries.
|
|
115
|
+
5. **Preserve existing descriptions**: Do NOT regenerate or modify existing descriptions — leave them unchanged even if stale. Description regeneration is handled by the weekly full rebuild.
|
|
116
|
+
|
|
117
|
+
### Rules
|
|
118
|
+
|
|
119
|
+
- Always preserve the \`# Memory Index\` header.
|
|
120
|
+
- When you create, modify, or delete memory files during this maintenance run, also update MEMORY.md per the standard index update rules (add new entries, update descriptions on meaningful changes, remove entries for deleted files).
|
|
121
|
+
- The consistency check runs in addition to your normal maintenance tasks.`;
|
|
122
|
+
export const scopeSection = (store) => `## Scope
|
|
123
|
+
|
|
124
|
+
You can read files anywhere in the workspace (needed for validation and deduplication). Only create or modify files within \`$WORKSPACE/memories/${store}/\`. You have no delete tool: when a file must go away (merged into another, obsolete, or misnamed), overwrite it with empty content — empty files are cleaned up automatically after you finish.`;
|
|
125
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/extensions/memory/prompts.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;6NASwL,CAAC;AAE9N,MAAM,CAAC,MAAM,+BAA+B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gFA6BiC,CAAC;AAEjF,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;uJAckH,CAAC;AAExJ,MAAM,CAAC,MAAM,4BAA4B,GAAG;;;;;;;;;;;;;;;kKAesH,CAAC;AAEnK,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6B7B,CAAC;AAER,MAAM,CAAC,MAAM,+BAA+B,GAAG;;;;;;;;;;;;;;;;;;;2EAmB4B,CAAC;AAE5E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAkB,EAAU,EAAE,CAAC;;mJAEuF,KAAK,mMAAmM,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ConversationTurn {
|
|
2
|
+
role: "user" | "assistant";
|
|
3
|
+
text: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Parse a pi session JSONL transcript into conversation turns. Keeps only
|
|
7
|
+
* user/assistant text — tool calls, tool results, thinking, and non-message
|
|
8
|
+
* entries are noise for memory extraction. Malformed lines are skipped.
|
|
9
|
+
*/
|
|
10
|
+
export declare const parseTranscript: (jsonl: string) => ConversationTurn[];
|
|
11
|
+
/**
|
|
12
|
+
* Render turns as a readable "role: text" conversation capped at maxChars.
|
|
13
|
+
* When over budget the newest turns win — the tail of a session carries the
|
|
14
|
+
* conclusions worth remembering.
|
|
15
|
+
*/
|
|
16
|
+
export declare const renderConversation: (turns: ConversationTurn[], maxChars: number) => string;
|
|
17
|
+
/** Read, parse, and render a transcript file. Returns "" when unreadable or empty. */
|
|
18
|
+
export declare const loadConversation: (path: string, maxChars: number) => Promise<string>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
const textOfContent = (content) => {
|
|
3
|
+
if (typeof content === "string")
|
|
4
|
+
return content;
|
|
5
|
+
return content
|
|
6
|
+
.filter((block) => block.type === "text" && block.text != null)
|
|
7
|
+
.map((block) => block.text)
|
|
8
|
+
.join("\n");
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Parse a pi session JSONL transcript into conversation turns. Keeps only
|
|
12
|
+
* user/assistant text — tool calls, tool results, thinking, and non-message
|
|
13
|
+
* entries are noise for memory extraction. Malformed lines are skipped.
|
|
14
|
+
*/
|
|
15
|
+
export const parseTranscript = (jsonl) => {
|
|
16
|
+
const turns = [];
|
|
17
|
+
for (const line of jsonl.split("\n")) {
|
|
18
|
+
if (line.trim() === "")
|
|
19
|
+
continue;
|
|
20
|
+
let entry;
|
|
21
|
+
try {
|
|
22
|
+
entry = JSON.parse(line);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (entry.type !== "message" || entry.message == null)
|
|
28
|
+
continue;
|
|
29
|
+
const { role, content } = entry.message;
|
|
30
|
+
if ((role !== "user" && role !== "assistant") || content == null)
|
|
31
|
+
continue;
|
|
32
|
+
const text = textOfContent(content).trim();
|
|
33
|
+
if (text === "")
|
|
34
|
+
continue;
|
|
35
|
+
turns.push({ role, text });
|
|
36
|
+
}
|
|
37
|
+
return turns;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Render turns as a readable "role: text" conversation capped at maxChars.
|
|
41
|
+
* When over budget the newest turns win — the tail of a session carries the
|
|
42
|
+
* conclusions worth remembering.
|
|
43
|
+
*/
|
|
44
|
+
export const renderConversation = (turns, maxChars) => {
|
|
45
|
+
const kept = [];
|
|
46
|
+
let total = 0;
|
|
47
|
+
let truncated = false;
|
|
48
|
+
for (let index = turns.length - 1; index >= 0; index -= 1) {
|
|
49
|
+
const turn = turns[index];
|
|
50
|
+
if (turn == null)
|
|
51
|
+
continue;
|
|
52
|
+
const line = `${turn.role}: ${turn.text}`;
|
|
53
|
+
if (total + line.length > maxChars) {
|
|
54
|
+
if (kept.length === 0) {
|
|
55
|
+
const budget = Math.max(0, maxChars - turn.role.length - 3);
|
|
56
|
+
kept.push(`${turn.role}: …${turn.text.slice(-budget)}`);
|
|
57
|
+
}
|
|
58
|
+
truncated = true;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
kept.push(line);
|
|
62
|
+
total += line.length + 2;
|
|
63
|
+
}
|
|
64
|
+
if (truncated)
|
|
65
|
+
kept.push("[earlier conversation truncated]");
|
|
66
|
+
return kept.reverse().join("\n\n");
|
|
67
|
+
};
|
|
68
|
+
/** Read, parse, and render a transcript file. Returns "" when unreadable or empty. */
|
|
69
|
+
export const loadConversation = async (path, maxChars) => {
|
|
70
|
+
let raw;
|
|
71
|
+
try {
|
|
72
|
+
raw = await readFile(path, "utf8");
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return "";
|
|
76
|
+
}
|
|
77
|
+
return renderConversation(parseTranscript(raw), maxChars);
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=transcript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../../../src/extensions/memory/transcript.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { NotifyPayload } from "./payload.ts";
|
|
2
|
+
/** Single notification with the source/time prefix block. */
|
|
3
|
+
export declare const formatNotification: (payload: NotifyPayload, now: Date) => string;
|
|
4
|
+
/** Combined digest for several accumulated notices. */
|
|
5
|
+
export declare const formatDigest: (items: NotifyPayload[], now: Date) => string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const formatTimestamp = (date) => `${date.toISOString().slice(0, 16).replace("T", " ")} UTC`;
|
|
2
|
+
/** Single notification with the source/time prefix block. */
|
|
3
|
+
export const formatNotification = (payload, now) => {
|
|
4
|
+
const body = payload.title != null ? `${payload.title}\n\n${payload.text}` : payload.text;
|
|
5
|
+
return `--- Notification ---\nSource: ${payload.source}\nTime: ${formatTimestamp(now)}\n\n${body}`;
|
|
6
|
+
};
|
|
7
|
+
/** Combined digest for several accumulated notices. */
|
|
8
|
+
export const formatDigest = (items, now) => {
|
|
9
|
+
const parts = [`--- Notifications digest ---\nTime: ${formatTimestamp(now)}`, ""];
|
|
10
|
+
items.forEach((item, index) => {
|
|
11
|
+
parts.push(`— Item ${index + 1} (${item.severity}, source: ${item.source}) —`);
|
|
12
|
+
parts.push(item.title != null ? `${item.title}\n${item.text}` : item.text);
|
|
13
|
+
parts.push("");
|
|
14
|
+
});
|
|
15
|
+
return parts.join("\n");
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=format.js.map
|