@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.
Files changed (77) hide show
  1. package/dist/commands/auth.d.ts +1 -1
  2. package/dist/commands/auth.js +52 -52
  3. package/dist/commands/batch.d.ts +1 -1
  4. package/dist/commands/batch.js +54 -46
  5. package/dist/commands/browser.d.ts +1 -1
  6. package/dist/commands/browser.js +14 -14
  7. package/dist/commands/config-claude.d.ts +1 -1
  8. package/dist/commands/config-claude.js +22 -22
  9. package/dist/commands/connect.d.ts +3 -3
  10. package/dist/commands/connect.js +150 -150
  11. package/dist/commands/doctor.d.ts +4 -4
  12. package/dist/commands/doctor.js +104 -104
  13. package/dist/commands/fetch.d.ts +1 -1
  14. package/dist/commands/fetch.js +24 -27
  15. package/dist/commands/onboard.d.ts +1 -1
  16. package/dist/commands/onboard.js +50 -50
  17. package/dist/commands/profile.d.ts +3 -3
  18. package/dist/commands/profile.js +45 -45
  19. package/dist/commands/run.d.ts +1 -1
  20. package/dist/commands/run.js +78 -65
  21. package/dist/commands/runs.d.ts +1 -1
  22. package/dist/commands/runs.js +63 -50
  23. package/dist/commands/search.d.ts +1 -1
  24. package/dist/commands/search.js +16 -16
  25. package/dist/commands/upgrade.d.ts +2 -2
  26. package/dist/commands/upgrade.js +36 -36
  27. package/dist/commands/vault.d.ts +1 -1
  28. package/dist/commands/vault.js +48 -45
  29. package/dist/commands/wallet.d.ts +1 -1
  30. package/dist/commands/wallet.js +14 -14
  31. package/dist/index.js +2 -2
  32. package/dist/lib/auth.d.ts +5 -5
  33. package/dist/lib/auth.js +56 -56
  34. package/dist/lib/batch-store.d.ts +1 -1
  35. package/dist/lib/batch-store.js +4 -4
  36. package/dist/lib/chrome-cookies.d.ts +1 -1
  37. package/dist/lib/chrome-cookies.js +24 -24
  38. package/dist/lib/claude-config.js +37 -37
  39. package/dist/lib/cli-install.js +12 -12
  40. package/dist/lib/client.d.ts +2 -2
  41. package/dist/lib/client.js +61 -61
  42. package/dist/lib/connect-all.js +140 -134
  43. package/dist/lib/connect-auth.d.ts +2 -2
  44. package/dist/lib/connect-auth.js +15 -15
  45. package/dist/lib/connect-clients.d.ts +6 -6
  46. package/dist/lib/connect-clients.js +143 -143
  47. package/dist/lib/connect-fallback.d.ts +1 -1
  48. package/dist/lib/connect-fallback.js +38 -38
  49. package/dist/lib/connect-picker.d.ts +4 -4
  50. package/dist/lib/connect-picker.js +28 -28
  51. package/dist/lib/connect-runtime.d.ts +7 -7
  52. package/dist/lib/connect-runtime.js +61 -61
  53. package/dist/lib/constants.js +13 -13
  54. package/dist/lib/cursor-config.d.ts +1 -1
  55. package/dist/lib/cursor-config.js +30 -30
  56. package/dist/lib/doctor-report.d.ts +2 -2
  57. package/dist/lib/doctor-report.js +22 -22
  58. package/dist/lib/harness-detect.js +39 -39
  59. package/dist/lib/harness.js +9 -9
  60. package/dist/lib/hermes-env.js +26 -23
  61. package/dist/lib/install-root.js +12 -12
  62. package/dist/lib/notice.d.ts +1 -1
  63. package/dist/lib/notice.js +12 -12
  64. package/dist/lib/output.js +14 -14
  65. package/dist/lib/registration-detect.d.ts +3 -3
  66. package/dist/lib/registration-detect.js +82 -82
  67. package/dist/lib/setup-telemetry.d.ts +4 -4
  68. package/dist/lib/setup-telemetry.js +34 -34
  69. package/dist/lib/signals.js +1 -1
  70. package/dist/lib/skill-install.d.ts +3 -3
  71. package/dist/lib/skill-install.js +40 -40
  72. package/dist/lib/types.d.ts +8 -8
  73. package/dist/lib/verify.d.ts +1 -1
  74. package/dist/lib/verify.js +28 -28
  75. package/dist/program.d.ts +1 -1
  76. package/dist/program.js +28 -28
  77. package/package.json +1 -1
