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.
Files changed (156) hide show
  1. package/LICENSE +26 -667
  2. package/NOTICE +14 -33
  3. package/dist/activation.d.ts.map +1 -1
  4. package/dist/activation.js +1 -44
  5. package/dist/activation.js.map +1 -1
  6. package/dist/agent-daemon.js +4 -281
  7. package/dist/agent-loop.js +7 -332
  8. package/dist/analytics.js +13 -236
  9. package/dist/attribution.js +1 -49
  10. package/dist/audit.js +2 -457
  11. package/dist/auto-capture.js +3 -138
  12. package/dist/auto-orchestrator.js +1 -325
  13. package/dist/autoconfig.js +39 -840
  14. package/dist/buddy-runner.js +1 -109
  15. package/dist/buddy.js +14 -564
  16. package/dist/build-flags.js +1 -17
  17. package/dist/capabilities.js +3 -183
  18. package/dist/capture.js +1 -56
  19. package/dist/causality.js +6 -107
  20. package/dist/cli.js +20 -281
  21. package/dist/cloud/cli.js +5 -541
  22. package/dist/cloud/client.js +1 -221
  23. package/dist/cloud/crypto.js +1 -85
  24. package/dist/cloud/machine-id.js +2 -113
  25. package/dist/cloud/recovery.js +1 -60
  26. package/dist/cloud/sync-engine.js +7 -543
  27. package/dist/cloud-backup.js +5 -579
  28. package/dist/cloud-profile.js +1 -138
  29. package/dist/cloud-sync-entrypoint.js +1 -47
  30. package/dist/cloud-sync.js +2 -309
  31. package/dist/constellation.js +12 -168
  32. package/dist/context-build-budgeted.js +4 -144
  33. package/dist/context-ranking.js +1 -69
  34. package/dist/crypto.js +1 -179
  35. package/dist/daemon-write-endpoint.js +1 -290
  36. package/dist/daemon-writer.js +2 -406
  37. package/dist/database.js +43 -1110
  38. package/dist/deprecations.js +2 -162
  39. package/dist/design.js +13 -141
  40. package/dist/event-replication.js +1 -112
  41. package/dist/events-sse.js +7 -43
  42. package/dist/events.js +6 -238
  43. package/dist/failure-patterns.js +42 -659
  44. package/dist/federation.js +12 -236
  45. package/dist/goals.js +13 -101
  46. package/dist/golden.js +3 -355
  47. package/dist/handlers/agent.js +4 -165
  48. package/dist/handlers/alias-adapters.js +1 -129
  49. package/dist/handlers/aliases.js +1 -171
  50. package/dist/handlers/audit.js +1 -87
  51. package/dist/handlers/boundary.js +1 -221
  52. package/dist/handlers/capture.js +73 -1109
  53. package/dist/handlers/causality.js +7 -114
  54. package/dist/handlers/cloud.js +85 -382
  55. package/dist/handlers/companion.js +28 -459
  56. package/dist/handlers/datalake.js +7 -187
  57. package/dist/handlers/dispatch-context.js +0 -22
  58. package/dist/handlers/entity.js +25 -256
  59. package/dist/handlers/events.js +16 -335
  60. package/dist/handlers/failure.js +13 -340
  61. package/dist/handlers/goals.js +4 -296
  62. package/dist/handlers/intelligence.js +126 -674
  63. package/dist/handlers/invoicing.js +1 -70
  64. package/dist/handlers/mcpclient.js +6 -137
  65. package/dist/handlers/orchestration.js +40 -125
  66. package/dist/handlers/output-schemas.js +1 -24
  67. package/dist/handlers/presence.js +3 -99
  68. package/dist/handlers/project.js +28 -182
  69. package/dist/handlers/prompts.js +6 -157
  70. package/dist/handlers/quest.js +4 -224
  71. package/dist/handlers/recall.js +11 -218
  72. package/dist/handlers/registry.js +1 -167
  73. package/dist/handlers/resources.js +1 -288
  74. package/dist/handlers/review.js +11 -74
  75. package/dist/handlers/run.js +17 -487
  76. package/dist/handlers/search.js +15 -326
  77. package/dist/handlers/session.js +28 -615
  78. package/dist/handlers/share.js +8 -184
  79. package/dist/handlers/shims.js +1 -464
  80. package/dist/handlers/skill.js +67 -449
  81. package/dist/handlers/survivors.js +1 -120
  82. package/dist/handlers/symbols.js +8 -109
  83. package/dist/handlers/syncops.js +4 -302
  84. package/dist/handlers/types.js +1 -27
  85. package/dist/harvest.js +5 -191
  86. package/dist/hours.js +7 -156
  87. package/dist/http-auth.js +3 -321
  88. package/dist/http-fast.js +21 -1137
  89. package/dist/icons.js +1 -47
  90. package/dist/index.js +2 -924
  91. package/dist/indexer.js +4 -145
  92. package/dist/intelligence.js +31 -261
  93. package/dist/internal-dispatch.js +3 -212
  94. package/dist/keyset.js +1 -110
  95. package/dist/knowledge-graph.js +12 -176
  96. package/dist/license.d.ts +11 -0
  97. package/dist/license.d.ts.map +1 -1
  98. package/dist/license.js +2 -414
  99. package/dist/license.js.map +1 -1
  100. package/dist/logger.js +2 -199
  101. package/dist/maintenance.js +2 -148
  102. package/dist/mcp-client.js +6 -262
  103. package/dist/memory-artifacts.js +30 -449
  104. package/dist/migrate-prompt.js +2 -124
  105. package/dist/migrations.js +40 -655
  106. package/dist/performance.js +1 -228
  107. package/dist/presence.js +11 -140
  108. package/dist/priority-embed.js +5 -164
  109. package/dist/providers/embedding-provider.js +1 -196
  110. package/dist/readonly-gate.js +1 -29
  111. package/dist/rehydration.js +9 -157
  112. package/dist/reindex.js +1 -88
  113. package/dist/render-target.js +21 -514
  114. package/dist/render.js +4 -280
  115. package/dist/repl-guard.js +1 -173
  116. package/dist/replication-daemon-entrypoint.js +1 -31
  117. package/dist/replication-daemon.js +2 -262
  118. package/dist/resilience.js +1 -591
  119. package/dist/reverse-bridge.js +5 -360
  120. package/dist/security.js +1 -244
  121. package/dist/session-seen.js +3 -51
  122. package/dist/setup.js +1 -260
  123. package/dist/skill-author.js +5 -168
  124. package/dist/spec-kit.js +1 -191
  125. package/dist/sqlite-busy.js +1 -154
  126. package/dist/statusline.js +11 -315
  127. package/dist/sub-agent.js +13 -262
  128. package/dist/summarizer.js +13 -139
  129. package/dist/symbols.js +7 -283
  130. package/dist/sync.js +5 -359
  131. package/dist/tasks-dispatch.js +1 -84
  132. package/dist/tasks.js +1 -282
  133. package/dist/token-budget.js +1 -143
  134. package/dist/tool-analytics.js +7 -129
  135. package/dist/tool-annotations.js +1 -365
  136. package/dist/tool-manifest-v2.json +1 -1
  137. package/dist/tool-manifest.json +1 -1
  138. package/dist/tool-profiles.js +1 -75
  139. package/dist/trace-harvest.js +6 -244
  140. package/dist/types.js +1 -30
  141. package/dist/ui-dashboard.js +41 -50
  142. package/dist/ulid.js +1 -81
  143. package/dist/validate.js +1 -129
  144. package/dist/vault.js +1 -534
  145. package/dist/vectors.js +3 -184
  146. package/dist/version-check.js +4 -136
  147. package/dist/visibility.js +19 -155
  148. package/dist/wyrm-cli.js +98 -2451
  149. package/dist/wyrm-cli.js.map +1 -1
  150. package/dist/wyrm-guard.js +14 -424
  151. package/dist/wyrm-loop.js +3 -150
  152. package/dist/wyrm-manifest.json +1 -1
  153. package/dist/wyrm-statusline-daemon.js +1 -11
  154. package/dist/wyrm-statusline.js +4 -56
  155. package/dist/wyrm-ui.js +9 -77
  156. package/package.json +4 -2
