@gmickel/gno 1.37.0 → 1.38.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/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/{gno-browser-clipper-v1.37.0.zip → gno-browser-clipper-v1.38.0.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.38.0.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +1 -1
- package/spec/cli.md +35 -15
- package/src/cli/commands/cleanup.ts +8 -2
- package/src/cli/commands/collection/clear-embeddings.ts +6 -1
- 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 +345 -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/serve/spa-production-build.ts +53 -7
- 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.0.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,
|
|
@@ -1505,39 +1556,51 @@ function wireOnboardingCommands(program: Command): void {
|
|
|
1505
1556
|
});
|
|
1506
1557
|
|
|
1507
1558
|
// 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
|
-
|
|
1559
|
+
addWriteLeaseFlags(
|
|
1560
|
+
program
|
|
1561
|
+
.command("index [collection]")
|
|
1562
|
+
.description("Index files from collections")
|
|
1563
|
+
.option("--no-embed", "skip embedding after sync")
|
|
1564
|
+
.option("--git-pull", "run git pull in git repositories")
|
|
1565
|
+
.option("--models-pull", "download models if missing")
|
|
1566
|
+
.option("--json", "JSON output")
|
|
1567
|
+
).action(
|
|
1568
|
+
async (
|
|
1569
|
+
collection: string | undefined,
|
|
1570
|
+
cmdOpts: Record<string, unknown>
|
|
1571
|
+
) => {
|
|
1572
|
+
const globals = getGlobals();
|
|
1573
|
+
const { index, formatIndex } = await import("./commands/index-cmd");
|
|
1574
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
1575
|
+
const opts = {
|
|
1576
|
+
configPath: globals.config,
|
|
1577
|
+
indexName: globals.index,
|
|
1578
|
+
collection,
|
|
1579
|
+
noEmbed: cmdOpts.embed === false,
|
|
1580
|
+
gitPull: Boolean(cmdOpts.gitPull),
|
|
1581
|
+
modelsPull: Boolean(cmdOpts.modelsPull),
|
|
1582
|
+
yes: globals.yes,
|
|
1583
|
+
verbose: globals.verbose,
|
|
1584
|
+
json: getFormat(cmdOpts) === "json",
|
|
1585
|
+
lockWaitMs: lease.lockWaitMs,
|
|
1586
|
+
noWait: lease.noWait,
|
|
1587
|
+
};
|
|
1588
|
+
const result = await index(opts);
|
|
1534
1589
|
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
process.stdout.write(`${formatIndex(result, opts)}\n`);
|
|
1590
|
+
if (!result.success) {
|
|
1591
|
+
throwIfWriteLeaseBusy(result, opts.json);
|
|
1592
|
+
throw new CliError("RUNTIME", result.error ?? "Index failed");
|
|
1539
1593
|
}
|
|
1540
|
-
|
|
1594
|
+
process.stdout.write(`${formatIndex(result, opts)}\n`);
|
|
1595
|
+
if ((result.embedResult?.contentionErrors ?? 0) > 0) {
|
|
1596
|
+
throw new CliError(
|
|
1597
|
+
"BUSY",
|
|
1598
|
+
"Some chunks were deferred by index contention",
|
|
1599
|
+
{ silent: true }
|
|
1600
|
+
);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
);
|
|
1541
1604
|
|
|
1542
1605
|
// audit - Read-only workspace integrity report
|
|
1543
1606
|
program
|
|
@@ -2225,19 +2288,33 @@ function wireManagementCommands(program: Command): void {
|
|
|
2225
2288
|
});
|
|
2226
2289
|
});
|
|
2227
2290
|
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2291
|
+
addWriteLeaseFlags(
|
|
2292
|
+
collectionCmd
|
|
2293
|
+
.command("clear-embeddings <name>")
|
|
2294
|
+
.description("Clear stale or all embeddings for a collection")
|
|
2295
|
+
.option("--all", "remove all embeddings for the collection")
|
|
2296
|
+
.option("--json", "JSON output")
|
|
2297
|
+
).action(async (name: string, cmdOpts: Record<string, unknown>) => {
|
|
2298
|
+
const { collectionClearEmbeddings } = await import("./commands/collection");
|
|
2299
|
+
const json = Boolean(cmdOpts.json);
|
|
2300
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2301
|
+
const result = await withCliWriteLease(
|
|
2302
|
+
{
|
|
2303
|
+
indexName: getGlobals().index,
|
|
2304
|
+
lockWaitMs: lease.lockWaitMs,
|
|
2305
|
+
noWait: lease.noWait,
|
|
2306
|
+
},
|
|
2307
|
+
async () => {
|
|
2308
|
+
await collectionClearEmbeddings(name, {
|
|
2309
|
+
all: Boolean(cmdOpts.all),
|
|
2310
|
+
indexName: getGlobals().index,
|
|
2311
|
+
json,
|
|
2312
|
+
});
|
|
2313
|
+
return { success: true as const };
|
|
2314
|
+
}
|
|
2315
|
+
);
|
|
2316
|
+
throwIfWriteLeaseBusy(result, json);
|
|
2317
|
+
});
|
|
2241
2318
|
|
|
2242
2319
|
const collectionPolicyCmd = collectionCmd
|
|
2243
2320
|
.command("policy")
|
|
@@ -2771,85 +2848,110 @@ function wireManagementCommands(program: Command): void {
|
|
|
2771
2848
|
});
|
|
2772
2849
|
|
|
2773
2850
|
// update - Sync files from disk
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2851
|
+
addWriteLeaseFlags(
|
|
2852
|
+
program
|
|
2853
|
+
.command("update")
|
|
2854
|
+
.description("Sync files from disk into the index")
|
|
2855
|
+
.option("--git-pull", "run git pull in git repositories")
|
|
2856
|
+
.option("--json", "JSON output")
|
|
2857
|
+
).action(async (cmdOpts: Record<string, unknown>) => {
|
|
2858
|
+
const globals = getGlobals();
|
|
2859
|
+
const { update, formatUpdate } = await import("./commands/update");
|
|
2860
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2861
|
+
const opts = {
|
|
2862
|
+
configPath: globals.config,
|
|
2863
|
+
indexName: globals.index,
|
|
2864
|
+
gitPull: Boolean(cmdOpts.gitPull),
|
|
2865
|
+
verbose: globals.verbose,
|
|
2866
|
+
json: getFormat(cmdOpts) === "json",
|
|
2867
|
+
lockWaitMs: lease.lockWaitMs,
|
|
2868
|
+
noWait: lease.noWait,
|
|
2869
|
+
};
|
|
2870
|
+
const result = await update(opts);
|
|
2871
|
+
|
|
2872
|
+
if (!result.success) {
|
|
2873
|
+
throwIfWriteLeaseBusy(result, opts.json);
|
|
2874
|
+
throw new CliError("RUNTIME", result.error ?? "Update failed");
|
|
2875
|
+
}
|
|
2876
|
+
process.stdout.write(`${formatUpdate(result, opts)}\n`);
|
|
2877
|
+
});
|
|
2878
|
+
|
|
2879
|
+
// embed - Generate embeddings
|
|
2880
|
+
addWriteLeaseFlags(
|
|
2881
|
+
program
|
|
2882
|
+
.command("embed [collection]")
|
|
2883
|
+
.description("Generate embeddings for indexed documents")
|
|
2884
|
+
.option("--collection <name>", "restrict to one collection")
|
|
2885
|
+
.option("--model <uri>", "embedding model URI")
|
|
2886
|
+
.option("--batch-size <num>", "batch size", "32")
|
|
2887
|
+
.option("--force", "regenerate all embeddings")
|
|
2888
|
+
.option("--dry-run", "show what would be done")
|
|
2889
|
+
.option("--json", "JSON output")
|
|
2890
|
+
).action(
|
|
2891
|
+
async (
|
|
2892
|
+
collectionArg: string | undefined,
|
|
2893
|
+
cmdOpts: Record<string, unknown>
|
|
2894
|
+
) => {
|
|
2780
2895
|
const globals = getGlobals();
|
|
2781
|
-
const
|
|
2896
|
+
const format = getFormat(cmdOpts);
|
|
2897
|
+
|
|
2898
|
+
const { embed, formatEmbed } = await import("./commands/embed");
|
|
2899
|
+
const collection =
|
|
2900
|
+
collectionArg ?? (cmdOpts.collection as string | undefined);
|
|
2901
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2782
2902
|
const opts = {
|
|
2783
2903
|
configPath: globals.config,
|
|
2784
2904
|
indexName: globals.index,
|
|
2785
|
-
|
|
2905
|
+
collection,
|
|
2906
|
+
model: cmdOpts.model as string | undefined,
|
|
2907
|
+
batchSize: parsePositiveInt("batch-size", cmdOpts.batchSize),
|
|
2908
|
+
force: Boolean(cmdOpts.force),
|
|
2909
|
+
dryRun: Boolean(cmdOpts.dryRun),
|
|
2910
|
+
yes: globals.yes,
|
|
2911
|
+
json: format === "json",
|
|
2786
2912
|
verbose: globals.verbose,
|
|
2787
|
-
|
|
2913
|
+
offline: globals.offline,
|
|
2914
|
+
lockWaitMs: lease.lockWaitMs,
|
|
2915
|
+
noWait: lease.noWait,
|
|
2788
2916
|
};
|
|
2789
|
-
const result = await
|
|
2917
|
+
const result = await embed(opts);
|
|
2790
2918
|
|
|
2791
2919
|
if (!result.success) {
|
|
2792
|
-
|
|
2920
|
+
throwIfWriteLeaseBusy(result, opts.json);
|
|
2921
|
+
throw new CliError("RUNTIME", result.error ?? "Embed failed");
|
|
2793
2922
|
}
|
|
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`);
|
|
2923
|
+
process.stdout.write(`${formatEmbed(result, opts)}\n`);
|
|
2924
|
+
if (result.contentionErrors > 0) {
|
|
2925
|
+
throw new CliError(
|
|
2926
|
+
"BUSY",
|
|
2927
|
+
"Some chunks were deferred by index contention",
|
|
2928
|
+
{ silent: true }
|
|
2929
|
+
);
|
|
2837
2930
|
}
|
|
2838
|
-
|
|
2931
|
+
}
|
|
2932
|
+
);
|
|
2839
2933
|
|
|
2840
2934
|
// cleanup - Clean stale data
|
|
2841
|
-
|
|
2842
|
-
.command("cleanup")
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2935
|
+
addWriteLeaseFlags(
|
|
2936
|
+
program.command("cleanup").description("Clean orphaned data from index")
|
|
2937
|
+
).action(async (cmdOpts: Record<string, unknown>) => {
|
|
2938
|
+
const { cleanup, formatCleanup } = await import("./commands/cleanup");
|
|
2939
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2940
|
+
const result = await withCliWriteLease(
|
|
2941
|
+
{
|
|
2942
|
+
indexName: getGlobals().index,
|
|
2943
|
+
lockWaitMs: lease.lockWaitMs,
|
|
2944
|
+
noWait: lease.noWait,
|
|
2945
|
+
},
|
|
2946
|
+
() => cleanup({ indexName: getGlobals().index })
|
|
2947
|
+
);
|
|
2948
|
+
throwIfWriteLeaseBusy(result, false);
|
|
2847
2949
|
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2950
|
+
if (!result.success) {
|
|
2951
|
+
throw new CliError("RUNTIME", result.error ?? "Cleanup failed");
|
|
2952
|
+
}
|
|
2953
|
+
process.stdout.write(`${formatCleanup(result)}\n`);
|
|
2954
|
+
});
|
|
2853
2955
|
|
|
2854
2956
|
// reset - Reset GNO to fresh state
|
|
2855
2957
|
program
|
|
@@ -2879,52 +2981,76 @@ function wireVecCommands(program: Command): void {
|
|
|
2879
2981
|
const vecCmd = program.command("vec").description("Vector index maintenance");
|
|
2880
2982
|
|
|
2881
2983
|
// vec sync
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2984
|
+
addWriteLeaseFlags(
|
|
2985
|
+
vecCmd
|
|
2986
|
+
.command("sync")
|
|
2987
|
+
.description("Sync vec0 index with content_vectors")
|
|
2988
|
+
.option("--json", "JSON output")
|
|
2989
|
+
).action(async (cmdOpts: Record<string, unknown>) => {
|
|
2990
|
+
const format = getFormat(cmdOpts);
|
|
2991
|
+
const globals = getGlobals();
|
|
2889
2992
|
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2993
|
+
const { vecSync, formatVecSync } = await import("./commands/vec");
|
|
2994
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
2995
|
+
const result = await withCliWriteLease(
|
|
2996
|
+
{
|
|
2997
|
+
indexName: globals.index,
|
|
2998
|
+
lockWaitMs: lease.lockWaitMs,
|
|
2999
|
+
noWait: lease.noWait,
|
|
3000
|
+
},
|
|
3001
|
+
() =>
|
|
3002
|
+
vecSync({
|
|
3003
|
+
configPath: globals.config,
|
|
3004
|
+
indexName: globals.index,
|
|
3005
|
+
json: format === "json",
|
|
3006
|
+
})
|
|
3007
|
+
);
|
|
3008
|
+
throwIfWriteLeaseBusy(result, format === "json");
|
|
2895
3009
|
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
3010
|
+
if (!result.success) {
|
|
3011
|
+
throw new CliError("RUNTIME", result.error);
|
|
3012
|
+
}
|
|
2899
3013
|
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
3014
|
+
process.stdout.write(
|
|
3015
|
+
`${formatVecSync(result, { json: format === "json" })}\n`
|
|
3016
|
+
);
|
|
3017
|
+
});
|
|
2904
3018
|
|
|
2905
3019
|
// vec rebuild
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
3020
|
+
addWriteLeaseFlags(
|
|
3021
|
+
vecCmd
|
|
3022
|
+
.command("rebuild")
|
|
3023
|
+
.description("Rebuild vec0 index from content_vectors")
|
|
3024
|
+
.option("--json", "JSON output")
|
|
3025
|
+
).action(async (cmdOpts: Record<string, unknown>) => {
|
|
3026
|
+
const format = getFormat(cmdOpts);
|
|
3027
|
+
const globals = getGlobals();
|
|
2913
3028
|
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
3029
|
+
const { vecRebuild, formatVecRebuild } = await import("./commands/vec");
|
|
3030
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
3031
|
+
const result = await withCliWriteLease(
|
|
3032
|
+
{
|
|
3033
|
+
indexName: globals.index,
|
|
3034
|
+
lockWaitMs: lease.lockWaitMs,
|
|
3035
|
+
noWait: lease.noWait,
|
|
3036
|
+
},
|
|
3037
|
+
() =>
|
|
3038
|
+
vecRebuild({
|
|
3039
|
+
configPath: globals.config,
|
|
3040
|
+
indexName: globals.index,
|
|
3041
|
+
json: format === "json",
|
|
3042
|
+
})
|
|
3043
|
+
);
|
|
3044
|
+
throwIfWriteLeaseBusy(result, format === "json");
|
|
2919
3045
|
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
3046
|
+
if (!result.success) {
|
|
3047
|
+
throw new CliError("RUNTIME", result.error);
|
|
3048
|
+
}
|
|
2923
3049
|
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
3050
|
+
process.stdout.write(
|
|
3051
|
+
`${formatVecRebuild(result, { json: format === "json" })}\n`
|
|
3052
|
+
);
|
|
3053
|
+
});
|
|
2928
3054
|
}
|
|
2929
3055
|
|
|
2930
3056
|
function wirePublishCommand(program: Command): void {
|
|
@@ -3217,6 +3343,7 @@ function wireTagsCommands(program: Command): void {
|
|
|
3217
3343
|
const { tagsList, formatTagsList } = await import("./commands/tags");
|
|
3218
3344
|
const result = await tagsList({
|
|
3219
3345
|
configPath: globals.config,
|
|
3346
|
+
indexName: globals.index,
|
|
3220
3347
|
collection: cmdOpts.collection as string | undefined,
|
|
3221
3348
|
prefix: cmdOpts.prefix as string | undefined,
|
|
3222
3349
|
json: format === "json",
|
|
@@ -3238,62 +3365,86 @@ function wireTagsCommands(program: Command): void {
|
|
|
3238
3365
|
});
|
|
3239
3366
|
|
|
3240
3367
|
// 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
|
-
});
|
|
3368
|
+
addWriteLeaseFlags(
|
|
3369
|
+
tagsCmd
|
|
3370
|
+
.command("add <doc> <tag>")
|
|
3371
|
+
.description("Add a tag to a document")
|
|
3372
|
+
.option("--json", "JSON output")
|
|
3373
|
+
).action(
|
|
3374
|
+
async (doc: string, tag: string, cmdOpts: Record<string, unknown>) => {
|
|
3375
|
+
const format = getFormat(cmdOpts);
|
|
3376
|
+
const globals = getGlobals();
|
|
3255
3377
|
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3378
|
+
const { tagsAdd, formatTagsAdd } = await import("./commands/tags");
|
|
3379
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
3380
|
+
const result = await withCliWriteLease(
|
|
3381
|
+
{
|
|
3382
|
+
indexName: globals.index,
|
|
3383
|
+
lockWaitMs: lease.lockWaitMs,
|
|
3384
|
+
noWait: lease.noWait,
|
|
3385
|
+
},
|
|
3386
|
+
() =>
|
|
3387
|
+
tagsAdd(doc, tag, {
|
|
3388
|
+
configPath: globals.config,
|
|
3389
|
+
indexName: globals.index,
|
|
3390
|
+
json: format === "json",
|
|
3391
|
+
})
|
|
3392
|
+
);
|
|
3393
|
+
throwIfWriteLeaseBusy(result, format === "json");
|
|
3262
3394
|
|
|
3263
|
-
|
|
3264
|
-
|
|
3395
|
+
if (!result.success) {
|
|
3396
|
+
throw new CliError(
|
|
3397
|
+
result.isValidation ? "VALIDATION" : "RUNTIME",
|
|
3398
|
+
result.error
|
|
3265
3399
|
);
|
|
3266
3400
|
}
|
|
3267
|
-
);
|
|
3268
3401
|
|
|
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();
|
|
3402
|
+
process.stdout.write(
|
|
3403
|
+
`${formatTagsAdd(result, { json: format === "json" })}\n`
|
|
3404
|
+
);
|
|
3405
|
+
}
|
|
3406
|
+
);
|
|
3278
3407
|
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3408
|
+
// tags rm <doc> <tag>
|
|
3409
|
+
addWriteLeaseFlags(
|
|
3410
|
+
tagsCmd
|
|
3411
|
+
.command("rm <doc> <tag>")
|
|
3412
|
+
.description("Remove a tag from a document")
|
|
3413
|
+
.option("--json", "JSON output")
|
|
3414
|
+
).action(
|
|
3415
|
+
async (doc: string, tag: string, cmdOpts: Record<string, unknown>) => {
|
|
3416
|
+
const format = getFormat(cmdOpts);
|
|
3417
|
+
const globals = getGlobals();
|
|
3284
3418
|
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3419
|
+
const { tagsRm, formatTagsRm } = await import("./commands/tags");
|
|
3420
|
+
const lease = parseWriteLeaseFlags(cmdOpts);
|
|
3421
|
+
const result = await withCliWriteLease(
|
|
3422
|
+
{
|
|
3423
|
+
indexName: globals.index,
|
|
3424
|
+
lockWaitMs: lease.lockWaitMs,
|
|
3425
|
+
noWait: lease.noWait,
|
|
3426
|
+
},
|
|
3427
|
+
() =>
|
|
3428
|
+
tagsRm(doc, tag, {
|
|
3429
|
+
configPath: globals.config,
|
|
3430
|
+
indexName: globals.index,
|
|
3431
|
+
json: format === "json",
|
|
3432
|
+
})
|
|
3433
|
+
);
|
|
3434
|
+
throwIfWriteLeaseBusy(result, format === "json");
|
|
3291
3435
|
|
|
3292
|
-
|
|
3293
|
-
|
|
3436
|
+
if (!result.success) {
|
|
3437
|
+
throw new CliError(
|
|
3438
|
+
result.isValidation ? "VALIDATION" : "RUNTIME",
|
|
3439
|
+
result.error
|
|
3294
3440
|
);
|
|
3295
3441
|
}
|
|
3296
|
-
|
|
3442
|
+
|
|
3443
|
+
process.stdout.write(
|
|
3444
|
+
`${formatTagsRm(result, { json: format === "json" })}\n`
|
|
3445
|
+
);
|
|
3446
|
+
}
|
|
3447
|
+
);
|
|
3297
3448
|
}
|
|
3298
3449
|
|
|
3299
3450
|
// ─────────────────────────────────────────────────────────────────────────────
|
package/src/config/defaults.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import {
|
|
8
8
|
CONFIG_VERSION,
|
|
9
9
|
type Config,
|
|
10
|
+
DEFAULT_BUSY_TIMEOUT_MS,
|
|
10
11
|
DEFAULT_FTS_TOKENIZER,
|
|
11
12
|
PROJECT_AFFINITY_MAX_CONTRIBUTION,
|
|
12
13
|
} from "./types";
|
|
@@ -19,6 +20,7 @@ export function createDefaultConfig(): Config {
|
|
|
19
20
|
return {
|
|
20
21
|
version: CONFIG_VERSION,
|
|
21
22
|
ftsTokenizer: DEFAULT_FTS_TOKENIZER,
|
|
23
|
+
busyTimeoutMs: DEFAULT_BUSY_TIMEOUT_MS,
|
|
22
24
|
collections: [],
|
|
23
25
|
contexts: [],
|
|
24
26
|
contentTypes: [],
|
package/src/config/index.ts
CHANGED
|
@@ -59,6 +59,7 @@ export {
|
|
|
59
59
|
CollectionSchema,
|
|
60
60
|
type Config,
|
|
61
61
|
ConfigSchema,
|
|
62
|
+
DEFAULT_BUSY_TIMEOUT_MS,
|
|
62
63
|
DEFAULT_EGRESS_POLICY,
|
|
63
64
|
DEFAULT_SOURCE_AVAILABILITY,
|
|
64
65
|
HttpGatewayConfigSchema,
|
|
@@ -83,6 +84,8 @@ export {
|
|
|
83
84
|
type FtsTokenizer,
|
|
84
85
|
getCollectionFromScope,
|
|
85
86
|
isValidLanguageHint,
|
|
87
|
+
MAX_BUSY_TIMEOUT_MS,
|
|
88
|
+
MIN_BUSY_TIMEOUT_MS,
|
|
86
89
|
parseScope,
|
|
87
90
|
resolveConfiguredEgressPolicy,
|
|
88
91
|
SOURCE_AVAILABILITY_MODES,
|