@tiny-fish/cli 0.40.1-next.317 → 0.41.1-next.321

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,8 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { buildProgram } from './program.js';
3
- const { program } = buildProgram();
4
3
  // Await parseAsync so async command handlers complete before the process exits
5
- program.parseAsync(process.argv).catch((e) => {
4
+ buildProgram()
5
+ .then(({ program }) => program.parseAsync(process.argv))
6
+ .catch((e) => {
6
7
  process.stderr.write(JSON.stringify({ error: e instanceof Error ? e.message : String(e) }) + '\n');
8
+ // A failed command import reads as a bare message; the stack names the module.
9
+ if (process.env['TINYFISH_DEBUG'] && e instanceof Error && e.stack) {
10
+ process.stderr.write(e.stack + '\n');
11
+ }
7
12
  process.exit(1);
8
13
  });
@@ -30,6 +30,10 @@ declare const cliFetchResponseSchema: z.ZodObject<{
30
30
  last_modified: z.ZodOptional<z.ZodNullable<z.ZodString>>;
31
31
  format: z.ZodLiteral<"markdown">;
32
32
  text: z.ZodNullable<z.ZodString>;
33
+ highlights: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
34
+ text: z.ZodString;
35
+ rank: z.ZodInt;
36
+ }, z.core.$strip>>>>;
33
37
  }, z.core.$strip>, z.ZodObject<{
34
38
  url: z.ZodString;
35
39
  final_url: z.ZodNullable<z.ZodString>;
@@ -4,6 +4,8 @@ export type HermesHomeReason = 'timeout' | 'exit' | 'no_line' | 'relative';
4
4
  export interface HermesHomeFailure {
5
5
  reason: HermesHomeReason;
6
6
  }
7
+ /** Tests share one process; the resolver result must not. */
8
+ export declare function resetHermesHomeCache(): void;
7
9
  /** Asking Hermes beats reimplementing its profile override, which we'd drift from. */
8
10
  export declare function resolveHermesHome(): string | HermesHomeFailure;
9
11
  export declare const HERMES_KEY_VAR = "MCP_TINYFISH_API_KEY";
@@ -7,8 +7,24 @@ import { HARNESS_PROBE_TIMEOUT_MS } from './constants.js';
7
7
  import { sanitizeLine } from './output.js';
8
8
  // display_hermes_home() abbreviates under $HOME, so the value is not always absolute.
9
9
  const HERMES_HOME_LINE = /^\s*hermes_home:\s*(\S.*?)\s*$/m;
10
+ // Cached: `hermes dump` starts Python, and doctor asks repeatedly.
11
+ let cachedHermesHome;
12
+ /** Tests share one process; the resolver result must not. */
13
+ export function resetHermesHomeCache() {
14
+ cachedHermesHome = undefined;
15
+ }
10
16
  /** Asking Hermes beats reimplementing its profile override, which we'd drift from. */
11
17
  export function resolveHermesHome() {
18
+ if (cachedHermesHome)
19
+ return cachedHermesHome.value;
20
+ const value = probeHermesHome();
21
+ // A timeout is load-dependent; caching it would sink a run a retry still saves.
22
+ if (typeof value === 'string' || value.reason !== 'timeout') {
23
+ cachedHermesHome = { value };
24
+ }
25
+ return value;
26
+ }
27
+ function probeHermesHome() {
12
28
  const result = spawn.sync('hermes', ['dump'], {
13
29
  encoding: 'utf8',
14
30
  env: { ...process.env, FORCE_COLOR: '0', NO_COLOR: '1' },
package/dist/program.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Command } from 'commander';
2
2
  /** Split from index.ts so tests can drive the real program instead of hand-assembling one. */
3
- export declare function buildProgram(): {
3
+ export declare function buildProgram(argv?: string[]): Promise<{
4
4
  program: Command;
5
5
  uninstallNotice: () => void;
6
- };
6
+ }>;
package/dist/program.js CHANGED
@@ -1,28 +1,55 @@
1
1
  import { Command } from 'commander';
2
2
  import { CLI_VERSION } from './lib/constants.js';
3
- import { registerAuth } from './commands/auth.js';
4
- import { registerBatch } from './commands/batch.js';
5
- import { registerFetch } from './commands/fetch.js';
6
- import { registerBrowser } from './commands/browser.js';
7
- import { registerProfile } from './commands/profile.js';
8
- import { registerVault } from './commands/vault.js';
9
- import { registerWallet } from './commands/wallet.js';
10
- import { registerRun } from './commands/run.js';
11
- import { registerRuns } from './commands/runs.js';
12
- import { registerConfigureClaude } from './commands/config-claude.js';
13
- import { registerSearch } from './commands/search.js';
14
- import { registerConnect } from './commands/connect.js';
15
- import { registerDoctor } from './commands/doctor.js';
16
- import { registerUpgrade } from './commands/upgrade.js';
17
- import { registerOnboard } from './commands/onboard.js';
18
3
  import { installNoticeEmit } from './lib/notice.js';
4
+ // Loaded on demand: static imports pull zod, yaml, which, cross-spawn always.
5
+ const GROUPS = {
6
+ auth: async (p) => (await import('./commands/auth.js')).registerAuth(p),
7
+ onboard: async (p) => (await import('./commands/onboard.js')).registerOnboard(p),
8
+ connect: async (p) => (await import('./commands/connect.js')).registerConnect(p),
9
+ doctor: async (p) => (await import('./commands/doctor.js')).registerDoctor(p),
10
+ upgrade: async (p) => (await import('./commands/upgrade.js')).registerUpgrade(p),
11
+ 'config-claude': async (p) => (await import('./commands/config-claude.js')).registerConfigureClaude(p),
12
+ browser: async (p) => (await import('./commands/browser.js')).registerBrowser(p),
13
+ profile: async (p) => (await import('./commands/profile.js')).registerProfile(p),
14
+ vault: async (p) => (await import('./commands/vault.js')).registerVault(p),
15
+ wallet: async (p) => (await import('./commands/wallet.js')).registerWallet(p),
16
+ agent: async (p) => {
17
+ const agentCmd = p
18
+ .command('agent')
19
+ .description('Agent automation commands')
20
+ .enablePositionalOptions();
21
+ // Measured: Promise.all is slower here; ESM loading is CPU-bound.
22
+ // registerRuns hangs off the `run` command registerRun returns.
23
+ const runCmd = (await import('./commands/run.js')).registerRun(agentCmd);
24
+ (await import('./commands/runs.js')).registerRuns(runCmd);
25
+ (await import('./commands/batch.js')).registerBatch(agentCmd);
26
+ },
27
+ search: async (p) => (await import('./commands/search.js')).registerSearch(p),
28
+ fetch: async (p) => (await import('./commands/fetch.js')).registerFetch(p),
29
+ };
30
+ /** Commander answers these before routing, so no command module is needed. */
31
+ const VERSION_FLAGS = ['-V', '--version'];
32
+ // Unknown names need the full list to suggest against.
33
+ /** First bare token is the command. Assumes no global option takes a value. */
34
+ function groupsFor(argv) {
35
+ for (const arg of argv.slice(2)) {
36
+ if (arg === '--')
37
+ break;
38
+ if (!arg.startsWith('-')) {
39
+ return Object.hasOwn(GROUPS, arg) ? [arg] : Object.keys(GROUPS);
40
+ }
41
+ if (VERSION_FLAGS.includes(arg))
42
+ return [];
43
+ }
44
+ return Object.keys(GROUPS);
45
+ }
19
46
  /** Split from index.ts so tests can drive the real program instead of hand-assembling one. */
20
- export function buildProgram() {
47
+ export async function buildProgram(argv = process.argv) {
21
48
  const program = new Command();
22
49
  program
23
50
  .name('tinyfish')
24
51
  .description('TinyFish CLI — run web automations from your terminal or agent.')
25
- .version(CLI_VERSION, '-V, --version', 'Show version')
52
+ .version(CLI_VERSION, VERSION_FLAGS.join(', '), 'Show version')
26
53
  .helpOption('-h, --help', 'Show help')
27
54
  .addHelpCommand(false)
28
55
  .enablePositionalOptions()
@@ -32,25 +59,10 @@ export function buildProgram() {
32
59
  process.env['TINYFISH_DEBUG'] = '1';
33
60
  }
34
61
  });
35
- registerAuth(program);
36
- registerOnboard(program);
37
- registerConnect(program);
38
- registerDoctor(program);
39
- registerUpgrade(program);
40
- registerConfigureClaude(program);
41
- registerBrowser(program);
42
- registerProfile(program);
43
- registerVault(program);
44
- registerWallet(program);
45
- const agentCmd = program
46
- .command('agent')
47
- .description('Agent automation commands')
48
- .enablePositionalOptions();
49
- const runCmd = registerRun(agentCmd);
50
- registerRuns(runCmd);
51
- registerBatch(agentCmd);
52
- registerSearch(program);
53
- registerFetch(program);
62
+ // Order is user-visible: help lists commands as registered.
63
+ for (const name of groupsFor(argv)) {
64
+ await GROUPS[name](program);
65
+ }
54
66
  const uninstallNotice = installNoticeEmit(program);
55
67
  return { program, uninstallNotice };
56
68
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiny-fish/cli",
3
- "version": "0.40.1-next.317",
3
+ "version": "0.41.1-next.321",
4
4
  "description": "TinyFish CLI — run web automations from your terminal",
5
5
  "type": "module",
6
6
  "bin": {
@@ -34,7 +34,7 @@
34
34
  "format:check": "oxfmt --check ."
35
35
  },
36
36
  "dependencies": {
37
- "@tiny-fish/sdk": "^0.5.0",
37
+ "@tiny-fish/sdk": "^0.6.0",
38
38
  "commander": "^12.0.0",
39
39
  "cross-spawn": "^7.0.6",
40
40
  "tldts": "^6.1.86",