add-coder 0.3.34 → 0.3.35

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 (147) hide show
  1. package/dist/index.js +21 -3
  2. package/package.json +3 -3
  3. package/templates/.add-coder-src-hash.json +144 -90
  4. package/templates/adapters/claude/hooks/doc-format-guard.mjs +172 -88
  5. package/templates/adapters/claude/hooks/notification.mjs +0 -4
  6. package/templates/adapters/claude/hooks/permission-denied.mjs +0 -4
  7. package/templates/adapters/claude/hooks/permission-gate.mjs +0 -4
  8. package/templates/adapters/claude/hooks/post-tool-use.mjs +59 -5
  9. package/templates/adapters/claude/hooks/pre-compact.mjs +0 -4
  10. package/templates/adapters/claude/hooks/pre-tool-use.mjs +0 -4
  11. package/templates/adapters/claude/hooks/prompt-submit.mjs +72 -4
  12. package/templates/adapters/claude/hooks/session-end.mjs +0 -4
  13. package/templates/adapters/claude/hooks/session-start.mjs +65 -5
  14. package/templates/adapters/claude/hooks/stop-check.mjs +6 -87
  15. package/templates/adapters/claude/hooks/stop-failure.mjs +0 -4
  16. package/templates/adapters/claude/hooks/subagent-guard.mjs +0 -4
  17. package/templates/adapters/claude/hooks/subagent-stop.mjs +0 -4
  18. package/templates/adapters/codex/hooks/doc-format-guard.mjs +172 -88
  19. package/templates/adapters/codex/hooks/notification.mjs +0 -4
  20. package/templates/adapters/codex/hooks/permission-gate.mjs +0 -4
  21. package/templates/adapters/codex/hooks/post-tool-failure.mjs +0 -4
  22. package/templates/adapters/codex/hooks/post-tool-use.mjs +59 -5
  23. package/templates/adapters/codex/hooks/pre-compact.mjs +0 -4
  24. package/templates/adapters/codex/hooks/pre-tool-use.mjs +0 -4
  25. package/templates/adapters/codex/hooks/prompt-submit.mjs +72 -4
  26. package/templates/adapters/codex/hooks/session-end.mjs +0 -4
  27. package/templates/adapters/codex/hooks/session-start.mjs +65 -5
  28. package/templates/adapters/codex/hooks/stop-check.mjs +6 -87
  29. package/templates/adapters/codex/hooks/subagent-guard.mjs +0 -4
  30. package/templates/adapters/codex/hooks/subagent-stop.mjs +0 -4
  31. package/templates/adapters/qoder/hooks/doc-format-guard.mjs +172 -88
  32. package/templates/adapters/qoder/hooks/notification.mjs +0 -4
  33. package/templates/adapters/qoder/hooks/permission-gate.mjs +0 -4
  34. package/templates/adapters/qoder/hooks/post-tool-failure.mjs +0 -4
  35. package/templates/adapters/qoder/hooks/post-tool-use.mjs +59 -5
  36. package/templates/adapters/qoder/hooks/pre-compact.mjs +0 -4
  37. package/templates/adapters/qoder/hooks/pre-tool-use.mjs +0 -4
  38. package/templates/adapters/qoder/hooks/prompt-submit.mjs +72 -4
  39. package/templates/adapters/qoder/hooks/review-checklist.mjs +0 -4
  40. package/templates/adapters/qoder/hooks/session-end.mjs +0 -4
  41. package/templates/adapters/qoder/hooks/session-start.mjs +67 -5
  42. package/templates/adapters/qoder/hooks/stop-check.mjs +6 -87
  43. package/templates/adapters/qoder/hooks/subagent-guard.mjs +0 -4
  44. package/templates/adapters/qoder/hooks/subagent-stop.mjs +0 -4
  45. package/templates/adapters/trae/hooks/doc-format-guard.mjs +172 -88
  46. package/templates/adapters/trae/hooks/notification.mjs +0 -4
  47. package/templates/adapters/trae/hooks/permission-gate.mjs +0 -4
  48. package/templates/adapters/trae/hooks/post-tool-failure.mjs +0 -4
  49. package/templates/adapters/trae/hooks/post-tool-use.mjs +59 -5
  50. package/templates/adapters/trae/hooks/pre-compact.mjs +0 -4
  51. package/templates/adapters/trae/hooks/pre-tool-use.mjs +0 -4
  52. package/templates/adapters/trae/hooks/prompt-submit.mjs +72 -4
  53. package/templates/adapters/trae/hooks/session-end.mjs +0 -4
  54. package/templates/adapters/trae/hooks/session-start.mjs +65 -5
  55. package/templates/adapters/trae/hooks/stop-check.mjs +6 -87
  56. package/templates/adapters/trae/hooks/subagent-guard.mjs +0 -4
  57. package/templates/adapters/trae/hooks/subagent-stop.mjs +0 -4
  58. package/templates/adapters/vscode/hooks/doc-format-guard.mjs +172 -88
  59. package/templates/adapters/vscode/hooks/notification.mjs +0 -4
  60. package/templates/adapters/vscode/hooks/permission-gate.mjs +0 -4
  61. package/templates/adapters/vscode/hooks/post-tool-failure.mjs +0 -4
  62. package/templates/adapters/vscode/hooks/post-tool-use.mjs +59 -5
  63. package/templates/adapters/vscode/hooks/pre-compact.mjs +0 -4
  64. package/templates/adapters/vscode/hooks/pre-tool-use.mjs +0 -4
  65. package/templates/adapters/vscode/hooks/prompt-submit.mjs +72 -4
  66. package/templates/adapters/vscode/hooks/session-end.mjs +0 -4
  67. package/templates/adapters/vscode/hooks/session-start.mjs +65 -5
  68. package/templates/adapters/vscode/hooks/stop-check.mjs +6 -87
  69. package/templates/adapters/vscode/hooks/subagent-guard.mjs +0 -4
  70. package/templates/adapters/vscode/hooks/subagent-stop.mjs +0 -4
  71. package/templates/core/governance/doc-format-guard.ts +29 -112
  72. package/templates/core/governance/post-tool-router.ts +33 -1
  73. package/templates/core/governance/prompt-router.ts +47 -0
  74. package/templates/core/governance/rules.ts +0 -4
  75. package/templates/core/governance/session-start-guard.ts +48 -1
  76. package/templates/core/governance/stop-router.ts +7 -101
  77. package/templates/core/prisma/add.prisma +203 -0
  78. package/templates/core/scripts/db-ensure.sh +61 -2
  79. package/templates/core/scripts/mcp-server/shared/db-types.ts +119 -0
  80. package/templates/core/scripts/mcp-server/shared/hitl-create-policy.ts +27 -0
  81. package/templates/core/scripts/mcp-server/shared/hitl-proposal-content.ts +110 -0
  82. package/templates/core/scripts/mcp-server/shared/hitl-widget-instance.ts +85 -0
  83. package/templates/core/scripts/mcp-server/shared/memory/calibration/batch-fit.ts +250 -0
  84. package/templates/core/scripts/mcp-server/shared/memory/calibration/feedback-stats.ts +101 -0
  85. package/templates/core/scripts/mcp-server/shared/memory/calibration/unit-state.ts +224 -0
  86. package/templates/core/scripts/mcp-server/shared/memory/domain/conflicts.ts +59 -0
  87. package/templates/core/scripts/mcp-server/shared/memory/domain/dedup.ts +45 -0
  88. package/templates/core/scripts/mcp-server/shared/memory/domain/errors.ts +33 -0
  89. package/templates/core/scripts/mcp-server/shared/memory/domain/handoff-digest.ts +92 -0
  90. package/templates/core/scripts/mcp-server/shared/memory/domain/metric-candidate.ts +79 -0
  91. package/templates/core/scripts/mcp-server/shared/memory/domain/scope.ts +94 -0
  92. package/templates/core/scripts/mcp-server/shared/memory/domain/secrets.ts +50 -0
  93. package/templates/core/scripts/mcp-server/shared/memory/domain/state-machine.ts +90 -0
  94. package/templates/core/scripts/mcp-server/shared/memory/embedding/index.ts +117 -0
  95. package/templates/core/scripts/mcp-server/shared/memory/embedding/local-onnx.ts +105 -0
  96. package/templates/core/scripts/mcp-server/shared/memory/embedding/openai-compatible.ts +87 -0
  97. package/templates/core/scripts/mcp-server/shared/memory/jobs/consolidation.ts +226 -0
  98. package/templates/core/scripts/mcp-server/shared/memory/jobs/evidence-collector.ts +153 -0
  99. package/templates/core/scripts/mcp-server/shared/memory/jobs/snapshot.ts +114 -0
  100. package/templates/core/scripts/mcp-server/shared/memory/metrics/gate-recall.ts +134 -0
  101. package/templates/core/scripts/mcp-server/shared/memory/metrics/gate-writer.ts +217 -0
  102. package/templates/core/scripts/mcp-server/shared/memory/metrics/stage-words.ts +69 -0
  103. package/templates/core/scripts/mcp-server/shared/memory/retrieval/context-builder.ts +89 -0
  104. package/templates/core/scripts/mcp-server/shared/memory/retrieval/fts/pg.ts +139 -0
  105. package/templates/core/scripts/mcp-server/shared/memory/retrieval/fts/sqlite-fts5.sql +29 -0
  106. package/templates/core/scripts/mcp-server/shared/memory/retrieval/fts/sqlite.ts +106 -0
  107. package/templates/core/scripts/mcp-server/shared/memory/retrieval/fusion.ts +43 -0
  108. package/templates/core/scripts/mcp-server/shared/memory/retrieval/pipeline.ts +285 -0
  109. package/templates/core/scripts/mcp-server/shared/memory/retrieval/query-terms.ts +31 -0
  110. package/templates/core/scripts/mcp-server/shared/memory/retrieval/recall-writer.ts +87 -0
  111. package/templates/core/scripts/mcp-server/shared/memory/retrieval/reranker.ts +116 -0
  112. package/templates/core/scripts/mcp-server/shared/memory/retrieval/types.ts +52 -0
  113. package/templates/core/scripts/mcp-server/shared/memory/retrieval/vector/pgvector.ts +143 -0
  114. package/templates/core/scripts/mcp-server/shared/memory/retrieval/vector/sqlite-vec.ts +118 -0
  115. package/templates/core/scripts/mcp-server/shared/memory/switches.ts +39 -0
  116. package/templates/core/scripts/mcp-server/shared/review-files.ts +22 -0
  117. package/templates/core/scripts/mcp-server/shared/runtime-freshness.ts +235 -0
  118. package/templates/core/scripts/mcp-server/tools/gateway/check_dps.ts +41 -3
  119. package/templates/core/scripts/mcp-server/tools/gateway/check_rahs.ts +40 -1
  120. package/templates/core/scripts/mcp-server/tools/gateway/check_spec_sync.ts +2 -2
  121. package/templates/core/scripts/mcp-server/tools/hitl.ts +108 -42
  122. package/templates/core/scripts/mcp-server/tools/index.ts +7 -1
  123. package/templates/core/scripts/mcp-server/tools/memory-compat.ts +258 -0
  124. package/templates/core/scripts/mcp-server/tools/memory.ts +654 -0
  125. package/templates/core/scripts/mcp-server/tools/plan.ts +8 -3
  126. package/templates/core/scripts/mcp-server/tools/review.ts +10 -7
  127. package/templates/core/scripts/mcp-server.ts +36 -0
  128. package/templates/core/templates/checklist-template.md +13 -0
  129. package/templates/core/templates/review-implementation-template.md +24 -0
  130. package/templates/core/templates/review-template.md +16 -0
  131. package/templates/core/validation/index.ts +136 -0
  132. package/templates/core/validation/policy.ts +91 -0
  133. package/templates/core/validation/registry.ts +61 -0
  134. package/templates/core/validation/schema-validator.ts +277 -0
  135. package/templates/core/validation/validators/add-route.ts +32 -0
  136. package/templates/core/validation/validators/checklist.ts +48 -0
  137. package/templates/core/validation/validators/handoff.ts +46 -0
  138. package/templates/core/validation/validators/hitl.ts +22 -0
  139. package/templates/core/validation/validators/index.ts +52 -0
  140. package/templates/core/validation/validators/plan.ts +20 -0
  141. package/templates/core/validation/validators/report.ts +16 -0
  142. package/templates/core/validation/validators/review.ts +30 -0
  143. package/templates/core/validation/validators/spec.ts +25 -0
  144. package/templates/core/validation/validators/tasks.ts +40 -0
  145. package/templates/core/validation/validators/types.ts +32 -0
  146. package/templates/core/vocabulary/add-governance-vocabulary.md +18 -0
  147. package/templates/core/scripts/mcp-server/shared/dps-spec-ref.ts +0 -17
