@rbbtsn0w/adg 0.3.0-beta.3 → 0.3.0-beta.4
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/bin/adg.js +12 -127
- package/dist/src/render/plugins.js +100 -0
- package/dist/src/render/ui.js +51 -0
- package/package.json +6 -5
package/dist/bin/adg.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { parseArgs } from "node:util";
|
|
3
|
-
import pc from "picocolors";
|
|
4
3
|
import { spawnSync } from "node:child_process";
|
|
5
4
|
import { readFileSync, realpathSync } from "node:fs";
|
|
6
|
-
import { homedir } from "node:os";
|
|
7
5
|
import { dirname, join, resolve } from "node:path";
|
|
8
6
|
import { fileURLToPath } from "node:url";
|
|
9
7
|
import { checkForUpdate, formatUpdateNotice } from "../src/update-check.js";
|
|
@@ -23,24 +21,11 @@ import { selectTargetsInteractive } from "../src/commands/select-agents.js";
|
|
|
23
21
|
import { selectPluginsInteractive } from "../src/commands/select-plugins.js";
|
|
24
22
|
import { selectScopeInteractive } from "../src/commands/select-scope.js";
|
|
25
23
|
import { confirmFullInstall, selectComponentsInteractive } from "../src/commands/select-components.js";
|
|
26
|
-
import { globalPluginsDir,
|
|
24
|
+
import { globalPluginsDir, projectPluginsDir } from "../src/paths.js";
|
|
27
25
|
import { COMPONENT_TYPES } from "../src/types.js";
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// commands: cyan = primary identifiers (plugins, agents, sources), dim =
|
|
32
|
-
// secondary metadata (paths, hashes, sub-details), green = success, yellow =
|
|
33
|
-
// notes/warnings, red = errors, bold = section titles. picocolors auto-disables
|
|
34
|
-
// on non-TTY / NO_COLOR, so piped output and tests stay plain.
|
|
35
|
-
// ---------------------------------------------------------------------------
|
|
36
|
-
const ui = {
|
|
37
|
-
title: (s) => pc.bold(s),
|
|
38
|
-
name: (s) => pc.cyan(s),
|
|
39
|
-
meta: (s) => pc.dim(s),
|
|
40
|
-
ok: (s) => pc.green(s),
|
|
41
|
-
warn: (s) => pc.yellow(s),
|
|
42
|
-
err: (s) => pc.red(s),
|
|
43
|
-
};
|
|
26
|
+
import { getAgent } from "../src/agents/index.js";
|
|
27
|
+
import { ui } from "../src/render/ui.js";
|
|
28
|
+
import { renderAgentReport, renderMarketplaceList, renderPluginList, } from "../src/render/plugins.js";
|
|
44
29
|
const FLAGS = {
|
|
45
30
|
// Short flags are first-letter aliases. Where several long flags share a
|
|
46
31
|
// first letter, the highest-frequency one wins the short and the rest stay
|
|
@@ -243,16 +228,6 @@ function scopeInfo(values) {
|
|
|
243
228
|
function scopeOf(values) {
|
|
244
229
|
return values.global ? "user" : "project";
|
|
245
230
|
}
|
|
246
|
-
/** Print per-agent sync outcomes (enabled/disabled/re-synced) generically. */
|
|
247
|
-
function reportAgents(agents, verb) {
|
|
248
|
-
for (const r of agents ?? []) {
|
|
249
|
-
const name = getAgent(r.agent)?.displayName ?? r.agent;
|
|
250
|
-
if (r.affected.length > 0)
|
|
251
|
-
console.log(`${ui.ok(verb)} in ${ui.name(name)}: ${r.affected.join(", ")}`);
|
|
252
|
-
else if (r.skipped)
|
|
253
|
-
console.log(ui.warn(`note: \`${r.agent}\` CLI not found — run \`adg plugins link --target ${r.agent}\` after installing it.`));
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
231
|
/** Friendly `--target` aliases mapped onto canonical adapter target ids. */
|
|
257
232
|
const TARGET_ALIASES = {
|
|
258
233
|
anthropic: "claude",
|
|
@@ -294,45 +269,6 @@ function parseVerb(name, flags, rest) {
|
|
|
294
269
|
process.exit(1);
|
|
295
270
|
}
|
|
296
271
|
}
|
|
297
|
-
/**
|
|
298
|
-
* Lay items out in aligned columns sized to the terminal width (row-major).
|
|
299
|
-
* Items longer than `maxColWidth` are truncated with an ellipsis. Falls back to
|
|
300
|
-
* a single column on narrow terminals. Returns the block as a string.
|
|
301
|
-
*/
|
|
302
|
-
function formatColumns(items, opts = {}) {
|
|
303
|
-
const indent = opts.indent ?? 2;
|
|
304
|
-
const gutter = opts.gutter ?? 2;
|
|
305
|
-
const maxColWidth = opts.maxColWidth ?? 24;
|
|
306
|
-
const termWidth = opts.width ?? process.stdout.columns ?? 80;
|
|
307
|
-
const cells = items.map((s) => (s.length > maxColWidth ? s.slice(0, maxColWidth - 1) + "…" : s));
|
|
308
|
-
const colWidth = Math.min(Math.max(1, ...cells.map((c) => c.length)), maxColWidth);
|
|
309
|
-
const cols = Math.max(1, Math.floor((termWidth - indent + gutter) / (colWidth + gutter)));
|
|
310
|
-
const lines = [];
|
|
311
|
-
for (let i = 0; i < cells.length; i += cols) {
|
|
312
|
-
const row = cells.slice(i, i + cols);
|
|
313
|
-
const padded = row.map((c, j) => (j === row.length - 1 ? c : c.padEnd(colWidth)));
|
|
314
|
-
lines.push(" ".repeat(indent) + padded.join(" ".repeat(gutter)));
|
|
315
|
-
}
|
|
316
|
-
return lines.join("\n");
|
|
317
|
-
}
|
|
318
|
-
/** Abbreviate the home-directory prefix of an absolute path to `~` (POSIX `/` or Windows `\`). */
|
|
319
|
-
function abbrevHome(p) {
|
|
320
|
-
const home = homedir();
|
|
321
|
-
if (p === home)
|
|
322
|
-
return "~";
|
|
323
|
-
if (p.startsWith(home + "/") || p.startsWith(home + "\\"))
|
|
324
|
-
return "~" + p.slice(home.length);
|
|
325
|
-
return p;
|
|
326
|
-
}
|
|
327
|
-
/** Print a plugin's components, each expanded to its member names (verbose view). */
|
|
328
|
-
function printContents(contents, headerIndent) {
|
|
329
|
-
const entries = Object.entries(contents ?? {}).filter(([, names]) => names.length > 0);
|
|
330
|
-
for (const [type, names] of entries) {
|
|
331
|
-
const maxColWidth = Math.max(1, ...names.map((n) => n.length));
|
|
332
|
-
console.log(`${" ".repeat(headerIndent)}${ui.name(type)} ${ui.meta(`(${names.length}):`)}`);
|
|
333
|
-
console.log(formatColumns(names, { indent: headerIndent + 2, maxColWidth }));
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
272
|
async function runPlugins(rawVerb, rest) {
|
|
337
273
|
// `adg plugins` (no verb) or an explicit help request → the L1 overview.
|
|
338
274
|
if (rawVerb === undefined || rawVerb === "-h" || rawVerb === "--help" || rawVerb === "help") {
|
|
@@ -447,7 +383,8 @@ async function runPlugins(rawVerb, rest) {
|
|
|
447
383
|
for (const f of res.adapted)
|
|
448
384
|
console.log(ui.meta(` adapted: ${f}`));
|
|
449
385
|
}
|
|
450
|
-
|
|
386
|
+
for (const line of renderAgentReport(agents, "enabled"))
|
|
387
|
+
console.log(line);
|
|
451
388
|
return;
|
|
452
389
|
}
|
|
453
390
|
case "import-skills": {
|
|
@@ -494,7 +431,8 @@ async function runPlugins(rawVerb, rest) {
|
|
|
494
431
|
console.log(`${r.changed ? ui.ok("updated") : ui.meta("unchanged")} ${ui.name(`${r.name}@${r.version}`)}`);
|
|
495
432
|
for (const m of missing)
|
|
496
433
|
console.error(ui.warn(` ! missing directory for locked plugin: ${m}`));
|
|
497
|
-
|
|
434
|
+
for (const line of renderAgentReport(agents, "re-synced"))
|
|
435
|
+
console.log(line);
|
|
498
436
|
return;
|
|
499
437
|
}
|
|
500
438
|
case "remove": {
|
|
@@ -528,43 +466,8 @@ async function runPlugins(rawVerb, rest) {
|
|
|
528
466
|
const { values } = parseVerb(verb, cmd.flags, rest);
|
|
529
467
|
const pluginsDir = resolveScopeDir(values);
|
|
530
468
|
const plugins = listPlugins(pluginsDir);
|
|
531
|
-
|
|
532
|
-
console.log(
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
// Pre-compute each plugin's display row so the name/path columns can be
|
|
536
|
-
// aligned across rows (à la `adg skills list`). The `Agents:` column is
|
|
537
|
-
// derived from the exposed component types — which agents can adapt it.
|
|
538
|
-
const PATH_MAX = 44;
|
|
539
|
-
const rows = plugins.map((p) => {
|
|
540
|
-
const exposed = Object.entries(p.contents ?? {}).filter(([, names]) => names.length > 0);
|
|
541
|
-
const types = exposed.map(([type]) => type);
|
|
542
|
-
const agents = agentsForComponents(types).map((a) => a.displayName);
|
|
543
|
-
return {
|
|
544
|
-
p,
|
|
545
|
-
label: `${p.name}@${p.version}`,
|
|
546
|
-
path: abbrevHome(installedPluginDir(pluginsDir, p.name, p.origin)),
|
|
547
|
-
agents: agents.length > 0 ? agents.join(", ") : "—",
|
|
548
|
-
counts: exposed.map(([type, names]) => `${type}: ${names.length}`),
|
|
549
|
-
};
|
|
550
|
-
});
|
|
551
|
-
const nameW = Math.max(...rows.map((r) => r.label.length));
|
|
552
|
-
const pathW = Math.min(PATH_MAX, Math.max(...rows.map((r) => r.path.length)));
|
|
553
|
-
const ellip = (s, w) => (s.length > w ? "…" + s.slice(s.length - w + 1) : s);
|
|
554
|
-
// Color mirrors `adg skills list`: cyan name, dim path / dim "Agents:"
|
|
555
|
-
// label with the agent names left bright, and the provenance/counts line
|
|
556
|
-
// fully dimmed as secondary metadata. Widths are measured on the uncolored
|
|
557
|
-
// strings (above), so wrapping the padded text keeps columns aligned.
|
|
558
|
-
// picocolors auto-disables on non-TTY / NO_COLOR, so pipes stay plain.
|
|
559
|
-
for (const r of rows) {
|
|
560
|
-
const partial = r.p.selection ? " (partial)" : "";
|
|
561
|
-
const name = ui.name(r.label.padEnd(nameW));
|
|
562
|
-
const path = ui.meta(ellip(r.path, pathW).padEnd(pathW));
|
|
563
|
-
console.log(`${name} ${path} ${ui.meta("Agents:")} ${r.agents}`);
|
|
564
|
-
const provenance = `[${r.p.origin.type}] ${r.p.folderHash.slice(0, 19)}${partial}`;
|
|
565
|
-
console.log(ui.meta(` ${[provenance, ...r.counts].join(" ")}`));
|
|
566
|
-
if (values.verbose)
|
|
567
|
-
printContents(r.p.contents, 4);
|
|
469
|
+
for (const line of renderPluginList(plugins, pluginsDir, { verbose: values.verbose })) {
|
|
470
|
+
console.log(line);
|
|
568
471
|
}
|
|
569
472
|
return;
|
|
570
473
|
}
|
|
@@ -618,28 +521,10 @@ async function runMarketplace(args) {
|
|
|
618
521
|
const { values } = parseVerb("marketplace", ["verbose", ...SCOPE], rest);
|
|
619
522
|
const dir = resolveScopeDir(values);
|
|
620
523
|
const groups = marketplaceList({ pluginsDir: dir });
|
|
621
|
-
if (groups.length === 0) {
|
|
622
|
-
console.log(ui.meta("No plugins installed."));
|
|
623
|
-
return;
|
|
624
|
-
}
|
|
625
524
|
// Verbose: drill each plugin down to its components (reuses `plugins list -v`).
|
|
626
525
|
const byName = values.verbose ? new Map(listPlugins(dir).map((p) => [p.name, p])) : undefined;
|
|
627
|
-
for (const
|
|
628
|
-
|
|
629
|
-
const n = g.installed.length;
|
|
630
|
-
const tag = g.remote ? "" : ui.warn(" (local — re-run add to update)");
|
|
631
|
-
console.log(`${ui.name(`${g.source}${ref}`)} ${ui.meta(`(${n} plugin${n !== 1 ? "s" : ""})`)}${tag}`);
|
|
632
|
-
if (byName) {
|
|
633
|
-
for (const name of g.installed) {
|
|
634
|
-
const p = byName.get(name);
|
|
635
|
-
console.log(` ${ui.name(name)}${p?.selection ? ui.meta(" (partial)") : ""}`);
|
|
636
|
-
printContents(p?.contents, 4);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
else {
|
|
640
|
-
console.log(formatColumns(g.installed));
|
|
641
|
-
}
|
|
642
|
-
}
|
|
526
|
+
for (const line of renderMarketplaceList(groups, byName))
|
|
527
|
+
console.log(line);
|
|
643
528
|
return;
|
|
644
529
|
}
|
|
645
530
|
case "upgrade": {
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ui, formatColumns, abbrevHome, ellipsizeStart } from "./ui.js";
|
|
2
|
+
import { installedPluginDir } from "../paths.js";
|
|
3
|
+
import { agentsForComponents, getAgent } from "../agents/index.js";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Presentation layer for `adg plugins`. Each function turns command-layer data
|
|
6
|
+
// into terminal-ready lines (returned as string[]), so bin/adg.ts only parses
|
|
7
|
+
// args, calls a command, prints the lines — and the formatting is unit-testable
|
|
8
|
+
// without spawning the CLI. Color mirrors `adg skills list` throughout.
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
/** A plugin's components, each expanded to its member names (verbose view). */
|
|
11
|
+
export function renderContents(contents, headerIndent) {
|
|
12
|
+
const out = [];
|
|
13
|
+
const entries = Object.entries(contents ?? {}).filter(([, names]) => names.length > 0);
|
|
14
|
+
for (const [type, names] of entries) {
|
|
15
|
+
const maxColWidth = Math.max(1, ...names.map((n) => n.length));
|
|
16
|
+
out.push(`${" ".repeat(headerIndent)}${ui.name(type)} ${ui.meta(`(${names.length}):`)}`);
|
|
17
|
+
// formatColumns returns one string with embedded newlines; split so `out`
|
|
18
|
+
// stays a flat list of single lines.
|
|
19
|
+
out.push(...formatColumns(names, { indent: headerIndent + 2, maxColWidth }).split("\n"));
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
/** Per-agent sync outcomes (enabled/disabled/re-synced), printed generically. */
|
|
24
|
+
export function renderAgentReport(agents, verb) {
|
|
25
|
+
const out = [];
|
|
26
|
+
for (const r of agents ?? []) {
|
|
27
|
+
const name = getAgent(r.agent)?.displayName ?? r.agent;
|
|
28
|
+
if (r.affected.length > 0)
|
|
29
|
+
out.push(`${ui.ok(verb)} in ${ui.name(name)}: ${r.affected.join(", ")}`);
|
|
30
|
+
else if (r.skipped)
|
|
31
|
+
out.push(ui.warn(`note: \`${r.agent}\` CLI not found — run \`adg plugins link --target ${r.agent}\` after installing it.`));
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
const PATH_MAX = 44;
|
|
36
|
+
/** `adg plugins list` — aligned name/path/agents rows, with optional verbose contents. */
|
|
37
|
+
export function renderPluginList(plugins, pluginsDir, opts = {}) {
|
|
38
|
+
if (plugins.length === 0)
|
|
39
|
+
return [ui.meta(`no plugins recorded in ${pluginsDir}`)];
|
|
40
|
+
// Pre-compute each plugin's display row so the name/path columns can be
|
|
41
|
+
// aligned across rows (à la `adg skills list`). The `Agents:` column is
|
|
42
|
+
// derived from the exposed component types — which agents can adapt it.
|
|
43
|
+
const rows = plugins.map((p) => {
|
|
44
|
+
const exposed = Object.entries(p.contents ?? {}).filter(([, names]) => names.length > 0);
|
|
45
|
+
const types = exposed.map(([type]) => type);
|
|
46
|
+
const agents = agentsForComponents(types).map((a) => a.displayName);
|
|
47
|
+
return {
|
|
48
|
+
p,
|
|
49
|
+
label: `${p.name}@${p.version}`,
|
|
50
|
+
path: abbrevHome(installedPluginDir(pluginsDir, p.name, p.origin)),
|
|
51
|
+
agents: agents.length > 0 ? agents.join(", ") : "—",
|
|
52
|
+
counts: exposed.map(([type, names]) => `${type}: ${names.length}`),
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
const nameW = Math.max(...rows.map((r) => r.label.length));
|
|
56
|
+
const pathW = Math.min(PATH_MAX, Math.max(...rows.map((r) => r.path.length)));
|
|
57
|
+
// Color mirrors `adg skills list`: cyan name, dim path / dim "Agents:" label
|
|
58
|
+
// with the agent names left bright, and the provenance/counts line fully
|
|
59
|
+
// dimmed as secondary metadata. Widths are measured on the uncolored strings
|
|
60
|
+
// (above), so wrapping the padded text keeps columns aligned.
|
|
61
|
+
const out = [];
|
|
62
|
+
for (const r of rows) {
|
|
63
|
+
const partial = r.p.selection ? " (partial)" : "";
|
|
64
|
+
const name = ui.name(r.label.padEnd(nameW));
|
|
65
|
+
const path = ui.meta(ellipsizeStart(r.path, pathW).padEnd(pathW));
|
|
66
|
+
out.push(`${name} ${path} ${ui.meta("Agents:")} ${r.agents}`);
|
|
67
|
+
const provenance = `[${r.p.origin.type}] ${(r.p.folderHash ?? "").slice(0, 19)}${partial}`;
|
|
68
|
+
out.push(ui.meta(` ${[provenance, ...r.counts].join(" ")}`));
|
|
69
|
+
if (opts.verbose)
|
|
70
|
+
out.push(...renderContents(r.p.contents, 4));
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* `adg plugins marketplace list` — installed plugins grouped by source.
|
|
76
|
+
* `details` (name → ListedPlugin) enables the verbose per-plugin component drill;
|
|
77
|
+
* pass it only when --verbose is set.
|
|
78
|
+
*/
|
|
79
|
+
export function renderMarketplaceList(groups, details) {
|
|
80
|
+
if (groups.length === 0)
|
|
81
|
+
return [ui.meta("No plugins installed.")];
|
|
82
|
+
const out = [];
|
|
83
|
+
for (const g of groups) {
|
|
84
|
+
const ref = g.ref ? `@${g.ref}` : "";
|
|
85
|
+
const n = g.installed.length;
|
|
86
|
+
const tag = g.remote ? "" : ui.warn(" (local — re-run add to update)");
|
|
87
|
+
out.push(`${ui.name(`${g.source}${ref}`)} ${ui.meta(`(${n} plugin${n !== 1 ? "s" : ""})`)}${tag}`);
|
|
88
|
+
if (details) {
|
|
89
|
+
for (const name of g.installed) {
|
|
90
|
+
const p = details.get(name);
|
|
91
|
+
out.push(` ${ui.name(name)}${p?.selection ? ui.meta(" (partial)") : ""}`);
|
|
92
|
+
out.push(...renderContents(p?.contents, 4));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
out.push(...formatColumns(g.installed).split("\n"));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Semantic colors, mirroring `adg skills list` so output reads the same across
|
|
5
|
+
// commands: cyan = primary identifiers (plugins, agents, sources), dim =
|
|
6
|
+
// secondary metadata (paths, hashes, sub-details), green = success, yellow =
|
|
7
|
+
// notes/warnings, red = errors, bold = section titles. picocolors auto-disables
|
|
8
|
+
// on non-TTY / NO_COLOR, so piped output and tests stay plain.
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
export const ui = {
|
|
11
|
+
title: (s) => pc.bold(s),
|
|
12
|
+
name: (s) => pc.cyan(s),
|
|
13
|
+
meta: (s) => pc.dim(s),
|
|
14
|
+
ok: (s) => pc.green(s),
|
|
15
|
+
warn: (s) => pc.yellow(s),
|
|
16
|
+
err: (s) => pc.red(s),
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Lay items out in aligned columns sized to the terminal width (row-major).
|
|
20
|
+
* Items longer than `maxColWidth` are truncated with an ellipsis. Falls back to
|
|
21
|
+
* a single column on narrow terminals. Returns the block as a string.
|
|
22
|
+
*/
|
|
23
|
+
export function formatColumns(items, opts = {}) {
|
|
24
|
+
const indent = opts.indent ?? 2;
|
|
25
|
+
const gutter = opts.gutter ?? 2;
|
|
26
|
+
const maxColWidth = opts.maxColWidth ?? 24;
|
|
27
|
+
const termWidth = opts.width ?? process.stdout.columns ?? 80;
|
|
28
|
+
const cells = items.map((s) => (s.length > maxColWidth ? s.slice(0, maxColWidth - 1) + "…" : s));
|
|
29
|
+
const colWidth = Math.min(Math.max(1, ...cells.map((c) => c.length)), maxColWidth);
|
|
30
|
+
const cols = Math.max(1, Math.floor((termWidth - indent + gutter) / (colWidth + gutter)));
|
|
31
|
+
const lines = [];
|
|
32
|
+
for (let i = 0; i < cells.length; i += cols) {
|
|
33
|
+
const row = cells.slice(i, i + cols);
|
|
34
|
+
const padded = row.map((c, j) => (j === row.length - 1 ? c : c.padEnd(colWidth)));
|
|
35
|
+
lines.push(" ".repeat(indent) + padded.join(" ".repeat(gutter)));
|
|
36
|
+
}
|
|
37
|
+
return lines.join("\n");
|
|
38
|
+
}
|
|
39
|
+
/** Abbreviate the home-directory prefix of an absolute path to `~` (POSIX `/` or Windows `\`). */
|
|
40
|
+
export function abbrevHome(p) {
|
|
41
|
+
const home = homedir();
|
|
42
|
+
if (p === home)
|
|
43
|
+
return "~";
|
|
44
|
+
if (p.startsWith(home + "/") || p.startsWith(home + "\\"))
|
|
45
|
+
return "~" + p.slice(home.length);
|
|
46
|
+
return p;
|
|
47
|
+
}
|
|
48
|
+
/** Tail-truncate a string to width `w`, prefixing an ellipsis when it overflows. */
|
|
49
|
+
export function ellipsizeStart(s, w) {
|
|
50
|
+
return s.length > w ? "…" + s.slice(s.length - w + 1) : s;
|
|
51
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rbbtsn0w/adg",
|
|
3
|
-
"version": "0.3.0-beta.
|
|
3
|
+
"version": "0.3.0-beta.4",
|
|
4
4
|
"description": "Agent Directory Group (ADG) toolkit — two domains: plugins and skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"adg": "node ./bin/adg.ts",
|
|
26
26
|
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json --noCheck && node -e \"require('fs').chmodSync('dist/bin/adg.js',0o755)\"",
|
|
27
27
|
"test": "node --test 'test/**/*.test.ts'",
|
|
28
|
+
"check:vendor-deps": "node scripts/check-vendor-deps.mjs",
|
|
28
29
|
"typecheck": "tsc --noEmit",
|
|
29
30
|
"prepare": "npm run typecheck",
|
|
30
31
|
"prepack": "npm run build"
|
|
@@ -35,12 +36,12 @@
|
|
|
35
36
|
"vendor",
|
|
36
37
|
"docs"
|
|
37
38
|
],
|
|
38
|
-
"comment:dependencies": "Runtime deps below are required only by the vendored skills CLI (vendor/skills)
|
|
39
|
+
"comment:dependencies": "Runtime deps below are required only by the vendored skills CLI (vendor/skills); ADG's own plugins code has zero runtime deps. Root is the single source of truth: each range MUST be >= the floor declared in vendor/skills/package.json, since that is the version the vendored source was authored against. `npm run check:vendor-deps` enforces this and fails on drift.",
|
|
39
40
|
"dependencies": {
|
|
40
|
-
"@clack/prompts": "^0.
|
|
41
|
+
"@clack/prompts": "^0.11.0",
|
|
41
42
|
"@vercel/detect-agent": "^1.2.3",
|
|
42
|
-
"picocolors": "^1.
|
|
43
|
-
"simple-git": "^3.
|
|
43
|
+
"picocolors": "^1.1.1",
|
|
44
|
+
"simple-git": "^3.36.0",
|
|
44
45
|
"xdg-basedir": "^5.1.0",
|
|
45
46
|
"yaml": "^2.8.3"
|
|
46
47
|
},
|