@gaia-ai/addon-dropsh 0.11.2 → 0.11.3

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.
@@ -1,6 +1,10 @@
1
- import { type GaiaCommandPlugin } from '@gaia-ai/core';
2
- /** Actionable hint when a `gaia dropsh` command runs with no loadable connection. */
1
+ import { type GaiaCommandHost, type GaiaCommandPlugin, type WorkspaceRecoveryOptions } from '@gaia-ai/core';
3
2
  export declare function dropshConfigHint(resolvedPath?: string): string;
4
- /** The `dropsh` command plugin the host mounts (`gaia dropsh …`). */
3
+ export interface DropshDispatchOptions extends WorkspaceRecoveryOptions {
4
+ stdout?: (text: string) => void;
5
+ stderr?: (text: string) => void;
6
+ }
7
+ /** Build the actual plugin registrations after the final connection is ready. */
8
+ export declare function dispatchGaiaDropsh(host: GaiaCommandHost, argv: string[], options?: DropshDispatchOptions): Promise<void>;
5
9
  declare const dropshCommandPlugin: GaiaCommandPlugin;
6
10
  export default dropshCommandPlugin;
package/dist/src/index.js CHANGED
@@ -1,82 +1,112 @@
1
- import { loadGaiaConfig, } from '@gaia-ai/core';
1
+ import { createGaiaConnectionContext, discoverGaiaWorkspaces, loadGaiaConnectionBootstrap, loadReadyGaiaConnection, } from '@gaia-ai/core';
2
2
  import { buildProgram as buildDropshProgram } from 'dropsh';
3
- // GAIA-201: the `gaia dropsh` command PLUGIN. It builds the inherited dropsh
4
- // JSON:API shell from the CONNECTION config (`loadGaiaConfig`) — NEVER
5
- // `loadConductorConfig`. That is the deepest AC-2 fix: the old `gaia dropsh`
6
- // went through `loadConductorConfig`, which eagerly constructed the whole engine
7
- // plugin farm (remote/executor/agent/workspace) just to read the auth `plugins`.
8
- // This package has no `@gaia-ai/conductor` edge and imports no engine plugin, so
9
- // a `gaia dropsh read …` instantiates nothing but the dropsh auth plugins.
10
- //
11
- // Connection precedence (AC-4, resolved in core `resolveGaiaConfigPath`):
12
- // explicit `--config` / `$DROPSH_CONFIG` → project `./.gaia/gaia.config.js`
13
- // walk-up (legacy `conductor.config.js` accepted) → home `~/.gaia/gaia.config.js`
14
- // → shipped fallback. `$DROPSH_CONFIG` is set to the resolved path so dropsh's
15
- // own subcommands (`auth login`) reload the same connection.
16
- /** Actionable hint when a `gaia dropsh` command runs with no loadable connection. */
17
3
  export function dropshConfigHint(resolvedPath) {
18
- const where = resolvedPath ? ` (looked at ${resolvedPath})` : '';
19
- return (`gaia dropsh: no connection config could be loaded${where}.\n` +
20
- 'Point at one with --config <path>, set $DROPSH_CONFIG, run from a directory ' +
21
- 'containing .gaia/gaia.config.js, or onboard this machine with ' +
22
- '`gaia conductor init --base-url <url>` (home fallback).');
4
+ return `gaia dropsh: no connection config at ${resolvedPath ?? '~/.gaia/gaia.config.js'}. Use --config <path> or run gaia config init --scope connection.`;
23
5
  }
