wyrm-mcp 7.2.0 → 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.
- package/LICENSE +26 -667
- package/NOTICE +14 -33
- package/dist/activation.d.ts.map +1 -1
- package/dist/activation.js +1 -44
- package/dist/activation.js.map +1 -1
- package/dist/agent-daemon.js +4 -281
- package/dist/agent-loop.js +7 -332
- package/dist/analytics.js +13 -236
- package/dist/attribution.js +1 -49
- package/dist/audit.js +2 -457
- package/dist/auto-capture.js +3 -138
- package/dist/auto-orchestrator.js +1 -325
- package/dist/autoconfig.js +39 -840
- package/dist/buddy-runner.js +1 -109
- package/dist/buddy.js +14 -564
- package/dist/build-flags.js +1 -17
- package/dist/capabilities.js +3 -183
- package/dist/capture.js +1 -56
- package/dist/causality.js +6 -107
- package/dist/cli.js +20 -281
- package/dist/cloud/cli.js +5 -541
- package/dist/cloud/client.js +1 -221
- package/dist/cloud/crypto.js +1 -85
- package/dist/cloud/machine-id.js +2 -113
- package/dist/cloud/recovery.js +1 -60
- package/dist/cloud/sync-engine.js +7 -543
- package/dist/cloud-backup.js +5 -579
- package/dist/cloud-profile.js +1 -138
- package/dist/cloud-sync-entrypoint.js +1 -47
- package/dist/cloud-sync.js +2 -309
- package/dist/constellation.js +12 -168
- package/dist/context-build-budgeted.js +4 -144
- package/dist/context-ranking.js +1 -69
- package/dist/crypto.js +1 -179
- package/dist/daemon-write-endpoint.js +1 -290
- package/dist/daemon-writer.js +2 -406
- package/dist/database.js +43 -1110
- package/dist/deprecations.js +2 -162
- package/dist/design.js +13 -141
- package/dist/event-replication.js +1 -112
- package/dist/events-sse.js +7 -43
- package/dist/events.js +6 -238
- package/dist/failure-patterns.js +42 -659
- package/dist/federation.js +12 -236
- package/dist/goals.js +13 -101
- package/dist/golden.js +3 -355
- package/dist/handlers/agent.js +4 -165
- package/dist/handlers/alias-adapters.js +1 -129
- package/dist/handlers/aliases.js +1 -171
- package/dist/handlers/audit.js +1 -87
- package/dist/handlers/boundary.js +1 -221
- package/dist/handlers/capture.js +73 -1109
- package/dist/handlers/causality.js +7 -114
- package/dist/handlers/cloud.js +85 -382
- package/dist/handlers/companion.js +28 -459
- package/dist/handlers/datalake.js +7 -187
- package/dist/handlers/dispatch-context.js +0 -22
- package/dist/handlers/entity.js +25 -256
- package/dist/handlers/events.js +16 -335
- package/dist/handlers/failure.js +13 -340
- package/dist/handlers/goals.js +4 -296
- package/dist/handlers/intelligence.js +126 -674
- package/dist/handlers/invoicing.js +1 -70
- package/dist/handlers/mcpclient.js +6 -137
- package/dist/handlers/orchestration.js +40 -125
- package/dist/handlers/output-schemas.js +1 -24
- package/dist/handlers/presence.js +3 -99
- package/dist/handlers/project.js +28 -182
- package/dist/handlers/prompts.js +6 -157
- package/dist/handlers/quest.js +4 -224
- package/dist/handlers/recall.js +11 -218
- package/dist/handlers/registry.js +1 -167
- package/dist/handlers/resources.js +1 -288
- package/dist/handlers/review.js +11 -74
- package/dist/handlers/run.js +17 -487
- package/dist/handlers/search.js +15 -326
- package/dist/handlers/session.js +28 -615
- package/dist/handlers/share.js +8 -184
- package/dist/handlers/shims.js +1 -464
- package/dist/handlers/skill.js +67 -449
- package/dist/handlers/survivors.js +1 -120
- package/dist/handlers/symbols.js +8 -109
- package/dist/handlers/syncops.js +4 -302
- package/dist/handlers/types.js +1 -27
- package/dist/harvest.js +5 -191
- package/dist/hours.js +7 -156
- package/dist/http-auth.js +3 -321
- package/dist/http-fast.js +21 -1137
- package/dist/icons.js +1 -47
- package/dist/index.js +2 -924
- package/dist/indexer.js +4 -145
- package/dist/intelligence.js +31 -261
- package/dist/internal-dispatch.js +3 -212
- package/dist/keyset.js +1 -110
- package/dist/knowledge-graph.js +12 -176
- package/dist/license.d.ts +11 -0
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +2 -414
- package/dist/license.js.map +1 -1
- package/dist/logger.js +2 -199
- package/dist/maintenance.js +2 -148
- package/dist/mcp-client.js +6 -262
- package/dist/memory-artifacts.js +30 -449
- package/dist/migrate-prompt.js +2 -124
- package/dist/migrations.js +40 -655
- package/dist/performance.js +1 -228
- package/dist/presence.js +11 -140
- package/dist/priority-embed.js +5 -164
- package/dist/providers/embedding-provider.js +1 -196
- package/dist/readonly-gate.js +1 -29
- package/dist/rehydration.js +9 -157
- package/dist/reindex.js +1 -88
- package/dist/render-target.js +21 -514
- package/dist/render.js +4 -280
- package/dist/repl-guard.js +1 -173
- package/dist/replication-daemon-entrypoint.js +1 -31
- package/dist/replication-daemon.js +2 -262
- package/dist/resilience.js +1 -591
- package/dist/reverse-bridge.js +5 -360
- package/dist/security.js +1 -244
- package/dist/session-seen.js +3 -51
- package/dist/setup.js +1 -260
- package/dist/skill-author.js +5 -168
- package/dist/spec-kit.js +1 -191
- package/dist/sqlite-busy.js +1 -154
- package/dist/statusline.js +11 -315
- package/dist/sub-agent.js +13 -262
- package/dist/summarizer.js +13 -139
- package/dist/symbols.js +7 -283
- package/dist/sync.js +5 -359
- package/dist/tasks-dispatch.js +1 -84
- package/dist/tasks.js +1 -282
- package/dist/token-budget.js +1 -143
- package/dist/tool-analytics.js +7 -129
- package/dist/tool-annotations.js +1 -365
- package/dist/tool-manifest-v2.json +1 -1
- package/dist/tool-manifest.json +1 -1
- package/dist/tool-profiles.js +1 -75
- package/dist/trace-harvest.js +6 -244
- package/dist/types.js +1 -30
- package/dist/ui-dashboard.js +41 -50
- package/dist/ulid.js +1 -81
- package/dist/validate.js +1 -129
- package/dist/vault.js +1 -534
- package/dist/vectors.js +3 -184
- package/dist/version-check.js +4 -136
- package/dist/visibility.js +19 -155
- package/dist/wyrm-cli.js +98 -2451
- package/dist/wyrm-cli.js.map +1 -1
- package/dist/wyrm-guard.js +14 -424
- package/dist/wyrm-loop.js +3 -150
- package/dist/wyrm-manifest.json +1 -1
- package/dist/wyrm-statusline-daemon.js +1 -11
- package/dist/wyrm-statusline.js +4 -56
- package/dist/wyrm-ui.js +9 -77
- package/package.json +4 -2
|
@@ -1,459 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
let injText = ` **System Prompt Injection**\n\n`;
|
|
30
|
-
if (injectResult.injected.length > 0) {
|
|
31
|
-
injText += `✅ Injected into:\n${injectResult.injected.map((f) => `- ${f}`).join('\n')}\n\n`;
|
|
32
|
-
}
|
|
33
|
-
if (injectResult.skipped.length > 0) {
|
|
34
|
-
injText += `○ Skipped (unknown client): ${injectResult.skipped.join(', ')}\n\n`;
|
|
35
|
-
}
|
|
36
|
-
if (injectResult.errors.length > 0) {
|
|
37
|
-
injText += `❌ Errors:\n${injectResult.errors.map((e) => `- ${e}`).join('\n')}\n\n`;
|
|
38
|
-
}
|
|
39
|
-
if (injectResult.injected.length > 0) {
|
|
40
|
-
injText += `AI models in this project will now call \`wyrm_session_prime\` at the start of each conversation.`;
|
|
41
|
-
}
|
|
42
|
-
return { content: [{ type: "text", text: injText }] };
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: "buddy",
|
|
47
|
-
description: "Use when another buddy-compatible MCP server (or the operator) asks Wyrm for a brief, data-grounded status reply - the Buddy Protocol v1.0 well-known entry point. Companion params switch to the full companion reply; bare calls stay protocol-pure. Cycle-protected.",
|
|
48
|
-
inputSchema: {
|
|
49
|
-
type: "object",
|
|
50
|
-
properties: {
|
|
51
|
-
// v7 F3 (T026): property prose compressed to fund the hot-path
|
|
52
|
-
// outputSchemas under the 8K default-surface pin (T022/T025 trade).
|
|
53
|
-
from_buddy: { type: "string", description: "Caller identity" },
|
|
54
|
-
project_hint: { type: "string", description: "Scope the reply" },
|
|
55
|
-
mood_hint: { type: "string", enum: ["normal", "celebratory", "stuck", "quiet"] },
|
|
56
|
-
size: { type: "string", enum: ["full", "compact", "mini"] },
|
|
57
|
-
format: { type: "string", enum: ["markdown", "json"], description: "Peer mode only." },
|
|
58
|
-
project_path: { type: "string", description: "Companion mode: project root (default cwd)" },
|
|
59
|
-
persona: { type: "string", enum: ["wyrm", "drogo", "berlin", "sumair", "custom"], description: "Companion voice." },
|
|
60
|
-
persona_name: { type: "string", description: "For persona=custom" },
|
|
61
|
-
mood: { type: "string", description: "Companion override (mood_hint values)" },
|
|
62
|
-
federate: { type: "boolean", description: "Fold in other buddy MCPs" },
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
annotations: TOOL_ANNOTATIONS["buddy"],
|
|
66
|
-
aliases: [],
|
|
67
|
-
handler: async (args, ctx) => {
|
|
68
|
-
const { WYRM_PACKAGE_VERSION, db, runCompanionBuddy } = ctx;
|
|
69
|
-
const a = args || {};
|
|
70
|
-
// v7 F3 (T021) buddy fold: wyrm_buddy's companion params live here as
|
|
71
|
-
// ADDITIVE optional args. Any of them present → the SAME companion
|
|
72
|
-
// code path wyrm_buddy runs (runCompanionBuddy — one implementation,
|
|
73
|
-
// not a duplicate). Absent → Buddy Protocol v1.0 peer behavior,
|
|
74
|
-
// byte-identical to 6.x ("protocol behavior unchanged when absent").
|
|
75
|
-
if (isCompanionBuddyCall(args ?? {})) {
|
|
76
|
-
return await runCompanionBuddy(args ?? {});
|
|
77
|
-
}
|
|
78
|
-
// Buddy Protocol v1.0 — peer entry point. Other MCP servers' buddies
|
|
79
|
-
// call this. Project-agnostic by default; project_hint scopes it.
|
|
80
|
-
const peerReq = args;
|
|
81
|
-
const reply = buildPeerBuddyReply(db.getDatabase(), peerReq, WYRM_PACKAGE_VERSION);
|
|
82
|
-
if (peerReq.format === 'json') {
|
|
83
|
-
return { content: [{ type: 'text', text: JSON.stringify(reply.json, null, 2) }] };
|
|
84
|
-
}
|
|
85
|
-
return { content: [{ type: 'text', text: reply.markdown }] };
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: "wyrm_buddy",
|
|
90
|
-
description: "Friendly, data-grounded coding companion. Returns a brief greeting + project state + suggested next step sourced entirely from Wyrm's real data. Every claim cites a real DB row ID — no hallucinated encouragement. Personas: wyrm (default, dragon-themed), drogo (gruff), berlin (precise), sumair (warm), custom. Moods: normal / celebratory / stuck / quiet — auto-detected. Sizes: full (10-line PhantomDragon-style mascot), compact (5-line workspace-friendly), mini (single-line inline prefix). Federates with other registered MCPs that expose `buddy`, `*_buddy`, or `buddy_*` tools — their replies fold into a 'From other buddies' section.",
|
|
91
|
-
inputSchema: {
|
|
92
|
-
type: "object",
|
|
93
|
-
properties: {
|
|
94
|
-
project_path: { type: "string", description: "Project root. Default: current cwd if registered." },
|
|
95
|
-
mood: { type: "string", enum: ["normal", "celebratory", "stuck", "quiet"], description: "Override the auto-detected mood." },
|
|
96
|
-
persona: { type: "string", enum: ["wyrm", "drogo", "berlin", "sumair", "custom"], description: "Voice. Default: WYRM_BUDDY_DEFAULT_PERSONA env or 'wyrm'." },
|
|
97
|
-
persona_name: { type: "string", description: "Required when persona === 'custom'." },
|
|
98
|
-
size: { type: "string", enum: ["full", "compact", "mini"], description: "Mascot size. 'full' = 10-line head+shoulder banner (default), 'compact' = 5-line workspace-friendly, 'mini' = single-line inline prefix on the greeting." },
|
|
99
|
-
federate: { type: "boolean", description: "Query other registered MCPs with *_buddy tools and fold their replies in. Default: true if any are registered." },
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
annotations: TOOL_ANNOTATIONS["wyrm_buddy"],
|
|
103
|
-
aliases: [],
|
|
104
|
-
handler: async (args, ctx) => {
|
|
105
|
-
const { runCompanionBuddy } = ctx;
|
|
106
|
-
// v7 F3 (T021): alias of the well-known `buddy` tool (the buddy fold).
|
|
107
|
-
// Routes to the EXACT code path buddy's companion mode runs; the alias
|
|
108
|
-
// spine (handlers/aliases.ts) carries the argument adapter and the
|
|
109
|
-
// golden replay CI proves equivalence on the live wire.
|
|
110
|
-
return await runCompanionBuddy(args ?? {});
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
name: "wyrm_token_set",
|
|
115
|
-
description: "Set a design token for a project. Tokens are colour / type / spacing / motion / shadow / radius / breakpoint / custom — the design system primitives the project is built on. Stored first-class so AI helpers working on creative tasks don't have to re-derive the system from scattered CSS each time. Upserts on (project_id, category, key).",
|
|
116
|
-
inputSchema: {
|
|
117
|
-
type: "object",
|
|
118
|
-
properties: {
|
|
119
|
-
projectPath: { type: "string", description: "Project root path." },
|
|
120
|
-
category: { type: "string", enum: ["color", "type", "spacing", "motion", "shadow", "radius", "breakpoint", "custom"], description: "Token category." },
|
|
121
|
-
key: { type: "string", description: "Short slug, e.g. 'primary' / 'h1' / 'page-padding-md'." },
|
|
122
|
-
value: { type: "string", description: "Actual value: '#00B89F' / 'Inter 900 2.5rem' / '1.25rem' / etc." },
|
|
123
|
-
notes: { type: "string", description: "Optional why / when-to-use guidance." },
|
|
124
|
-
source: { type: "string", enum: ["user", "derived", "imported", "observed"], description: "How the token was determined. Default: 'user'." },
|
|
125
|
-
},
|
|
126
|
-
required: ["projectPath", "category", "key", "value"],
|
|
127
|
-
},
|
|
128
|
-
annotations: TOOL_ANNOTATIONS["wyrm_token_set"],
|
|
129
|
-
aliases: [],
|
|
130
|
-
handler: async (args, ctx) => {
|
|
131
|
-
const { db, designSystem } = ctx;
|
|
132
|
-
const { projectPath: tsPath, category: tsCat, key: tsKey, value: tsVal, notes: tsNotes, source: tsSrc } = args;
|
|
133
|
-
const proj = db.getProject(tsPath);
|
|
134
|
-
if (!proj)
|
|
135
|
-
return { content: [{ type: 'text', text: `Project not found: ${tsPath}` }], isError: true };
|
|
136
|
-
const token = designSystem().setToken({ projectId: proj.id, category: tsCat, key: tsKey, value: tsVal, notes: tsNotes, source: tsSrc });
|
|
137
|
-
return { content: [{ type: 'text', text: `🎨 token set: \`${token.category}/${token.key}\` = \`${token.value}\`` + (token.notes ? ` — ${token.notes}` : '') }] };
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
name: "wyrm_token_get",
|
|
142
|
-
description: "Retrieve all design tokens for a project, optionally filtered by category. Returns the design system primitives the project is built on.",
|
|
143
|
-
inputSchema: {
|
|
144
|
-
type: "object",
|
|
145
|
-
properties: {
|
|
146
|
-
projectPath: { type: "string", description: "Project root path." },
|
|
147
|
-
category: { type: "string", enum: ["color", "type", "spacing", "motion", "shadow", "radius", "breakpoint", "custom"], description: "Filter by category. Omit for all tokens." },
|
|
148
|
-
},
|
|
149
|
-
required: ["projectPath"],
|
|
150
|
-
},
|
|
151
|
-
annotations: TOOL_ANNOTATIONS["wyrm_token_get"],
|
|
152
|
-
aliases: [],
|
|
153
|
-
handler: async (args, ctx) => {
|
|
154
|
-
const { db, designSystem } = ctx;
|
|
155
|
-
const { projectPath: tgPath, category: tgCat } = args;
|
|
156
|
-
const proj = db.getProject(tgPath);
|
|
157
|
-
if (!proj)
|
|
158
|
-
return { content: [{ type: 'text', text: `Project not found: ${tgPath}` }], isError: true };
|
|
159
|
-
const md = designSystem().formatForContext(proj.id);
|
|
160
|
-
if (!md)
|
|
161
|
-
return { content: [{ type: 'text', text: `_(no design tokens for ${proj.name} yet — use \`wyrm_token_set\` to start the design system)_` }] };
|
|
162
|
-
// If category filter, slice the markdown
|
|
163
|
-
if (tgCat) {
|
|
164
|
-
const tokens = designSystem().listTokens(proj.id, tgCat);
|
|
165
|
-
if (tokens.length === 0)
|
|
166
|
-
return { content: [{ type: 'text', text: `_(no ${tgCat} tokens for ${proj.name})_` }] };
|
|
167
|
-
const lines = [`### 🎨 ${tgCat} tokens for ${proj.name}`, ''];
|
|
168
|
-
for (const t of tokens)
|
|
169
|
-
lines.push(`- \`${t.key}\` = \`${t.value}\`${t.notes ? ` — ${t.notes}` : ''}`);
|
|
170
|
-
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
171
|
-
}
|
|
172
|
-
return { content: [{ type: 'text', text: md }] };
|
|
173
|
-
},
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
name: "wyrm_token_delete",
|
|
177
|
-
description: "Remove a design token from a project.",
|
|
178
|
-
inputSchema: {
|
|
179
|
-
type: "object",
|
|
180
|
-
properties: {
|
|
181
|
-
projectPath: { type: "string", description: "Project root path." },
|
|
182
|
-
category: { type: "string", enum: ["color", "type", "spacing", "motion", "shadow", "radius", "breakpoint", "custom"] },
|
|
183
|
-
key: { type: "string", description: "Token key to remove." },
|
|
184
|
-
},
|
|
185
|
-
required: ["projectPath", "category", "key"],
|
|
186
|
-
},
|
|
187
|
-
annotations: TOOL_ANNOTATIONS["wyrm_token_delete"],
|
|
188
|
-
aliases: [],
|
|
189
|
-
handler: async (args, ctx) => {
|
|
190
|
-
const { db, designSystem } = ctx;
|
|
191
|
-
const { projectPath: tdPath, category: tdCat, key: tdKey } = args;
|
|
192
|
-
const proj = db.getProject(tdPath);
|
|
193
|
-
if (!proj)
|
|
194
|
-
return { content: [{ type: 'text', text: `Project not found: ${tdPath}` }], isError: true };
|
|
195
|
-
const ok = designSystem().deleteToken(proj.id, tdCat, tdKey);
|
|
196
|
-
return { content: [{ type: 'text', text: ok ? `🗑 removed \`${tdCat}/${tdKey}\`` : `not found: \`${tdCat}/${tdKey}\`` }] };
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
name: "wyrm_reference_add",
|
|
201
|
-
description: "Clip a design reference (URL, image path, palette, or inline snippet) for inspiration. Stored per-project (or globally if no project path). Tag aggressively — tags drive future search and recall when building a new project in the same vein.",
|
|
202
|
-
inputSchema: {
|
|
203
|
-
type: "object",
|
|
204
|
-
properties: {
|
|
205
|
-
projectPath: { type: "string", description: "Project root path. Omit to attach as a global reference." },
|
|
206
|
-
kind: { type: "string", enum: ["url", "image", "palette", "snippet"], description: "Reference type." },
|
|
207
|
-
location: { type: "string", description: "URL, file path, or inline payload (e.g. palette like '#00B89F,#ff5a55,#0a0c0e' or a code snippet)." },
|
|
208
|
-
title: { type: "string", description: "Short title — what is this reference?" },
|
|
209
|
-
notes: { type: "string", description: "Why you saved it / what to remember about it." },
|
|
210
|
-
tags: { type: "string", description: "Comma-separated tags — 'hero,scroll-tied,framer-motion'." },
|
|
211
|
-
},
|
|
212
|
-
required: ["kind", "location"],
|
|
213
|
-
},
|
|
214
|
-
annotations: TOOL_ANNOTATIONS["wyrm_reference_add"],
|
|
215
|
-
aliases: [],
|
|
216
|
-
handler: async (args, ctx) => {
|
|
217
|
-
const { db, designSystem } = ctx;
|
|
218
|
-
const { projectPath: raPath, kind: raKind, location: raLoc, title: raTitle, notes: raNotes, tags: raTags } = args;
|
|
219
|
-
let projectId = null;
|
|
220
|
-
if (raPath) {
|
|
221
|
-
const proj = db.getProject(raPath);
|
|
222
|
-
if (!proj)
|
|
223
|
-
return { content: [{ type: 'text', text: `Project not found: ${raPath}` }], isError: true };
|
|
224
|
-
projectId = proj.id;
|
|
225
|
-
}
|
|
226
|
-
const ref = designSystem().addReference({ projectId, kind: raKind, location: raLoc, title: raTitle, notes: raNotes, tags: raTags });
|
|
227
|
-
const scope = projectId ? ` (project ${projectId})` : ' (global)';
|
|
228
|
-
return { content: [{ type: 'text', text: `📌 reference #${ref.id} saved${scope}: \`${ref.kind}\` ${ref.title ?? ref.location.slice(0, 60)}${ref.tags ? ` · tags: ${ref.tags}` : ''}` }] };
|
|
229
|
-
},
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
name: "wyrm_reference_list",
|
|
233
|
-
description: "Browse saved design references. Filter by project or tag. Default: 50 most recent across all projects.",
|
|
234
|
-
inputSchema: {
|
|
235
|
-
type: "object",
|
|
236
|
-
properties: {
|
|
237
|
-
projectPath: { type: "string", description: "Limit to a specific project." },
|
|
238
|
-
tag: { type: "string", description: "Filter to references containing this tag." },
|
|
239
|
-
limit: { type: "number", description: "Max results (default 50, max 200)." },
|
|
240
|
-
},
|
|
241
|
-
},
|
|
242
|
-
annotations: TOOL_ANNOTATIONS["wyrm_reference_list"],
|
|
243
|
-
aliases: [],
|
|
244
|
-
handler: async (args, ctx) => {
|
|
245
|
-
const { db, designSystem } = ctx;
|
|
246
|
-
const { projectPath: rlPath, tag: rlTag, limit: rlLimit } = args;
|
|
247
|
-
let projectId;
|
|
248
|
-
if (rlPath) {
|
|
249
|
-
const proj = db.getProject(rlPath);
|
|
250
|
-
if (!proj)
|
|
251
|
-
return { content: [{ type: 'text', text: `Project not found: ${rlPath}` }], isError: true };
|
|
252
|
-
projectId = proj.id;
|
|
253
|
-
}
|
|
254
|
-
const refs = designSystem().listReferences({ projectId, tag: rlTag, limit: rlLimit });
|
|
255
|
-
if (refs.length === 0)
|
|
256
|
-
return { content: [{ type: 'text', text: '_(no references match)_' }] };
|
|
257
|
-
const lines = [`📌 **${refs.length} reference${refs.length === 1 ? '' : 's'}**`];
|
|
258
|
-
for (const r of refs) {
|
|
259
|
-
const scope = r.project_id ? `p${r.project_id}` : 'global';
|
|
260
|
-
lines.push(`- [${r.id}/${scope}] \`${r.kind}\` ${r.title ?? r.location.slice(0, 60)}${r.tags ? ` · ${r.tags}` : ''}`);
|
|
261
|
-
}
|
|
262
|
-
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
263
|
-
},
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
name: "wyrm_reference_search",
|
|
267
|
-
description: "Full-text search across design references' title / notes / tags. Returns matching references sorted by recency.",
|
|
268
|
-
inputSchema: {
|
|
269
|
-
type: "object",
|
|
270
|
-
properties: {
|
|
271
|
-
query: { type: "string", description: "FTS5 query — keywords, phrases in quotes." },
|
|
272
|
-
projectPath: { type: "string", description: "Limit to a specific project." },
|
|
273
|
-
limit: { type: "number", description: "Max results (default 20, max 100)." },
|
|
274
|
-
},
|
|
275
|
-
required: ["query"],
|
|
276
|
-
},
|
|
277
|
-
annotations: TOOL_ANNOTATIONS["wyrm_reference_search"],
|
|
278
|
-
aliases: [],
|
|
279
|
-
handler: async (args, ctx) => {
|
|
280
|
-
const { db, designSystem } = ctx;
|
|
281
|
-
const { query: rsQuery, projectPath: rsPath, limit: rsLimit } = args;
|
|
282
|
-
let projectId;
|
|
283
|
-
if (rsPath) {
|
|
284
|
-
const proj = db.getProject(rsPath);
|
|
285
|
-
if (!proj)
|
|
286
|
-
return { content: [{ type: 'text', text: `Project not found: ${rsPath}` }], isError: true };
|
|
287
|
-
projectId = proj.id;
|
|
288
|
-
}
|
|
289
|
-
const refs = designSystem().searchReferences(rsQuery, { projectId, limit: rsLimit });
|
|
290
|
-
if (refs.length === 0)
|
|
291
|
-
return { content: [{ type: 'text', text: `_(no references match "${rsQuery}")_` }] };
|
|
292
|
-
const lines = [`🔍 **${refs.length} reference${refs.length === 1 ? '' : 's'}** matching "${rsQuery}"`];
|
|
293
|
-
for (const r of refs) {
|
|
294
|
-
const scope = r.project_id ? `p${r.project_id}` : 'global';
|
|
295
|
-
lines.push(`- [${r.id}/${scope}] \`${r.kind}\` ${r.title ?? r.location.slice(0, 60)}${r.tags ? ` · ${r.tags}` : ''}`);
|
|
296
|
-
}
|
|
297
|
-
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
298
|
-
},
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
name: "wyrm_capabilities",
|
|
302
|
-
description: "Use to learn what your memory system can actually do - feature inventory, why each matters, runtime state, and which tool to reach for. Call at session start instead of re-discovering the surface.",
|
|
303
|
-
inputSchema: {
|
|
304
|
-
type: "object",
|
|
305
|
-
properties: {
|
|
306
|
-
format: { type: "string", enum: ["json", "markdown"] },
|
|
307
|
-
},
|
|
308
|
-
},
|
|
309
|
-
annotations: TOOL_ANNOTATIONS["wyrm_capabilities"],
|
|
310
|
-
aliases: [],
|
|
311
|
-
handler: async (args, ctx) => {
|
|
312
|
-
const { WYRM_TOOL_COUNT, agentDaemon, db } = ctx;
|
|
313
|
-
const { format: capFmt = "markdown" } = args;
|
|
314
|
-
const report = getCapabilities(db.getDatabase(), WYRM_TOOL_COUNT, {
|
|
315
|
-
detectVectorProvider: () => {
|
|
316
|
-
if (process.env.WYRM_VECTOR_PROVIDER === 'openai')
|
|
317
|
-
return 'openai';
|
|
318
|
-
return 'ollama';
|
|
319
|
-
},
|
|
320
|
-
hasEncryption: () => !!process.env.WYRM_ENCRYPTION_KEY,
|
|
321
|
-
isFederationEnabled: () => true,
|
|
322
|
-
isAgentRunning: () => {
|
|
323
|
-
try {
|
|
324
|
-
return agentDaemon.status().running;
|
|
325
|
-
}
|
|
326
|
-
catch {
|
|
327
|
-
return null;
|
|
328
|
-
}
|
|
329
|
-
},
|
|
330
|
-
});
|
|
331
|
-
if (capFmt === 'json') {
|
|
332
|
-
return { content: [{ type: 'text', text: JSON.stringify(report, null, 2) }] };
|
|
333
|
-
}
|
|
334
|
-
return { content: [{ type: 'text', text: renderCapabilityBriefing(report) }] };
|
|
335
|
-
},
|
|
336
|
-
},
|
|
337
|
-
{
|
|
338
|
-
name: "wyrm_intro",
|
|
339
|
-
description: "Return a plain-English explanation of what Wyrm is and what it does. Aimed at HUMANS who don't yet understand Wyrm's value — co-founders, operators, designers, anyone who didn't read the docs. Call this when a human user asks 'what does Wyrm even do?' or seems unaware Wyrm is involved in their AI assistant's behavior. NOT for AI-agent self-orientation (use wyrm_capabilities for that).",
|
|
340
|
-
inputSchema: {
|
|
341
|
-
type: "object",
|
|
342
|
-
properties: {},
|
|
343
|
-
},
|
|
344
|
-
annotations: TOOL_ANNOTATIONS["wyrm_intro"],
|
|
345
|
-
aliases: [],
|
|
346
|
-
handler: async (args, ctx) => {
|
|
347
|
-
const { WYRM_PACKAGE_VERSION } = ctx;
|
|
348
|
-
const { renderIntro } = await import('../visibility.js');
|
|
349
|
-
return { content: [{ type: 'text', text: renderIntro(WYRM_PACKAGE_VERSION) }] };
|
|
350
|
-
},
|
|
351
|
-
},
|
|
352
|
-
{
|
|
353
|
-
name: "wyrm_migrate_prompt",
|
|
354
|
-
description: "Rewrite the Wyrm-managed block in this project's AI-client instruction files (.cursor/rules, .github/copilot-instructions.md, CLAUDE.md, etc.) to the current canonical version. Operator-authored content outside the <!-- wyrm:start --> / <!-- wyrm:end --> markers is preserved verbatim. Dry-run by default; pass apply:true to write changes.",
|
|
355
|
-
inputSchema: {
|
|
356
|
-
type: "object",
|
|
357
|
-
properties: {
|
|
358
|
-
project_path: { type: "string", description: "Project root containing the client config files." },
|
|
359
|
-
apply: { type: "boolean", description: "Default false (dry-run). Set true to actually write changes." },
|
|
360
|
-
},
|
|
361
|
-
required: ["project_path"],
|
|
362
|
-
},
|
|
363
|
-
annotations: TOOL_ANNOTATIONS["wyrm_migrate_prompt"],
|
|
364
|
-
aliases: [],
|
|
365
|
-
handler: async (args, ctx) => {
|
|
366
|
-
const { migrateProject, renderMigrationReport } = await import('../migrate-prompt.js');
|
|
367
|
-
const { WYRM_INJECT_BLOCK } = await import('../autoconfig.js');
|
|
368
|
-
const { project_path: mpPath, apply: mpApply = false } = args;
|
|
369
|
-
if (!mpPath) {
|
|
370
|
-
return { content: [{ type: 'text', text: 'project_path required' }], isError: true };
|
|
371
|
-
}
|
|
372
|
-
const results = migrateProject({ projectPath: mpPath, newBlock: WYRM_INJECT_BLOCK, apply: mpApply });
|
|
373
|
-
return { content: [{ type: 'text', text: renderMigrationReport(results, mpApply) }] };
|
|
374
|
-
},
|
|
375
|
-
},
|
|
376
|
-
{
|
|
377
|
-
name: "wyrm_digest",
|
|
378
|
-
description: "Render a plain-English summary of what Wyrm has done for the operator over a period. Shows counts (sessions tracked, quests completed, repeated failures blocked, ground truths set, references clipped, hours logged) and highlights so a non-technical operator can see Wyrm's actual contribution. Use this when the user asks 'what did Wyrm do?', 'is Wyrm doing anything?', or to demonstrate value to skeptics.",
|
|
379
|
-
inputSchema: {
|
|
380
|
-
type: "object",
|
|
381
|
-
properties: {
|
|
382
|
-
period: { type: "string", enum: ["today", "week", "month", "quarter", "year", "all"], description: "Reporting window (default: week)." },
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
annotations: TOOL_ANNOTATIONS["wyrm_digest"],
|
|
386
|
-
aliases: [],
|
|
387
|
-
handler: async (args, ctx) => {
|
|
388
|
-
const { db } = ctx;
|
|
389
|
-
const { gatherDigest, renderDigest } = await import('../visibility.js');
|
|
390
|
-
const { period = 'week' } = args;
|
|
391
|
-
const data = gatherDigest(db.getDatabase(), period);
|
|
392
|
-
return { content: [{ type: 'text', text: renderDigest(data) }] };
|
|
393
|
-
},
|
|
394
|
-
},
|
|
395
|
-
{
|
|
396
|
-
name: "wyrm_check_update",
|
|
397
|
-
description: "Check whether a newer wyrm-mcp is available on npm. Cached 24h by default; pass force:true to bypass cache.",
|
|
398
|
-
inputSchema: {
|
|
399
|
-
type: "object",
|
|
400
|
-
properties: {
|
|
401
|
-
force: { type: "boolean", description: "Bypass the 24-hour cache and re-query the registry." },
|
|
402
|
-
},
|
|
403
|
-
},
|
|
404
|
-
annotations: TOOL_ANNOTATIONS["wyrm_check_update"],
|
|
405
|
-
aliases: [],
|
|
406
|
-
handler: async (args, ctx) => {
|
|
407
|
-
const { WYRM_PACKAGE_VERSION, db } = ctx;
|
|
408
|
-
const { force = false } = args;
|
|
409
|
-
const status = await getUpdateStatus(db.getDatabase(), WYRM_PACKAGE_VERSION, { force });
|
|
410
|
-
let text = ` **Update check**\n\n- Current: ${status.current}\n- Latest: ${status.latest ?? 'unknown (offline?)'}\n- Update available: ${status.updateAvailable ? 'yes' : 'no'}\n- Checked: ${status.checkedAt} (${status.source})`;
|
|
411
|
-
if (status.updateAvailable) {
|
|
412
|
-
text += `\n\nRun \`wyrm_self_update\` with \`confirm: true\` to upgrade, or \`npm install -g wyrm-mcp@latest\` from your shell.`;
|
|
413
|
-
}
|
|
414
|
-
return { content: [{ type: 'text', text }] };
|
|
415
|
-
},
|
|
416
|
-
},
|
|
417
|
-
{
|
|
418
|
-
name: "wyrm_self_update",
|
|
419
|
-
description: "Run `npm install -g wyrm-mcp@latest` to upgrade. Returns the install transcript. Requires the operator to have write access to the global npm prefix.",
|
|
420
|
-
inputSchema: {
|
|
421
|
-
type: "object",
|
|
422
|
-
properties: {
|
|
423
|
-
confirm: { type: "boolean", description: "Must be true to actually run the upgrade (safety guard)." },
|
|
424
|
-
},
|
|
425
|
-
required: ["confirm"],
|
|
426
|
-
},
|
|
427
|
-
annotations: TOOL_ANNOTATIONS["wyrm_self_update"],
|
|
428
|
-
aliases: [],
|
|
429
|
-
handler: async (args, ctx) => {
|
|
430
|
-
const { confirm: selfConfirm = false } = args;
|
|
431
|
-
if (!selfConfirm) {
|
|
432
|
-
return {
|
|
433
|
-
content: [{
|
|
434
|
-
type: 'text',
|
|
435
|
-
text: ' **Self-update declined**: call again with `confirm: true` to run `npm install -g wyrm-mcp@latest`. Note: requires write access to the global npm prefix.',
|
|
436
|
-
}],
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
const transcript = await new Promise((resolve) => {
|
|
440
|
-
const proc = cpSpawn('npm', ['install', '-g', 'wyrm-mcp@latest'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
441
|
-
const chunks = [];
|
|
442
|
-
proc.stdout.on('data', (b) => chunks.push(b.toString()));
|
|
443
|
-
proc.stderr.on('data', (b) => chunks.push(b.toString()));
|
|
444
|
-
proc.on('close', (code) => {
|
|
445
|
-
chunks.push(`\n[exit ${code ?? 'unknown'}]`);
|
|
446
|
-
resolve(chunks.join(''));
|
|
447
|
-
});
|
|
448
|
-
proc.on('error', (err) => resolve(`spawn failed: ${err.message}`));
|
|
449
|
-
});
|
|
450
|
-
return {
|
|
451
|
-
content: [{
|
|
452
|
-
type: 'text',
|
|
453
|
-
text: ` **Self-update transcript**\n\n\`\`\`\n${transcript}\n\`\`\`\n\nRestart your MCP client to pick up the new binary.`,
|
|
454
|
-
}],
|
|
455
|
-
};
|
|
456
|
-
},
|
|
457
|
-
},
|
|
458
|
-
];
|
|
459
|
-
//# sourceMappingURL=companion.js.map
|
|
1
|
+
import{TOOL_ANNOTATIONS as l}from"../tool-annotations.js";import{injectSystemPrompt as h}from"../autoconfig.js";import{buildPeerBuddyReply as g}from"../buddy.js";import{getCapabilities as f,renderCapabilityBriefing as w}from"../capabilities.js";import{getUpdateStatus as j}from"../version-check.js";import{isCompanionBuddyCall as b}from"./alias-adapters.js";import{spawn as _}from"child_process";const R=[{name:"wyrm_inject_prompt",description:"Opt-in: inject a Wyrm session-prime instruction block into .github/copilot-instructions.md and/or .cursor/rules for a project. Uses managed markers so re-runs are safe.",inputSchema:{type:"object",properties:{project_path:{type:"string",description:"Absolute path to the project root"},clients:{type:"array",items:{type:"string"},description:"Clients to inject into: 'copilot', 'cursor' (default: both detected)"}},required:["project_path"]},annotations:l.wyrm_inject_prompt,aliases:[],handler:async(o,c)=>{const{project_path:i,clients:a}=o,t=h(i,a??[]);let e=`\u{F115D} **System Prompt Injection**
|
|
2
|
+
|
|
3
|
+
`;return t.injected.length>0&&(e+=`\u2705 Injected into:
|
|
4
|
+
${t.injected.map(r=>`- ${r}`).join(`
|
|
5
|
+
`)}
|
|
6
|
+
|
|
7
|
+
`),t.skipped.length>0&&(e+=`\u25CB Skipped (unknown client): ${t.skipped.join(", ")}
|
|
8
|
+
|
|
9
|
+
`),t.errors.length>0&&(e+=`\u274C Errors:
|
|
10
|
+
${t.errors.map(r=>`- ${r}`).join(`
|
|
11
|
+
`)}
|
|
12
|
+
|
|
13
|
+
`),t.injected.length>0&&(e+="AI models in this project will now call `wyrm_session_prime` at the start of each conversation."),{content:[{type:"text",text:e}]}}},{name:"buddy",description:"Use when another buddy-compatible MCP server (or the operator) asks Wyrm for a brief, data-grounded status reply - the Buddy Protocol v1.0 well-known entry point. Companion params switch to the full companion reply; bare calls stay protocol-pure. Cycle-protected.",inputSchema:{type:"object",properties:{from_buddy:{type:"string",description:"Caller identity"},project_hint:{type:"string",description:"Scope the reply"},mood_hint:{type:"string",enum:["normal","celebratory","stuck","quiet"]},size:{type:"string",enum:["full","compact","mini"]},format:{type:"string",enum:["markdown","json"],description:"Peer mode only."},project_path:{type:"string",description:"Companion mode: project root (default cwd)"},persona:{type:"string",enum:["wyrm","drogo","berlin","sumair","custom"],description:"Companion voice."},persona_name:{type:"string",description:"For persona=custom"},mood:{type:"string",description:"Companion override (mood_hint values)"},federate:{type:"boolean",description:"Fold in other buddy MCPs"}}},annotations:l.buddy,aliases:[],handler:async(o,c)=>{const{WYRM_PACKAGE_VERSION:i,db:a,runCompanionBuddy:t}=c,e=o||{};if(b(o??{}))return await t(o??{});const r=o,s=g(a.getDatabase(),r,i);return r.format==="json"?{content:[{type:"text",text:JSON.stringify(s.json,null,2)}]}:{content:[{type:"text",text:s.markdown}]}}},{name:"wyrm_buddy",description:"Friendly, data-grounded coding companion. Returns a brief greeting + project state + suggested next step sourced entirely from Wyrm's real data. Every claim cites a real DB row ID \u2014 no hallucinated encouragement. Personas: wyrm (default, dragon-themed), drogo (gruff), berlin (precise), sumair (warm), custom. Moods: normal / celebratory / stuck / quiet \u2014 auto-detected. Sizes: full (10-line PhantomDragon-style mascot), compact (5-line workspace-friendly), mini (single-line inline prefix). Federates with other registered MCPs that expose `buddy`, `*_buddy`, or `buddy_*` tools \u2014 their replies fold into a 'From other buddies' section.",inputSchema:{type:"object",properties:{project_path:{type:"string",description:"Project root. Default: current cwd if registered."},mood:{type:"string",enum:["normal","celebratory","stuck","quiet"],description:"Override the auto-detected mood."},persona:{type:"string",enum:["wyrm","drogo","berlin","sumair","custom"],description:"Voice. Default: WYRM_BUDDY_DEFAULT_PERSONA env or 'wyrm'."},persona_name:{type:"string",description:"Required when persona === 'custom'."},size:{type:"string",enum:["full","compact","mini"],description:"Mascot size. 'full' = 10-line head+shoulder banner (default), 'compact' = 5-line workspace-friendly, 'mini' = single-line inline prefix on the greeting."},federate:{type:"boolean",description:"Query other registered MCPs with *_buddy tools and fold their replies in. Default: true if any are registered."}}},annotations:l.wyrm_buddy,aliases:[],handler:async(o,c)=>{const{runCompanionBuddy:i}=c;return await i(o??{})}},{name:"wyrm_token_set",description:"Set a design token for a project. Tokens are colour / type / spacing / motion / shadow / radius / breakpoint / custom \u2014 the design system primitives the project is built on. Stored first-class so AI helpers working on creative tasks don't have to re-derive the system from scattered CSS each time. Upserts on (project_id, category, key).",inputSchema:{type:"object",properties:{projectPath:{type:"string",description:"Project root path."},category:{type:"string",enum:["color","type","spacing","motion","shadow","radius","breakpoint","custom"],description:"Token category."},key:{type:"string",description:"Short slug, e.g. 'primary' / 'h1' / 'page-padding-md'."},value:{type:"string",description:"Actual value: '#00B89F' / 'Inter 900 2.5rem' / '1.25rem' / etc."},notes:{type:"string",description:"Optional why / when-to-use guidance."},source:{type:"string",enum:["user","derived","imported","observed"],description:"How the token was determined. Default: 'user'."}},required:["projectPath","category","key","value"]},annotations:l.wyrm_token_set,aliases:[],handler:async(o,c)=>{const{db:i,designSystem:a}=c,{projectPath:t,category:e,key:r,value:s,notes:p,source:u}=o,n=i.getProject(t);if(!n)return{content:[{type:"text",text:`Project not found: ${t}`}],isError:!0};const d=a().setToken({projectId:n.id,category:e,key:r,value:s,notes:p,source:u});return{content:[{type:"text",text:`\u{1F3A8} token set: \`${d.category}/${d.key}\` = \`${d.value}\``+(d.notes?` \u2014 ${d.notes}`:"")}]}}},{name:"wyrm_token_get",description:"Retrieve all design tokens for a project, optionally filtered by category. Returns the design system primitives the project is built on.",inputSchema:{type:"object",properties:{projectPath:{type:"string",description:"Project root path."},category:{type:"string",enum:["color","type","spacing","motion","shadow","radius","breakpoint","custom"],description:"Filter by category. Omit for all tokens."}},required:["projectPath"]},annotations:l.wyrm_token_get,aliases:[],handler:async(o,c)=>{const{db:i,designSystem:a}=c,{projectPath:t,category:e}=o,r=i.getProject(t);if(!r)return{content:[{type:"text",text:`Project not found: ${t}`}],isError:!0};const s=a().formatForContext(r.id);if(!s)return{content:[{type:"text",text:`_(no design tokens for ${r.name} yet \u2014 use \`wyrm_token_set\` to start the design system)_`}]};if(e){const p=a().listTokens(r.id,e);if(p.length===0)return{content:[{type:"text",text:`_(no ${e} tokens for ${r.name})_`}]};const u=[`### \u{1F3A8} ${e} tokens for ${r.name}`,""];for(const n of p)u.push(`- \`${n.key}\` = \`${n.value}\`${n.notes?` \u2014 ${n.notes}`:""}`);return{content:[{type:"text",text:u.join(`
|
|
14
|
+
`)}]}}return{content:[{type:"text",text:s}]}}},{name:"wyrm_token_delete",description:"Remove a design token from a project.",inputSchema:{type:"object",properties:{projectPath:{type:"string",description:"Project root path."},category:{type:"string",enum:["color","type","spacing","motion","shadow","radius","breakpoint","custom"]},key:{type:"string",description:"Token key to remove."}},required:["projectPath","category","key"]},annotations:l.wyrm_token_delete,aliases:[],handler:async(o,c)=>{const{db:i,designSystem:a}=c,{projectPath:t,category:e,key:r}=o,s=i.getProject(t);return s?{content:[{type:"text",text:a().deleteToken(s.id,e,r)?`\u{1F5D1} removed \`${e}/${r}\``:`not found: \`${e}/${r}\``}]}:{content:[{type:"text",text:`Project not found: ${t}`}],isError:!0}}},{name:"wyrm_reference_add",description:"Clip a design reference (URL, image path, palette, or inline snippet) for inspiration. Stored per-project (or globally if no project path). Tag aggressively \u2014 tags drive future search and recall when building a new project in the same vein.",inputSchema:{type:"object",properties:{projectPath:{type:"string",description:"Project root path. Omit to attach as a global reference."},kind:{type:"string",enum:["url","image","palette","snippet"],description:"Reference type."},location:{type:"string",description:"URL, file path, or inline payload (e.g. palette like '#00B89F,#ff5a55,#0a0c0e' or a code snippet)."},title:{type:"string",description:"Short title \u2014 what is this reference?"},notes:{type:"string",description:"Why you saved it / what to remember about it."},tags:{type:"string",description:"Comma-separated tags \u2014 'hero,scroll-tied,framer-motion'."}},required:["kind","location"]},annotations:l.wyrm_reference_add,aliases:[],handler:async(o,c)=>{const{db:i,designSystem:a}=c,{projectPath:t,kind:e,location:r,title:s,notes:p,tags:u}=o;let n=null;if(t){const m=i.getProject(t);if(!m)return{content:[{type:"text",text:`Project not found: ${t}`}],isError:!0};n=m.id}const d=a().addReference({projectId:n,kind:e,location:r,title:s,notes:p,tags:u}),y=n?` (project ${n})`:" (global)";return{content:[{type:"text",text:`\u{1F4CC} reference #${d.id} saved${y}: \`${d.kind}\` ${d.title??d.location.slice(0,60)}${d.tags?` \xB7 tags: ${d.tags}`:""}`}]}}},{name:"wyrm_reference_list",description:"Browse saved design references. Filter by project or tag. Default: 50 most recent across all projects.",inputSchema:{type:"object",properties:{projectPath:{type:"string",description:"Limit to a specific project."},tag:{type:"string",description:"Filter to references containing this tag."},limit:{type:"number",description:"Max results (default 50, max 200)."}}},annotations:l.wyrm_reference_list,aliases:[],handler:async(o,c)=>{const{db:i,designSystem:a}=c,{projectPath:t,tag:e,limit:r}=o;let s;if(t){const n=i.getProject(t);if(!n)return{content:[{type:"text",text:`Project not found: ${t}`}],isError:!0};s=n.id}const p=a().listReferences({projectId:s,tag:e,limit:r});if(p.length===0)return{content:[{type:"text",text:"_(no references match)_"}]};const u=[`\u{1F4CC} **${p.length} reference${p.length===1?"":"s"}**`];for(const n of p){const d=n.project_id?`p${n.project_id}`:"global";u.push(`- [${n.id}/${d}] \`${n.kind}\` ${n.title??n.location.slice(0,60)}${n.tags?` \xB7 ${n.tags}`:""}`)}return{content:[{type:"text",text:u.join(`
|
|
15
|
+
`)}]}}},{name:"wyrm_reference_search",description:"Full-text search across design references' title / notes / tags. Returns matching references sorted by recency.",inputSchema:{type:"object",properties:{query:{type:"string",description:"FTS5 query \u2014 keywords, phrases in quotes."},projectPath:{type:"string",description:"Limit to a specific project."},limit:{type:"number",description:"Max results (default 20, max 100)."}},required:["query"]},annotations:l.wyrm_reference_search,aliases:[],handler:async(o,c)=>{const{db:i,designSystem:a}=c,{query:t,projectPath:e,limit:r}=o;let s;if(e){const n=i.getProject(e);if(!n)return{content:[{type:"text",text:`Project not found: ${e}`}],isError:!0};s=n.id}const p=a().searchReferences(t,{projectId:s,limit:r});if(p.length===0)return{content:[{type:"text",text:`_(no references match "${t}")_`}]};const u=[`\u{1F50D} **${p.length} reference${p.length===1?"":"s"}** matching "${t}"`];for(const n of p){const d=n.project_id?`p${n.project_id}`:"global";u.push(`- [${n.id}/${d}] \`${n.kind}\` ${n.title??n.location.slice(0,60)}${n.tags?` \xB7 ${n.tags}`:""}`)}return{content:[{type:"text",text:u.join(`
|
|
16
|
+
`)}]}}},{name:"wyrm_capabilities",description:"Use to learn what your memory system can actually do - feature inventory, why each matters, runtime state, and which tool to reach for. Call at session start instead of re-discovering the surface.",inputSchema:{type:"object",properties:{format:{type:"string",enum:["json","markdown"]}}},annotations:l.wyrm_capabilities,aliases:[],handler:async(o,c)=>{const{WYRM_TOOL_COUNT:i,agentDaemon:a,db:t}=c,{format:e="markdown"}=o,r=f(t.getDatabase(),i,{detectVectorProvider:()=>process.env.WYRM_VECTOR_PROVIDER==="openai"?"openai":"ollama",hasEncryption:()=>!!process.env.WYRM_ENCRYPTION_KEY,isFederationEnabled:()=>!0,isAgentRunning:()=>{try{return a.status().running}catch{return null}}});return e==="json"?{content:[{type:"text",text:JSON.stringify(r,null,2)}]}:{content:[{type:"text",text:w(r)}]}}},{name:"wyrm_intro",description:"Return a plain-English explanation of what Wyrm is and what it does. Aimed at HUMANS who don't yet understand Wyrm's value \u2014 co-founders, operators, designers, anyone who didn't read the docs. Call this when a human user asks 'what does Wyrm even do?' or seems unaware Wyrm is involved in their AI assistant's behavior. NOT for AI-agent self-orientation (use wyrm_capabilities for that).",inputSchema:{type:"object",properties:{}},annotations:l.wyrm_intro,aliases:[],handler:async(o,c)=>{const{WYRM_PACKAGE_VERSION:i}=c,{renderIntro:a}=await import("../visibility.js");return{content:[{type:"text",text:a(i)}]}}},{name:"wyrm_migrate_prompt",description:"Rewrite the Wyrm-managed block in this project's AI-client instruction files (.cursor/rules, .github/copilot-instructions.md, CLAUDE.md, etc.) to the current canonical version. Operator-authored content outside the <!-- wyrm:start --> / <!-- wyrm:end --> markers is preserved verbatim. Dry-run by default; pass apply:true to write changes.",inputSchema:{type:"object",properties:{project_path:{type:"string",description:"Project root containing the client config files."},apply:{type:"boolean",description:"Default false (dry-run). Set true to actually write changes."}},required:["project_path"]},annotations:l.wyrm_migrate_prompt,aliases:[],handler:async(o,c)=>{const{migrateProject:i,renderMigrationReport:a}=await import("../migrate-prompt.js"),{WYRM_INJECT_BLOCK:t}=await import("../autoconfig.js"),{project_path:e,apply:r=!1}=o;if(!e)return{content:[{type:"text",text:"project_path required"}],isError:!0};const s=i({projectPath:e,newBlock:t,apply:r});return{content:[{type:"text",text:a(s,r)}]}}},{name:"wyrm_digest",description:"Render a plain-English summary of what Wyrm has done for the operator over a period. Shows counts (sessions tracked, quests completed, repeated failures blocked, ground truths set, references clipped, hours logged) and highlights so a non-technical operator can see Wyrm's actual contribution. Use this when the user asks 'what did Wyrm do?', 'is Wyrm doing anything?', or to demonstrate value to skeptics.",inputSchema:{type:"object",properties:{period:{type:"string",enum:["today","week","month","quarter","year","all"],description:"Reporting window (default: week)."}}},annotations:l.wyrm_digest,aliases:[],handler:async(o,c)=>{const{db:i}=c,{gatherDigest:a,renderDigest:t}=await import("../visibility.js"),{period:e="week"}=o,r=a(i.getDatabase(),e);return{content:[{type:"text",text:t(r)}]}}},{name:"wyrm_check_update",description:"Check whether a newer wyrm-mcp is available on npm. Cached 24h by default; pass force:true to bypass cache.",inputSchema:{type:"object",properties:{force:{type:"boolean",description:"Bypass the 24-hour cache and re-query the registry."}}},annotations:l.wyrm_check_update,aliases:[],handler:async(o,c)=>{const{WYRM_PACKAGE_VERSION:i,db:a}=c,{force:t=!1}=o,e=await j(a.getDatabase(),i,{force:t});let r=`\u{F115D} **Update check**
|
|
17
|
+
|
|
18
|
+
- Current: ${e.current}
|
|
19
|
+
- Latest: ${e.latest??"unknown (offline?)"}
|
|
20
|
+
- Update available: ${e.updateAvailable?"yes":"no"}
|
|
21
|
+
- Checked: ${e.checkedAt} (${e.source})`;return e.updateAvailable&&(r+="\n\nRun `wyrm_self_update` with `confirm: true` to upgrade, or `npm install -g wyrm-mcp@latest` from your shell."),{content:[{type:"text",text:r}]}}},{name:"wyrm_self_update",description:"Run `npm install -g wyrm-mcp@latest` to upgrade. Returns the install transcript. Requires the operator to have write access to the global npm prefix.",inputSchema:{type:"object",properties:{confirm:{type:"boolean",description:"Must be true to actually run the upgrade (safety guard)."}},required:["confirm"]},annotations:l.wyrm_self_update,aliases:[],handler:async(o,c)=>{const{confirm:i=!1}=o;return i?{content:[{type:"text",text:`\u{F115D} **Self-update transcript**
|
|
22
|
+
|
|
23
|
+
\`\`\`
|
|
24
|
+
${await new Promise(t=>{const e=_("npm",["install","-g","wyrm-mcp@latest"],{stdio:["ignore","pipe","pipe"]}),r=[];e.stdout.on("data",s=>r.push(s.toString())),e.stderr.on("data",s=>r.push(s.toString())),e.on("close",s=>{r.push(`
|
|
25
|
+
[exit ${s??"unknown"}]`),t(r.join(""))}),e.on("error",s=>t(`spawn failed: ${s.message}`))})}
|
|
26
|
+
\`\`\`
|
|
27
|
+
|
|
28
|
+
Restart your MCP client to pick up the new binary.`}]}:{content:[{type:"text",text:"\u{F115D} **Self-update declined**: call again with `confirm: true` to run `npm install -g wyrm-mcp@latest`. Note: requires write access to the global npm prefix."}]}}}];export{R as companionToolSpecs};
|