chapterhouse 0.13.1 → 0.14.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.
Files changed (132) hide show
  1. package/dist/api/route-coverage.test.js +1 -3
  2. package/dist/api/server.js +0 -2
  3. package/dist/api/server.test.js +0 -281
  4. package/dist/config.js +3 -85
  5. package/dist/config.test.js +5 -123
  6. package/dist/copilot/agents.js +13 -10
  7. package/dist/copilot/agents.test.js +10 -11
  8. package/dist/copilot/memory-coordinator.js +12 -227
  9. package/dist/copilot/memory-coordinator.test.js +31 -250
  10. package/dist/copilot/orchestrator.js +8 -66
  11. package/dist/copilot/orchestrator.test.js +9 -467
  12. package/dist/copilot/skills.js +15 -1
  13. package/dist/copilot/system-message.js +9 -15
  14. package/dist/copilot/system-message.test.js +9 -22
  15. package/dist/copilot/tools/index.js +3 -3
  16. package/dist/copilot/tools-deps.js +1 -1
  17. package/dist/copilot/tools.agent.test.js +6 -0
  18. package/dist/copilot/tools.inventory.test.js +1 -14
  19. package/dist/daemon.js +7 -9
  20. package/dist/memory/assets.js +33 -0
  21. package/dist/memory/domains.js +58 -0
  22. package/dist/memory/domains.test.js +47 -0
  23. package/dist/memory/git.js +66 -0
  24. package/dist/memory/git.test.js +32 -0
  25. package/dist/memory/history.js +19 -0
  26. package/dist/memory/hottier.js +32 -0
  27. package/dist/memory/hottier.test.js +33 -0
  28. package/dist/memory/index.js +5 -13
  29. package/dist/memory/instructions.js +17 -0
  30. package/dist/memory/manager.js +92 -0
  31. package/dist/memory/markdown.js +78 -0
  32. package/dist/memory/markdown.test.js +42 -0
  33. package/dist/memory/mutex.js +18 -0
  34. package/dist/memory/path-guard.js +26 -0
  35. package/dist/memory/path-guard.test.js +27 -0
  36. package/dist/memory/paths.js +12 -0
  37. package/dist/memory/reconcile.js +75 -0
  38. package/dist/memory/reconcile.test.js +50 -0
  39. package/dist/memory/scaffold.js +37 -0
  40. package/dist/memory/scaffold.test.js +52 -0
  41. package/dist/memory/tools/commit-wrapper.js +32 -0
  42. package/dist/memory/tools/domains.js +73 -0
  43. package/dist/memory/tools/domains.test.js +66 -0
  44. package/dist/memory/tools/git.js +52 -0
  45. package/dist/memory/tools/index.js +25 -0
  46. package/dist/memory/tools/read.js +101 -0
  47. package/dist/memory/tools/read.test.js +69 -0
  48. package/dist/memory/tools/search.js +103 -0
  49. package/dist/memory/tools/search.test.js +63 -0
  50. package/dist/memory/tools/sessions.js +45 -0
  51. package/dist/memory/tools/sessions.test.js +74 -0
  52. package/dist/memory/tools/shared.js +7 -0
  53. package/dist/memory/tools/write.js +116 -0
  54. package/dist/memory/tools/write.test.js +107 -0
  55. package/dist/memory/walk.js +39 -0
  56. package/dist/store/repositories/sessions.js +40 -0
  57. package/dist/wiki/consolidation.js +3 -31
  58. package/dist/wiki/consolidation.test.js +0 -19
  59. package/memory-assets/domain-skill.md +38 -0
  60. package/memory-assets/seed/cog-meta/improvements.md +8 -0
  61. package/memory-assets/seed/cog-meta/patterns.md +5 -0
  62. package/memory-assets/seed/cog-meta/reflect-cursor.md +4 -0
  63. package/memory-assets/seed/cog-meta/scenario-calibration.md +14 -0
  64. package/memory-assets/seed/cog-meta/self-observations.md +4 -0
  65. package/memory-assets/seed/domains.yml +19 -0
  66. package/memory-assets/seed/glacier/index.md +6 -0
  67. package/memory-assets/seed/hot-memory.md +5 -0
  68. package/memory-assets/seed/link-index.md +6 -0
  69. package/memory-assets/system-instructions.md +214 -0
  70. package/memory-assets/templates/action-items.md +8 -0
  71. package/memory-assets/templates/entities.md +4 -0
  72. package/memory-assets/templates/generic.md +2 -0
  73. package/memory-assets/templates/hot-memory.md +4 -0
  74. package/memory-assets/templates/observations.md +4 -0
  75. package/package.json +2 -1
  76. package/skills/system/evolve/SKILL.md +131 -0
  77. package/skills/system/foresight/SKILL.md +116 -0
  78. package/skills/system/history/SKILL.md +58 -0
  79. package/skills/system/housekeeping/SKILL.md +185 -0
  80. package/skills/system/reflect/SKILL.md +214 -0
  81. package/skills/system/scenario/SKILL.md +198 -0
  82. package/skills/system/setup/SKILL.md +113 -0
  83. package/web/dist/assets/{WikiEdit-CGRxNazp.js → WikiEdit-BTsiBfbC.js} +2 -2
  84. package/web/dist/assets/{WikiEdit-CGRxNazp.js.map → WikiEdit-BTsiBfbC.js.map} +1 -1
  85. package/web/dist/assets/{WikiGraph-eVWNhZS3.js → WikiGraph-COOZbUeH.js} +2 -2
  86. package/web/dist/assets/{WikiGraph-eVWNhZS3.js.map → WikiGraph-COOZbUeH.js.map} +1 -1
  87. package/web/dist/assets/{index-gAvLNEvJ.js → index-aCcfpaLM.js} +101 -101
  88. package/web/dist/assets/index-aCcfpaLM.js.map +1 -0
  89. package/web/dist/index.html +1 -1
  90. package/dist/api/routes/memory.js +0 -475
  91. package/dist/api/routes/memory.test.js +0 -108
  92. package/dist/copilot/tools/memory.js +0 -678
  93. package/dist/copilot/tools.memory.test.js +0 -590
  94. package/dist/memory/action-items.js +0 -100
  95. package/dist/memory/action-items.test.js +0 -83
  96. package/dist/memory/active-scope.js +0 -78
  97. package/dist/memory/active-scope.test.js +0 -80
  98. package/dist/memory/checkpoint-prompt.js +0 -71
  99. package/dist/memory/checkpoint.js +0 -274
  100. package/dist/memory/checkpoint.test.js +0 -275
  101. package/dist/memory/decisions.js +0 -54
  102. package/dist/memory/decisions.test.js +0 -92
  103. package/dist/memory/entities.js +0 -70
  104. package/dist/memory/entities.test.js +0 -65
  105. package/dist/memory/eot.js +0 -459
  106. package/dist/memory/eot.test.js +0 -949
  107. package/dist/memory/hooks.js +0 -149
  108. package/dist/memory/hooks.test.js +0 -325
  109. package/dist/memory/hot-tier.js +0 -283
  110. package/dist/memory/hot-tier.test.js +0 -275
  111. package/dist/memory/housekeeping-scheduler.js +0 -187
  112. package/dist/memory/housekeeping-scheduler.test.js +0 -236
  113. package/dist/memory/housekeeping.js +0 -497
  114. package/dist/memory/housekeeping.test.js +0 -410
  115. package/dist/memory/inbox.js +0 -83
  116. package/dist/memory/inbox.test.js +0 -178
  117. package/dist/memory/migration.js +0 -244
  118. package/dist/memory/migration.test.js +0 -108
  119. package/dist/memory/observations.js +0 -46
  120. package/dist/memory/observations.test.js +0 -86
  121. package/dist/memory/recall.js +0 -269
  122. package/dist/memory/recall.test.js +0 -265
  123. package/dist/memory/reflect.js +0 -273
  124. package/dist/memory/reflect.test.js +0 -256
  125. package/dist/memory/scope-lock.js +0 -26
  126. package/dist/memory/scope-lock.test.js +0 -118
  127. package/dist/memory/scopes.js +0 -89
  128. package/dist/memory/scopes.test.js +0 -176
  129. package/dist/memory/tiering.js +0 -223
  130. package/dist/memory/tiering.test.js +0 -323
  131. package/dist/memory/types.js +0 -2
  132. package/web/dist/assets/index-gAvLNEvJ.js.map +0 -1
