@ai-studio-3d/vyasa 0.1.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 +69 -0
- package/data/common-kit.json +34 -0
- package/data/pricing.json +119 -0
- package/data/schema/AnalyticsData.json +214 -0
- package/data/schema/FoundationData.json +42 -0
- package/data/schema/KitData.json +321 -0
- package/data/schema/SearchData.json +173 -0
- package/data/schema/SessionDetailData.json +231 -0
- package/data/schema/SessionsListData.json +115 -0
- package/data/schema/WasteData.json +95 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +343 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/billing/index.d.ts +4 -0
- package/dist/core/billing/index.d.ts.map +1 -0
- package/dist/core/billing/index.js +43 -0
- package/dist/core/billing/index.js.map +1 -0
- package/dist/core/budget/index.d.ts +30 -0
- package/dist/core/budget/index.d.ts.map +1 -0
- package/dist/core/budget/index.js +61 -0
- package/dist/core/budget/index.js.map +1 -0
- package/dist/core/codex/index.d.ts +3 -0
- package/dist/core/codex/index.d.ts.map +1 -0
- package/dist/core/codex/index.js +212 -0
- package/dist/core/codex/index.js.map +1 -0
- package/dist/core/cursor/index.d.ts +3 -0
- package/dist/core/cursor/index.d.ts.map +1 -0
- package/dist/core/cursor/index.js +304 -0
- package/dist/core/cursor/index.js.map +1 -0
- package/dist/core/cursor/scan.d.ts +28 -0
- package/dist/core/cursor/scan.d.ts.map +1 -0
- package/dist/core/cursor/scan.js +79 -0
- package/dist/core/cursor/scan.js.map +1 -0
- package/dist/core/decisions/index.d.ts +21 -0
- package/dist/core/decisions/index.d.ts.map +1 -0
- package/dist/core/decisions/index.js +133 -0
- package/dist/core/decisions/index.js.map +1 -0
- package/dist/core/dlp/index.d.ts +7 -0
- package/dist/core/dlp/index.d.ts.map +1 -0
- package/dist/core/dlp/index.js +115 -0
- package/dist/core/dlp/index.js.map +1 -0
- package/dist/core/health/index.d.ts +10 -0
- package/dist/core/health/index.d.ts.map +1 -0
- package/dist/core/health/index.js +21 -0
- package/dist/core/health/index.js.map +1 -0
- package/dist/core/index/index.d.ts +9 -0
- package/dist/core/index/index.d.ts.map +1 -0
- package/dist/core/index/index.js +103 -0
- package/dist/core/index/index.js.map +1 -0
- package/dist/core/index/ingest.d.ts +16 -0
- package/dist/core/index/ingest.d.ts.map +1 -0
- package/dist/core/index/ingest.js +184 -0
- package/dist/core/index/ingest.js.map +1 -0
- package/dist/core/index/platforms.d.ts +21 -0
- package/dist/core/index/platforms.d.ts.map +1 -0
- package/dist/core/index/platforms.js +44 -0
- package/dist/core/index/platforms.js.map +1 -0
- package/dist/core/index/pricing-map.d.ts +10 -0
- package/dist/core/index/pricing-map.d.ts.map +1 -0
- package/dist/core/index/pricing-map.js +16 -0
- package/dist/core/index/pricing-map.js.map +1 -0
- package/dist/core/index/progress.d.ts +26 -0
- package/dist/core/index/progress.d.ts.map +1 -0
- package/dist/core/index/progress.js +59 -0
- package/dist/core/index/progress.js.map +1 -0
- package/dist/core/index/scan.d.ts +9 -0
- package/dist/core/index/scan.d.ts.map +1 -0
- package/dist/core/index/scan.js +42 -0
- package/dist/core/index/scan.js.map +1 -0
- package/dist/core/index/statements.d.ts +18 -0
- package/dist/core/index/statements.d.ts.map +1 -0
- package/dist/core/index/statements.js +82 -0
- package/dist/core/index/statements.js.map +1 -0
- package/dist/core/index/tail.d.ts +42 -0
- package/dist/core/index/tail.d.ts.map +1 -0
- package/dist/core/index/tail.js +123 -0
- package/dist/core/index/tail.js.map +1 -0
- package/dist/core/jsonl/index.d.ts +3 -0
- package/dist/core/jsonl/index.d.ts.map +1 -0
- package/dist/core/jsonl/index.js +106 -0
- package/dist/core/jsonl/index.js.map +1 -0
- package/dist/core/jsonl-validate/index.d.ts +10 -0
- package/dist/core/jsonl-validate/index.d.ts.map +1 -0
- package/dist/core/jsonl-validate/index.js +40 -0
- package/dist/core/jsonl-validate/index.js.map +1 -0
- package/dist/core/kit/detection.d.ts +94 -0
- package/dist/core/kit/detection.d.ts.map +1 -0
- package/dist/core/kit/detection.js +312 -0
- package/dist/core/kit/detection.js.map +1 -0
- package/dist/core/kit/index.d.ts +12 -0
- package/dist/core/kit/index.d.ts.map +1 -0
- package/dist/core/kit/index.js +131 -0
- package/dist/core/kit/index.js.map +1 -0
- package/dist/core/kit/scan.d.ts +28 -0
- package/dist/core/kit/scan.d.ts.map +1 -0
- package/dist/core/kit/scan.js +432 -0
- package/dist/core/kit/scan.js.map +1 -0
- package/dist/core/recap/index.d.ts +18 -0
- package/dist/core/recap/index.d.ts.map +1 -0
- package/dist/core/recap/index.js +88 -0
- package/dist/core/recap/index.js.map +1 -0
- package/dist/core/repetition/index.d.ts +5 -0
- package/dist/core/repetition/index.d.ts.map +1 -0
- package/dist/core/repetition/index.js +0 -0
- package/dist/core/repetition/index.js.map +1 -0
- package/dist/core/schema/index.d.ts +514 -0
- package/dist/core/schema/index.d.ts.map +1 -0
- package/dist/core/schema/index.js +2 -0
- package/dist/core/schema/index.js.map +1 -0
- package/dist/core/schema-watch/index.d.ts +34 -0
- package/dist/core/schema-watch/index.d.ts.map +1 -0
- package/dist/core/schema-watch/index.js +87 -0
- package/dist/core/schema-watch/index.js.map +1 -0
- package/dist/core/search/index.d.ts +44 -0
- package/dist/core/search/index.d.ts.map +1 -0
- package/dist/core/search/index.js +641 -0
- package/dist/core/search/index.js.map +1 -0
- package/dist/core/settings/index.d.ts +24 -0
- package/dist/core/settings/index.d.ts.map +1 -0
- package/dist/core/settings/index.js +76 -0
- package/dist/core/settings/index.js.map +1 -0
- package/dist/core/share/bundle.d.ts +40 -0
- package/dist/core/share/bundle.d.ts.map +1 -0
- package/dist/core/share/bundle.js +158 -0
- package/dist/core/share/bundle.js.map +1 -0
- package/dist/core/share/canonical/from-claude.d.ts +13 -0
- package/dist/core/share/canonical/from-claude.d.ts.map +1 -0
- package/dist/core/share/canonical/from-claude.js +129 -0
- package/dist/core/share/canonical/from-claude.js.map +1 -0
- package/dist/core/share/canonical/from-codex.d.ts +18 -0
- package/dist/core/share/canonical/from-codex.d.ts.map +1 -0
- package/dist/core/share/canonical/from-codex.js +183 -0
- package/dist/core/share/canonical/from-codex.js.map +1 -0
- package/dist/core/share/canonical/to-claude.d.ts +15 -0
- package/dist/core/share/canonical/to-claude.d.ts.map +1 -0
- package/dist/core/share/canonical/to-claude.js +146 -0
- package/dist/core/share/canonical/to-claude.js.map +1 -0
- package/dist/core/share/canonical/to-codex.d.ts +21 -0
- package/dist/core/share/canonical/to-codex.d.ts.map +1 -0
- package/dist/core/share/canonical/to-codex.js +124 -0
- package/dist/core/share/canonical/to-codex.js.map +1 -0
- package/dist/core/share/canonical/tool-map.d.ts +61 -0
- package/dist/core/share/canonical/tool-map.d.ts.map +1 -0
- package/dist/core/share/canonical/tool-map.js +299 -0
- package/dist/core/share/canonical/tool-map.js.map +1 -0
- package/dist/core/share/canonical/types.d.ts +57 -0
- package/dist/core/share/canonical/types.d.ts.map +1 -0
- package/dist/core/share/canonical/types.js +9 -0
- package/dist/core/share/canonical/types.js.map +1 -0
- package/dist/core/share/import.d.ts +28 -0
- package/dist/core/share/import.d.ts.map +1 -0
- package/dist/core/share/import.js +174 -0
- package/dist/core/share/import.js.map +1 -0
- package/dist/core/share/manifest.d.ts +37 -0
- package/dist/core/share/manifest.d.ts.map +1 -0
- package/dist/core/share/manifest.js +31 -0
- package/dist/core/share/manifest.js.map +1 -0
- package/dist/core/share/preview.d.ts +4 -0
- package/dist/core/share/preview.d.ts.map +1 -0
- package/dist/core/share/preview.js +153 -0
- package/dist/core/share/preview.js.map +1 -0
- package/dist/core/share/primer.d.ts +19 -0
- package/dist/core/share/primer.d.ts.map +1 -0
- package/dist/core/share/primer.js +196 -0
- package/dist/core/share/primer.js.map +1 -0
- package/dist/core/share/resume.d.ts +10 -0
- package/dist/core/share/resume.d.ts.map +1 -0
- package/dist/core/share/resume.js +58 -0
- package/dist/core/share/resume.js.map +1 -0
- package/dist/core/share/scrub.d.ts +10 -0
- package/dist/core/share/scrub.d.ts.map +1 -0
- package/dist/core/share/scrub.js +198 -0
- package/dist/core/share/scrub.js.map +1 -0
- package/dist/core/share/tar.d.ts +12 -0
- package/dist/core/share/tar.d.ts.map +1 -0
- package/dist/core/share/tar.js +78 -0
- package/dist/core/share/tar.js.map +1 -0
- package/dist/core/tags/index.d.ts +48 -0
- package/dist/core/tags/index.d.ts.map +1 -0
- package/dist/core/tags/index.js +113 -0
- package/dist/core/tags/index.js.map +1 -0
- package/dist/core/today/index.d.ts +25 -0
- package/dist/core/today/index.d.ts.map +1 -0
- package/dist/core/today/index.js +42 -0
- package/dist/core/today/index.js.map +1 -0
- package/dist/core/waste/abandoned.d.ts +12 -0
- package/dist/core/waste/abandoned.d.ts.map +1 -0
- package/dist/core/waste/abandoned.js +127 -0
- package/dist/core/waste/abandoned.js.map +1 -0
- package/dist/core/waste/cache-miss.d.ts +9 -0
- package/dist/core/waste/cache-miss.d.ts.map +1 -0
- package/dist/core/waste/cache-miss.js +84 -0
- package/dist/core/waste/cache-miss.js.map +1 -0
- package/dist/core/waste/index.d.ts +12 -0
- package/dist/core/waste/index.d.ts.map +1 -0
- package/dist/core/waste/index.js +45 -0
- package/dist/core/waste/index.js.map +1 -0
- package/dist/core/waste/wrong-model.d.ts +11 -0
- package/dist/core/waste/wrong-model.d.ts.map +1 -0
- package/dist/core/waste/wrong-model.js +104 -0
- package/dist/core/waste/wrong-model.js.map +1 -0
- package/dist/db/index.d.ts +10 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +29 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrate.d.ts +8 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +282 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/server/events.d.ts +4 -0
- package/dist/server/events.d.ts.map +1 -0
- package/dist/server/events.js +54 -0
- package/dist/server/events.js.map +1 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +238 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes/foundation.d.ts +2 -0
- package/dist/server/routes/foundation.d.ts.map +1 -0
- package/dist/server/routes/foundation.js +2 -0
- package/dist/server/routes/foundation.js.map +1 -0
- package/dist/server/routes/search.d.ts +2 -0
- package/dist/server/routes/search.d.ts.map +1 -0
- package/dist/server/routes/search.js +2 -0
- package/dist/server/routes/search.js.map +1 -0
- package/dist/server/routes/sessions.d.ts +2 -0
- package/dist/server/routes/sessions.d.ts.map +1 -0
- package/dist/server/routes/sessions.js +2 -0
- package/dist/server/routes/sessions.js.map +1 -0
- package/dist/server/routes/waste.d.ts +2 -0
- package/dist/server/routes/waste.d.ts.map +1 -0
- package/dist/server/routes/waste.js +2 -0
- package/dist/server/routes/waste.js.map +1 -0
- package/dist/web/assets/index-Ba1VvTj0.js +37 -0
- package/dist/web/index.html +12 -0
- package/package.json +76 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns per-skill usage statistics over the lookback window.
|
|
3
|
+
* Skill firings are tool_calls with tool='Skill' and input_json containing
|
|
4
|
+
* {"skill": "<plugin>:<name>"} (plugin-installed)
|
|
5
|
+
* {"skill": "<name>"} (loose)
|
|
6
|
+
* The canonical id from the call is the join key.
|
|
7
|
+
*/
|
|
8
|
+
export function loadSkillUsage(db, lookbackDays) {
|
|
9
|
+
const sinceMs = Date.now() - lookbackDays * 24 * 60 * 60 * 1000;
|
|
10
|
+
const sinceIso = new Date(sinceMs).toISOString();
|
|
11
|
+
// JSON parsing in SQL would require json_extract on a million-row scan; pulling
|
|
12
|
+
// candidate rows to JS is faster for the row counts we care about (typically
|
|
13
|
+
// single-digit thousands of Skill calls).
|
|
14
|
+
const rows = db
|
|
15
|
+
.prepare(`
|
|
16
|
+
SELECT tc.input_json, m.ts
|
|
17
|
+
FROM tool_calls tc
|
|
18
|
+
JOIN messages m ON m.id = tc.message_id
|
|
19
|
+
WHERE tc.tool = 'Skill'
|
|
20
|
+
AND m.ts >= ?
|
|
21
|
+
`)
|
|
22
|
+
.all(sinceIso);
|
|
23
|
+
const out = new Map();
|
|
24
|
+
for (const r of rows) {
|
|
25
|
+
if (!r.input_json)
|
|
26
|
+
continue;
|
|
27
|
+
let id;
|
|
28
|
+
try {
|
|
29
|
+
const obj = JSON.parse(r.input_json);
|
|
30
|
+
if (typeof obj.skill !== 'string')
|
|
31
|
+
continue;
|
|
32
|
+
id = obj.skill;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const tsMs = Date.parse(r.ts);
|
|
38
|
+
if (!Number.isFinite(tsMs))
|
|
39
|
+
continue;
|
|
40
|
+
const cur = out.get(id);
|
|
41
|
+
if (!cur) {
|
|
42
|
+
out.set(id, { count: 1, lastUsedMs: tsMs });
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
cur.count++;
|
|
46
|
+
if (tsMs > cur.lastUsedMs)
|
|
47
|
+
cur.lastUsedMs = tsMs;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Returns per-MCP-server usage statistics over the lookback window. Server
|
|
54
|
+
* name is the token between the first two '__' in the tool name (e.g.
|
|
55
|
+
* `mcp__chrome-devtools__navigate_page` → 'chrome-devtools').
|
|
56
|
+
*/
|
|
57
|
+
export function loadMcpUsage(db, lookbackDays) {
|
|
58
|
+
const sinceMs = Date.now() - lookbackDays * 24 * 60 * 60 * 1000;
|
|
59
|
+
const sinceIso = new Date(sinceMs).toISOString();
|
|
60
|
+
const rows = db
|
|
61
|
+
.prepare(`
|
|
62
|
+
SELECT tc.tool, m.ts
|
|
63
|
+
FROM tool_calls tc
|
|
64
|
+
JOIN messages m ON m.id = tc.message_id
|
|
65
|
+
WHERE tc.tool LIKE 'mcp__%'
|
|
66
|
+
AND m.ts >= ?
|
|
67
|
+
`)
|
|
68
|
+
.all(sinceIso);
|
|
69
|
+
const out = new Map();
|
|
70
|
+
for (const r of rows) {
|
|
71
|
+
// tool format: mcp__<server>__<method>. Server name may contain hyphens but
|
|
72
|
+
// not '__' — splitting on '__' and taking element [1] is safe.
|
|
73
|
+
const parts = r.tool.split('__');
|
|
74
|
+
if (parts.length < 3)
|
|
75
|
+
continue;
|
|
76
|
+
const server = parts[1];
|
|
77
|
+
if (!server)
|
|
78
|
+
continue;
|
|
79
|
+
const tsMs = Date.parse(r.ts);
|
|
80
|
+
if (!Number.isFinite(tsMs))
|
|
81
|
+
continue;
|
|
82
|
+
const cur = out.get(server);
|
|
83
|
+
if (!cur) {
|
|
84
|
+
out.set(server, { count: 1, lastUsedMs: tsMs });
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
cur.count++;
|
|
88
|
+
if (tsMs > cur.lastUsedMs)
|
|
89
|
+
cur.lastUsedMs = tsMs;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Returns every non-Skill, non-MCP tool_call in the window paired with its
|
|
96
|
+
* input_json. Used by the gap detector to grep for "replaces" patterns.
|
|
97
|
+
* Limited to the tool names we currently emit patterns against, to avoid
|
|
98
|
+
* pulling 100K+ Read/Edit rows.
|
|
99
|
+
*/
|
|
100
|
+
export function loadCandidateToolCalls(db, lookbackDays, toolFilter) {
|
|
101
|
+
if (toolFilter.length === 0)
|
|
102
|
+
return [];
|
|
103
|
+
const sinceMs = Date.now() - lookbackDays * 24 * 60 * 60 * 1000;
|
|
104
|
+
const sinceIso = new Date(sinceMs).toISOString();
|
|
105
|
+
const placeholders = toolFilter.map(() => '?').join(',');
|
|
106
|
+
return db
|
|
107
|
+
.prepare(`
|
|
108
|
+
SELECT tc.tool, tc.input_json, m.ts
|
|
109
|
+
FROM tool_calls tc
|
|
110
|
+
JOIN messages m ON m.id = tc.message_id
|
|
111
|
+
WHERE tc.tool IN (${placeholders})
|
|
112
|
+
AND m.ts >= ?
|
|
113
|
+
`)
|
|
114
|
+
.all(...toolFilter, sinceIso);
|
|
115
|
+
}
|
|
116
|
+
// ─── State hydration ──────────────────────────────────────────────────────────
|
|
117
|
+
/**
|
|
118
|
+
* Annotates each SkillState with its usage stats from the tool_calls table.
|
|
119
|
+
*
|
|
120
|
+
* Plugin skills can fire under EITHER '<plugin>:<name>' OR bare '<name>' depending
|
|
121
|
+
* on how the user invoked them — verified in real data (e.g. `update-config`
|
|
122
|
+
* appears as bare even though it's plugin-bundled). Merge both keys so we don't
|
|
123
|
+
* surface false-positive zombies for skills that are actually being used.
|
|
124
|
+
*/
|
|
125
|
+
export function hydrateSkillUsage(skills, usage) {
|
|
126
|
+
return skills.map((s) => {
|
|
127
|
+
const primary = usage.get(s.id);
|
|
128
|
+
const bare = s.plugin ? usage.get(s.name) : undefined;
|
|
129
|
+
if (!primary && !bare)
|
|
130
|
+
return s;
|
|
131
|
+
const count = (primary?.count ?? 0) + (bare?.count ?? 0);
|
|
132
|
+
const lastMs = Math.max(primary?.lastUsedMs ?? 0, bare?.lastUsedMs ?? 0);
|
|
133
|
+
return { ...s, usageCount: count, lastUsedMs: lastMs || null };
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
export function hydrateMcpUsage(mcps, usage) {
|
|
137
|
+
return mcps.map((m) => {
|
|
138
|
+
const u = usage.get(m.id);
|
|
139
|
+
if (!u)
|
|
140
|
+
return m;
|
|
141
|
+
return { ...m, usageCount: u.count, lastUsedMs: u.lastUsedMs };
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// ─── Gap detection ────────────────────────────────────────────────────────────
|
|
145
|
+
/**
|
|
146
|
+
* Parses a "replaces" pattern of the form "tool:substring". Returns null on
|
|
147
|
+
* malformed entries (logged at the call site).
|
|
148
|
+
*/
|
|
149
|
+
function parseReplacePattern(pat) {
|
|
150
|
+
const idx = pat.indexOf(':');
|
|
151
|
+
if (idx < 0)
|
|
152
|
+
return null;
|
|
153
|
+
const tool = pat.slice(0, idx);
|
|
154
|
+
const needle = pat.slice(idx + 1);
|
|
155
|
+
if (!tool || !needle)
|
|
156
|
+
return null;
|
|
157
|
+
return { tool, needle };
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* For each common-kit item not already installed, build a GapItem. For MCP
|
|
161
|
+
* gaps, count tool_calls matching the `replaces` patterns over the lookback
|
|
162
|
+
* window — these are loosely the calls an MCP server would handle directly,
|
|
163
|
+
* eliminating the need for shelling out / fetching.
|
|
164
|
+
*
|
|
165
|
+
* Savings heuristic for MCP: we currently surface the match count as a
|
|
166
|
+
* "potential reduction" signal (rendered in the UI as "N calls would be
|
|
167
|
+
* replaced") but do NOT compute dollar savings — Bash/WebFetch cost lives in
|
|
168
|
+
* the assistant's output tokens around the call, which we don't attribute
|
|
169
|
+
* per-tool. So potentialSavingsCents stays 0 in V1 unless the kit grows entries
|
|
170
|
+
* with a model-aware estimate; matchingCallCount is the actionable number.
|
|
171
|
+
*/
|
|
172
|
+
export function detectGaps(kit, installedSkillIds, installedMcpIds, candidateCalls) {
|
|
173
|
+
const gaps = [];
|
|
174
|
+
// Skills — flat membership check; no savings heuristic in V1.
|
|
175
|
+
for (const s of kit.skills) {
|
|
176
|
+
if (installedSkillIds.has(s.id))
|
|
177
|
+
continue;
|
|
178
|
+
gaps.push({
|
|
179
|
+
kind: 'skill',
|
|
180
|
+
id: s.id,
|
|
181
|
+
purpose: s.purpose,
|
|
182
|
+
installCommand: s.install,
|
|
183
|
+
potentialSavingsCents: 0,
|
|
184
|
+
matchingCallCount: 0,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
// MCP — count `replaces` matches on candidate tool_calls.
|
|
188
|
+
for (const m of kit.mcpServers) {
|
|
189
|
+
if (installedMcpIds.has(m.id))
|
|
190
|
+
continue;
|
|
191
|
+
let matchCount = 0;
|
|
192
|
+
if (m.replaces && m.replaces.length > 0) {
|
|
193
|
+
const patterns = m.replaces
|
|
194
|
+
.map(parseReplacePattern)
|
|
195
|
+
.filter((p) => p !== null);
|
|
196
|
+
for (const call of candidateCalls) {
|
|
197
|
+
for (const p of patterns) {
|
|
198
|
+
if (call.tool !== p.tool)
|
|
199
|
+
continue;
|
|
200
|
+
const hay = call.input_json ?? '';
|
|
201
|
+
if (hay.includes(p.needle)) {
|
|
202
|
+
matchCount++;
|
|
203
|
+
break; // count each call at most once
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
gaps.push({
|
|
209
|
+
kind: 'mcp',
|
|
210
|
+
id: m.id,
|
|
211
|
+
purpose: m.purpose,
|
|
212
|
+
installCommand: m.install,
|
|
213
|
+
potentialSavingsCents: 0,
|
|
214
|
+
matchingCallCount: matchCount,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
// Rank: MCP gaps with matches first (descending), then unmatched, then skills.
|
|
218
|
+
gaps.sort((a, b) => {
|
|
219
|
+
if (b.matchingCallCount !== a.matchingCallCount)
|
|
220
|
+
return b.matchingCallCount - a.matchingCallCount;
|
|
221
|
+
if (a.kind !== b.kind)
|
|
222
|
+
return a.kind === 'mcp' ? -1 : 1;
|
|
223
|
+
return a.id.localeCompare(b.id);
|
|
224
|
+
});
|
|
225
|
+
return gaps;
|
|
226
|
+
}
|
|
227
|
+
/** Returns the union of tool names referenced by the kit's `replaces` patterns. */
|
|
228
|
+
export function collectReplacedTools(kit) {
|
|
229
|
+
const set = new Set();
|
|
230
|
+
for (const m of kit.mcpServers) {
|
|
231
|
+
for (const p of m.replaces ?? []) {
|
|
232
|
+
const parsed = parseReplacePattern(p);
|
|
233
|
+
if (parsed)
|
|
234
|
+
set.add(parsed.tool);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return Array.from(set);
|
|
238
|
+
}
|
|
239
|
+
// ─── Zombie detection ─────────────────────────────────────────────────────────
|
|
240
|
+
/**
|
|
241
|
+
* A skill or MCP server is a "zombie" when it's installed on the filesystem
|
|
242
|
+
* but has not been invoked in the lookback window. We treat usageCount=0 as
|
|
243
|
+
* the threshold (the spec mentions "below threshold like 2 over 30d for skills"
|
|
244
|
+
* — but for V1 we use the strict zero gate since the user has few-to-no skills
|
|
245
|
+
* installed, and a single intentional use is enough to "save" a skill from the
|
|
246
|
+
* list).
|
|
247
|
+
*/
|
|
248
|
+
export function detectZombies(skills, mcp) {
|
|
249
|
+
const out = [];
|
|
250
|
+
for (const s of skills) {
|
|
251
|
+
if (s.usageCount > 0)
|
|
252
|
+
continue;
|
|
253
|
+
out.push({
|
|
254
|
+
kind: 'skill',
|
|
255
|
+
id: s.id,
|
|
256
|
+
displayName: s.name,
|
|
257
|
+
platform: s.platform,
|
|
258
|
+
scope: s.scope,
|
|
259
|
+
projectPath: s.projectPath,
|
|
260
|
+
installedAtMs: s.installedAtMs,
|
|
261
|
+
lastUsedMs: s.lastUsedMs,
|
|
262
|
+
usageCount: s.usageCount,
|
|
263
|
+
removeCommand: removeCommandForSkill(s),
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
for (const m of mcp) {
|
|
267
|
+
if (m.usageCount > 0)
|
|
268
|
+
continue;
|
|
269
|
+
out.push({
|
|
270
|
+
kind: 'mcp',
|
|
271
|
+
id: m.id,
|
|
272
|
+
displayName: m.id,
|
|
273
|
+
platform: m.platform,
|
|
274
|
+
scope: m.scope,
|
|
275
|
+
projectPath: m.projectPath,
|
|
276
|
+
installedAtMs: m.installedAtMs,
|
|
277
|
+
lastUsedMs: m.lastUsedMs,
|
|
278
|
+
usageCount: m.usageCount,
|
|
279
|
+
removeCommand: removeCommandForMcp(m),
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// Oldest installs first — those are the most clearly forgotten.
|
|
283
|
+
out.sort((a, b) => a.installedAtMs - b.installedAtMs);
|
|
284
|
+
return out;
|
|
285
|
+
}
|
|
286
|
+
function removeCommandForSkill(s) {
|
|
287
|
+
if (s.plugin) {
|
|
288
|
+
// Plugin-installed skills can't be removed in isolation — uninstalling the
|
|
289
|
+
// plugin removes them all. Surface that affordance instead.
|
|
290
|
+
if (s.platform === 'claude-code')
|
|
291
|
+
return `claude plugin uninstall ${s.plugin}`;
|
|
292
|
+
if (s.platform === 'codex')
|
|
293
|
+
return `codex plugin uninstall ${s.plugin}`;
|
|
294
|
+
}
|
|
295
|
+
// Loose skills: just nuke the directory
|
|
296
|
+
// `dirname` gives us the skill folder above SKILL.md
|
|
297
|
+
const skillDir = s.sourcePath.replace(/\/SKILL\.md$/, '');
|
|
298
|
+
return `rm -rf "${skillDir}"`;
|
|
299
|
+
}
|
|
300
|
+
function removeCommandForMcp(m) {
|
|
301
|
+
if (m.platform === 'claude-code') {
|
|
302
|
+
return m.scope === 'project'
|
|
303
|
+
? `claude mcp remove ${m.id} --scope project`
|
|
304
|
+
: `claude mcp remove ${m.id}`;
|
|
305
|
+
}
|
|
306
|
+
if (m.platform === 'cursor') {
|
|
307
|
+
// Cursor edits mcp.json by hand or via Settings UI — there's no CLI.
|
|
308
|
+
return `Edit ${m.sourcePath} and remove the "${m.id}" entry`;
|
|
309
|
+
}
|
|
310
|
+
return `Remove "${m.id}" from ${m.sourcePath}`;
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detection.js","sourceRoot":"","sources":["../../../src/core/kit/detection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import type { KitData, KitPlatform } from '../schema/index.js';
|
|
3
|
+
export interface GetKitOptions {
|
|
4
|
+
lookbackDays?: number;
|
|
5
|
+
platform?: KitPlatform;
|
|
6
|
+
/** Override the common-kit.json path (tests). */
|
|
7
|
+
commonKitPath?: string;
|
|
8
|
+
/** Override project roots (tests). When omitted, derived from sessions table. */
|
|
9
|
+
projectRoots?: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function getKit(db: Database.Database, opts?: GetKitOptions): Promise<KitData>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/kit/index.ts"],"names":[],"mappings":"AAIA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AACrC,OAAO,KAAK,EACV,OAAO,EAIP,WAAW,EACZ,MAAM,oBAAoB,CAAA;AAuB3B,MAAM,WAAW,aAAa;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACxB;AAwED,wBAAsB,MAAM,CAC1B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,OAAO,CAAC,CA2DlB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { scanGlobalSkills, scanProjectSkills, scanGlobalMcp, scanProjectMcp, decodeClaudeProjectSlug, } from './scan.js';
|
|
6
|
+
import { detectGaps, detectZombies, hydrateMcpUsage, hydrateSkillUsage, loadCandidateToolCalls, loadMcpUsage, loadSkillUsage, collectReplacedTools, } from './detection.js';
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
const DEFAULT_LOOKBACK_DAYS = 30;
|
|
10
|
+
/** Loads data/common-kit.json. Searches up from this file because the runtime
|
|
11
|
+
* layout is dist/core/kit/index.js with data/ at the package root.
|
|
12
|
+
* Falls back to a minimal empty kit if the file is missing/malformed. */
|
|
13
|
+
async function loadCommonKit(overridePath) {
|
|
14
|
+
const empty = { version: 1, skills: [], mcpServers: [] };
|
|
15
|
+
const candidates = [];
|
|
16
|
+
if (overridePath)
|
|
17
|
+
candidates.push(overridePath);
|
|
18
|
+
candidates.push(join(__dirname, '../../../data/common-kit.json'), join(__dirname, '../../../../data/common-kit.json'));
|
|
19
|
+
for (const p of candidates) {
|
|
20
|
+
if (!existsSync(p))
|
|
21
|
+
continue;
|
|
22
|
+
try {
|
|
23
|
+
const text = await readFile(p, 'utf8');
|
|
24
|
+
return JSON.parse(text);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
console.error(`[vyasa] kit: failed to load common-kit.json at ${p}:`, err);
|
|
28
|
+
return empty;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return empty;
|
|
32
|
+
}
|
|
33
|
+
/** Distinct project paths derived from sessions. Claude rows store a slug
|
|
34
|
+
* (`-Users-abhinav-foo`); Codex/Cursor store absolute paths. Decode the
|
|
35
|
+
* Claude slug back to a path and dedupe. */
|
|
36
|
+
function deriveProjectRoots(db) {
|
|
37
|
+
const rows = db
|
|
38
|
+
.prepare('SELECT DISTINCT project, platform FROM sessions WHERE project IS NOT NULL')
|
|
39
|
+
.all();
|
|
40
|
+
const set = new Set();
|
|
41
|
+
for (const r of rows) {
|
|
42
|
+
if (!r.project)
|
|
43
|
+
continue;
|
|
44
|
+
if (r.platform === 'claude-code') {
|
|
45
|
+
// Claude slugs start with '-' for absolute paths; if it doesn't, treat
|
|
46
|
+
// as-is (project might be a literal name from a non-absolute cwd).
|
|
47
|
+
const decoded = decodeClaudeProjectSlug(r.project);
|
|
48
|
+
if (decoded.startsWith('/'))
|
|
49
|
+
set.add(decoded);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Codex + Cursor store absolute paths already
|
|
53
|
+
if (r.project.startsWith('/'))
|
|
54
|
+
set.add(r.project);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return Array.from(set);
|
|
58
|
+
}
|
|
59
|
+
/** Build a per-project inventory by grouping skills + MCP by their projectPath.
|
|
60
|
+
* Projects with no installs are omitted. */
|
|
61
|
+
function groupByProject(skills, mcp) {
|
|
62
|
+
const map = new Map();
|
|
63
|
+
for (const s of skills) {
|
|
64
|
+
if (s.scope !== 'project' || !s.projectPath)
|
|
65
|
+
continue;
|
|
66
|
+
const entry = map.get(s.projectPath) ?? { project: s.projectPath, skills: [], mcp: [] };
|
|
67
|
+
entry.skills.push(s);
|
|
68
|
+
map.set(s.projectPath, entry);
|
|
69
|
+
}
|
|
70
|
+
for (const m of mcp) {
|
|
71
|
+
if (m.scope !== 'project' || !m.projectPath)
|
|
72
|
+
continue;
|
|
73
|
+
const entry = map.get(m.projectPath) ?? { project: m.projectPath, skills: [], mcp: [] };
|
|
74
|
+
entry.mcp.push(m);
|
|
75
|
+
map.set(m.projectPath, entry);
|
|
76
|
+
}
|
|
77
|
+
return Array.from(map.values()).sort((a, b) => a.project.localeCompare(b.project));
|
|
78
|
+
}
|
|
79
|
+
export async function getKit(db, opts = {}) {
|
|
80
|
+
const lookbackDays = opts.lookbackDays ?? DEFAULT_LOOKBACK_DAYS;
|
|
81
|
+
const projectRoots = opts.projectRoots ?? deriveProjectRoots(db);
|
|
82
|
+
// Filesystem scan (parallel)
|
|
83
|
+
const [globalSkillsRaw, globalMcpRaw, projectSkillsRaw, projectMcpRaw] = await Promise.all([
|
|
84
|
+
scanGlobalSkills(),
|
|
85
|
+
scanGlobalMcp(),
|
|
86
|
+
scanProjectSkills(projectRoots),
|
|
87
|
+
scanProjectMcp(projectRoots),
|
|
88
|
+
]);
|
|
89
|
+
// Usage hydration
|
|
90
|
+
const skillUsage = loadSkillUsage(db, lookbackDays);
|
|
91
|
+
const mcpUsage = loadMcpUsage(db, lookbackDays);
|
|
92
|
+
let globalSkills = hydrateSkillUsage(globalSkillsRaw, skillUsage);
|
|
93
|
+
let globalMcp = hydrateMcpUsage(globalMcpRaw, mcpUsage);
|
|
94
|
+
let projectSkills = hydrateSkillUsage(projectSkillsRaw, skillUsage);
|
|
95
|
+
let projectMcp = hydrateMcpUsage(projectMcpRaw, mcpUsage);
|
|
96
|
+
// Platform filter (post-hydration so usage data is still complete for tests)
|
|
97
|
+
if (opts.platform) {
|
|
98
|
+
const p = opts.platform;
|
|
99
|
+
globalSkills = globalSkills.filter((s) => s.platform === p);
|
|
100
|
+
globalMcp = globalMcp.filter((m) => m.platform === p);
|
|
101
|
+
projectSkills = projectSkills.filter((s) => s.platform === p);
|
|
102
|
+
projectMcp = projectMcp.filter((m) => m.platform === p);
|
|
103
|
+
}
|
|
104
|
+
// Detection
|
|
105
|
+
const kit = await loadCommonKit(opts.commonKitPath);
|
|
106
|
+
const installedSkillIds = new Set();
|
|
107
|
+
for (const s of [...globalSkills, ...projectSkills])
|
|
108
|
+
installedSkillIds.add(s.id);
|
|
109
|
+
// Also accept bare-name match: a plugin-installed skill like 'superpowers:brainstorming'
|
|
110
|
+
// satisfies a common-kit entry whose id is 'brainstorming' (the user installed it
|
|
111
|
+
// via a plugin instead of as a loose ~/.claude/skills/<id>/ skill).
|
|
112
|
+
for (const s of [...globalSkills, ...projectSkills]) {
|
|
113
|
+
if (s.plugin)
|
|
114
|
+
installedSkillIds.add(s.name);
|
|
115
|
+
}
|
|
116
|
+
const installedMcpIds = new Set();
|
|
117
|
+
for (const m of [...globalMcp, ...projectMcp])
|
|
118
|
+
installedMcpIds.add(m.id);
|
|
119
|
+
const candidateTools = collectReplacedTools(kit);
|
|
120
|
+
const candidateCalls = loadCandidateToolCalls(db, lookbackDays, candidateTools);
|
|
121
|
+
const gaps = detectGaps(kit, installedSkillIds, installedMcpIds, candidateCalls);
|
|
122
|
+
const zombies = detectZombies([...globalSkills, ...projectSkills], [...globalMcp, ...projectMcp]);
|
|
123
|
+
return {
|
|
124
|
+
lookbackDays,
|
|
125
|
+
gaps,
|
|
126
|
+
zombies,
|
|
127
|
+
globalInstalled: { skills: globalSkills, mcp: globalMcp },
|
|
128
|
+
projectInstalled: groupByProject(projectSkills, projectMcp),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/kit/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { platform } from 'node:os';
|
|
2
|
+
import type { SkillState, McpState } from '../schema/index.js';
|
|
3
|
+
export declare function scanGlobalSkills(): Promise<SkillState[]>;
|
|
4
|
+
/**
|
|
5
|
+
* Scans likely project-scoped skill dirs under each given project root.
|
|
6
|
+
* `projectRoots` should be absolute paths that look like project working
|
|
7
|
+
* directories (decoded from session.project where possible).
|
|
8
|
+
*/
|
|
9
|
+
export declare function scanProjectSkills(projectRoots: string[]): Promise<SkillState[]>;
|
|
10
|
+
export declare function scanGlobalMcp(): Promise<McpState[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Returns MCP servers declared at project-scope for the given roots:
|
|
13
|
+
* • Claude: ~/.claude.json's projects[<root>].mcpServers
|
|
14
|
+
* • Cursor: <root>/.cursor/mcp.json
|
|
15
|
+
*/
|
|
16
|
+
export declare function scanProjectMcp(projectRoots: string[]): Promise<McpState[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Claude encodes the project working dir as a slug — `/Users/abhinav/foo` becomes
|
|
19
|
+
* `-Users-abhinav-foo`. The encoding is lossy: literal dashes inside path
|
|
20
|
+
* components (e.g. `claude-tool`) get merged with the separator dashes. We
|
|
21
|
+
* recover the true path by probing the filesystem — try the naive split first,
|
|
22
|
+
* then merge adjacent segments left-to-right until we find a directory that
|
|
23
|
+
* exists. Longest matching prefix wins. Falls back to the naive split (which
|
|
24
|
+
* won't `existsSync`, so callers harmlessly skip it) when no resolution is possible.
|
|
25
|
+
*/
|
|
26
|
+
export declare function decodeClaudeProjectSlug(slug: string): string;
|
|
27
|
+
export { platform as osPlatform };
|
|
28
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../src/core/kit/scan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAW,QAAQ,EAAE,MAAM,SAAS,CAAA;AAE3C,OAAO,KAAK,EAAe,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAkM3E,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAkD9D;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAgDrF;AA2BD,wBAAsB,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAoDzD;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAmDhF;AASD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5D;AAuCD,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,CAAA"}
|