@tiny-fish/cli 0.30.2-next.257 → 0.30.2-next.259
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/commands/auth.d.ts +1 -1
- package/dist/commands/auth.js +52 -52
- package/dist/commands/batch.d.ts +1 -1
- package/dist/commands/batch.js +54 -46
- package/dist/commands/browser.d.ts +1 -1
- package/dist/commands/browser.js +14 -14
- package/dist/commands/config-claude.d.ts +1 -1
- package/dist/commands/config-claude.js +22 -22
- package/dist/commands/connect.d.ts +3 -3
- package/dist/commands/connect.js +150 -150
- package/dist/commands/doctor.d.ts +4 -4
- package/dist/commands/doctor.js +104 -104
- package/dist/commands/fetch.d.ts +1 -1
- package/dist/commands/fetch.js +24 -27
- package/dist/commands/onboard.d.ts +1 -1
- package/dist/commands/onboard.js +50 -50
- package/dist/commands/profile.d.ts +3 -3
- package/dist/commands/profile.js +45 -45
- package/dist/commands/run.d.ts +1 -1
- package/dist/commands/run.js +78 -65
- package/dist/commands/runs.d.ts +1 -1
- package/dist/commands/runs.js +63 -50
- package/dist/commands/search.d.ts +1 -1
- package/dist/commands/search.js +16 -16
- package/dist/commands/upgrade.d.ts +2 -2
- package/dist/commands/upgrade.js +36 -36
- package/dist/commands/vault.d.ts +1 -1
- package/dist/commands/vault.js +48 -45
- package/dist/commands/wallet.d.ts +1 -1
- package/dist/commands/wallet.js +14 -14
- package/dist/index.js +2 -2
- package/dist/lib/auth.d.ts +5 -5
- package/dist/lib/auth.js +56 -56
- package/dist/lib/batch-store.d.ts +1 -1
- package/dist/lib/batch-store.js +4 -4
- package/dist/lib/chrome-cookies.d.ts +1 -1
- package/dist/lib/chrome-cookies.js +24 -24
- package/dist/lib/claude-config.js +37 -37
- package/dist/lib/cli-install.js +12 -12
- package/dist/lib/client.d.ts +2 -2
- package/dist/lib/client.js +61 -61
- package/dist/lib/connect-all.js +140 -134
- package/dist/lib/connect-auth.d.ts +2 -2
- package/dist/lib/connect-auth.js +15 -15
- package/dist/lib/connect-clients.d.ts +6 -6
- package/dist/lib/connect-clients.js +143 -143
- package/dist/lib/connect-fallback.d.ts +1 -1
- package/dist/lib/connect-fallback.js +38 -38
- package/dist/lib/connect-picker.d.ts +4 -4
- package/dist/lib/connect-picker.js +28 -28
- package/dist/lib/connect-runtime.d.ts +7 -7
- package/dist/lib/connect-runtime.js +61 -61
- package/dist/lib/constants.js +13 -13
- package/dist/lib/cursor-config.d.ts +1 -1
- package/dist/lib/cursor-config.js +30 -30
- package/dist/lib/doctor-report.d.ts +2 -2
- package/dist/lib/doctor-report.js +22 -22
- package/dist/lib/harness-detect.js +39 -39
- package/dist/lib/harness.js +9 -9
- package/dist/lib/hermes-env.js +26 -23
- package/dist/lib/install-root.js +12 -12
- package/dist/lib/notice.d.ts +1 -1
- package/dist/lib/notice.js +12 -12
- package/dist/lib/output.js +14 -14
- package/dist/lib/registration-detect.d.ts +3 -3
- package/dist/lib/registration-detect.js +82 -82
- package/dist/lib/setup-telemetry.d.ts +4 -4
- package/dist/lib/setup-telemetry.js +34 -34
- package/dist/lib/signals.js +1 -1
- package/dist/lib/skill-install.d.ts +3 -3
- package/dist/lib/skill-install.js +40 -40
- package/dist/lib/types.d.ts +8 -8
- package/dist/lib/verify.d.ts +1 -1
- package/dist/lib/verify.js +28 -28
- package/dist/program.d.ts +1 -1
- package/dist/program.js +28 -28
- package/package.json +1 -1
package/dist/commands/upgrade.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import spawn from
|
|
2
|
-
import { resolvedApiKey } from
|
|
3
|
-
import { CLI_VERSION, TINYFISH_CLI_PACKAGE } from
|
|
4
|
-
import { installRoot, readInstalledVersion } from
|
|
5
|
-
import { suppressNotice } from
|
|
6
|
-
import { errLine } from
|
|
7
|
-
import { sendUpgradeCompleted, telemetryDisabled, } from
|
|
8
|
-
import { installSignalGuard, SIGNAL_EXIT_CODES } from
|
|
9
|
-
import { installTinyFishCli } from
|
|
10
|
-
import { updateWebSkill } from
|
|
11
|
-
import { ConnectInterruptedError } from
|
|
1
|
+
import spawn from 'cross-spawn';
|
|
2
|
+
import { resolvedApiKey } from '../lib/auth.js';
|
|
3
|
+
import { CLI_VERSION, TINYFISH_CLI_PACKAGE } from '../lib/constants.js';
|
|
4
|
+
import { installRoot, readInstalledVersion } from '../lib/install-root.js';
|
|
5
|
+
import { suppressNotice } from '../lib/notice.js';
|
|
6
|
+
import { errLine } from '../lib/output.js';
|
|
7
|
+
import { sendUpgradeCompleted, telemetryDisabled, } from '../lib/setup-telemetry.js';
|
|
8
|
+
import { installSignalGuard, SIGNAL_EXIT_CODES } from '../lib/signals.js';
|
|
9
|
+
import { installTinyFishCli } from '../lib/cli-install.js';
|
|
10
|
+
import { updateWebSkill } from '../lib/skill-install.js';
|
|
11
|
+
import { ConnectInterruptedError } from '../lib/connect-runtime.js';
|
|
12
12
|
const VERSION_READ_TIMEOUT_MS = 2_000;
|
|
13
|
-
const INTERRUPTED_MESSAGE =
|
|
13
|
+
const INTERRUPTED_MESSAGE = 'Upgrade interrupted — run `tinyfish upgrade` again to finish.';
|
|
14
14
|
function attempt(label, run) {
|
|
15
15
|
try {
|
|
16
16
|
run();
|
|
@@ -27,23 +27,23 @@ 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, scope =
|
|
31
|
-
errLine(
|
|
30
|
+
export function runUpgrade(verbose = false, scope = 'both') {
|
|
31
|
+
errLine('Upgrading TinyFish...');
|
|
32
32
|
let refreshed = false;
|
|
33
33
|
try {
|
|
34
34
|
// Every selected step runs: one failing must not stall the other.
|
|
35
35
|
const failures = [
|
|
36
|
-
scope ===
|
|
36
|
+
scope === 'skill'
|
|
37
37
|
? undefined
|
|
38
|
-
: attempt(
|
|
39
|
-
scope ===
|
|
38
|
+
: attempt('update the TinyFish CLI', () => installTinyFishCli({ verbose })),
|
|
39
|
+
scope === 'cli'
|
|
40
40
|
? undefined
|
|
41
|
-
: attempt(
|
|
41
|
+
: attempt('refresh the TinyFish web skill', () => {
|
|
42
42
|
refreshed = updateWebSkill({ verbose });
|
|
43
43
|
}),
|
|
44
44
|
].filter((failure) => failure !== undefined);
|
|
45
45
|
if (failures.length > 0)
|
|
46
|
-
throw new Error(`tinyfish upgrade failed: ${failures.join(
|
|
46
|
+
throw new Error(`tinyfish upgrade failed: ${failures.join('; ')}`);
|
|
47
47
|
}
|
|
48
48
|
catch (error) {
|
|
49
49
|
if (!(error instanceof ConnectInterruptedError))
|
|
@@ -54,9 +54,9 @@ export function runUpgrade(verbose = false, scope = "both") {
|
|
|
54
54
|
}
|
|
55
55
|
const version = installedCliVersion();
|
|
56
56
|
// --skill-only never checked the CLI, so no versioned claim.
|
|
57
|
-
const upToDate = version && scope !==
|
|
57
|
+
const upToDate = version && scope !== 'skill'
|
|
58
58
|
? `TinyFish CLI ${version} is up to date.`
|
|
59
|
-
:
|
|
59
|
+
: 'TinyFish is up to date.';
|
|
60
60
|
// Only a rewritten skill needs an agent restart.
|
|
61
61
|
errLine(refreshed ? `${upToDate} Restart your agent to pick up the refreshed skill.` : upToDate);
|
|
62
62
|
return version;
|
|
@@ -69,8 +69,8 @@ function installedCliVersion() {
|
|
|
69
69
|
/** Fallback when no prefix was detected: npm's own global tree is the only place left to look. */
|
|
70
70
|
function globalCliVersion() {
|
|
71
71
|
try {
|
|
72
|
-
const result = spawn.sync(
|
|
73
|
-
const parsed = JSON.parse(result.stdout ??
|
|
72
|
+
const result = spawn.sync('npm', ['ls', '--global', '--depth=0', '--json', TINYFISH_CLI_PACKAGE], { encoding: 'utf8', timeout: VERSION_READ_TIMEOUT_MS });
|
|
73
|
+
const parsed = JSON.parse(result.stdout ?? '');
|
|
74
74
|
return parsed.dependencies?.[TINYFISH_CLI_PACKAGE]?.version ?? null;
|
|
75
75
|
}
|
|
76
76
|
catch {
|
|
@@ -78,7 +78,7 @@ function globalCliVersion() {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
/** `runUpgrade` plus its outcome telemetry, which must never change what the upgrade does. */
|
|
81
|
-
export async function runUpgradeCommand(verbose = false, scope =
|
|
81
|
+
export async function runUpgradeCommand(verbose = false, scope = 'both') {
|
|
82
82
|
// This command is the upgrade, so a trailing "an update is available" would be noise.
|
|
83
83
|
suppressNotice();
|
|
84
84
|
let reported = false;
|
|
@@ -92,21 +92,21 @@ export async function runUpgradeCommand(verbose = false, scope = "both") {
|
|
|
92
92
|
if (telemetryDisabled())
|
|
93
93
|
return;
|
|
94
94
|
// Interrupted skips the read — racing the exit. Undercounts; see posthog-events.md.
|
|
95
|
-
const toVersion = outcome ===
|
|
95
|
+
const toVersion = outcome === 'interrupted' ? null : (printedVersion ?? installedCliVersion());
|
|
96
96
|
await sendUpgradeCompleted(CLI_VERSION, toVersion, outcome, scope, resolvedApiKey());
|
|
97
97
|
};
|
|
98
98
|
const uninstallSignalGuard = installSignalGuard(async () => {
|
|
99
99
|
errLine(INTERRUPTED_MESSAGE);
|
|
100
|
-
await report(
|
|
100
|
+
await report('interrupted');
|
|
101
101
|
});
|
|
102
|
-
let outcome =
|
|
102
|
+
let outcome = 'updated';
|
|
103
103
|
try {
|
|
104
104
|
printedVersion = runUpgrade(verbose, scope);
|
|
105
105
|
if (process.exitCode === SIGNAL_EXIT_CODES.SIGINT)
|
|
106
|
-
outcome =
|
|
106
|
+
outcome = 'interrupted';
|
|
107
107
|
}
|
|
108
108
|
catch (error) {
|
|
109
|
-
outcome =
|
|
109
|
+
outcome = 'failed';
|
|
110
110
|
throw error;
|
|
111
111
|
}
|
|
112
112
|
finally {
|
|
@@ -117,16 +117,16 @@ export async function runUpgradeCommand(verbose = false, scope = "both") {
|
|
|
117
117
|
}
|
|
118
118
|
export function registerUpgrade(program) {
|
|
119
119
|
program
|
|
120
|
-
.command(
|
|
121
|
-
.description(
|
|
122
|
-
.option(
|
|
123
|
-
.option(
|
|
124
|
-
.option(
|
|
120
|
+
.command('upgrade')
|
|
121
|
+
.description('Update the TinyFish CLI and the use-tinyfish skill to the latest versions')
|
|
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')
|
|
125
125
|
.action(async (options) => {
|
|
126
126
|
if (options.cliOnly && options.skillOnly) {
|
|
127
|
-
throw new Error(
|
|
127
|
+
throw new Error('Pass either --cli-only or --skill-only, not both.');
|
|
128
128
|
}
|
|
129
|
-
const scope = options.cliOnly ?
|
|
129
|
+
const scope = options.cliOnly ? 'cli' : options.skillOnly ? 'skill' : 'both';
|
|
130
130
|
await runUpgradeCommand(Boolean(options.verbose), scope);
|
|
131
131
|
});
|
|
132
132
|
}
|
package/dist/commands/vault.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Command } from
|
|
1
|
+
import { Command } from 'commander';
|
|
2
2
|
export declare function registerVault(program: Command): void;
|
package/dist/commands/vault.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { getApiKey } from
|
|
2
|
-
import { vaultConnect, vaultConnections, vaultDisconnect, vaultItems, vaultSync, } from
|
|
3
|
-
import { err, handleApiError, out, outLine } from
|
|
4
|
-
const VALID_PROVIDERS = [
|
|
1
|
+
import { getApiKey } from '../lib/auth.js';
|
|
2
|
+
import { vaultConnect, vaultConnections, vaultDisconnect, vaultItems, vaultSync, } from '../lib/client.js';
|
|
3
|
+
import { err, handleApiError, out, outLine } from '../lib/output.js';
|
|
4
|
+
const VALID_PROVIDERS = ['1password', 'bitwarden'];
|
|
5
5
|
// Provider secrets are read from the environment, never flags — same model as
|
|
6
6
|
// the API key (TINYFISH_API_KEY). This keeps tokens out of shell history and
|
|
7
7
|
// process listings, and needs no interactive prompt (agent-safe).
|
|
8
|
-
const TOKEN_ENV =
|
|
9
|
-
const CLIENT_SECRET_ENV =
|
|
10
|
-
const MASTER_PASSWORD_ENV =
|
|
8
|
+
const TOKEN_ENV = 'TINYFISH_VAULT_TOKEN';
|
|
9
|
+
const CLIENT_SECRET_ENV = 'TINYFISH_VAULT_CLIENT_SECRET';
|
|
10
|
+
const MASTER_PASSWORD_ENV = 'TINYFISH_VAULT_MASTER_PASSWORD';
|
|
11
11
|
function requireEnv(name, field, provider) {
|
|
12
12
|
const value = process.env[name];
|
|
13
13
|
if (!value) {
|
|
@@ -18,47 +18,50 @@ function requireEnv(name, field, provider) {
|
|
|
18
18
|
}
|
|
19
19
|
function buildConnectRequest(opts) {
|
|
20
20
|
if (!opts.provider || !VALID_PROVIDERS.includes(opts.provider)) {
|
|
21
|
-
err({ error: `--provider must be one of: ${VALID_PROVIDERS.join(
|
|
21
|
+
err({ error: `--provider must be one of: ${VALID_PROVIDERS.join(', ')}` });
|
|
22
22
|
process.exit(1);
|
|
23
23
|
}
|
|
24
|
-
if (opts.provider ===
|
|
25
|
-
return {
|
|
24
|
+
if (opts.provider === '1password') {
|
|
25
|
+
return {
|
|
26
|
+
provider: '1password',
|
|
27
|
+
token: requireEnv(TOKEN_ENV, 'a service-account token', '1password'),
|
|
28
|
+
};
|
|
26
29
|
}
|
|
27
30
|
// bitwarden
|
|
28
31
|
if (!opts.clientId) {
|
|
29
|
-
err({ error:
|
|
32
|
+
err({ error: 'bitwarden requires --client-id' });
|
|
30
33
|
process.exit(1);
|
|
31
34
|
}
|
|
32
35
|
return {
|
|
33
|
-
provider:
|
|
36
|
+
provider: 'bitwarden',
|
|
34
37
|
clientId: opts.clientId,
|
|
35
|
-
clientSecret: requireEnv(CLIENT_SECRET_ENV,
|
|
36
|
-
masterPassword: requireEnv(MASTER_PASSWORD_ENV,
|
|
38
|
+
clientSecret: requireEnv(CLIENT_SECRET_ENV, 'a client secret', 'bitwarden'),
|
|
39
|
+
masterPassword: requireEnv(MASTER_PASSWORD_ENV, 'a master password', 'bitwarden'),
|
|
37
40
|
...(opts.serverUrl ? { serverUrl: opts.serverUrl } : {}),
|
|
38
41
|
};
|
|
39
42
|
}
|
|
40
43
|
// ── Pretty printers ───────────────────────────────────────────────────────────
|
|
41
44
|
function printConnections(connections) {
|
|
42
45
|
if (connections.length === 0) {
|
|
43
|
-
outLine(
|
|
46
|
+
outLine('No vault connections.');
|
|
44
47
|
return;
|
|
45
48
|
}
|
|
46
49
|
for (const c of connections) {
|
|
47
|
-
outLine(`${c.id} ${c.provider} ${c.connectionStatus} (validated: ${c.lastValidatedAt ??
|
|
50
|
+
outLine(`${c.id} ${c.provider} ${c.connectionStatus} (validated: ${c.lastValidatedAt ?? 'never'})`);
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
function printItems(items) {
|
|
51
54
|
if (items.length === 0) {
|
|
52
|
-
outLine(
|
|
55
|
+
outLine('No vault items. Connect a provider and run `tinyfish vault item sync`.');
|
|
53
56
|
return;
|
|
54
57
|
}
|
|
55
58
|
for (const item of items) {
|
|
56
|
-
const totp = item.hasTotp ?
|
|
57
|
-
outLine(`${item.itemId} ${item.label} (${item.vaultName}) ${item.domains.join(
|
|
59
|
+
const totp = item.hasTotp ? ' [TOTP]' : '';
|
|
60
|
+
outLine(`${item.itemId} ${item.label} (${item.vaultName}) ${item.domains.join(', ')}${totp}`);
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
function printConnect(result) {
|
|
61
|
-
outLine(
|
|
64
|
+
outLine('Vault connected');
|
|
62
65
|
outLine(`Connection ID: ${result.connectionId}`);
|
|
63
66
|
outLine(`Provider: ${result.provider}`);
|
|
64
67
|
outLine(`Items: ${result.items.length}`);
|
|
@@ -70,17 +73,17 @@ function printSync(result) {
|
|
|
70
73
|
// ── Command registration ──────────────────────────────────────────────────────
|
|
71
74
|
export function registerVault(program) {
|
|
72
75
|
const vaultCmd = program
|
|
73
|
-
.command(
|
|
74
|
-
.description(
|
|
76
|
+
.command('vault')
|
|
77
|
+
.description('Vault credential commands')
|
|
75
78
|
.enablePositionalOptions();
|
|
76
79
|
const connectionCmd = vaultCmd
|
|
77
|
-
.command(
|
|
78
|
-
.description(
|
|
80
|
+
.command('connection')
|
|
81
|
+
.description('Manage vault provider connections')
|
|
79
82
|
.enablePositionalOptions();
|
|
80
83
|
connectionCmd
|
|
81
|
-
.command(
|
|
82
|
-
.description(
|
|
83
|
-
.option(
|
|
84
|
+
.command('list')
|
|
85
|
+
.description('List connected vault providers')
|
|
86
|
+
.option('--pretty', 'Human-readable output')
|
|
84
87
|
.action(async (opts) => {
|
|
85
88
|
const apiKey = getApiKey();
|
|
86
89
|
try {
|
|
@@ -95,13 +98,13 @@ export function registerVault(program) {
|
|
|
95
98
|
}
|
|
96
99
|
});
|
|
97
100
|
connectionCmd
|
|
98
|
-
.command(
|
|
101
|
+
.command('add')
|
|
99
102
|
.description(`Connect a vault provider. Secrets come from the environment, not flags: ` +
|
|
100
103
|
`1password reads $${TOKEN_ENV}; bitwarden reads $${CLIENT_SECRET_ENV} and $${MASTER_PASSWORD_ENV}.`)
|
|
101
|
-
.requiredOption(
|
|
102
|
-
.option(
|
|
103
|
-
.option(
|
|
104
|
-
.option(
|
|
104
|
+
.requiredOption('--provider <provider>', `Vault provider (${VALID_PROVIDERS.join('|')})`)
|
|
105
|
+
.option('--client-id <id>', 'Bitwarden client ID (non-secret)')
|
|
106
|
+
.option('--server-url <url>', 'Self-hosted Bitwarden server URL')
|
|
107
|
+
.option('--pretty', 'Human-readable output')
|
|
105
108
|
.action(async (opts) => {
|
|
106
109
|
const apiKey = getApiKey();
|
|
107
110
|
const req = buildConnectRequest(opts);
|
|
@@ -117,10 +120,10 @@ export function registerVault(program) {
|
|
|
117
120
|
}
|
|
118
121
|
});
|
|
119
122
|
connectionCmd
|
|
120
|
-
.command(
|
|
121
|
-
.description(
|
|
122
|
-
.argument(
|
|
123
|
-
.option(
|
|
123
|
+
.command('remove')
|
|
124
|
+
.description('Disconnect a vault provider and delete its stored credentials')
|
|
125
|
+
.argument('<connectionId>', 'Connection ID to disconnect')
|
|
126
|
+
.option('--pretty', 'Human-readable output')
|
|
124
127
|
.action(async (connectionId, opts) => {
|
|
125
128
|
const apiKey = getApiKey();
|
|
126
129
|
try {
|
|
@@ -135,15 +138,15 @@ export function registerVault(program) {
|
|
|
135
138
|
}
|
|
136
139
|
});
|
|
137
140
|
const itemCmd = vaultCmd
|
|
138
|
-
.command(
|
|
139
|
-
.description(
|
|
141
|
+
.command('item')
|
|
142
|
+
.description('Inspect vault credential items')
|
|
140
143
|
.enablePositionalOptions();
|
|
141
144
|
itemCmd
|
|
142
|
-
.command(
|
|
145
|
+
.command('list')
|
|
143
146
|
.description("List vault credential items across all connections. Each item's `itemId` " +
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
.option(
|
|
147
|
+
'is what you pass to `agent run --credential-item-id`. If the list is empty ' +
|
|
148
|
+
'after connecting, run `vault item sync` first.')
|
|
149
|
+
.option('--pretty', 'Human-readable output')
|
|
147
150
|
.action(async (opts) => {
|
|
148
151
|
const apiKey = getApiKey();
|
|
149
152
|
try {
|
|
@@ -158,9 +161,9 @@ export function registerVault(program) {
|
|
|
158
161
|
}
|
|
159
162
|
});
|
|
160
163
|
itemCmd
|
|
161
|
-
.command(
|
|
162
|
-
.description(
|
|
163
|
-
.option(
|
|
164
|
+
.command('sync')
|
|
165
|
+
.description('Re-sync credential items from connected providers')
|
|
166
|
+
.option('--pretty', 'Human-readable output')
|
|
164
167
|
.action(async (opts) => {
|
|
165
168
|
const apiKey = getApiKey();
|
|
166
169
|
try {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Command } from
|
|
1
|
+
import { Command } from 'commander';
|
|
2
2
|
export declare function registerWallet(program: Command): void;
|
package/dist/commands/wallet.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import { WalletAutoReloadState } from
|
|
2
|
-
import { getApiKey } from
|
|
3
|
-
import { getWallet } from
|
|
4
|
-
import { handleApiError, out, outLine } from
|
|
1
|
+
import { WalletAutoReloadState } from '@tiny-fish/sdk';
|
|
2
|
+
import { getApiKey } from '../lib/auth.js';
|
|
3
|
+
import { getWallet } from '../lib/client.js';
|
|
4
|
+
import { handleApiError, out, outLine } from '../lib/output.js';
|
|
5
5
|
function formatWallet(wallet) {
|
|
6
6
|
outLine(`Balance: ${wallet.available_balance} ${wallet.currency}`);
|
|
7
7
|
if (wallet.auto_reload === null) {
|
|
8
|
-
outLine(
|
|
8
|
+
outLine('Auto-reload: unavailable');
|
|
9
9
|
}
|
|
10
10
|
else if (wallet.auto_reload.state === WalletAutoReloadState.UNCONFIGURED) {
|
|
11
|
-
outLine(
|
|
11
|
+
outLine('Auto-reload: unconfigured');
|
|
12
12
|
}
|
|
13
13
|
else {
|
|
14
14
|
const { state, threshold, recharge_to } = wallet.auto_reload;
|
|
15
15
|
outLine(`Auto-reload: ${state} (threshold ${threshold}, recharge to ${recharge_to})`);
|
|
16
16
|
}
|
|
17
17
|
if (wallet.pending_top_up === null) {
|
|
18
|
-
outLine(
|
|
18
|
+
outLine('Pending top-up: none');
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
21
|
outLine(`Pending top-up: ${wallet.pending_top_up.amount} (started ${wallet.pending_top_up.started_at})`);
|
|
22
22
|
}
|
|
23
23
|
if (wallet.rates === null) {
|
|
24
|
-
outLine(
|
|
24
|
+
outLine('Rates: unavailable');
|
|
25
25
|
}
|
|
26
26
|
else if (wallet.rates.meters.length === 0) {
|
|
27
|
-
outLine(
|
|
27
|
+
outLine('Rates: none');
|
|
28
28
|
}
|
|
29
29
|
else {
|
|
30
30
|
for (const meter of wallet.rates.meters) {
|
|
31
|
-
const per = meter.per ? `/${meter.per}` :
|
|
31
|
+
const per = meter.per ? `/${meter.per}` : '';
|
|
32
32
|
outLine(`${meter.label}: ${meter.unit_amount} ${meter.currency}${per}`);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
export function registerWallet(program) {
|
|
37
|
-
const wallet = program.command(
|
|
37
|
+
const wallet = program.command('wallet').description('View your TinyFish wallet');
|
|
38
38
|
wallet
|
|
39
|
-
.command(
|
|
40
|
-
.description(
|
|
41
|
-
.option(
|
|
39
|
+
.command('status')
|
|
40
|
+
.description('Show wallet balance, auto-reload, pending top-up, and rates')
|
|
41
|
+
.option('--pretty', 'Human-readable output')
|
|
42
42
|
.action(async (opts) => {
|
|
43
43
|
const apiKey = getApiKey();
|
|
44
44
|
try {
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { buildProgram } from
|
|
2
|
+
import { buildProgram } from './program.js';
|
|
3
3
|
const { program } = buildProgram();
|
|
4
4
|
// Await parseAsync so async command handlers complete before the process exits
|
|
5
5
|
program.parseAsync(process.argv).catch((e) => {
|
|
6
|
-
process.stderr.write(JSON.stringify({ error: e instanceof Error ? e.message : String(e) }) +
|
|
6
|
+
process.stderr.write(JSON.stringify({ error: e instanceof Error ? e.message : String(e) }) + '\n');
|
|
7
7
|
process.exit(1);
|
|
8
8
|
});
|
package/dist/lib/auth.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { DASHBOARD_URL, getDashboardUrl } from
|
|
1
|
+
export { DASHBOARD_URL, getDashboardUrl } from './constants.js';
|
|
2
2
|
export declare function configDir(): string;
|
|
3
3
|
/** Install channel baked onto connect context; the connect flow is always CLI-driven. */
|
|
4
4
|
export declare const CONNECT_SOURCE = "tinyfish_cli";
|
|
5
5
|
export declare const CONNECT_ATTEMPT_ENV = "TINYFISH_CONNECT_ATTEMPT_ID";
|
|
6
6
|
/** Mirrors ConnectAuthMode; duplicated to keep auth.ts free of connect-runtime imports. */
|
|
7
|
-
export type RecordedAuthMode =
|
|
7
|
+
export type RecordedAuthMode = 'api-key' | 'oauth' | 'deferred';
|
|
8
8
|
export interface ConnectEntry {
|
|
9
9
|
attempt_id: string;
|
|
10
10
|
auth_mode?: RecordedAuthMode;
|
|
@@ -33,7 +33,7 @@ export declare function saveConfig(apiKey: string): void;
|
|
|
33
33
|
/** `authMode` omitted rewrites the entry without one: a reconnect that degraded must not keep a stale key claim. */
|
|
34
34
|
export declare function saveConnectContext(client: string, attemptId: string, authMode?: RecordedAuthMode): void;
|
|
35
35
|
/** Distinguishes a missing entry from an unreadable config file. */
|
|
36
|
-
export declare function connectContextState(client: string):
|
|
36
|
+
export declare function connectContextState(client: string): 'present' | 'absent' | 'unreadable';
|
|
37
37
|
/** Kept marker after uninstall makes doctor offer to reinstall the harness. */
|
|
38
38
|
export declare function clearConnectContext(client: string): void;
|
|
39
39
|
interface EnvironmentOptions {
|
|
@@ -46,10 +46,10 @@ export declare function clearConfig(): boolean;
|
|
|
46
46
|
export declare function isHeaderSafe(key: string): boolean;
|
|
47
47
|
export declare function validateKeyFormat(key: string): boolean;
|
|
48
48
|
export declare function maskKey(key: string): string;
|
|
49
|
-
export type KeySource =
|
|
49
|
+
export type KeySource = 'explicit' | 'env' | 'config' | 'none';
|
|
50
50
|
export interface ResolvedKey {
|
|
51
51
|
key: string;
|
|
52
|
-
source: Exclude<KeySource,
|
|
52
|
+
source: Exclude<KeySource, 'none'>;
|
|
53
53
|
}
|
|
54
54
|
export interface UnresolvedKey {
|
|
55
55
|
error: string;
|