@@ -1,678 +0,0 @@
1
- import { defineTool } from "@github/copilot-sdk";
2
- import { z } from "zod";
3
- import { getDb } from "../../store/db.js";
4
- import { appendTimeline } from "../../wiki/timeline.js";
5
- import { topicPagePath } from "../../wiki/topic-structure.js";
6
- import { childLogger } from "../../util/logger.js";
7
- import { getAgent, loadAgents, agentsModule } from "../tools-deps.js";
8
- import { getCurrentSessionKey, invalidateOrchestratorSession, maybeScheduleScopeChangeCheckpoint, resetCheckpointSessionState, } from "../tools-deps.js";
9
- import { getActiveScope as getMemoryActiveScope, createScope as createMemoryScope, getScope as getMemoryScope, inferScopeFromText, completeActionItem, demoteToCold, demoteToWarm, dropActionItem, queueMemoryProposal, recall as recallMemory, listActionItems, recordDecision, recordActionItem, recordObservation, runHousekeeping, reflectOnScope, reflectAllScopes, setActiveScope as setMemoryActiveScope, snoozeActionItem, promoteToHot, upsertEntity, hookDispatcher, } from "../../memory/index.js";
10
- const log = childLogger("tools");
11
- function requireOrchestratorMemoryWrite() {
12
- const agentSlug = agentsModule.getCurrentToolAgentSlug?.();
13
- if (agentSlug && agentSlug !== "chapterhouse") {
14
- return "Memory writes are orchestrator-only. Use memory_propose instead.";
15
- }
16
- return null;
17
- }
18
- function resolveProposalScopeSlug(requestedScopeSlug) {
19
- if (requestedScopeSlug) {
20
- return requestedScopeSlug;
21
- }
22
- const agentSlug = agentsModule.getCurrentToolAgentSlug?.();
23
- if (!agentSlug || agentSlug === "chapterhouse") {
24
- return getMemoryActiveScope()?.slug;
25
- }
26
- const agent = getAgent(agentSlug);
27
- const boundScope = agent?.scope ?? loadAgents().find((entry) => entry.slug === agentSlug)?.scope;
28
- if (boundScope && getMemoryScope(boundScope)) {
29
- return boundScope;
30
- }
31
- return getMemoryActiveScope()?.slug;
32
- }
33
- function resolveMemoryScopeForWrite(explicitScope, content) {
34
- const explicit = explicitScope ? getMemoryScope(explicitScope) : undefined;
35
- if (explicitScope && !explicit) {
36
- throw new Error(`Unknown memory scope '${explicitScope}'.`);
37
- }
38
- if (explicit) {
39
- return { scopeId: explicit.id, scopeSlug: explicit.slug };
40
- }
41
- const active = getMemoryActiveScope();
42
- if (active) {
43
- return { scopeId: active.id, scopeSlug: active.slug };
44
- }
45
- const inferred = inferScopeFromText(content);
46
- if (inferred) {
47
- const inferredScope = getMemoryScope(inferred.scope_id);
48
- if (inferredScope) {
49
- return { scopeId: inferredScope.id, scopeSlug: inferredScope.slug };
50
- }
51
- }
52
- const validScopes = getDb().prepare(`
53
- SELECT slug
54
- FROM mem_scopes
55
- WHERE active = 1
56
- ORDER BY slug
57
- `).all();
58
- const activeScope = getMemoryActiveScope()?.slug ?? "none";
59
- throw new Error(`No scope inferred. Active scope: ${activeScope}. Valid scopes: [${validScopes.map((row) => row.slug).join(", ")}]. `
60
- + "Set active scope with memory_set_scope or pass scope explicitly.");
61
- }
62
- const observationProposalPayloadSchema = z.object({
63
- content: z.string(),
64
- entity_id: z.number().int().positive().optional(),
65
- source: z.string().optional(),
66
- });
67
- const decisionProposalPayloadSchema = z.object({
68
- title: z.string(),
69
- rationale: z.string().optional(),
70
- decided_at: z.string().optional(),
71
- });
72
- const entityProposalPayloadSchema = z.object({
73
- name: z.string(),
74
- entity_kind: z.string().optional(),
75
- kind: z.string().optional(),
76
- summary: z.string().optional(),
77
- }).superRefine((value, context) => {
78
- if (!value.entity_kind && !value.kind) {
79
- context.addIssue({
80
- code: z.ZodIssueCode.custom,
81
- message: "entity_kind is required for entity proposals.",
82
- path: ["entity_kind"],
83
- });
84
- }
85
- }).transform((value) => ({
86
- name: value.name,
87
- entity_kind: value.entity_kind ?? value.kind,
88
- summary: value.summary,
89
- }));
90
- const actionItemProposalPayloadSchema = z.object({
91
- title: z.string().trim().min(1, "title is required for action_item proposals."),
92
- detail: z.string().optional(),
93
- due_at: z.string().optional(),
94
- source: z.string().optional(),
95
- entity_id: z.number().int().positive().optional(),
96
- entity_name: z.string().trim().min(1, "entity_name must be non-empty when provided.").optional(),
97
- entity_kind: z.string().trim().min(1, "entity_kind must be non-empty when provided.").optional(),
98
- }).superRefine((value, context) => {
99
- if ((value.entity_name && !value.entity_kind) || (!value.entity_name && value.entity_kind)) {
100
- context.addIssue({
101
- code: z.ZodIssueCode.custom,
102
- message: "entity_name and entity_kind must be provided together for action_item proposals.",
103
- path: ["entity_name"],
104
- });
105
- }
106
- if (value.entity_id !== undefined && value.entity_name) {
107
- context.addIssue({
108
- code: z.ZodIssueCode.custom,
109
- message: "Provide either entity_id or entity_name/entity_kind for action_item proposals, not both.",
110
- path: ["entity_id"],
111
- });
112
- }
113
- });
114
- const memoryProposeArgsSchema = z.object({
115
- kind: z.enum(["observation", "decision", "entity", "action_item"]),
116
- scope_slug: z.string().optional(),
117
- payload: z.record(z.string(), z.unknown()),
118
- confidence: z.number().min(0).max(1).optional(),
119
- reason: z.string().optional(),
120
- }).superRefine((value, context) => {
121
- const schema = value.kind === "observation"
122
- ? observationProposalPayloadSchema
123
- : value.kind === "decision"
124
- ? decisionProposalPayloadSchema
125
- : value.kind === "entity"
126
- ? entityProposalPayloadSchema
127
- : actionItemProposalPayloadSchema;
128
- const parsed = schema.safeParse(value.payload);
129
- if (!parsed.success) {
130
- for (const issue of parsed.error.issues) {
131
- context.addIssue({
132
- code: z.ZodIssueCode.custom,
133
- message: issue.message,
134
- path: ["payload", ...issue.path],
135
- });
136
- }
137
- }
138
- });
139
- const memoryTierTableSchema = z.enum(["observation", "decision", "entity", "action_item"]);
140
- export function createMemoryTools(_deps) {
141
- return [
142
- defineTool("memory_remember", {
143
- description: "Write scoped agent memory (observation or decision) into the SQLite memory store. " +
144
- "Use this for the new agent-memory system, not the legacy wiki-backed remember tool.",
145
- parameters: z.object({
146
- content: z.string().describe("Observation content or decision rationale."),
147
- scope: z.string().optional().describe("Optional memory scope slug. Defaults to active scope, then keyword inference."),
148
- kind: z.enum(["observation", "decision"]).optional().describe("Memory entry kind. Defaults to observation."),
149
- entity_name: z.string().optional().describe("Optional entity name to attach. Auto-upserts the entity if provided."),
150
- entity_kind: z.string().optional().describe("Required when entity_name is provided."),
151
- title: z.string().optional().describe("Required for decision entries."),
152
- decided_at: z.string().optional().describe("Decision date. Defaults to today."),
153
- tier: z.enum(["hot", "warm", "cold"]).optional().describe("Storage tier. Defaults to warm."),
154
- }),
155
- handler: async (args) => {
156
- const denied = requireOrchestratorMemoryWrite();
157
- if (denied)
158
- return denied;
159
- if (args.entity_name && !args.entity_kind) {
160
- return "entity_kind is required when entity_name is provided.";
161
- }
162
- try {
163
- const { scopeId, scopeSlug } = resolveMemoryScopeForWrite(args.scope, args.content);
164
- const kind = args.kind ?? "observation";
165
- const entity = args.entity_name
166
- ? upsertEntity({
167
- scope_id: scopeId,
168
- kind: args.entity_kind,
169
- name: args.entity_name,
170
- tier: args.tier ?? "warm",
171
- })
172
- : undefined;
173
- if (kind === "decision") {
174
- if (!args.title) {
175
- return "title is required when kind='decision'.";
176
- }
177
- const decision = recordDecision({
178
- scope_id: scopeId,
179
- entity_id: entity?.id,
180
- title: args.title,
181
- rationale: args.content,
182
- decided_at: args.decided_at ?? new Date().toISOString().slice(0, 10),
183
- tier: args.tier ?? "warm",
184
- });
185
- if (entity) {
186
- appendTimeline(topicPagePath(entity.kind, entity.name), `${decision.title}\n\n${decision.rationale}`);
187
- }
188
- hookDispatcher.dispatch("memory:decision", {
189
- id: decision.id,
190
- scope_id: scopeId,
191
- title: decision.title,
192
- rationale: decision.rationale,
193
- }).catch((err) => {
194
- log.error({ err }, "memory.hooks.decision.dispatch_error");
195
- });
196
- return {
197
- ok: true,
198
- id: decision.id,
199
- scope: scopeSlug,
200
- kind,
201
- entity_id: entity?.id,
202
- };
203
- }
204
- const observation = recordObservation({
205
- scope_id: scopeId,
206
- entity_id: entity?.id,
207
- content: args.content,
208
- source: `agent:${agentsModule.getCurrentToolAgentSlug?.() ?? "chapterhouse"}`,
209
- tier: args.tier ?? "warm",
210
- });
211
- return {
212
- ok: true,
213
- id: observation.id,
214
- scope: scopeSlug,
215
- kind,
216
- entity_id: entity?.id,
217
- };
218
- }
219
- catch (err) {
220
- return err instanceof Error ? err.message : String(err);
221
- }
222
- },
223
- }),
224
- defineTool("memory_propose", {
225
- description: "Queue a proposed scoped memory item for orchestrator review at end-of-task. " +
226
- "Available to all agents; writes land in mem_inbox as pending proposals.",
227
- parameters: memoryProposeArgsSchema,
228
- handler: async (args) => {
229
- try {
230
- const parsedArgs = memoryProposeArgsSchema.parse(args);
231
- const payload = parsedArgs.kind === "observation"
232
- ? observationProposalPayloadSchema.parse(parsedArgs.payload)
233
- : parsedArgs.kind === "decision"
234
- ? decisionProposalPayloadSchema.parse(parsedArgs.payload)
235
- : parsedArgs.kind === "entity"
236
- ? entityProposalPayloadSchema.parse(parsedArgs.payload)
237
- : actionItemProposalPayloadSchema.parse(parsedArgs.payload);
238
- const proposal = queueMemoryProposal({
239
- kind: parsedArgs.kind,
240
- scopeSlug: resolveProposalScopeSlug(parsedArgs.scope_slug),
241
- payload,
242
- confidence: parsedArgs.confidence ?? 0.5,
243
- reason: parsedArgs.reason,
244
- sourceAgent: agentsModule.getCurrentToolAgentSlug?.() ?? "chapterhouse",
245
- sourceTaskId: agentsModule.getCurrentToolTaskId?.(),
246
- });
247
- return {
248
- proposal_id: proposal.id,
249
- status: "queued",
250
- };
251
- }
252
- catch (err) {
253
- if (err instanceof z.ZodError) {
254
- return err.issues.map((issue) => issue.message).join("; ");
255
- }
256
- return err instanceof Error ? err.message : String(err);
257
- }
258
- },
259
- }),
260
- defineTool("memory_create_scope", {
261
- description: "Create a new user-defined memory scope. Slugs must be unique kebab-case; baseline installs only include global and chapterhouse.",
262
- parameters: z.object({
263
- slug: z.string()
264
- .trim()
265
- .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "slug must be unique kebab-case"),
266
- title: z.string().trim().min(1, "title is required"),
267
- description: z.string().optional(),
268
- }),
269
- handler: async (args) => {
270
- const denied = requireOrchestratorMemoryWrite();
271
- if (denied)
272
- return denied;
273
- const parsed = z.object({
274
- slug: z.string()
275
- .trim()
276
- .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "slug must be unique kebab-case"),
277
- title: z.string().trim().min(1, "title is required"),
278
- description: z.string().optional(),
279
- }).safeParse(args);
280
- if (!parsed.success) {
281
- return parsed.error.issues.map((issue) => issue.message).join("; ");
282
- }
283
- try {
284
- if (getMemoryScope(parsed.data.slug)) {
285
- return `Memory scope '${parsed.data.slug}' already exists.`;
286
- }
287
- const scope = createMemoryScope({
288
- slug: parsed.data.slug,
289
- title: parsed.data.title,
290
- description: parsed.data.description ?? "",
291
- keywords: [parsed.data.slug],
292
- });
293
- hookDispatcher.dispatch("scope:created", {
294
- slug: scope.slug,
295
- title: scope.title,
296
- description: scope.description,
297
- }).catch((err) => {
298
- log.error({ err }, "memory.hooks.scope_created.dispatch_error");
299
- });
300
- return {
301
- ok: true,
302
- scope: {
303
- slug: scope.slug,
304
- title: scope.title,
305
- description: scope.description,
306
- active: scope.active,
307
- },
308
- };
309
- }
310
- catch (err) {
311
- return err instanceof Error ? err.message : String(err);
312
- }
313
- },
314
- }),
315
- defineTool("memory_add_action_item", {
316
- description: "Add a scoped memory action item/reminder. Orchestrator-only write tool for follow-ups and proactive reminders.",
317
- parameters: z.object({
318
- scope: z.string().optional().describe("Optional memory scope slug. Defaults to active scope, then keyword inference."),
319
- title: z.string().min(1).describe("Short action item title."),
320
- detail: z.string().optional().describe("Longer action item detail."),
321
- due_at: z.string().optional().describe("Optional ISO due timestamp."),
322
- entity_name: z.string().optional().describe("Optional entity name to attach. Auto-upserts the entity if provided."),
323
- entity_kind: z.string().optional().describe("Required when entity_name is provided."),
324
- source: z.string().optional().describe("Action item source, e.g. manual, subagent_proposal, external."),
325
- }),
326
- handler: async (args) => {
327
- const denied = requireOrchestratorMemoryWrite();
328
- if (denied)
329
- return denied;
330
- if (args.entity_name && !args.entity_kind) {
331
- return "entity_kind is required when entity_name is provided.";
332
- }
333
- try {
334
- const { scopeId, scopeSlug } = resolveMemoryScopeForWrite(args.scope, `${args.title}\n${args.detail ?? ""}`);
335
- const entity = args.entity_name
336
- ? upsertEntity({
337
- scope_id: scopeId,
338
- kind: args.entity_kind,
339
- name: args.entity_name,
340
- })
341
- : undefined;
342
- const actionItem = recordActionItem({
343
- scope_id: scopeId,
344
- entity_id: entity?.id,
345
- title: args.title,
346
- detail: args.detail,
347
- due_at: args.due_at,
348
- source: args.source ?? "manual",
349
- });
350
- return {
351
- ok: true,
352
- id: actionItem.id,
353
- scope: scopeSlug,
354
- status: actionItem.status,
355
- entity_id: entity?.id,
356
- };
357
- }
358
- catch (err) {
359
- return err instanceof Error ? err.message : String(err);
360
- }
361
- },
362
- }),
363
- defineTool("memory_complete_action_item", {
364
- description: "Complete a memory action item. Orchestrator-only write tool.",
365
- parameters: z.object({
366
- id: z.number().int().positive(),
367
- resolution_reason: z.string().optional(),
368
- }),
369
- handler: async (args) => {
370
- const denied = requireOrchestratorMemoryWrite();
371
- if (denied)
372
- return denied;
373
- try {
374
- const actionItem = completeActionItem(args.id, args.resolution_reason);
375
- return { ok: true, id: actionItem.id, status: actionItem.status, resolved_at: actionItem.resolvedAt };
376
- }
377
- catch (err) {
378
- return err instanceof Error ? err.message : String(err);
379
- }
380
- },
381
- }),
382
- defineTool("memory_drop_action_item", {
383
- description: "Drop a memory action item with a reason. Orchestrator-only write tool.",
384
- parameters: z.object({
385
- id: z.number().int().positive(),
386
- reason: z.string().min(1),
387
- }),
388
- handler: async (args) => {
389
- const denied = requireOrchestratorMemoryWrite();
390
- if (denied)
391
- return denied;
392
- try {
393
- const actionItem = dropActionItem(args.id, args.reason);
394
- return { ok: true, id: actionItem.id, status: actionItem.status, resolved_at: actionItem.resolvedAt };
395
- }
396
- catch (err) {
397
- return err instanceof Error ? err.message : String(err);
398
- }
399
- },
400
- }),
401
- defineTool("memory_snooze_action_item", {
402
- description: "Snooze a memory action item until an ISO timestamp. Orchestrator-only write tool.",
403
- parameters: z.object({
404
- id: z.number().int().positive(),
405
- snooze_until: z.string().min(1),
406
- }),
407
- handler: async (args) => {
408
- const denied = requireOrchestratorMemoryWrite();
409
- if (denied)
410
- return denied;
411
- try {
412
- const actionItem = snoozeActionItem(args.id, args.snooze_until);
413
- return {
414
- ok: true,
415
- id: actionItem.id,
416
- status: actionItem.status,
417
- snooze_until: actionItem.snoozeUntil,
418
- };
419
- }
420
- catch (err) {
421
- return err instanceof Error ? err.message : String(err);
422
- }
423
- },
424
- }),
425
- defineTool("memory_list_action_items", {
426
- description: "List scoped memory action items/reminders. Defaults to currently actionable open items.",
427
- parameters: z.object({
428
- scope: z.string().optional().describe("Optional memory scope slug. Defaults to active scope when available."),
429
- status: z.enum(["open", "done", "dropped", "snoozed"]).optional().describe("Optional status filter."),
430
- due_before: z.string().optional().describe("Optional ISO timestamp; only include items due at or before this time."),
431
- includeArchived: z.boolean().optional().describe("Include cold-tier items. Defaults to false."),
432
- }),
433
- handler: async (args) => {
434
- const requestedScope = args.scope ? getMemoryScope(args.scope) : undefined;
435
- if (args.scope && !requestedScope) {
436
- return `Unknown memory scope '${args.scope}'.`;
437
- }
438
- const activeScope = getMemoryActiveScope();
439
- const scope = requestedScope ?? activeScope ?? undefined;
440
- const actionItems = listActionItems({
441
- scope_id: scope?.id,
442
- status: args.status,
443
- due_before: args.due_before,
444
- includeArchived: args.includeArchived,
445
- });
446
- return {
447
- active_scope: activeScope ? { slug: activeScope.slug, title: activeScope.title } : null,
448
- scope: scope ? { slug: scope.slug, title: scope.title } : null,
449
- action_items: actionItems.map((item) => ({
450
- id: item.id,
451
- scope_id: item.scopeId,
452
- entity_id: item.entityId,
453
- title: item.title,
454
- detail: item.detail,
455
- status: item.status,
456
- due_at: item.dueAt,
457
- snooze_until: item.snoozeUntil,
458
- source: item.source,
459
- created_at: item.createdAt,
460
- updated_at: item.updatedAt,
461
- resolved_at: item.resolvedAt,
462
- resolution_reason: item.resolutionReason,
463
- })),
464
- };
465
- },
466
- }),
467
- defineTool("memory_recall", {
468
- description: "Search scoped agent memory with FTS-backed recall. Use this for the new agent-memory store, not the wiki-backed recall tool.",
469
- parameters: z.object({
470
- query: z.string().describe("Query text to search for."),
471
- scope: z.string().optional().describe("Optional scope slug. Defaults to the active scope when available."),
472
- kinds: z.array(z.enum(["observation", "decision", "entity", "action_item"])).optional()
473
- .describe("Optional filter for memory entry kinds."),
474
- limit: z.number().int().positive().optional().describe("Maximum number of ranked hits to return. Defaults to 10."),
475
- includeSuperseded: z.boolean().optional().describe("Include superseded observations and decisions. Defaults to false."),
476
- includeArchived: z.boolean().optional().describe("Include archived observations and decisions. Defaults to false."),
477
- includeCold: z.boolean().optional().describe("Include cold-tier rows. Defaults to false."),
478
- }),
479
- handler: async (args) => {
480
- const requestedScope = args.scope ? getMemoryScope(args.scope) : undefined;
481
- if (args.scope && !requestedScope) {
482
- return `Unknown memory scope '${args.scope}'.`;
483
- }
484
- const result = recallMemory({
485
- query: args.query,
486
- scope_id: requestedScope?.id,
487
- kinds: args.kinds,
488
- limit: args.limit ?? 10,
489
- includeSuperseded: args.includeSuperseded,
490
- includeArchived: args.includeArchived,
491
- includeCold: args.includeCold,
492
- });
493
- return {
494
- active_scope: result.activeScope
495
- ? { slug: result.activeScope.slug, title: result.activeScope.title }
496
- : null,
497
- hot_tier: result.hotTier,
498
- hits: result.hits.map((hit) => ({
499
- kind: hit.kind,
500
- id: hit.id,
501
- scope: hit.scope,
502
- content: hit.content,
503
- decided_at: hit.decidedAt,
504
- score: hit.score,
505
- snippet: hit.snippet,
506
- })),
507
- };
508
- },
509
- }),
510
- defineTool("memory_housekeep", {
511
- description: "Run the scoped agent-memory housekeeping pipeline. Orchestrator-only write-tier maintenance tool.",
512
- parameters: z.object({
513
- scope_slug: z.string().optional().describe("Optional scope slug. Defaults to the active scope."),
514
- all_scopes: z.boolean().optional().describe("Run scoped passes for all active scopes instead of one scope."),
515
- passes: z.array(z.string()).optional().describe("Optional pass names: dedup_observations, dedup_decisions, orphan_cleanup, decay, compact_inbox."),
516
- }),
517
- handler: async (args) => {
518
- const denied = requireOrchestratorMemoryWrite();
519
- if (denied)
520
- return denied;
521
- if (args.scope_slug && args.all_scopes) {
522
- return "Pass either scope_slug or all_scopes, not both.";
523
- }
524
- try {
525
- const requestedScope = args.scope_slug ? getMemoryScope(args.scope_slug) : undefined;
526
- if (args.scope_slug && !requestedScope) {
527
- return `Unknown memory scope '${args.scope_slug}'.`;
528
- }
529
- const result = await runHousekeeping({
530
- scopeIds: requestedScope ? [requestedScope.id] : undefined,
531
- allScopes: args.all_scopes,
532
- passes: args.passes,
533
- });
534
- return {
535
- ok: result.summaries.every((summary) => summary.errors.length === 0),
536
- scope_ids: result.scopeIds,
537
- total_examined: result.totalExamined,
538
- total_modified: result.totalModified,
539
- duration_ms: result.durationMs,
540
- summaries: result.summaries,
541
- };
542
- }
543
- catch (err) {
544
- return err instanceof Error ? err.message : String(err);
545
- }
546
- },
547
- }),
548
- defineTool("memory_reflect", {
549
- description: "Synthesize durable scoped memory patterns from repeated observations. Orchestrator-only reflect tool.",
550
- parameters: z.object({
551
- scope: z.string().optional(),
552
- }),
553
- handler: async (args) => {
554
- const denied = requireOrchestratorMemoryWrite();
555
- if (denied)
556
- return denied;
557
- try {
558
- if (args.scope) {
559
- const requestedScope = getMemoryScope(args.scope);
560
- if (!requestedScope) {
561
- return `Unknown memory scope '${args.scope}'.`;
562
- }
563
- const result = await reflectOnScope(args.scope, getDb());
564
- return {
565
- ok: true,
566
- scope: args.scope,
567
- patterns_created: result.patternsCreated,
568
- patterns_updated: result.patternsUpdated,
569
- contradictions_found: result.contradictionsFound,
570
- };
571
- }
572
- const results = await reflectAllScopes(getDb());
573
- const totals = Object.values(results).reduce((acc, result) => ({
574
- patterns_created: acc.patterns_created + result.patternsCreated,
575
- patterns_updated: acc.patterns_updated + result.patternsUpdated,
576
- contradictions_found: acc.contradictions_found + result.contradictionsFound,
577
- }), {
578
- patterns_created: 0,
579
- patterns_updated: 0,
580
- contradictions_found: 0,
581
- });
582
- return {
583
- ok: true,
584
- scope: "all",
585
- ...totals,
586
- };
587
- }
588
- catch (err) {
589
- return err instanceof Error ? err.message : String(err);
590
- }
591
- },
592
- }),
593
- defineTool("memory_promote", {
594
- description: "Promote a memory row to the hot tier. Orchestrator-only manual override.",
595
- parameters: z.object({
596
- table: memoryTierTableSchema,
597
- id: z.number().int().positive(),
598
- reason: z.string().min(1),
599
- }),
600
- handler: async (args) => {
601
- const denied = requireOrchestratorMemoryWrite();
602
- if (denied)
603
- return denied;
604
- try {
605
- promoteToHot(args.table, args.id, args.reason);
606
- return { ok: true, table: args.table, id: args.id, tier: "hot" };
607
- }
608
- catch (err) {
609
- return err instanceof Error ? err.message : String(err);
610
- }
611
- },
612
- }),
613
- defineTool("memory_demote", {
614
- description: "Demote a memory row to warm or cold tier. Orchestrator-only manual override.",
615
- parameters: z.object({
616
- table: memoryTierTableSchema,
617
- id: z.number().int().positive(),
618
- reason: z.string().min(1),
619
- tier: z.enum(["warm", "cold"]).optional().describe("Target demotion tier. Defaults to warm."),
620
- }),
621
- handler: async (args) => {
622
- const denied = requireOrchestratorMemoryWrite();
623
- if (denied)
624
- return denied;
625
- try {
626
- if (args.tier === "cold") {
627
- demoteToCold(args.table, args.id, args.reason);
628
- return { ok: true, table: args.table, id: args.id, tier: "cold" };
629
- }
630
- demoteToWarm(args.table, args.id, args.reason);
631
- return { ok: true, table: args.table, id: args.id, tier: "warm" };
632
- }
633
- catch (err) {
634
- return err instanceof Error ? err.message : String(err);
635
- }
636
- },
637
- }),
638
- defineTool("memory_set_scope", {
639
- description: "Set or clear the active scope for the agent-memory system. This affects default routing for memory_remember and memory_recall.",
640
- parameters: z.object({
641
- slug: z.string().nullable().describe("Scope slug to activate, or null to clear the active scope."),
642
- }),
643
- handler: async (args) => {
644
- const denied = requireOrchestratorMemoryWrite();
645
- if (denied)
646
- return denied;
647
- try {
648
- const previousScope = getMemoryActiveScope();
649
- const nextScope = args.slug === null ? null : (getMemoryScope(args.slug) ?? null);
650
- if (args.slug !== null && !nextScope) {
651
- return `Unknown memory scope '${args.slug}'.`;
652
- }
653
- const previousSlug = previousScope?.slug ?? null;
654
- const nextSlug = nextScope?.slug ?? null;
655
- const didChange = previousSlug !== nextSlug;
656
- const sessionKey = getCurrentSessionKey();
657
- if (didChange) {
658
- maybeScheduleScopeChangeCheckpoint(sessionKey, previousScope, nextScope);
659
- }
660
- const activeScope = setMemoryActiveScope(args.slug);
661
- if (didChange) {
662
- invalidateOrchestratorSession(sessionKey);
663
- resetCheckpointSessionState(sessionKey);
664
- }
665
- return {
666
- active_scope: activeScope
667
- ? { slug: activeScope.slug, title: activeScope.title }
668
- : null,
669
- };
670
- }
671
- catch (err) {
672
- return err instanceof Error ? err.message : String(err);
673
- }
674
- },
675
- }),
676
- ];
677
- }
678
- //# sourceMappingURL=memory.js.map