wyrm-mcp 7.2.1 → 7.2.2

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 (150) hide show
  1. package/LICENSE +26 -667
  2. package/NOTICE +14 -33
  3. package/dist/activation.js +1 -60
  4. package/dist/agent-daemon.js +4 -281
  5. package/dist/agent-loop.js +7 -332
  6. package/dist/analytics.js +13 -236
  7. package/dist/attribution.js +1 -49
  8. package/dist/audit.js +2 -457
  9. package/dist/auto-capture.js +3 -138
  10. package/dist/auto-orchestrator.js +1 -325
  11. package/dist/autoconfig.js +39 -840
  12. package/dist/buddy-runner.js +1 -109
  13. package/dist/buddy.js +14 -564
  14. package/dist/build-flags.js +1 -17
  15. package/dist/capabilities.js +3 -183
  16. package/dist/capture.js +1 -56
  17. package/dist/causality.js +6 -107
  18. package/dist/cli.js +20 -281
  19. package/dist/cloud/cli.js +5 -541
  20. package/dist/cloud/client.js +1 -221
  21. package/dist/cloud/crypto.js +1 -85
  22. package/dist/cloud/machine-id.js +2 -113
  23. package/dist/cloud/recovery.js +1 -60
  24. package/dist/cloud/sync-engine.js +7 -543
  25. package/dist/cloud-backup.js +5 -579
  26. package/dist/cloud-profile.js +1 -138
  27. package/dist/cloud-sync-entrypoint.js +1 -47
  28. package/dist/cloud-sync.js +2 -309
  29. package/dist/constellation.js +12 -168
  30. package/dist/context-build-budgeted.js +4 -144
  31. package/dist/context-ranking.js +1 -69
  32. package/dist/crypto.js +1 -179
  33. package/dist/daemon-write-endpoint.js +1 -290
  34. package/dist/daemon-writer.js +2 -406
  35. package/dist/database.js +43 -1110
  36. package/dist/deprecations.js +2 -162
  37. package/dist/design.js +13 -141
  38. package/dist/event-replication.js +1 -112
  39. package/dist/events-sse.js +7 -43
  40. package/dist/events.js +6 -238
  41. package/dist/failure-patterns.js +42 -659
  42. package/dist/federation.js +12 -236
  43. package/dist/goals.js +13 -101
  44. package/dist/golden.js +3 -355
  45. package/dist/handlers/agent.js +4 -165
  46. package/dist/handlers/alias-adapters.js +1 -129
  47. package/dist/handlers/aliases.js +1 -171
  48. package/dist/handlers/audit.js +1 -87
  49. package/dist/handlers/boundary.js +1 -221
  50. package/dist/handlers/capture.js +73 -1109
  51. package/dist/handlers/causality.js +7 -114
  52. package/dist/handlers/cloud.js +85 -382
  53. package/dist/handlers/companion.js +28 -459
  54. package/dist/handlers/datalake.js +7 -187
  55. package/dist/handlers/dispatch-context.js +0 -22
  56. package/dist/handlers/entity.js +25 -256
  57. package/dist/handlers/events.js +16 -335
  58. package/dist/handlers/failure.js +13 -340
  59. package/dist/handlers/goals.js +4 -296
  60. package/dist/handlers/intelligence.js +126 -674
  61. package/dist/handlers/invoicing.js +1 -70
  62. package/dist/handlers/mcpclient.js +6 -137
  63. package/dist/handlers/orchestration.js +40 -125
  64. package/dist/handlers/output-schemas.js +1 -24
  65. package/dist/handlers/presence.js +3 -99
  66. package/dist/handlers/project.js +28 -182
  67. package/dist/handlers/prompts.js +6 -157
  68. package/dist/handlers/quest.js +4 -224
  69. package/dist/handlers/recall.js +11 -218
  70. package/dist/handlers/registry.js +1 -167
  71. package/dist/handlers/resources.js +1 -288
  72. package/dist/handlers/review.js +11 -74
  73. package/dist/handlers/run.js +17 -487
  74. package/dist/handlers/search.js +15 -326
  75. package/dist/handlers/session.js +28 -615
  76. package/dist/handlers/share.js +8 -184
  77. package/dist/handlers/shims.js +1 -464
  78. package/dist/handlers/skill.js +67 -449
  79. package/dist/handlers/survivors.js +1 -120
  80. package/dist/handlers/symbols.js +8 -109
  81. package/dist/handlers/syncops.js +4 -302
  82. package/dist/handlers/types.js +1 -27
  83. package/dist/harvest.js +5 -191
  84. package/dist/hours.js +7 -156
  85. package/dist/http-auth.js +3 -321
  86. package/dist/http-fast.js +21 -1137
  87. package/dist/icons.js +1 -47
  88. package/dist/index.js +2 -924
  89. package/dist/indexer.js +4 -145
  90. package/dist/intelligence.js +31 -261
  91. package/dist/internal-dispatch.js +3 -212
  92. package/dist/keyset.js +1 -110
  93. package/dist/knowledge-graph.js +12 -176
  94. package/dist/license.js +2 -441
  95. package/dist/logger.js +2 -199
  96. package/dist/maintenance.js +2 -148
  97. package/dist/mcp-client.js +6 -262
  98. package/dist/memory-artifacts.js +30 -449
  99. package/dist/migrate-prompt.js +2 -124
  100. package/dist/migrations.js +40 -655
  101. package/dist/performance.js +1 -228
  102. package/dist/presence.js +11 -140
  103. package/dist/priority-embed.js +5 -164
  104. package/dist/providers/embedding-provider.js +1 -196
  105. package/dist/readonly-gate.js +1 -29
  106. package/dist/rehydration.js +9 -157
  107. package/dist/reindex.js +1 -88
  108. package/dist/render-target.js +21 -514
  109. package/dist/render.js +4 -280
  110. package/dist/repl-guard.js +1 -173
  111. package/dist/replication-daemon-entrypoint.js +1 -31
  112. package/dist/replication-daemon.js +2 -262
  113. package/dist/resilience.js +1 -591
  114. package/dist/reverse-bridge.js +5 -360
  115. package/dist/security.js +1 -244
  116. package/dist/session-seen.js +3 -51
  117. package/dist/setup.js +1 -260
  118. package/dist/skill-author.js +5 -168
  119. package/dist/spec-kit.js +1 -191
  120. package/dist/sqlite-busy.js +1 -154
  121. package/dist/statusline.js +11 -315
  122. package/dist/sub-agent.js +13 -262
  123. package/dist/summarizer.js +13 -139
  124. package/dist/symbols.js +7 -283
  125. package/dist/sync.js +5 -359
  126. package/dist/tasks-dispatch.js +1 -84
  127. package/dist/tasks.js +1 -282
  128. package/dist/token-budget.js +1 -143
  129. package/dist/tool-analytics.js +7 -129
  130. package/dist/tool-annotations.js +1 -365
  131. package/dist/tool-manifest-v2.json +1 -1
  132. package/dist/tool-manifest.json +1 -1
  133. package/dist/tool-profiles.js +1 -75
  134. package/dist/trace-harvest.js +6 -244
  135. package/dist/types.js +1 -30
  136. package/dist/ui-dashboard.js +41 -50
  137. package/dist/ulid.js +1 -81
  138. package/dist/validate.js +1 -129
  139. package/dist/vault.js +1 -534
  140. package/dist/vectors.js +3 -184
  141. package/dist/version-check.js +4 -136
  142. package/dist/visibility.js +19 -155
  143. package/dist/wyrm-cli.js +98 -2464
  144. package/dist/wyrm-guard.js +14 -424
  145. package/dist/wyrm-loop.js +3 -150
  146. package/dist/wyrm-manifest.json +1 -1
  147. package/dist/wyrm-statusline-daemon.js +1 -11
  148. package/dist/wyrm-statusline.js +4 -56
  149. package/dist/wyrm-ui.js +9 -77
  150. package/package.json +4 -2