@@ -9,6 +9,8 @@ import { registerHookEventTools } from "./hook-event-report.js"
9
9
  import { registerHitlTools } from "./hitl.js"
10
10
  import { registerPlanTools } from "./plan.js"
11
11
  import { registerReviewTools } from "./review.js"
12
+ import { registerMemoryTools } from "./memory.js"
13
+ import { registerMemoryCompatTools } from "./memory-compat.js"
12
14
  import { PROJECT_ID } from "../shared/env.js"
13
15
  import type { ToolRegistrar } from "./registrar.js"
14
16
 
@@ -24,6 +26,8 @@ const READ_TOOLS = new Set([
24
26
  "check_dps", "check_rahs", "check_add_route_status", "check_spec_sync",
25
27
  "check_add_route_completeness", "check_phase_symmetry", "check_failure_path",
26
28
  "check_add_compliance", "get_hook_events",
29
+ "recall_memory", "get_memory", "list_memories", "review_memory", "get_memory_health",
30
+ "search_memory", "read_memory", "memory_stats",
27
31
  ])
28
32
 
29
33
  function createSemaphore(limit: number) {
@@ -104,5 +108,7 @@ export function registerAllTools(server: McpServer) {
104
108
  registerHitlTools(registrar) // 4 tools: create_hitl / update_hitl / status_hitl / render_hitl_approval
105
109
  registerPlanTools(registrar) // 3 tools: plan_track / plan_status / plan_sync
106
110
  registerReviewTools(registrar) // 3 tools: review_track / review_status / review_sync
107
- // Total: 30 tools
111
+ registerMemoryTools(registrar) // 8 tools: propose_memory / recall_memory / get_memory / list_memories / review_memory / resolve_memory / feedback_memory / get_memory_health
112
+ registerMemoryCompatTools(registrar) // 6 tools: 5 个 v1 弃用门面(append_memory/search_memory/read_memory/link_memory/memory_stats)+ forget_memory(合规清除)
113
+ // Total: 44 tools
108
114
  }
@@ -0,0 +1,258 @@
1
+ /*
2
+ * Memory 兼容面与合规清除(Plan §3.4 轮 2 / Spec §4 §CompatAndPurge)
3
+ *
4
+ * 两部分:
5
+ * A. v1 shim —— 5 个旧工具名注册为**弃用门面**:正常受理调用、把参数映射到 v2 语义、
6
+ * 返回 `deprecated: true` + 目标工具 + 迁移指引,不重复实现 v2 逻辑(避免与 memory.ts 双源漂移)。
7
+ * ⚠️ 溯源声明:v1 工具名在仓库内**零命中**(CHANGELOG / docs / 五个 magic 目录均无),
8
+ * 名字集合按 Plan §3.4 的「append/search/read/link/stats」字面构造。真实 v1 名单若不同,
9
+ * 只需改下方 SHIM_TABLE 一行。
10
+ * 执行转发(真正跑 v2 逻辑)需要把 memory.ts 的操作层抽成共享 ops 模块,按轮次边界
11
+ * (memory.ts 仅轮 3 装配)不在本轮改动,已登记为待补项。
12
+ * B. forget_memory —— 合规清除:物理删除记忆行,并清理三类外键占用(证据关联 / 召回记录 /
13
+ * 被 supersede 指向),最后写 AuditLog 留痕(ADD-5:不落库的清除视为未发生)。
14
+ * 普通废弃仍走状态机(resolve_memory 的 archive/reject/supersede),不物理删除。
15
+ */
16
+ import * as z from "zod/v4"
17
+ import type { ToolRegistrar } from "./registrar.js"
18
+ import { textResponse, errorResponse } from "../shared/response.js"
19
+ import { prisma } from "../shared/prisma.js"
20
+ import { getRuntimeContext } from "../shared/env.js"
21
+ import {
22
+ validatedDelegate,
23
+ AddMemoryRowSchema,
24
+ AddMemoryEvidenceLinkRowSchema,
25
+ AddMemoryRecallItemRowSchema,
26
+ AuditLogRowSchema,
27
+ AddUserRowSchema,
28
+ type AddMemoryRow,
29
+ type AddMemoryEvidenceLinkRow,
30
+ type AddMemoryRecallItemRow,
31
+ type AuditLogRow,
32
+ type AddUserRow,
33
+ type TableDelegate,
34
+ } from "../shared/db-types.js"
35
+ import { MemoryError, isMemoryError } from "../shared/memory/domain/errors.js"
36
+
37
+ /** v1 → v2 映射表(表驱动:真实名单变化时只改这里) */
38
+ export interface ShimEntry {
39
+ v1: string
40
+ mappedTo: string
41
+ note: string
42
+ }
43
+
44
+ export const SHIM_TABLE: readonly ShimEntry[] = [
45
+ { v1: "append_memory", mappedTo: "propose_memory", note: "候选写入语义:落 CANDIDATE,绝不直接 ACTIVE" },
46
+ { v1: "search_memory", mappedTo: "recall_memory", note: "受治理混合召回:RRF 融合 + 治理重排 + token 预算,返回 degradedMode" },
47
+ { v1: "read_memory", mappedTo: "get_memory", note: "单条详情 + 证据链 + supersession 链" },
48
+ { v1: "link_memory", mappedTo: "get_memory", note: "关联改由证据链承载(AddMemoryEvidenceLink),无独立链接工具" },
49
+ { v1: "memory_stats", mappedTo: "get_memory_health", note: "backlog / leakage / provider / FTS 健康度" },
50
+ ] as const
51
+
52
+ /** 弃用响应体(纯函数,便于测试) */
53
+ export function buildShimPayload(v1: string, args: Record<string, unknown>) {
54
+ const entry = SHIM_TABLE.find((s) => s.v1 === v1)
55
+ return {
56
+ deprecated: true,
57
+ v1,
58
+ mappedTo: entry?.mappedTo ?? null,
59
+ mappedArgs: args,
60
+ note: entry?.note ?? null,
61
+ executed: false,
62
+ hint: entry
63
+ ? `v1 工具 ${v1} 已弃用:请改用 ${entry.mappedTo}(参数同上表映射)。`
64
+ : `未知的 v1 工具名 ${v1}。`,
65
+ }
66
+ }
67
+
68
+ export type PurgeReason = "secret" | "privacy" | "compliance"
69
+
70
+ export interface PurgeResult {
71
+ deleted: true
72
+ memoryId: string
73
+ reason: PurgeReason
74
+ ftsCleared: true
75
+ vectorCleared: boolean
76
+ clearedLinks: number
77
+ clearedRecallItems: number
78
+ clearedSupersedePointers: number
79
+ auditId: string
80
+ }
81
+
82
+ export interface PurgeDeps {
83
+ /** 目标仓库(= 运行时 projectKey,越库直接拒绝) */
84
+ repositoryRef: string
85
+ context: { projectKey: string; adapterKey: string; contextId: string }
86
+ memoryDb: Pick<TableDelegate<AddMemoryRow>, "findUnique" | "delete" | "updateMany">
87
+ linkDb: Pick<TableDelegate<AddMemoryEvidenceLinkRow>, "deleteMany">
88
+ recallItemDb: Pick<TableDelegate<AddMemoryRecallItemRow>, "deleteMany">
89
+ auditDb: Pick<TableDelegate<AuditLogRow>, "create">
90
+ ensureUserId: () => Promise<string>
91
+ }
92
+
93
+ /**
94
+ * 合规清除(物理删除)。仅限 secret / privacy / compliance 三类原因;
95
+ * FTS 索引随行删除自动维护(PG GIN 索引与 SQLite FTS5 触发器均为行级同步),故 ftsCleared 恒为 true;
96
+ * 向量列由 embeddingState 决定:首版 provider=none → 无向量可清(vectorCleared=false)。
97
+ */
98
+ export async function purgeMemory(
99
+ deps: PurgeDeps,
100
+ input: { memoryId: string; repositoryRef: string; reason: PurgeReason; actor?: string },
101
+ ): Promise<PurgeResult> {
102
+ if (input.repositoryRef !== deps.context.projectKey) {
103
+ throw new MemoryError("ERR_REPOSITORY_MISMATCH", `越库清除被拒绝:${input.repositoryRef}`)
104
+ }
105
+ const row = await deps.memoryDb.findUnique({ where: { id: input.memoryId } })
106
+ if (!row) throw new MemoryError("ERR_NOT_FOUND", `memoryId=${input.memoryId}`)
107
+ if (row.repositoryRef !== deps.context.projectKey) {
108
+ throw new MemoryError("ERR_REPOSITORY_MISMATCH", `memoryId=${input.memoryId} 属于 ${row.repositoryRef}`)
109
+ }
110
+
111
+ // 外键占用清理顺序:证据关联 → 召回记录 → 被指向的 supersede 指针 → 行本身
112
+ const links = await deps.linkDb.deleteMany({ where: { memoryId: row.id } })
113
+ const recItems = await deps.recallItemDb.deleteMany({ where: { memoryId: row.id } })
114
+ const pointers = await deps.memoryDb.updateMany({
115
+ where: { supersededById: row.id },
116
+ data: { supersededById: null },
117
+ })
118
+
119
+ const vectorCleared = String(row.embeddingState ?? "DISABLED") !== "DISABLED"
120
+ const userId = await deps.ensureUserId()
121
+ const log = await deps.auditDb.create({
122
+ data: {
123
+ userId,
124
+ projectKey: deps.context.projectKey,
125
+ producerAdapterKey: deps.context.adapterKey,
126
+ contextId: deps.context.contextId,
127
+ action: "MEMORY_PURGE",
128
+ targetType: "AddMemory",
129
+ targetId: row.id,
130
+ beforeState: {
131
+ status: row.status,
132
+ kind: row.kind,
133
+ topic: row.topic,
134
+ contentHash: row.contentHash,
135
+ scopeType: row.scopeType,
136
+ scopeValue: row.scopeValue,
137
+ embeddingState: row.embeddingState ?? null,
138
+ evidenceLinks: links.count ?? 0,
139
+ recallItems: recItems.count ?? 0,
140
+ supersedePointers: pointers.count ?? 0,
141
+ },
142
+ afterState: {
143
+ deleted: true,
144
+ ftsCleared: true,
145
+ vectorCleared,
146
+ reason: input.reason,
147
+ actor: input.actor ?? null,
148
+ },
149
+ reason: input.reason,
150
+ },
151
+ })
152
+
153
+ await deps.memoryDb.delete({ where: { id: row.id } })
154
+
155
+ return {
156
+ deleted: true,
157
+ memoryId: row.id,
158
+ reason: input.reason,
159
+ ftsCleared: true,
160
+ vectorCleared,
161
+ clearedLinks: links.count ?? 0,
162
+ clearedRecallItems: recItems.count ?? 0,
163
+ clearedSupersedePointers: pointers.count ?? 0,
164
+ auditId: log.id,
165
+ }
166
+ }
167
+
168
+ export function registerMemoryCompatTools(server: ToolRegistrar) {
169
+ const runtimeContext = getRuntimeContext()
170
+
171
+ const memoryDb = validatedDelegate<AddMemoryRow>(prisma.addMemory, AddMemoryRowSchema, "AddMemory")
172
+ const linkDb = validatedDelegate<AddMemoryEvidenceLinkRow>(
173
+ prisma.addMemoryEvidenceLink, AddMemoryEvidenceLinkRowSchema, "AddMemoryEvidenceLink",
174
+ )
175
+ const recallItemDb = validatedDelegate<AddMemoryRecallItemRow>(
176
+ prisma.addMemoryRecallItem, AddMemoryRecallItemRowSchema, "AddMemoryRecallItem",
177
+ )
178
+ const auditDb = validatedDelegate<AuditLogRow>(prisma.auditLog, AuditLogRowSchema, "AuditLog")
179
+ const userDb = validatedDelegate<AddUserRow>(prisma.addUser, AddUserRowSchema, "AddUser")
180
+
181
+ function fail(e: unknown) {
182
+ if (isMemoryError(e)) return errorResponse(e.message)
183
+ return errorResponse(`ERR_INTERNAL: ${e instanceof Error ? e.message : String(e)}`)
184
+ }
185
+
186
+ async function ensureSystemUser(): Promise<string> {
187
+ let u = await userDb.findUnique({ where: { username: "ai-assistant" } })
188
+ if (!u) {
189
+ u = await userDb.create({
190
+ data: { id: "ai-assistant", username: "ai-assistant", email: "ai-assistant@internal" },
191
+ })
192
+ }
193
+ return u.id
194
+ }
195
+
196
+ // ===== A. v1 shim(5 个弃用门面) =====
197
+ for (const entry of SHIM_TABLE) {
198
+ server.registerTool(
199
+ entry.v1,
200
+ {
201
+ description: `[已弃用] v1 兼容门面 → 请改用 ${entry.mappedTo}。${entry.note}`,
202
+ inputSchema: z.looseObject({}),
203
+ },
204
+ (args: Record<string, unknown>) => {
205
+ try {
206
+ return Promise.resolve(textResponse(JSON.stringify(buildShimPayload(entry.v1, args))))
207
+ } catch (e) {
208
+ return Promise.resolve(fail(e))
209
+ }
210
+ },
211
+ )
212
+ }
213
+
214
+ // ===== B. forget_memory(合规清除,非 shim:v2 新增运维工具) =====
215
+ server.registerTool(
216
+ "forget_memory",
217
+ {
218
+ description:
219
+ "合规清除(物理删除 + 清证据/召回/supersede 占用 + AuditLog 留痕)。仅限 reason=secret|privacy|compliance;" +
220
+ "普通废弃请用 resolve_memory 的 archive/reject/supersede(状态机,不物理删除)。必须显式 confirm=true。",
221
+ inputSchema: z.object({
222
+ repositoryRef: z.string().describe("仓库标识(必须等于运行时 projectKey)"),
223
+ memoryId: z.string(),
224
+ reason: z.enum(["secret", "privacy", "compliance"]).describe("清除原因(决定审计口径)"),
225
+ actor: z.string().optional().describe("操作者标识"),
226
+ confirm: z.boolean().describe("必须为 true:物理删除不可恢复"),
227
+ }),
228
+ },
229
+ async (args: Record<string, unknown>, _ctx: unknown) => {
230
+ try {
231
+ if (args.confirm !== true) {
232
+ return errorResponse("ERR_INVARIANT: 物理清除必须显式 confirm=true")
233
+ }
234
+ const result = await purgeMemory(
235
+ {
236
+ repositoryRef: runtimeContext.projectKey,
237
+ context: {
238
+ projectKey: runtimeContext.projectKey,
239
+ adapterKey: runtimeContext.adapterKey,
240
+ contextId: runtimeContext.contextId,
241
+ },
242
+ memoryDb, linkDb, recallItemDb, auditDb,
243
+ ensureUserId: ensureSystemUser,
244
+ },
245
+ {
246
+ memoryId: args.memoryId as string,
247
+ repositoryRef: args.repositoryRef as string,
248
+ reason: args.reason as PurgeReason,
249
+ actor: args.actor as string | undefined,
250
+ },
251
+ )
252
+ return textResponse(JSON.stringify(result))
253
+ } catch (e) {
254
+ return fail(e)
255
+ }
256
+ },
257
+ )
258
+ }