wyrm-mcp 7.3.2 → 7.4.0
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/README.md +12 -18
- package/dist/activation.js +59 -1
- package/dist/agent-daemon.js +281 -4
- package/dist/agent-loop.js +332 -7
- package/dist/analytics.js +236 -13
- package/dist/attribution.js +49 -1
- package/dist/audit.js +457 -2
- package/dist/auto-capture.js +138 -3
- package/dist/auto-orchestrator.js +325 -1
- package/dist/autoconfig.d.ts +51 -0
- package/dist/autoconfig.d.ts.map +1 -1
- package/dist/autoconfig.js +1121 -39
- package/dist/autoconfig.js.map +1 -1
- package/dist/buddy-runner.js +109 -1
- package/dist/buddy.js +564 -14
- package/dist/build-flags.js +15 -1
- package/dist/capabilities.js +183 -3
- package/dist/capture.js +56 -1
- package/dist/causality.js +148 -8
- package/dist/cli.js +281 -20
- package/dist/cloud/cli.js +541 -5
- package/dist/cloud/client.js +221 -1
- package/dist/cloud/crypto.js +85 -1
- package/dist/cloud/machine-id.js +113 -2
- package/dist/cloud/recovery.js +60 -1
- package/dist/cloud/sync-engine.js +543 -7
- package/dist/cloud-backup.js +579 -5
- package/dist/cloud-profile.js +138 -1
- package/dist/cloud-sync-entrypoint.js +47 -1
- package/dist/cloud-sync.js +309 -2
- package/dist/connectors/bridge-source.d.ts +46 -0
- package/dist/connectors/bridge-source.d.ts.map +1 -0
- package/dist/connectors/bridge-source.js +77 -0
- package/dist/connectors/bridge-source.js.map +1 -0
- package/dist/connectors/index.d.ts +24 -0
- package/dist/connectors/index.d.ts.map +1 -0
- package/dist/connectors/index.js +69 -0
- package/dist/connectors/index.js.map +1 -0
- package/dist/connectors/ingest.d.ts +16 -0
- package/dist/connectors/ingest.d.ts.map +1 -0
- package/dist/connectors/ingest.js +116 -0
- package/dist/connectors/ingest.js.map +1 -0
- package/dist/connectors/types.d.ts +99 -0
- package/dist/connectors/types.d.ts.map +1 -0
- package/dist/connectors/types.js +17 -0
- package/dist/connectors/types.js.map +1 -0
- package/dist/constellation.js +168 -12
- package/dist/content-signature.js +45 -1
- package/dist/context-build-budgeted.js +144 -4
- package/dist/context-ranking.js +69 -1
- package/dist/crypto.js +179 -1
- package/dist/daemon-write-endpoint.js +290 -1
- package/dist/daemon-writer.js +406 -2
- package/dist/database.js +1278 -53
- package/dist/deprecations.js +162 -2
- package/dist/design.js +141 -13
- package/dist/event-replication.js +112 -1
- package/dist/events-sse.js +43 -7
- package/dist/events.js +238 -6
- package/dist/failure-patterns.d.ts +107 -0
- package/dist/failure-patterns.d.ts.map +1 -1
- package/dist/failure-patterns.js +924 -43
- package/dist/failure-patterns.js.map +1 -1
- package/dist/federation.js +236 -12
- package/dist/goals.js +101 -13
- package/dist/golden.js +355 -3
- package/dist/handlers/agent.js +165 -4
- package/dist/handlers/alias-adapters.js +129 -1
- package/dist/handlers/aliases.js +171 -1
- package/dist/handlers/audit.js +87 -1
- package/dist/handlers/boundary.js +221 -1
- package/dist/handlers/capture.js +1114 -73
- package/dist/handlers/causality.js +119 -9
- package/dist/handlers/cloud.js +382 -85
- package/dist/handlers/companion.js +459 -28
- package/dist/handlers/datalake.js +187 -7
- package/dist/handlers/dispatch-context.js +22 -0
- package/dist/handlers/entity.js +256 -25
- package/dist/handlers/events.js +335 -16
- package/dist/handlers/failure.d.ts +1 -0
- package/dist/handlers/failure.d.ts.map +1 -1
- package/dist/handlers/failure.js +458 -13
- package/dist/handlers/failure.js.map +1 -1
- package/dist/handlers/goals.js +296 -4
- package/dist/handlers/intelligence.d.ts.map +1 -1
- package/dist/handlers/intelligence.js +690 -126
- package/dist/handlers/intelligence.js.map +1 -1
- package/dist/handlers/invoicing.js +70 -1
- package/dist/handlers/mcpclient.js +137 -6
- package/dist/handlers/orchestration.js +125 -40
- package/dist/handlers/output-schemas.js +24 -1
- package/dist/handlers/presence.js +99 -3
- package/dist/handlers/project.js +182 -28
- package/dist/handlers/prompts.js +157 -6
- package/dist/handlers/quest.js +224 -4
- package/dist/handlers/recall.js +237 -13
- package/dist/handlers/registry.js +167 -1
- package/dist/handlers/resources.js +288 -1
- package/dist/handlers/review.js +74 -11
- package/dist/handlers/run.js +498 -16
- package/dist/handlers/search.js +338 -15
- package/dist/handlers/session.js +643 -31
- package/dist/handlers/share.js +184 -8
- package/dist/handlers/shims.js +464 -1
- package/dist/handlers/skill.js +449 -67
- package/dist/handlers/survivors.js +120 -1
- package/dist/handlers/symbols.js +109 -8
- package/dist/handlers/syncops.js +302 -4
- package/dist/handlers/types.js +27 -1
- package/dist/harvest.js +191 -5
- package/dist/hours.js +156 -7
- package/dist/http-auth.js +321 -3
- package/dist/http-fast.d.ts.map +1 -1
- package/dist/http-fast.js +1308 -22
- package/dist/http-fast.js.map +1 -1
- package/dist/icons.js +47 -1
- package/dist/importers.js +268 -1
- package/dist/index.js +844 -2
- package/dist/index.js.map +1 -1
- package/dist/indexer.js +145 -4
- package/dist/intelligence.d.ts +16 -0
- package/dist/intelligence.d.ts.map +1 -1
- package/dist/intelligence.js +283 -31
- package/dist/intelligence.js.map +1 -1
- package/dist/internal-dispatch.js +212 -3
- package/dist/keyset.js +110 -1
- package/dist/knowledge-graph.js +176 -12
- package/dist/license.js +441 -2
- package/dist/logger.js +199 -2
- package/dist/maintenance.js +148 -2
- package/dist/mcp-client.js +262 -6
- package/dist/memory-artifacts.js +596 -32
- package/dist/migrate-prompt.js +124 -2
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +799 -42
- package/dist/migrations.js.map +1 -1
- package/dist/performance.js +228 -1
- package/dist/presence.js +140 -11
- package/dist/priority-embed.js +164 -5
- package/dist/providers/embedding-provider.js +196 -1
- package/dist/readonly-gate.js +29 -1
- package/dist/receipt.js +43 -1
- package/dist/rehydration.js +157 -9
- package/dist/reindex.js +88 -1
- package/dist/render-target.js +544 -21
- package/dist/render.js +280 -4
- package/dist/repl-guard.js +173 -1
- package/dist/replication-daemon-entrypoint.js +31 -1
- package/dist/replication-daemon.js +262 -2
- package/dist/rerank.js +142 -1
- package/dist/resilience.js +591 -1
- package/dist/reverse-bridge.js +360 -5
- package/dist/security.js +244 -1
- package/dist/session-seen.js +51 -3
- package/dist/setup.js +260 -1
- package/dist/skill-author.js +168 -5
- package/dist/spec-kit.js +191 -1
- package/dist/sqlite-busy.js +154 -1
- package/dist/statusline.js +315 -11
- package/dist/sub-agent.js +262 -13
- package/dist/summarizer.js +139 -13
- package/dist/symbols.js +283 -7
- package/dist/sync.js +359 -5
- package/dist/tasks-dispatch.js +84 -1
- package/dist/tasks.js +282 -1
- package/dist/token-budget.js +143 -1
- package/dist/tool-analytics.js +129 -7
- package/dist/tool-annotations.js +365 -1
- package/dist/tool-manifest-v2.json +1 -1
- package/dist/tool-manifest.json +1 -1
- package/dist/tool-profiles.js +75 -1
- package/dist/trace-harvest.js +244 -6
- package/dist/truth-cascade.d.ts +13 -0
- package/dist/truth-cascade.d.ts.map +1 -0
- package/dist/truth-cascade.js +4 -0
- package/dist/truth-cascade.js.map +1 -0
- package/dist/types.js +30 -1
- package/dist/ui-dashboard.js +50 -41
- package/dist/ulid.js +81 -1
- package/dist/usage-tracker.js +66 -1
- package/dist/validate.js +129 -1
- package/dist/vault.js +534 -1
- package/dist/vector-init.js +67 -1
- package/dist/vectors.js +184 -3
- package/dist/version-check.d.ts.map +1 -1
- package/dist/version-check.js +145 -4
- package/dist/version-check.js.map +1 -1
- package/dist/visibility.js +155 -19
- package/dist/wyrm-cli.js +2849 -101
- package/dist/wyrm-cli.js.map +1 -1
- package/dist/wyrm-guard.d.ts.map +1 -1
- package/dist/wyrm-guard.js +475 -14
- package/dist/wyrm-guard.js.map +1 -1
- package/dist/wyrm-loop.js +174 -3
- package/dist/wyrm-loop.js.map +1 -1
- package/dist/wyrm-manifest.json +1 -1
- package/dist/wyrm-statusline-daemon.js +11 -1
- package/dist/wyrm-statusline.js +56 -4
- package/dist/wyrm-ui.js +77 -9
- package/package.json +3 -2
|
@@ -1,9 +1,119 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @copyright 2026 Ghost Protocol (Pvt) Ltd.
|
|
3
|
+
* @license Proprietary — (c) 2026 Ghost Protocol (Pvt) Ltd. All rights reserved. See LICENSE.
|
|
4
|
+
*/
|
|
5
|
+
import { TOOL_ANNOTATIONS } from "../tool-annotations.js";
|
|
6
|
+
import { staleFoundationWarning } from "../causality.js";
|
|
7
|
+
export const causalityToolSpecs = [
|
|
8
|
+
{
|
|
9
|
+
name: "wyrm_decided_because",
|
|
10
|
+
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.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: "object",
|
|
13
|
+
properties: {
|
|
14
|
+
projectPath: { type: "string" },
|
|
15
|
+
from_kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
|
|
16
|
+
from_id: { type: "number" },
|
|
17
|
+
to_kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
|
|
18
|
+
to_id: { type: "number" },
|
|
19
|
+
relation: { type: "string", enum: ["because_of", "supersedes", "refutes", "verifies"], description: "Default because_of" },
|
|
20
|
+
rationale: { type: "string", description: "Why" },
|
|
21
|
+
confidence: { type: "number", description: "0-1, default 1.0" },
|
|
22
|
+
},
|
|
23
|
+
required: ["projectPath", "from_kind", "from_id", "to_kind", "to_id"],
|
|
24
|
+
},
|
|
25
|
+
annotations: TOOL_ANNOTATIONS["wyrm_decided_because"],
|
|
26
|
+
aliases: [],
|
|
27
|
+
handler: async (args, ctx) => {
|
|
28
|
+
const { causality, db } = ctx;
|
|
29
|
+
const { projectPath, from_kind, from_id, to_kind, to_id, relation, rationale, confidence, } = args;
|
|
30
|
+
const project = db.getProject(projectPath);
|
|
31
|
+
if (!project)
|
|
32
|
+
return { content: [{ type: "text", text: "Project not found" }], isError: true };
|
|
33
|
+
const edge = causality.link({
|
|
34
|
+
project_id: project.id,
|
|
35
|
+
from_kind, from_id, to_kind, to_id, relation, rationale, confidence,
|
|
36
|
+
});
|
|
37
|
+
return { content: [{ type: "text", text: ` Edge #${edge.id} — ${from_kind}#${from_id} ${edge.relation} ${to_kind}#${to_id}` }] };
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "wyrm_decision_downstream",
|
|
42
|
+
description: "List all decisions that depend on the given source. Use before invalidating a truth to see the blast radius.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: "object",
|
|
45
|
+
properties: {
|
|
46
|
+
kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
|
|
47
|
+
id: { type: "number" },
|
|
48
|
+
},
|
|
49
|
+
required: ["kind", "id"],
|
|
50
|
+
},
|
|
51
|
+
annotations: TOOL_ANNOTATIONS["wyrm_decision_downstream"],
|
|
52
|
+
aliases: [],
|
|
53
|
+
handler: async (args, ctx) => {
|
|
54
|
+
const { causality } = ctx;
|
|
55
|
+
const { kind, id } = args;
|
|
56
|
+
const edges = causality.downstreamOf(kind, id);
|
|
57
|
+
if (edges.length === 0) {
|
|
58
|
+
return { content: [{ type: "text", text: ` No active dependents on ${kind}#${id}.` }] };
|
|
59
|
+
}
|
|
60
|
+
const text = edges.map(e => `• ${e.from_kind}#${e.from_id} (${e.relation}, conf ${e.confidence})${e.rationale ? ` — ${e.rationale}` : ''}`).join('\n');
|
|
61
|
+
return { content: [{ type: "text", text: ` ${edges.length} dependent(s):\n${text}` }] };
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "wyrm_decision_upstream",
|
|
66
|
+
description: "List all sources a decision was based on (incoming edges). Walks the 'why did we choose this?' chain.",
|
|
67
|
+
inputSchema: {
|
|
68
|
+
type: "object",
|
|
69
|
+
properties: {
|
|
70
|
+
kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
|
|
71
|
+
id: { type: "number" },
|
|
72
|
+
},
|
|
73
|
+
required: ["kind", "id"],
|
|
74
|
+
},
|
|
75
|
+
annotations: TOOL_ANNOTATIONS["wyrm_decision_upstream"],
|
|
76
|
+
aliases: [],
|
|
77
|
+
handler: async (args, ctx) => {
|
|
78
|
+
const { causality } = ctx;
|
|
79
|
+
const { kind, id } = args;
|
|
80
|
+
const edges = causality.upstreamOf(kind, id);
|
|
81
|
+
// Warn-at-recall: surface any foundation that has gone stale (superseded
|
|
82
|
+
// / refuted) so the agent RE-EVALUATES before relying on this decision.
|
|
83
|
+
const warn = staleFoundationWarning(causality.staleFoundations(kind, id));
|
|
84
|
+
const banner = warn ? `${warn}\n\n` : '';
|
|
85
|
+
if (edges.length === 0) {
|
|
86
|
+
return { content: [{ type: "text", text: `${banner} No recorded basis for ${kind}#${id}.` }] };
|
|
87
|
+
}
|
|
88
|
+
const text = edges.map(e => `• ${e.to_kind}#${e.to_id} (${e.relation}, conf ${e.confidence})${e.rationale ? ` — ${e.rationale}` : ''}`).join('\n');
|
|
89
|
+
return { content: [{ type: "text", text: `${banner} ${edges.length} basis edge(s):\n${text}` }] };
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "wyrm_decision_invalidate",
|
|
94
|
+
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.",
|
|
95
|
+
inputSchema: {
|
|
96
|
+
type: "object",
|
|
97
|
+
properties: {
|
|
98
|
+
kind: { type: "string", enum: ["truth", "artifact", "quest", "session", "data"] },
|
|
99
|
+
id: { type: "number" },
|
|
100
|
+
reason: { type: "string", description: "Why the source was invalidated" },
|
|
101
|
+
},
|
|
102
|
+
required: ["kind", "id"],
|
|
103
|
+
},
|
|
104
|
+
annotations: TOOL_ANNOTATIONS["wyrm_decision_invalidate"],
|
|
105
|
+
aliases: [],
|
|
106
|
+
handler: async (args, ctx) => {
|
|
107
|
+
const { causality } = ctx;
|
|
108
|
+
const a = args || {};
|
|
109
|
+
const { kind, id, reason } = args;
|
|
110
|
+
const result = causality.invalidateDownstream(kind, id, reason);
|
|
111
|
+
if (result.invalidated === 0) {
|
|
112
|
+
return { content: [{ type: "text", text: ` No dependents to invalidate from ${kind}#${id}.` }] };
|
|
113
|
+
}
|
|
114
|
+
const text = result.affected.map(a => `• ${a.kind}#${a.id} (edge #${a.edge_id})`).join('\n');
|
|
115
|
+
return { content: [{ type: "text", text: ` Invalidated ${result.invalidated} downstream decision(s):\n${text}` }] };
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
//# sourceMappingURL=causality.js.map
|
package/dist/handlers/cloud.js
CHANGED
|
@@ -1,85 +1,382 @@
|
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
`;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @copyright 2026 Ghost Protocol (Pvt) Ltd.
|
|
3
|
+
* @license Proprietary — (c) 2026 Ghost Protocol (Pvt) Ltd. All rights reserved. See LICENSE.
|
|
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
|