@gmickel/gno 1.37.1 → 1.39.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/assets/skill/README.md +2 -0
- package/browser-extension/artifacts/{gno-browser-clipper-v1.37.1.zip → gno-browser-clipper-v1.39.0.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.39.0.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +1 -1
- package/spec/cli.md +243 -26
- package/spec/output-schemas/agents-mutation.schema.json +108 -0
- package/spec/output-schemas/agents-verify.schema.json +89 -0
- package/src/cli/commands/agents/block.ts +164 -0
- package/src/cli/commands/agents/commands.ts +413 -0
- package/src/cli/commands/agents/engine.ts +417 -0
- package/src/cli/commands/agents/harnesses.ts +298 -0
- package/src/cli/commands/agents/index.ts +35 -0
- package/src/cli/commands/cleanup.ts +8 -2
- package/src/cli/commands/collection/clear-embeddings.ts +6 -1
- package/src/cli/commands/completion/scripts.ts +5 -0
- package/src/cli/commands/doctor-activation.ts +5 -1
- package/src/cli/commands/doctor.ts +72 -2
- package/src/cli/commands/embed.ts +227 -194
- package/src/cli/commands/index-cmd.ts +74 -50
- package/src/cli/commands/init.ts +5 -1
- package/src/cli/commands/profile-apply.ts +5 -1
- package/src/cli/commands/setup-activation.ts +2 -1
- package/src/cli/commands/setup.ts +2 -1
- package/src/cli/commands/shared.ts +5 -1
- package/src/cli/commands/status.ts +5 -1
- package/src/cli/commands/tags.ts +18 -3
- package/src/cli/commands/update.ts +34 -27
- package/src/cli/commands/vec.ts +13 -4
- package/src/cli/errors.ts +3 -2
- package/src/cli/program.ts +449 -194
- package/src/config/defaults.ts +2 -0
- package/src/config/index.ts +3 -0
- package/src/config/types.ts +32 -1
- package/src/core/file-lock.ts +16 -4
- package/src/core/write-lease.ts +354 -0
- package/src/embed/backlog.ts +9 -1
- package/src/embed/retry.ts +116 -3
- package/src/sdk/client.ts +3 -1
- package/src/sdk/embed.ts +8 -3
- package/src/sdk/types.ts +2 -0
- package/src/serve/embed-scheduler.ts +8 -0
- package/src/serve/resident-runtime.ts +5 -1
- package/src/store/sqlite/adapter.ts +28 -4
- package/src/store/sqlite/scoped-index.ts +5 -1
- package/src/store/vector/sqlite-vec.ts +2 -1
- package/browser-extension/artifacts/gno-browser-clipper-v1.37.1.zip.sha256 +0 -1
package/src/cli/program.ts
CHANGED
|
@@ -21,6 +21,14 @@ import {
|
|
|
21
21
|
import { INDEX_NAME_REQUIREMENTS, isValidIndexName } from "../app/index-name";
|
|
22
22
|
import { resolveDepthPolicy } from "../core/depth-policy";
|
|
23
23
|
import { parseAndValidateTagFilter } from "../core/tags";
|
|
24
|
+
import {
|
|
25
|
+
formatWriteLeaseBusyJson,
|
|
26
|
+
formatWriteLeaseBusyMessage,
|
|
27
|
+
isWriteLeaseBusyResult,
|
|
28
|
+
parseLockWaitMs,
|
|
29
|
+
withCliWriteLease,
|
|
30
|
+
type WriteLeaseBusyFailure,
|
|
31
|
+
} from "../core/write-lease";
|
|
24
32
|
import { setColorsEnabled } from "./colors";
|
|
25
33
|
import {
|
|
26
34
|
applyGlobalOptions,
|
|
@@ -221,6 +229,49 @@ function parseCsvValues(raw: unknown): string[] | undefined {
|
|
|
221
229
|
return values.length > 0 ? values : undefined;
|
|
222
230
|
}
|
|
223
231
|
|
|
232
|
+
function addWriteLeaseFlags(command: Command): Command {
|
|
233
|
+
return command
|
|
234
|
+
.option(
|
|
235
|
+
"--lock-wait <duration>",
|
|
236
|
+
"how long to wait for the index write lease (default: 120s)",
|
|
237
|
+
"120s"
|
|
238
|
+
)
|
|
239
|
+
.option("--no-wait", "fail immediately if the index write lease is held");
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function parseWriteLeaseFlags(cmdOpts: Record<string, unknown>): {
|
|
243
|
+
lockWaitMs: number;
|
|
244
|
+
noWait: boolean;
|
|
245
|
+
} {
|
|
246
|
+
const parsed = parseLockWaitMs(cmdOpts.lockWait);
|
|
247
|
+
if (parsed === null) {
|
|
248
|
+
throw new CliError(
|
|
249
|
+
"VALIDATION",
|
|
250
|
+
`Invalid --lock-wait duration: ${String(cmdOpts.lockWait)}. Use seconds ("120"), "120s", or "2m".`
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
lockWaitMs: parsed,
|
|
255
|
+
noWait: cmdOpts.wait === false,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function throwIfWriteLeaseBusy<
|
|
260
|
+
T extends { success: boolean; error?: string; contention?: unknown },
|
|
261
|
+
>(result: T | WriteLeaseBusyFailure, json: boolean): asserts result is T {
|
|
262
|
+
if (!isWriteLeaseBusyResult(result)) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (json) {
|
|
266
|
+
process.stdout.write(
|
|
267
|
+
`${JSON.stringify(formatWriteLeaseBusyJson(result.contention))}\n`
|
|
268
|
+
);
|
|
269
|
+
} else {
|
|
270
|
+
process.stderr.write(`${formatWriteLeaseBusyMessage(result.contention)}\n`);
|
|
271
|
+
}
|
|
272
|
+
throw new CliError("BUSY", result.error, { silent: true });
|
|
273
|
+
}
|
|
274
|
+
|
|
224
275
|
function parseContextInteger(
|
|
225
276
|
name: string,
|
|
226
277
|
value: unknown,
|
|
@@ -313,6 +364,7 @@ export function createProgram(): Command {
|
|
|
313
364
|
wireKnowledgeDeltaCommands(program);
|
|
314
365
|
wireMcpCommand(program);
|
|
315
366
|
wireSkillCommands(program);
|
|
367
|
+
wireAgentsCommands(program);
|
|
316
368
|
wireDaemonCommand(program);
|
|
317
369
|
wireServeCommand(program);
|
|
318
370
|
wireCompletionCommand(program);
|
|
@@ -1505,39 +1557,51 @@ function wireOnboardingCommands(program: Command): void {
|
|
|
1505
1557
|
});
|
|
1506
1558
|
|
|
1507
1559
|
// index - Index collections
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1560
|
+
addWriteLeaseFlags(
|
|
1561
|
+
program
|
|
1562
|
+
.command("index [collection]")
|
|
1563
|
+
.description("Index files from collections")
|
|
1564
|
+
.option("--no-embed", "skip embedding after sync")
|
|
1565
|
+
.option("--git-pull", "run git pull in git repositories")
|
|
1566
|
+
.option("--models-pull", "download models if missing")
|
|
1567
|
+
.option("--json", "JSON output")
|
|
1568
|
+
).action(
|
|
1569
|
+
async (
|
|
1570
|
+
collection: string | undefined,
|
|
1571
|
+
cmdOpts: Record<string, unknown>
|
|
1572
|
+
) => {
|
|
1573
|
+
const globals = getGlobals();
|
|
1574
|
+
const { index, formatIndex } = await import("./commands/index-cmd");
|
|
1575
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
1576
|
+
const opts = {
|
|
1577
|
+
configPath: globals.config,
|
|
1578
|
+
indexName: globals.index,
|
|
1579
|
+
collection,
|
|
1580
|
+
noEmbed: cmdOpts.embed === false,
|
|
1581
|
+
gitPull: Boolean(cmdOpts.gitPull),
|
|
1582
|
+
modelsPull: Boolean(cmdOpts.modelsPull),
|
|
1583
|
+
yes: globals.yes,
|
|
1584
|
+
verbose: globals.verbose,
|
|
1585
|
+
json: getFormat(cmdOpts) === "json",
|
|
1586
|
+
lockWaitMs: lease.lockWaitMs,
|
|
1587
|
+
noWait: lease.noWait,
|
|
1588
|
+
};
|
|
1589
|
+
const result = await index(opts);
|
|
1534
1590
|
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
process.stdout.write(`${formatIndex(result, opts)}\n`);
|
|
1591
|
+
if (!result.success) {
|
|
1592
|
+
throwIfWriteLeaseBusy(result, opts.json);
|
|
1593
|
+
throw new CliError("RUNTIME", result.error ?? "Index failed");
|
|
1539
1594
|
}
|
|
1540
|
-
|
|
1595
|
+
process.stdout.write(`${formatIndex(result, opts)}\n`);
|
|
1596
|
+
if ((result.embedResult?.contentionErrors ?? 0) > 0) {
|
|
1597
|
+
throw new CliError(
|
|
1598
|
+
"BUSY",
|
|
1599
|
+
"Some chunks were deferred by index contention",
|
|
1600
|
+
{ silent: true }
|
|
1601
|
+
);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
);
|
|
1541
1605
|
|
|
1542
1606
|
// audit - Read-only workspace integrity report
|
|
1543
1607
|
program
|
|
@@ -2225,19 +2289,33 @@ function wireManagementCommands(program: Command): void {
|
|
|
2225
2289
|
});
|
|
2226
2290
|
});
|
|
2227
2291
|
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2292
|
+
addWriteLeaseFlags(
|
|
2293
|
+
collectionCmd
|
|
2294
|
+
.command("clear-embeddings <name>")
|
|
2295
|
+
.description("Clear stale or all embeddings for a collection")
|
|
2296
|
+
.option("--all", "remove all embeddings for the collection")
|
|
2297
|
+
.option("--json", "JSON output")
|
|
2298
|
+
).action(async (name: string, cmdOpts: Record<string, unknown>) => {
|
|
2299
|
+
const { collectionClearEmbeddings } = await import("./commands/collection");
|
|
2300
|
+
const json = Boolean(cmdOpts.json);
|
|
2301
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2302
|
+
const result = await withCliWriteLease(
|
|
2303
|
+
{
|
|
2304
|
+
indexName: getGlobals().index,
|
|
2305
|
+
lockWaitMs: lease.lockWaitMs,
|
|
2306
|
+
noWait: lease.noWait,
|
|
2307
|
+
},
|
|
2308
|
+
async () => {
|
|
2309
|
+
await collectionClearEmbeddings(name, {
|
|
2310
|
+
all: Boolean(cmdOpts.all),
|
|
2311
|
+
indexName: getGlobals().index,
|
|
2312
|
+
json,
|
|
2313
|
+
});
|
|
2314
|
+
return { success: true as const };
|
|
2315
|
+
}
|
|
2316
|
+
);
|
|
2317
|
+
throwIfWriteLeaseBusy(result, json);
|
|
2318
|
+
});
|
|
2241
2319
|
|
|
2242
2320
|
const collectionPolicyCmd = collectionCmd
|
|
2243
2321
|
.command("policy")
|
|
@@ -2771,85 +2849,110 @@ function wireManagementCommands(program: Command): void {
|
|
|
2771
2849
|
});
|
|
2772
2850
|
|
|
2773
2851
|
// update - Sync files from disk
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2852
|
+
addWriteLeaseFlags(
|
|
2853
|
+
program
|
|
2854
|
+
.command("update")
|
|
2855
|
+
.description("Sync files from disk into the index")
|
|
2856
|
+
.option("--git-pull", "run git pull in git repositories")
|
|
2857
|
+
.option("--json", "JSON output")
|
|
2858
|
+
).action(async (cmdOpts: Record<string, unknown>) => {
|
|
2859
|
+
const globals = getGlobals();
|
|
2860
|
+
const { update, formatUpdate } = await import("./commands/update");
|
|
2861
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2862
|
+
const opts = {
|
|
2863
|
+
configPath: globals.config,
|
|
2864
|
+
indexName: globals.index,
|
|
2865
|
+
gitPull: Boolean(cmdOpts.gitPull),
|
|
2866
|
+
verbose: globals.verbose,
|
|
2867
|
+
json: getFormat(cmdOpts) === "json",
|
|
2868
|
+
lockWaitMs: lease.lockWaitMs,
|
|
2869
|
+
noWait: lease.noWait,
|
|
2870
|
+
};
|
|
2871
|
+
const result = await update(opts);
|
|
2872
|
+
|
|
2873
|
+
if (!result.success) {
|
|
2874
|
+
throwIfWriteLeaseBusy(result, opts.json);
|
|
2875
|
+
throw new CliError("RUNTIME", result.error ?? "Update failed");
|
|
2876
|
+
}
|
|
2877
|
+
process.stdout.write(`${formatUpdate(result, opts)}\n`);
|
|
2878
|
+
});
|
|
2879
|
+
|
|
2880
|
+
// embed - Generate embeddings
|
|
2881
|
+
addWriteLeaseFlags(
|
|
2882
|
+
program
|
|
2883
|
+
.command("embed [collection]")
|
|
2884
|
+
.description("Generate embeddings for indexed documents")
|
|
2885
|
+
.option("--collection <name>", "restrict to one collection")
|
|
2886
|
+
.option("--model <uri>", "embedding model URI")
|
|
2887
|
+
.option("--batch-size <num>", "batch size", "32")
|
|
2888
|
+
.option("--force", "regenerate all embeddings")
|
|
2889
|
+
.option("--dry-run", "show what would be done")
|
|
2890
|
+
.option("--json", "JSON output")
|
|
2891
|
+
).action(
|
|
2892
|
+
async (
|
|
2893
|
+
collectionArg: string | undefined,
|
|
2894
|
+
cmdOpts: Record<string, unknown>
|
|
2895
|
+
) => {
|
|
2780
2896
|
const globals = getGlobals();
|
|
2781
|
-
const
|
|
2897
|
+
const format = getFormat(cmdOpts);
|
|
2898
|
+
|
|
2899
|
+
const { embed, formatEmbed } = await import("./commands/embed");
|
|
2900
|
+
const collection =
|
|
2901
|
+
collectionArg ?? (cmdOpts.collection as string | undefined);
|
|
2902
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2782
2903
|
const opts = {
|
|
2783
2904
|
configPath: globals.config,
|
|
2784
2905
|
indexName: globals.index,
|
|
2785
|
-
|
|
2906
|
+
collection,
|
|
2907
|
+
model: cmdOpts.model as string | undefined,
|
|
2908
|
+
batchSize: parsePositiveInt("batch-size", cmdOpts.batchSize),
|
|
2909
|
+
force: Boolean(cmdOpts.force),
|
|
2910
|
+
dryRun: Boolean(cmdOpts.dryRun),
|
|
2911
|
+
yes: globals.yes,
|
|
2912
|
+
json: format === "json",
|
|
2786
2913
|
verbose: globals.verbose,
|
|
2787
|
-
|
|
2914
|
+
offline: globals.offline,
|
|
2915
|
+
lockWaitMs: lease.lockWaitMs,
|
|
2916
|
+
noWait: lease.noWait,
|
|
2788
2917
|
};
|
|
2789
|
-
const result = await
|
|
2918
|
+
const result = await embed(opts);
|
|
2790
2919
|
|
|
2791
2920
|
if (!result.success) {
|
|
2792
|
-
|
|
2921
|
+
throwIfWriteLeaseBusy(result, opts.json);
|
|
2922
|
+
throw new CliError("RUNTIME", result.error ?? "Embed failed");
|
|
2793
2923
|
}
|
|
2794
|
-
process.stdout.write(`${
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
.option("--collection <name>", "restrict to one collection")
|
|
2802
|
-
.option("--model <uri>", "embedding model URI")
|
|
2803
|
-
.option("--batch-size <num>", "batch size", "32")
|
|
2804
|
-
.option("--force", "regenerate all embeddings")
|
|
2805
|
-
.option("--dry-run", "show what would be done")
|
|
2806
|
-
.option("--json", "JSON output")
|
|
2807
|
-
.action(
|
|
2808
|
-
async (
|
|
2809
|
-
collectionArg: string | undefined,
|
|
2810
|
-
cmdOpts: Record<string, unknown>
|
|
2811
|
-
) => {
|
|
2812
|
-
const globals = getGlobals();
|
|
2813
|
-
const format = getFormat(cmdOpts);
|
|
2814
|
-
|
|
2815
|
-
const { embed, formatEmbed } = await import("./commands/embed");
|
|
2816
|
-
const collection =
|
|
2817
|
-
collectionArg ?? (cmdOpts.collection as string | undefined);
|
|
2818
|
-
const opts = {
|
|
2819
|
-
configPath: globals.config,
|
|
2820
|
-
indexName: globals.index,
|
|
2821
|
-
collection,
|
|
2822
|
-
model: cmdOpts.model as string | undefined,
|
|
2823
|
-
batchSize: parsePositiveInt("batch-size", cmdOpts.batchSize),
|
|
2824
|
-
force: Boolean(cmdOpts.force),
|
|
2825
|
-
dryRun: Boolean(cmdOpts.dryRun),
|
|
2826
|
-
yes: globals.yes,
|
|
2827
|
-
json: format === "json",
|
|
2828
|
-
verbose: globals.verbose,
|
|
2829
|
-
offline: globals.offline,
|
|
2830
|
-
};
|
|
2831
|
-
const result = await embed(opts);
|
|
2832
|
-
|
|
2833
|
-
if (!result.success) {
|
|
2834
|
-
throw new CliError("RUNTIME", result.error ?? "Embed failed");
|
|
2835
|
-
}
|
|
2836
|
-
process.stdout.write(`${formatEmbed(result, opts)}\n`);
|
|
2924
|
+
process.stdout.write(`${formatEmbed(result, opts)}\n`);
|
|
2925
|
+
if (result.contentionErrors > 0) {
|
|
2926
|
+
throw new CliError(
|
|
2927
|
+
"BUSY",
|
|
2928
|
+
"Some chunks were deferred by index contention",
|
|
2929
|
+
{ silent: true }
|
|
2930
|
+
);
|
|
2837
2931
|
}
|
|
2838
|
-
|
|
2932
|
+
}
|
|
2933
|
+
);
|
|
2839
2934
|
|
|
2840
2935
|
// cleanup - Clean stale data
|
|
2841
|
-
|
|
2842
|
-
.command("cleanup")
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2936
|
+
addWriteLeaseFlags(
|
|
2937
|
+
program.command("cleanup").description("Clean orphaned data from index")
|
|
2938
|
+
).action(async (cmdOpts: Record<string, unknown>) => {
|
|
2939
|
+
const { cleanup, formatCleanup } = await import("./commands/cleanup");
|
|
2940
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2941
|
+
const result = await withCliWriteLease(
|
|
2942
|
+
{
|
|
2943
|
+
indexName: getGlobals().index,
|
|
2944
|
+
lockWaitMs: lease.lockWaitMs,
|
|
2945
|
+
noWait: lease.noWait,
|
|
2946
|
+
},
|
|
2947
|
+
() => cleanup({ indexName: getGlobals().index })
|
|
2948
|
+
);
|
|
2949
|
+
throwIfWriteLeaseBusy(result, false);
|
|
2847
2950
|
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2951
|
+
if (!result.success) {
|
|
2952
|
+
throw new CliError("RUNTIME", result.error ?? "Cleanup failed");
|
|
2953
|
+
}
|
|
2954
|
+
process.stdout.write(`${formatCleanup(result)}\n`);
|
|
2955
|
+
});
|
|
2853
2956
|
|
|
2854
2957
|
// reset - Reset GNO to fresh state
|
|
2855
2958
|
program
|
|
@@ -2879,52 +2982,76 @@ function wireVecCommands(program: Command): void {
|
|
|
2879
2982
|
const vecCmd = program.command("vec").description("Vector index maintenance");
|
|
2880
2983
|
|
|
2881
2984
|
// vec sync
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2985
|
+
addWriteLeaseFlags(
|
|
2986
|
+
vecCmd
|
|
2987
|
+
.command("sync")
|
|
2988
|
+
.description("Sync vec0 index with content_vectors")
|
|
2989
|
+
.option("--json", "JSON output")
|
|
2990
|
+
).action(async (cmdOpts: Record<string, unknown>) => {
|
|
2991
|
+
const format = getFormat(cmdOpts);
|
|
2992
|
+
const globals = getGlobals();
|
|
2889
2993
|
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2994
|
+
const { vecSync, formatVecSync } = await import("./commands/vec");
|
|
2995
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2996
|
+
const result = await withCliWriteLease(
|
|
2997
|
+
{
|
|
2998
|
+
indexName: globals.index,
|
|
2999
|
+
lockWaitMs: lease.lockWaitMs,
|
|
3000
|
+
noWait: lease.noWait,
|
|
3001
|
+
},
|
|
3002
|
+
() =>
|
|
3003
|
+
vecSync({
|
|
3004
|
+
configPath: globals.config,
|
|
3005
|
+
indexName: globals.index,
|
|
3006
|
+
json: format === "json",
|
|
3007
|
+
})
|
|
3008
|
+
);
|
|
3009
|
+
throwIfWriteLeaseBusy(result, format === "json");
|
|
2895
3010
|
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
3011
|
+
if (!result.success) {
|
|
3012
|
+
throw new CliError("RUNTIME", result.error);
|
|
3013
|
+
}
|
|
2899
3014
|
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
3015
|
+
process.stdout.write(
|
|
3016
|
+
`${formatVecSync(result, { json: format === "json" })}\n`
|
|
3017
|
+
);
|
|
3018
|
+
});
|
|
2904
3019
|
|
|
2905
3020
|
// vec rebuild
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
3021
|
+
addWriteLeaseFlags(
|
|
3022
|
+
vecCmd
|
|
3023
|
+
.command("rebuild")
|
|
3024
|
+
.description("Rebuild vec0 index from content_vectors")
|
|
3025
|
+
.option("--json", "JSON output")
|
|
3026
|
+
).action(async (cmdOpts: Record<string, unknown>) => {
|
|
3027
|
+
const format = getFormat(cmdOpts);
|
|
3028
|
+
const globals = getGlobals();
|
|
2913
3029
|
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
3030
|
+
const { vecRebuild, formatVecRebuild } = await import("./commands/vec");
|
|
3031
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
3032
|
+
const result = await withCliWriteLease(
|
|
3033
|
+
{
|
|
3034
|
+
indexName: globals.index,
|
|
3035
|
+
lockWaitMs: lease.lockWaitMs,
|
|
3036
|
+
noWait: lease.noWait,
|
|
3037
|
+
},
|
|
3038
|
+
() =>
|
|
3039
|
+
vecRebuild({
|
|
3040
|
+
configPath: globals.config,
|
|
3041
|
+
indexName: globals.index,
|
|
3042
|
+
json: format === "json",
|
|
3043
|
+
})
|
|
3044
|
+
);
|
|
3045
|
+
throwIfWriteLeaseBusy(result, format === "json");
|
|
2919
3046
|
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
3047
|
+
if (!result.success) {
|
|
3048
|
+
throw new CliError("RUNTIME", result.error);
|
|
3049
|
+
}
|
|
2923
3050
|
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
3051
|
+
process.stdout.write(
|
|
3052
|
+
`${formatVecRebuild(result, { json: format === "json" })}\n`
|
|
3053
|
+
);
|
|
3054
|
+
});
|
|
2928
3055
|
}
|
|
2929
3056
|
|
|
2930
3057
|
function wirePublishCommand(program: Command): void {
|
|
@@ -3194,6 +3321,109 @@ function wireSkillCommands(program: Command): void {
|
|
|
3194
3321
|
});
|
|
3195
3322
|
}
|
|
3196
3323
|
|
|
3324
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
3325
|
+
// Agents Commands (install, update, verify, uninstall)
|
|
3326
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
3327
|
+
|
|
3328
|
+
function wireAgentsCommands(program: Command): void {
|
|
3329
|
+
const agentsCmd = program
|
|
3330
|
+
.command("agents")
|
|
3331
|
+
.description(
|
|
3332
|
+
"Manage the GNO protocol block in global harness instruction files"
|
|
3333
|
+
);
|
|
3334
|
+
|
|
3335
|
+
const targetDescription =
|
|
3336
|
+
"target harness (claude, codex, cursor, opencode, grok, hermes, openclaw, all)";
|
|
3337
|
+
|
|
3338
|
+
const collectExtraDir = (value: string, previous: string[]): string[] => [
|
|
3339
|
+
...previous,
|
|
3340
|
+
value,
|
|
3341
|
+
];
|
|
3342
|
+
|
|
3343
|
+
const parseCommonOpts = async (cmdOpts: Record<string, unknown>) => {
|
|
3344
|
+
const { parseTargetOption } = await import("./commands/agents/commands.js");
|
|
3345
|
+
return {
|
|
3346
|
+
target: parseTargetOption((cmdOpts.target as string) ?? "all"),
|
|
3347
|
+
extraDirs: (cmdOpts.extraDir as string[] | undefined) ?? [],
|
|
3348
|
+
dryRun: Boolean(cmdOpts.dryRun),
|
|
3349
|
+
// The root program also defines a global --json and may consume the
|
|
3350
|
+
// flag; leave undefined here so the runner falls back to globals.
|
|
3351
|
+
json: cmdOpts.json ? true : undefined,
|
|
3352
|
+
};
|
|
3353
|
+
};
|
|
3354
|
+
|
|
3355
|
+
agentsCmd
|
|
3356
|
+
.command("install")
|
|
3357
|
+
.description(
|
|
3358
|
+
"Install the GNO protocol block into detected harnesses' global instruction files"
|
|
3359
|
+
)
|
|
3360
|
+
.option("-t, --target <target>", targetDescription, "all")
|
|
3361
|
+
.option(
|
|
3362
|
+
"--extra-dir <path>",
|
|
3363
|
+
"additional instruction dir (repeatable, for nonstandard layouts)",
|
|
3364
|
+
collectExtraDir,
|
|
3365
|
+
[] as string[]
|
|
3366
|
+
)
|
|
3367
|
+
.option("--dry-run", "print the unified diff and write nothing")
|
|
3368
|
+
.option("--json", "JSON output")
|
|
3369
|
+
.action(async (cmdOpts: Record<string, unknown>) => {
|
|
3370
|
+
const { installAgents } = await import("./commands/agents/commands.js");
|
|
3371
|
+
await installAgents(await parseCommonOpts(cmdOpts), "install");
|
|
3372
|
+
});
|
|
3373
|
+
|
|
3374
|
+
agentsCmd
|
|
3375
|
+
.command("update")
|
|
3376
|
+
.description("Refresh an installed GNO protocol block in place")
|
|
3377
|
+
.option("-t, --target <target>", targetDescription, "all")
|
|
3378
|
+
.option(
|
|
3379
|
+
"--extra-dir <path>",
|
|
3380
|
+
"additional instruction dir (repeatable, for nonstandard layouts)",
|
|
3381
|
+
collectExtraDir,
|
|
3382
|
+
[] as string[]
|
|
3383
|
+
)
|
|
3384
|
+
.option("--dry-run", "print the unified diff and write nothing")
|
|
3385
|
+
.option("--json", "JSON output")
|
|
3386
|
+
.action(async (cmdOpts: Record<string, unknown>) => {
|
|
3387
|
+
const { installAgents } = await import("./commands/agents/commands.js");
|
|
3388
|
+
await installAgents(await parseCommonOpts(cmdOpts), "update");
|
|
3389
|
+
});
|
|
3390
|
+
|
|
3391
|
+
agentsCmd
|
|
3392
|
+
.command("verify")
|
|
3393
|
+
.description(
|
|
3394
|
+
"Verify installed GNO protocol blocks (one block, version + hash)"
|
|
3395
|
+
)
|
|
3396
|
+
.option("-t, --target <target>", targetDescription, "all")
|
|
3397
|
+
.option(
|
|
3398
|
+
"--extra-dir <path>",
|
|
3399
|
+
"additional instruction dir (repeatable, for nonstandard layouts)",
|
|
3400
|
+
collectExtraDir,
|
|
3401
|
+
[] as string[]
|
|
3402
|
+
)
|
|
3403
|
+
.option("--json", "JSON output")
|
|
3404
|
+
.action(async (cmdOpts: Record<string, unknown>) => {
|
|
3405
|
+
const { verifyAgents } = await import("./commands/agents/commands.js");
|
|
3406
|
+
await verifyAgents(await parseCommonOpts(cmdOpts));
|
|
3407
|
+
});
|
|
3408
|
+
|
|
3409
|
+
agentsCmd
|
|
3410
|
+
.command("uninstall")
|
|
3411
|
+
.description("Remove the GNO protocol block and markers from harness files")
|
|
3412
|
+
.option("-t, --target <target>", targetDescription, "all")
|
|
3413
|
+
.option(
|
|
3414
|
+
"--extra-dir <path>",
|
|
3415
|
+
"additional instruction dir (repeatable, for nonstandard layouts)",
|
|
3416
|
+
collectExtraDir,
|
|
3417
|
+
[] as string[]
|
|
3418
|
+
)
|
|
3419
|
+
.option("--dry-run", "print the unified diff and write nothing")
|
|
3420
|
+
.option("--json", "JSON output")
|
|
3421
|
+
.action(async (cmdOpts: Record<string, unknown>) => {
|
|
3422
|
+
const { uninstallAgents } = await import("./commands/agents/commands.js");
|
|
3423
|
+
await uninstallAgents(await parseCommonOpts(cmdOpts));
|
|
3424
|
+
});
|
|
3425
|
+
}
|
|
3426
|
+
|
|
3197
3427
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
3198
3428
|
// Tags Commands (list, add, rm)
|
|
3199
3429
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -3217,6 +3447,7 @@ function wireTagsCommands(program: Command): void {
|
|
|
3217
3447
|
const { tagsList, formatTagsList } = await import("./commands/tags");
|
|
3218
3448
|
const result = await tagsList({
|
|
3219
3449
|
configPath: globals.config,
|
|
3450
|
+
indexName: globals.index,
|
|
3220
3451
|
collection: cmdOpts.collection as string | undefined,
|
|
3221
3452
|
prefix: cmdOpts.prefix as string | undefined,
|
|
3222
3453
|
json: format === "json",
|
|
@@ -3238,62 +3469,86 @@ function wireTagsCommands(program: Command): void {
|
|
|
3238
3469
|
});
|
|
3239
3470
|
|
|
3240
3471
|
// tags add <doc> <tag>
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
const { tagsAdd, formatTagsAdd } = await import("./commands/tags");
|
|
3251
|
-
const result = await tagsAdd(doc, tag, {
|
|
3252
|
-
configPath: globals.config,
|
|
3253
|
-
json: format === "json",
|
|
3254
|
-
});
|
|
3472
|
+
addWriteLeaseFlags(
|
|
3473
|
+
tagsCmd
|
|
3474
|
+
.command("add <doc> <tag>")
|
|
3475
|
+
.description("Add a tag to a document")
|
|
3476
|
+
.option("--json", "JSON output")
|
|
3477
|
+
).action(
|
|
3478
|
+
async (doc: string, tag: string, cmdOpts: Record<string, unknown>) => {
|
|
3479
|
+
const format = getFormat(cmdOpts);
|
|
3480
|
+
const globals = getGlobals();
|
|
3255
3481
|
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3482
|
+
const { tagsAdd, formatTagsAdd } = await import("./commands/tags");
|
|
3483
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
3484
|
+
const result = await withCliWriteLease(
|
|
3485
|
+
{
|
|
3486
|
+
indexName: globals.index,
|
|
3487
|
+
lockWaitMs: lease.lockWaitMs,
|
|
3488
|
+
noWait: lease.noWait,
|
|
3489
|
+
},
|
|
3490
|
+
() =>
|
|
3491
|
+
tagsAdd(doc, tag, {
|
|
3492
|
+
configPath: globals.config,
|
|
3493
|
+
indexName: globals.index,
|
|
3494
|
+
json: format === "json",
|
|
3495
|
+
})
|
|
3496
|
+
);
|
|
3497
|
+
throwIfWriteLeaseBusy(result, format === "json");
|
|
3262
3498
|
|
|
3263
|
-
|
|
3264
|
-
|
|
3499
|
+
if (!result.success) {
|
|
3500
|
+
throw new CliError(
|
|
3501
|
+
result.isValidation ? "VALIDATION" : "RUNTIME",
|
|
3502
|
+
result.error
|
|
3265
3503
|
);
|
|
3266
3504
|
}
|
|
3267
|
-
);
|
|
3268
3505
|
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
.action(
|
|
3275
|
-
async (doc: string, tag: string, cmdOpts: Record<string, unknown>) => {
|
|
3276
|
-
const format = getFormat(cmdOpts);
|
|
3277
|
-
const globals = getGlobals();
|
|
3506
|
+
process.stdout.write(
|
|
3507
|
+
`${formatTagsAdd(result, { json: format === "json" })}\n`
|
|
3508
|
+
);
|
|
3509
|
+
}
|
|
3510
|
+
);
|
|
3278
3511
|
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3512
|
+
// tags rm <doc> <tag>
|
|
3513
|
+
addWriteLeaseFlags(
|
|
3514
|
+
tagsCmd
|
|
3515
|
+
.command("rm <doc> <tag>")
|
|
3516
|
+
.description("Remove a tag from a document")
|
|
3517
|
+
.option("--json", "JSON output")
|
|
3518
|
+
).action(
|
|
3519
|
+
async (doc: string, tag: string, cmdOpts: Record<string, unknown>) => {
|
|
3520
|
+
const format = getFormat(cmdOpts);
|
|
3521
|
+
const globals = getGlobals();
|
|
3284
3522
|
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3523
|
+
const { tagsRm, formatTagsRm } = await import("./commands/tags");
|
|
3524
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
3525
|
+
const result = await withCliWriteLease(
|
|
3526
|
+
{
|
|
3527
|
+
indexName: globals.index,
|
|
3528
|
+
lockWaitMs: lease.lockWaitMs,
|
|
3529
|
+
noWait: lease.noWait,
|
|
3530
|
+
},
|
|
3531
|
+
() =>
|
|
3532
|
+
tagsRm(doc, tag, {
|
|
3533
|
+
configPath: globals.config,
|
|
3534
|
+
indexName: globals.index,
|
|
3535
|
+
json: format === "json",
|
|
3536
|
+
})
|
|
3537
|
+
);
|
|
3538
|
+
throwIfWriteLeaseBusy(result, format === "json");
|
|
3291
3539
|
|
|
3292
|
-
|
|
3293
|
-
|
|
3540
|
+
if (!result.success) {
|
|
3541
|
+
throw new CliError(
|
|
3542
|
+
result.isValidation ? "VALIDATION" : "RUNTIME",
|
|
3543
|
+
result.error
|
|
3294
3544
|
);
|
|
3295
3545
|
}
|
|
3296
|
-
|
|
3546
|
+
|
|
3547
|
+
process.stdout.write(
|
|
3548
|
+
`${formatTagsRm(result, { json: format === "json" })}\n`
|
|
3549
|
+
);
|
|
3550
|
+
}
|
|
3551
|
+
);
|
|
3297
3552
|
}
|
|
3298
3553
|
|
|
3299
3554
|
// ─────────────────────────────────────────────────────────────────────────────
|