@danieldeusing/seedr 0.1.129 → 0.1.130
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.js +166 -62
- package/dist/index.d.ts +7 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -148,7 +148,7 @@ function isTelemetryDisabled(env = process.env) {
|
|
|
148
148
|
return env[TELEMETRY_OPT_OUT_VARIABLE] !== void 0;
|
|
149
149
|
}
|
|
150
150
|
function cliVersion() {
|
|
151
|
-
return true ? "0.1.
|
|
151
|
+
return true ? "0.1.130" : "dev";
|
|
152
152
|
}
|
|
153
153
|
async function sendEvent(event) {
|
|
154
154
|
try {
|
|
@@ -168,6 +168,36 @@ function trackInstalls(slug, type, results, scope) {
|
|
|
168
168
|
return Promise.all(sends).then(() => void 0);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
// src/utils/ledger.ts
|
|
172
|
+
import { homedir } from "os";
|
|
173
|
+
import { join } from "path";
|
|
174
|
+
var LEDGER_PATH = join(homedir(), ".seedr", "installed.json");
|
|
175
|
+
function ledgerKey(type, slug) {
|
|
176
|
+
return `${type}:${slug}`;
|
|
177
|
+
}
|
|
178
|
+
async function readLedger() {
|
|
179
|
+
const ledger = await readJson(LEDGER_PATH);
|
|
180
|
+
return { version: 1, items: ledger.items ?? {} };
|
|
181
|
+
}
|
|
182
|
+
async function recordInstall(entry) {
|
|
183
|
+
const ledger = await readLedger();
|
|
184
|
+
const key = ledgerKey(entry.type, entry.slug);
|
|
185
|
+
const previous = ledger.items[key];
|
|
186
|
+
const agents = previous && previous.version === entry.version ? [.../* @__PURE__ */ new Set([...previous.agents, ...entry.agents])].sort() : [...entry.agents].sort();
|
|
187
|
+
ledger.items[key] = { ...entry, agents };
|
|
188
|
+
await writeJson(LEDGER_PATH, ledger);
|
|
189
|
+
}
|
|
190
|
+
async function recordRemoval(type, slug, agents) {
|
|
191
|
+
const ledger = await readLedger();
|
|
192
|
+
const key = ledgerKey(type, slug);
|
|
193
|
+
const entry = ledger.items[key];
|
|
194
|
+
if (!entry) return;
|
|
195
|
+
const left = entry.agents.filter((agent) => !agents.includes(agent));
|
|
196
|
+
if (left.length === 0) delete ledger.items[key];
|
|
197
|
+
else ledger.items[key] = { ...entry, agents: left };
|
|
198
|
+
await writeJson(LEDGER_PATH, ledger);
|
|
199
|
+
}
|
|
200
|
+
|
|
171
201
|
// src/config/compatibility.ts
|
|
172
202
|
function filterCompatibleAgents(type, agents) {
|
|
173
203
|
const compatible = AGENT_COMPATIBILITY[type];
|
|
@@ -185,8 +215,8 @@ function describeIncompatibility(type, agent) {
|
|
|
185
215
|
}
|
|
186
216
|
|
|
187
217
|
// src/handlers/agent.ts
|
|
188
|
-
import { join, relative } from "path";
|
|
189
|
-
import { homedir } from "os";
|
|
218
|
+
import { join as join2, relative } from "path";
|
|
219
|
+
import { homedir as homedir2 } from "os";
|
|
190
220
|
import { lstat, readdir, unlink } from "fs/promises";
|
|
191
221
|
import chalk2 from "chalk";
|
|
192
222
|
import ora from "ora";
|
|
@@ -197,7 +227,7 @@ function subagentFileName(agent, slug) {
|
|
|
197
227
|
async function resolveAgentFilePath(agent, slug, scope, cwd) {
|
|
198
228
|
const destDir = getContentPath(agent, "agent", scope, cwd);
|
|
199
229
|
if (!destDir) return null;
|
|
200
|
-
const scopeRoot = scope === "user" ?
|
|
230
|
+
const scopeRoot = scope === "user" ? homedir2() : cwd;
|
|
201
231
|
return resolveContained(scopeRoot, relative(scopeRoot, destDir), subagentFileName(agent, slug));
|
|
202
232
|
}
|
|
203
233
|
async function installAgentForCodingAgent(item, agent, scope, method, force, cwd) {
|
|
@@ -212,7 +242,7 @@ async function installAgentForCodingAgent(item, agent, scope, method, force, cwd
|
|
|
212
242
|
}
|
|
213
243
|
await assertOverwritable(destPath, force);
|
|
214
244
|
const sourcePath = getItemSourcePath(item);
|
|
215
|
-
const sourceFile = sourcePath ?
|
|
245
|
+
const sourceFile = sourcePath ? join2(sourcePath, mainFileName("agent")) : null;
|
|
216
246
|
if (method === "symlink" && sourceFile && await exists(sourceFile)) {
|
|
217
247
|
await installFile(sourceFile, destPath, "symlink");
|
|
218
248
|
} else {
|
|
@@ -273,12 +303,12 @@ async function planAgent(item, agents, scope, method, cwd) {
|
|
|
273
303
|
const destPath = await resolveAgentFilePath(agent, item.slug, scope, cwd);
|
|
274
304
|
if (!destPath) throw new Error(`${CODING_AGENTS[agent].name} does not support agents`);
|
|
275
305
|
const sourcePath = getItemSourcePath(item);
|
|
276
|
-
const linked = method === "symlink" && sourcePath !== null && await exists(
|
|
306
|
+
const linked = method === "symlink" && sourcePath !== null && await exists(join2(sourcePath, mainFileName("agent")));
|
|
277
307
|
changes.push({
|
|
278
308
|
agent,
|
|
279
309
|
kind: await exists(destPath) ? "modify" : "create",
|
|
280
310
|
path: destPath,
|
|
281
|
-
detail: linked ? `symlink \u2192 ${
|
|
311
|
+
detail: linked ? `symlink \u2192 ${join2(sourcePath, mainFileName("agent"))}` : "agent definition file"
|
|
282
312
|
});
|
|
283
313
|
}
|
|
284
314
|
return changes;
|
|
@@ -298,8 +328,8 @@ var agentHandler = {
|
|
|
298
328
|
};
|
|
299
329
|
|
|
300
330
|
// src/handlers/command.ts
|
|
301
|
-
import { join as
|
|
302
|
-
import { homedir as
|
|
331
|
+
import { join as join3, relative as relative2 } from "path";
|
|
332
|
+
import { homedir as homedir3 } from "os";
|
|
303
333
|
import { lstat as lstat2, readdir as readdir2, unlink as unlink2 } from "fs/promises";
|
|
304
334
|
import chalk3 from "chalk";
|
|
305
335
|
import ora2 from "ora";
|
|
@@ -307,7 +337,7 @@ var SLUG_LABEL2 = "command slug";
|
|
|
307
337
|
async function resolveCommandFilePath(agent, slug, scope, cwd) {
|
|
308
338
|
const destDir = getContentPath(agent, "command", scope, cwd);
|
|
309
339
|
if (!destDir) return null;
|
|
310
|
-
const scopeRoot = scope === "user" ?
|
|
340
|
+
const scopeRoot = scope === "user" ? homedir3() : cwd;
|
|
311
341
|
return resolveContained(scopeRoot, relative2(scopeRoot, destDir), `${slug}.md`);
|
|
312
342
|
}
|
|
313
343
|
async function installCommandForCodingAgent(item, agent, scope, method, force, cwd) {
|
|
@@ -322,7 +352,7 @@ async function installCommandForCodingAgent(item, agent, scope, method, force, c
|
|
|
322
352
|
}
|
|
323
353
|
await assertOverwritable(destPath, force);
|
|
324
354
|
const sourcePath = getItemSourcePath(item);
|
|
325
|
-
const sourceFile = sourcePath ?
|
|
355
|
+
const sourceFile = sourcePath ? join3(sourcePath, mainFileName("command")) : null;
|
|
326
356
|
if (method === "symlink" && sourceFile && await exists(sourceFile)) {
|
|
327
357
|
await installFile(sourceFile, destPath, "symlink");
|
|
328
358
|
} else {
|
|
@@ -382,12 +412,12 @@ async function planCommand(item, agents, scope, method, cwd) {
|
|
|
382
412
|
const destPath = await resolveCommandFilePath(agent, item.slug, scope, cwd);
|
|
383
413
|
if (!destPath) throw new Error(`${CODING_AGENTS[agent].name} does not support commands`);
|
|
384
414
|
const sourcePath = getItemSourcePath(item);
|
|
385
|
-
const linked = method === "symlink" && sourcePath !== null && await exists(
|
|
415
|
+
const linked = method === "symlink" && sourcePath !== null && await exists(join3(sourcePath, mainFileName("command")));
|
|
386
416
|
changes.push({
|
|
387
417
|
agent,
|
|
388
418
|
kind: await exists(destPath) ? "modify" : "create",
|
|
389
419
|
path: destPath,
|
|
390
|
-
detail: linked ? `symlink \u2192 ${
|
|
420
|
+
detail: linked ? `symlink \u2192 ${join3(sourcePath, mainFileName("command"))}` : "slash command file"
|
|
391
421
|
});
|
|
392
422
|
}
|
|
393
423
|
return changes;
|
|
@@ -407,8 +437,8 @@ var commandHandler = {
|
|
|
407
437
|
};
|
|
408
438
|
|
|
409
439
|
// src/handlers/hook.ts
|
|
410
|
-
import { join as
|
|
411
|
-
import { homedir as
|
|
440
|
+
import { join as join4, basename, dirname } from "path";
|
|
441
|
+
import { homedir as homedir4 } from "os";
|
|
412
442
|
import { lstat as lstat3, mkdir, mkdtemp, readFile, realpath, rm, unlink as unlink3 } from "fs/promises";
|
|
413
443
|
import chalk4 from "chalk";
|
|
414
444
|
import ora3 from "ora";
|
|
@@ -416,10 +446,10 @@ var CLAUDE_ONLY_ERROR = "Hooks are only supported for Claude Code";
|
|
|
416
446
|
var SCRIPT_NAME_LABEL = "hook script name";
|
|
417
447
|
var SCRIPT_MODE = 493;
|
|
418
448
|
function getScopeRoot(scope, cwd) {
|
|
419
|
-
return scope === "user" ?
|
|
449
|
+
return scope === "user" ? homedir4() : cwd;
|
|
420
450
|
}
|
|
421
451
|
function getHooksDir(scope, cwd) {
|
|
422
|
-
return scope === "user" ?
|
|
452
|
+
return scope === "user" ? join4(claudeUserRoot(), "hooks") : join4(getScopeRoot(scope, cwd), ".claude", "hooks");
|
|
423
453
|
}
|
|
424
454
|
function getScriptPath(scope, scriptName) {
|
|
425
455
|
switch (scope) {
|
|
@@ -465,13 +495,13 @@ async function assertRegularFileOrMissing(path) {
|
|
|
465
495
|
async function loadScriptBytes(item, scriptFile, hooksDir) {
|
|
466
496
|
const sourcePath = getItemSourcePath(item);
|
|
467
497
|
if (sourcePath && await exists(sourcePath)) {
|
|
468
|
-
return readFile(
|
|
498
|
+
return readFile(join4(sourcePath, scriptFile));
|
|
469
499
|
}
|
|
470
|
-
const fetchDir = await mkdtemp(
|
|
500
|
+
const fetchDir = await mkdtemp(join4(dirname(hooksDir), ".seedr-hook-"));
|
|
471
501
|
try {
|
|
472
|
-
const contentDir =
|
|
502
|
+
const contentDir = join4(fetchDir, "content");
|
|
473
503
|
await fetchItemToDestination(item, contentDir);
|
|
474
|
-
return await readFile(
|
|
504
|
+
return await readFile(join4(contentDir, scriptFile));
|
|
475
505
|
} finally {
|
|
476
506
|
await rm(fetchDir, { recursive: true, force: true });
|
|
477
507
|
}
|
|
@@ -1219,18 +1249,18 @@ var settingsHandler = {
|
|
|
1219
1249
|
};
|
|
1220
1250
|
|
|
1221
1251
|
// src/handlers/plugin.ts
|
|
1222
|
-
import { join as
|
|
1252
|
+
import { join as join6, relative as relative3 } from "path";
|
|
1223
1253
|
import { mkdir as mkdir3, mkdtemp as mkdtemp2, rm as rm2, stat } from "fs/promises";
|
|
1224
1254
|
import chalk7 from "chalk";
|
|
1225
1255
|
import ora6 from "ora";
|
|
1226
1256
|
|
|
1227
1257
|
// src/handlers/pluginStores.ts
|
|
1228
|
-
import { homedir as
|
|
1229
|
-
import { basename as basename2, dirname as dirname3, isAbsolute, join as
|
|
1258
|
+
import { homedir as homedir5 } from "os";
|
|
1259
|
+
import { basename as basename2, dirname as dirname3, isAbsolute, join as join5 } from "path";
|
|
1230
1260
|
import { mkdir as mkdir2, readFile as readFile3, writeFile } from "fs/promises";
|
|
1231
1261
|
import { execFile } from "child_process";
|
|
1232
1262
|
import { promisify } from "util";
|
|
1233
|
-
var home =
|
|
1263
|
+
var home = homedir5();
|
|
1234
1264
|
var CLAUDE_MANIFEST = ".claude-plugin/plugin.json";
|
|
1235
1265
|
async function readTextOrEmpty2(path) {
|
|
1236
1266
|
try {
|
|
@@ -1240,7 +1270,7 @@ async function readTextOrEmpty2(path) {
|
|
|
1240
1270
|
}
|
|
1241
1271
|
}
|
|
1242
1272
|
async function writeText(path, text) {
|
|
1243
|
-
await mkdir2(
|
|
1273
|
+
await mkdir2(join5(path, ".."), { recursive: true });
|
|
1244
1274
|
await writeFile(path, text, "utf-8");
|
|
1245
1275
|
}
|
|
1246
1276
|
function getPluginId(name, marketplace) {
|
|
@@ -1255,8 +1285,8 @@ function manifestsFor(ownManifest) {
|
|
|
1255
1285
|
return ownManifest ? [ownManifest, CLAUDE_MANIFEST] : [CLAUDE_MANIFEST];
|
|
1256
1286
|
}
|
|
1257
1287
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1258
|
-
var CLAUDE_SELF_MARKETPLACE =
|
|
1259
|
-
var COPILOT_SELF_MARKETPLACE =
|
|
1288
|
+
var CLAUDE_SELF_MARKETPLACE = join5(".claude-plugin", "marketplace.json");
|
|
1289
|
+
var COPILOT_SELF_MARKETPLACE = join5(".github", "plugin", "marketplace.json");
|
|
1260
1290
|
async function alignSelfMarketplace(path, marketplace, name, item) {
|
|
1261
1291
|
const existing = await exists(path) ? await readJson(path) : {};
|
|
1262
1292
|
const plugins = Array.isArray(existing.plugins) ? existing.plugins : [];
|
|
@@ -1272,17 +1302,17 @@ async function alignSelfMarketplace(path, marketplace, name, item) {
|
|
|
1272
1302
|
});
|
|
1273
1303
|
}
|
|
1274
1304
|
async function ensureSelfMarketplace(contentPath, marketplace, name, item, alsoAlign = []) {
|
|
1275
|
-
await alignSelfMarketplace(
|
|
1305
|
+
await alignSelfMarketplace(join5(contentPath, CLAUDE_SELF_MARKETPLACE), marketplace, name, item);
|
|
1276
1306
|
for (const relative4 of alsoAlign) {
|
|
1277
|
-
const path =
|
|
1307
|
+
const path = join5(contentPath, relative4);
|
|
1278
1308
|
if (await exists(path)) await alignSelfMarketplace(path, marketplace, name, item);
|
|
1279
1309
|
}
|
|
1280
1310
|
}
|
|
1281
|
-
var CLAUDE_PLUGINS_DIR =
|
|
1282
|
-
var CLAUDE_CACHE_DIR =
|
|
1283
|
-
var CLAUDE_INSTALLED_PATH =
|
|
1284
|
-
var CLAUDE_KNOWN_MARKETPLACES_PATH =
|
|
1285
|
-
var CLAUDE_MARKETPLACES_DIR =
|
|
1311
|
+
var CLAUDE_PLUGINS_DIR = join5(claudeUserRoot(), "plugins");
|
|
1312
|
+
var CLAUDE_CACHE_DIR = join5(CLAUDE_PLUGINS_DIR, "cache");
|
|
1313
|
+
var CLAUDE_INSTALLED_PATH = join5(CLAUDE_PLUGINS_DIR, "installed_plugins.json");
|
|
1314
|
+
var CLAUDE_KNOWN_MARKETPLACES_PATH = join5(CLAUDE_PLUGINS_DIR, "known_marketplaces.json");
|
|
1315
|
+
var CLAUDE_MARKETPLACES_DIR = join5(CLAUDE_PLUGINS_DIR, "marketplaces");
|
|
1286
1316
|
function isScopeEntry(entry, scope, cwd) {
|
|
1287
1317
|
return entry.scope === scope && (scope === "user" || entry.projectPath === cwd);
|
|
1288
1318
|
}
|
|
@@ -1446,8 +1476,21 @@ var claudeStore = {
|
|
|
1446
1476
|
}
|
|
1447
1477
|
};
|
|
1448
1478
|
var COPILOT_DIR = copilotUserRoot();
|
|
1449
|
-
var COPILOT_SETTINGS_PATH =
|
|
1450
|
-
var COPILOT_PLUGINS_DIR =
|
|
1479
|
+
var COPILOT_SETTINGS_PATH = join5(COPILOT_DIR, "settings.json");
|
|
1480
|
+
var COPILOT_PLUGINS_DIR = join5(COPILOT_DIR, "installed-plugins");
|
|
1481
|
+
var COPILOT_HOOKS_DIR = join5(COPILOT_DIR, "hooks");
|
|
1482
|
+
var COPILOT_PLUGIN_HOOKS = join5("hooks", "hooks-copilot.json");
|
|
1483
|
+
function copilotHooksPath(name) {
|
|
1484
|
+
return resolveContained(COPILOT_HOOKS_DIR, name, "hooks.json");
|
|
1485
|
+
}
|
|
1486
|
+
async function writeCopilotHooks(cachePath, name) {
|
|
1487
|
+
const source = join5(cachePath, COPILOT_PLUGIN_HOOKS);
|
|
1488
|
+
if (!await exists(source)) return;
|
|
1489
|
+
const destination = await copilotHooksPath(name);
|
|
1490
|
+
const hooks = (await readFile3(source, "utf8")).replaceAll("${PLUGIN_ROOT}", cachePath);
|
|
1491
|
+
await mkdir2(dirname3(destination), { recursive: true });
|
|
1492
|
+
await writeFile(destination, hooks);
|
|
1493
|
+
}
|
|
1451
1494
|
var copilotStore = {
|
|
1452
1495
|
manifestPaths: manifestsFor(),
|
|
1453
1496
|
userGlobal: true,
|
|
@@ -1515,7 +1558,14 @@ var copilotStore = {
|
|
|
1515
1558
|
path: COPILOT_SETTINGS_PATH,
|
|
1516
1559
|
detail: `enabledPlugins["${context.pluginId}"] = true`,
|
|
1517
1560
|
apply: () => enableInJsonSettings(COPILOT_SETTINGS_PATH, context.pluginId)
|
|
1518
|
-
}
|
|
1561
|
+
},
|
|
1562
|
+
...context.cachePath ? [
|
|
1563
|
+
{
|
|
1564
|
+
path: join5(COPILOT_HOOKS_DIR, context.name, "hooks.json"),
|
|
1565
|
+
detail: `${COPILOT_PLUGIN_HOOKS} with \${PLUGIN_ROOT} resolved \u2014 only when the plugin ships one`,
|
|
1566
|
+
apply: () => writeCopilotHooks(context.cachePath, context.name)
|
|
1567
|
+
}
|
|
1568
|
+
] : []
|
|
1519
1569
|
],
|
|
1520
1570
|
async listInstalled() {
|
|
1521
1571
|
const settings = await readJson(COPILOT_SETTINGS_PATH);
|
|
@@ -1526,6 +1576,7 @@ var copilotStore = {
|
|
|
1526
1576
|
if (!disabled) return false;
|
|
1527
1577
|
const split = splitPluginId(pluginId);
|
|
1528
1578
|
if (split) {
|
|
1579
|
+
await removePathEntry(dirname3(await copilotHooksPath(split.name)));
|
|
1529
1580
|
let tree;
|
|
1530
1581
|
try {
|
|
1531
1582
|
tree = await resolveContained(COPILOT_PLUGINS_DIR, split.marketplace, split.name);
|
|
@@ -1544,8 +1595,8 @@ var copilotStore = {
|
|
|
1544
1595
|
}
|
|
1545
1596
|
};
|
|
1546
1597
|
var CODEX_DIR = codexUserRoot();
|
|
1547
|
-
var CODEX_CONFIG_PATH =
|
|
1548
|
-
var CODEX_CACHE_DIR =
|
|
1598
|
+
var CODEX_CONFIG_PATH = join5(CODEX_DIR, "config.toml");
|
|
1599
|
+
var CODEX_CACHE_DIR = join5(CODEX_DIR, "plugins", "cache");
|
|
1549
1600
|
function toCodexMarketplaceTable(marketplace, url, revision) {
|
|
1550
1601
|
return {
|
|
1551
1602
|
keyPath: ["marketplaces", marketplace],
|
|
@@ -1617,9 +1668,9 @@ var codexStore = {
|
|
|
1617
1668
|
}
|
|
1618
1669
|
};
|
|
1619
1670
|
function openCodeConfigPath(scope, cwd) {
|
|
1620
|
-
return scope === "user" ?
|
|
1671
|
+
return scope === "user" ? join5(openCodeUserConfigDir(), "opencode.json") : join5(cwd, "opencode.json");
|
|
1621
1672
|
}
|
|
1622
|
-
var OPENCODE_PLUGINS_DIR =
|
|
1673
|
+
var OPENCODE_PLUGINS_DIR = join5(openCodeUserConfigDir(), "plugins");
|
|
1623
1674
|
function toOpenCodePluginSpec(item, name, cachePath) {
|
|
1624
1675
|
if (isFirstParty(item.sourceType)) {
|
|
1625
1676
|
if (!cachePath) throw new Error(`OpenCode cannot install "${name}": a first-party plugin needs a directory to load from`);
|
|
@@ -1691,9 +1742,9 @@ var openCodeStore = {
|
|
|
1691
1742
|
return true;
|
|
1692
1743
|
}
|
|
1693
1744
|
};
|
|
1694
|
-
var GEMINI_CONFIG_DIR =
|
|
1695
|
-
var GEMINI_PLUGINS_DIR =
|
|
1696
|
-
var GEMINI_IMPORT_MANIFEST_PATH =
|
|
1745
|
+
var GEMINI_CONFIG_DIR = join5(home, ".gemini", "config");
|
|
1746
|
+
var GEMINI_PLUGINS_DIR = join5(GEMINI_CONFIG_DIR, "plugins");
|
|
1747
|
+
var GEMINI_IMPORT_MANIFEST_PATH = join5(GEMINI_CONFIG_DIR, "import_manifest.json");
|
|
1697
1748
|
var antigravityStore = {
|
|
1698
1749
|
manifestPaths: manifestsFor(),
|
|
1699
1750
|
userGlobal: true,
|
|
@@ -1715,7 +1766,7 @@ var antigravityStore = {
|
|
|
1715
1766
|
* (compound-engineering does) is left exactly as it is.
|
|
1716
1767
|
*/
|
|
1717
1768
|
async prepareTree(contentPath, { name, version, item }) {
|
|
1718
|
-
const manifestPath =
|
|
1769
|
+
const manifestPath = join5(contentPath, "plugin.json");
|
|
1719
1770
|
if (await exists(manifestPath)) return;
|
|
1720
1771
|
await writeJson(manifestPath, {
|
|
1721
1772
|
name,
|
|
@@ -1814,7 +1865,7 @@ function resolvePluginIdentity(item, pluginJson) {
|
|
|
1814
1865
|
}
|
|
1815
1866
|
async function readManifestFromDir(dir, manifestPaths) {
|
|
1816
1867
|
for (const manifest of manifestPaths) {
|
|
1817
|
-
const path =
|
|
1868
|
+
const path = join6(dir, ...manifest.split("/"));
|
|
1818
1869
|
if (await exists(path)) return readJson(path);
|
|
1819
1870
|
}
|
|
1820
1871
|
return {};
|
|
@@ -1833,7 +1884,7 @@ async function readManifestForPlan(item, manifestPaths) {
|
|
|
1833
1884
|
async function createStagingDir(cacheRoot, slug) {
|
|
1834
1885
|
const tmpRoot = await resolveContained(cacheRoot, ".tmp");
|
|
1835
1886
|
await mkdir3(tmpRoot, { recursive: true });
|
|
1836
|
-
const staging = await mkdtemp2(
|
|
1887
|
+
const staging = await mkdtemp2(join6(tmpRoot, `${slug}-`));
|
|
1837
1888
|
return resolveContained(cacheRoot, relative3(cacheRoot, staging));
|
|
1838
1889
|
}
|
|
1839
1890
|
async function stageContent(item, contentPath) {
|
|
@@ -1901,7 +1952,7 @@ async function installPluginForAgent(item, agent, scope, _method, force, cwd) {
|
|
|
1901
1952
|
const cacheRoot = store.cacheRoot ?? (isFirstParty(item.sourceType) ? store.firstPartyCacheRoot ?? null : null);
|
|
1902
1953
|
const staging = cacheRoot ? await createStagingDir(cacheRoot, item.slug) : null;
|
|
1903
1954
|
try {
|
|
1904
|
-
const contentPath = staging ?
|
|
1955
|
+
const contentPath = staging ? join6(staging, "content") : null;
|
|
1905
1956
|
const fetched = contentPath ? await stageContent(item, contentPath) : null;
|
|
1906
1957
|
const pluginJson = contentPath ? await readManifestFromDir(contentPath, store.manifestPaths) : await readManifestForPlan(item, store.manifestPaths);
|
|
1907
1958
|
const { name, version } = resolvePluginIdentity(item, pluginJson);
|
|
@@ -1929,7 +1980,7 @@ async function installPluginForAgent(item, agent, scope, _method, force, cwd) {
|
|
|
1929
1980
|
...store.mutations(context)
|
|
1930
1981
|
]);
|
|
1931
1982
|
spinner.succeed(brand(`Installed ${item.name} for ${CODING_AGENTS[agent].name}`));
|
|
1932
|
-
return { agent, success: true, path: cachePath ?? "" };
|
|
1983
|
+
return { agent, success: true, path: cachePath ?? "", version };
|
|
1933
1984
|
} finally {
|
|
1934
1985
|
if (staging) await rm2(staging, { recursive: true, force: true });
|
|
1935
1986
|
}
|
|
@@ -2056,35 +2107,35 @@ import chalk8 from "chalk";
|
|
|
2056
2107
|
import ora7 from "ora";
|
|
2057
2108
|
|
|
2058
2109
|
// src/handlers/ruleTargets.ts
|
|
2059
|
-
import { homedir as
|
|
2060
|
-
import { join as
|
|
2061
|
-
var home2 =
|
|
2110
|
+
import { homedir as homedir6 } from "os";
|
|
2111
|
+
import { join as join7 } from "path";
|
|
2112
|
+
var home2 = homedir6();
|
|
2062
2113
|
var markdownFile = (slug) => `${slug}.md`;
|
|
2063
2114
|
var claudeTarget = {
|
|
2064
2115
|
kind: "file",
|
|
2065
|
-
dir: (scope, cwd) =>
|
|
2116
|
+
dir: (scope, cwd) => join7(scope === "user" ? claudeUserRoot() : join7(cwd, ".claude"), "rules"),
|
|
2066
2117
|
fileName: markdownFile,
|
|
2067
2118
|
keepsFrontmatter: true
|
|
2068
2119
|
};
|
|
2069
2120
|
var antigravityTarget = {
|
|
2070
2121
|
kind: "file",
|
|
2071
|
-
dir: (scope, cwd) =>
|
|
2122
|
+
dir: (scope, cwd) => join7(scope === "user" ? join7(home2, ".gemini", "config") : join7(cwd, ".agents"), "rules"),
|
|
2072
2123
|
fileName: markdownFile,
|
|
2073
2124
|
keepsFrontmatter: true
|
|
2074
2125
|
};
|
|
2075
2126
|
var copilotTarget = {
|
|
2076
2127
|
kind: "file",
|
|
2077
|
-
dir: (scope, cwd) =>
|
|
2128
|
+
dir: (scope, cwd) => join7(scope === "user" ? copilotUserRoot() : join7(cwd, ".github"), "instructions"),
|
|
2078
2129
|
fileName: (slug) => `${slug}.instructions.md`,
|
|
2079
2130
|
keepsFrontmatter: true
|
|
2080
2131
|
};
|
|
2081
2132
|
var codexTarget = {
|
|
2082
2133
|
kind: "section",
|
|
2083
|
-
file: (scope, cwd) => scope === "user" ?
|
|
2134
|
+
file: (scope, cwd) => scope === "user" ? join7(codexUserRoot(), "AGENTS.md") : join7(cwd, "AGENTS.md")
|
|
2084
2135
|
};
|
|
2085
2136
|
var openCodeTarget = {
|
|
2086
2137
|
kind: "section",
|
|
2087
|
-
file: (scope, cwd) => scope === "user" ?
|
|
2138
|
+
file: (scope, cwd) => scope === "user" ? join7(openCodeUserConfigDir(), "AGENTS.md") : join7(cwd, "AGENTS.md")
|
|
2088
2139
|
};
|
|
2089
2140
|
var TARGETS = {
|
|
2090
2141
|
claude: claudeTarget,
|
|
@@ -2354,6 +2405,24 @@ function formatPlan(changes) {
|
|
|
2354
2405
|
}
|
|
2355
2406
|
return lines;
|
|
2356
2407
|
}
|
|
2408
|
+
async function noteInstall(item, results, scope) {
|
|
2409
|
+
const succeeded = results.filter((r) => r.success);
|
|
2410
|
+
const installed = succeeded.map((r) => r.agent);
|
|
2411
|
+
if (installed.length === 0) return;
|
|
2412
|
+
try {
|
|
2413
|
+
await recordInstall({
|
|
2414
|
+
type: item.type,
|
|
2415
|
+
slug: item.slug,
|
|
2416
|
+
version: succeeded.find((r) => r.version)?.version ?? item.version,
|
|
2417
|
+
contentDigest: item.contentDigest,
|
|
2418
|
+
agents: installed,
|
|
2419
|
+
scope,
|
|
2420
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2421
|
+
});
|
|
2422
|
+
} catch (error2) {
|
|
2423
|
+
warn(`Installed, but the install record could not be written: ${error2.message}`);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2357
2426
|
function summarizeResults(results) {
|
|
2358
2427
|
const successful = results.filter((r) => r.success);
|
|
2359
2428
|
const failed = results.filter((r) => !r.success);
|
|
@@ -2526,6 +2595,7 @@ async function runAdd(name, options, cwd = process.cwd()) {
|
|
|
2526
2595
|
console.log();
|
|
2527
2596
|
const results = await handler.install(item, agents, scope, method, decideForce(options), cwd);
|
|
2528
2597
|
void trackInstalls(item.slug, item.type, results, scope);
|
|
2598
|
+
await noteInstall(item, results, scope);
|
|
2529
2599
|
const exitCode = printInstallSummary(results);
|
|
2530
2600
|
if (exitCode === 0) outro("Installation complete");
|
|
2531
2601
|
return exitCode;
|
|
@@ -2645,11 +2715,37 @@ ${itemType.toUpperCase()}S`));
|
|
|
2645
2715
|
);
|
|
2646
2716
|
return 0;
|
|
2647
2717
|
}
|
|
2718
|
+
async function installedVersionAnnotator() {
|
|
2719
|
+
let ledger;
|
|
2720
|
+
try {
|
|
2721
|
+
ledger = await readLedger();
|
|
2722
|
+
} catch {
|
|
2723
|
+
return () => "";
|
|
2724
|
+
}
|
|
2725
|
+
let current;
|
|
2726
|
+
try {
|
|
2727
|
+
const items = await listItems();
|
|
2728
|
+
current = new Map(
|
|
2729
|
+
items.filter((item) => item.contentDigest).map((item) => [ledgerKey(item.type, item.slug), item.contentDigest])
|
|
2730
|
+
);
|
|
2731
|
+
} catch {
|
|
2732
|
+
current = /* @__PURE__ */ new Map();
|
|
2733
|
+
}
|
|
2734
|
+
return (type, slug) => {
|
|
2735
|
+
const key = ledgerKey(type, slug);
|
|
2736
|
+
const entry = ledger.items[key];
|
|
2737
|
+
if (!entry?.version) return "";
|
|
2738
|
+
const available = current.get(key);
|
|
2739
|
+
const stale = entry.contentDigest && available && available !== entry.contentDigest;
|
|
2740
|
+
return chalk10.gray(` ${entry.version}`) + (stale ? chalk10.yellow(" \u2192 update available") : "");
|
|
2741
|
+
};
|
|
2742
|
+
}
|
|
2648
2743
|
async function listInstalled(params) {
|
|
2649
2744
|
console.log(brand(`
|
|
2650
2745
|
Installed items (${params.scope} scope):
|
|
2651
2746
|
`));
|
|
2652
2747
|
const groups = await collectInstalledItems(params);
|
|
2748
|
+
const annotate = await installedVersionAnnotator();
|
|
2653
2749
|
let total = 0;
|
|
2654
2750
|
let currentType = null;
|
|
2655
2751
|
for (const group of groups) {
|
|
@@ -2660,7 +2756,7 @@ Installed items (${params.scope} scope):
|
|
|
2660
2756
|
}
|
|
2661
2757
|
console.log(chalk10.blue(` ${CODING_AGENTS[group.agent].name}`));
|
|
2662
2758
|
for (const slug of group.slugs) {
|
|
2663
|
-
console.log(` ${chalk10.white(slug)}`);
|
|
2759
|
+
console.log(` ${chalk10.white(slug)}${annotate(group.type, slug)}`);
|
|
2664
2760
|
total++;
|
|
2665
2761
|
}
|
|
2666
2762
|
console.log("");
|
|
@@ -2707,6 +2803,7 @@ async function removeFromAgents(slug, type, agents, scope, cwd) {
|
|
|
2707
2803
|
const handler = getHandler(type);
|
|
2708
2804
|
if (!handler) return 0;
|
|
2709
2805
|
let successCount = 0;
|
|
2806
|
+
const removedFrom = [];
|
|
2710
2807
|
for (const agent of agents) {
|
|
2711
2808
|
if (!isTypeSupported(type, agent)) {
|
|
2712
2809
|
ora8().start().info(
|
|
@@ -2718,11 +2815,18 @@ async function removeFromAgents(slug, type, agents, scope, cwd) {
|
|
|
2718
2815
|
const removed = await handler.uninstall(slug, agent, scope, cwd);
|
|
2719
2816
|
if (removed) {
|
|
2720
2817
|
spinner.succeed(brand(`Removed from ${CODING_AGENTS[agent].name}`));
|
|
2818
|
+
removedFrom.push(agent);
|
|
2721
2819
|
successCount++;
|
|
2722
2820
|
} else {
|
|
2723
2821
|
spinner.info(chalk11.gray(`Not found in ${CODING_AGENTS[agent].name}`));
|
|
2724
2822
|
}
|
|
2725
2823
|
}
|
|
2824
|
+
if (removedFrom.length > 0) {
|
|
2825
|
+
try {
|
|
2826
|
+
await recordRemoval(type, slug, removedFrom);
|
|
2827
|
+
} catch {
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2726
2830
|
return successCount;
|
|
2727
2831
|
}
|
|
2728
2832
|
function validateRemoveRequest(name, options) {
|
|
@@ -2815,7 +2919,7 @@ var removeCommand = new Command3("remove").alias("rm").description("Remove an in
|
|
|
2815
2919
|
import { Command as Command4 } from "commander";
|
|
2816
2920
|
import chalk12 from "chalk";
|
|
2817
2921
|
import ora9 from "ora";
|
|
2818
|
-
import { join as
|
|
2922
|
+
import { join as join8 } from "path";
|
|
2819
2923
|
function readmeFor(agent) {
|
|
2820
2924
|
return `# ${CODING_AGENTS[agent].name} Configuration
|
|
2821
2925
|
|
|
@@ -2833,7 +2937,7 @@ async function initializeAgent(agent, cwd) {
|
|
|
2833
2937
|
const path = getAgentPath(agent, "project", cwd);
|
|
2834
2938
|
if (await exists(path)) return false;
|
|
2835
2939
|
await ensureDir(path);
|
|
2836
|
-
await writeTextFile(
|
|
2940
|
+
await writeTextFile(join8(path, "README.md"), readmeFor(agent));
|
|
2837
2941
|
return true;
|
|
2838
2942
|
}
|
|
2839
2943
|
async function runInit(options, cwd = process.cwd()) {
|
|
@@ -2894,7 +2998,7 @@ var initCommand = new Command4("init").description("Initialize coding agent conf
|
|
|
2894
2998
|
// package.json
|
|
2895
2999
|
var package_default = {
|
|
2896
3000
|
name: "@danieldeusing/seedr",
|
|
2897
|
-
version: "0.1.
|
|
3001
|
+
version: "0.1.130",
|
|
2898
3002
|
description: "Seed your projects with AI configurations",
|
|
2899
3003
|
type: "module",
|
|
2900
3004
|
bin: {
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,13 @@ interface InstallResult {
|
|
|
72
72
|
success: boolean;
|
|
73
73
|
path: string;
|
|
74
74
|
error?: string;
|
|
75
|
+
/**
|
|
76
|
+
* The version that landed, when it differs from the registry item's own.
|
|
77
|
+
* A plugin carries its version in its manifest and the registry item carries
|
|
78
|
+
* a separate one for the catalogue entry — recording the item's would say
|
|
79
|
+
* "1.0.20" for a plugin every agent knows as 0.16.2.
|
|
80
|
+
*/
|
|
81
|
+
version?: string;
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
declare function installSkill(item: RegistryItem, agents: CodingAgent[], scope: InstallScope, method: InstallMethod, force: boolean, cwd?: string): Promise<InstallResult[]>;
|