@@ -1,44 +1,44 @@
1
- import * as readline from "readline/promises";
2
- import { getApiKey, saveConfig } from "../lib/auth.js";
3
- import { fetchContentGet, searchQuery } from "../lib/client.js";
4
- import { BASE_URL, TINYFISH_API_KEY_VAR } from "../lib/constants.js";
5
- import { errLine, handleApiError, outLine } from "../lib/output.js";
6
- import { connectClaudeCode, connectCodex, connectHermes, connectOpenClaw, connectOpencode, launchAgent, } from "./connect.js";
1
+ import * as readline from 'readline/promises';
2
+ import { getApiKey, saveConfig } from '../lib/auth.js';
3
+ import { fetchContentGet, searchQuery } from '../lib/client.js';
4
+ import { BASE_URL, TINYFISH_API_KEY_VAR } from '../lib/constants.js';
5
+ import { errLine, handleApiError, outLine } from '../lib/output.js';
6
+ import { connectClaudeCode, connectCodex, connectHermes, connectOpenClaw, connectOpencode, launchAgent, } from './connect.js';
7
7
  const EXAMPLE_QUERIES = [
8
- "What are recent changes in the AI dev stack? Give me the top 5 changes that matter, why they matter, and any action needed.",
9
- "Find a new-grad software engineering role posted in the last 24 hours and fetch the job description.",
8
+ 'What are recent changes in the AI dev stack? Give me the top 5 changes that matter, why they matter, and any action needed.',
9
+ 'Find a new-grad software engineering role posted in the last 24 hours and fetch the job description.',
10
10
  "Analyse today's market and recommend the best investments for $5,000 with expected returns and risks.",
11
11
  ];
12
12
  const AGENTS = [
13
- { id: "claude-code", label: "Claude Code", connect: connectClaudeCode },
14
- { id: "codex", label: "Codex", connect: connectCodex },
15
- { id: "hermes", label: "Hermes", connect: connectHermes },
16
- { id: "openclaw", label: "OpenClaw", connect: connectOpenClaw },
17
- { id: "opencode", label: "OpenCode", connect: connectOpencode },
13
+ { id: 'claude-code', label: 'Claude Code', connect: connectClaudeCode },
14
+ { id: 'codex', label: 'Codex', connect: connectCodex },
15
+ { id: 'hermes', label: 'Hermes', connect: connectHermes },
16
+ { id: 'openclaw', label: 'OpenClaw', connect: connectOpenClaw },
17
+ { id: 'opencode', label: 'OpenCode', connect: connectOpencode },
18
18
  ];
19
19
  function cleanFetchedContent(text) {
20
20
  const cleaned = text
21
- .replace(/!\[[^\]]*\]\([^)]+\)/g, "")
22
- .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
23
- .replace(/^#{1,6}\s+/gm, "")
24
- .replace(/[ \t]+/g, " ")
25
- .replace(/\n{3,}/g, "\n\n")
21
+ .replace(/!\[[^\]]*\]\([^)]+\)/g, '')
22
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
23
+ .replace(/^#{1,6}\s+/gm, '')
24
+ .replace(/[ \t]+/g, ' ')
25
+ .replace(/\n{3,}/g, '\n\n')
26
26
  .trim();
27
27
  if (cleaned.length <= 1_200)
28
28
  return cleaned;
29
29
  const shortened = cleaned.slice(0, 1_200);
30
- return `${shortened.slice(0, shortened.lastIndexOf(" "))}…`;
30
+ return `${shortened.slice(0, shortened.lastIndexOf(' '))}…`;
31
31
  }
32
32
  function isUsefulFetchedContent(text) {
33
- const normalized = text.replace(/\s+/g, " ").trim();
33
+ const normalized = text.replace(/\s+/g, ' ').trim();
34
34
  return (normalized.length >= 120 &&
35
- normalized.split(" ").length >= 20 &&
35
+ normalized.split(' ').length >= 20 &&
36
36
  !/about press copyright contact us creators|there was an error while loading/i.test(normalized));
37
37
  }