@@ -1,114 +1,7 @@
1
- /**
2
- * @copyright 2026 Ghost Protocol (Pvt) Ltd.
3
- * @license AGPL-3.0-or-later
4
- */
5
- import { TOOL_ANNOTATIONS } from "../tool-annotations.js";
6
- export const causalityToolSpecs = [
7
- {
8
- name: "wyrm_decided_because",
9
- description: "Use to link a choice or decision to the assumption or evidence it was based on - records a causal edge (truth/quest/artifact/session) so stale foundations invalidate downstream.",
10
- inputSchema: {
11
- type: "object",
12
- properties: {
13
- projectPath: { type: "string" },
14
- from_kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
15
- from_id: { type: "number" },
16
- to_kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
17
- to_id: { type: "number" },
18
- relation: { type: "string", enum: ["because_of", "supersedes", "refutes", "verifies"], description: "Default because_of" },
19
- rationale: { type: "string", description: "Why" },
20
- confidence: { type: "number", description: "0-1, default 1.0" },
21
- },
22
- required: ["projectPath", "from_kind", "from_id", "to_kind", "to_id"],
23
- },
24
- annotations: TOOL_ANNOTATIONS["wyrm_decided_because"],
25
- aliases: [],
26
- handler: async (args, ctx) => {
27
- const { causality, db } = ctx;
28
- const { projectPath, from_kind, from_id, to_kind, to_id, relation, rationale, confidence, } = args;
29
- const project = db.getProject(projectPath);
30
- if (!project)
31
- return { content: [{ type: "text", text: "Project not found" }], isError: true };
32
- const edge = causality.link({
33
- project_id: project.id,
34
- from_kind, from_id, to_kind, to_id, relation, rationale, confidence,
35
- });
36
- return { content: [{ type: "text", text: `󱅝 Edge #${edge.id} — ${from_kind}#${from_id} ${edge.relation} ${to_kind}#${to_id}` }] };
37
- },
38
- },
39
- {
40
- name: "wyrm_decision_downstream",
41
- description: "List all decisions that depend on the given source. Use before invalidating a truth to see the blast radius.",
42
- inputSchema: {
43
- type: "object",
44
- properties: {
45
- kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
46
- id: { type: "number" },
47
- },
48
- required: ["kind", "id"],
49
- },
50
- annotations: TOOL_ANNOTATIONS["wyrm_decision_downstream"],
51
- aliases: [],
52
- handler: async (args, ctx) => {
53
- const { causality } = ctx;
54
- const { kind, id } = args;
55
- const edges = causality.downstreamOf(kind, id);
56
- if (edges.length === 0) {
57
- return { content: [{ type: "text", text: `󱅝 No active dependents on ${kind}#${id}.` }] };
58
- }
59
- const text = edges.map(e => `• ${e.from_kind}#${e.from_id} (${e.relation}, conf ${e.confidence})${e.rationale ? ` — ${e.rationale}` : ''}`).join('\n');
60
- return { content: [{ type: "text", text: `󱅝 ${edges.length} dependent(s):\n${text}` }] };
61
- },
62
- },
63
- {
64
- name: "wyrm_decision_upstream",
65
- description: "List all sources a decision was based on (incoming edges). Walks the 'why did we choose this?' chain.",
66
- inputSchema: {
67
- type: "object",
68
- properties: {
69
- kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
70
- id: { type: "number" },
71
- },
72
- required: ["kind", "id"],
73
- },
74
- annotations: TOOL_ANNOTATIONS["wyrm_decision_upstream"],
75
- aliases: [],
76
- handler: async (args, ctx) => {
77
- const { causality } = ctx;
78
- const { kind, id } = args;
79
- const edges = causality.upstreamOf(kind, id);
80
- if (edges.length === 0) {
81
- return { content: [{ type: "text", text: `󱅝 No recorded basis for ${kind}#${id}.` }] };
82
- }
83
- const text = edges.map(e => `• ${e.to_kind}#${e.to_id} (${e.relation}, conf ${e.confidence})${e.rationale ? ` — ${e.rationale}` : ''}`).join('\n');
84
- return { content: [{ type: "text", text: `󱅝 ${edges.length} basis edge(s):\n${text}` }] };
85
- },
86
- },
87
- {
88
- name: "wyrm_decision_invalidate",
89
- description: "Cascade-invalidate all decisions downstream of a source (recursive). Use when a foundational truth turns out to be wrong. Returns the set of affected (kind, id) pairs.",
90
- inputSchema: {
91
- type: "object",
92
- properties: {
93
- kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
94
- id: { type: "number" },
95
- reason: { type: "string", description: "Why the source was invalidated" },
96
- },
97
- required: ["kind", "id"],
98
- },
99
- annotations: TOOL_ANNOTATIONS["wyrm_decision_invalidate"],
100
- aliases: [],
101
- handler: async (args, ctx) => {
102
- const { causality } = ctx;
103
- const a = args || {};
104
- const { kind, id, reason } = args;
105
- const result = causality.invalidateDownstream(kind, id, reason);
106
- if (result.invalidated === 0) {
107
- return { content: [{ type: "text", text: `󱅝 No dependents to invalidate from ${kind}#${id}.` }] };
108
- }
109
- const text = result.affected.map(a => `• ${a.kind}#${a.id} (edge #${a.edge_id})`).join('\n');
110
- return { content: [{ type: "text", text: `󱅝 Invalidated ${result.invalidated} downstream decision(s):\n${text}` }] };
111
- },
112
- },
113
- ];
114
- //# sourceMappingURL=causality.js.map
1
+ import{TOOL_ANNOTATIONS as u}from"../tool-annotations.js";const h=[{name:"wyrm_decided_because",description:"Use to link a choice or decision to the assumption or evidence it was based on - records a causal edge (truth/quest/artifact/session) so stale foundations invalidate downstream.",inputSchema:{type:"object",properties:{projectPath:{type:"string"},from_kind:{type:"string",enum:["truth","artifact","quest","session","data"]},from_id:{type:"number"},to_kind:{type:"string",enum:["truth","artifact","quest","session","data"]},to_id:{type:"number"},relation:{type:"string",enum:["because_of","supersedes","refutes","verifies"],description:"Default because_of"},rationale:{type:"string",description:"Why"},confidence:{type:"number",description:"0-1, default 1.0"}},required:["projectPath","from_kind","from_id","to_kind","to_id"]},annotations:u.wyrm_decided_because,aliases:[],handler:async(i,a)=>{const{causality:r,db:o}=a,{projectPath:n,from_kind:e,from_id:s,to_kind:t,to_id:c,relation:d,rationale:m,confidence:y}=i,p=o.getProject(n);if(!p)return{content:[{type:"text",text:"Project not found"}],isError:!0};const l=r.link({project_id:p.id,from_kind:e,from_id:s,to_kind:t,to_id:c,relation:d,rationale:m,confidence:y});return{content:[{type:"text",text:`\u{F115D} Edge #${l.id} \u2014 ${e}#${s} ${l.relation} ${t}#${c}`}]}}},{name:"wyrm_decision_downstream",description:"List all decisions that depend on the given source. Use before invalidating a truth to see the blast radius.",inputSchema:{type:"object",properties:{kind:{type:"string",enum:["truth","artifact","quest","session","data"]},id:{type:"number"}},required:["kind","id"]},annotations:u.wyrm_decision_downstream,aliases:[],handler:async(i,a)=>{const{causality:r}=a,{kind:o,id:n}=i,e=r.downstreamOf(o,n);if(e.length===0)return{content:[{type:"text",text:`\u{F115D} No active dependents on ${o}#${n}.`}]};const s=e.map(t=>`\u2022 ${t.from_kind}#${t.from_id} (${t.relation}, conf ${t.confidence})${t.rationale?` \u2014 ${t.rationale}`:""}`).join(`
2
+ `);return{content:[{type:"text",text:`\u{F115D} ${e.length} dependent(s):
3
+ ${s}`}]}}},{name:"wyrm_decision_upstream",description:"List all sources a decision was based on (incoming edges). Walks the 'why did we choose this?' chain.",inputSchema:{type:"object",properties:{kind:{type:"string",enum:["truth","artifact","quest","session","data"]},id:{type:"number"}},required:["kind","id"]},annotations:u.wyrm_decision_upstream,aliases:[],handler:async(i,a)=>{const{causality:r}=a,{kind:o,id:n}=i,e=r.upstreamOf(o,n);if(e.length===0)return{content:[{type:"text",text:`\u{F115D} No recorded basis for ${o}#${n}.`}]};const s=e.map(t=>`\u2022 ${t.to_kind}#${t.to_id} (${t.relation}, conf ${t.confidence})${t.rationale?` \u2014 ${t.rationale}`:""}`).join(`
4
+ `);return{content:[{type:"text",text:`\u{F115D} ${e.length} basis edge(s):
5
+ ${s}`}]}}},{name:"wyrm_decision_invalidate",description:"Cascade-invalidate all decisions downstream of a source (recursive). Use when a foundational truth turns out to be wrong. Returns the set of affected (kind, id) pairs.",inputSchema:{type:"object",properties:{kind:{type:"string",enum:["truth","artifact","quest","session","data"]},id:{type:"number"},reason:{type:"string",description:"Why the source was invalidated"}},required:["kind","id"]},annotations:u.wyrm_decision_invalidate,aliases:[],handler:async(i,a)=>{const{causality:r}=a,o=i||{},{kind:n,id:e,reason:s}=i,t=r.invalidateDownstream(n,e,s);if(t.invalidated===0)return{content:[{type:"text",text:`\u{F115D} No dependents to invalidate from ${n}#${e}.`}]};const c=t.affected.map(d=>`\u2022 ${d.kind}#${d.id} (edge #${d.edge_id})`).join(`
6
+ `);return{content:[{type:"text",text:`\u{F115D} Invalidated ${t.invalidated} downstream decision(s):
7
+ ${c}`}]}}}];export{h as causalityToolSpecs};
@@ -1,382 +1,85 @@
1
- /**
2
- * @copyright 2026 Ghost Protocol (Pvt) Ltd.
3
- * @license AGPL-3.0-or-later
4
- */
5
- import { TOOL_ANNOTATIONS } from "../tool-annotations.js";
6
- import { CloudSyncDaemon } from "../cloud-sync.js";
7
- import { getCrypto, initializeCrypto } from "../crypto.js";
8
- import { activateLicense, getLicenseInfo, getTier, hasFeature } from "../license.js";
9
- export const cloudToolSpecs = [
10
- {
11
- name: "wyrm_license",
12
- description: "View current license status, tier, and available features",
13
- inputSchema: {
14
- type: "object",
15
- properties: {},
16
- },
17
- annotations: TOOL_ANNOTATIONS["wyrm_license"],
18
- aliases: [],
19
- handler: async (args, ctx) => {
20
- const { cachedResponse, sync } = ctx;
21
- const a = args || {};
22
- const license = getLicenseInfo();
23
- const tier = getTier();
24
- let text = `󱅝 **Wyrm License Status**\n\n`;
25
- text += `- **Tier:** ${tier.charAt(0).toUpperCase() + tier.slice(1)}\n`;
26
- if (license.valid && license.key) {
27
- text += `- **Key:** ${license.key}\n`;
28
- text += `- **Issued To:** ${license.issuedTo || 'Unknown'}\n`;
29
- text += `- **Expires:** ${license.expiresAt ? new Date(license.expiresAt).toLocaleDateString() : 'Never'}\n`;
30
- text += `- **Status:** ✓ Valid\n\n`;
31
- text += `### Features\n`;
32
- for (const f of license.features) {
33
- text += `- ✓ ${f}\n`;
34
- }
35
- }
36
- else {
37
- text += `- **Status:** Free tier (no license key)\n\n`;
38
- text += `### Free Features\n`;
39
- text += `- Local SQLite storage\n`;
40
- text += `- ✓ 32 MCP tools\n`;
41
- text += `- ✓ FTS5 search\n`;
42
- text += `- ✓ File-based sync\n\n`;
43
- text += `### Upgrade to Pro\n`;
44
- text += `- Analytics dashboard & cost tracking\n`;
45
- text += `- Cloud backup to R2\n`;
46
- text += `- Encryption at rest\n`;
47
- text += `- Priority support\n\n`;
48
- text += `### Already have a license?\n`;
49
- text += `Activate it — paste the license JSON into the \`wyrm_activate\` tool, or save it to \`~/.wyrm/license.json\` and restart Wyrm.\n`;
50
- text += `Manage or download your license at https://account.ghosts.lk · buy one at https://ghosts.lk/wyrm.`;
51
- }
52
- return cachedResponse(text);
53
- },
54
- },
55
- {
56
- name: "wyrm_activate",
57
- description: "Activate a license key to unlock Pro/Team/Enterprise features",
58
- inputSchema: {
59
- type: "object",
60
- properties: {
61
- license: { type: "string", description: "License JSON string (signed license from Ghost Protocol)" },
62
- },
63
- required: ["license"],
64
- },
65
- annotations: TOOL_ANNOTATIONS["wyrm_activate"],
66
- aliases: [],
67
- handler: async (args, ctx) => {
68
- const licenseStr = args?.license;
69
- if (!licenseStr)
70
- throw new Error("License JSON string required");
71
- try {
72
- const result = activateLicense(licenseStr);
73
- if (result.valid) {
74
- return {
75
- content: [{ type: "text", text: `󱅝 ✓ License activated!\n\n- **Tier:** ${result.tier}\n- **Features:** ${result.features.join(', ')}\n\nRestart Wyrm to apply all features.` }],
76
- };
77
- }
78
- else {
79
- return {
80
- content: [{ type: "text", text: `󱅝 ✗ License activation failed: ${result.error || 'unknown error'}` }],
81
- isError: true,
82
- };
83
- }
84
- }
85
- catch (e) {
86
- return {
87
- content: [{ type: "text", text: `󱅝 ✗ Invalid license format. Please verify your license key.` }],
88
- isError: true,
89
- };
90
- }
91
- },
92
- },
93
- {
94
- name: "wyrm_analytics_dashboard",
95
- description: "View usage analytics dashboard — tool calls, tokens, costs, cache efficiency (Pro+)",
96
- inputSchema: {
97
- type: "object",
98
- properties: {
99
- days: { type: "number", description: "Number of days to analyze (default: 30)" },
100
- },
101
- },
102
- annotations: TOOL_ANNOTATIONS["wyrm_analytics_dashboard"],
103
- aliases: [],
104
- handler: async (args, ctx) => {
105
- const { analytics } = ctx;
106
- const a = args || {};
107
- if (!hasFeature('analytics')) {
108
- return {
109
- content: [{ type: "text", text: `󱅝 Analytics requires a Pro license or higher.\nVisit https://ghosts.lk/wyrm to upgrade.` }],
110
- };
111
- }
112
- const days = args?.days || 30;
113
- const dashboard = analytics.dashboard(days);
114
- let text = `󱅝 **Usage Analytics** (last ${days} days)\n\n`;
115
- text += `### Overview\n`;
116
- text += `- **Total Tool Calls:** ${dashboard.summary.total_calls.toLocaleString()}\n`;
117
- text += `- **Unique Tools Used:** ${dashboard.summary.unique_tools}\n`;
118
- text += `- **Total Tokens (In):** ${dashboard.summary.total_tokens_in.toLocaleString()}\n`;
119
- text += `- **Total Tokens (Out):** ${dashboard.summary.total_tokens_out.toLocaleString()}\n`;
120
- text += `- **Cache Hit Rate:** ${(dashboard.summary.cache_hit_rate * 100).toFixed(1)}%\n`;
121
- text += `- **Estimated Cost:** $${dashboard.summary.estimated_cost_usd.toFixed(4)}\n\n`;
122
- if (dashboard.top_tools.length > 0) {
123
- text += `### Top Tools\n`;
124
- for (const t of dashboard.top_tools.slice(0, 10)) {
125
- text += `- **${t.tool}** — ${t.calls} calls, ${t.tokens.toLocaleString()} tokens\n`;
126
- }
127
- text += `\n`;
128
- }
129
- if (dashboard.daily.length > 0) {
130
- text += `### Recent Activity\n`;
131
- for (const d of dashboard.daily.slice(-7)) {
132
- text += `- ${d.date}: ${d.calls} calls, ${d.tokens.toLocaleString()} tokens\n`;
133
- }
134
- }
135
- return { content: [{ type: "text", text }] };
136
- },
137
- },
138
- {
139
- name: "wyrm_cost_report",
140
- description: "View estimated API cost report for current billing period (Pro+)",
141
- inputSchema: {
142
- type: "object",
143
- properties: {
144
- period: { type: "string", description: "Period in YYYY-MM format (default: current month)" },
145
- },
146
- },
147
- annotations: TOOL_ANNOTATIONS["wyrm_cost_report"],
148
- aliases: [],
149
- handler: async (args, ctx) => {
150
- const { analytics } = ctx;
151
- const a = args || {};
152
- if (!hasFeature('analytics')) {
153
- return {
154
- content: [{ type: "text", text: `󱅝 Cost reports require a Pro license or higher.\nVisit https://ghosts.lk/wyrm to upgrade.` }],
155
- };
156
- }
157
- const period = args?.period;
158
- const report = analytics.costReport(period);
159
- let text = `󱅝 **Cost Report** — ${report.period}\n\n`;
160
- text += `- **Total Cost:** $${report.total_cost_usd.toFixed(4)}\n`;
161
- text += `- **Projected Monthly:** $${report.projected_monthly_usd.toFixed(2)}\n\n`;
162
- if (report.tools.length > 0) {
163
- text += `### By Tool\n`;
164
- for (const t of report.tools.slice(0, 10)) {
165
- text += `- **${t.tool}** — ${t.calls} calls, $${t.cost_usd.toFixed(4)}\n`;
166
- }
167
- }
168
- return { content: [{ type: "text", text }] };
169
- },
170
- },
171
- {
172
- name: "wyrm_cloud_backup",
173
- description: "Backup Wyrm database to encrypted cloud storage (Pro+)",
174
- inputSchema: {
175
- type: "object",
176
- properties: {
177
- action: { type: "string", description: "Action: backup, restore, list, prune", enum: ["backup", "restore", "list", "prune"] },
178
- backupKey: { type: "string", description: "Backup key for restore (from list)" },
179
- keepCount: { type: "number", description: "Number of backups to keep when pruning (default: 10)" },
180
- },
181
- required: ["action"],
182
- },
183
- annotations: TOOL_ANNOTATIONS["wyrm_cloud_backup"],
184
- aliases: [],
185
- handler: async (args, ctx) => {
186
- const { cloudBackup, db } = ctx;
187
- const a = args || {};
188
- if (!hasFeature('cloud_backup')) {
189
- return {
190
- content: [{ type: "text", text: `󱅝 Cloud backup requires a Pro license or higher.\nVisit https://ghosts.lk/wyrm to upgrade.` }],
191
- };
192
- }
193
- const action = args?.action;
194
- switch (action) {
195
- case "backup": {
196
- const result = await cloudBackup.backup(db.getDatabasePath());
197
- const meta = result.metadata;
198
- return {
199
- content: [{ type: "text", text: `󱅝 ✓ Backup complete!\n\n- **Key:** ${result.key}\n- **Size:** ${(meta.db_size / 1024).toFixed(1)} KB → ${(meta.compressed_size / 1024).toFixed(1)} KB compressed\n- **Encrypted:** ${meta.encrypted ? 'Yes' : 'No'}\n- **Checksum:** ${meta.checksum.slice(0, 16)}...` }],
200
- };
201
- }
202
- case "restore": {
203
- const backupKey = args?.backupKey;
204
- if (!backupKey)
205
- throw new Error("backupKey required for restore");
206
- const result = await cloudBackup.restore(backupKey, db.getDatabasePath());
207
- return {
208
- content: [{ type: "text", text: `󱅝 ✓ Restore complete!\n\n- **Restored:** ${result.restored ? 'Yes' : 'No'}\n- **Size:** ${(result.size / 1024).toFixed(1)} KB\n- **Previous DB backed up to:** ${db.getDatabasePath()}.bak\n\n⚠️ Restart Wyrm to use the restored database.` }],
209
- };
210
- }
211
- case "list": {
212
- const backups = await cloudBackup.listBackups();
213
- if (backups.length === 0) {
214
- return { content: [{ type: "text", text: `󱅝 No backups found.` }] };
215
- }
216
- let text = `󱅝 **Cloud Backups** (${backups.length} found)\n\n`;
217
- for (const b of backups) {
218
- text += `- **${b.timestamp}** — ${(b.db_size / 1024).toFixed(1)} KB, encrypted: ${b.encrypted}, machine: ${b.machine_id.slice(0, 8)}...\n`;
219
- }
220
- return { content: [{ type: "text", text }] };
221
- }
222
- case "prune": {
223
- const keepCount = args?.keepCount || 10;
224
- const result = await cloudBackup.pruneBackups(keepCount);
225
- return {
226
- content: [{ type: "text", text: `󱅝 ✓ Pruned ${result.deleted} old backup(s). Kept ${keepCount} most recent.` }],
227
- };
228
- }
229
- default:
230
- return { content: [{ type: "text", text: `Unknown backup action: ${action}. Use: backup, restore, list, prune` }], isError: true };
231
- }
232
- },
233
- },
234
- {
235
- name: "wyrm_cloud_sync",
236
- description: "Start, stop, or check the cloud-sync daemon — Phase 2 multi-device sync. Periodically backs up the DB to R2 and restores on startup if a newer snapshot exists. Last-write-wins by mtime.",
237
- inputSchema: {
238
- type: "object",
239
- properties: {
240
- action: { type: "string", description: "Action: start, stop, restart, status, force-sync", enum: ["start", "stop", "restart", "status", "force-sync"] },
241
- interval_minutes: { type: "number", description: "Sync interval (default: 10)" },
242
- keep_count: { type: "number", description: "Snapshots to retain after pruning (default: 20)" },
243
- },
244
- required: ["action"],
245
- },
246
- annotations: TOOL_ANNOTATIONS["wyrm_cloud_sync"],
247
- aliases: [],
248
- handler: async (args, ctx) => {
249
- const { cloudBackup, cloudSyncManager, db, sync } = ctx;
250
- const a = args || {};
251
- if (!hasFeature('cloud_backup')) {
252
- return {
253
- content: [{ type: "text", text: `󱅝 Cloud sync requires a Pro license or higher.\nVisit https://ghosts.lk/wyrm to upgrade.` }],
254
- };
255
- }
256
- const action = args?.action;
257
- const interval_minutes = args?.interval_minutes;
258
- const keep_count = args?.keep_count;
259
- switch (action) {
260
- case "start": {
261
- const r = cloudSyncManager.start({ interval_minutes, keep_count });
262
- if (!r.ok) {
263
- return { content: [{ type: "text", text: `󱅝 cloud-sync: ${r.reason ?? 'failed to start'}${r.pid ? ` (pid ${r.pid})` : ''}` }], isError: !r.pid };
264
- }
265
- return { content: [{ type: "text", text: `󱅝 ✓ cloud-sync daemon started (pid ${r.pid}). Logs: ~/.wyrm/wyrm-cloud-sync.log` }] };
266
- }
267
- case "stop": {
268
- const r = cloudSyncManager.stop();
269
- return {
270
- content: [{ type: "text", text: r.ok
271
- ? `󱅝 ✓ cloud-sync daemon stopped`
272
- : `󱅝 cloud-sync: ${r.reason ?? 'failed to stop'}` }],
273
- isError: !r.ok,
274
- };
275
- }
276
- case "restart": {
277
- cloudSyncManager.stop();
278
- // Brief grace period for the daemon's final tick before re-spawning
279
- await new Promise((res) => { setTimeout(res, 500); });
280
- const r = cloudSyncManager.start({ interval_minutes, keep_count });
281
- return {
282
- content: [{ type: "text", text: r.ok
283
- ? `󱅝 ✓ cloud-sync daemon restarted (pid ${r.pid})`
284
- : `󱅝 cloud-sync restart failed: ${r.reason ?? 'unknown'}` }],
285
- isError: !r.ok,
286
- };
287
- }
288
- case "status": {
289
- const s = cloudSyncManager.status();
290
- const lines = [`󱅝 **Cloud Sync Status**`];
291
- lines.push(`- Running: ${s.running ? '✓ yes' : '✗ no'}`);
292
- if (s.pid)
293
- lines.push(`- PID: ${s.pid}`);
294
- if (s.state) {
295
- if (s.state.last_uploaded_ts) {
296
- lines.push(`- Last upload: ${new Date(s.state.last_uploaded_ts).toISOString()}${s.state.last_uploaded_key ? ` (${s.state.last_uploaded_key})` : ''}`);
297
- }
298
- if (s.state.last_restored_key)
299
- lines.push(`- Last restore: ${s.state.last_restored_key}`);
300
- if (s.state.last_check_ts)
301
- lines.push(`- Last check: ${new Date(s.state.last_check_ts).toISOString()}`);
302
- lines.push(`- Machine: ${s.state.machine}`);
303
- }
304
- return { content: [{ type: "text", text: lines.join('\n') }] };
305
- }
306
- case "force-sync": {
307
- // One-shot tick without the long-running daemon. Uses the in-process
308
- // cloudBackup client, so works even when the daemon is stopped.
309
- const daemon = new CloudSyncDaemon(cloudBackup, db.getDatabasePath());
310
- const result = await daemon.tick();
311
- return { content: [{ type: "text", text: `󱅝 force-sync: ${JSON.stringify(result, null, 2)}` }] };
312
- }
313
- default:
314
- return { content: [{ type: "text", text: `Unknown cloud-sync action: ${action}. Use: start, stop, restart, status, force-sync` }], isError: true };
315
- }
316
- },
317
- },
318
- {
319
- name: "wyrm_encrypt_setup",
320
- description: "Set up or check encryption status for sensitive data (Pro+)",
321
- inputSchema: {
322
- type: "object",
323
- properties: {
324
- action: { type: "string", description: "Action: status, enable, test", enum: ["status", "enable", "test"] },
325
- password: { type: "string", description: "Encryption password (min 8 chars, required for enable)" },
326
- },
327
- required: ["action"],
328
- },
329
- annotations: TOOL_ANNOTATIONS["wyrm_encrypt_setup"],
330
- aliases: [],
331
- handler: async (args, ctx) => {
332
- const a = args || {};
333
- if (!hasFeature('encryption')) {
334
- return {
335
- content: [{ type: "text", text: `󱅝 Encryption setup requires a Pro license or higher.\nVisit https://ghosts.lk/wyrm to upgrade.` }],
336
- };
337
- }
338
- const encAction = args?.action;
339
- const cryptoInstance = getCrypto();
340
- switch (encAction) {
341
- case "status": {
342
- const enabled = cryptoInstance.isEnabled();
343
- let text = `󱅝 **Encryption Status**\n\n`;
344
- text += `- **Enabled:** ${enabled ? '✓ Yes' : '✗ No'}\n`;
345
- text += `- **Algorithm:** AES-256-GCM\n`;
346
- if (enabled) {
347
- text += `- **Status:** Active — new data is encrypted at rest\n`;
348
- }
349
- else {
350
- text += `\nTo enable, run: \`wyrm_encrypt_setup\` with action "enable" and a strong password.\n`;
351
- }
352
- return { content: [{ type: "text", text }] };
353
- }
354
- case "enable": {
355
- const password = args?.password;
356
- if (!password || password.length < 8) {
357
- return { content: [{ type: "text", text: `󱅝 Password must be at least 8 characters.` }], isError: true };
358
- }
359
- initializeCrypto(password);
360
- return {
361
- content: [{ type: "text", text: `󱅝 ✓ Encryption enabled!\n\n- **Algorithm:** AES-256-GCM\n- **Key derived from:** your password (PBKDF2)\n\n⚠️ **Store your password safely.** Lost passwords cannot be recovered.\nNew data lake entries will be encrypted at rest.` }],
362
- };
363
- }
364
- case "test": {
365
- if (!cryptoInstance.isEnabled()) {
366
- return { content: [{ type: "text", text: `󱅝 Encryption not enabled. Run with action "enable" first.` }] };
367
- }
368
- const testData = "Wyrm encryption test " + Date.now();
369
- const encrypted = cryptoInstance.encrypt(testData);
370
- const decrypted = cryptoInstance.decrypt(encrypted);
371
- const ok = decrypted === testData;
372
- return {
373
- content: [{ type: "text", text: `󱅝 Encryption test: ${ok ? '✓ PASSED' : '✗ FAILED'}\n- Encrypted ${testData.length} chars → decrypted back to ${decrypted.length} chars` }],
374
- };
375
- }
376
- default:
377
- return { content: [{ type: "text", text: `Unknown encrypt action: ${encAction}. Use: status, enable, test` }], isError: true };
378
- }
379
- },
380
- },
381
- ];
382
- //# sourceMappingURL=cloud.js.map
1
+ import{TOOL_ANNOTATIONS as u}from"../tool-annotations.js";import{CloudSyncDaemon as m}from"../cloud-sync.js";import{getCrypto as h,initializeCrypto as k}from"../crypto.js";import{activateLicense as f,getLicenseInfo as b,getTier as x,hasFeature as d}from"../license.js";const S=[{name:"wyrm_license",description:"View current license status, tier, and available features",inputSchema:{type:"object",properties:{}},annotations:u.wyrm_license,aliases:[],handler:async(o,i)=>{const{cachedResponse:a,sync:r}=i,c=o||{},n=b(),e=x();let t=`\u{F115D} **Wyrm License Status**
2
+
3
+ `;if(t+=`- **Tier:** ${e.charAt(0).toUpperCase()+e.slice(1)}
4
+ `,n.valid&&n.key){t+=`- **Key:** ${n.key}
5
+ `,t+=`- **Issued To:** ${n.issuedTo||"Unknown"}
6
+ `,t+=`- **Expires:** ${n.expiresAt?new Date(n.expiresAt).toLocaleDateString():"Never"}
7
+ `,t+=`- **Status:** \u2713 Valid
8
+
9
+ `,t+=`### Features
10
+ `;for(const l of n.features)t+=`- \u2713 ${l}
11
+ `}else t+=`- **Status:** Free tier (no license key)
12
+
13
+ `,t+=`### Free Features
14
+ `,t+=`- \u2713 Local SQLite storage
15
+ `,t+=`- \u2713 32 MCP tools
16
+ `,t+=`- \u2713 FTS5 search
17
+ `,t+=`- \u2713 File-based sync
18
+
19
+ `,t+=`### Upgrade to Pro
20
+ `,t+=`- Analytics dashboard & cost tracking
21
+ `,t+=`- Cloud backup to R2
22
+ `,t+=`- Encryption at rest
23
+ `,t+=`- Priority support
24
+
25
+ `,t+=`### Already have a license?
26
+ `,t+="Activate it \u2014 paste the license JSON into the `wyrm_activate` tool, or save it to `~/.wyrm/license.json` and restart Wyrm.\n",t+="Manage or download your license at https://account.ghosts.lk \xB7 buy one at https://ghosts.lk/wyrm.";return a(t)}},{name:"wyrm_activate",description:"Activate a license key to unlock Pro/Team/Enterprise features",inputSchema:{type:"object",properties:{license:{type:"string",description:"License JSON string (signed license from Ghost Protocol)"}},required:["license"]},annotations:u.wyrm_activate,aliases:[],handler:async(o,i)=>{const a=o?.license;if(!a)throw new Error("License JSON string required");try{const r=f(a);return r.valid?{content:[{type:"text",text:`\u{F115D} \u2713 License activated!
27
+
28
+ - **Tier:** ${r.tier}
29
+ - **Features:** ${r.features.join(", ")}
30
+
31
+ Restart Wyrm to apply all features.`}]}:{content:[{type:"text",text:`\u{F115D} \u2717 License activation failed: ${r.error||"unknown error"}`}],isError:!0}}catch{return{content:[{type:"text",text:"\u{F115D} \u2717 Invalid license format. Please verify your license key."}],isError:!0}}}},{name:"wyrm_analytics_dashboard",description:"View usage analytics dashboard \u2014 tool calls, tokens, costs, cache efficiency (Pro+)",inputSchema:{type:"object",properties:{days:{type:"number",description:"Number of days to analyze (default: 30)"}}},annotations:u.wyrm_analytics_dashboard,aliases:[],handler:async(o,i)=>{const{analytics:a}=i,r=o||{};if(!d("analytics"))return{content:[{type:"text",text:`\u{F115D} Analytics requires a Pro license or higher.
32
+ Visit https://ghosts.lk/wyrm to upgrade.`}]};const c=o?.days||30,n=a.dashboard(c);let e=`\u{F115D} **Usage Analytics** (last ${c} days)
33
+
34
+ `;if(e+=`### Overview
35
+ `,e+=`- **Total Tool Calls:** ${n.summary.total_calls.toLocaleString()}
36
+ `,e+=`- **Unique Tools Used:** ${n.summary.unique_tools}
37
+ `,e+=`- **Total Tokens (In):** ${n.summary.total_tokens_in.toLocaleString()}
38
+ `,e+=`- **Total Tokens (Out):** ${n.summary.total_tokens_out.toLocaleString()}
39
+ `,e+=`- **Cache Hit Rate:** ${(n.summary.cache_hit_rate*100).toFixed(1)}%
40
+ `,e+=`- **Estimated Cost:** $${n.summary.estimated_cost_usd.toFixed(4)}
41
+
42
+ `,n.top_tools.length>0){e+=`### Top Tools
43
+ `;for(const t of n.top_tools.slice(0,10))e+=`- **${t.tool}** \u2014 ${t.calls} calls, ${t.tokens.toLocaleString()} tokens
44
+ `;e+=`
45
+ `}if(n.daily.length>0){e+=`### Recent Activity
46
+ `;for(const t of n.daily.slice(-7))e+=`- ${t.date}: ${t.calls} calls, ${t.tokens.toLocaleString()} tokens
47
+ `}return{content:[{type:"text",text:e}]}}},{name:"wyrm_cost_report",description:"View estimated API cost report for current billing period (Pro+)",inputSchema:{type:"object",properties:{period:{type:"string",description:"Period in YYYY-MM format (default: current month)"}}},annotations:u.wyrm_cost_report,aliases:[],handler:async(o,i)=>{const{analytics:a}=i,r=o||{};if(!d("analytics"))return{content:[{type:"text",text:`\u{F115D} Cost reports require a Pro license or higher.
48
+ Visit https://ghosts.lk/wyrm to upgrade.`}]};const c=o?.period,n=a.costReport(c);let e=`\u{F115D} **Cost Report** \u2014 ${n.period}
49
+
50
+ `;if(e+=`- **Total Cost:** $${n.total_cost_usd.toFixed(4)}
51
+ `,e+=`- **Projected Monthly:** $${n.projected_monthly_usd.toFixed(2)}
52
+
53
+ `,n.tools.length>0){e+=`### By Tool
54
+ `;for(const t of n.tools.slice(0,10))e+=`- **${t.tool}** \u2014 ${t.calls} calls, $${t.cost_usd.toFixed(4)}
55
+ `}return{content:[{type:"text",text:e}]}}},{name:"wyrm_cloud_backup",description:"Backup Wyrm database to encrypted cloud storage (Pro+)",inputSchema:{type:"object",properties:{action:{type:"string",description:"Action: backup, restore, list, prune",enum:["backup","restore","list","prune"]},backupKey:{type:"string",description:"Backup key for restore (from list)"},keepCount:{type:"number",description:"Number of backups to keep when pruning (default: 10)"}},required:["action"]},annotations:u.wyrm_cloud_backup,aliases:[],handler:async(o,i)=>{const{cloudBackup:a,db:r}=i,c=o||{};if(!d("cloud_backup"))return{content:[{type:"text",text:`\u{F115D} Cloud backup requires a Pro license or higher.
56
+ Visit https://ghosts.lk/wyrm to upgrade.`}]};const n=o?.action;switch(n){case"backup":{const e=await a.backup(r.getDatabasePath()),t=e.metadata;return{content:[{type:"text",text:`\u{F115D} \u2713 Backup complete!
57
+
58
+ - **Key:** ${e.key}
59
+ - **Size:** ${(t.db_size/1024).toFixed(1)} KB \u2192 ${(t.compressed_size/1024).toFixed(1)} KB compressed
60
+ - **Encrypted:** ${t.encrypted?"Yes":"No"}
61
+ - **Checksum:** ${t.checksum.slice(0,16)}...`}]}}case"restore":{const e=o?.backupKey;if(!e)throw new Error("backupKey required for restore");const t=await a.restore(e,r.getDatabasePath());return{content:[{type:"text",text:`\u{F115D} \u2713 Restore complete!
62
+
63
+ - **Restored:** ${t.restored?"Yes":"No"}
64
+ - **Size:** ${(t.size/1024).toFixed(1)} KB
65
+ - **Previous DB backed up to:** ${r.getDatabasePath()}.bak
66
+
67
+ \u26A0\uFE0F Restart Wyrm to use the restored database.`}]}}case"list":{const e=await a.listBackups();if(e.length===0)return{content:[{type:"text",text:"\u{F115D} No backups found."}]};let t=`\u{F115D} **Cloud Backups** (${e.length} found)
68
+
69
+ `;for(const l of e)t+=`- **${l.timestamp}** \u2014 ${(l.db_size/1024).toFixed(1)} KB, encrypted: ${l.encrypted}, machine: ${l.machine_id.slice(0,8)}...
70
+ `;return{content:[{type:"text",text:t}]}}case"prune":{const e=o?.keepCount||10;return{content:[{type:"text",text:`\u{F115D} \u2713 Pruned ${(await a.pruneBackups(e)).deleted} old backup(s). Kept ${e} most recent.`}]}}default:return{content:[{type:"text",text:`Unknown backup action: ${n}. Use: backup, restore, list, prune`}],isError:!0}}}},{name:"wyrm_cloud_sync",description:"Start, stop, or check the cloud-sync daemon \u2014 Phase 2 multi-device sync. Periodically backs up the DB to R2 and restores on startup if a newer snapshot exists. Last-write-wins by mtime.",inputSchema:{type:"object",properties:{action:{type:"string",description:"Action: start, stop, restart, status, force-sync",enum:["start","stop","restart","status","force-sync"]},interval_minutes:{type:"number",description:"Sync interval (default: 10)"},keep_count:{type:"number",description:"Snapshots to retain after pruning (default: 20)"}},required:["action"]},annotations:u.wyrm_cloud_sync,aliases:[],handler:async(o,i)=>{const{cloudBackup:a,cloudSyncManager:r,db:c,sync:n}=i,e=o||{};if(!d("cloud_backup"))return{content:[{type:"text",text:`\u{F115D} Cloud sync requires a Pro license or higher.
71
+ Visit https://ghosts.lk/wyrm to upgrade.`}]};const t=o?.action,l=o?.interval_minutes,y=o?.keep_count;switch(t){case"start":{const s=r.start({interval_minutes:l,keep_count:y});return s.ok?{content:[{type:"text",text:`\u{F115D} \u2713 cloud-sync daemon started (pid ${s.pid}). Logs: ~/.wyrm/wyrm-cloud-sync.log`}]}:{content:[{type:"text",text:`\u{F115D} cloud-sync: ${s.reason??"failed to start"}${s.pid?` (pid ${s.pid})`:""}`}],isError:!s.pid}}case"stop":{const s=r.stop();return{content:[{type:"text",text:s.ok?"\u{F115D} \u2713 cloud-sync daemon stopped":`\u{F115D} cloud-sync: ${s.reason??"failed to stop"}`}],isError:!s.ok}}case"restart":{r.stop(),await new Promise(p=>{setTimeout(p,500)});const s=r.start({interval_minutes:l,keep_count:y});return{content:[{type:"text",text:s.ok?`\u{F115D} \u2713 cloud-sync daemon restarted (pid ${s.pid})`:`\u{F115D} cloud-sync restart failed: ${s.reason??"unknown"}`}],isError:!s.ok}}case"status":{const s=r.status(),p=["\u{F115D} **Cloud Sync Status**"];return p.push(`- Running: ${s.running?"\u2713 yes":"\u2717 no"}`),s.pid&&p.push(`- PID: ${s.pid}`),s.state&&(s.state.last_uploaded_ts&&p.push(`- Last upload: ${new Date(s.state.last_uploaded_ts).toISOString()}${s.state.last_uploaded_key?` (${s.state.last_uploaded_key})`:""}`),s.state.last_restored_key&&p.push(`- Last restore: ${s.state.last_restored_key}`),s.state.last_check_ts&&p.push(`- Last check: ${new Date(s.state.last_check_ts).toISOString()}`),p.push(`- Machine: ${s.state.machine}`)),{content:[{type:"text",text:p.join(`
72
+ `)}]}}case"force-sync":{const p=await new m(a,c.getDatabasePath()).tick();return{content:[{type:"text",text:`\u{F115D} force-sync: ${JSON.stringify(p,null,2)}`}]}}default:return{content:[{type:"text",text:`Unknown cloud-sync action: ${t}. Use: start, stop, restart, status, force-sync`}],isError:!0}}}},{name:"wyrm_encrypt_setup",description:"Set up or check encryption status for sensitive data (Pro+)",inputSchema:{type:"object",properties:{action:{type:"string",description:"Action: status, enable, test",enum:["status","enable","test"]},password:{type:"string",description:"Encryption password (min 8 chars, required for enable)"}},required:["action"]},annotations:u.wyrm_encrypt_setup,aliases:[],handler:async(o,i)=>{const a=o||{};if(!d("encryption"))return{content:[{type:"text",text:`\u{F115D} Encryption setup requires a Pro license or higher.
73
+ Visit https://ghosts.lk/wyrm to upgrade.`}]};const r=o?.action,c=h();switch(r){case"status":{const n=c.isEnabled();let e=`\u{F115D} **Encryption Status**
74
+
75
+ `;return e+=`- **Enabled:** ${n?"\u2713 Yes":"\u2717 No"}
76
+ `,e+=`- **Algorithm:** AES-256-GCM
77
+ `,n?e+=`- **Status:** Active \u2014 new data is encrypted at rest
78
+ `:e+='\nTo enable, run: `wyrm_encrypt_setup` with action "enable" and a strong password.\n',{content:[{type:"text",text:e}]}}case"enable":{const n=o?.password;return!n||n.length<8?{content:[{type:"text",text:"\u{F115D} Password must be at least 8 characters."}],isError:!0}:(k(n),{content:[{type:"text",text:`\u{F115D} \u2713 Encryption enabled!
79
+
80
+ - **Algorithm:** AES-256-GCM
81
+ - **Key derived from:** your password (PBKDF2)
82
+
83
+ \u26A0\uFE0F **Store your password safely.** Lost passwords cannot be recovered.
84
+ New data lake entries will be encrypted at rest.`}]})}case"test":{if(!c.isEnabled())return{content:[{type:"text",text:'\u{F115D} Encryption not enabled. Run with action "enable" first.'}]};const n="Wyrm encryption test "+Date.now(),e=c.encrypt(n),t=c.decrypt(e);return{content:[{type:"text",text:`\u{F115D} Encryption test: ${t===n?"\u2713 PASSED":"\u2717 FAILED"}
85
+ - Encrypted ${n.length} chars \u2192 decrypted back to ${t.length} chars`}]}}default:return{content:[{type:"text",text:`Unknown encrypt action: ${r}. Use: status, enable, test`}],isError:!0}}}}];export{S as cloudToolSpecs};