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
package/dist/handlers/recall.js
CHANGED
|
@@ -1,218 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*
|
|
13
|
-
* @copyright 2026 Ghost Protocol (Pvt) Ltd.
|
|
14
|
-
* @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
|
|
15
|
-
*/
|
|
16
|
-
import { TOOL_ANNOTATIONS } from '../tool-annotations.js';
|
|
17
|
-
import { renderResult, withGlyph } from '../render.js';
|
|
18
|
-
import { memoryUri, resourceLink } from './resources.js';
|
|
19
|
-
export const recallToolSpecs = [
|
|
20
|
-
{
|
|
21
|
-
name: "wyrm_recall",
|
|
22
|
-
description: "Use before starting any non-trivial task - what do we know about this? Pull up relevant lessons learned, proven patterns, anti-patterns, and reasoning traces from past work. Hybrid lexical+semantic retrieval, fully local, no LLM. Mark what you recalled as useful (or not) with wyrm_feedback.",
|
|
23
|
-
inputSchema: {
|
|
24
|
-
type: "object",
|
|
25
|
-
properties: {
|
|
26
|
-
// v7 F3 (T026): property prose compressed to fund the hot-path
|
|
27
|
-
// outputSchemas under the 8K default-surface pin (T022/T025 trade).
|
|
28
|
-
projectPath: { type: "string" },
|
|
29
|
-
query: { type: "string", description: "The task or problem" },
|
|
30
|
-
kind: {
|
|
31
|
-
type: "string",
|
|
32
|
-
enum: ["reasoning_trace", "lesson", "pattern", "anti_pattern", "heuristic"],
|
|
33
|
-
},
|
|
34
|
-
limit: { type: "number", description: "Default 10" },
|
|
35
|
-
minConfidence: { type: "number", description: "0-1 (default 0)" },
|
|
36
|
-
// v7 F4 (T034): 'full' (default) inlines the complete result bodies;
|
|
37
|
-
// 'link' ALSO appends a wyrm://memory/{id} resource_link per result for
|
|
38
|
-
// resource-capable clients. Either way the full body rides — the link
|
|
39
|
-
// is additive, never a substitution (no data loss).
|
|
40
|
-
detail: { type: "string", enum: ["full", "link"], description: "Default full" },
|
|
41
|
-
},
|
|
42
|
-
required: ["projectPath", "query"],
|
|
43
|
-
},
|
|
44
|
-
outputSchema: {
|
|
45
|
-
type: "object",
|
|
46
|
-
properties: {
|
|
47
|
-
query: { type: "string" },
|
|
48
|
-
count: { type: "integer" },
|
|
49
|
-
results: {
|
|
50
|
-
type: "array",
|
|
51
|
-
items: {
|
|
52
|
-
type: "object",
|
|
53
|
-
properties: {
|
|
54
|
-
id: { type: "integer" },
|
|
55
|
-
kind: { type: "string" },
|
|
56
|
-
relevance: { type: "number" },
|
|
57
|
-
problem: { type: "string" },
|
|
58
|
-
// FEATHERWEIGHT review (major): constraints/why_it_worked/outcome/
|
|
59
|
-
// reuse_success_count carry the fix rationale + the negative-
|
|
60
|
-
// learning signal. They ride the body undeclared (declaring them
|
|
61
|
-
// here would push the default ListTools surface OVER the §7.1 8K
|
|
62
|
-
// pin). Losslessness under WYRM_CHANNEL=structured is instead
|
|
63
|
-
// guaranteed by recall being exemptStructured (handler below): its
|
|
64
|
-
// FULL per-result prose always rides the text channel, so the
|
|
65
|
-
// rationale never depends on a consumer preserving undeclared
|
|
66
|
-
// structured fields.
|
|
67
|
-
validated_fix: { type: ["string", "null"] },
|
|
68
|
-
confidence: { type: "number" },
|
|
69
|
-
reuse_count: { type: "integer" },
|
|
70
|
-
},
|
|
71
|
-
required: ["id", "kind", "relevance", "problem", "confidence", "reuse_count"],
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
required: ["query", "count", "results"],
|
|
76
|
-
},
|
|
77
|
-
annotations: TOOL_ANNOTATIONS.wyrm_recall,
|
|
78
|
-
aliases: [],
|
|
79
|
-
handler: async (args, { store, raw, memory, vectors, clientSupportsResources }) => {
|
|
80
|
-
const { projectPath: rcPath, query: rcQuery, kind: rcKind, limit: rcLimit, minConfidence: rcMinConf, detail: rcDetail } = args;
|
|
81
|
-
const rcProject = store.getProject(rcPath);
|
|
82
|
-
if (!rcProject)
|
|
83
|
-
return { content: [{ type: "text", text: `Project not found: ${rcPath}` }], isError: true };
|
|
84
|
-
// Hybrid (FTS ⊕ vectors, RRF) when a vector store is available; lexical otherwise.
|
|
85
|
-
const rcOpts = { kind: rcKind, limit: rcLimit ?? 10, minConfidence: rcMinConf };
|
|
86
|
-
const results = vectors()
|
|
87
|
-
? await memory.recallHybrid(rcProject.id, rcQuery, rcOpts)
|
|
88
|
-
: memory.recall(rcProject.id, rcQuery, rcOpts);
|
|
89
|
-
// Track access for memory decay
|
|
90
|
-
if (results.length > 0) {
|
|
91
|
-
const ids = results.map(r => r.artifact.id);
|
|
92
|
-
const placeholders = ids.map(() => '?').join(',');
|
|
93
|
-
raw().prepare(`UPDATE memory_artifacts SET last_accessed_at = datetime('now'), access_count = access_count + 1 WHERE id IN (${placeholders})`).run(...ids);
|
|
94
|
-
}
|
|
95
|
-
// FEATHERWEIGHT #5 — number & null hygiene (default, lossless):
|
|
96
|
-
// (a) `relevance` is an internal RRF/FTS ranking score in [0,1] the
|
|
97
|
-
// consumer only ever reads as an ORDER and renders as an integer %
|
|
98
|
-
// (text channel: `(relevance*100).toFixed(0)`). Its raw form carries
|
|
99
|
-
// up to 17 significant digits of float noise (0.9992261132463348)
|
|
100
|
-
// that no consumer compares on. Rounding to 4 dp (0.0001 resolution —
|
|
101
|
-
// 100× finer than the integer-% display and far below any tie the
|
|
102
|
-
// sort could surface) drops only excess precision, never a value a
|
|
103
|
-
// consumer distinguishes. `confidence` is rounded the same way (it is
|
|
104
|
-
// stored ≤2 dp; the round is a no-op on clean rows and a safety clamp
|
|
105
|
-
// on any future sub-percent float).
|
|
106
|
-
// (b) `constraints`/`validated_fix`/`why_it_worked` are `string | null`.
|
|
107
|
-
// A null is the ABSENCE of that rationale — it carries no information,
|
|
108
|
-
// and the text derivation already guards each with a truthy check
|
|
109
|
-
// (`if (a.validated_fix) …`), so an absent key reads identically to a
|
|
110
|
-
// null one for every consumer. Omitting the key when null is lossless
|
|
111
|
-
// null-elision (a present non-null value is ALWAYS kept). `outcome`,
|
|
112
|
-
// `reuse_count`, `reuse_success_count` are non-null by construction
|
|
113
|
-
// (enum default 'neutral' / integer counters) and ride unchanged.
|
|
114
|
-
const round4 = (n) => Math.round(n * 10000) / 10000;
|
|
115
|
-
const body = {
|
|
116
|
-
query: rcQuery,
|
|
117
|
-
count: results.length,
|
|
118
|
-
results: results.map((r) => {
|
|
119
|
-
const a = r.artifact;
|
|
120
|
-
const result = {
|
|
121
|
-
id: a.id,
|
|
122
|
-
kind: a.kind,
|
|
123
|
-
relevance: round4(r.relevance_score),
|
|
124
|
-
problem: a.problem,
|
|
125
|
-
outcome: a.outcome,
|
|
126
|
-
// round4(null) === 0 in JS, which would present an UNKNOWN
|
|
127
|
-
// confidence as a meaningful 0%. The `confidence` column is `REAL
|
|
128
|
-
// DEFAULT 1.0` but NOT NULL-constrained (migrations.ts), so a
|
|
129
|
-
// synced/foreign row can carry null; preserve it rather than
|
|
130
|
-
// coerce. round4 only ever drops excess float precision (lossless).
|
|
131
|
-
confidence: a.confidence == null ? a.confidence : round4(a.confidence),
|
|
132
|
-
reuse_count: a.reuse_count,
|
|
133
|
-
reuse_success_count: a.reuse_success_count,
|
|
134
|
-
};
|
|
135
|
-
// Lossless null-elision: include the rationale fields only when they
|
|
136
|
-
// carry a value (a null = no rationale = nothing to transmit; the text
|
|
137
|
-
// derivation already guards each with a truthy check, so an absent key
|
|
138
|
-
// reads identically to a null one for every consumer).
|
|
139
|
-
if (a.constraints != null)
|
|
140
|
-
result.constraints = a.constraints;
|
|
141
|
-
if (a.validated_fix != null)
|
|
142
|
-
result.validated_fix = a.validated_fix;
|
|
143
|
-
if (a.why_it_worked != null)
|
|
144
|
-
result.why_it_worked = a.why_it_worked;
|
|
145
|
-
return result;
|
|
146
|
-
}),
|
|
147
|
-
};
|
|
148
|
-
const rendered = renderResult(body, (b, g) => {
|
|
149
|
-
if (b.count === 0) {
|
|
150
|
-
return withGlyph(g.brand, `No relevant memory found for: "${b.query}"`) +
|
|
151
|
-
`\n\nUse \`wyrm_remember\` to store knowledge as you work.`;
|
|
152
|
-
}
|
|
153
|
-
let text = withGlyph(g.brand, `**Memory Recall** -- "${b.query}" (${b.count} found)`) + '\n\n';
|
|
154
|
-
for (const a of b.results) {
|
|
155
|
-
text += `### ${a.kind} (ID: ${a.id}) -- relevance ${(a.relevance * 100).toFixed(0)}%\n`;
|
|
156
|
-
text += `**Problem:** ${a.problem}\n`;
|
|
157
|
-
if (a.constraints)
|
|
158
|
-
text += `**Constraints:** ${a.constraints}\n`;
|
|
159
|
-
if (a.validated_fix)
|
|
160
|
-
text += `**Solution:** ${a.validated_fix}\n`;
|
|
161
|
-
if (a.why_it_worked)
|
|
162
|
-
text += `**Why:** ${a.why_it_worked}\n`;
|
|
163
|
-
if (a.outcome === 'negative')
|
|
164
|
-
text += withGlyph(g.warn, `_This approach failed -- see solution for what to do instead_`) + '\n';
|
|
165
|
-
// Mirror the structured-body null guard (FW follow-up second-round):
|
|
166
|
-
// a synced/foreign row can carry a null confidence (`REAL DEFAULT 1.0`
|
|
167
|
-
// but NOT NULL-constrained in migrations.ts). null * 100 === 0 in JS
|
|
168
|
-
// would render an UNKNOWN confidence as a meaningful "0%" on the text
|
|
169
|
-
// channel — the SAME invented-value bug the minors commit fixed in the
|
|
170
|
-
// structured body, but on recall's dominant (exemptStructured) channel.
|
|
171
|
-
// Render "unknown" so unknown ≠ 0%.
|
|
172
|
-
const confStr = a.confidence == null ? 'unknown' : `${(a.confidence * 100).toFixed(0)}%`;
|
|
173
|
-
text += `_Confidence: ${confStr} | Used ${a.reuse_count}x | Success rate: ${a.reuse_count > 0 ? ((a.reuse_success_count / a.reuse_count) * 100).toFixed(0) + '%' : 'not yet used'}_\n\n`;
|
|
174
|
-
}
|
|
175
|
-
text += `_Use \`wyrm_feedback\` to record whether these were helpful._`;
|
|
176
|
-
return text;
|
|
177
|
-
}, {
|
|
178
|
-
// FEATHERWEIGHT review (major): recall's per-result rationale lives in
|
|
179
|
-
// body fields NOT declared in outputSchema (declaring them would push
|
|
180
|
-
// the default ListTools surface over the §7.1 8K pin). A strict harness
|
|
181
|
-
// that trims structuredContent to declared properties under
|
|
182
|
-
// WYRM_CHANNEL=structured would therefore drop the fix rationale + the
|
|
183
|
-
// negative-learning signal — UNLESS the text channel keeps carrying the
|
|
184
|
-
// full prose. So recall is exemptStructured: its complete per-result
|
|
185
|
-
// detail (problem/constraints/validated_fix/why_it_worked/outcome) rides
|
|
186
|
-
// the text channel on EVERY channel policy, never collapsing to a one-
|
|
187
|
-
// line header. Losslessness is then independent of consumer schema-
|
|
188
|
-
// trimming — the hard-gate-5 contract.
|
|
189
|
-
exemptStructured: true,
|
|
190
|
-
});
|
|
191
|
-
// v7 F4 (T034): resourceLink affordance. The full result bodies ALWAYS
|
|
192
|
-
// ride above (the detail=full FALLBACK is the default and is never
|
|
193
|
-
// dropped — no data loss for any client). ADDITIONALLY, append one
|
|
194
|
-
// wyrm://memory/{id} resource_link per result so a resource-capable client
|
|
195
|
-
// can re-fetch the canonical artifact on demand without re-running recall.
|
|
196
|
-
// The gate is EITHER honest signal that the client can resolve a link:
|
|
197
|
-
// • the caller explicitly asked (detail='link') — an explicit request IS
|
|
198
|
-
// the client telling us it understands wyrm:// links; OR
|
|
199
|
-
// • the client advertised experimental.resources at initialize.
|
|
200
|
-
// detail='full' (the default) NEVER appends links — it is the resource-less
|
|
201
|
-
// fallback, the full inline body and nothing dangling. Either way the body
|
|
202
|
-
// is unchanged; the link is purely additive, so no client loses data and a
|
|
203
|
-
// resource-less client (no opt-in, no advertised capability) gets no link
|
|
204
|
-
// it cannot resolve. The links append to content[] AFTER the text block, so
|
|
205
|
-
// content[0].text + structuredContent are byte-identical to the base return.
|
|
206
|
-
const wantsLinks = rcDetail === 'link' || (rcDetail !== 'full' && !!clientSupportsResources?.());
|
|
207
|
-
if (wantsLinks && body.count > 0) {
|
|
208
|
-
const links = body.results.map((r) => resourceLink(memoryUri(r.id), `memory #${r.id} (${r.kind})`, {
|
|
209
|
-
description: r.problem.slice(0, 120),
|
|
210
|
-
mimeType: 'application/json',
|
|
211
|
-
}));
|
|
212
|
-
return { ...rendered, content: [...rendered.content, ...links] };
|
|
213
|
-
}
|
|
214
|
-
return rendered;
|
|
215
|
-
},
|
|
216
|
-
},
|
|
217
|
-
];
|
|
218
|
-
//# sourceMappingURL=recall.js.map
|
|
1
|
+
import{TOOL_ANNOTATIONS as x}from"../tool-annotations.js";import{renderResult as j,withGlyph as u}from"../render.js";import{memoryUri as q,resourceLink as P}from"./resources.js";const U=[{name:"wyrm_recall",description:"Use before starting any non-trivial task - what do we know about this? Pull up relevant lessons learned, proven patterns, anti-patterns, and reasoning traces from past work. Hybrid lexical+semantic retrieval, fully local, no LLM. Mark what you recalled as useful (or not) with wyrm_feedback.",inputSchema:{type:"object",properties:{projectPath:{type:"string"},query:{type:"string",description:"The task or problem"},kind:{type:"string",enum:["reasoning_trace","lesson","pattern","anti_pattern","heuristic"]},limit:{type:"number",description:"Default 10"},minConfidence:{type:"number",description:"0-1 (default 0)"},detail:{type:"string",enum:["full","link"],description:"Default full"}},required:["projectPath","query"]},outputSchema:{type:"object",properties:{query:{type:"string"},count:{type:"integer"},results:{type:"array",items:{type:"object",properties:{id:{type:"integer"},kind:{type:"string"},relevance:{type:"number"},problem:{type:"string"},validated_fix:{type:["string","null"]},confidence:{type:"number"},reuse_count:{type:"integer"}},required:["id","kind","relevance","problem","confidence","reuse_count"]}}},required:["query","count","results"]},annotations:x.wyrm_recall,aliases:[],handler:async(y,{store:_,raw:w,memory:l,vectors:h,clientSupportsResources:k})=>{const{projectPath:d,query:i,kind:b,limit:v,minConfidence:$,detail:p}=y,c=_.getProject(d);if(!c)return{content:[{type:"text",text:`Project not found: ${d}`}],isError:!0};const f={kind:b,limit:v??10,minConfidence:$},o=h()?await l.recallHybrid(c.id,i,f):l.recall(c.id,i,f);if(o.length>0){const r=o.map(n=>n.artifact.id),e=r.map(()=>"?").join(",");w().prepare(`UPDATE memory_artifacts SET last_accessed_at = datetime('now'), access_count = access_count + 1 WHERE id IN (${e})`).run(...r)}const m=r=>Math.round(r*1e4)/1e4,s={query:i,count:o.length,results:o.map(r=>{const e=r.artifact,n={id:e.id,kind:e.kind,relevance:m(r.relevance_score),problem:e.problem,outcome:e.outcome,confidence:e.confidence==null?e.confidence:m(e.confidence),reuse_count:e.reuse_count,reuse_success_count:e.reuse_success_count};return e.constraints!=null&&(n.constraints=e.constraints),e.validated_fix!=null&&(n.validated_fix=e.validated_fix),e.why_it_worked!=null&&(n.why_it_worked=e.why_it_worked),n})},a=j(s,(r,e)=>{if(r.count===0)return u(e.brand,`No relevant memory found for: "${r.query}"`)+"\n\nUse `wyrm_remember` to store knowledge as you work.";let n=u(e.brand,`**Memory Recall** -- "${r.query}" (${r.count} found)`)+`
|
|
2
|
+
|
|
3
|
+
`;for(const t of r.results){n+=`### ${t.kind} (ID: ${t.id}) -- relevance ${(t.relevance*100).toFixed(0)}%
|
|
4
|
+
`,n+=`**Problem:** ${t.problem}
|
|
5
|
+
`,t.constraints&&(n+=`**Constraints:** ${t.constraints}
|
|
6
|
+
`),t.validated_fix&&(n+=`**Solution:** ${t.validated_fix}
|
|
7
|
+
`),t.why_it_worked&&(n+=`**Why:** ${t.why_it_worked}
|
|
8
|
+
`),t.outcome==="negative"&&(n+=u(e.warn,"_This approach failed -- see solution for what to do instead_")+`
|
|
9
|
+
`);const g=t.confidence==null?"unknown":`${(t.confidence*100).toFixed(0)}%`;n+=`_Confidence: ${g} | Used ${t.reuse_count}x | Success rate: ${t.reuse_count>0?(t.reuse_success_count/t.reuse_count*100).toFixed(0)+"%":"not yet used"}_
|
|
10
|
+
|
|
11
|
+
`}return n+="_Use `wyrm_feedback` to record whether these were helpful._",n},{exemptStructured:!0});if((p==="link"||p!=="full"&&!!k?.())&&s.count>0){const r=s.results.map(e=>P(q(e.id),`memory #${e.id} (${e.kind})`,{description:e.problem.slice(0,120),mimeType:"application/json"}));return{...a,content:[...a.content,...r]}}return a}}];export{U as recallToolSpecs};
|
|
@@ -1,167 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Tool-handler registry (v7 A2; upgraded to the ToolSpec contract v2 in
|
|
3
|
-
* v7 F3 T018). Domain modules export `ToolSpec[]` — ONE object per tool
|
|
4
|
-
* carrying {name, description, inputSchema, outputSchema, annotations,
|
|
5
|
-
* examples, aliases, handler} — and this registry derives from those specs:
|
|
6
|
-
*
|
|
7
|
-
* (a) the DISPATCH map (`handlerRegistry`): the CallTool dispatcher consults
|
|
8
|
-
* it BEFORE the legacy `switch (name)` in index.ts, so an extracted tool
|
|
9
|
-
* is served from here while every tool still in the switch keeps its
|
|
10
|
-
* exact original path. Domains migrate in, one green-suite commit at a
|
|
11
|
-
* time, until the switch is empty (T036).
|
|
12
|
-
*
|
|
13
|
-
* (b) the ADVERTISED wire entries (`registryToolDefs`): merged with
|
|
14
|
-
* buildAllTools() in the ListTools handler, then canonicalized by
|
|
15
|
-
* `buildStableToolList` — a byte-stable, deterministically ordered list
|
|
16
|
-
* (stable tool order, stable key order, no Date/random anywhere in the
|
|
17
|
-
* serialization; locked by tests/listtools-byte-stability.test.ts).
|
|
18
|
-
*
|
|
19
|
-
* @copyright 2026 Ghost Protocol (Pvt) Ltd.
|
|
20
|
-
* @license AGPL-3.0-or-later
|
|
21
|
-
*/
|
|
22
|
-
import { goalToolSpecs } from './goals.js';
|
|
23
|
-
import { captureToolSpecs } from './capture.js';
|
|
24
|
-
import { recallToolSpecs } from './recall.js';
|
|
25
|
-
import { searchToolSpecs } from './search.js';
|
|
26
|
-
import { failureToolSpecs } from './failure.js';
|
|
27
|
-
import { questToolSpecs } from './quest.js';
|
|
28
|
-
import { sessionToolSpecs } from './session.js';
|
|
29
|
-
import { reviewToolSpecs } from './review.js';
|
|
30
|
-
import { runToolSpecs } from './run.js';
|
|
31
|
-
import { declaredOutputSchemas } from './output-schemas.js';
|
|
32
|
-
// v7 F4 (T036): the drained non-hot domains — every formerly switch-resident
|
|
33
|
-
// tool, lifted VERBATIM into per-domain ToolSpec modules behind the broad
|
|
34
|
-
// DispatcherContext slice. These complete the monolith drain (quest #80):
|
|
35
|
-
// buildAllTools() + the 142-case switch are deleted; index.ts ≤1,000 lines.
|
|
36
|
-
import { projectToolSpecs } from './project.js';
|
|
37
|
-
import { eventsToolSpecs } from './events.js';
|
|
38
|
-
import { skillToolSpecs } from './skill.js';
|
|
39
|
-
import { datalakeToolSpecs } from './datalake.js';
|
|
40
|
-
import { entityToolSpecs } from './entity.js';
|
|
41
|
-
import { intelligenceToolSpecs } from './intelligence.js';
|
|
42
|
-
import { orchestrationToolSpecs } from './orchestration.js';
|
|
43
|
-
import { cloudToolSpecs } from './cloud.js';
|
|
44
|
-
import { companionToolSpecs } from './companion.js';
|
|
45
|
-
import { syncopsToolSpecs } from './syncops.js';
|
|
46
|
-
import { presenceToolSpecs } from './presence.js';
|
|
47
|
-
import { causalityToolSpecs } from './causality.js';
|
|
48
|
-
import { symbolsToolSpecs } from './symbols.js';
|
|
49
|
-
import { invoicingToolSpecs } from './invoicing.js';
|
|
50
|
-
import { auditToolSpecs } from './audit.js';
|
|
51
|
-
import { shareToolSpecs } from './share.js';
|
|
52
|
-
import { agentToolSpecs } from './agent.js';
|
|
53
|
-
import { mcpclientToolSpecs } from './mcpclient.js';
|
|
54
|
-
/**
|
|
55
|
-
* Every ToolSpec from every migrated domain. A domain's specs are typed
|
|
56
|
-
* against its narrow context slice; they widen to ToolSpec<HandlerContext>
|
|
57
|
-
* here by structural contravariance (HandlerContext implements every slice).
|
|
58
|
-
* v7 F3 (T026): + the seven hot-path domains (capture write funnel, recall,
|
|
59
|
-
* search incl. constellation, failure, quest, session+prime, review).
|
|
60
|
-
*/
|
|
61
|
-
export const toolSpecs = [
|
|
62
|
-
...goalToolSpecs,
|
|
63
|
-
...captureToolSpecs,
|
|
64
|
-
...recallToolSpecs,
|
|
65
|
-
...searchToolSpecs,
|
|
66
|
-
...failureToolSpecs,
|
|
67
|
-
...questToolSpecs,
|
|
68
|
-
...sessionToolSpecs,
|
|
69
|
-
...reviewToolSpecs,
|
|
70
|
-
// v7 F3 (T027): the run loop — wyrm_run is a NEW first-class tool (the
|
|
71
|
-
// 32nd survivor), not an extraction; see handlers/run.ts + survivors.ts.
|
|
72
|
-
...runToolSpecs,
|
|
73
|
-
// v7 F4 (T036): the drained non-hot domains (quest #80). Typed against the
|
|
74
|
-
// broad DispatcherContext slice; they widen to ToolSpec<HandlerContext> here
|
|
75
|
-
// by the same structural contravariance (DispatcherContext extends
|
|
76
|
-
// HandlerContext). index.ts wires `dispatcherCtx` once and the registry
|
|
77
|
-
// dispatches every name from this list — the switch is gone.
|
|
78
|
-
...projectToolSpecs,
|
|
79
|
-
...eventsToolSpecs,
|
|
80
|
-
...skillToolSpecs,
|
|
81
|
-
...datalakeToolSpecs,
|
|
82
|
-
...entityToolSpecs,
|
|
83
|
-
...intelligenceToolSpecs,
|
|
84
|
-
...orchestrationToolSpecs,
|
|
85
|
-
...cloudToolSpecs,
|
|
86
|
-
...companionToolSpecs,
|
|
87
|
-
...syncopsToolSpecs,
|
|
88
|
-
...presenceToolSpecs,
|
|
89
|
-
...causalityToolSpecs,
|
|
90
|
-
...symbolsToolSpecs,
|
|
91
|
-
...invoicingToolSpecs,
|
|
92
|
-
...auditToolSpecs,
|
|
93
|
-
...shareToolSpecs,
|
|
94
|
-
...agentToolSpecs,
|
|
95
|
-
...mcpclientToolSpecs,
|
|
96
|
-
];
|
|
97
|
-
/** Tool-name → handler, derived from the specs (never built by hand). */
|
|
98
|
-
export const handlerRegistry = new Map(toolSpecs.map((spec) => [spec.name, spec.handler]));
|
|
99
|
-
/**
|
|
100
|
-
* Advertised ListTools entries for every registry-resident tool, derived from
|
|
101
|
-
* the SAME ToolSpec objects that carry the handlers — surface and behavior
|
|
102
|
-
* cannot drift. Annotations are deliberately NOT emitted here: the ListTools
|
|
103
|
-
* pipeline merges them centrally via annotateTools() (tool-annotations.ts)
|
|
104
|
-
* for switch- and registry-resident tools alike, and each ToolSpec.annotations
|
|
105
|
-
* is locked to be the same registry entry by tests/toolspec-registry.test.ts.
|
|
106
|
-
*/
|
|
107
|
-
export function registryToolDefs() {
|
|
108
|
-
return toolSpecs.map((spec) => ({
|
|
109
|
-
name: spec.name,
|
|
110
|
-
description: spec.description,
|
|
111
|
-
inputSchema: spec.inputSchema,
|
|
112
|
-
...(spec.outputSchema !== undefined ? { outputSchema: spec.outputSchema } : {}),
|
|
113
|
-
}));
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Attach declared outputSchemas (handlers/output-schemas.ts) to
|
|
117
|
-
* switch-resident tools that already return structuredContent — T014's
|
|
118
|
-
* wyrm_failure_check verdict is the first. Non-mutating; a tool that already
|
|
119
|
-
* carries an outputSchema (a ToolSpec one) is left untouched.
|
|
120
|
-
*/
|
|
121
|
-
export function applyDeclaredOutputSchemas(tools) {
|
|
122
|
-
return tools.map((tool) => {
|
|
123
|
-
const schema = declaredOutputSchemas[tool.name];
|
|
124
|
-
if (!schema || tool.outputSchema !== undefined)
|
|
125
|
-
return tool;
|
|
126
|
-
return { ...tool, outputSchema: schema };
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
// ── Byte-stable ListTools canonicalization (T018) ───────────────────────────
|
|
130
|
-
/** Canonical top-level key order for one advertised tool entry. */
|
|
131
|
-
const CANONICAL_TOOL_KEYS = ['name', 'description', 'inputSchema', 'outputSchema', 'annotations'];
|
|
132
|
-
/**
|
|
133
|
-
* Canonicalize the final advertised tool list so consecutive ListTools
|
|
134
|
-
* serializations are BYTE-IDENTICAL (spec §7.1):
|
|
135
|
-
*
|
|
136
|
-
* - stable TOOL order: sorted by name via codepoint comparison (never
|
|
137
|
-
* localeCompare — locale-dependent collation would make the bytes depend
|
|
138
|
-
* on the host environment);
|
|
139
|
-
* - stable KEY order per entry: the canonical keys above first, then any
|
|
140
|
-
* remaining keys in codepoint order (future-proof against new fields);
|
|
141
|
-
* - values are passed through UNTOUCHED: schemas/annotations are static
|
|
142
|
-
* literals whose insertion order is fixed at author time, and nothing in
|
|
143
|
-
* the pipeline derives from Date/random. (Deep key-sorting is deliberately
|
|
144
|
-
* avoided — it would rewrite inputSchema property order and break the
|
|
145
|
-
* golden-fixture schema_sha256 drift guards for zero stability gain.)
|
|
146
|
-
*
|
|
147
|
-
* Pure and non-mutating: same input ⇒ same output, fresh objects.
|
|
148
|
-
*/
|
|
149
|
-
export function buildStableToolList(tools) {
|
|
150
|
-
return [...tools]
|
|
151
|
-
.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))
|
|
152
|
-
.map((tool) => {
|
|
153
|
-
const source = tool;
|
|
154
|
-
const out = {};
|
|
155
|
-
for (const key of CANONICAL_TOOL_KEYS) {
|
|
156
|
-
if (key in source && source[key] !== undefined)
|
|
157
|
-
out[key] = source[key];
|
|
158
|
-
}
|
|
159
|
-
const rest = Object.keys(source)
|
|
160
|
-
.filter((k) => !CANONICAL_TOOL_KEYS.includes(k) && source[k] !== undefined)
|
|
161
|
-
.sort();
|
|
162
|
-
for (const key of rest)
|
|
163
|
-
out[key] = source[key];
|
|
164
|
-
return out;
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
//# sourceMappingURL=registry.js.map
|
|
1
|
+
import{goalToolSpecs as n}from"./goals.js";import{captureToolSpecs as s}from"./capture.js";import{recallToolSpecs as l}from"./recall.js";import{searchToolSpecs as a}from"./search.js";import{failureToolSpecs as f}from"./failure.js";import{questToolSpecs as u}from"./quest.js";import{sessionToolSpecs as S}from"./session.js";import{reviewToolSpecs as T}from"./review.js";import{runToolSpecs as d}from"./run.js";import{declaredOutputSchemas as h}from"./output-schemas.js";import{projectToolSpecs as y}from"./project.js";import{eventsToolSpecs as g}from"./events.js";import{skillToolSpecs as O}from"./skill.js";import{datalakeToolSpecs as x}from"./datalake.js";import{entityToolSpecs as k}from"./entity.js";import{intelligenceToolSpecs as b}from"./intelligence.js";import{orchestrationToolSpecs as v}from"./orchestration.js";import{cloudToolSpecs as L}from"./cloud.js";import{companionToolSpecs as j}from"./companion.js";import{syncopsToolSpecs as w}from"./syncops.js";import{presenceToolSpecs as A}from"./presence.js";import{causalityToolSpecs as C}from"./causality.js";import{symbolsToolSpecs as D}from"./symbols.js";import{invoicingToolSpecs as N}from"./invoicing.js";import{auditToolSpecs as _}from"./audit.js";import{shareToolSpecs as q}from"./share.js";import{agentToolSpecs as E}from"./agent.js";import{mcpclientToolSpecs as I}from"./mcpclient.js";const p=[...n,...s,...l,...a,...f,...u,...S,...T,...d,...y,...g,...O,...x,...k,...b,...v,...L,...j,...w,...A,...C,...D,...N,..._,...q,...E,...I],lo=new Map(p.map(o=>[o.name,o.handler]));function ao(){return p.map(o=>({name:o.name,description:o.description,inputSchema:o.inputSchema,...o.outputSchema!==void 0?{outputSchema:o.outputSchema}:{}}))}function fo(o){return o.map(t=>{const e=h[t.name];return!e||t.outputSchema!==void 0?t:{...t,outputSchema:e}})}const c=["name","description","inputSchema","outputSchema","annotations"];function uo(o){return[...o].sort((t,e)=>t.name<e.name?-1:t.name>e.name?1:0).map(t=>{const e=t,m={};for(const r of c)r in e&&e[r]!==void 0&&(m[r]=e[r]);const i=Object.keys(e).filter(r=>!c.includes(r)&&e[r]!==void 0).sort();for(const r of i)m[r]=e[r];return m})}export{fo as applyDeclaredOutputSchemas,uo as buildStableToolList,lo as handlerRegistry,ao as registryToolDefs,p as toolSpecs};
|