@sporesec/arcana 2.4.0 → 3.0.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/dist/cli.d.ts +0 -1
- package/dist/cli.js +120 -9
- package/dist/command-registry.d.ts +10 -0
- package/dist/command-registry.js +65 -0
- package/dist/commands/audit.d.ts +0 -1
- package/dist/commands/audit.js +16 -6
- package/dist/commands/benchmark.d.ts +4 -0
- package/dist/commands/benchmark.js +178 -0
- package/dist/commands/clean.d.ts +0 -1
- package/dist/commands/clean.js +19 -8
- package/dist/commands/compact.d.ts +2 -1
- package/dist/commands/compact.js +74 -14
- package/dist/commands/completions.d.ts +3 -0
- package/dist/commands/completions.js +104 -0
- package/dist/commands/config.d.ts +0 -1
- package/dist/commands/config.js +15 -6
- package/dist/commands/create.d.ts +0 -1
- package/dist/commands/create.js +1 -1
- package/dist/commands/diff.d.ts +4 -0
- package/dist/commands/diff.js +166 -0
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/doctor.js +64 -23
- package/dist/commands/export-cmd.d.ts +4 -0
- package/dist/commands/export-cmd.js +66 -0
- package/dist/commands/import-cmd.d.ts +4 -0
- package/dist/commands/import-cmd.js +131 -0
- package/dist/commands/info.d.ts +0 -1
- package/dist/commands/info.js +29 -4
- package/dist/commands/init.d.ts +0 -1
- package/dist/commands/init.js +26 -33
- package/dist/commands/install.d.ts +1 -1
- package/dist/commands/install.js +118 -205
- package/dist/commands/list.d.ts +0 -1
- package/dist/commands/list.js +12 -4
- package/dist/commands/lock.d.ts +4 -0
- package/dist/commands/lock.js +171 -0
- package/dist/commands/optimize.d.ts +0 -1
- package/dist/commands/optimize.js +111 -20
- package/dist/commands/outdated.d.ts +4 -0
- package/dist/commands/outdated.js +159 -0
- package/dist/commands/profile.d.ts +3 -0
- package/dist/commands/profile.js +274 -0
- package/dist/commands/providers.d.ts +0 -1
- package/dist/commands/providers.js +1 -4
- package/dist/commands/recommend.d.ts +5 -0
- package/dist/commands/recommend.js +96 -0
- package/dist/commands/scan.d.ts +0 -1
- package/dist/commands/scan.js +13 -7
- package/dist/commands/search.d.ts +2 -1
- package/dist/commands/search.js +32 -9
- package/dist/commands/stats.d.ts +0 -1
- package/dist/commands/stats.js +24 -20
- package/dist/commands/team.d.ts +3 -0
- package/dist/commands/team.js +291 -0
- package/dist/commands/uninstall.d.ts +0 -1
- package/dist/commands/uninstall.js +18 -4
- package/dist/commands/update.d.ts +0 -1
- package/dist/commands/update.js +155 -155
- package/dist/commands/validate.d.ts +0 -1
- package/dist/commands/validate.js +14 -6
- package/dist/commands/verify.d.ts +4 -0
- package/dist/commands/verify.js +116 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +13 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/interactive/browse.d.ts +4 -0
- package/dist/interactive/browse.js +103 -0
- package/dist/interactive/categories.d.ts +4 -0
- package/dist/interactive/categories.js +87 -0
- package/dist/interactive/health.d.ts +1 -0
- package/dist/interactive/health.js +57 -0
- package/dist/interactive/helpers.d.ts +11 -0
- package/dist/interactive/helpers.js +66 -0
- package/dist/interactive/index.d.ts +1 -0
- package/dist/interactive/index.js +1 -0
- package/dist/interactive/manage.d.ts +2 -0
- package/dist/interactive/manage.js +187 -0
- package/dist/interactive/menu.d.ts +1 -0
- package/dist/interactive/menu.js +107 -0
- package/dist/interactive/search.d.ts +2 -0
- package/dist/interactive/search.js +66 -0
- package/dist/interactive/setup.d.ts +2 -0
- package/dist/interactive/setup.js +48 -0
- package/dist/interactive/skill-detail.d.ts +5 -0
- package/dist/interactive/skill-detail.js +126 -0
- package/dist/interactive.d.ts +0 -1
- package/dist/interactive.js +89 -66
- package/dist/providers/arcana.d.ts +0 -1
- package/dist/providers/arcana.js +0 -1
- package/dist/providers/base.d.ts +0 -1
- package/dist/providers/base.js +0 -1
- package/dist/providers/github.d.ts +0 -1
- package/dist/providers/github.js +8 -3
- package/dist/registry.d.ts +0 -1
- package/dist/registry.js +1 -4
- package/dist/types.d.ts +10 -1
- package/dist/types.js +0 -1
- package/dist/utils/atomic.d.ts +0 -1
- package/dist/utils/atomic.js +3 -2
- package/dist/utils/cache.d.ts +0 -1
- package/dist/utils/cache.js +3 -2
- package/dist/utils/config.d.ts +2 -1
- package/dist/utils/config.js +30 -5
- package/dist/utils/conflict-check.d.ts +8 -0
- package/dist/utils/conflict-check.js +72 -0
- package/dist/utils/errors.d.ts +0 -1
- package/dist/utils/errors.js +0 -1
- package/dist/utils/frontmatter.d.ts +0 -1
- package/dist/utils/frontmatter.js +37 -10
- package/dist/utils/fs.d.ts +0 -1
- package/dist/utils/fs.js +30 -11
- package/dist/utils/help.d.ts +0 -1
- package/dist/utils/help.js +15 -28
- package/dist/utils/history.d.ts +0 -1
- package/dist/utils/history.js +0 -1
- package/dist/utils/http.d.ts +0 -1
- package/dist/utils/http.js +14 -5
- package/dist/utils/install-core.d.ts +48 -0
- package/dist/utils/install-core.js +108 -0
- package/dist/utils/integrity.d.ts +17 -0
- package/dist/utils/integrity.js +84 -0
- package/dist/utils/parallel.d.ts +0 -1
- package/dist/utils/parallel.js +0 -1
- package/dist/utils/project-context.d.ts +19 -0
- package/dist/utils/project-context.js +283 -0
- package/dist/utils/scanner.d.ts +0 -1
- package/dist/utils/scanner.js +138 -10
- package/dist/utils/scoring.d.ts +10 -0
- package/dist/utils/scoring.js +84 -0
- package/dist/utils/ui.d.ts +0 -1
- package/dist/utils/ui.js +11 -4
- package/dist/utils/validate.d.ts +0 -1
- package/dist/utils/validate.js +4 -1
- package/package.json +74 -62
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/audit.d.ts.map +0 -1
- package/dist/commands/audit.js.map +0 -1
- package/dist/commands/audit.test.d.ts +0 -2
- package/dist/commands/audit.test.d.ts.map +0 -1
- package/dist/commands/audit.test.js +0 -217
- package/dist/commands/audit.test.js.map +0 -1
- package/dist/commands/clean.d.ts.map +0 -1
- package/dist/commands/clean.js.map +0 -1
- package/dist/commands/compact.d.ts.map +0 -1
- package/dist/commands/compact.js.map +0 -1
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/create.d.ts.map +0 -1
- package/dist/commands/create.js.map +0 -1
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/info.d.ts.map +0 -1
- package/dist/commands/info.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/install.d.ts.map +0 -1
- package/dist/commands/install.js.map +0 -1
- package/dist/commands/list.d.ts.map +0 -1
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/optimize.d.ts.map +0 -1
- package/dist/commands/optimize.js.map +0 -1
- package/dist/commands/providers.d.ts.map +0 -1
- package/dist/commands/providers.js.map +0 -1
- package/dist/commands/scan.d.ts.map +0 -1
- package/dist/commands/scan.js.map +0 -1
- package/dist/commands/search.d.ts.map +0 -1
- package/dist/commands/search.js.map +0 -1
- package/dist/commands/stats.d.ts.map +0 -1
- package/dist/commands/stats.js.map +0 -1
- package/dist/commands/uninstall.d.ts.map +0 -1
- package/dist/commands/uninstall.js.map +0 -1
- package/dist/commands/update.d.ts.map +0 -1
- package/dist/commands/update.js.map +0 -1
- package/dist/commands/validate.d.ts.map +0 -1
- package/dist/commands/validate.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/interactive.d.ts.map +0 -1
- package/dist/interactive.js.map +0 -1
- package/dist/providers/arcana.d.ts.map +0 -1
- package/dist/providers/arcana.js.map +0 -1
- package/dist/providers/base.d.ts.map +0 -1
- package/dist/providers/base.js.map +0 -1
- package/dist/providers/github.d.ts.map +0 -1
- package/dist/providers/github.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/atomic.d.ts.map +0 -1
- package/dist/utils/atomic.js.map +0 -1
- package/dist/utils/atomic.test.d.ts +0 -2
- package/dist/utils/atomic.test.d.ts.map +0 -1
- package/dist/utils/atomic.test.js +0 -31
- package/dist/utils/atomic.test.js.map +0 -1
- package/dist/utils/cache.d.ts.map +0 -1
- package/dist/utils/cache.js.map +0 -1
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/config.test.d.ts +0 -2
- package/dist/utils/config.test.d.ts.map +0 -1
- package/dist/utils/config.test.js +0 -38
- package/dist/utils/config.test.js.map +0 -1
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/frontmatter.d.ts.map +0 -1
- package/dist/utils/frontmatter.js.map +0 -1
- package/dist/utils/frontmatter.test.d.ts +0 -2
- package/dist/utils/frontmatter.test.d.ts.map +0 -1
- package/dist/utils/frontmatter.test.js +0 -152
- package/dist/utils/frontmatter.test.js.map +0 -1
- package/dist/utils/fs.d.ts.map +0 -1
- package/dist/utils/fs.js.map +0 -1
- package/dist/utils/fs.test.d.ts +0 -2
- package/dist/utils/fs.test.d.ts.map +0 -1
- package/dist/utils/fs.test.js +0 -145
- package/dist/utils/fs.test.js.map +0 -1
- package/dist/utils/help.d.ts.map +0 -1
- package/dist/utils/help.js.map +0 -1
- package/dist/utils/help.test.d.ts +0 -2
- package/dist/utils/help.test.d.ts.map +0 -1
- package/dist/utils/help.test.js +0 -66
- package/dist/utils/help.test.js.map +0 -1
- package/dist/utils/history.d.ts.map +0 -1
- package/dist/utils/history.js.map +0 -1
- package/dist/utils/http.d.ts.map +0 -1
- package/dist/utils/http.js.map +0 -1
- package/dist/utils/http.test.d.ts +0 -2
- package/dist/utils/http.test.d.ts.map +0 -1
- package/dist/utils/http.test.js +0 -55
- package/dist/utils/http.test.js.map +0 -1
- package/dist/utils/parallel.d.ts.map +0 -1
- package/dist/utils/parallel.js.map +0 -1
- package/dist/utils/scanner.d.ts.map +0 -1
- package/dist/utils/scanner.js.map +0 -1
- package/dist/utils/ui.d.ts.map +0 -1
- package/dist/utils/ui.js.map +0 -1
- package/dist/utils/ui.test.d.ts +0 -2
- package/dist/utils/ui.test.d.ts.map +0 -1
- package/dist/utils/ui.test.js +0 -31
- package/dist/utils/ui.test.js.map +0 -1
- package/dist/utils/validate.d.ts.map +0 -1
- package/dist/utils/validate.js.map +0 -1
package/dist/commands/compact.js
CHANGED
|
@@ -3,6 +3,7 @@ import { join } from "node:path";
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { ui, banner } from "../utils/ui.js";
|
|
5
5
|
import { getDirSize } from "../utils/fs.js";
|
|
6
|
+
import { PRUNE_DEFAULT_DAYS, PRUNE_SIZE_THRESHOLD_BYTES, PRUNE_KEEP_NEWEST } from "../constants.js";
|
|
6
7
|
function analyzeProject(projDir, projName) {
|
|
7
8
|
const now = Date.now();
|
|
8
9
|
const mainFiles = [];
|
|
@@ -40,12 +41,11 @@ function analyzeProject(projDir, projName) {
|
|
|
40
41
|
continue;
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
const totalBytes = mainFiles.reduce((s, f) => s + f.sizeBytes, 0)
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
const totalBytes = mainFiles.reduce((s, f) => s + f.sizeBytes, 0) +
|
|
45
|
+
agentFiles.reduce((s, f) => s + f.sizeBytes, 0) +
|
|
46
|
+
sessionDirs.reduce((s, d) => s + d.sizeBytes, 0);
|
|
46
47
|
// Reclaimable: all agent files + all session dirs
|
|
47
|
-
const reclaimableBytes = agentFiles.reduce((s, f) => s + f.sizeBytes, 0)
|
|
48
|
-
+ sessionDirs.reduce((s, d) => s + d.sizeBytes, 0);
|
|
48
|
+
const reclaimableBytes = agentFiles.reduce((s, f) => s + f.sizeBytes, 0) + sessionDirs.reduce((s, d) => s + d.sizeBytes, 0);
|
|
49
49
|
return { name: projName, mainFiles, agentFiles, sessionDirs, totalBytes, reclaimableBytes };
|
|
50
50
|
}
|
|
51
51
|
function formatBytes(bytes) {
|
|
@@ -57,6 +57,39 @@ function formatBytes(bytes) {
|
|
|
57
57
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
58
58
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Prune oversized main session files.
|
|
62
|
+
* Targets files older than pruneDays AND larger than 10 MB.
|
|
63
|
+
* Always keeps the 3 newest sessions per project regardless.
|
|
64
|
+
*/
|
|
65
|
+
function pruneMainSessions(analyses, projectsDir, pruneDays, dryRun, json) {
|
|
66
|
+
const pruned = [];
|
|
67
|
+
let reclaimedBytes = 0;
|
|
68
|
+
for (const a of analyses) {
|
|
69
|
+
// Sort main files by age (newest first) to protect the 3 newest
|
|
70
|
+
const sorted = [...a.mainFiles].sort((x, y) => x.daysOld - y.daysOld);
|
|
71
|
+
const candidates = sorted.slice(PRUNE_KEEP_NEWEST); // Skip the 3 newest
|
|
72
|
+
for (const f of candidates) {
|
|
73
|
+
if (f.daysOld > pruneDays && f.sizeBytes > PRUNE_SIZE_THRESHOLD_BYTES) {
|
|
74
|
+
const sizeMB = (f.sizeBytes / (1024 * 1024)).toFixed(1);
|
|
75
|
+
if (!json) {
|
|
76
|
+
console.log(` ${ui.warn("Prune:")} ${f.name} ${ui.dim(`(${sizeMB} MB, ${f.daysOld}d old)`)}`);
|
|
77
|
+
}
|
|
78
|
+
if (!dryRun) {
|
|
79
|
+
try {
|
|
80
|
+
rmSync(join(projectsDir, a.name, f.name), { force: true });
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
/* skip */
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
pruned.push({ project: a.name, file: f.name, sizeMB, daysOld: f.daysOld });
|
|
87
|
+
reclaimedBytes += f.sizeBytes;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return { pruned, reclaimedBytes };
|
|
92
|
+
}
|
|
60
93
|
export async function compactCommand(opts) {
|
|
61
94
|
if (!opts.json)
|
|
62
95
|
banner();
|
|
@@ -89,7 +122,7 @@ export async function compactCommand(opts) {
|
|
|
89
122
|
analyses.sort((a, b) => b.totalBytes - a.totalBytes);
|
|
90
123
|
if (opts.json) {
|
|
91
124
|
const jsonResult = {
|
|
92
|
-
projects: analyses.map(a => ({
|
|
125
|
+
projects: analyses.map((a) => ({
|
|
93
126
|
name: a.name,
|
|
94
127
|
totalBytes: a.totalBytes,
|
|
95
128
|
reclaimableBytes: a.reclaimableBytes,
|
|
@@ -99,7 +132,6 @@ export async function compactCommand(opts) {
|
|
|
99
132
|
})),
|
|
100
133
|
totalReclaimed: dryRun ? 0 : analyses.reduce((s, a) => s + a.reclaimableBytes, 0),
|
|
101
134
|
};
|
|
102
|
-
console.log(JSON.stringify(jsonResult, null, 2));
|
|
103
135
|
if (!dryRun) {
|
|
104
136
|
for (const a of analyses) {
|
|
105
137
|
const projDir = join(projectsDir, a.name);
|
|
@@ -107,22 +139,36 @@ export async function compactCommand(opts) {
|
|
|
107
139
|
try {
|
|
108
140
|
rmSync(join(projDir, f.name), { force: true });
|
|
109
141
|
}
|
|
110
|
-
catch {
|
|
142
|
+
catch {
|
|
143
|
+
/* skip */
|
|
144
|
+
}
|
|
111
145
|
}
|
|
112
146
|
for (const d of a.sessionDirs) {
|
|
113
147
|
try {
|
|
114
148
|
rmSync(join(projDir, d.name), { recursive: true, force: true });
|
|
115
149
|
}
|
|
116
|
-
catch {
|
|
150
|
+
catch {
|
|
151
|
+
/* skip */
|
|
152
|
+
}
|
|
117
153
|
}
|
|
118
154
|
}
|
|
119
155
|
}
|
|
156
|
+
if (opts.prune) {
|
|
157
|
+
const pruneDays = opts.pruneDays ?? PRUNE_DEFAULT_DAYS;
|
|
158
|
+
const pruneResult = pruneMainSessions(analyses, projectsDir, pruneDays, dryRun, true);
|
|
159
|
+
jsonResult.pruned = pruneResult.pruned;
|
|
160
|
+
jsonResult.prunedBytes = pruneResult.reclaimedBytes;
|
|
161
|
+
if (!dryRun) {
|
|
162
|
+
jsonResult.totalReclaimed = jsonResult.totalReclaimed + pruneResult.reclaimedBytes;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
console.log(JSON.stringify(jsonResult, null, 2));
|
|
120
166
|
return;
|
|
121
167
|
}
|
|
122
168
|
if (!opts.json)
|
|
123
169
|
console.log(ui.bold(" Session Compaction Report\n"));
|
|
124
170
|
let totalReclaimed = 0;
|
|
125
|
-
const hasWork = analyses.some(a => a.reclaimableBytes > 0);
|
|
171
|
+
const hasWork = analyses.some((a) => a.reclaimableBytes > 0);
|
|
126
172
|
for (const a of analyses) {
|
|
127
173
|
if (a.totalBytes < 1024)
|
|
128
174
|
continue; // Skip tiny projects
|
|
@@ -141,7 +187,9 @@ export async function compactCommand(opts) {
|
|
|
141
187
|
try {
|
|
142
188
|
rmSync(join(projDir, f.name), { force: true });
|
|
143
189
|
}
|
|
144
|
-
catch {
|
|
190
|
+
catch {
|
|
191
|
+
/* skip */
|
|
192
|
+
}
|
|
145
193
|
}
|
|
146
194
|
}
|
|
147
195
|
totalReclaimed += agentSize;
|
|
@@ -157,7 +205,9 @@ export async function compactCommand(opts) {
|
|
|
157
205
|
try {
|
|
158
206
|
rmSync(join(projDir, d.name), { recursive: true, force: true });
|
|
159
207
|
}
|
|
160
|
-
catch {
|
|
208
|
+
catch {
|
|
209
|
+
/* skip */
|
|
210
|
+
}
|
|
161
211
|
}
|
|
162
212
|
}
|
|
163
213
|
totalReclaimed += dirSize;
|
|
@@ -165,8 +215,19 @@ export async function compactCommand(opts) {
|
|
|
165
215
|
}
|
|
166
216
|
console.log();
|
|
167
217
|
}
|
|
218
|
+
// Prune oversized main sessions if requested
|
|
219
|
+
if (opts.prune) {
|
|
220
|
+
const pruneDays = opts.pruneDays ?? PRUNE_DEFAULT_DAYS;
|
|
221
|
+
console.log(ui.bold(` Pruning main sessions (>${pruneDays}d old AND >10 MB, keeping 3 newest per project)\n`));
|
|
222
|
+
const pruneResult = pruneMainSessions(analyses, projectsDir, pruneDays, dryRun, false);
|
|
223
|
+
totalReclaimed += pruneResult.reclaimedBytes;
|
|
224
|
+
if (pruneResult.pruned.length === 0) {
|
|
225
|
+
console.log(ui.dim(" No oversized sessions to prune."));
|
|
226
|
+
}
|
|
227
|
+
console.log();
|
|
228
|
+
}
|
|
168
229
|
// Summary
|
|
169
|
-
if (!hasWork) {
|
|
230
|
+
if (!hasWork && !opts.prune) {
|
|
170
231
|
console.log(ui.success(" Already compact. No agent logs to remove."));
|
|
171
232
|
}
|
|
172
233
|
else {
|
|
@@ -176,4 +237,3 @@ export async function compactCommand(opts) {
|
|
|
176
237
|
}
|
|
177
238
|
console.log();
|
|
178
239
|
}
|
|
179
|
-
//# sourceMappingURL=compact.js.map
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const BASH_COMPLETIONS = `# arcana bash completion
|
|
2
|
+
_arcana_completions() {
|
|
3
|
+
local cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
4
|
+
local commands="list install info search providers create validate update uninstall init doctor clean compact stats config audit scan optimize verify lock profile benchmark diff outdated team export import completions"
|
|
5
|
+
|
|
6
|
+
if [ "\${COMP_CWORD}" -eq 1 ]; then
|
|
7
|
+
COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
|
|
8
|
+
fi
|
|
9
|
+
}
|
|
10
|
+
complete -F _arcana_completions arcana
|
|
11
|
+
`;
|
|
12
|
+
const ZSH_COMPLETIONS = `#compdef arcana
|
|
13
|
+
_arcana() {
|
|
14
|
+
local -a commands
|
|
15
|
+
commands=(
|
|
16
|
+
'list:List available skills'
|
|
17
|
+
'install:Install one or more skills'
|
|
18
|
+
'info:Show skill details'
|
|
19
|
+
'search:Search for skills'
|
|
20
|
+
'providers:Manage skill providers'
|
|
21
|
+
'create:Create a new skill'
|
|
22
|
+
'validate:Validate skill structure'
|
|
23
|
+
'update:Update installed skills'
|
|
24
|
+
'uninstall:Uninstall skills'
|
|
25
|
+
'init:Initialize arcana in project'
|
|
26
|
+
'doctor:Check environment'
|
|
27
|
+
'clean:Remove orphaned data'
|
|
28
|
+
'compact:Remove agent logs'
|
|
29
|
+
'stats:Show session analytics'
|
|
30
|
+
'config:View or modify config'
|
|
31
|
+
'audit:Audit skill quality'
|
|
32
|
+
'scan:Scan for security threats'
|
|
33
|
+
'optimize:Suggest improvements'
|
|
34
|
+
'verify:Verify skill integrity'
|
|
35
|
+
'lock:Manage lockfile'
|
|
36
|
+
'profile:Manage skill profiles'
|
|
37
|
+
'benchmark:Measure token cost'
|
|
38
|
+
'diff:Show skill changes'
|
|
39
|
+
'outdated:List outdated skills'
|
|
40
|
+
'team:Team skill management'
|
|
41
|
+
'export:Export skill manifest'
|
|
42
|
+
'import:Import skills'
|
|
43
|
+
'completions:Generate shell completions'
|
|
44
|
+
)
|
|
45
|
+
_describe 'command' commands
|
|
46
|
+
}
|
|
47
|
+
_arcana
|
|
48
|
+
`;
|
|
49
|
+
const FISH_COMPLETIONS = `# arcana fish completion
|
|
50
|
+
set -l commands list install info search providers create validate update uninstall init doctor clean compact stats config audit scan optimize verify lock profile benchmark diff outdated team export import completions
|
|
51
|
+
complete -c arcana -f
|
|
52
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a list -d "List available skills"
|
|
53
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a install -d "Install skills"
|
|
54
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a info -d "Show skill details"
|
|
55
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a search -d "Search for skills"
|
|
56
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a providers -d "Manage providers"
|
|
57
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a create -d "Create a skill"
|
|
58
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a validate -d "Validate skills"
|
|
59
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a update -d "Update skills"
|
|
60
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a uninstall -d "Uninstall skills"
|
|
61
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a init -d "Initialize arcana"
|
|
62
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a doctor -d "Check environment"
|
|
63
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a clean -d "Remove orphaned data"
|
|
64
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a compact -d "Remove agent logs"
|
|
65
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a stats -d "Session analytics"
|
|
66
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a config -d "View/modify config"
|
|
67
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a audit -d "Audit skill quality"
|
|
68
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a scan -d "Security scan"
|
|
69
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a optimize -d "Suggest improvements"
|
|
70
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a verify -d "Verify integrity"
|
|
71
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a lock -d "Manage lockfile"
|
|
72
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a profile -d "Skill profiles"
|
|
73
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a benchmark -d "Measure token cost"
|
|
74
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a diff -d "Show skill changes"
|
|
75
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a outdated -d "List outdated skills"
|
|
76
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a team -d "Team management"
|
|
77
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a export -d "Export manifest"
|
|
78
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a import -d "Import skills"
|
|
79
|
+
complete -c arcana -n "not __fish_seen_subcommand_from $commands" -a completions -d "Shell completions"
|
|
80
|
+
`;
|
|
81
|
+
const SHELLS = {
|
|
82
|
+
bash: BASH_COMPLETIONS,
|
|
83
|
+
zsh: ZSH_COMPLETIONS,
|
|
84
|
+
fish: FISH_COMPLETIONS,
|
|
85
|
+
};
|
|
86
|
+
export function completionsCommand(shell, opts) {
|
|
87
|
+
const supported = Object.keys(SHELLS);
|
|
88
|
+
if (!supported.includes(shell)) {
|
|
89
|
+
if (opts.json) {
|
|
90
|
+
console.log(JSON.stringify({ error: `Unsupported shell: ${shell}`, supported }));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.error(`Unsupported shell: ${shell}`);
|
|
94
|
+
console.error(`Supported: ${supported.join(", ")}`);
|
|
95
|
+
}
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
if (opts.json) {
|
|
99
|
+
console.log(JSON.stringify({ shell, script: SHELLS[shell] }));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.log(SHELLS[shell]);
|
|
103
|
+
}
|
|
104
|
+
}
|
package/dist/commands/config.js
CHANGED
|
@@ -20,9 +20,15 @@ export async function configCommand(action, value, opts) {
|
|
|
20
20
|
const envInstallDir = process.env.ARCANA_INSTALL_DIR;
|
|
21
21
|
const envProvider = process.env.ARCANA_DEFAULT_PROVIDER;
|
|
22
22
|
const rows = [
|
|
23
|
-
[
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
[
|
|
24
|
+
ui.dim("defaultProvider"),
|
|
25
|
+
config.defaultProvider + (envProvider ? ` ${ui.warn("(overridden by ARCANA_DEFAULT_PROVIDER)")}` : ""),
|
|
26
|
+
],
|
|
27
|
+
[
|
|
28
|
+
ui.dim("installDir"),
|
|
29
|
+
config.installDir + (envInstallDir ? ` ${ui.warn("(overridden by ARCANA_INSTALL_DIR)")}` : ""),
|
|
30
|
+
],
|
|
31
|
+
[ui.dim("providers"), config.providers.map((p) => p.name).join(", ")],
|
|
26
32
|
];
|
|
27
33
|
table(rows);
|
|
28
34
|
console.log();
|
|
@@ -58,7 +64,11 @@ export async function configCommand(action, value, opts) {
|
|
|
58
64
|
}
|
|
59
65
|
catch (err) {
|
|
60
66
|
if (opts?.json) {
|
|
61
|
-
console.log(JSON.stringify({
|
|
67
|
+
console.log(JSON.stringify({
|
|
68
|
+
action: "reset",
|
|
69
|
+
success: false,
|
|
70
|
+
error: err instanceof Error ? err.message : "Failed to remove config",
|
|
71
|
+
}));
|
|
62
72
|
}
|
|
63
73
|
else {
|
|
64
74
|
console.log(ui.error(` Failed to reset config: ${err instanceof Error ? err.message : "unknown error"}`));
|
|
@@ -115,7 +125,7 @@ export async function configCommand(action, value, opts) {
|
|
|
115
125
|
}
|
|
116
126
|
}
|
|
117
127
|
if (key === "defaultProvider") {
|
|
118
|
-
const providerNames = config.providers.map(p => p.name);
|
|
128
|
+
const providerNames = config.providers.map((p) => p.name);
|
|
119
129
|
if (!providerNames.includes(value)) {
|
|
120
130
|
console.log(ui.error(` Provider '${value}' not configured. Add it first with: arcana providers --add owner/repo`));
|
|
121
131
|
console.log();
|
|
@@ -132,4 +142,3 @@ export async function configCommand(action, value, opts) {
|
|
|
132
142
|
console.log();
|
|
133
143
|
}
|
|
134
144
|
}
|
|
135
|
-
//# sourceMappingURL=config.js.map
|
package/dist/commands/create.js
CHANGED
|
@@ -65,6 +65,7 @@ export async function createCommand(name) {
|
|
|
65
65
|
return "Description is required";
|
|
66
66
|
if (val.length < 10)
|
|
67
67
|
return "Too short (minimum 10 chars)";
|
|
68
|
+
return undefined;
|
|
68
69
|
},
|
|
69
70
|
});
|
|
70
71
|
if (p.isCancel(description)) {
|
|
@@ -97,4 +98,3 @@ export async function createCommand(name) {
|
|
|
97
98
|
p.log.info("Edit SKILL.md to add your skill instructions.");
|
|
98
99
|
p.outro(`Next: ${chalk.cyan("arcana validate " + name)}`);
|
|
99
100
|
}
|
|
100
|
-
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, lstatSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { getInstallDir, readSkillMeta } from "../utils/fs.js";
|
|
4
|
+
import { getProvider } from "../registry.js";
|
|
5
|
+
import { loadConfig } from "../utils/config.js";
|
|
6
|
+
import { validateSlug } from "../utils/validate.js";
|
|
7
|
+
function readDirRecursive(dir) {
|
|
8
|
+
const results = [];
|
|
9
|
+
const queue = [{ fullDir: dir, relPrefix: "" }];
|
|
10
|
+
while (queue.length > 0) {
|
|
11
|
+
const { fullDir, relPrefix } = queue.pop();
|
|
12
|
+
let entries;
|
|
13
|
+
try {
|
|
14
|
+
entries = readdirSync(fullDir);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
const fullPath = join(fullDir, entry);
|
|
21
|
+
try {
|
|
22
|
+
const stat = lstatSync(fullPath);
|
|
23
|
+
if (stat.isSymbolicLink())
|
|
24
|
+
continue;
|
|
25
|
+
const relPath = relPrefix ? `${relPrefix}/${entry}` : entry;
|
|
26
|
+
if (stat.isDirectory()) {
|
|
27
|
+
queue.push({ fullDir: fullPath, relPrefix: relPath });
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
results.push({
|
|
31
|
+
path: relPath,
|
|
32
|
+
content: readFileSync(fullPath, "utf-8"),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// skip unreadable entries
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return results;
|
|
42
|
+
}
|
|
43
|
+
function computeLineDiff(localContent, remoteContent) {
|
|
44
|
+
const localLines = localContent.split("\n");
|
|
45
|
+
const remoteLines = remoteContent.split("\n");
|
|
46
|
+
const localSet = new Set(localLines);
|
|
47
|
+
const remoteSet = new Set(remoteLines);
|
|
48
|
+
let linesAdded = 0;
|
|
49
|
+
let linesRemoved = 0;
|
|
50
|
+
for (const line of remoteLines) {
|
|
51
|
+
if (!localSet.has(line)) {
|
|
52
|
+
linesAdded++;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
for (const line of localLines) {
|
|
56
|
+
if (!remoteSet.has(line)) {
|
|
57
|
+
linesRemoved++;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { linesAdded, linesRemoved };
|
|
61
|
+
}
|
|
62
|
+
export async function diffCommand(skill, opts) {
|
|
63
|
+
try {
|
|
64
|
+
validateSlug(skill, "skill name");
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.error(err instanceof Error ? err.message : "Invalid skill name");
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
const installDir = getInstallDir();
|
|
71
|
+
const skillDir = join(installDir, skill);
|
|
72
|
+
if (!existsSync(skillDir)) {
|
|
73
|
+
console.error(`Skill "${skill}" is not installed.`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
const providerName = opts.provider ?? loadConfig().defaultProvider;
|
|
77
|
+
const provider = getProvider(providerName);
|
|
78
|
+
let remoteFiles;
|
|
79
|
+
try {
|
|
80
|
+
remoteFiles = await provider.fetch(skill);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
console.error(`Failed to fetch remote skill "${skill}": ${err instanceof Error ? err.message : "unknown error"}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
const localFiles = readDirRecursive(skillDir);
|
|
87
|
+
const meta = readSkillMeta(skill);
|
|
88
|
+
const localVersion = meta?.version ?? "0.0.0";
|
|
89
|
+
let remoteVersion = "0.0.0";
|
|
90
|
+
try {
|
|
91
|
+
const remoteInfo = await provider.info(skill);
|
|
92
|
+
if (remoteInfo) {
|
|
93
|
+
remoteVersion = remoteInfo.version;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// keep default
|
|
98
|
+
}
|
|
99
|
+
const localMap = new Map();
|
|
100
|
+
for (const file of localFiles) {
|
|
101
|
+
localMap.set(file.path, file.content);
|
|
102
|
+
}
|
|
103
|
+
const remoteMap = new Map();
|
|
104
|
+
for (const file of remoteFiles) {
|
|
105
|
+
remoteMap.set(file.path, file.content);
|
|
106
|
+
}
|
|
107
|
+
const added = [];
|
|
108
|
+
const removed = [];
|
|
109
|
+
const modified = [];
|
|
110
|
+
for (const [path] of remoteMap) {
|
|
111
|
+
if (!localMap.has(path)) {
|
|
112
|
+
added.push(path);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
for (const [path] of localMap) {
|
|
116
|
+
if (!remoteMap.has(path)) {
|
|
117
|
+
removed.push(path);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const [path, remoteContent] of remoteMap) {
|
|
121
|
+
const localContent = localMap.get(path);
|
|
122
|
+
if (localContent !== undefined && localContent !== remoteContent) {
|
|
123
|
+
const { linesAdded, linesRemoved } = computeLineDiff(localContent, remoteContent);
|
|
124
|
+
modified.push({ path, linesAdded, linesRemoved });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const result = {
|
|
128
|
+
skill,
|
|
129
|
+
localVersion,
|
|
130
|
+
remoteVersion,
|
|
131
|
+
added,
|
|
132
|
+
removed,
|
|
133
|
+
modified,
|
|
134
|
+
};
|
|
135
|
+
if (opts.json) {
|
|
136
|
+
console.log(JSON.stringify(result, null, 2));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// Console output
|
|
140
|
+
console.log(`Diff: ${skill}`);
|
|
141
|
+
console.log(` Local version: ${localVersion}`);
|
|
142
|
+
console.log(` Remote version: ${remoteVersion}`);
|
|
143
|
+
console.log();
|
|
144
|
+
if (added.length === 0 && removed.length === 0 && modified.length === 0) {
|
|
145
|
+
console.log(" No differences found.");
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (added.length > 0) {
|
|
149
|
+
console.log(` Added (${added.length}):`);
|
|
150
|
+
for (const path of added) {
|
|
151
|
+
console.log(` + ${path}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (removed.length > 0) {
|
|
155
|
+
console.log(` Removed (${removed.length}):`);
|
|
156
|
+
for (const path of removed) {
|
|
157
|
+
console.log(` - ${path}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (modified.length > 0) {
|
|
161
|
+
console.log(` Modified (${modified.length}):`);
|
|
162
|
+
for (const entry of modified) {
|
|
163
|
+
console.log(` ~ ${entry.path} (+${entry.linesAdded} / -${entry.linesRemoved})`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|