24
- /**
25
- * Build the `dropsh` command from a resolved connection. Sets `$DROPSH_CONFIG`
26
- * to the connection path (unless already set) so dropsh's own subcommands reload
27
- * the same site + plugins.
28
- */
29
- async function buildDropshCommand(host) {
30
- let connection;
31
- try {
32
- connection = await loadGaiaConfig(host, {});
6
+ /** Consume only wrapper flags; forward all actual dropsh arguments unchanged. */
7
+ function invocation(argv) {
8
+ const forwarded = [];
9
+ let explicit;
10
+ let format;
11
+ let yes = false;
12
+ let profile;
13
+ for (let i = 0; i < argv.length; i++) {
14
+ const token = argv[i];
15
+ if (token === '--yes') {
16
+ yes = true;
17
+ continue;
18
+ }
19
+ if (token === '--config' ||
20
+ token === '--format' ||
21
+ token === '--auth-profile') {
22
+ const value = argv[i + 1];
23
+ if (value !== undefined) {
24
+ if (token === '--config')
25
+ explicit = value;
26
+ else if (token === '--format')
27
+ format = value;
28
+ else
29
+ profile = value;
30
+ forwarded.push(token, value);
31
+ i++;
32
+ continue;
33
+ }
34
+ }
35
+ if (token.startsWith('--config='))
36
+ explicit = token.slice(9);
37
+ if (token.startsWith('--format='))
38
+ format = token.slice(9);
39
+ forwarded.push(token);
33
40
  }
34
- catch {
35
- connection = undefined;
41
+ // Global options can appear late, after the command's positional arguments.
42
+ const positional = forwarded.filter((token, i) => !['--config', '--format', '--auth-profile', '--view-mode'].includes(token) &&
43
+ !/^--(?:config|format|auth-profile|view-mode)=/.test(token) &&
44
+ !['--config', '--format', '--auth-profile', '--view-mode'].includes(forwarded[i - 1] ?? ''));
45
+ return { forwarded, explicit, format, yes, profile, positional };
46
+ }
47
+ /** Build the actual plugin registrations after the final connection is ready. */
48
+ export async function dispatchGaiaDropsh(host, argv, options = {}) {
49
+ const args = invocation(argv);
50
+ const opts = {
51
+ ...options,
52
+ ...(args.explicit ? { explicit: args.explicit } : {}),
53
+ ...(args.format ? { format: args.format } : {}),
54
+ yes: options.yes || args.yes,
55
+ };
56
+ const help = argv.includes('--help') || argv.includes('-h') || argv.length === 0;
57
+ const auth = args.positional[0] === 'auth';
58
+ const search = args.positional[0] === 'search' &&
59
+ args.positional[1] === 'gaia_workspace' &&
60
+ args.positional.length === 2 &&
61
+ (!args.format || ['md', 'json'].includes(args.format));
62
+ if (search) {
63
+ const connection = await loadGaiaConnectionBootstrap(host, opts);
64
+ const rows = await discoverGaiaWorkspaces(connection, opts);
65
+ const stdout = options.stdout ?? ((s) => process.stdout.write(s));
66
+ if (args.format === 'md')
67
+ stdout(`| Workspace | UUID |\n| --- | --- |\n${rows.map((r) => `| ${r.name.replace(/[|\r\n]/g, ' ')} | ${r.id} |`).join('\n')}\n`);
68
+ else
69
+ stdout(`${JSON.stringify(rows, null, 2)}\n`);
70
+ return;
36
71
  }
37
- const dropsh = buildDropshProgram({
72
+ const connection = help
73
+ ? undefined
74
+ : auth
75
+ ? await loadGaiaConnectionBootstrap(host, opts)
76
+ : await loadReadyGaiaConnection(host, opts);
77
+ const program = buildDropshProgram({
38
78
  plugins: connection?.plugins ?? [],
39
- });
40
- if (connection && !process.env.DROPSH_CONFIG) {
41
- process.env.DROPSH_CONFIG = connection.config_path;
42
- }
43
- if (!connection) {
44
- // Registration is unconditional; a config problem must surface WHEN a dropsh
45
- // command runs, not make the command vanish. The hook fires only on a real
46
- // subcommand dispatch — never for `--help` — so discoverability holds. It
47
- // honours a late `--config` (AC-4 explicit leg).
48
- dropsh.hook('preSubcommand', async (thisCommand) => {
49
- const override = thisCommand.opts().config ??
50
- process.env.DROPSH_CONFIG;
51
- let resolvedPath;
52
- try {
53
- const c = await loadGaiaConfig(host, { explicit: override });
54
- resolvedPath = c.config_path;
55
- }
56
- catch (cause) {
57
- // A config that was FOUND and then REJECTED (no `site.base_url`, no
58
- // `workspace_id`) must not be reported as "no config could be loaded":
59
- // that sends the reader hunting for a file which is right there and
60
- // names its own problem. Only a genuine resolution failure gets the hint.
61
- if (cause?.name === 'GaiaConnectionConfigError') {
62
- throw cause;
63
- }
64
- throw new Error(dropshConfigHint(override));
79
+ ...(options.stdout ? { stdout: options.stdout } : {}),
80
+ ...(options.stderr ? { stderr: options.stderr } : {}),
81
+ ...(connection
82
+ ? {
83
+ contextFactory: () => createGaiaConnectionContext(connection, {
84
+ ...opts,
85
+ ...(args.profile ? { profile: args.profile } : {}),
86
+ }),
65
87
  }
66
- if (!process.env.DROPSH_CONFIG) {
67
- process.env.DROPSH_CONFIG = resolvedPath;
68
- }
69
- });
70
- }
71
- return dropsh;
88
+ : {}),
89
+ });
90
+ // Auth commands perform their own reload; bind it explicitly to the same path.
91
+ const forwarded = connection
92
+ ? ['--config', connection.config_path, ...args.forwarded]
93
+ : args.forwarded;
94
+ await program.parseAsync(forwarded, { from: 'user' });
72
95
  }
73
- /** The `dropsh` command plugin the host mounts (`gaia dropsh …`). */
74
96
  const dropshCommandPlugin = {
75
97
  kind: 'command',
76
98
  name: 'dropsh',
77
99
  describe: 'JSON:API shell (dropsh) bound to the GAIA connection config',
78
- async register(program, host) {
79
- program.addCommand(await buildDropshCommand(host));
100
+ register(program, host) {
101
+ program
102
+ .command('dropsh')
103
+ .description('JSON:API shell bound to the GAIA connection')
104
+ .helpOption(false)
105
+ .allowUnknownOption()
106
+ .argument('[args...]')
107
+ .action(async (args) => {
108
+ await dispatchGaiaDropsh(host, args);
109
+ });
80
110
  },
81
111
  };
82
112
  export default dropshCommandPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gaia-ai/addon-dropsh",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "GAIA dropsh command plugin: the `gaia dropsh` JSON:API shell bound to the split connection config.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,6 +26,6 @@
26
26
  "dropsh": "^0.6.1"
27
27
  },
28
28
  "peerDependencies": {
29
- "@gaia-ai/core": "^0.11.2"
29
+ "@gaia-ai/core": "^0.11.3"
30
30
  }
31
31
  }