@@ -1,288 +1 @@
1
- /**
2
- * MCP resources — `wyrm://` URI scheme (v7 F4 T034, spec FR-3 context economy).
3
- *
4
- * THE CONTEXT-ECONOMY MOVE: big payloads (a project's full truths/failures/
5
- * quests, the capability inventory, an individual memory artifact) return as
6
- * LINKS, not inlined bytes. A resource-capable client fetches the body on
7
- * demand via `resources/read`; a resource-LESS client loses NO data because
8
- * every hot-path return that emits a `resourceLink` also carries a
9
- * `detail=full` FALLBACK (the full inline body) — the link is an ADDITIONAL
10
- * affordance, never a substitution. This module is the single source of truth
11
- * for the URI grammar, the listing, and the read backends.
12
- *
13
- * URI grammar (path-safe, NO network — Article VII):
14
- * wyrm://capabilities the feature inventory (markdown)
15
- * wyrm://stats the global DB stats (json)
16
- * wyrm://memory/{id} one memory artifact by id (json)
17
- * wyrm://project/{id}/truths a project's current ground truths
18
- * wyrm://project/{id}/failures a project's unresolved failures
19
- * wyrm://project/{id}/quests a project's open quests
20
- * wyrm://project/{id}/memory a project's validated artifacts
21
- * wyrm://project/{id}/stats a project's memory stats
22
- *
23
- * Every dynamic segment is validated against a strict allowlist before any DB
24
- * access: project/memory ids are non-negative integers, the leaf is one of a
25
- * fixed set. A malformed URI yields a clean structured error, never a path
26
- * escape, never an SQL injection vector (ids are bound params), never a fetch.
27
- *
28
- * Article III: zero LLM, zero network, zero clock — a resource read is a pure
29
- * function of the URI and the local SQLite state.
30
- *
31
- * @copyright 2026 Ghost Protocol (Pvt) Ltd.
32
- * @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
33
- */
34
- import { getCapabilities, renderCapabilityBriefing } from '../capabilities.js';
35
- import { decodeCursor } from '../keyset.js';
36
- /** The single URI scheme. */
37
- export const WYRM_URI_SCHEME = 'wyrm://';
38
- /** JSON MIME for structured resource bodies; markdown for the capability prose. */
39
- const MIME_JSON = 'application/json';
40
- const MIME_MARKDOWN = 'text/markdown';
41
- /** The leaf names a project-scoped resource may carry (closed set). */
42
- const PROJECT_LEAVES = ['truths', 'failures', 'quests', 'memory', 'stats'];
43
- // ── URI builders (the ONE place a wyrm:// URI is constructed) ────────────────
44
- export function memoryUri(id) {
45
- return `${WYRM_URI_SCHEME}memory/${id}`;
46
- }
47
- export function projectUri(projectId, leaf, cursor) {
48
- const base = `${WYRM_URI_SCHEME}project/${projectId}/${leaf}`;
49
- return cursor ? `${base}?cursor=${cursor}` : base;
50
- }
51
- export const CAPABILITIES_URI = `${WYRM_URI_SCHEME}capabilities`;
52
- export const STATS_URI = `${WYRM_URI_SCHEME}stats`;
53
- /** Build a resource_link content block. */
54
- export function resourceLink(uri, name, opts) {
55
- return {
56
- type: 'resource_link',
57
- uri,
58
- name,
59
- ...(opts?.description ? { description: opts.description } : {}),
60
- ...(opts?.mimeType ? { mimeType: opts.mimeType } : {}),
61
- };
62
- }
63
- /** Non-negative integer, no leading zeros surprise, no sign, ≤ 15 digits. */
64
- function parseId(segment) {
65
- if (!/^\d{1,15}$/.test(segment))
66
- return null;
67
- const n = Number(segment);
68
- return Number.isSafeInteger(n) && n >= 0 ? n : null;
69
- }
70
- /**
71
- * Parse a wyrm:// URI into a typed shape, or null when malformed/unknown.
72
- * Defensive against path traversal: only the scheme + a fixed grammar of
73
- * allowlisted segments is accepted; '..', empty segments, extra depth, and any
74
- * non-grammar leaf all reject. There is NO filesystem and NO network behind a
75
- * resource read — this guards the DB-query dispatch, not a path open.
76
- */
77
- export function parseWyrmUri(uri) {
78
- if (typeof uri !== 'string' || !uri.startsWith(WYRM_URI_SCHEME))
79
- return null;
80
- let rest = uri.slice(WYRM_URI_SCHEME.length);
81
- // A single optional `?cursor=<opaque>` query is permitted on the project
82
- // listings (v7 F4 T035 keyset pagination). The cursor is base64url (alnum +
83
- // '-' '_'); anything else is rejected outright so the query suffix can never
84
- // smuggle a traversal/control byte past the path grammar below.
85
- let cursor;
86
- const q = rest.indexOf('?');
87
- if (q >= 0) {
88
- const query = rest.slice(q + 1);
89
- rest = rest.slice(0, q);
90
- const m = /^cursor=([A-Za-z0-9_-]{1,512})$/.exec(query);
91
- if (!m)
92
- return null;
93
- cursor = m[1];
94
- }
95
- // Reject control chars, traversal, and query/fragment noise outright.
96
- if (/[\x00-\x1f\x7f]/.test(rest) || rest.includes('..'))
97
- return null;
98
- const segs = rest.split('/');
99
- if (segs.some((s) => s.length === 0))
100
- return null;
101
- if (segs.length === 1) {
102
- if (cursor !== undefined)
103
- return null;
104
- if (segs[0] === 'capabilities')
105
- return { kind: 'capabilities' };
106
- if (segs[0] === 'stats')
107
- return { kind: 'stats' };
108
- return null;
109
- }
110
- if (segs.length === 2 && segs[0] === 'memory') {
111
- if (cursor !== undefined)
112
- return null;
113
- const id = parseId(segs[1]);
114
- return id === null ? null : { kind: 'memory', id };
115
- }
116
- if (segs.length === 3 && segs[0] === 'project') {
117
- const id = parseId(segs[1]);
118
- if (id === null)
119
- return null;
120
- const leaf = segs[2];
121
- if (PROJECT_LEAVES.includes(leaf)) {
122
- // Cursor only meaningful on the paginated `memory` leaf; reject it on the
123
- // others rather than silently ignoring (strict grammar).
124
- if (cursor !== undefined && leaf !== 'memory')
125
- return null;
126
- return { kind: 'project', id, leaf: leaf, ...(cursor !== undefined ? { cursor } : {}) };
127
- }
128
- return null;
129
- }
130
- return null;
131
- }
132
- // ── resources/list + resources/templates/list ───────────────────────────────
133
- /**
134
- * The static, always-available resources (no project context needed). The
135
- * project-scoped resources are advertised as TEMPLATES (their id is a
136
- * parameter), so resources/list stays small and stable while every project's
137
- * data is still reachable by URI.
138
- */
139
- export function listWyrmResources() {
140
- return [
141
- {
142
- uri: CAPABILITIES_URI,
143
- name: 'Wyrm capabilities',
144
- description: 'Feature inventory + runtime state — what this memory system can do and which tool to reach for. The resource form of wyrm_capabilities.',
145
- mimeType: MIME_MARKDOWN,
146
- },
147
- {
148
- uri: STATS_URI,
149
- name: 'Wyrm global stats',
150
- description: 'Global database stats (projects, sessions, quests, data points, size). The resource form of wyrm_stats.',
151
- mimeType: MIME_JSON,
152
- },
153
- ];
154
- }
155
- /** Resource templates for the project-scoped + by-id resources. */
156
- export function listWyrmResourceTemplates() {
157
- return [
158
- {
159
- uriTemplate: `${WYRM_URI_SCHEME}memory/{id}`,
160
- name: 'Memory artifact',
161
- description: 'A single memory artifact (lesson/pattern/anti-pattern/heuristic/reasoning trace) by id.',
162
- mimeType: MIME_JSON,
163
- },
164
- {
165
- uriTemplate: `${WYRM_URI_SCHEME}project/{id}/truths`,
166
- name: 'Project ground truths',
167
- description: "A project's current ground truths (the authoritative facts).",
168
- mimeType: MIME_JSON,
169
- },
170
- {
171
- uriTemplate: `${WYRM_URI_SCHEME}project/{id}/failures`,
172
- name: 'Project failures',
173
- description: "A project's unresolved failure patterns (the negative-learning set).",
174
- mimeType: MIME_JSON,
175
- },
176
- {
177
- uriTemplate: `${WYRM_URI_SCHEME}project/{id}/quests`,
178
- name: 'Project quests',
179
- description: "A project's open quests (pending + in-progress).",
180
- mimeType: MIME_JSON,
181
- },
182
- {
183
- uriTemplate: `${WYRM_URI_SCHEME}project/{id}/memory`,
184
- name: 'Project memory',
185
- description: "A project's validated memory artifacts.",
186
- mimeType: MIME_JSON,
187
- },
188
- {
189
- uriTemplate: `${WYRM_URI_SCHEME}project/{id}/stats`,
190
- name: 'Project memory stats',
191
- description: "A project's memory artifact stats (totals by kind, avg confidence).",
192
- mimeType: MIME_JSON,
193
- },
194
- ];
195
- }
196
- // ── resources/read backends ──────────────────────────────────────────────────
197
- /** Hard read caps so a resource read can never inline an unbounded payload. */
198
- const PROJECT_LIST_CAP = 200;
199
- /** Raised when a URI is well-formed-but-not-found / malformed. The caller maps
200
- * it to a clean MCP error; it is never a crash or a leaked stack. */
201
- export class ResourceNotFoundError extends Error {
202
- uri;
203
- constructor(uri, message) {
204
- super(message);
205
- this.uri = uri;
206
- this.name = 'ResourceNotFoundError';
207
- }
208
- }
209
- /** Deterministic 2-space JSON (Article III/VIII: same state ⇒ same bytes). */
210
- function jsonContent(uri, body) {
211
- return { uri, mimeType: MIME_JSON, text: JSON.stringify(body, null, 2) };
212
- }
213
- /**
214
- * Read a wyrm:// resource against the local DB. Pure read — no writes, no
215
- * network, no clock. Throws ResourceNotFoundError for a malformed/unknown URI
216
- * or a missing row.
217
- */
218
- export function readWyrmResource(uri, ctx) {
219
- const parsed = parseWyrmUri(uri);
220
- if (!parsed)
221
- throw new ResourceNotFoundError(uri, `Unknown or malformed resource URI: ${uri}`);
222
- switch (parsed.kind) {
223
- case 'capabilities': {
224
- const report = getCapabilities(ctx.db.getDatabase(), ctx.WYRM_TOOL_COUNT, {
225
- detectVectorProvider: () => (process.env.WYRM_VECTOR_PROVIDER === 'openai' ? 'openai' : 'ollama'),
226
- hasEncryption: () => !!process.env.WYRM_ENCRYPTION_KEY,
227
- isFederationEnabled: () => true,
228
- isAgentRunning: () => {
229
- try {
230
- return ctx.agentDaemon.status().running;
231
- }
232
- catch {
233
- return null;
234
- }
235
- },
236
- });
237
- // Markdown body — the human briefing, same bytes wyrm_capabilities emits.
238
- return { uri, mimeType: MIME_MARKDOWN, text: renderCapabilityBriefing(report) };
239
- }
240
- case 'stats': {
241
- return jsonContent(uri, ctx.db.getStats());
242
- }
243
- case 'memory': {
244
- const artifact = ctx.memory.get(parsed.id);
245
- if (!artifact)
246
- throw new ResourceNotFoundError(uri, `Memory artifact not found: ${parsed.id}`);
247
- return jsonContent(uri, artifact);
248
- }
249
- case 'project': {
250
- const project = ctx.db.getProjectById(parsed.id);
251
- if (!project)
252
- throw new ResourceNotFoundError(uri, `Project not found: ${parsed.id}`);
253
- switch (parsed.leaf) {
254
- case 'truths':
255
- return jsonContent(uri, { project_id: parsed.id, truths: ctx.groundTruths.getCurrent(parsed.id) });
256
- case 'failures':
257
- return jsonContent(uri, { project_id: parsed.id, failures: ctx.failures.list(parsed.id, PROJECT_LIST_CAP) });
258
- case 'quests': {
259
- const quests = ctx.db
260
- .getDatabase()
261
- .prepare("SELECT * FROM quests WHERE project_id = ? AND status IN ('pending','in_progress') ORDER BY CASE priority WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END, id LIMIT ?")
262
- .all(parsed.id, PROJECT_LIST_CAP);
263
- return jsonContent(uri, { project_id: parsed.id, quests });
264
- }
265
- case 'memory': {
266
- // Keyset-paginated (v7 F4 T035): a project's full artifact set can be
267
- // larger than one inline payload, so the listing returns a PAGE +
268
- // an opaque nextCursor instead of a hard 200-row truncation that
269
- // silently drops the tail. A bad/garbage cursor decodes to null → the
270
- // first page (never throws on the wire).
271
- const after = decodeCursor(parsed.cursor);
272
- const page = ctx.memory.listPage(parsed.id, { pageSize: PROJECT_LIST_CAP, after });
273
- const content = jsonContent(uri, {
274
- project_id: parsed.id,
275
- artifacts: page.items,
276
- ...(page.nextCursor ? { next_cursor: page.nextCursor } : {}),
277
- });
278
- if (page.nextCursor)
279
- content.nextCursor = page.nextCursor;
280
- return content;
281
- }
282
- case 'stats':
283
- return jsonContent(uri, { project_id: parsed.id, stats: ctx.memory.getStats(parsed.id) });
284
- }
285
- }
286
- }
287
- }
288
- //# sourceMappingURL=resources.js.map
1
+ import{getCapabilities as f,renderCapabilityBriefing as y}from"../capabilities.js";import{decodeCursor as g}from"../keyset.js";const o="wyrm://",c="application/json",l="text/markdown",T=["truths","failures","quests","memory","stats"];function b(r){return`${o}memory/${r}`}function C(r,t,e){const i=`${o}project/${r}/${t}`;return e?`${i}?cursor=${e}`:i}const h=`${o}capabilities`,j=`${o}stats`;function $(r,t,e){return{type:"resource_link",uri:r,name:t,...e?.description?{description:e.description}:{},...e?.mimeType?{mimeType:e.mimeType}:{}}}function d(r){if(!/^\d{1,15}$/.test(r))return null;const t=Number(r);return Number.isSafeInteger(t)&&t>=0?t:null}function E(r){if(typeof r!="string"||!r.startsWith(o))return null;let t=r.slice(o.length),e;const i=t.indexOf("?");if(i>=0){const s=t.slice(i+1);t=t.slice(0,i);const a=/^cursor=([A-Za-z0-9_-]{1,512})$/.exec(s);if(!a)return null;e=a[1]}if(/[\x00-\x1f\x7f]/.test(t)||t.includes(".."))return null;const n=t.split("/");if(n.some(s=>s.length===0))return null;if(n.length===1)return e!==void 0?null:n[0]==="capabilities"?{kind:"capabilities"}:n[0]==="stats"?{kind:"stats"}:null;if(n.length===2&&n[0]==="memory"){if(e!==void 0)return null;const s=d(n[1]);return s===null?null:{kind:"memory",id:s}}if(n.length===3&&n[0]==="project"){const s=d(n[1]);if(s===null)return null;const a=n[2];return T.includes(a)?e!==void 0&&a!=="memory"?null:{kind:"project",id:s,leaf:a,...e!==void 0?{cursor:e}:{}}:null}return null}function N(){return[{uri:h,name:"Wyrm capabilities",description:"Feature inventory + runtime state \u2014 what this memory system can do and which tool to reach for. The resource form of wyrm_capabilities.",mimeType:l},{uri:j,name:"Wyrm global stats",description:"Global database stats (projects, sessions, quests, data points, size). The resource form of wyrm_stats.",mimeType:c}]}function I(){return[{uriTemplate:`${o}memory/{id}`,name:"Memory artifact",description:"A single memory artifact (lesson/pattern/anti-pattern/heuristic/reasoning trace) by id.",mimeType:c},{uriTemplate:`${o}project/{id}/truths`,name:"Project ground truths",description:"A project's current ground truths (the authoritative facts).",mimeType:c},{uriTemplate:`${o}project/{id}/failures`,name:"Project failures",description:"A project's unresolved failure patterns (the negative-learning set).",mimeType:c},{uriTemplate:`${o}project/{id}/quests`,name:"Project quests",description:"A project's open quests (pending + in-progress).",mimeType:c},{uriTemplate:`${o}project/{id}/memory`,name:"Project memory",description:"A project's validated memory artifacts.",mimeType:c},{uriTemplate:`${o}project/{id}/stats`,name:"Project memory stats",description:"A project's memory artifact stats (totals by kind, avg confidence).",mimeType:c}]}const m=200;class p extends Error{uri;constructor(t,e){super(e),this.uri=t,this.name="ResourceNotFoundError"}}function u(r,t){return{uri:r,mimeType:c,text:JSON.stringify(t,null,2)}}function x(r,t){const e=E(r);if(!e)throw new p(r,`Unknown or malformed resource URI: ${r}`);switch(e.kind){case"capabilities":{const i=f(t.db.getDatabase(),t.WYRM_TOOL_COUNT,{detectVectorProvider:()=>process.env.WYRM_VECTOR_PROVIDER==="openai"?"openai":"ollama",hasEncryption:()=>!!process.env.WYRM_ENCRYPTION_KEY,isFederationEnabled:()=>!0,isAgentRunning:()=>{try{return t.agentDaemon.status().running}catch{return null}}});return{uri:r,mimeType:l,text:y(i)}}case"stats":return u(r,t.db.getStats());case"memory":{const i=t.memory.get(e.id);if(!i)throw new p(r,`Memory artifact not found: ${e.id}`);return u(r,i)}case"project":{if(!t.db.getProjectById(e.id))throw new p(r,`Project not found: ${e.id}`);switch(e.leaf){case"truths":return u(r,{project_id:e.id,truths:t.groundTruths.getCurrent(e.id)});case"failures":return u(r,{project_id:e.id,failures:t.failures.list(e.id,m)});case"quests":{const n=t.db.getDatabase().prepare("SELECT * FROM quests WHERE project_id = ? AND status IN ('pending','in_progress') ORDER BY CASE priority WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END, id LIMIT ?").all(e.id,m);return u(r,{project_id:e.id,quests:n})}case"memory":{const n=g(e.cursor),s=t.memory.listPage(e.id,{pageSize:m,after:n}),a=u(r,{project_id:e.id,artifacts:s.items,...s.nextCursor?{next_cursor:s.nextCursor}:{}});return s.nextCursor&&(a.nextCursor=s.nextCursor),a}case"stats":return u(r,{project_id:e.id,stats:t.memory.getStats(e.id)})}}}}export{h as CAPABILITIES_URI,p as ResourceNotFoundError,j as STATS_URI,o as WYRM_URI_SCHEME,I as listWyrmResourceTemplates,N as listWyrmResources,b as memoryUri,E as parseWyrmUri,C as projectUri,x as readWyrmResource,$ as resourceLink};
@@ -1,74 +1,11 @@
1
- /**
2
- * Review domain — ToolSpec contract v2 (v7 F3 T026, hot-path extraction).
3
- *
4
- * wyrm_review (the review-queue gate), moved VERBATIM from the index.ts
5
- * dispatch switch + buildAllTools(). Approve flips needs_review off; reject
6
- * HARD-DELETES the artifact (the raw SQL moved with the handler — the
7
- * ctx.raw() verbatim-SQL seam, see handlers/types.ts).
8
- *
9
- * @copyright 2026 Ghost Protocol (Pvt) Ltd.
10
- * @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
11
- */
12
- import { TOOL_ANNOTATIONS } from '../tool-annotations.js';
13
- import { renderResult, withGlyph } from '../render.js';
14
- import { reverseBridgeSigFromTags, recordReverseBridgeRejection } from '../reverse-bridge.js';
15
- export const reviewToolSpecs = [
16
- {
17
- name: "wyrm_review",
18
- description: "Use to process the review queue - approve or reject the pending memory candidates waiting from extraction, harvest, imports, capture conflicts, or session distillation. Approve activates the artifact for recall; reject permanently deletes it (unrecoverable).",
19
- inputSchema: {
20
- type: "object",
21
- properties: {
22
- artifactId: { type: "number" },
23
- approved: { type: "boolean", description: "true = activate, false = hard delete" },
24
- notes: { type: "string" },
25
- },
26
- required: ["artifactId", "approved"],
27
- },
28
- outputSchema: {
29
- type: "object",
30
- properties: {
31
- artifact_id: { type: "integer" },
32
- approved: { type: "boolean" },
33
- deleted: { type: "boolean" },
34
- problem: { type: "string" },
35
- notes: { type: ["string", "null"] },
36
- },
37
- required: ["artifact_id", "approved", "deleted", "problem", "notes"],
38
- },
39
- annotations: TOOL_ANNOTATIONS.wyrm_review,
40
- aliases: [],
41
- handler: (args, { memory, raw }) => {
42
- const { artifactId: rvId, approved, notes: rvNotes } = args;
43
- const artifact = memory.get(rvId);
44
- if (!artifact)
45
- return { content: [{ type: "text", text: `Artifact #${rvId} not found.` }], isError: true };
46
- if (approved) {
47
- memory.update(rvId, { needs_review: 0 });
48
- }
49
- else {
50
- // A reverse-bridge candidate (rb:-tagged) that the operator rejects gets
51
- // a rejection tombstone BEFORE the delete, so the next bridge sweep does
52
- // not re-extract + re-queue the identical outside-prose (security pass
53
- // #2, finding #1). Non-bridge artifacts have no rb: sig → no tombstone.
54
- const rbSig = reverseBridgeSigFromTags(artifact.tags);
55
- if (rbSig)
56
- recordReverseBridgeRejection(raw(), artifact.project_id, rbSig);
57
- raw().prepare('DELETE FROM memory_artifacts WHERE id = ?').run(rvId);
58
- }
59
- const body = {
60
- artifact_id: rvId,
61
- approved,
62
- deleted: !approved,
63
- problem: artifact.problem.slice(0, 80),
64
- notes: rvNotes ?? null,
65
- };
66
- return renderResult(body, (b, g) => b.approved
67
- ? withGlyph(g.ok, `**Approved** -- Artifact #${b.artifact_id} is now active.`) +
68
- `\n\n"${b.problem}"\n\nIt will appear in future \`wyrm_recall\` and \`wyrm_context_build\` results.${b.notes ? `\n\nNotes: ${b.notes}` : ''}`
69
- : withGlyph(g.fail, `**Rejected** -- Artifact #${b.artifact_id} permanently deleted.`) +
70
- `\n\n"${b.problem}"${b.notes ? `\n\nNotes: ${b.notes}` : ''}`);
71
- },
72
- },
73
- ];
74
- //# sourceMappingURL=review.js.map
1
+ import{TOOL_ANNOTATIONS as l}from"../tool-annotations.js";import{renderResult as f,withGlyph as p}from"../render.js";import{reverseBridgeSigFromTags as m,recordReverseBridgeRejection as u}from"../reverse-bridge.js";const g=[{name:"wyrm_review",description:"Use to process the review queue - approve or reject the pending memory candidates waiting from extraction, harvest, imports, capture conflicts, or session distillation. Approve activates the artifact for recall; reject permanently deletes it (unrecoverable).",inputSchema:{type:"object",properties:{artifactId:{type:"number"},approved:{type:"boolean",description:"true = activate, false = hard delete"},notes:{type:"string"}},required:["artifactId","approved"]},outputSchema:{type:"object",properties:{artifact_id:{type:"integer"},approved:{type:"boolean"},deleted:{type:"boolean"},problem:{type:"string"},notes:{type:["string","null"]}},required:["artifact_id","approved","deleted","problem","notes"]},annotations:l.wyrm_review,aliases:[],handler:(s,{memory:i,raw:a})=>{const{artifactId:t,approved:o,notes:d}=s,r=i.get(t);if(!r)return{content:[{type:"text",text:`Artifact #${t} not found.`}],isError:!0};if(o)i.update(t,{needs_review:0});else{const e=m(r.tags);e&&u(a(),r.project_id,e),a().prepare("DELETE FROM memory_artifacts WHERE id = ?").run(t)}const c={artifact_id:t,approved:o,deleted:!o,problem:r.problem.slice(0,80),notes:d??null};return f(c,(e,n)=>e.approved?p(n.ok,`**Approved** -- Artifact #${e.artifact_id} is now active.`)+`
2
+
3
+ "${e.problem}"
4
+
5
+ It will appear in future \`wyrm_recall\` and \`wyrm_context_build\` results.${e.notes?`
6
+
7
+ Notes: ${e.notes}`:""}`:p(n.fail,`**Rejected** -- Artifact #${e.artifact_id} permanently deleted.`)+`
8
+
9
+ "${e.problem}"${e.notes?`
10
+
11
+ Notes: ${e.notes}`:""}`)}}];export{g as reviewToolSpecs};