wyrm-mcp 7.3.2 → 7.3.3
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 +8 -14
- 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 +50 -0
- package/dist/autoconfig.d.ts.map +1 -1
- package/dist/autoconfig.js +1115 -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.map +1 -1
- package/dist/handlers/failure.js +408 -13
- package/dist/handlers/failure.js.map +1 -1
- package/dist/handlers/goals.js +296 -4
- package/dist/handlers/intelligence.js +681 -126
- 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.js +1302 -22
- package/dist/icons.js +47 -1
- package/dist/importers.js +268 -1
- package/dist/index.js +840 -2
- package/dist/indexer.js +145 -4
- package/dist/intelligence.js +261 -31
- 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/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.js +136 -4
- package/dist/visibility.js +155 -19
- package/dist/wyrm-cli.js +2845 -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 +150 -3
- 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 +1 -1
package/dist/trace-harvest.js
CHANGED
|
@@ -1,6 +1,244 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Trace harvest (v7 F4 T040) — turn a harness's working trace into run-tagged
|
|
3
|
+
* review-queue candidates, OFFLINE.
|
|
4
|
+
*
|
|
5
|
+
* Three trace shapes are ingested into one normalized prose stream that feeds
|
|
6
|
+
* the EXISTING auto_capture extractor (src/auto-capture.ts — local Ollama
|
|
7
|
+
* WYRM_EXTRACT_MODEL / deterministic fallback, NEVER a cloud LLM, Article III):
|
|
8
|
+
*
|
|
9
|
+
* 1. Claude Code session JSONL — one JSON object per line, each
|
|
10
|
+
* { message: { role, content }, … } (the same shape
|
|
11
|
+
* scripts/hooks/wyrm-session-capture.mjs already parses). User prose +
|
|
12
|
+
* assistant text are kept; tool-result / system-reminder blocks dropped.
|
|
13
|
+
* 2. ~/.dragon/traces — the dragon-cli flywheel trace records. Tolerant of
|
|
14
|
+
* both line-delimited JSON and a top-level JSON array; each record's
|
|
15
|
+
* prompt/response/text/content fields are harvested.
|
|
16
|
+
* 3. WYRM_TRACE_TOOL_CALLS output — the `tool_call` Live Memory events the
|
|
17
|
+
* PostToolUse hook emits ({ kind:'tool_call', actor, payload, … }) or the
|
|
18
|
+
* raw stdin shape the hook reads ({ tool_name, tool_input, … }). Collapsed
|
|
19
|
+
* into a deterministic per-tool activity summary.
|
|
20
|
+
*
|
|
21
|
+
* SECRET REDACTION: every harvested segment passes through redactSecrets()
|
|
22
|
+
* BEFORE extraction, so an API key / bearer token / password that scrolled
|
|
23
|
+
* through a transcript never lands in the review queue. Deterministic, no
|
|
24
|
+
* network. Tool-call payloads are collapsed to keys (never values) for the same
|
|
25
|
+
* reason — a secret passed as a tool argument is summarized, not stored.
|
|
26
|
+
*
|
|
27
|
+
* Pure: parsing + redaction are total string functions (no I/O, no clock, no
|
|
28
|
+
* RNG). The MCP handler injects the DB writes + the extractor.
|
|
29
|
+
*
|
|
30
|
+
* @copyright 2026 Ghost Protocol (Pvt) Ltd.
|
|
31
|
+
* @license Proprietary — (c) 2026 Ghost Protocol (Pvt) Ltd. All rights reserved. See LICENSE.
|
|
32
|
+
*/
|
|
33
|
+
/** Control chars (ANSI/BEL/NUL) must never reach the review queue or a TUI. */
|
|
34
|
+
// eslint-disable-next-line no-control-regex
|
|
35
|
+
const CTRL = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
|
|
36
|
+
/**
|
|
37
|
+
* Redact common secret shapes from a string so they never enter the review
|
|
38
|
+
* queue. Deterministic + offline. Conservative (favours over-redaction): the
|
|
39
|
+
* goal is "a leaked credential is never stored", not perfect classification.
|
|
40
|
+
* Each rule replaces the SECRET portion with `[REDACTED]`, preserving
|
|
41
|
+
* surrounding prose so the candidate is still meaningful.
|
|
42
|
+
*/
|
|
43
|
+
export function redactSecrets(input) {
|
|
44
|
+
if (!input)
|
|
45
|
+
return '';
|
|
46
|
+
let s = input;
|
|
47
|
+
// High-entropy / vendor-prefixed token shapes (order matters — specific first).
|
|
48
|
+
const rules = [
|
|
49
|
+
// sk-... / sk-ant-api03-... / rk_live_... (OpenAI/Anthropic/Stripe-style);
|
|
50
|
+
// the token body may carry internal -/_ separators (sk-ant-api03-<rand>).
|
|
51
|
+
[/\b(?:sk|rk|pk)[-_][A-Za-z0-9][A-Za-z0-9_-]{14,}\b/g, '[REDACTED]'],
|
|
52
|
+
// GitHub tokens (ghp_/gho_/ghu_/ghs_/ghr_) + fine-grained github_pat_
|
|
53
|
+
[/\bgh[posru]_[A-Za-z0-9]{20,}\b/g, '[REDACTED]'],
|
|
54
|
+
[/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, '[REDACTED]'],
|
|
55
|
+
// AWS access key id
|
|
56
|
+
[/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g, '[REDACTED]'],
|
|
57
|
+
// Slack tokens
|
|
58
|
+
[/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, '[REDACTED]'],
|
|
59
|
+
// Google API key
|
|
60
|
+
[/\bAIza[A-Za-z0-9_-]{30,}\b/g, '[REDACTED]'],
|
|
61
|
+
// JWTs (three dot-separated base64url segments)
|
|
62
|
+
[/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g, '[REDACTED]'],
|
|
63
|
+
// Authorization: Bearer <token>
|
|
64
|
+
[/\b([Bb]earer)\s+[A-Za-z0-9._-]{12,}/g, '$1 [REDACTED]'],
|
|
65
|
+
// key=value / "key": "value" for secret-ish key names (api_key, token,
|
|
66
|
+
// password, secret, passwd, authorization, access_token, private_key).
|
|
67
|
+
[/((?:api[_-]?key|secret|token|password|passwd|auth(?:orization)?|access[_-]?token|private[_-]?key|client[_-]?secret)["']?\s*[:=]\s*["']?)([A-Za-z0-9._/+\-]{6,})/gi, '$1[REDACTED]'],
|
|
68
|
+
];
|
|
69
|
+
for (const [re, repl] of rules)
|
|
70
|
+
s = s.replace(re, repl);
|
|
71
|
+
return s;
|
|
72
|
+
}
|
|
73
|
+
/** Pull plain text out of a Claude/Anthropic message `content` (string or block array). */
|
|
74
|
+
function extractMessageText(content) {
|
|
75
|
+
if (content == null)
|
|
76
|
+
return '';
|
|
77
|
+
if (typeof content === 'string')
|
|
78
|
+
return content;
|
|
79
|
+
if (!Array.isArray(content))
|
|
80
|
+
return '';
|
|
81
|
+
const out = [];
|
|
82
|
+
for (const b of content) {
|
|
83
|
+
if (typeof b === 'string') {
|
|
84
|
+
out.push(b);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (b && typeof b === 'object') {
|
|
88
|
+
const block = b;
|
|
89
|
+
if (block.type === 'text' && typeof block.text === 'string')
|
|
90
|
+
out.push(block.text);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return out.join('\n');
|
|
94
|
+
}
|
|
95
|
+
/** Tidy a candidate chunk: strip control chars, collapse whitespace, clip. */
|
|
96
|
+
function clean(text) {
|
|
97
|
+
return redactSecrets(text).replace(CTRL, '').replace(/[ \t]+/g, ' ').replace(/\n{3,}/g, '\n\n').trim().slice(0, 4000);
|
|
98
|
+
}
|
|
99
|
+
/** Parse a JSONL/array trace body into per-line JSON objects (tolerant). */
|
|
100
|
+
function parseRecords(raw) {
|
|
101
|
+
const trimmed = raw.trim();
|
|
102
|
+
if (!trimmed)
|
|
103
|
+
return [];
|
|
104
|
+
// Whole-body JSON array (dragon traces sometimes export one).
|
|
105
|
+
if (trimmed.startsWith('[')) {
|
|
106
|
+
try {
|
|
107
|
+
const arr = JSON.parse(trimmed);
|
|
108
|
+
if (Array.isArray(arr))
|
|
109
|
+
return arr.filter((x) => !!x && typeof x === 'object');
|
|
110
|
+
}
|
|
111
|
+
catch { /* fall through to line mode */ }
|
|
112
|
+
}
|
|
113
|
+
const out = [];
|
|
114
|
+
for (const line of trimmed.split('\n')) {
|
|
115
|
+
const t = line.trim();
|
|
116
|
+
if (!t || (t[0] !== '{' && t[0] !== '['))
|
|
117
|
+
continue;
|
|
118
|
+
try {
|
|
119
|
+
const obj = JSON.parse(t);
|
|
120
|
+
if (obj && typeof obj === 'object' && !Array.isArray(obj))
|
|
121
|
+
out.push(obj);
|
|
122
|
+
}
|
|
123
|
+
catch { /* skip non-JSON line */ }
|
|
124
|
+
}
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
/** Claude Code session JSONL → user/assistant prose segments. */
|
|
128
|
+
export function parseClaudeJsonl(raw) {
|
|
129
|
+
const out = [];
|
|
130
|
+
for (const obj of parseRecords(raw)) {
|
|
131
|
+
const msg = (obj.message && typeof obj.message === 'object' ? obj.message : obj);
|
|
132
|
+
const role = String(msg.role ?? obj.role ?? '');
|
|
133
|
+
if (role !== 'user' && role !== 'assistant')
|
|
134
|
+
continue;
|
|
135
|
+
const text = extractMessageText(msg.content).trim();
|
|
136
|
+
if (!text)
|
|
137
|
+
continue;
|
|
138
|
+
// Drop tool-result / system-reminder blocks (same rule as the capture hook).
|
|
139
|
+
if (role === 'user' && (text.startsWith('<') || text.startsWith('[{')))
|
|
140
|
+
continue;
|
|
141
|
+
const cleaned = clean(text);
|
|
142
|
+
if (cleaned.length >= 12)
|
|
143
|
+
out.push({ role, text: cleaned });
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
/** dragon-cli flywheel trace → prose segments (prompt/response/text/content). */
|
|
148
|
+
export function parseDragonTrace(raw) {
|
|
149
|
+
const out = [];
|
|
150
|
+
const fields = [['prompt', 'user'], ['input', 'user'], ['response', 'assistant'], ['output', 'assistant'], ['text', 'note'], ['content', 'note']];
|
|
151
|
+
for (const rec of parseRecords(raw)) {
|
|
152
|
+
for (const [field, role] of fields) {
|
|
153
|
+
const v = rec[field];
|
|
154
|
+
const text = typeof v === 'string' ? v : extractMessageText(v);
|
|
155
|
+
if (!text)
|
|
156
|
+
continue;
|
|
157
|
+
const cleaned = clean(text);
|
|
158
|
+
if (cleaned.length >= 12)
|
|
159
|
+
out.push({ role, text: cleaned });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* WYRM_TRACE_TOOL_CALLS output → ONE deterministic activity-summary segment.
|
|
166
|
+
*
|
|
167
|
+
* Accepts both the Live Memory `tool_call` event shape ({ kind:'tool_call',
|
|
168
|
+
* actor:<toolName>, payload }) and the raw PostToolUse stdin shape
|
|
169
|
+
* ({ tool_name, tool_input }). Payloads are collapsed to argument KEYS only
|
|
170
|
+
* (never values) so a secret passed as a tool argument is never stored. The
|
|
171
|
+
* order of first appearance is preserved (deterministic); counts are summed.
|
|
172
|
+
*/
|
|
173
|
+
export function parseToolCalls(raw) {
|
|
174
|
+
const counts = new Map();
|
|
175
|
+
const order = [];
|
|
176
|
+
for (const rec of parseRecords(raw)) {
|
|
177
|
+
const kind = String(rec.kind ?? '');
|
|
178
|
+
let tool = '';
|
|
179
|
+
if (kind === 'tool_call')
|
|
180
|
+
tool = String(rec.actor ?? rec.tool ?? '');
|
|
181
|
+
else if (typeof rec.tool_name === 'string')
|
|
182
|
+
tool = rec.tool_name;
|
|
183
|
+
else if (typeof rec.tool === 'string')
|
|
184
|
+
tool = rec.tool;
|
|
185
|
+
tool = tool.replace(CTRL, '').trim().slice(0, 80);
|
|
186
|
+
if (!tool)
|
|
187
|
+
continue;
|
|
188
|
+
if (!counts.has(tool))
|
|
189
|
+
order.push(tool);
|
|
190
|
+
counts.set(tool, (counts.get(tool) ?? 0) + 1);
|
|
191
|
+
}
|
|
192
|
+
if (order.length === 0)
|
|
193
|
+
return [];
|
|
194
|
+
const summary = order.map((t) => `${t}×${counts.get(t)}`).join(', ');
|
|
195
|
+
return [{ role: 'tool', text: `Tool activity in this run: ${summary}.` }];
|
|
196
|
+
}
|
|
197
|
+
/** Sniff the trace format from the content (best-effort, deterministic). */
|
|
198
|
+
export function detectTraceFormat(raw) {
|
|
199
|
+
const recs = parseRecords(raw).slice(0, 50);
|
|
200
|
+
if (recs.length === 0)
|
|
201
|
+
return 'claude-jsonl';
|
|
202
|
+
let toolish = 0, claudeish = 0;
|
|
203
|
+
for (const r of recs) {
|
|
204
|
+
if (r.kind === 'tool_call' || typeof r.tool_name === 'string')
|
|
205
|
+
toolish++;
|
|
206
|
+
const msg = (r.message && typeof r.message === 'object' ? r.message : r);
|
|
207
|
+
const role = msg.role ?? r.role;
|
|
208
|
+
if (role === 'user' || role === 'assistant' || role === 'system')
|
|
209
|
+
claudeish++;
|
|
210
|
+
}
|
|
211
|
+
if (toolish > 0 && toolish >= claudeish)
|
|
212
|
+
return 'tool-calls';
|
|
213
|
+
if (claudeish > 0)
|
|
214
|
+
return 'claude-jsonl';
|
|
215
|
+
return 'dragon';
|
|
216
|
+
}
|
|
217
|
+
/** Parse a trace body into normalized segments using the chosen (or sniffed) format. */
|
|
218
|
+
export function parseTrace(raw, format = 'auto') {
|
|
219
|
+
const fmt = format === 'auto' ? detectTraceFormat(raw) : format;
|
|
220
|
+
const segments = fmt === 'tool-calls' ? parseToolCalls(raw) :
|
|
221
|
+
fmt === 'dragon' ? parseDragonTrace(raw) :
|
|
222
|
+
parseClaudeJsonl(raw);
|
|
223
|
+
return { segments, format: fmt };
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Fold parsed segments into ONE prose blob for the extractor. Deterministic
|
|
227
|
+
* (preserves segment order); bounded so a huge transcript can't materialize an
|
|
228
|
+
* unbounded segment array downstream (the deterministic extractor splits the
|
|
229
|
+
* FULL text). Caps total chars; drops the tail past the cap rather than
|
|
230
|
+
* silently mangling.
|
|
231
|
+
*/
|
|
232
|
+
export function segmentsToText(segments, maxChars = 24_000) {
|
|
233
|
+
const parts = [];
|
|
234
|
+
let total = 0;
|
|
235
|
+
for (const s of segments) {
|
|
236
|
+
const line = s.text;
|
|
237
|
+
if (total + line.length > maxChars)
|
|
238
|
+
break;
|
|
239
|
+
parts.push(line);
|
|
240
|
+
total += line.length + 1;
|
|
241
|
+
}
|
|
242
|
+
return parts.join('\n');
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=trace-harvest.js.map
|
package/dist/types.js
CHANGED
|
@@ -1 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Wyrm Types - Core type definitions
|
|
3
|
+
*
|
|
4
|
+
* @copyright 2026 Ghost Protocol (Pvt) Ltd.
|
|
5
|
+
* @license Proprietary — (c) 2026 Ghost Protocol (Pvt) Ltd. All rights reserved. See LICENSE.
|
|
6
|
+
* @module types
|
|
7
|
+
* @version 3.0.0
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_CONFIG = {
|
|
10
|
+
database: {
|
|
11
|
+
wal: true,
|
|
12
|
+
cacheSize: 64000,
|
|
13
|
+
},
|
|
14
|
+
encryption: {
|
|
15
|
+
enabled: false,
|
|
16
|
+
},
|
|
17
|
+
logging: {
|
|
18
|
+
level: 'info',
|
|
19
|
+
console: true,
|
|
20
|
+
},
|
|
21
|
+
http: {
|
|
22
|
+
port: 3333,
|
|
23
|
+
host: '127.0.0.1',
|
|
24
|
+
},
|
|
25
|
+
sync: {
|
|
26
|
+
autoImport: true,
|
|
27
|
+
autoExport: false,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=types.js.map
|
package/dist/ui-dashboard.js
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Wyrm Visual Web Dashboard — Self-contained HTML SPA
|
|
3
|
+
*
|
|
4
|
+
* @copyright 2026 Ghost Protocol (Pvt) Ltd.
|
|
5
|
+
* @license Proprietary — (c) 2026 Ghost Protocol (Pvt) Ltd. All rights reserved. See LICENSE.
|
|
6
|
+
*/
|
|
7
|
+
export function getUIDashboardHTML() {
|
|
8
|
+
return `<!DOCTYPE html>
|
|
2
9
|
<html lang="en">
|
|
3
10
|
<head>
|
|
4
11
|
<meta charset="UTF-8">
|
|
@@ -254,7 +261,7 @@ main { padding: calc(var(--nav-h) + 24px) 24px 24px; max-width: 1200px; margin:
|
|
|
254
261
|
(function() {
|
|
255
262
|
'use strict';
|
|
256
263
|
|
|
257
|
-
//
|
|
264
|
+
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
258
265
|
function el(tag, cls, text) {
|
|
259
266
|
const e = document.createElement(tag);
|
|
260
267
|
if (cls) e.className = cls;
|
|
@@ -306,7 +313,7 @@ async function apiPost(path) {
|
|
|
306
313
|
|
|
307
314
|
function truncate(s, n) {
|
|
308
315
|
if (!s) return '';
|
|
309
|
-
return s.length > n ? s.slice(0, n) + '
|
|
316
|
+
return s.length > n ? s.slice(0, n) + '…' : s;
|
|
310
317
|
}
|
|
311
318
|
|
|
312
319
|
function clearEl(e) {
|
|
@@ -374,7 +381,7 @@ function staleBar(staleness) {
|
|
|
374
381
|
return wrap;
|
|
375
382
|
}
|
|
376
383
|
|
|
377
|
-
//
|
|
384
|
+
// ── Router ───────────────────────────────────────────────────────────────────
|
|
378
385
|
const TABS = ['overview', 'impact', 'memories', 'quests', 'truths', 'skills', 'review'];
|
|
379
386
|
let currentTab = '';
|
|
380
387
|
// Set from GET /ui/account.readonly at boot (WYRM_UI_READONLY=1 on the server).
|
|
@@ -406,7 +413,7 @@ document.querySelectorAll('.tab-btn').forEach(btn => {
|
|
|
406
413
|
});
|
|
407
414
|
window.addEventListener('hashchange', router);
|
|
408
415
|
|
|
409
|
-
//
|
|
416
|
+
// ── Overview ─────────────────────────────────────────────────────────────────
|
|
410
417
|
async function loadOverview() {
|
|
411
418
|
const pane = document.getElementById('pane-overview');
|
|
412
419
|
clearEl(pane);
|
|
@@ -449,13 +456,13 @@ async function loadOverview() {
|
|
|
449
456
|
card.replaceChild(vEl, skel);
|
|
450
457
|
}
|
|
451
458
|
});
|
|
452
|
-
// Recent sessions
|
|
459
|
+
// Recent sessions — remove skeleton list, then insert real data
|
|
453
460
|
pane.querySelector('.list')?.remove();
|
|
454
461
|
const sl = el('div', 'sessions-list');
|
|
455
462
|
const sessions = data.recent_sessions || [];
|
|
456
463
|
if (sessions.length === 0) {
|
|
457
464
|
const em = el('div', 'empty');
|
|
458
|
-
em.appendChild(el('div', 'empty-icon', '
|
|
465
|
+
em.appendChild(el('div', 'empty-icon', '📭'));
|
|
459
466
|
em.appendChild(el('div', null, 'No sessions yet'));
|
|
460
467
|
sl.appendChild(em);
|
|
461
468
|
} else {
|
|
@@ -470,7 +477,7 @@ async function loadOverview() {
|
|
|
470
477
|
} catch(e) { showToast(String(e), 'error'); }
|
|
471
478
|
}
|
|
472
479
|
|
|
473
|
-
//
|
|
480
|
+
// ── Memories ─────────────────────────────────────────────────────────────────
|
|
474
481
|
let memPage = 1, memKind = '', memSearch = '', memDebounce = null;
|
|
475
482
|
|
|
476
483
|
async function loadMemories(page, kind, search) {
|
|
@@ -496,7 +503,7 @@ async function loadMemories(page, kind, search) {
|
|
|
496
503
|
const newList = el('div', 'list');
|
|
497
504
|
if (!data.items || data.items.length === 0) {
|
|
498
505
|
const em = el('div', 'empty');
|
|
499
|
-
em.appendChild(el('div', 'empty-icon', '
|
|
506
|
+
em.appendChild(el('div', 'empty-icon', '🧠'));
|
|
500
507
|
em.appendChild(el('div', null, 'No memory artifacts found'));
|
|
501
508
|
newList.appendChild(em);
|
|
502
509
|
} else {
|
|
@@ -544,7 +551,7 @@ function initMemoriesPane() {
|
|
|
544
551
|
const filters = el('div', 'filters');
|
|
545
552
|
const si = el('input', 'filter-input');
|
|
546
553
|
si.type = 'search';
|
|
547
|
-
si.placeholder = 'Search memories
|
|
554
|
+
si.placeholder = 'Search memories…';
|
|
548
555
|
si.addEventListener('input', () => {
|
|
549
556
|
memSearch = si.value;
|
|
550
557
|
clearTimeout(memDebounce);
|
|
@@ -571,7 +578,7 @@ function initMemoriesPane() {
|
|
|
571
578
|
pane.insertBefore(filters, pane.firstChild);
|
|
572
579
|
}
|
|
573
580
|
|
|
574
|
-
//
|
|
581
|
+
// ── Quests ───────────────────────────────────────────────────────────────────
|
|
575
582
|
async function loadQuests() {
|
|
576
583
|
const pane = document.getElementById('pane-quests');
|
|
577
584
|
clearEl(pane);
|
|
@@ -583,7 +590,7 @@ async function loadQuests() {
|
|
|
583
590
|
const col = el('div', 'kanban-col');
|
|
584
591
|
const hdr = el('div', 'kanban-header');
|
|
585
592
|
hdr.appendChild(el('span', 'kanban-title', colLabels[status]));
|
|
586
|
-
const cnt = el('span', 'kanban-count', '
|
|
593
|
+
const cnt = el('span', 'kanban-count', '…');
|
|
587
594
|
hdr.appendChild(cnt);
|
|
588
595
|
col.appendChild(hdr);
|
|
589
596
|
col.dataset.status = status;
|
|
@@ -620,7 +627,7 @@ async function loadQuests() {
|
|
|
620
627
|
} catch(e) { showToast(String(e), 'error'); }
|
|
621
628
|
}
|
|
622
629
|
|
|
623
|
-
//
|
|
630
|
+
// ── Truths ───────────────────────────────────────────────────────────────────
|
|
624
631
|
let truthPage = 1;
|
|
625
632
|
|
|
626
633
|
async function loadTruths(page) {
|
|
@@ -639,7 +646,7 @@ async function loadTruths(page) {
|
|
|
639
646
|
const list = el('div', 'list');
|
|
640
647
|
if (!data.items || data.items.length === 0) {
|
|
641
648
|
const em = el('div', 'empty');
|
|
642
|
-
em.appendChild(el('div', 'empty-icon', '
|
|
649
|
+
em.appendChild(el('div', 'empty-icon', '📚'));
|
|
643
650
|
em.appendChild(el('div', null, 'No ground truths yet'));
|
|
644
651
|
list.appendChild(em);
|
|
645
652
|
} else {
|
|
@@ -649,7 +656,7 @@ async function loadTruths(page) {
|
|
|
649
656
|
row1.appendChild(el('span', 'truth-cat', t.category));
|
|
650
657
|
row1.appendChild(el('span', 'truth-key', t.key));
|
|
651
658
|
if (t.staleness != null && t.staleness > 0.7) {
|
|
652
|
-
row1.appendChild(el('span', null, '
|
|
659
|
+
row1.appendChild(el('span', null, '⚠️'));
|
|
653
660
|
}
|
|
654
661
|
item.appendChild(row1);
|
|
655
662
|
item.appendChild(el('div', 'truth-value', truncate(t.value, 150)));
|
|
@@ -682,7 +689,7 @@ async function loadTruths(page) {
|
|
|
682
689
|
} catch(e) { showToast(String(e), 'error'); }
|
|
683
690
|
}
|
|
684
691
|
|
|
685
|
-
//
|
|
692
|
+
// ── Review ───────────────────────────────────────────────────────────────────
|
|
686
693
|
async function loadReview() {
|
|
687
694
|
const pane = document.getElementById('pane-review');
|
|
688
695
|
clearEl(pane);
|
|
@@ -694,7 +701,7 @@ async function loadReview() {
|
|
|
694
701
|
const items = data.items || [];
|
|
695
702
|
if (items.length === 0) {
|
|
696
703
|
const em = el('div', 'empty');
|
|
697
|
-
em.appendChild(el('div', 'empty-icon', '
|
|
704
|
+
em.appendChild(el('div', 'empty-icon', '✅'));
|
|
698
705
|
em.appendChild(el('div', null, 'Review queue is empty'));
|
|
699
706
|
pane.appendChild(em);
|
|
700
707
|
return;
|
|
@@ -712,8 +719,8 @@ async function loadReview() {
|
|
|
712
719
|
// Approve/reject mutate the queue, withheld in read-only/public view.
|
|
713
720
|
if (!READONLY) {
|
|
714
721
|
const actions = el('div', 'review-actions');
|
|
715
|
-
const approveBtn = el('button', 'btn btn-approve', '
|
|
716
|
-
const rejectBtn = el('button', 'btn btn-reject', '
|
|
722
|
+
const approveBtn = el('button', 'btn btn-approve', '✓ Approve');
|
|
723
|
+
const rejectBtn = el('button', 'btn btn-reject', '✕ Reject');
|
|
717
724
|
approveBtn.addEventListener('click', async () => {
|
|
718
725
|
try {
|
|
719
726
|
await apiPost('/ui/review/' + m.id + '/approve');
|
|
@@ -722,7 +729,7 @@ async function loadReview() {
|
|
|
722
729
|
if (list.querySelectorAll('.review-item').length === 0) {
|
|
723
730
|
list.remove();
|
|
724
731
|
const em = el('div', 'empty');
|
|
725
|
-
em.appendChild(el('div', 'empty-icon', '
|
|
732
|
+
em.appendChild(el('div', 'empty-icon', '✅'));
|
|
726
733
|
em.appendChild(el('div', null, 'Review queue is empty'));
|
|
727
734
|
pane.appendChild(em);
|
|
728
735
|
}
|
|
@@ -736,7 +743,7 @@ async function loadReview() {
|
|
|
736
743
|
if (list.querySelectorAll('.review-item').length === 0) {
|
|
737
744
|
list.remove();
|
|
738
745
|
const em = el('div', 'empty');
|
|
739
|
-
em.appendChild(el('div', 'empty-icon', '
|
|
746
|
+
em.appendChild(el('div', 'empty-icon', '✅'));
|
|
740
747
|
em.appendChild(el('div', null, 'Review queue is empty'));
|
|
741
748
|
pane.appendChild(em);
|
|
742
749
|
}
|
|
@@ -752,7 +759,7 @@ async function loadReview() {
|
|
|
752
759
|
} catch(e) { showToast(String(e), 'error'); }
|
|
753
760
|
}
|
|
754
761
|
|
|
755
|
-
//
|
|
762
|
+
// ── Skills ─────────────────────────────────────────────────────────────────
|
|
756
763
|
async function loadSkills() {
|
|
757
764
|
const pane = document.getElementById('pane-skills');
|
|
758
765
|
clearEl(pane);
|
|
@@ -763,7 +770,7 @@ async function loadSkills() {
|
|
|
763
770
|
const items = data.items || [];
|
|
764
771
|
if (items.length === 0) {
|
|
765
772
|
const em = el('div', 'empty');
|
|
766
|
-
em.appendChild(el('div', 'empty-icon', '
|
|
773
|
+
em.appendChild(el('div', 'empty-icon', '🧩'));
|
|
767
774
|
em.appendChild(el('div', null, 'No skills registered yet'));
|
|
768
775
|
pane.appendChild(em);
|
|
769
776
|
return;
|
|
@@ -791,7 +798,7 @@ async function loadSkills() {
|
|
|
791
798
|
} catch(e) { showToast(String(e), 'error'); }
|
|
792
799
|
}
|
|
793
800
|
|
|
794
|
-
//
|
|
801
|
+
// ── Impact ───────────────────────────────────────────────────────────────────
|
|
795
802
|
function fmtNum(n) {
|
|
796
803
|
if (n >= 1000) return (n / 1000).toFixed(n >= 10000 ? 0 : 1).replace(/\\.0$/, '') + 'k';
|
|
797
804
|
return String(n || 0);
|
|
@@ -850,15 +857,15 @@ async function loadImpact() {
|
|
|
850
857
|
} catch(e) { showToast(String(e), 'error'); }
|
|
851
858
|
}
|
|
852
859
|
|
|
853
|
-
//
|
|
860
|
+
// ── Memory detail modal ───────────────────────────────────────────────────────
|
|
854
861
|
let modalReq = 0;
|
|
855
862
|
async function openMemoryModal(id) {
|
|
856
863
|
const myReq = ++modalReq;
|
|
857
864
|
const ov = document.getElementById('modal-overlay');
|
|
858
865
|
const card = document.getElementById('modal-card');
|
|
859
866
|
clearEl(card);
|
|
860
|
-
const close = el('span', 'modal-close', '
|
|
861
|
-
card.appendChild(el('div', 'item-sub', 'Loading
|
|
867
|
+
const close = el('span', 'modal-close', '✕'); close.onclick = closeModal; card.appendChild(close);
|
|
868
|
+
card.appendChild(el('div', 'item-sub', 'Loading…'));
|
|
862
869
|
ov.classList.add('open');
|
|
863
870
|
try {
|
|
864
871
|
const d = await apiFetch('/ui/memory?id=' + id);
|
|
@@ -866,7 +873,7 @@ async function openMemoryModal(id) {
|
|
|
866
873
|
if (myReq !== modalReq || !ov.classList.contains('open')) return;
|
|
867
874
|
const it = d.item;
|
|
868
875
|
clearEl(card);
|
|
869
|
-
const cl = el('span', 'modal-close', '
|
|
876
|
+
const cl = el('span', 'modal-close', '✕'); cl.onclick = closeModal; card.appendChild(cl);
|
|
870
877
|
if (!it) { card.appendChild(el('div', 'item-sub', 'Memory not found.')); return; }
|
|
871
878
|
const row = el('div', 'item-row');
|
|
872
879
|
if (it.kind) row.appendChild(kindBadge(it.kind));
|
|
@@ -895,12 +902,12 @@ async function openMemoryModal(id) {
|
|
|
895
902
|
const used = (it.access_count || 0), reused = (it.reuse_count || 0);
|
|
896
903
|
// "Surfaced" = times recalled (auto); "Confirmed helpful" = times an agent
|
|
897
904
|
// called wyrm_feedback after applying it. 0 here means no feedback yet, not broken.
|
|
898
|
-
card.appendChild(el('div', 'item-sub', 'Surfaced ' + used + '
|
|
905
|
+
card.appendChild(el('div', 'item-sub', 'Surfaced ' + used + '× · confirmed helpful ' + reused + '×'));
|
|
899
906
|
} catch(e) { if (myReq === modalReq) closeModal(); }
|
|
900
907
|
}
|
|
901
908
|
function closeModal() { const ov = document.getElementById('modal-overlay'); if (ov) ov.classList.remove('open'); }
|
|
902
909
|
|
|
903
|
-
//
|
|
910
|
+
// ── Account badge ────────────────────────────────────────────────────────────
|
|
904
911
|
async function loadAccount() {
|
|
905
912
|
const box = document.getElementById('acct');
|
|
906
913
|
if (!box) return;
|
|
@@ -920,14 +927,14 @@ async function loadAccount() {
|
|
|
920
927
|
box.classList.add('ro');
|
|
921
928
|
box.title = 'Read-only public view';
|
|
922
929
|
} else {
|
|
923
|
-
box.appendChild(el('span', 'acct-caret', '
|
|
930
|
+
box.appendChild(el('span', 'acct-caret', '▾'));
|
|
924
931
|
box.title = 'Click to switch account / home';
|
|
925
932
|
box.onclick = toggleAcctMenu;
|
|
926
933
|
}
|
|
927
934
|
} catch(e) { /* badge stays empty on failure */ }
|
|
928
935
|
}
|
|
929
936
|
|
|
930
|
-
//
|
|
937
|
+
// ── Account switcher dropdown ─────────────────────────────────────────────────
|
|
931
938
|
let acctMenuOpen = false;
|
|
932
939
|
async function toggleAcctMenu(ev) {
|
|
933
940
|
if (ev) ev.stopPropagation();
|
|
@@ -936,7 +943,7 @@ async function toggleAcctMenu(ev) {
|
|
|
936
943
|
if (acctMenuOpen) { menu.classList.remove('open'); acctMenuOpen = false; return; }
|
|
937
944
|
clearEl(menu);
|
|
938
945
|
menu.appendChild(el('div', 'acct-menu-label', 'Switch account / home'));
|
|
939
|
-
menu.appendChild(el('div', 'acct-menu-label', 'Loading
|
|
946
|
+
menu.appendChild(el('div', 'acct-menu-label', 'Loading…'));
|
|
940
947
|
menu.classList.add('open'); acctMenuOpen = true;
|
|
941
948
|
try {
|
|
942
949
|
const r = await fetch('/ui/homes');
|
|
@@ -949,9 +956,9 @@ async function toggleAcctMenu(ev) {
|
|
|
949
956
|
const it = el('div', 'acct-menu-item' + (h.active ? ' active' : ''));
|
|
950
957
|
const a = el('div', 'ai-acct');
|
|
951
958
|
a.appendChild(el('span', null, h.account || h.name));
|
|
952
|
-
if (h.active) a.appendChild(el('span', 'ai-check', '
|
|
959
|
+
if (h.active) a.appendChild(el('span', 'ai-check', '● active'));
|
|
953
960
|
it.appendChild(a);
|
|
954
|
-
it.appendChild(el('div', 'ai-meta', (h.tier || 'free') + '
|
|
961
|
+
it.appendChild(el('div', 'ai-meta', (h.tier || 'free') + ' · ' + h.name));
|
|
955
962
|
if (!h.active) it.addEventListener('click', () => switchHome(h.dbPath));
|
|
956
963
|
menu.appendChild(it);
|
|
957
964
|
});
|
|
@@ -983,22 +990,22 @@ document.getElementById('modal-overlay').addEventListener('click', (e) => {
|
|
|
983
990
|
});
|
|
984
991
|
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeModal(); });
|
|
985
992
|
|
|
986
|
-
//
|
|
993
|
+
// ── Pagination helper ─────────────────────────────────────────────────────────
|
|
987
994
|
function buildPagination(current, total, onPage) {
|
|
988
995
|
const pgn = el('div', 'pagination');
|
|
989
|
-
const prev = el('button', 'page-btn', '
|
|
996
|
+
const prev = el('button', 'page-btn', '← Prev');
|
|
990
997
|
prev.disabled = current <= 1;
|
|
991
998
|
prev.addEventListener('click', () => onPage(current - 1));
|
|
992
999
|
pgn.appendChild(prev);
|
|
993
1000
|
pgn.appendChild(el('span', 'page-info', 'Page ' + current + ' of ' + total));
|
|
994
|
-
const next = el('button', 'page-btn', 'Next
|
|
1001
|
+
const next = el('button', 'page-btn', 'Next →');
|
|
995
1002
|
next.disabled = current >= total;
|
|
996
1003
|
next.addEventListener('click', () => onPage(current + 1));
|
|
997
1004
|
pgn.appendChild(next);
|
|
998
1005
|
return pgn;
|
|
999
1006
|
}
|
|
1000
1007
|
|
|
1001
|
-
//
|
|
1008
|
+
// ── Tab loader ────────────────────────────────────────────────────────────────
|
|
1002
1009
|
function loadTab(name) {
|
|
1003
1010
|
if (name === 'overview') loadOverview();
|
|
1004
1011
|
else if (name === 'impact') loadImpact();
|
|
@@ -1014,6 +1021,8 @@ function loadTab(name) {
|
|
|
1014
1021
|
// so the Review pane knows whether to show approve/reject controls.
|
|
1015
1022
|
loadAccount().then(router);
|
|
1016
1023
|
})();
|
|
1017
|
-
|
|
1024
|
+
</script>
|
|
1018
1025
|
</body>
|
|
1019
|
-
</html
|
|
1026
|
+
</html>`;
|
|
1027
|
+
}
|
|
1028
|
+
//# sourceMappingURL=ui-dashboard.js.map
|