@tiny-fish/cli 0.24.1-next.211 → 0.24.1-next.212

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 CHANGED
@@ -101,6 +101,9 @@ Brings both halves of an install current: the global `@tiny-fish/cli` package an
101
101
  Successful steps are summarised in one line each. Add `--verbose` to see the full npm and skills
102
102
  output; a failing step prints its output either way.
103
103
 
104
+ `--cli-only` updates just the global package and `--skill-only` refreshes just the skill. The two
105
+ flags are mutually exclusive.
106
+
104
107
  The skill step refreshes only the TinyFish skill, and only for the agents you ran
105
108
  `tinyfish connect` against. Other global skills, and agents you never connected, are left alone.
106
109
  The refresh overwrites your copy of the skill, including any local edits to it. Restart your
@@ -9,6 +9,8 @@ interface NativeConnectOptions {
9
9
  attemptId?: string;
10
10
  /** Headless: refuse rather than fall back to an unfinishable browser sign-in. */
11
11
  keyAuthOnly?: boolean;
12
+ /** Internal only: false leaves the global npm tree untouched. */
13
+ cliInstall?: boolean;
12
14
  /** Set by `--all`: the CLI install already ran once, upfront. */
13
15
  hoistedCliInstall?: TakeHoistedCliInstall;
14
16
  /** Lets `--all` warn in its summary instead of all-green. */
@@ -23,7 +25,7 @@ export declare function connectOpenClaw(options: {
23
25
  apiKey?: string;
24
26
  mcpUrl: string;
25
27
  launch: boolean;
26
- installCli?: boolean;
28
+ cliInstall?: boolean;
27
29
  attemptId?: string;
28
30
  /** Set by `--all`: the CLI install already ran once, upfront. */
29
31
  hoistedCliInstall?: TakeHoistedCliInstall;
@@ -162,7 +162,9 @@ function runPostInstallSteps(client, options, state, telemetry, signInDeferred)
162
162
  }
163
163
  };
164
164
  try {
165
- attempt("cli_install", () => runCliInstallStep(options, telemetry));
165
+ if (options.cliInstall !== false) {
166
+ attempt("cli_install", () => runCliInstallStep(options, telemetry));
167
+ }
166
168
  if (client.skillAgent) {
167
169
  attempt("skill_install", () => {
168
170
  installWebSkill(client);
@@ -275,7 +277,7 @@ export async function connectOpenClaw(options) {
275
277
  });
276
278
  }
277
279
  }
278
- else if (options.installCli !== false) {
280
+ else if (options.cliInstall !== false) {
279
281
  state.stage = "cli_install";
280
282
  installTinyFishCli({ verbose: true });
281
283
  telemetry.track("checkpoint", { phase: "cli_installed" });
@@ -87,7 +87,7 @@ async function connectAgent(id) {
87
87
  return;
88
88
  const mcpUrl = new URL("/mcp", BASE_URL).toString();
89
89
  if (id === "openclaw") {
90
- await connectOpenClaw({ mcpUrl, launch: false, installCli: false });
90
+ await connectOpenClaw({ mcpUrl, launch: false, cliInstall: false });
91
91
  }
92
92
  else {
93
93
  await agent.connect({ mcpUrl, launch: false });
@@ -1,6 +1,7 @@
1
1
  import { Command } from "commander";
2
+ import { type UpgradeScope } from "../lib/setup-telemetry.js";
2
3
  /** Returns the version now installed, so the caller reports exactly what the user was told. */
3
- export declare function runUpgrade(verbose?: boolean): string | null;
4
+ export declare function runUpgrade(verbose?: boolean, scope?: UpgradeScope): string | null;
4
5
  /** `runUpgrade` plus its outcome telemetry, which must never change what the upgrade does. */
5
- export declare function runUpgradeCommand(verbose?: boolean): Promise<void>;
6
+ export declare function runUpgradeCommand(verbose?: boolean, scope?: UpgradeScope): Promise<void>;
6
7
  export declare function registerUpgrade(program: Command): void;
@@ -27,16 +27,20 @@ function attempt(label, run) {
27
27
  }
28
28
  }
29
29
  /** Returns the version now installed, so the caller reports exactly what the user was told. */
30
- export function runUpgrade(verbose = false) {
30
+ export function runUpgrade(verbose = false, scope = "both") {
31
31
  errLine("Upgrading TinyFish...");
32
32
  let refreshed = false;
33
33
  try {
34
- // Both steps always run: neither artifact should stay stale because the other failed.
34
+ // Every selected step runs: one failing must not stall the other.
35
35
  const failures = [
36
- attempt("update the TinyFish CLI", () => installTinyFishCli({ verbose })),
37
- attempt("refresh the TinyFish web skill", () => {
38
- refreshed = updateWebSkill({ verbose });
39
- }),
36
+ scope === "skill"
37
+ ? undefined
38
+ : attempt("update the TinyFish CLI", () => installTinyFishCli({ verbose })),
39
+ scope === "cli"
40
+ ? undefined
41
+ : attempt("refresh the TinyFish web skill", () => {
42
+ refreshed = updateWebSkill({ verbose });
43
+ }),
40
44
  ].filter((failure) => failure !== undefined);
41
45
  if (failures.length > 0)
42
46
  throw new Error(`tinyfish upgrade failed: ${failures.join("; ")}`);
@@ -49,7 +53,10 @@ export function runUpgrade(verbose = false) {
49
53
  return null;
50
54
  }
51
55
  const version = installedCliVersion();
52
- const upToDate = version ? `TinyFish CLI ${version} is up to date.` : "TinyFish is up to date.";
56
+ // --skill-only never checked the CLI, so no versioned claim.
57
+ const upToDate = version && scope !== "skill"
58
+ ? `TinyFish CLI ${version} is up to date.`
59
+ : "TinyFish is up to date.";
53
60
  // Only a rewritten skill needs an agent restart.
54
61
  errLine(refreshed ? `${upToDate} Restart your agent to pick up the refreshed skill.` : upToDate);
55
62
  return version;
@@ -71,7 +78,7 @@ function globalCliVersion() {
71
78
  }
72
79
  }
73
80
  /** `runUpgrade` plus its outcome telemetry, which must never change what the upgrade does. */
74
- export async function runUpgradeCommand(verbose = false) {
81
+ export async function runUpgradeCommand(verbose = false, scope = "both") {
75
82
  // This command is the upgrade, so a trailing "an update is available" would be noise.
76
83
  suppressNotice();
77
84
  let reported = false;
@@ -86,7 +93,7 @@ export async function runUpgradeCommand(verbose = false) {
86
93
  return;
87
94
  // Interrupted skips the read — racing the exit. Undercounts; see posthog-events.md.
88
95
  const toVersion = outcome === "interrupted" ? null : (printedVersion ?? installedCliVersion());
89
- await sendUpgradeCompleted(CLI_VERSION, toVersion, outcome, resolvedApiKey());
96
+ await sendUpgradeCompleted(CLI_VERSION, toVersion, outcome, scope, resolvedApiKey());
90
97
  };
91
98
  const uninstallSignalGuard = installSignalGuard(async () => {
92
99
  errLine(INTERRUPTED_MESSAGE);
@@ -94,7 +101,7 @@ export async function runUpgradeCommand(verbose = false) {
94
101
  });
95
102
  let outcome = "updated";
96
103
  try {
97
- printedVersion = runUpgrade(verbose);
104
+ printedVersion = runUpgrade(verbose, scope);
98
105
  if (process.exitCode === SIGNAL_EXIT_CODES.SIGINT)
99
106
  outcome = "interrupted";
100
107
  }
@@ -113,7 +120,13 @@ export function registerUpgrade(program) {
113
120
  .command("upgrade")
114
121
  .description("Update the TinyFish CLI and the use-tinyfish skill to the latest versions")
115
122
  .option("--verbose", "Print the full npm and skills output instead of only on failure")
123
+ .option("--cli-only", "Update only the TinyFish CLI, leaving the skill untouched")
124
+ .option("--skill-only", "Refresh only the use-tinyfish skill, leaving the CLI untouched")
116
125
  .action(async (options) => {
117
- await runUpgradeCommand(Boolean(options.verbose));
126
+ if (options.cliOnly && options.skillOnly) {
127
+ throw new Error("Pass either --cli-only or --skill-only, not both.");
128
+ }
129
+ const scope = options.cliOnly ? "cli" : options.skillOnly ? "skill" : "both";
130
+ await runUpgradeCommand(Boolean(options.verbose), scope);
118
131
  });
119
132
  }
@@ -64,7 +64,9 @@ export declare const setupCompletedPayloadSchema: z.ZodObject<{
64
64
  export type SetupCompletedPayload = z.infer<typeof setupCompletedPayloadSchema>;
65
65
  export type HarnessResult = z.infer<typeof harnessResultSchema>;
66
66
  export type UpgradeOutcome = "updated" | "failed" | "interrupted";
67
+ /** Step selection; "updated" means every selected step ran. */
68
+ export type UpgradeScope = "both" | "cli" | "skill";
67
69
  /** `toVersion` is null when the run was interrupted or the installed version could not be read. */
68
- export declare function sendUpgradeCompleted(fromVersion: string, toVersion: string | null, outcome: UpgradeOutcome, apiKey?: string): Promise<void>;
70
+ export declare function sendUpgradeCompleted(fromVersion: string, toVersion: string | null, outcome: UpgradeOutcome, scope: UpgradeScope, apiKey?: string): Promise<void>;
69
71
  export declare function sendSetupCompleted(mcpUrl: string, harnesses: HarnessResult[], apiKey?: string): Promise<void>;
70
72
  export {};
@@ -111,7 +111,7 @@ export const setupCompletedPayloadSchema = z.object({
111
111
  cli_version: z.string(),
112
112
  });
113
113
  /** `toVersion` is null when the run was interrupted or the installed version could not be read. */
114
- export async function sendUpgradeCompleted(fromVersion, toVersion, outcome, apiKey) {
114
+ export async function sendUpgradeCompleted(fromVersion, toVersion, outcome, scope, apiKey) {
115
115
  await postConnectEvent({
116
116
  endpoint: new URL("/api/cli/connect-event", BASE_URL).toString(),
117
117
  body: JSON.stringify({
@@ -119,6 +119,7 @@ export async function sendUpgradeCompleted(fromVersion, toVersion, outcome, apiK
119
119
  from_version: fromVersion,
120
120
  to_version: toVersion,
121
121
  outcome,
122
+ scope,
122
123
  }),
123
124
  attempts: 1,
124
125
  label: "upgrade",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiny-fish/cli",
3
- "version": "0.24.1-next.211",
3
+ "version": "0.24.1-next.212",
4
4
  "description": "TinyFish CLI — run web automations from your terminal",
5
5
  "type": "module",
6
6
  "bin": {