38
38
  function parseAgents(value) {
39
39
  if (!value.trim())
40
40
  return [];
41
- const selections = value.split(",").map((item) => item.trim());
41
+ const selections = value.split(',').map((item) => item.trim());
42
42
  return selections.map((selection) => {
43
43
  const agent = AGENTS[Number(selection) - 1];
44
44
  if (!agent)
@@ -56,7 +56,7 @@ async function ask(question) {
56
56
  }
57
57
  }
58
58
  function sdkSnippet(language, query) {
59
- if (language === "python") {
59
+ if (language === 'python') {
60
60
  return `from tinyfish import TinyFish
61
61
 
62
62
  client = TinyFish()
@@ -85,8 +85,8 @@ async function connectAgent(id) {
85
85
  const agent = AGENTS.find((candidate) => candidate.id === id);
86
86
  if (!agent)
87
87
  return;
88
- const mcpUrl = new URL("/mcp", BASE_URL).toString();
89
- if (id === "openclaw") {
88
+ const mcpUrl = new URL('/mcp', BASE_URL).toString();
89
+ if (id === 'openclaw') {
90
90
  await connectOpenClaw({ mcpUrl, launch: false, cliInstall: false });
91
91
  }
92
92
  else {
@@ -98,33 +98,33 @@ function parseSelectedAgent(value, selected) {
98
98
  return undefined;
99
99
  const agent = selected[Number(value) - 1];
100
100
  if (!agent)
101
- throw new Error("Choose one of the agents you connected.");
101
+ throw new Error('Choose one of the agents you connected.');
102
102
  return agent;
103
103
  }
104
104
  async function chooseQuery(query, interactive) {
105
105
  if (query)
106
106
  return query;
107
107
  if (!interactive)
108
- throw new Error("Pass a query, or run `tinyfish onboard` in a terminal.");
109
- outLine("\nChoose a live-web job, or type your own:");
108
+ throw new Error('Pass a query, or run `tinyfish onboard` in a terminal.');
109
+ outLine('\nChoose a live-web job, or type your own:');
110
110
  EXAMPLE_QUERIES.forEach((example, index) => outLine(` ${index + 1}. ${example}`));
111
- const answer = await ask("Job [1]: ");
112
- return EXAMPLE_QUERIES[Number(answer || "1") - 1] ?? answer;
111
+ const answer = await ask('Job [1]: ');
112
+ return EXAMPLE_QUERIES[Number(answer || '1') - 1] ?? answer;
113
113
  }
114
114
  async function runSearchStep(query, apiKey, persistEnvKey) {
115
115
  outLine(`\n1. Searching the live web for: ${query}`);
116
116
  const search = await searchQuery({ query }, apiKey);
117
117
  if (persistEnvKey) {
118
118
  saveConfig(apiKey);
119
- outLine("✓ API key saved to ~/.tinyfish/config.json");
119
+ outLine('✓ API key saved to ~/.tinyfish/config.json');
120
120
  }
121
121
  if (!search.results.length) {
122
- throw new Error("Search returned no results. Try a more specific query.");
122
+ throw new Error('Search returned no results. Try a more specific query.');
123
123
  }
124
- outLine("\nSearch results");
124
+ outLine('\nSearch results');
125
125
  for (const result of search.results.slice(0, 3)) {
126
126
  outLine(` ${result.position}. ${result.title}\n` +
127
- ` ${result.site_name}${result.date ? ` · ${result.date}` : ""}\n` +
127
+ ` ${result.site_name}${result.date ? ` · ${result.date}` : ''}\n` +
128
128
  ` ${result.snippet}\n` +
129
129
  ` ${result.url}`);
130
130
  }
@@ -136,9 +136,9 @@ async function runFetchStep(results, apiKey) {
136
136
  let lastFetchError;
137
137
  for (const candidate of candidates) {
138
138
  try {
139
- const fetched = await fetchContentGet({ urls: [candidate.url], format: "markdown" }, apiKey);
139
+ const fetched = await fetchContentGet({ urls: [candidate.url], format: 'markdown' }, apiKey);
140
140
  const page = fetched.results[0];
141
- if (page && typeof page.text === "string" && isUsefulFetchedContent(page.text)) {
141
+ if (page && typeof page.text === 'string' && isUsefulFetchedContent(page.text)) {
142
142
  return { source: candidate, text: cleanFetchedContent(page.text) };
143
143
  }
144
144
  }
@@ -149,13 +149,13 @@ async function runFetchStep(results, apiKey) {
149
149
  }
150
150
  if (failedFetches === candidates.length)
151
151
  throw lastFetchError;
152
- throw new Error("Search found sources, but Fetch did not return useful page content.");
152
+ throw new Error('Search found sources, but Fetch did not return useful page content.');
153
153
  }
154
154
  function renderFetchedResult({ source, text }) {
155
155
  outLine(`\n2. Fetched source\n ${source.title}\n ${source.site_name} · ${source.url}`);
156
156
  outLine(`\nWhy it matched\n${source.snippet}`);
157
157
  outLine(`\nFetched content\n${text}`);
158
- outLine("\n✓ Search found relevant sources; Fetch returned clean, usable content.");
158
+ outLine('\n✓ Search found relevant sources; Fetch returned clean, usable content.');
159
159
  }
160
160
  function agentLabel(id) {
161
161
  return AGENTS.find((agent) => agent.id === id)?.label ?? id;
@@ -166,9 +166,9 @@ function errorMessage(error) {
166
166
  async function runAgentSteps(interactive) {
167
167
  if (!interactive)
168
168
  return;
169
- outLine("\n3. Add TinyFish to your agents (choose any, or press Enter to skip):");
169
+ outLine('\n3. Add TinyFish to your agents (choose any, or press Enter to skip):');
170
170
  AGENTS.forEach((agent, index) => outLine(` ${index + 1}. ${agent.label}`));
171
- const selected = parseAgents(await ask("Agents [e.g. 1,2]: "));
171
+ const selected = parseAgents(await ask('Agents [e.g. 1,2]: '));
172
172
  const connected = [];
173
173
  for (const id of selected) {
174
174
  try {
@@ -181,9 +181,9 @@ async function runAgentSteps(interactive) {
181
181
  }
182
182
  if (!connected.length)
183
183
  return;
184
- outLine("\n4. Open an agent now:");
184
+ outLine('\n4. Open an agent now:');
185
185
  connected.forEach((id, index) => outLine(` ${index + 1}. ${agentLabel(id)}`));
186
- const launchId = parseSelectedAgent(await ask("Open [number or Enter to skip]: "), connected);
186
+ const launchId = parseSelectedAgent(await ask('Open [number or Enter to skip]: '), connected);
187
187
  if (!launchId)
188
188
  return;
189
189
  try {
@@ -196,21 +196,21 @@ async function runAgentSteps(interactive) {
196
196
  async function runSdkStep(interactive, query) {
197
197
  if (!interactive)
198
198
  return;
199
- const choice = await ask("\nShow this as SDK code? [t] TypeScript, [p] Python, [Enter] skip: ");
199
+ const choice = await ask('\nShow this as SDK code? [t] TypeScript, [p] Python, [Enter] skip: ');
200
200
  if (!choice)
201
201
  return;
202
- const language = choice === "p" || choice === "python" ? "python" : "typescript";
202
+ const language = choice === 'p' || choice === 'python' ? 'python' : 'typescript';
203
203
  outLine(`\n${sdkSnippet(language, query)}\n`);
204
204
  }
205
205
  export function registerOnboard(program) {
206
206
  program
207
- .command("onboard")
208
- .description("Run a guided Search → Fetch demo, then add TinyFish to your agents or SDK")
209
- .argument("[query]", "A real topic to research")
210
- .addHelpText("after", "\nExamples:\n" +
207
+ .command('onboard')
208
+ .description('Run a guided Search → Fetch demo, then add TinyFish to your agents or SDK')
209
+ .argument('[query]', 'A real topic to research')
210
+ .addHelpText('after', '\nExamples:\n' +
211
211
  ' tinyfish onboard "What changed in the AI dev stack this week?"\n' +
212
- "\nAgents: claude-code, codex, hermes, openclaw, opencode.\n" +
213
- "Run `tinyfish connect <client> --launch` later to add one directly.")
212
+ '\nAgents: claude-code, codex, hermes, openclaw, opencode.\n' +
213
+ 'Run `tinyfish connect <client> --launch` later to add one directly.')
214
214
  .action(async (query) => {
215
215
  const apiKey = getApiKey();
216
216
  const persistEnvKey = Boolean(process.env[TINYFISH_API_KEY_VAR]);
@@ -1,6 +1,6 @@
1
- import { Command } from "commander";
2
- import { type DecryptStats } from "../lib/chrome-cookies.js";
3
- import type { CookieRecord } from "../lib/types.js";
1
+ import { Command } from 'commander';
2
+ import { type DecryptStats } from '../lib/chrome-cookies.js';
3
+ import type { CookieRecord } from '../lib/types.js';
4
4
  export declare function extractChromeCookies(domain: string, stats?: DecryptStats): CookieRecord[];
5
5
  export declare function extractAllChromeCookies(stats?: DecryptStats): CookieRecord[];
6
6
  type TldtsParse = (host: string, opts: {
@@ -1,55 +1,55 @@
1
- import * as fs from "fs";
2
- import * as os from "os";
3
- import * as path from "path";
4
- import { createRequire } from "module";
5
- import { getApiKey } from "../lib/auth.js";
6
- import { deriveChromeKey, listAuthRelevantHostKeys, openCookiesDb, readCookiesForHost, } from "../lib/chrome-cookies.js";
7
- import { profileCreate, profileUpload } from "../lib/client.js";
8
- import { err, errLine, handleApiError, out, outLine } from "../lib/output.js";
1
+ import * as fs from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import { createRequire } from 'module';
5
+ import { getApiKey } from '../lib/auth.js';
6
+ import { deriveChromeKey, listAuthRelevantHostKeys, openCookiesDb, readCookiesForHost, } from '../lib/chrome-cookies.js';
7
+ import { profileCreate, profileUpload } from '../lib/client.js';
8
+ import { err, errLine, handleApiError, out, outLine } from '../lib/output.js';
9
9
  // ── UserFacingError ───────────────────────────────────────────────────────────
10
10
  // Thrown by helpers to signal a terminal error that should be printed and exit 1
11
11
  // without going through handleApiError (which would print a second error line).
12
12
  class UserFacingError extends Error {
13
13
  constructor(message) {
14
14
  super(message);
15
- this.name = "UserFacingError";
15
+ this.name = 'UserFacingError';
16
16
  }
17
17
  }
18
18
  // ── Helpers ───────────────────────────────────────────────────────────────────
19
19
  function getChromeCookiesPath() {
20
20
  const platform = process.platform;
21
- if (platform === "darwin") {
22
- return path.join(os.homedir(), "Library", "Application Support", "Google", "Chrome", "Default", "Cookies");
21
+ if (platform === 'darwin') {
22
+ return path.join(os.homedir(), 'Library', 'Application Support', 'Google', 'Chrome', 'Default', 'Cookies');
23
23
  }
24
- if (platform === "linux") {
25
- return path.join(os.homedir(), ".config", "google-chrome", "Default", "Cookies");
24
+ if (platform === 'linux') {
25
+ return path.join(os.homedir(), '.config', 'google-chrome', 'Default', 'Cookies');
26
26
  }
27
27
  // Windows guard — handled in withCookiesDb
28
- return "";
28
+ return '';
29
29
  }
30
30
  function validateDomain(domain) {
31
- if (domain.includes("/") || domain.includes("://") || /\s/.test(domain) || /:\d/.test(domain)) {
32
- err({ error: "domain must be a plain hostname (e.g. github.com)" });
31
+ if (domain.includes('/') || domain.includes('://') || /\s/.test(domain) || /:\d/.test(domain)) {
32
+ err({ error: 'domain must be a plain hostname (e.g. github.com)' });
33
33
  process.exit(1);
34
34
  }
35
35
  }
36
36
  // Opens a private copy of Chrome's cookie DB, derives the decryption key, and calls fn.
37
37
  function withCookiesDb(fn) {
38
- if (process.platform === "win32") {
39
- throw new UserFacingError("Cookie extraction is not supported on Windows yet");
38
+ if (process.platform === 'win32') {
39
+ throw new UserFacingError('Cookie extraction is not supported on Windows yet');
40
40
  }
41
41
  const cookiesPath = getChromeCookiesPath();
42
42
  if (!fs.existsSync(cookiesPath)) {
43
43
  throw new UserFacingError(`Chrome cookies file not found at ${cookiesPath}. Is Google Chrome installed?`);
44
44
  }
45
45
  // Copy the DB out of the profile directory so we avoid the Chrome file lock.
46
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "tinyfish-chrome-cookies-"));
46
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tinyfish-chrome-cookies-'));
47
47
  let db;
48
48
  try {
49
- const dbPath = path.join(tmpDir, "Cookies"); // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
49
+ const dbPath = path.join(tmpDir, 'Cookies'); // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
50
50
  fs.copyFileSync(cookiesPath, dbPath);
51
51
  // Committed rows can sit in Cookies-wal until Chrome checkpoints.
52
- for (const ext of ["-wal", "-shm"]) {
52
+ for (const ext of ['-wal', '-shm']) {
53
53
  if (fs.existsSync(cookiesPath + ext))
54
54
  fs.copyFileSync(cookiesPath + ext, dbPath + ext);
55
55
  }
@@ -92,10 +92,10 @@ export function extractAllChromeCookies(stats) {
92
92
  }
93
93
  // Canonicalize host_keys → registrable domains (mirrors frontend/app/lib/services/domain-utils.ts)
94
94
  const require = createRequire(import.meta.url);
95
- const { parse } = require("tldts");
95
+ const { parse } = require('tldts');
96
96
  const registrableDomains = new Set();
97
97
  for (const hk of hostKeys) {
98
- const cleaned = hk.startsWith(".") ? hk.slice(1) : hk;
98
+ const cleaned = hk.startsWith('.') ? hk.slice(1) : hk;
99
99
  const result = parse(cleaned, { allowPrivateDomains: true });
100
100
  if (result.domain)
101
101
  registrableDomains.add(result.domain.toLowerCase());
@@ -120,7 +120,7 @@ export function extractAllChromeCookies(stats) {
120
120
  export function groupByCanonicalDomain(cookies, parse) {
121
121
  const groups = new Map();
122
122
  for (const c of cookies) {
123
- const cleaned = c.domain.startsWith(".") ? c.domain.slice(1) : c.domain;
123
+ const cleaned = c.domain.startsWith('.') ? c.domain.slice(1) : c.domain;
124
124
  const cd = parse(cleaned, { allowPrivateDomains: true }).domain?.toLowerCase() ?? cleaned;
125
125
  const bucket = groups.get(cd) ?? [];
126
126
  bucket.push(c);
@@ -157,7 +157,7 @@ export function buildChunks(groups) {
157
157
  }
158
158
  // ── Pretty printers ───────────────────────────────────────────────────────────
159
159
  function printPrettyProfileCreate(profile) {
160
- outLine("Profile created");
160
+ outLine('Profile created');
161
161
  outLine(`ID: ${profile.id}`);
162
162
  outLine(`Name: ${profile.name}`);
163
163
  outLine(`Created at: ${profile.created_at}`);
@@ -166,18 +166,18 @@ function printPrettyProfileUpload(result) {
166
166
  if (result.profile_id)
167
167
  outLine(`Profile ID: ${result.profile_id}`);
168
168
  outLine(`Cookies uploaded: ${result.cookie_count}`);
169
- outLine(`Domains updated: ${result.domains_updated.join(", ")}`);
169
+ outLine(`Domains updated: ${result.domains_updated.join(', ')}`);
170
170
  }
171
171
  export function registerProfile(program) {
172
172
  const profileCmd = program
173
- .command("profile")
174
- .description("Profile commands")
173
+ .command('profile')
174
+ .description('Profile commands')
175
175
  .enablePositionalOptions();
176
176
  profileCmd
177
- .command("create")
178
- .description("Create a browser profile")
179
- .requiredOption("--name <name>", "Profile name")
180
- .option("--pretty", "Human-readable output")
177
+ .command('create')
178
+ .description('Create a browser profile')
179
+ .requiredOption('--name <name>', 'Profile name')
180
+ .option('--pretty', 'Human-readable output')
181
181
  .action(async (opts) => {
182
182
  const apiKey = getApiKey();
183
183
  try {
@@ -194,20 +194,20 @@ export function registerProfile(program) {
194
194
  }
195
195
  });
196
196
  profileCmd
197
- .command("import-cookies")
198
- .description("Import Chrome cookies into a profile. Use --domain for a single domain or --all-domains for every domain in your Chrome profile. Exactly one must be provided.")
199
- .option("--domain <domain>", "Domain to import cookies for (e.g. github.com)")
200
- .option("--all-domains", "Import cookies for all registrable domains (e.g. github.com) found in your Chrome profile. IPs and non-resolvable hostnames (e.g. localhost) are skipped.")
201
- .option("--profile-id <id>", "Profile ID to import cookies into (creates new profile if omitted)")
202
- .option("--pretty", "Human-readable output")
197
+ .command('import-cookies')
198
+ .description('Import Chrome cookies into a profile. Use --domain for a single domain or --all-domains for every domain in your Chrome profile. Exactly one must be provided.')
199
+ .option('--domain <domain>', 'Domain to import cookies for (e.g. github.com)')
200
+ .option('--all-domains', 'Import cookies for all registrable domains (e.g. github.com) found in your Chrome profile. IPs and non-resolvable hostnames (e.g. localhost) are skipped.')
201
+ .option('--profile-id <id>', 'Profile ID to import cookies into (creates new profile if omitted)')
202
+ .option('--pretty', 'Human-readable output')
203
203
  .action(async (opts) => {
204
204
  // Mutual-exclusivity guard — must provide exactly one of --domain / --all-domains
205
205
  if (!opts.domain && !opts.allDomains) {
206
- err({ error: "Provide exactly one of --domain or --all-domains" });
206
+ err({ error: 'Provide exactly one of --domain or --all-domains' });
207
207
  process.exit(1);
208
208
  }
209
209
  if (opts.domain && opts.allDomains) {
210
- err({ error: "Provide exactly one of --domain or --all-domains" });
210
+ err({ error: 'Provide exactly one of --domain or --all-domains' });
211
211
  process.exit(1);
212
212
  }
213
213
  const apiKey = getApiKey();
@@ -229,13 +229,13 @@ export function registerProfile(program) {
229
229
  }
230
230
  if (cookies.length === 0) {
231
231
  throw new UserFacingError(stats.keyringSkipped > 0
232
- ? "Chrome on Linux encrypts cookies with the system keyring, which is not supported yet."
232
+ ? 'Chrome on Linux encrypts cookies with the system keyring, which is not supported yet.'
233
233
  : opts.allDomains
234
- ? "No Chrome cookies found. Is Google Chrome installed and have you logged in to any sites?"
234
+ ? 'No Chrome cookies found. Is Google Chrome installed and have you logged in to any sites?'
235
235
  : `No Chrome cookies found for ${opts.domain}. Are you logged in to this site in Chrome?`);
236
236
  }
237
237
  if (profileId === undefined) {
238
- const name = opts.allDomains ? "chrome-import" : opts.domain;
238
+ const name = opts.allDomains ? 'chrome-import' : opts.domain;
239
239
  const created = await profileCreate(name, apiKey);
240
240
  profileId = created.id;
241
241
  }
@@ -243,7 +243,7 @@ export function registerProfile(program) {
243
243
  if (opts.allDomains) {
244
244
  // Batch upload — never split a canonical domain across chunks
245
245
  const require = createRequire(import.meta.url);
246
- const { parse } = require("tldts");
246
+ const { parse } = require('tldts');
247
247
  const groups = groupByCanonicalDomain(cookies, parse);
248
248
  const chunks = buildChunks(groups);
249
249
  let cookieCount = 0;
@@ -267,7 +267,7 @@ export function registerProfile(program) {
267
267
  result = await profileUpload(profileId, cookies, apiKey);
268
268
  }
269
269
  if (result.domains_failed && result.domains_failed.length > 0) {
270
- errLine(`Warning: failed to update cookies for domains: ${result.domains_failed.join(", ")}`);
270
+ errLine(`Warning: failed to update cookies for domains: ${result.domains_failed.join(', ')}`);
271
271
  }
272
272
  if (opts.pretty) {
273
273
  printPrettyProfileUpload(result);
@@ -1,2 +1,2 @@
1
- import { Command } from "commander";
1
+ import { Command } from 'commander';
2
2
  export declare function registerRun(agentCmd: Command): Command;