@taurgis/bonsai 1.0.5 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -12
- package/agents/agents/official-docs-researcher.agent.md +15 -26
- package/agents/agents/salesforce-docs-researcher.agent.md +17 -35
- package/agents/hooks/README.md +2 -9
- package/agents/hooks/claude-code/hooks/bonsai-web-fetch.sh +1 -1
- package/agents/hooks/codex/hooks/bonsai-user-prompt-context.sh +1 -1
- package/agents/hooks/codex/hooks/bonsai-web-fetch.sh +1 -1
- package/agents/hooks/cursor/hooks/bonsai-web-fetch.sh +1 -1
- package/agents/hooks/github-copilot/bonsai-web-fetch.sh +1 -1
- package/agents/instructions/salesforce-research.instructions.md +7 -6
- package/agents/instructions/web-research.instructions.md +3 -2
- package/agents/skills/web-research/SKILL.md +24 -32
- package/bin/cli.mjs +44 -14
- package/dist/base-command.d.ts +17 -1
- package/dist/base-command.js +70 -9
- package/dist/commands/config/base.d.ts +2 -0
- package/dist/commands/config/base.js +15 -1
- package/dist/commands/config/get.d.ts +1 -1
- package/dist/commands/config/get.js +4 -5
- package/dist/commands/config/index.d.ts +12 -0
- package/dist/commands/config/index.js +34 -0
- package/dist/commands/config/list.js +2 -2
- package/dist/commands/config/set.js +18 -12
- package/dist/commands/config/unset.d.ts +1 -1
- package/dist/commands/config/unset.js +9 -6
- package/dist/commands/fetch.d.ts +2 -0
- package/dist/commands/fetch.js +69 -45
- package/dist/commands/import.d.ts +3 -0
- package/dist/commands/import.js +91 -53
- package/dist/commands/inspect.d.ts +8 -0
- package/dist/commands/inspect.js +59 -30
- package/dist/commands/list.d.ts +5 -3
- package/dist/commands/list.js +60 -35
- package/dist/commands/prune.d.ts +2 -1
- package/dist/commands/prune.js +62 -19
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.js +84 -26
- package/dist/commands.d.ts +2 -2
- package/dist/commands.js +2 -2
- package/dist/hooks/command-not-found/suggest.d.ts +7 -1
- package/dist/hooks/command-not-found/suggest.js +100 -46
- package/dist/lib/argv.d.ts +10 -0
- package/dist/lib/argv.js +97 -0
- package/dist/lib/color.d.ts +20 -0
- package/dist/lib/color.js +36 -0
- package/dist/lib/envelope.d.ts +36 -0
- package/dist/lib/envelope.js +82 -0
- package/dist/lib/help-preflight.d.ts +15 -0
- package/dist/lib/help-preflight.js +81 -0
- package/dist/lib/json-meta.d.ts +10 -0
- package/dist/lib/json-meta.js +98 -0
- package/dist/lib/limit-flag.d.ts +1 -0
- package/dist/lib/limit-flag.js +24 -0
- package/dist/lib/research/{search-index.d.ts → artifact-index.d.ts} +5 -5
- package/dist/lib/research/{search-index.js → artifact-index.js} +10 -10
- package/dist/lib/research/browser.d.ts +0 -8
- package/dist/lib/research/browser.js +20 -43
- package/dist/lib/research/regression.d.ts +18 -0
- package/dist/lib/research/regression.js +47 -0
- package/dist/lib/research/revalidate.js +3 -1
- package/dist/lib/research/schema.d.ts +5 -2
- package/dist/lib/research/schema.js +12 -1
- package/dist/lib/research/storage.d.ts +0 -1
- package/dist/lib/research/storage.js +15 -13
- package/dist/lib/research/url.d.ts +22 -0
- package/dist/lib/research/url.js +63 -1
- package/dist/lib/text.d.ts +5 -1
- package/dist/lib/text.js +11 -1
- package/dist/sites/coveo.d.ts +7 -0
- package/dist/sites/coveo.js +33 -0
- package/dist/sites/index.js +1 -2
- package/dist/sites/salesforce/fetch-page.js +1 -1
- package/dist/sites/salesforce/index.js +3 -8
- package/dist/sites/salesforce-developer/fetch-page.js +3 -1
- package/dist/sites/salesforce-developer/index.js +1 -2
- package/dist/sites/salesforce-doc-fetch.d.ts +11 -0
- package/dist/sites/salesforce-doc-fetch.js +117 -76
- package/dist/sites/salesforce-dom-probe.d.ts +16 -0
- package/dist/sites/salesforce-dom-probe.js +114 -0
- package/dist/sites/types.d.ts +0 -6
- package/oclif.manifest.json +153 -155
- package/package.json +38 -25
- package/dist/commands/index.d.ts +0 -35
- package/dist/commands/index.js +0 -306
- package/dist/commands/research/config/base.d.ts +0 -23
- package/dist/commands/research/config/base.js +0 -46
- package/dist/commands/research/config/get.d.ts +0 -20
- package/dist/commands/research/config/get.js +0 -45
- package/dist/commands/research/config/list.d.ts +0 -17
- package/dist/commands/research/config/list.js +0 -42
- package/dist/commands/research/config/set.d.ts +0 -31
- package/dist/commands/research/config/set.js +0 -94
- package/dist/commands/research/config/unset.d.ts +0 -21
- package/dist/commands/research/config/unset.js +0 -59
- package/dist/commands/research/import.d.ts +0 -38
- package/dist/commands/research/import.js +0 -313
- package/dist/commands/research/inspect.d.ts +0 -13
- package/dist/commands/research/inspect.js +0 -86
- package/dist/commands/research/list.d.ts +0 -25
- package/dist/commands/research/list.js +0 -143
- package/dist/commands/research/prune.d.ts +0 -24
- package/dist/commands/research/prune.js +0 -141
- package/dist/commands/research/search.d.ts +0 -32
- package/dist/commands/research/search.js +0 -334
- package/dist/commands/research/status.d.ts +0 -17
- package/dist/commands/research/status.js +0 -108
- package/dist/commands/research.d.ts +0 -36
- package/dist/commands/research.js +0 -304
- package/dist/commands/search.d.ts +0 -31
- package/dist/commands/search.js +0 -329
- package/dist/lib/research/docs/__fixtures__/sphinx-searchindex.d.ts +0 -1
- package/dist/lib/research/docs/__fixtures__/sphinx-searchindex.js +0 -2
- package/dist/lib/research/docs/discovery-index.d.ts +0 -14
- package/dist/lib/research/docs/discovery-index.js +0 -112
- package/dist/lib/research/docs/remote-search-runner.d.ts +0 -21
- package/dist/lib/research/docs/remote-search-runner.js +0 -114
- package/dist/lib/research/docs/remote-search.d.ts +0 -14
- package/dist/lib/research/docs/remote-search.js +0 -101
- package/dist/lib/research/docs/search-index.d.ts +0 -13
- package/dist/lib/research/docs/search-index.js +0 -176
- package/dist/sites/salesforce/browser-search.d.ts +0 -7
- package/dist/sites/salesforce/browser-search.js +0 -82
- package/dist/sites/salesforce/coveo.d.ts +0 -23
- package/dist/sites/salesforce/coveo.js +0 -161
- package/dist/sites/salesforce/token.d.ts +0 -26
- package/dist/sites/salesforce/token.js +0 -154
package/dist/base-command.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command, Interfaces } from '@oclif/core';
|
|
2
|
+
import { type ResolveResearchTargetOptions, type ResolvedResearchTarget } from './lib/research/resolve-target.js';
|
|
2
3
|
/**
|
|
3
4
|
* Shared base for every Bonsai command. Enables oclif's native `--json` flag,
|
|
4
5
|
* parses args/flags once in `init()` so commands read `this.args`/`this.flags`
|
|
@@ -9,10 +10,11 @@ export declare abstract class BaseCommand<T extends typeof Command> extends Comm
|
|
|
9
10
|
static enableJsonFlag: boolean;
|
|
10
11
|
flags: Interfaces.InferredFlags<T['flags']>;
|
|
11
12
|
args: Interfaces.InferredArgs<T['args']>;
|
|
13
|
+
parsedArgv: string[];
|
|
12
14
|
init(): Promise<void>;
|
|
13
15
|
/**
|
|
14
16
|
* Always surface warnings on stderr, even under `--json`. oclif silences `warn()` in JSON mode,
|
|
15
|
-
* but our warnings (secret-redirect, stale-serve,
|
|
17
|
+
* but our warnings (secret-redirect, stale-serve, prune failures) are
|
|
16
18
|
* security- and freshness-relevant side effects users must see. stderr never pollutes the stdout
|
|
17
19
|
* JSON envelope, so machine output stays clean.
|
|
18
20
|
*/
|
|
@@ -36,9 +38,23 @@ export declare abstract class BaseCommand<T extends typeof Command> extends Comm
|
|
|
36
38
|
exit?: number;
|
|
37
39
|
};
|
|
38
40
|
exitCode?: number;
|
|
41
|
+
code?: string;
|
|
39
42
|
}): Promise<any>;
|
|
40
43
|
/** Command id for the JSON envelope; falls back to the binary name when a command has no id. */
|
|
41
44
|
protected envelopeCommandId(): string;
|
|
45
|
+
/**
|
|
46
|
+
* Resolve a URL against the research cache, exiting on a normalization failure. A scheme-less but
|
|
47
|
+
* domain-shaped input reports MISSING_URL_SCHEME — the same code the root `bonsai <url>` shorthand
|
|
48
|
+
* uses — so an agent sees one stable code for "forgot https://" everywhere; truly unparseable input
|
|
49
|
+
* stays INVALID_URL.
|
|
50
|
+
*/
|
|
51
|
+
protected resolveResearchTargetOrFail(url: string, extra?: Pick<ResolveResearchTargetOptions, 'flagOverride' | 'lookup'>): ResolvedResearchTarget;
|
|
52
|
+
/**
|
|
53
|
+
* Single exit point for a URL that failed normalization, shared by every URL-accepting command.
|
|
54
|
+
* The scheme-less message is already self-contained and actionable, so it is surfaced as-is;
|
|
55
|
+
* other parse failures keep the "Invalid URL:" prefix for context.
|
|
56
|
+
*/
|
|
57
|
+
protected failInvalidUrl(url: string, message: string): never;
|
|
42
58
|
/** Single source of truth for the `--json` envelope shape, shared by success and error output. */
|
|
43
59
|
private envelope;
|
|
44
60
|
/** Wrap a command's return value in the machine-readable envelope emitted under `--json`. */
|
package/dist/base-command.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { Command, Errors } from '@oclif/core';
|
|
1
|
+
import { Command, Errors, toConfiguredId } from '@oclif/core';
|
|
2
2
|
import { invalidEnvOverrideWarnings } from './lib/config/index.js';
|
|
3
|
+
import { buildEnvelope, formatErrorForJson, normalizeCliErrorMessage, stableErrorCodeFrom, } from './lib/envelope.js';
|
|
4
|
+
import { resolveResearchTarget, } from './lib/research/resolve-target.js';
|
|
5
|
+
import { looksLikeSchemelessUrl } from './lib/research/url.js';
|
|
3
6
|
/**
|
|
4
7
|
* Shared base for every Bonsai command. Enables oclif's native `--json` flag,
|
|
5
8
|
* parses args/flags once in `init()` so commands read `this.args`/`this.flags`
|
|
@@ -10,9 +13,10 @@ export class BaseCommand extends Command {
|
|
|
10
13
|
static enableJsonFlag = true;
|
|
11
14
|
flags;
|
|
12
15
|
args;
|
|
16
|
+
parsedArgv;
|
|
13
17
|
async init() {
|
|
14
18
|
await super.init();
|
|
15
|
-
const { args, flags } = await this.parse({
|
|
19
|
+
const { args, flags, argv } = await this.parse({
|
|
16
20
|
flags: this.ctor.flags,
|
|
17
21
|
enableJsonFlag: this.ctor.enableJsonFlag,
|
|
18
22
|
args: this.ctor.args,
|
|
@@ -20,6 +24,7 @@ export class BaseCommand extends Command {
|
|
|
20
24
|
});
|
|
21
25
|
this.flags = flags;
|
|
22
26
|
this.args = args;
|
|
27
|
+
this.parsedArgv = argv;
|
|
23
28
|
// Surface a set-but-invalid BONSAI_* override once per run. Resolution silently drops such a
|
|
24
29
|
// value, so without this a typo'd env var would take no effect with no signal. Warnings go to
|
|
25
30
|
// stderr (even under --json), so machine output stays clean.
|
|
@@ -28,7 +33,7 @@ export class BaseCommand extends Command {
|
|
|
28
33
|
}
|
|
29
34
|
/**
|
|
30
35
|
* Always surface warnings on stderr, even under `--json`. oclif silences `warn()` in JSON mode,
|
|
31
|
-
* but our warnings (secret-redirect, stale-serve,
|
|
36
|
+
* but our warnings (secret-redirect, stale-serve, prune failures) are
|
|
32
37
|
* security- and freshness-relevant side effects users must see. stderr never pollutes the stdout
|
|
33
38
|
* JSON envelope, so machine output stays clean.
|
|
34
39
|
*/
|
|
@@ -53,24 +58,66 @@ export class BaseCommand extends Command {
|
|
|
53
58
|
* the shared resolver so the framework's `??` keeps it, then defer to the default behavior.
|
|
54
59
|
*/
|
|
55
60
|
async catch(err) {
|
|
61
|
+
// Parse failures throw before `this.parse()` sets `parsed`, which makes oclif emit a spurious
|
|
62
|
+
// [UnparsedCommand] warning to stderr even under `--json`. CLIParseError subclasses carry `parse`.
|
|
63
|
+
if (err && typeof err === 'object' && 'parse' in err)
|
|
64
|
+
this.parsed = true;
|
|
65
|
+
// Attach the stable code to the error itself so oclif's human pretty-print renders the same
|
|
66
|
+
// `Code:` line that `--json` already reports via stableErrorCodeFrom. Without this, built-in
|
|
67
|
+
// oclif parse errors (invalid enum value, missing arg, unknown flag) printed a code under
|
|
68
|
+
// --json but not for humans — the two output modes disagreed on whether an error had a code.
|
|
69
|
+
if (err && typeof err === 'object' && !err.code) {
|
|
70
|
+
const code = stableErrorCodeFrom(err);
|
|
71
|
+
if (code)
|
|
72
|
+
err.code = code;
|
|
73
|
+
}
|
|
56
74
|
process.exitCode = process.exitCode ?? BaseCommand.exitCodeOf(err);
|
|
57
75
|
return super.catch(err);
|
|
58
76
|
}
|
|
59
77
|
/** Command id for the JSON envelope; falls back to the binary name when a command has no id. */
|
|
60
78
|
envelopeCommandId() {
|
|
61
|
-
return this.ctor.id
|
|
79
|
+
return this.ctor.id ? toConfiguredId(this.ctor.id, this.config) : this.config.bin;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Resolve a URL against the research cache, exiting on a normalization failure. A scheme-less but
|
|
83
|
+
* domain-shaped input reports MISSING_URL_SCHEME — the same code the root `bonsai <url>` shorthand
|
|
84
|
+
* uses — so an agent sees one stable code for "forgot https://" everywhere; truly unparseable input
|
|
85
|
+
* stays INVALID_URL.
|
|
86
|
+
*/
|
|
87
|
+
resolveResearchTargetOrFail(url, extra) {
|
|
88
|
+
try {
|
|
89
|
+
return resolveResearchTarget({
|
|
90
|
+
configDir: this.config.configDir,
|
|
91
|
+
cwd: process.cwd(),
|
|
92
|
+
dataDir: this.config.dataDir,
|
|
93
|
+
url,
|
|
94
|
+
...extra,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
this.failInvalidUrl(url, err.message);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Single exit point for a URL that failed normalization, shared by every URL-accepting command.
|
|
103
|
+
* The scheme-less message is already self-contained and actionable, so it is surfaced as-is;
|
|
104
|
+
* other parse failures keep the "Invalid URL:" prefix for context.
|
|
105
|
+
*/
|
|
106
|
+
failInvalidUrl(url, message) {
|
|
107
|
+
if (looksLikeSchemelessUrl(url)) {
|
|
108
|
+
this.error(message, { exit: 2, code: 'MISSING_URL_SCHEME' });
|
|
109
|
+
}
|
|
110
|
+
this.error(`Invalid URL: ${message}`, { exit: 2, code: 'INVALID_URL' });
|
|
62
111
|
}
|
|
63
112
|
/** Single source of truth for the `--json` envelope shape, shared by success and error output. */
|
|
64
113
|
envelope(parts) {
|
|
65
|
-
return {
|
|
66
|
-
schemaVersion: 1,
|
|
114
|
+
return buildEnvelope({
|
|
67
115
|
command: this.envelopeCommandId(),
|
|
68
116
|
ok: parts.ok,
|
|
69
117
|
exitCode: parts.exitCode,
|
|
70
|
-
stdout: '',
|
|
71
118
|
stderr: parts.stderr,
|
|
72
119
|
data: parts.data,
|
|
73
|
-
};
|
|
120
|
+
});
|
|
74
121
|
}
|
|
75
122
|
/** Wrap a command's return value in the machine-readable envelope emitted under `--json`. */
|
|
76
123
|
toSuccessJson(data) {
|
|
@@ -85,6 +132,20 @@ export class BaseCommand extends Command {
|
|
|
85
132
|
toErrorJson(err) {
|
|
86
133
|
const e = err;
|
|
87
134
|
const exitCode = BaseCommand.exitCodeOf(e);
|
|
88
|
-
|
|
135
|
+
const code = stableErrorCodeFrom(e);
|
|
136
|
+
const message = typeof e?.message === 'string' ? normalizeCliErrorMessage(e.message) : undefined;
|
|
137
|
+
const stderr = message || code || e?.suggestions?.length || e?.ref
|
|
138
|
+
? formatErrorForJson({ ...e, message, code })
|
|
139
|
+
: String(err);
|
|
140
|
+
return buildEnvelope({
|
|
141
|
+
command: this.envelopeCommandId(),
|
|
142
|
+
ok: false,
|
|
143
|
+
exitCode,
|
|
144
|
+
stderr,
|
|
145
|
+
data: null,
|
|
146
|
+
code,
|
|
147
|
+
suggestions: e.suggestions?.length ? e.suggestions : undefined,
|
|
148
|
+
ref: e.ref,
|
|
149
|
+
});
|
|
89
150
|
}
|
|
90
151
|
}
|
|
@@ -12,6 +12,8 @@ export declare abstract class ConfigCommand<T extends typeof Command> extends Ba
|
|
|
12
12
|
/** Read scope for get/list: an explicit `--global`/`--local`, else the merged effective view. */
|
|
13
13
|
protected readScope(global?: boolean, local?: boolean): ConfigScope;
|
|
14
14
|
protected assertKnownKey(keyArg: string): asserts keyArg is ConfigKey;
|
|
15
|
+
protected requireConfigKey(key: string | undefined): asserts key is ConfigKey;
|
|
16
|
+
protected validateConfigKeyAndScope(key: string | undefined, global?: boolean, local?: boolean): asserts key is ConfigKey;
|
|
15
17
|
}
|
|
16
18
|
/** Build the `--global`/`--local` scope-flag pair with per-command descriptions. */
|
|
17
19
|
export declare function configScopeFlags(descriptions: {
|
|
@@ -8,7 +8,10 @@ import { isKnownKey, suggestKey, validKeysHint } from '../../lib/config/index.js
|
|
|
8
8
|
export class ConfigCommand extends BaseCommand {
|
|
9
9
|
assertScopeFlagsExclusive(global, local) {
|
|
10
10
|
if (global && local) {
|
|
11
|
-
this.error('--global and --local are mutually exclusive.', {
|
|
11
|
+
this.error('--global and --local are mutually exclusive.', {
|
|
12
|
+
exit: 2,
|
|
13
|
+
code: 'CONFLICTING_FLAGS',
|
|
14
|
+
});
|
|
12
15
|
}
|
|
13
16
|
}
|
|
14
17
|
/** `--local` writes/reads the project file; otherwise the user-level file. */
|
|
@@ -29,9 +32,20 @@ export class ConfigCommand extends BaseCommand {
|
|
|
29
32
|
const hint = suggestion ? ` Did you mean: ${suggestion}?` : '';
|
|
30
33
|
this.error(`Unknown config key: "${keyArg}".${hint} Valid keys: ${validKeysHint()}.`, {
|
|
31
34
|
exit: 2,
|
|
35
|
+
code: 'UNKNOWN_KEY',
|
|
32
36
|
});
|
|
33
37
|
}
|
|
34
38
|
}
|
|
39
|
+
requireConfigKey(key) {
|
|
40
|
+
if (!key) {
|
|
41
|
+
this.error('Missing required argument: key', { exit: 2, code: 'MISSING_ARGUMENT' });
|
|
42
|
+
}
|
|
43
|
+
this.assertKnownKey(key);
|
|
44
|
+
}
|
|
45
|
+
validateConfigKeyAndScope(key, global, local) {
|
|
46
|
+
this.requireConfigKey(key);
|
|
47
|
+
this.assertScopeFlagsExclusive(global, local);
|
|
48
|
+
}
|
|
35
49
|
}
|
|
36
50
|
/** Build the `--global`/`--local` scope-flag pair with per-command descriptions. */
|
|
37
51
|
export function configScopeFlags(descriptions) {
|
|
@@ -8,7 +8,7 @@ export default class ConfigGet extends ConfigCommand<typeof ConfigGet> {
|
|
|
8
8
|
command: string;
|
|
9
9
|
}[];
|
|
10
10
|
static args: {
|
|
11
|
-
key: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
11
|
+
key: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
12
12
|
};
|
|
13
13
|
static flags: {
|
|
14
14
|
global: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -7,16 +7,16 @@ export default class ConfigGet extends ConfigCommand {
|
|
|
7
7
|
static description = `Print a config value. Without --global/--local, shows the merged effective value (flag > env > project > user > default).\n\nValid keys: ${validKeysHint()}.`;
|
|
8
8
|
static examples = [
|
|
9
9
|
{
|
|
10
|
-
description: '
|
|
10
|
+
description: 'get the effective storage mode',
|
|
11
11
|
command: '<%= config.bin %> config get storage',
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
|
-
description: '
|
|
14
|
+
description: 'read only the project-level value',
|
|
15
15
|
command: '<%= config.bin %> config get storage --local',
|
|
16
16
|
},
|
|
17
17
|
];
|
|
18
18
|
static args = {
|
|
19
|
-
key: Args.string({ required:
|
|
19
|
+
key: Args.string({ required: false, description: 'the configuration key to read' }),
|
|
20
20
|
};
|
|
21
21
|
static flags = {
|
|
22
22
|
...configScopeFlags({
|
|
@@ -27,8 +27,7 @@ export default class ConfigGet extends ConfigCommand {
|
|
|
27
27
|
static stdoutIsPrimaryData = true;
|
|
28
28
|
async run() {
|
|
29
29
|
const key = this.args.key;
|
|
30
|
-
this.
|
|
31
|
-
this.assertScopeFlagsExclusive(this.flags.global, this.flags.local);
|
|
30
|
+
this.validateConfigKeyAndScope(key, this.flags.global, this.flags.local);
|
|
32
31
|
const scope = this.readScope(this.flags.global, this.flags.local);
|
|
33
32
|
const value = readScopedConfig(scope, this.config.configDir, process.cwd())[key];
|
|
34
33
|
const meta = KEY_META[key];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
export default class ConfigIndex extends BaseCommand<typeof ConfigIndex> {
|
|
3
|
+
static id: string;
|
|
4
|
+
static summary: string;
|
|
5
|
+
static description: string;
|
|
6
|
+
static examples: {
|
|
7
|
+
description: string;
|
|
8
|
+
command: string;
|
|
9
|
+
}[];
|
|
10
|
+
static stdoutIsPrimaryData: boolean;
|
|
11
|
+
run(): Promise<unknown>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Help, toConfiguredId } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
export default class ConfigIndex extends BaseCommand {
|
|
4
|
+
static id = 'config';
|
|
5
|
+
static summary = 'Manage research cache storage configuration (global vs project).';
|
|
6
|
+
static description = 'Show config subcommands for reading and writing Bonsai research cache configuration.';
|
|
7
|
+
static examples = [
|
|
8
|
+
{
|
|
9
|
+
description: 'get a configuration value',
|
|
10
|
+
command: '<%= config.bin %> <%= command.id %> get storage',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
description: 'set a configuration value for the current project',
|
|
14
|
+
command: '<%= config.bin %> <%= command.id %> set storage project --local',
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
static stdoutIsPrimaryData = true;
|
|
18
|
+
async run() {
|
|
19
|
+
if (!this.jsonEnabled()) {
|
|
20
|
+
await new Help(this.config, this.config.pjson.oclif.helpOptions ?? {}).showHelp(['config']);
|
|
21
|
+
}
|
|
22
|
+
const commands = this.config.commands
|
|
23
|
+
.filter((c) => c.id.startsWith('config:') && !c.hidden)
|
|
24
|
+
.map((c) => ({
|
|
25
|
+
id: toConfiguredId(c.id, this.config),
|
|
26
|
+
summary: c.summary || c.description || '',
|
|
27
|
+
}))
|
|
28
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
29
|
+
return {
|
|
30
|
+
topic: 'config',
|
|
31
|
+
commands,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -6,11 +6,11 @@ export default class ConfigList extends ConfigCommand {
|
|
|
6
6
|
static description = `Show every configuration key with its current value. Use --global/--local to show a single scope.\n\nValid keys: ${validKeysHint()}.`;
|
|
7
7
|
static examples = [
|
|
8
8
|
{
|
|
9
|
-
description: '
|
|
9
|
+
description: 'show all effective config values',
|
|
10
10
|
command: '<%= config.bin %> config list',
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
|
-
description: '
|
|
13
|
+
description: 'show only project-level config',
|
|
14
14
|
command: '<%= config.bin %> config list --local',
|
|
15
15
|
},
|
|
16
16
|
];
|
|
@@ -8,17 +8,17 @@ export default class ConfigSet extends ConfigCommand {
|
|
|
8
8
|
`Valid keys: ${validKeysHint()}. The inline form \`<key>=<value>\` is also accepted.`;
|
|
9
9
|
static examples = [
|
|
10
10
|
{
|
|
11
|
-
description: '
|
|
11
|
+
description: 'store research cache inside the current project',
|
|
12
12
|
command: '<%= config.bin %> config set storage project --local',
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
description: '
|
|
15
|
+
description: 'set the user-level default using the inline key=value form',
|
|
16
16
|
command: '<%= config.bin %> config set storage=global',
|
|
17
17
|
},
|
|
18
18
|
];
|
|
19
19
|
static args = {
|
|
20
|
-
key: Args.string({ required: false, description: '
|
|
21
|
-
value: Args.string({ required: false, description: '
|
|
20
|
+
key: Args.string({ required: false, description: 'the configuration key to set' }),
|
|
21
|
+
value: Args.string({ required: false, description: 'the value to assign' }),
|
|
22
22
|
};
|
|
23
23
|
static flags = {
|
|
24
24
|
...configScopeFlags({
|
|
@@ -26,26 +26,28 @@ export default class ConfigSet extends ConfigCommand {
|
|
|
26
26
|
local: 'Write to project-level config (.bonsai.json in cwd).',
|
|
27
27
|
}),
|
|
28
28
|
'dry-run': Flags.boolean({
|
|
29
|
-
description: '
|
|
29
|
+
description: 'show what would be written without saving',
|
|
30
30
|
default: false,
|
|
31
31
|
}),
|
|
32
32
|
};
|
|
33
33
|
static stdoutIsPrimaryData = true;
|
|
34
34
|
async run() {
|
|
35
35
|
const { keyArg, valueArg } = splitInlineKeyValue(this.args.key, this.args.value);
|
|
36
|
-
|
|
37
|
-
this.error('Missing required argument: key', { exit: 2 });
|
|
38
|
-
}
|
|
39
|
-
this.assertKnownKey(keyArg);
|
|
40
|
-
this.assertScopeFlagsExclusive(this.flags.global, this.flags.local);
|
|
36
|
+
this.validateConfigKeyAndScope(keyArg, this.flags.global, this.flags.local);
|
|
41
37
|
const meta = KEY_META[keyArg];
|
|
42
38
|
if (valueArg === undefined) {
|
|
43
|
-
this.error(`Missing required argument: value for key "${keyArg}"`, {
|
|
39
|
+
this.error(`Missing required argument: value for key "${keyArg}"`, {
|
|
40
|
+
exit: 2,
|
|
41
|
+
code: 'MISSING_ARGUMENT',
|
|
42
|
+
});
|
|
44
43
|
}
|
|
45
44
|
const parsed = meta.parseValue(valueArg);
|
|
46
45
|
if (!meta.isValid(parsed)) {
|
|
47
46
|
const guidance = meta.values ? `Valid values: ${meta.values.join(', ')}.` : meta.description;
|
|
48
|
-
this.error(`Invalid value "${valueArg}" for "${keyArg}". ${guidance}`, {
|
|
47
|
+
this.error(`Invalid value "${valueArg}" for "${keyArg}". ${guidance}`, {
|
|
48
|
+
exit: 2,
|
|
49
|
+
code: 'INVALID_VALUE',
|
|
50
|
+
});
|
|
49
51
|
}
|
|
50
52
|
const scope = this.writeScope(this.flags.local);
|
|
51
53
|
const formatted = meta.format(parsed);
|
|
@@ -63,6 +65,10 @@ export default class ConfigSet extends ConfigCommand {
|
|
|
63
65
|
if (!configDir) {
|
|
64
66
|
this.error('Could not determine user config directory. Use --local to write project config.', {
|
|
65
67
|
exit: 1,
|
|
68
|
+
code: 'CONFIG_DIR_UNAVAILABLE',
|
|
69
|
+
suggestions: [
|
|
70
|
+
`Write project config instead: ${this.config.bin} config set <key> <value> --local`,
|
|
71
|
+
],
|
|
66
72
|
});
|
|
67
73
|
}
|
|
68
74
|
writeUserConfig(configDir, patch);
|
|
@@ -8,7 +8,7 @@ export default class ConfigUnset extends ConfigCommand<typeof ConfigUnset> {
|
|
|
8
8
|
command: string;
|
|
9
9
|
}[];
|
|
10
10
|
static args: {
|
|
11
|
-
key: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
11
|
+
key: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
12
12
|
};
|
|
13
13
|
static flags: {
|
|
14
14
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -7,16 +7,16 @@ export default class ConfigUnset extends ConfigCommand {
|
|
|
7
7
|
static description = `Delete a key from user-level config (default) or project-level config (--local), restoring the built-in default.\n\nValid keys: ${validKeysHint()}.`;
|
|
8
8
|
static examples = [
|
|
9
9
|
{
|
|
10
|
-
description: '
|
|
10
|
+
description: 'remove the user-level storage setting',
|
|
11
11
|
command: '<%= config.bin %> config unset storage',
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
|
-
description: '
|
|
14
|
+
description: 'remove the project-level storage setting',
|
|
15
15
|
command: '<%= config.bin %> config unset storage --local',
|
|
16
16
|
},
|
|
17
17
|
];
|
|
18
18
|
static args = {
|
|
19
|
-
key: Args.string({ required:
|
|
19
|
+
key: Args.string({ required: false, description: 'the configuration key to remove' }),
|
|
20
20
|
};
|
|
21
21
|
static flags = {
|
|
22
22
|
...configScopeFlags({
|
|
@@ -24,15 +24,14 @@ export default class ConfigUnset extends ConfigCommand {
|
|
|
24
24
|
local: 'Remove from project-level config (.bonsai.json in cwd).',
|
|
25
25
|
}),
|
|
26
26
|
'dry-run': Flags.boolean({
|
|
27
|
-
description: '
|
|
27
|
+
description: 'show what would be removed without saving',
|
|
28
28
|
default: false,
|
|
29
29
|
}),
|
|
30
30
|
};
|
|
31
31
|
static stdoutIsPrimaryData = true;
|
|
32
32
|
async run() {
|
|
33
33
|
const key = this.args.key;
|
|
34
|
-
this.
|
|
35
|
-
this.assertScopeFlagsExclusive(this.flags.global, this.flags.local);
|
|
34
|
+
this.validateConfigKeyAndScope(key, this.flags.global, this.flags.local);
|
|
36
35
|
const scope = this.writeScope(this.flags.local);
|
|
37
36
|
if (this.flags['dry-run']) {
|
|
38
37
|
if (!this.jsonEnabled())
|
|
@@ -48,6 +47,10 @@ export default class ConfigUnset extends ConfigCommand {
|
|
|
48
47
|
if (!configDir) {
|
|
49
48
|
this.error('Could not determine user config directory. Use --local to remove project config.', {
|
|
50
49
|
exit: 1,
|
|
50
|
+
code: 'CONFIG_DIR_UNAVAILABLE',
|
|
51
|
+
suggestions: [
|
|
52
|
+
`Remove project config instead: ${this.config.bin} config unset ${key} --local`,
|
|
53
|
+
],
|
|
51
54
|
});
|
|
52
55
|
}
|
|
53
56
|
writeUserConfig(configDir, patch);
|
package/dist/commands/fetch.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export default class FetchCommand extends BaseCommand<typeof FetchCommand> {
|
|
|
8
8
|
description: string;
|
|
9
9
|
command: string;
|
|
10
10
|
}[];
|
|
11
|
+
static strict: boolean;
|
|
11
12
|
static args: {
|
|
12
13
|
url: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
13
14
|
};
|
|
@@ -35,6 +36,7 @@ export default class FetchCommand extends BaseCommand<typeof FetchCommand> {
|
|
|
35
36
|
private persistFreshArtifact;
|
|
36
37
|
private persistSectionsIfFresh;
|
|
37
38
|
run(): Promise<unknown>;
|
|
39
|
+
private fetchSingleTarget;
|
|
38
40
|
}
|
|
39
41
|
export declare function fetchFailureGuidance(message: string, url: string): {
|
|
40
42
|
suggestions: string[];
|