@todoforai/cli 0.1.62 → 0.1.64

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.
@@ -42675,25 +42675,53 @@ var require_dist = __commonJS((exports) => {
42675
42675
  });
42676
42676
 
42677
42677
  // src/index.ts
42678
- import { realpathSync as realpathSync2, readFileSync as readFileSync3, existsSync as existsSync2 } from "fs";
42679
- import { resolve as resolve4 } from "path";
42678
+ import { realpathSync as realpathSync2, readFileSync as readFileSync5, existsSync as existsSync4 } from "fs";
42679
+ import { resolve as resolve5 } from "path";
42680
42680
  import { fileURLToPath } from "url";
42681
- import { homedir as homedir3 } from "os";
42681
+ import { homedir as homedir5 } from "os";
42682
42682
  import path4 from "path";
42683
42683
 
42684
42684
  // node_modules/@todoforai/update-notifier/src/index.ts
42685
42685
  import fs from "node:fs";
42686
42686
  import path from "node:path";
42687
42687
  import os from "node:os";
42688
- function isLinkedInstall() {
42688
+ import { spawn, spawnSync } from "node:child_process";
42689
+ function installer() {
42690
+ let real;
42689
42691
  try {
42690
- return !fs.realpathSync(process.argv[1] || "").includes(`${path.sep}node_modules${path.sep}`);
42692
+ real = fs.realpathSync(process.argv[1] || "");
42691
42693
  } catch {
42692
- return false;
42694
+ return null;
42693
42695
  }
42696
+ if (!real.includes(`${path.sep}node_modules${path.sep}`))
42697
+ return null;
42698
+ return real.includes(path.join(".bun", "install", "global")) ? "bun" : "npm";
42694
42699
  }
42695
42700
  var TTL_MS = 24 * 60 * 60 * 1000;
42696
42701
  var CACHE_DIR = path.join(os.homedir(), ".config", "todoforai");
42702
+ var cacheFileFor = (name) => path.join(CACHE_DIR, `notifier-${encodeURIComponent(name)}.json`);
42703
+ function readCache(name) {
42704
+ try {
42705
+ return JSON.parse(fs.readFileSync(cacheFileFor(name), "utf8"));
42706
+ } catch {
42707
+ return {};
42708
+ }
42709
+ }
42710
+ function writeCache(name, cache) {
42711
+ try {
42712
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
42713
+ fs.writeFileSync(cacheFileFor(name), JSON.stringify(cache));
42714
+ } catch {}
42715
+ }
42716
+ function refreshCache(name, cache) {
42717
+ if (Date.now() - (cache.ts ?? 0) <= TTL_MS)
42718
+ return;
42719
+ writeCache(name, { ...cache, ts: Date.now() });
42720
+ fetch(`https://registry.npmjs.org/${name}/latest`, { signal: AbortSignal.timeout(3000) }).then((r) => r.ok ? r.json() : null).then((j) => {
42721
+ if (j?.version)
42722
+ writeCache(name, { ...cache, ts: Date.now(), latest: j.version });
42723
+ }).catch(() => {});
42724
+ }
42697
42725
  function cmpVer(a, b) {
42698
42726
  const pa = a.split("-")[0].split(".").map((n) => parseInt(n, 10) || 0);
42699
42727
  const pb = b.split("-")[0].split(".").map((n) => parseInt(n, 10) || 0);
@@ -42705,13 +42733,11 @@ function cmpVer(a, b) {
42705
42733
  return 0;
42706
42734
  }
42707
42735
  function checkForUpdates(pkg) {
42708
- if (!process.stderr.isTTY || process.env.CI || process.env.NO_UPDATE_NOTIFIER || isLinkedInstall())
42736
+ if (!process.stderr.isTTY || process.env.CI || process.env.NO_UPDATE_NOTIFIER || !installer())
42709
42737
  return;
42710
- const cacheFile = path.join(CACHE_DIR, `notifier-${encodeURIComponent(pkg.name)}.json`);
42711
- let cache = {};
42712
- try {
42713
- cache = JSON.parse(fs.readFileSync(cacheFile, "utf8"));
42714
- } catch {}
42738
+ if (process.argv.includes("--json"))
42739
+ return;
42740
+ const cache = readCache(pkg.name);
42715
42741
  if (cache.latest && cmpVer(cache.latest, pkg.version) > 0) {
42716
42742
  process.stderr.write(`
42717
42743
  \x1B[33m Update available: \x1B[2m${pkg.version}\x1B[22m → \x1B[1m${cache.latest}\x1B[0m
@@ -42719,17 +42745,67 @@ function checkForUpdates(pkg) {
42719
42745
 
42720
42746
  `);
42721
42747
  }
42722
- if (Date.now() - (cache.ts ?? 0) > TTL_MS) {
42748
+ refreshCache(pkg.name, cache);
42749
+ }
42750
+ function backgroundUpdate(pkg) {
42751
+ const mgr = installer();
42752
+ if (process.env.CI || process.env.NO_UPDATE_NOTIFIER || !mgr)
42753
+ return;
42754
+ const cache = readCache(pkg.name);
42755
+ const latest = cache.latest;
42756
+ if (latest && cmpVer(latest, pkg.version) > 0 && cache.tried !== latest) {
42757
+ const next = { ...cache, tried: latest };
42758
+ writeCache(pkg.name, next);
42723
42759
  try {
42724
- fs.mkdirSync(CACHE_DIR, { recursive: true });
42725
- fs.writeFileSync(cacheFile, JSON.stringify({ ...cache, ts: Date.now() }));
42760
+ const args = mgr === "bun" ? ["add", "-g", `${pkg.name}@${latest}`] : ["i", "-g", `${pkg.name}@${latest}`];
42761
+ const win = process.platform === "win32";
42762
+ spawn(win ? `${mgr}.cmd` : mgr, args, { detached: true, stdio: "ignore", shell: win, windowsHide: true }).unref();
42726
42763
  } catch {}
42727
- fetch(`https://registry.npmjs.org/${pkg.name}/latest`, { signal: AbortSignal.timeout(3000) }).then((r) => r.ok ? r.json() : null).then((j) => {
42728
- if (!j?.version)
42729
- return;
42730
- fs.writeFileSync(cacheFile, JSON.stringify({ ts: Date.now(), latest: j.version }));
42731
- }).catch(() => {});
42764
+ refreshCache(pkg.name, next);
42765
+ return;
42766
+ }
42767
+ checkForUpdates(pkg);
42768
+ }
42769
+ var log = (msg) => process.stderr.write(msg + `
42770
+ `);
42771
+ function install(pkg, mgr, latest) {
42772
+ log(`\x1B[33m Updating ${pkg.name} ${pkg.version} → ${latest} ...\x1B[0m`);
42773
+ const cmd = process.platform === "win32" ? `${mgr}.cmd` : mgr;
42774
+ const args = mgr === "bun" ? ["add", "-g", `${pkg.name}@${latest}`] : ["i", "-g", `${pkg.name}@${latest}`];
42775
+ const r = spawnSync(cmd, args, { stdio: "inherit", timeout: 120000 });
42776
+ if (r.status !== 0) {
42777
+ writeCache(pkg.name, { ...readCache(pkg.name), failed: latest });
42778
+ log(`\x1B[31m Update to ${latest} failed — run manually: ${mgr} ${args.join(" ")}\x1B[0m`);
42779
+ return "failed";
42780
+ }
42781
+ log(`\x1B[32m ✓ Updated to ${latest}\x1B[0m (active from the next start)`);
42782
+ writeCache(pkg.name, { ts: Date.now(), latest });
42783
+ return "updated";
42784
+ }
42785
+ async function fetchLatest(name, timeoutMs) {
42786
+ try {
42787
+ const r = await fetch(`https://registry.npmjs.org/${name}/latest`, { signal: AbortSignal.timeout(timeoutMs) });
42788
+ return r.ok ? (await r.json())?.version : undefined;
42789
+ } catch {
42790
+ return;
42791
+ }
42792
+ }
42793
+ async function selfUpdate(pkg) {
42794
+ const mgr = installer();
42795
+ if (!mgr) {
42796
+ log(`\x1B[33mNot a package-manager install — update manually: npm i -g ${pkg.name}\x1B[0m`);
42797
+ return "unsupported";
42798
+ }
42799
+ const latest = await fetchLatest(pkg.name, 1e4);
42800
+ if (!latest) {
42801
+ log("\x1B[31mCould not reach the npm registry.\x1B[0m");
42802
+ return "failed";
42732
42803
  }
42804
+ if (cmpVer(latest, pkg.version) <= 0) {
42805
+ log(`\x1B[32m✓ Already up to date (${pkg.version}).\x1B[0m`);
42806
+ return "current";
42807
+ }
42808
+ return install(pkg, mgr, latest);
42733
42809
  }
42734
42810
 
42735
42811
  // src/tips.ts
@@ -42981,6 +43057,9 @@ class ApiClient {
42981
43057
  getAgentSettings(id) {
42982
43058
  return this.request("GET", `/api/v1/agents/${id}`);
42983
43059
  }
43060
+ importSession(input) {
43061
+ return this.request("POST", "/api/v1/todos/import", input, 120000);
43062
+ }
42984
43063
  addMessage(projectId, content, agentSettings, todoId, attachments, scheduledTimestamp, groupTag, groupName) {
42985
43064
  const payload = { content, agentSettings, attachments: attachments || [] };
42986
43065
  if (todoId)
@@ -43245,7 +43324,7 @@ function writeCredential(apiUrl, apiKey) {
43245
43324
  }
43246
43325
 
43247
43326
  // ../packages/shared-api/src/frontend-ws.ts
43248
- var log = (level, ...args) => console.log(`[frontend-ws:${level}]`, ...args);
43327
+ var log2 = (level, ...args) => console.log(`[frontend-ws:${level}]`, ...args);
43249
43328
 
43250
43329
  class FrontendWebSocket {
43251
43330
  apiUrl;
@@ -43327,7 +43406,7 @@ class FrontendWebSocket {
43327
43406
  resolve(false);
43328
43407
  });
43329
43408
  sock.on("error", (err) => {
43330
- log("error", "WS error:", err.message);
43409
+ log2("error", "WS error:", err.message);
43331
43410
  if (current())
43332
43411
  this.connected = false;
43333
43412
  resolve(false);
@@ -43764,6 +43843,75 @@ var NON_SHELL_TYPES = new Set([
43764
43843
  "IOS" /* IOS */
43765
43844
  ]);
43766
43845
  // ../packages/shared-fbe/src/blocks/index.ts
43846
+ var ToolType;
43847
+ ((ToolType2) => {
43848
+ ToolType2["Read"] = "read";
43849
+ ToolType2["Create"] = "create";
43850
+ ToolType2["Write"] = "write";
43851
+ ToolType2["Edit"] = "edit";
43852
+ ToolType2["ModifyFile"] = "modify_file";
43853
+ ToolType2["Bash"] = "bash";
43854
+ ToolType2["Grep"] = "grep";
43855
+ ToolType2["List"] = "list";
43856
+ ToolType2["Skill"] = "skill";
43857
+ ToolType2["ApiGetCurrentContext"] = "api_get_current_context";
43858
+ ToolType2["ApiGetTodo"] = "api_get_todo";
43859
+ ToolType2["ApiAddTodoMessage"] = "api_add_todo_message";
43860
+ ToolType2["ApiUpdateTodoStatus"] = "api_update_todo_status";
43861
+ ToolType2["ApiDeleteTodo"] = "api_delete_todo";
43862
+ ToolType2["ApiListProjects"] = "api_list_projects";
43863
+ ToolType2["ApiGetProject"] = "api_get_project";
43864
+ ToolType2["ApiCreateProject"] = "api_create_project";
43865
+ ToolType2["ApiListProjectTodos"] = "api_list_project_todos";
43866
+ ToolType2["ApiCreateTodo"] = "api_create_todo";
43867
+ ToolType2["ApiListAgents"] = "api_list_agents";
43868
+ ToolType2["ApiGetAgent"] = "api_get_agent";
43869
+ ToolType2["ApiUpdateAgent"] = "api_update_agent";
43870
+ ToolType2["ApiListBusinessContexts"] = "api_list_business_contexts";
43871
+ ToolType2["ApiGetContextItem"] = "api_get_context_item";
43872
+ ToolType2["ApiCreateContextItem"] = "api_create_context_item";
43873
+ ToolType2["ApiUpdateContextItem"] = "api_update_context_item";
43874
+ ToolType2["ApiDeleteContextItem"] = "api_delete_context_item";
43875
+ ToolType2["ApiListEdges"] = "api_list_edges";
43876
+ ToolType2["ApiGetEdge"] = "api_get_edge";
43877
+ ToolType2["ApiListMcps"] = "api_list_mcps";
43878
+ ToolType2["ApiGetUsage"] = "api_get_usage";
43879
+ ToolType2["ApiGetBalance"] = "api_get_balance";
43880
+ ToolType2["ApiGetApiSchema"] = "api_get_api_schema";
43881
+ ToolType2["ApiListBoard"] = "api_list_board";
43882
+ ToolType2["ApiUpsertGroup"] = "api_upsert_group";
43883
+ ToolType2["ApiCreateTemplate"] = "api_create_template";
43884
+ ToolType2["ApiRecommendTemplate"] = "api_recommend_template";
43885
+ ToolType2["ImageGen"] = "image_gen";
43886
+ ToolType2["HtmlSnippet"] = "html_snippet";
43887
+ ToolType2["LivePreview"] = "live_preview";
43888
+ ToolType2["OpenBrowser"] = "open_browser";
43889
+ ToolType2["Show"] = "show";
43890
+ ToolType2["Text"] = "text";
43891
+ ToolType2["Reason"] = "reason";
43892
+ ToolType2["Error"] = "error";
43893
+ ToolType2["Compact"] = "compact";
43894
+ ToolType2["Question"] = "question";
43895
+ ToolType2["Login"] = "login_prompt";
43896
+ ToolType2["BusinessOnboarding"] = "business_onboarding";
43897
+ ToolType2["RequestMcpAccess"] = "request_mcp_access";
43898
+ ToolType2["EdgeNotRunning"] = "edge_not_running";
43899
+ ToolType2["WebFetch"] = "webfetch";
43900
+ ToolType2["GoogleSearch"] = "google_search";
43901
+ ToolType2["WebSearch"] = "web_search";
43902
+ ToolType2["VaultSearch"] = "vault_search";
43903
+ ToolType2["VaultResolve"] = "vault_resolve";
43904
+ ToolType2["VaultWrite"] = "vault_write";
43905
+ ToolType2["VaultWriteBatch"] = "vault_write_batch";
43906
+ ToolType2["VaultUpdate"] = "vault_update";
43907
+ ToolType2["Explore"] = "explore";
43908
+ ToolType2["Plan"] = "plan";
43909
+ ToolType2["Review"] = "review";
43910
+ ToolType2["DeviceList"] = "device_list";
43911
+ ToolType2["Mcp"] = "mcp";
43912
+ ToolType2["NamedTool"] = "named_tool";
43913
+ })(ToolType ||= {});
43914
+ var TOOL_TYPE_VALUES = new Set(Object.values(ToolType));
43767
43915
  var USER_INPUT_BLOCK_TYPES = new Set([
43768
43916
  "question" /* Question */,
43769
43917
  "login_prompt" /* Login */,
@@ -43908,6 +44056,31 @@ var SERVER_TO_FRONTENDS = {
43908
44056
  }
43909
44057
  };
43910
44058
  // ../packages/shared-fbe/src/REST_types.ts
44059
+ var voiceSourceKey = (s) => s.account ? `${s.channel}/${s.account}` : s.channel;
44060
+ function voiceName(s) {
44061
+ if (!s.account)
44062
+ return s.channel;
44063
+ let h = (s.label || s.account).trim();
44064
+ try {
44065
+ const u = new URL(h);
44066
+ h = u.pathname.split("/").filter(Boolean).pop() ?? u.hostname;
44067
+ } catch {}
44068
+ return `${s.channel}@${h.replace(/^@/, "").replace(/[^\p{L}\p{N}._-]+/gu, "-").replace(/^-+|-+$/g, "") || "account"}`;
44069
+ }
44070
+ function voiceNamesOf(sources) {
44071
+ const keys = sources.map(voiceSourceKey);
44072
+ const out = new Array(sources.length);
44073
+ const owner = new Map;
44074
+ for (const i of sources.map((_, i2) => i2).sort((a, b) => keys[a].localeCompare(keys[b]))) {
44075
+ const base = voiceName(sources[i]);
44076
+ let name = base;
44077
+ for (let n = 2;owner.has(name.toLowerCase()) && owner.get(name.toLowerCase()) !== keys[i]; n++)
44078
+ name = `${base}-${n}`;
44079
+ owner.set(name.toLowerCase(), keys[i]);
44080
+ out[i] = name;
44081
+ }
44082
+ return out;
44083
+ }
43911
44084
  var MANUAL_CHANNEL = "Manual";
43912
44085
  function manualAnswersOf(sources) {
43913
44086
  const manual = sources?.find((s) => s.channel === MANUAL_CHANNEL);
@@ -44444,8 +44617,9 @@ var tool_catalog_default = {
44444
44617
  pkg: "zele",
44445
44618
  installer: "npm",
44446
44619
  label: "Gmail",
44620
+ voiceChannel: "Gmail",
44447
44621
  summary: "Read and send Gmail from your own account.",
44448
- statusCmd: "zele whoami 2>/dev/null | grep 'email:' | grep -m1 .",
44622
+ statusCmd: "zele whoami 2>/dev/null | grep -o 'email: *[^ ]*' | tr -d ' ' | paste -sd ' ' - | grep -m1 .",
44449
44623
  loginNeedsPty: true,
44450
44624
  loginCmd: "zele login --method google",
44451
44625
  oauthUrlPattern: "(https://accounts\\.google\\.com\\S+)",
@@ -44464,7 +44638,7 @@ var tool_catalog_default = {
44464
44638
  binName: "zele",
44465
44639
  label: "Google Calendar",
44466
44640
  summary: "See your Google Calendar and book, move or cancel events.",
44467
- statusCmd: "zele whoami 2>/dev/null | grep 'email:' | grep -m1 .",
44641
+ statusCmd: "zele whoami 2>/dev/null | grep -o 'email: *[^ ]*' | tr -d ' ' | paste -sd ' ' - | grep -m1 .",
44468
44642
  loginNeedsPty: true,
44469
44643
  loginCmd: "zele login --method google",
44470
44644
  oauthUrlPattern: "(https://accounts\\.google\\.com\\S+)",
@@ -44479,6 +44653,7 @@ var tool_catalog_default = {
44479
44653
  pkg: "@xdevplatform/xurl",
44480
44654
  installer: "npm",
44481
44655
  label: "X",
44656
+ voiceChannel: "X",
44482
44657
  summary: "Post to X and read timelines, replies and DMs.",
44483
44658
  statusCmd: `xurl whoami 2>&1 | sed -n 's/.*"username"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
44484
44659
  loginCmd: "xurl auth oauth2",
@@ -44497,6 +44672,7 @@ var tool_catalog_default = {
44497
44672
  pkg: "@todoforai/linkedin-api",
44498
44673
  installer: "npm",
44499
44674
  label: "LinkedIn",
44675
+ voiceChannel: "LinkedIn",
44500
44676
  summary: "Read LinkedIn profiles and send messages and connection requests.",
44501
44677
  statusCmd: `linkedin-api whoami 2>/dev/null | sed -n 's/.*"publicId"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
44502
44678
  loginCmd: "linkedin-api auth <li_at> <jsessionid>",
@@ -44525,6 +44701,7 @@ var tool_catalog_default = {
44525
44701
  pkg: "slack-cli",
44526
44702
  installer: "binary",
44527
44703
  label: "Slack",
44704
+ voiceChannel: "Slack",
44528
44705
  summary: "Work with Slack workspaces and apps.",
44529
44706
  statusCmd: "slack-cli auth list 2>&1 | grep 'Team' >/dev/null && echo authenticated",
44530
44707
  loginCmd: "slack-cli login",
@@ -44690,7 +44867,7 @@ var tool_catalog_default = {
44690
44867
  preinstallCloud: true,
44691
44868
  label: "GitHub",
44692
44869
  summary: "Work with your GitHub repos, pull requests and issues.",
44693
- statusCmd: "gh auth status 2>&1 | grep 'Logged in to' | grep -m1 .",
44870
+ statusCmd: "gh auth status 2>&1 | grep -o 'Logged in to [^ ]* [a-z]* [^ ]*' | paste -sd ' ' - | grep -m1 .",
44694
44871
  loginCmd: "gh auth login --hostname github.com --git-protocol https",
44695
44872
  oauthUrlPattern: "(https://github\\.com/login/device\\S*)",
44696
44873
  deviceCodePattern: "one-time code:\\s*([A-Z0-9]{4}-[A-Z0-9]{4})",
@@ -44707,8 +44884,8 @@ var tool_catalog_default = {
44707
44884
  installer: "npm",
44708
44885
  label: "MCP (mcporter)",
44709
44886
  summary: "Use tools from any MCP server.",
44710
- statusCmd: "mcporter list 2>/dev/null | grep -v 'No MCP servers' | grep -m1 .",
44711
- description: "MCP servers as CLI: `mcporter list [server] [--schema]`, `mcporter call <server>.<tool> key=value` (`key=@file`), `mcporter config add <name> <cmd-or-url>`, `mcporter auth <server>`. `--help` for more.",
44887
+ statusCmd: 'mcporter config list --json 2>/dev/null | node -e \'let d="";process.stdin.on("data",c=>d+=c).on("end",()=>{const s=JSON.parse(d||"{}").servers||[];if(!s.length)process.exit(1);console.log("Configured MCP servers (one line each; run `mcporter list <name>` before first use):");for(const x of s)console.log(`- ${x.name} — ${x.description?x.description+" ":""}(${x.baseUrl?new URL(x.baseUrl).host:x.command})`)})\'',
44888
+ description: "MCP servers as CLI: `mcporter list <server>` (its tools), `mcporter call <server>.<tool> key=value` (`key=@file`), `mcporter auth <server>`, `mcporter config add <name> <cmd-or-url>`.",
44712
44889
  versionCmd: "mcporter --version 2>/dev/null | sed -n 1p",
44713
44890
  preinstallJarvis: true,
44714
44891
  preinstallCloud: true
@@ -44722,7 +44899,7 @@ var tool_catalog_default = {
44722
44899
  installer: "binary",
44723
44900
  label: "GitLab",
44724
44901
  summary: "Work with your GitLab repos, merge requests and pipelines.",
44725
- statusCmd: "glab auth status 2>&1 | grep 'Logged in to' | grep -m1 .",
44902
+ statusCmd: "glab auth status 2>&1 | grep -o 'Logged in to [^ ]* [a-z]* [^ ]*' | paste -sd ' ' - | grep -m1 .",
44726
44903
  loginCmd: "glab auth login --device",
44727
44904
  credentialPaths: ["~/.config/glab-cli/config.yml"],
44728
44905
  description: "GitLab equivalent of `gh`.",
@@ -44785,7 +44962,7 @@ var tool_catalog_default = {
44785
44962
  installer: "npm",
44786
44963
  label: "Firebase",
44787
44964
  summary: "Deploy and manage Firebase hosting, database and functions.",
44788
- statusCmd: "firebase login:list 2>&1 | grep -oiE '[[:alnum:]._%+-]+@[[:alnum:].-]+\\.[[:alpha:]]{2,}' | grep -m1 .",
44965
+ statusCmd: "firebase login:list 2>&1 | grep -oiE '[[:alnum:]._%+-]+@[[:alnum:].-]+\\.[[:alpha:]]{2,}' | sort -u | paste -sd ' ' - | grep -m1 .",
44789
44966
  loginCmd: "firebase login --no-localhost --reauth",
44790
44967
  loginNeedsPty: true,
44791
44968
  stdinPaste: true,
@@ -44825,9 +45002,7 @@ var tool_catalog_default = {
44825
45002
  credentialPaths: ["~/.config/stripe/config.toml"],
44826
45003
  description: "`stripe listen` forwards webhooks locally; `stripe get/post /v1/...` for raw API.",
44827
45004
  versionCmd: "stripe --version 2>/dev/null | sed -n 1p",
44828
- deviceCodePattern: "verification code:\\s*([A-Z0-9]{4}-[A-Z0-9]{4})",
44829
- oauthUrlPattern: "(https://access\\.stripe\\.com/stripecli/\\S+)",
44830
- canStreamLogin: true
45005
+ oauthUrlPattern: "(https://dashboard\\.stripe\\.com/stripecli/confirm_auth\\S+)"
44831
45006
  },
44832
45007
  flyctl: {
44833
45008
  preinstallCloud: true,
@@ -45678,6 +45853,7 @@ var tool_catalog_default = {
45678
45853
  label: "Mailchimp",
45679
45854
  summary: "Manage Mailchimp audiences, contacts, email campaigns and reports.",
45680
45855
  loginCmd: "mailchimp-api auth --api-key <api_key>",
45856
+ oauthBroker: true,
45681
45857
  statusCmd: `mailchimp-api whoami 2>/dev/null | sed -n 's/.*"account_name"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m1 .`,
45682
45858
  credentialPaths: [
45683
45859
  "~/.config/mailchimp-api/credentials.json"
@@ -45691,6 +45867,7 @@ var tool_catalog_default = {
45691
45867
  pkg: "@todoforai/facebook-pages-api",
45692
45868
  installer: "npm",
45693
45869
  label: "Facebook Pages",
45870
+ voiceChannel: "Facebook",
45694
45871
  summary: "Post to your Facebook Page and handle comments.",
45695
45872
  statusCmd: `facebook-pages-api whoami 2>/dev/null | sed -n 's/.*"name"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
45696
45873
  loginCmd: "facebook-pages-api auth --page-id <id> --page-token <token>",
@@ -45719,6 +45896,7 @@ var tool_catalog_default = {
45719
45896
  pkg: "@todoforai/outlook-api",
45720
45897
  installer: "npm",
45721
45898
  label: "Outlook (Graph)",
45899
+ voiceChannel: "Outlook",
45722
45900
  summary: "Read and write your Outlook mail.",
45723
45901
  statusCmd: `outlook-api whoami 2>/dev/null | sed -n 's/.*"userPrincipalName"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
45724
45902
  loginCmd: "outlook-api auth",
@@ -46196,7 +46374,13 @@ import { parseArgs } from "util";
46196
46374
  // package.json
46197
46375
  var package_default = {
46198
46376
  name: "@todoforai/cli",
46199
- version: "0.1.62",
46377
+ description: "TODOforAI CLI — create and manage tasks with tfa-cli.",
46378
+ homepage: "https://todofor.ai",
46379
+ repository: {
46380
+ type: "git",
46381
+ url: "git+https://github.com/todoforai/cli.git"
46382
+ },
46383
+ version: "0.1.64",
46200
46384
  type: "module",
46201
46385
  bin: {
46202
46386
  "todoforai-cli": "bin/todoforai-cli.js",
@@ -46216,7 +46400,7 @@ var package_default = {
46216
46400
  },
46217
46401
  dependencies: {
46218
46402
  "@agentclientprotocol/sdk": "^1.4.0",
46219
- "@todoforai/update-notifier": "^0.1.0",
46403
+ "@todoforai/update-notifier": "^0.4.0",
46220
46404
  chalk: "^6.0.0",
46221
46405
  "cli-highlight": "^2.1.11",
46222
46406
  "diff-match-patch": "^1.0.5",
@@ -46258,6 +46442,7 @@ Examples:
46258
46442
  tfa-cli device list|rename|wallpaper … # Paired machines
46259
46443
  tfa-cli list [-n 30] [--cursor N] [--all] [--status S] # List todos (paginated)
46260
46444
  tfa-cli status <todo-id> <STATUS> # Update a todo's status
46445
+ tfa-cli update # Update tfa-cli itself (also auto-updates in background; NO_UPDATE_NOTIFIER=1 disables)
46261
46446
  tfa-cli delete <todo-id> # Permanently delete a todo
46262
46447
  tfa-cli addmessage <todo-id> "text" # Send a message and exit (like -r, no watch/bridge)
46263
46448
  tfa-cli show <file|-> [todo-id] # Render a local file (image/pdf/html…) in the chat; - = stdin
@@ -46269,6 +46454,7 @@ Examples:
46269
46454
  tfa-cli notify [--to <email>] "Title" "message" [--href /t/<id>] # Note to your own user, or --to a project member (Messages tab + phone push)
46270
46455
  tfa-cli claim mint --seed <projectId> [--emails a@x,b@y] [--ttl <sec>] # Mint /claim/<token> links for a project you own
46271
46456
  tfa-cli next [--direction "<text>"] # Analyzer growth recommendation cards
46457
+ tfa-cli import [claude|codex|<file>...] [--dry-run] # Import Claude Code / Codex sessions as todos
46272
46458
  tfa-cli <command> help # Details per command
46273
46459
 
46274
46460
  Options:
@@ -46359,7 +46545,7 @@ var WORD_FLAGS = {
46359
46545
  agents: "list-agents",
46360
46546
  config: "show-config"
46361
46547
  };
46362
- var HELP_SUBCOMMANDS = ["agent", "todo", "project", "brand", "device", "list", "ls", "status", "show", "open", "inbox", "notify"];
46548
+ var HELP_SUBCOMMANDS = ["agent", "todo", "project", "brand", "device", "list", "ls", "status", "show", "open", "inbox", "notify", "import"];
46363
46549
  function parseCliArgs() {
46364
46550
  const { values, positionals } = parseArgs({
46365
46551
  args: process.argv.slice(2),
@@ -46399,6 +46585,7 @@ function parseCliArgs() {
46399
46585
  to: { type: "string" },
46400
46586
  unread: { type: "boolean", default: false },
46401
46587
  limit: { type: "string" },
46588
+ days: { type: "string" },
46402
46589
  resume: { type: "string", short: "r" },
46403
46590
  continue: { type: "boolean", short: "c", default: false },
46404
46591
  "non-interactive": { type: "boolean", short: "n", default: false },
@@ -46771,7 +46958,7 @@ Cancelled
46771
46958
  import { resolve, basename } from "path";
46772
46959
 
46773
46960
  // src/ensure-bridge.ts
46774
- import { spawn, spawnSync } from "child_process";
46961
+ import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
46775
46962
  import fs2 from "fs";
46776
46963
  import path2 from "path";
46777
46964
  import os2 from "os";
@@ -46781,7 +46968,7 @@ var INSTALL_TIMEOUT_MS = 90000;
46781
46968
  var bridgeBin = "todoforai-bridge";
46782
46969
  var bridgeBinary = () => bridgeBin;
46783
46970
  function probeBridge(bin) {
46784
- return spawnSync(bin, ["--version"], { stdio: "ignore" }).status === 0;
46971
+ return spawnSync2(bin, ["--version"], { stdio: "ignore" }).status === 0;
46785
46972
  }
46786
46973
  function hasBridge() {
46787
46974
  if (probeBridge(bridgeBin))
@@ -46796,7 +46983,7 @@ function installBridge() {
46796
46983
  if (process.platform !== "linux" && process.platform !== "darwin")
46797
46984
  return false;
46798
46985
  console.error(`\x1B[2mInstalling TODOforAI Bridge (${INSTALLER_URL})...\x1B[0m`);
46799
- const r = spawnSync("sh", ["-c", `curl -fsSL --connect-timeout 10 --max-time 30 ${INSTALLER_URL} | sh`], { stdio: ["ignore", "ignore", "inherit"], timeout: INSTALL_TIMEOUT_MS, killSignal: "SIGKILL" });
46986
+ const r = spawnSync2("sh", ["-c", `curl -fsSL --connect-timeout 10 --max-time 30 ${INSTALLER_URL} | sh`], { stdio: ["ignore", "ignore", "inherit"], timeout: INSTALL_TIMEOUT_MS, killSignal: "SIGKILL" });
46800
46987
  if (r.error?.code === "ETIMEDOUT")
46801
46988
  console.error("\x1B[33mBridge install timed out\x1B[0m");
46802
46989
  return r.status === 0 && hasBridge();
@@ -46849,7 +47036,7 @@ function bridgeWhoamiArgs(apiUrl) {
46849
47036
  return withProfile(["whoami"], apiUrl);
46850
47037
  }
46851
47038
  function bridgeDeviceId(apiUrl) {
46852
- const r = spawnSync(bridgeBin, bridgeWhoamiArgs(apiUrl), { encoding: "utf-8" });
47039
+ const r = spawnSync2(bridgeBin, bridgeWhoamiArgs(apiUrl), { encoding: "utf-8" });
46853
47040
  if (r.status !== 0)
46854
47041
  return null;
46855
47042
  const m = (r.stdout || "").match(/^Device:.*\(id:\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\)/im);
@@ -46875,11 +47062,11 @@ async function enrollBridgeWithApiKey(apiUrl, apiKey) {
46875
47062
  console.error(`\x1B[33mBridge enroll: mint failed (${e?.message || e})\x1B[0m`);
46876
47063
  return false;
46877
47064
  }
46878
- const login = spawnSync(bridgeBin, [...bridgeLoginArgs(apiUrl), "--token", token], { stdio: ["ignore", "ignore", "inherit"], timeout: 30000, killSignal: "SIGKILL" });
47065
+ const login = spawnSync2(bridgeBin, [...bridgeLoginArgs(apiUrl), "--token", token], { stdio: ["ignore", "ignore", "inherit"], timeout: 30000, killSignal: "SIGKILL" });
46879
47066
  return login.status === 0;
46880
47067
  }
46881
47068
  function ensureBridgeCredentials(apiUrl, opts = {}) {
46882
- const whoami = spawnSync(bridgeBin, bridgeWhoamiArgs(apiUrl), { stdio: "ignore" });
47069
+ const whoami = spawnSync2(bridgeBin, bridgeWhoamiArgs(apiUrl), { stdio: "ignore" });
46883
47070
  if (whoami.status === 0)
46884
47071
  return true;
46885
47072
  if (opts.interactive === false) {
@@ -46887,7 +47074,7 @@ function ensureBridgeCredentials(apiUrl, opts = {}) {
46887
47074
  return false;
46888
47075
  }
46889
47076
  console.error("\x1B[2mBridge credentials not found. Starting `todoforai-bridge login`...\x1B[0m");
46890
- const login = spawnSync(bridgeBin, bridgeLoginArgs(apiUrl), { stdio: "inherit" });
47077
+ const login = spawnSync2(bridgeBin, bridgeLoginArgs(apiUrl), { stdio: "inherit" });
46891
47078
  return login.status === 0;
46892
47079
  }
46893
47080
  async function bridgeState(apiUrl, apiKey, deviceId) {
@@ -46913,7 +47100,7 @@ async function ensureBridgeRunning(apiUrl, apiKey, opts = {}) {
46913
47100
  console.error(`\x1B[2mBridge not started: \`todoforai-bridge\` was not found on PATH. Install it (curl -fsSL ${INSTALLER_URL} | sh), or pass --no-bridge (or deprecated --no-edge) to silence this.\x1B[0m`);
46914
47101
  return false;
46915
47102
  }
46916
- const hasCreds = spawnSync(bridgeBin, bridgeWhoamiArgs(apiUrl), { stdio: "ignore" }).status === 0 || await enrollBridgeWithApiKey(apiUrl, apiKey) || ensureBridgeCredentials(apiUrl, opts);
47103
+ const hasCreds = spawnSync2(bridgeBin, bridgeWhoamiArgs(apiUrl), { stdio: "ignore" }).status === 0 || await enrollBridgeWithApiKey(apiUrl, apiKey) || ensureBridgeCredentials(apiUrl, opts);
46917
47104
  if (!hasCreds) {
46918
47105
  console.error("\x1B[33mBridge not started: `todoforai-bridge login` did not complete successfully.\x1B[0m");
46919
47106
  return false;
@@ -46930,7 +47117,7 @@ async function ensureBridgeRunning(apiUrl, apiKey, opts = {}) {
46930
47117
  fs2.mkdirSync(logDir, { recursive: true });
46931
47118
  const logFile = path2.join(logDir, "bridge.log");
46932
47119
  const out = fs2.openSync(logFile, "a");
46933
- const child = spawn(bridgeBin, bridgeRunArgs(apiUrl), {
47120
+ const child = spawn2(bridgeBin, bridgeRunArgs(apiUrl), {
46934
47121
  detached: true,
46935
47122
  stdio: ["ignore", out, out]
46936
47123
  });
@@ -47164,7 +47351,7 @@ class ScopedConfig {
47164
47351
  }
47165
47352
  }
47166
47353
  // src/device-login.ts
47167
- import { spawn as spawn2 } from "child_process";
47354
+ import { spawn as spawn3 } from "child_process";
47168
47355
  class DeviceLoginError extends Error {
47169
47356
  }
47170
47357
  async function runDeviceLogin(apiUrl) {
@@ -47182,7 +47369,7 @@ async function runDeviceLogin(apiUrl) {
47182
47369
  `);
47183
47370
  try {
47184
47371
  const [cmd, args] = process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : [process.platform === "darwin" ? "open" : "xdg-open", [url]];
47185
- const child = spawn2(cmd, args, { stdio: "ignore", detached: true });
47372
+ const child = spawn3(cmd, args, { stdio: "ignore", detached: true });
47186
47373
  child.on("error", () => {});
47187
47374
  child.unref();
47188
47375
  } catch {}
@@ -50002,8 +50189,9 @@ ${profile.profile}
50002
50189
  ${DIM}match ${profile.match}/100 · source ${profile.source}${RESET}
50003
50190
  ` : `${DIM}(no voice learned yet)${RESET}
50004
50191
  `);
50005
- for (const s of sources)
50006
- process.stderr.write(` ${s.channel}${s.account ? ` ${s.label} ${DIM}(${s.account})${RESET}` : ""} ${DIM}${s.posts ?? "?"} posts · ${s.chars ?? "?"} chars${RESET}
50192
+ const names = voiceNamesOf(sources);
50193
+ for (const [i, s] of sources.entries())
50194
+ process.stderr.write(` ${names[i]}${s.account ? ` ${DIM}(${s.account})${RESET}` : ""} ${DIM}${s.posts ?? "?"} posts · ${s.chars ?? "?"} chars${RESET}
50007
50195
  `);
50008
50196
  return;
50009
50197
  }
@@ -50780,11 +50968,442 @@ ${message}`).digest("hex").slice(0, 16);
50780
50968
  `);
50781
50969
  }
50782
50970
 
50971
+ // src/import-command.ts
50972
+ import { statSync as statSync3 } from "fs";
50973
+ import { basename as basename3, dirname as dirname3, resolve as resolve4 } from "path";
50974
+
50975
+ // src/import/claude.ts
50976
+ import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync3, statSync } from "fs";
50977
+ import { homedir as homedir3 } from "os";
50978
+ import { join as join3 } from "path";
50979
+
50980
+ // src/import/common.ts
50981
+ import { createHash as createHash2 } from "crypto";
50982
+ var NOTE_MAX_LEN = 2000;
50983
+ var TOOL_RESULT_MAX_LEN = 4000;
50984
+ var SESSION_TITLE_MAX_LEN = 120;
50985
+ var clip = (s, max) => s.length > max ? `${s.slice(0, max)}…` : s;
50986
+ var hashContent = (s) => createHash2("sha256").update(s).digest("hex");
50987
+ function noteToolCall(name, input) {
50988
+ const lines = [`[external_agent_tool_call: ${typeof name === "string" ? name : "tool"}]`];
50989
+ const inp = input && typeof input === "object" ? input : null;
50990
+ let shown = false;
50991
+ if (inp) {
50992
+ for (const [label, keys] of [["description", ["description"]], ["command", ["command", "cmd"]], ["file", ["file_path", "path", "notebook_path"]]]) {
50993
+ const v = keys.map((k) => inp[k]).find((x) => typeof x === "string" && x);
50994
+ if (v) {
50995
+ lines.push(`${label}: ${clip(v, NOTE_MAX_LEN)}`);
50996
+ shown = true;
50997
+ }
50998
+ }
50999
+ }
51000
+ if (!shown && input !== undefined)
51001
+ lines.push(`input: ${clip(typeof input === "string" ? input : JSON.stringify(input), NOTE_MAX_LEN)}`);
51002
+ lines.push("[/external_agent_tool_call]");
51003
+ return lines.join(`
51004
+ `);
51005
+ }
51006
+ function noteToolResult(output, isError) {
51007
+ const head = isError ? "[external_agent_tool_result: error]" : "[external_agent_tool_result]";
51008
+ return `${head}
51009
+ ${clip(output.trim(), TOOL_RESULT_MAX_LEN)}
51010
+ [/external_agent_tool_result]`;
51011
+ }
51012
+ function titleFromMessages(messages, fallback = "Imported session") {
51013
+ const first = messages.find((m) => m.role === "user" && !m.content.startsWith("[external_agent_tool"))?.content ?? "";
51014
+ const line = first.split(`
51015
+ `).map((l) => l.trim()).find(Boolean) ?? "";
51016
+ return line ? clip(line, SESSION_TITLE_MAX_LEN) : fallback;
51017
+ }
51018
+
51019
+ // src/import/claude.ts
51020
+ var claudeHome = () => process.env.CLAUDE_CONFIG_DIR || join3(homedir3(), ".claude");
51021
+ function listClaudeSessionFiles(home = claudeHome()) {
51022
+ const root = join3(home, "projects");
51023
+ if (!existsSync2(root))
51024
+ return [];
51025
+ const files = [];
51026
+ for (const slug of readdirSync(root, { withFileTypes: true })) {
51027
+ if (!slug.isDirectory())
51028
+ continue;
51029
+ const dir = join3(root, slug.name);
51030
+ for (const f of readdirSync(dir))
51031
+ if (f.endsWith(".jsonl"))
51032
+ files.push(join3(dir, f));
51033
+ }
51034
+ return files;
51035
+ }
51036
+ var parseTs = (r) => {
51037
+ if (typeof r.timestamp === "string") {
51038
+ const t = Date.parse(r.timestamp);
51039
+ if (!Number.isNaN(t))
51040
+ return t;
51041
+ }
51042
+ if (typeof r.timestamp_ms === "number")
51043
+ return r.timestamp_ms;
51044
+ return;
51045
+ };
51046
+ var stripUserQuery = (s) => {
51047
+ const m = s.match(/^\s*<user_query>\s*([\s\S]*?)\s*<\/user_query>\s*$/);
51048
+ return m ? m[1] : s;
51049
+ };
51050
+ var isHarnessUserText = (s) => /^\s*<(command-name|local-command-caveat|local-command-stdout|local-command-stderr|system-reminder)>/.test(s);
51051
+ function flattenContent(content) {
51052
+ if (typeof content === "string")
51053
+ return { text: content, onlyToolResults: false };
51054
+ if (!Array.isArray(content))
51055
+ return { text: "", onlyToolResults: false };
51056
+ const parts = [];
51057
+ let toolResults = 0;
51058
+ for (const b of content) {
51059
+ if (!b || typeof b !== "object")
51060
+ continue;
51061
+ switch (b.type) {
51062
+ case "text":
51063
+ if (typeof b.text === "string" && b.text.trim())
51064
+ parts.push(b.text);
51065
+ break;
51066
+ case "tool_use":
51067
+ parts.push(noteToolCall(b.name, b.input));
51068
+ break;
51069
+ case "tool_result": {
51070
+ toolResults++;
51071
+ const inner = typeof b.content === "string" ? b.content : Array.isArray(b.content) ? b.content.map((c3) => c3?.type === "text" ? c3.text : `[${c3?.type ?? "block"}]`).join(`
51072
+ `) : "";
51073
+ parts.push(noteToolResult(inner, b.is_error === true));
51074
+ break;
51075
+ }
51076
+ case "thinking":
51077
+ case "redacted_thinking":
51078
+ break;
51079
+ default:
51080
+ parts.push(`[external unsupported block: ${b.type}]`);
51081
+ }
51082
+ }
51083
+ return { text: parts.join(`
51084
+
51085
+ `), onlyToolResults: toolResults > 0 && toolResults === content.length };
51086
+ }
51087
+ function parseClaudeSession(path3) {
51088
+ const raw = readFileSync3(path3, "utf8");
51089
+ const messages = [];
51090
+ let cwd;
51091
+ let customTitle;
51092
+ let aiTitle;
51093
+ for (const line of raw.split(`
51094
+ `)) {
51095
+ if (!line.trim())
51096
+ continue;
51097
+ let r;
51098
+ try {
51099
+ r = JSON.parse(line);
51100
+ } catch {
51101
+ continue;
51102
+ }
51103
+ if (!cwd && typeof r.cwd === "string" && r.cwd)
51104
+ cwd = r.cwd;
51105
+ if (r.type === "custom-title" && typeof r.customTitle === "string")
51106
+ customTitle = r.customTitle;
51107
+ if (r.type === "ai-title" && typeof r.aiTitle === "string")
51108
+ aiTitle = r.aiTitle;
51109
+ if (r.type !== "user" && r.type !== "assistant")
51110
+ continue;
51111
+ if (r.isMeta === true || r.isSidechain === true)
51112
+ continue;
51113
+ const { text, onlyToolResults } = flattenContent(r.message?.content);
51114
+ const role = r.type === "user" && !onlyToolResults ? "user" : "assistant";
51115
+ const content = (role === "user" ? stripUserQuery(text) : text).trim();
51116
+ if (!content || role === "user" && isHarnessUserText(content))
51117
+ continue;
51118
+ messages.push({ role, content, timestamp: parseTs(r) });
51119
+ }
51120
+ if (!cwd || !messages.some((m) => m.role === "user"))
51121
+ return null;
51122
+ const st = statSync(path3);
51123
+ return {
51124
+ kind: "claude",
51125
+ path: path3,
51126
+ cwd,
51127
+ messages,
51128
+ title: customTitle?.trim() || aiTitle?.trim() || titleFromMessages(messages),
51129
+ sha256: hashContent(raw),
51130
+ modifiedAt: st.mtimeMs
51131
+ };
51132
+ }
51133
+
51134
+ // src/import/codex.ts
51135
+ import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
51136
+ import { homedir as homedir4 } from "os";
51137
+ import { join as join4 } from "path";
51138
+ var codexHome = () => process.env.CODEX_HOME || join4(homedir4(), ".codex");
51139
+ function listCodexSessionFiles(home = codexHome()) {
51140
+ const root = join4(home, "sessions");
51141
+ if (!existsSync3(root))
51142
+ return [];
51143
+ const out = [];
51144
+ const walk = (dir) => {
51145
+ for (const e of readdirSync2(dir, { withFileTypes: true })) {
51146
+ const p = join4(dir, e.name);
51147
+ if (e.isDirectory())
51148
+ walk(p);
51149
+ else if (e.name.startsWith("rollout-") && e.name.endsWith(".jsonl"))
51150
+ out.push(p);
51151
+ }
51152
+ };
51153
+ walk(root);
51154
+ return out;
51155
+ }
51156
+ function readCodexTitles(home = codexHome()) {
51157
+ const titles = new Map;
51158
+ const idx = join4(home, "session_index.jsonl");
51159
+ if (!existsSync3(idx))
51160
+ return titles;
51161
+ for (const line of readFileSync4(idx, "utf8").split(`
51162
+ `)) {
51163
+ try {
51164
+ const r = JSON.parse(line);
51165
+ if (r?.id && typeof r.thread_name === "string")
51166
+ titles.set(r.id, r.thread_name);
51167
+ } catch {}
51168
+ }
51169
+ return titles;
51170
+ }
51171
+ var HARNESS_TAGS = ["environment_context", "recommended_plugins", "user_instructions", "permissions_instructions", "turn_aborted", "collaboration_mode_instructions"];
51172
+ var isHarnessBlock = (s) => {
51173
+ const m = /^\s*<([a-z_]+)>[\s\S]*<\/\1>\s*$/.exec(s);
51174
+ return !!m && HARNESS_TAGS.includes(m[1]);
51175
+ };
51176
+ var partsText = (content, dropHarness = false) => Array.isArray(content) ? content.map((c3) => typeof c3?.text === "string" ? c3.text : "").filter((t) => t.trim() && !(dropHarness && isHarnessBlock(t))).join(`
51177
+
51178
+ `) : typeof content === "string" ? content : "";
51179
+ var outputText = (output) => {
51180
+ if (typeof output === "string") {
51181
+ try {
51182
+ const parsed = JSON.parse(output);
51183
+ if (Array.isArray(parsed))
51184
+ return partsText(parsed);
51185
+ } catch {}
51186
+ return output;
51187
+ }
51188
+ return partsText(output);
51189
+ };
51190
+ function parseCodexSession(path3, titles = readCodexTitles()) {
51191
+ const raw = readFileSync4(path3, "utf8");
51192
+ const messages = [];
51193
+ let cwd;
51194
+ let sessionId;
51195
+ for (const line of raw.split(`
51196
+ `)) {
51197
+ if (!line.trim())
51198
+ continue;
51199
+ let r;
51200
+ try {
51201
+ r = JSON.parse(line);
51202
+ } catch {
51203
+ continue;
51204
+ }
51205
+ const ts = typeof r.timestamp === "string" ? Date.parse(r.timestamp) : NaN;
51206
+ const timestamp = Number.isNaN(ts) ? undefined : ts;
51207
+ if (r.type === "session_meta") {
51208
+ cwd = cwd || r.payload?.cwd;
51209
+ sessionId = sessionId || r.payload?.session_id || r.payload?.id;
51210
+ continue;
51211
+ }
51212
+ if (r.type !== "response_item")
51213
+ continue;
51214
+ const p = r.payload ?? {};
51215
+ switch (p.type) {
51216
+ case "message": {
51217
+ if (p.role !== "user" && p.role !== "assistant")
51218
+ break;
51219
+ const content = partsText(p.content, p.role === "user").trim();
51220
+ if (content)
51221
+ messages.push({ role: p.role, content, timestamp });
51222
+ break;
51223
+ }
51224
+ case "function_call":
51225
+ case "custom_tool_call": {
51226
+ let input = p.arguments ?? p.input;
51227
+ if (typeof input === "string") {
51228
+ try {
51229
+ input = JSON.parse(input);
51230
+ } catch {}
51231
+ }
51232
+ messages.push({ role: "assistant", content: noteToolCall(p.name, input), timestamp });
51233
+ break;
51234
+ }
51235
+ case "function_call_output":
51236
+ case "custom_tool_call_output":
51237
+ messages.push({ role: "assistant", content: noteToolResult(outputText(p.output), false), timestamp });
51238
+ break;
51239
+ default:
51240
+ break;
51241
+ }
51242
+ }
51243
+ if (!cwd || !messages.some((m) => m.role === "user"))
51244
+ return null;
51245
+ const st = statSync2(path3);
51246
+ return {
51247
+ kind: "codex",
51248
+ path: path3,
51249
+ cwd,
51250
+ messages,
51251
+ title: sessionId && titles.get(sessionId)?.trim() || titleFromMessages(messages),
51252
+ sha256: hashContent(raw),
51253
+ modifiedAt: st.mtimeMs
51254
+ };
51255
+ }
51256
+
51257
+ // src/import-command.ts
51258
+ var DEFAULT_MAX_AGE_DAYS = 30;
51259
+ var DEFAULT_MAX_COUNT = 50;
51260
+ var SOURCES = ["claude", "codex"];
51261
+ function printImportHelp() {
51262
+ process.stderr.write(`
51263
+ tfa-cli import — import Claude Code / Codex sessions as todos
51264
+
51265
+ Usage:
51266
+ tfa-cli import [claude|codex] [flags]
51267
+ tfa-cli import <session.jsonl>... [flags]
51268
+
51269
+ Flags:
51270
+ --project <id> Target project (default: current default project)
51271
+ -a, --agent <id|name> Agent for every imported todo (default: match the session cwd, else your default agent)
51272
+ --days <n> Only sessions modified in the last n days (default: ${DEFAULT_MAX_AGE_DAYS}; 0 = all)
51273
+ --limit <n> Max sessions per source, newest first (default: ${DEFAULT_MAX_COUNT}; 0 = all)
51274
+ --dry-run Parse and list, write nothing (no login needed)
51275
+ --json Machine-readable output
51276
+ -h, --help Show this help
51277
+
51278
+ Sources on this machine:
51279
+ Claude Code ${claudeHome()}/projects/*/*.jsonl
51280
+ Codex ${codexHome()}/sessions/**/rollout-*.jsonl
51281
+ `);
51282
+ }
51283
+ var codexTitles;
51284
+ function safeParse(kind, file) {
51285
+ try {
51286
+ return kind === "claude" ? parseClaudeSession(file) : parseCodexSession(file, codexTitles ??= readCodexTitles());
51287
+ } catch {
51288
+ return null;
51289
+ }
51290
+ }
51291
+ function collect(kinds, days, limit) {
51292
+ const cutoff = days > 0 ? Date.now() - days * 86400000 : 0;
51293
+ return kinds.flatMap((kind) => {
51294
+ const files = kind === "claude" ? listClaudeSessionFiles() : listCodexSessionFiles();
51295
+ const sessions = files.map((f) => ({ f, mtime: statSync3(f).mtimeMs })).filter((x) => x.mtime >= cutoff).sort((a, b) => b.mtime - a.mtime).map((x) => safeParse(kind, x.f)).filter((s) => !!s);
51296
+ return limit > 0 ? sessions.slice(0, limit) : sessions;
51297
+ });
51298
+ }
51299
+ async function agentForCwd(api, cwd, fallback, cache) {
51300
+ for (let dir = cwd;; dir = dirname3(dir)) {
51301
+ const hit = cache.get(dir);
51302
+ if (hit)
51303
+ return hit;
51304
+ const matches = await api.listAgentSettings({ workspacePath: dir }).catch(() => []);
51305
+ if (matches.length) {
51306
+ cache.set(dir, matches[0].id);
51307
+ return matches[0].id;
51308
+ }
51309
+ if (dirname3(dir) === dir)
51310
+ break;
51311
+ }
51312
+ cache.set(cwd, fallback);
51313
+ return fallback;
51314
+ }
51315
+ async function importCommand(api, positionals, args, scopedProject, defaultAgentId) {
51316
+ const days = args.days !== undefined ? Number(args.days) : DEFAULT_MAX_AGE_DAYS;
51317
+ const limit = args.limit !== undefined ? Number(args.limit) : DEFAULT_MAX_COUNT;
51318
+ const json = !!args.json;
51319
+ const ops = positionals.slice(1);
51320
+ const named = ops.filter((o) => SOURCES.includes(o));
51321
+ const files = ops.filter((o) => !SOURCES.includes(o)).map((f) => resolve4(f));
51322
+ const skipped = [];
51323
+ const sessions = files.length ? files.flatMap((f) => {
51324
+ const kind = named[0] ?? (basename3(f).startsWith("rollout-") ? "codex" : "claude");
51325
+ const s = safeParse(kind, f);
51326
+ if (!s)
51327
+ skipped.push(f);
51328
+ return s ? [s] : [];
51329
+ }) : collect(named.length ? named : SOURCES, days, limit);
51330
+ if (!json)
51331
+ for (const f of skipped)
51332
+ process.stderr.write(`${YELLOW}skip ${f}: not a readable session${RESET}
51333
+ `);
51334
+ if (args["dry-run"]) {
51335
+ const rows = sessions.map((s) => ({ kind: s.kind, title: s.title, cwd: s.cwd, messages: s.messages.length, path: s.path, modifiedAt: s.modifiedAt }));
51336
+ if (json) {
51337
+ console.log(JSON.stringify({ sessions: rows, skipped }));
51338
+ return;
51339
+ }
51340
+ for (const r of rows)
51341
+ process.stderr.write(`${CYAN}${r.kind.padEnd(7)}${RESET} ${r.title} ${DIM}${r.messages} msgs · ${r.cwd}${RESET}
51342
+ `);
51343
+ process.stderr.write(`${DIM}${rows.length} session(s) — dry run, nothing written${RESET}
51344
+ `);
51345
+ return;
51346
+ }
51347
+ if (!api)
51348
+ throw new Error("import: not authenticated");
51349
+ const projectId = args.project || scopedProject;
51350
+ if (!projectId) {
51351
+ process.stderr.write(`${RED}No project — pass --project <id>${RESET}
51352
+ `);
51353
+ process.exit(2);
51354
+ }
51355
+ let fallbackAgent = defaultAgentId;
51356
+ if (args.agent || !fallbackAgent) {
51357
+ const agents = await api.listAgentSettings();
51358
+ fallbackAgent = args.agent ? agents.find((a) => a.id === args.agent || a.name === args.agent)?.id : agents[0]?.id;
51359
+ if (!fallbackAgent) {
51360
+ process.stderr.write(`${RED}Agent not found — pass --agent <id>${RESET}
51361
+ `);
51362
+ process.exit(2);
51363
+ }
51364
+ }
51365
+ const agentCache = new Map;
51366
+ const results = [];
51367
+ for (const s of sessions) {
51368
+ const agentSettingsId = args.agent ? fallbackAgent : await agentForCwd(api, s.cwd, fallbackAgent, agentCache);
51369
+ try {
51370
+ const r = await api.importSession({
51371
+ projectId,
51372
+ agentSettingsId,
51373
+ title: s.title,
51374
+ messages: s.messages,
51375
+ source: { kind: s.kind, path: s.path, sha256: s.sha256, cwd: s.cwd }
51376
+ });
51377
+ results.push({ ...r, kind: s.kind, title: s.title, path: s.path });
51378
+ if (!json) {
51379
+ const mark = r.outcome === "unchanged" ? `${DIM}=` : `${GREEN}✓`;
51380
+ process.stderr.write(`${mark} ${r.outcome.padEnd(9)}${RESET} ${s.title} ${DIM}${r.messageCount} msgs · ${r.todoId}${RESET}
51381
+ `);
51382
+ }
51383
+ } catch (e) {
51384
+ results.push({ kind: s.kind, title: s.title, path: s.path, error: e.message });
51385
+ if (!json)
51386
+ process.stderr.write(`${RED}✗ failed ${RESET} ${s.title} ${DIM}${e.message}${RESET}
51387
+ `);
51388
+ }
51389
+ }
51390
+ const failed = results.filter((r) => r.error).length;
51391
+ if (json)
51392
+ console.log(JSON.stringify({ imported: results, total: results.length, skipped }));
51393
+ else {
51394
+ const count = (o) => results.filter((r) => r.outcome === o).length;
51395
+ process.stderr.write(`${GREEN}Imported ${count("created")} new, ${count("updated")} updated${failed ? `, ${RED}${failed} failed` : ""}${RESET}
51396
+ `);
51397
+ }
51398
+ if (failed)
51399
+ process.exitCode = 1;
51400
+ }
51401
+
50783
51402
  // src/index.ts
50784
51403
  import { randomUUID as randomUUID3 } from "crypto";
50785
51404
 
50786
51405
  // src/ensure-bridge.ts
50787
- import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
51406
+ import { spawn as spawn4, spawnSync as spawnSync3 } from "child_process";
50788
51407
  import fs3 from "fs";
50789
51408
  import path3 from "path";
50790
51409
  import os4 from "os";
@@ -50793,7 +51412,7 @@ var INSTALL_PREFIX2 = process.env.TODOFORAI_PREFIX || path3.join(os4.homedir(),
50793
51412
  var INSTALL_TIMEOUT_MS2 = 90000;
50794
51413
  var bridgeBin2 = "todoforai-bridge";
50795
51414
  function probeBridge2(bin) {
50796
- return spawnSync2(bin, ["--version"], { stdio: "ignore" }).status === 0;
51415
+ return spawnSync3(bin, ["--version"], { stdio: "ignore" }).status === 0;
50797
51416
  }
50798
51417
  function hasBridge2() {
50799
51418
  if (probeBridge2(bridgeBin2))
@@ -50808,7 +51427,7 @@ function installBridge2() {
50808
51427
  if (process.platform !== "linux" && process.platform !== "darwin")
50809
51428
  return false;
50810
51429
  console.error(`\x1B[2mInstalling TODOforAI Bridge (${INSTALLER_URL2})...\x1B[0m`);
50811
- const r = spawnSync2("sh", ["-c", `curl -fsSL --connect-timeout 10 --max-time 30 ${INSTALLER_URL2} | sh`], { stdio: ["ignore", "ignore", "inherit"], timeout: INSTALL_TIMEOUT_MS2, killSignal: "SIGKILL" });
51430
+ const r = spawnSync3("sh", ["-c", `curl -fsSL --connect-timeout 10 --max-time 30 ${INSTALLER_URL2} | sh`], { stdio: ["ignore", "ignore", "inherit"], timeout: INSTALL_TIMEOUT_MS2, killSignal: "SIGKILL" });
50812
51431
  if (r.error?.code === "ETIMEDOUT")
50813
51432
  console.error("\x1B[33mBridge install timed out\x1B[0m");
50814
51433
  return r.status === 0 && hasBridge2();
@@ -50861,7 +51480,7 @@ function bridgeWhoamiArgs2(apiUrl) {
50861
51480
  return withProfile2(["whoami"], apiUrl);
50862
51481
  }
50863
51482
  function bridgeDeviceId2(apiUrl) {
50864
- const r = spawnSync2(bridgeBin2, bridgeWhoamiArgs2(apiUrl), { encoding: "utf-8" });
51483
+ const r = spawnSync3(bridgeBin2, bridgeWhoamiArgs2(apiUrl), { encoding: "utf-8" });
50865
51484
  if (r.status !== 0)
50866
51485
  return null;
50867
51486
  const m = (r.stdout || "").match(/^Device:.*\(id:\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\)/im);
@@ -50887,11 +51506,11 @@ async function enrollBridgeWithApiKey2(apiUrl, apiKey) {
50887
51506
  console.error(`\x1B[33mBridge enroll: mint failed (${e?.message || e})\x1B[0m`);
50888
51507
  return false;
50889
51508
  }
50890
- const login = spawnSync2(bridgeBin2, [...bridgeLoginArgs2(apiUrl), "--token", token], { stdio: ["ignore", "ignore", "inherit"], timeout: 30000, killSignal: "SIGKILL" });
51509
+ const login = spawnSync3(bridgeBin2, [...bridgeLoginArgs2(apiUrl), "--token", token], { stdio: ["ignore", "ignore", "inherit"], timeout: 30000, killSignal: "SIGKILL" });
50891
51510
  return login.status === 0;
50892
51511
  }
50893
51512
  function ensureBridgeCredentials2(apiUrl, opts = {}) {
50894
- const whoami = spawnSync2(bridgeBin2, bridgeWhoamiArgs2(apiUrl), { stdio: "ignore" });
51513
+ const whoami = spawnSync3(bridgeBin2, bridgeWhoamiArgs2(apiUrl), { stdio: "ignore" });
50895
51514
  if (whoami.status === 0)
50896
51515
  return true;
50897
51516
  if (opts.interactive === false) {
@@ -50899,7 +51518,7 @@ function ensureBridgeCredentials2(apiUrl, opts = {}) {
50899
51518
  return false;
50900
51519
  }
50901
51520
  console.error("\x1B[2mBridge credentials not found. Starting `todoforai-bridge login`...\x1B[0m");
50902
- const login = spawnSync2(bridgeBin2, bridgeLoginArgs2(apiUrl), { stdio: "inherit" });
51521
+ const login = spawnSync3(bridgeBin2, bridgeLoginArgs2(apiUrl), { stdio: "inherit" });
50903
51522
  return login.status === 0;
50904
51523
  }
50905
51524
  async function bridgeState2(apiUrl, apiKey, deviceId) {
@@ -50916,7 +51535,7 @@ async function waitForBridgeOnline2(apiUrl, apiKey, deviceId, timeoutMs = 5000)
50916
51535
  const state = await bridgeState2(apiUrl, apiKey, deviceId);
50917
51536
  if (state !== "offline")
50918
51537
  return state === "online";
50919
- await new Promise((resolve4) => setTimeout(resolve4, 150));
51538
+ await new Promise((resolve5) => setTimeout(resolve5, 150));
50920
51539
  } while (Date.now() < deadline);
50921
51540
  return false;
50922
51541
  }
@@ -50925,7 +51544,7 @@ async function ensureBridgeRunning2(apiUrl, apiKey, opts = {}) {
50925
51544
  console.error(`\x1B[2mBridge not started: \`todoforai-bridge\` was not found on PATH. Install it (curl -fsSL ${INSTALLER_URL2} | sh), or pass --no-bridge (or deprecated --no-edge) to silence this.\x1B[0m`);
50926
51545
  return false;
50927
51546
  }
50928
- const hasCreds = spawnSync2(bridgeBin2, bridgeWhoamiArgs2(apiUrl), { stdio: "ignore" }).status === 0 || await enrollBridgeWithApiKey2(apiUrl, apiKey) || ensureBridgeCredentials2(apiUrl, opts);
51547
+ const hasCreds = spawnSync3(bridgeBin2, bridgeWhoamiArgs2(apiUrl), { stdio: "ignore" }).status === 0 || await enrollBridgeWithApiKey2(apiUrl, apiKey) || ensureBridgeCredentials2(apiUrl, opts);
50929
51548
  if (!hasCreds) {
50930
51549
  console.error("\x1B[33mBridge not started: `todoforai-bridge login` did not complete successfully.\x1B[0m");
50931
51550
  return false;
@@ -50942,7 +51561,7 @@ async function ensureBridgeRunning2(apiUrl, apiKey, opts = {}) {
50942
51561
  fs3.mkdirSync(logDir, { recursive: true });
50943
51562
  const logFile = path3.join(logDir, "bridge.log");
50944
51563
  const out = fs3.openSync(logFile, "a");
50945
- const child = spawn3(bridgeBin2, bridgeRunArgs2(apiUrl), {
51564
+ const child = spawn4(bridgeBin2, bridgeRunArgs2(apiUrl), {
50946
51565
  detached: true,
50947
51566
  stdio: ["ignore", out, out]
50948
51567
  });
@@ -50967,7 +51586,7 @@ async function ensureBridgeRunning2(apiUrl, apiKey, opts = {}) {
50967
51586
  }
50968
51587
 
50969
51588
  // src/isolated.ts
50970
- import { spawn as spawn4 } from "child_process";
51589
+ import { spawn as spawn5 } from "child_process";
50971
51590
  async function mintMayflyToken(apiUrl, apiKey, todoId) {
50972
51591
  const res = await fetch(`${apiUrl}${restBasePath(apiKey)}/cli/mayfly/token`, {
50973
51592
  method: "POST",
@@ -50998,7 +51617,7 @@ async function spawnMayflyBridge(apiUrl, todoId, workspace, opts = {}) {
50998
51617
  delete env2[p + n];
50999
51618
  env2.TODOFORAI_MAYFLY_TOKEN = sessionToken;
51000
51619
  }
51001
- const child = spawn4(bridgeBinary(), args, { stdio: ["ignore", "pipe", "pipe"], env: env2 });
51620
+ const child = spawn5(bridgeBinary(), args, { stdio: ["ignore", "pipe", "pipe"], env: env2 });
51002
51621
  let stopped = false;
51003
51622
  const stop = () => {
51004
51623
  if (stopped)
@@ -51092,9 +51711,7 @@ var CLIENT_METHODS = {
51092
51711
  terminal_release: "terminal/release",
51093
51712
  terminal_wait_for_exit: "terminal/wait_for_exit",
51094
51713
  terminal_kill: "terminal/kill",
51095
- mcp_connect: "mcp/connect",
51096
51714
  mcp_message: "mcp/message",
51097
- mcp_disconnect: "mcp/disconnect",
51098
51715
  elicitation_create: "elicitation/create",
51099
51716
  elicitation_complete: "elicitation/complete"
51100
51717
  };
@@ -51147,7 +51764,7 @@ __export(exports_external, {
51147
51764
  setErrorMap: () => setErrorMap,
51148
51765
  set: () => set,
51149
51766
  safeParseAsync: () => safeParseAsync2,
51150
- safeParse: () => safeParse2,
51767
+ safeParse: () => safeParse3,
51151
51768
  safeEncodeAsync: () => safeEncodeAsync2,
51152
51769
  safeEncode: () => safeEncode2,
51153
51770
  safeDecodeAsync: () => safeDecodeAsync2,
@@ -51384,7 +52001,7 @@ __export(exports_core2, {
51384
52001
  stripTabAndNewline: () => stripTabAndNewline,
51385
52002
  standardProps: () => standardProps,
51386
52003
  safeParseAsync: () => safeParseAsync,
51387
- safeParse: () => safeParse,
52004
+ safeParse: () => safeParse2,
51388
52005
  safeEncodeAsync: () => safeEncodeAsync,
51389
52006
  safeEncode: () => safeEncode,
51390
52007
  safeDecodeAsync: () => safeDecodeAsync,
@@ -52880,7 +53497,7 @@ var _safeParse = (_Err) => (schema, value, _ctx) => {
52880
53497
  }
52881
53498
  return result.issues.length ? failure(_Err, result.issues, ctx) : { success: true, data: result.value };
52882
53499
  };
52883
- var safeParse = /* @__PURE__ */ _safeParse($ZodRealError);
53500
+ var safeParse2 = /* @__PURE__ */ _safeParse($ZodRealError);
52884
53501
  function failure(Err, issues, ctx) {
52885
53502
  let error;
52886
53503
  return {
@@ -55068,7 +55685,7 @@ function handleIntersectionResults(result, left, right) {
55068
55685
  const unrecKeys = new Map;
55069
55686
  let unrecIssue;
55070
55687
  const keyIssues = new Map;
55071
- const collect = (iss, side) => {
55688
+ const collect2 = (iss, side) => {
55072
55689
  let keys;
55073
55690
  if (iss.code === "unrecognized_keys" && !iss.path?.length) {
55074
55691
  unrecIssue ?? (unrecIssue = iss);
@@ -55089,11 +55706,11 @@ function handleIntersectionResults(result, left, right) {
55089
55706
  return true;
55090
55707
  };
55091
55708
  for (const iss of left.issues) {
55092
- if (!collect(iss, "l"))
55709
+ if (!collect2(iss, "l"))
55093
55710
  result.issues.push(iss);
55094
55711
  }
55095
55712
  for (const iss of right.issues) {
55096
- if (!collect(iss, "r"))
55713
+ if (!collect2(iss, "r"))
55097
55714
  result.issues.push(iss);
55098
55715
  }
55099
55716
  const bothKeys = [...unrecKeys].filter(([, f]) => f.l && f.r).map(([k]) => k);
@@ -56109,7 +56726,7 @@ var recursive = /* @__PURE__ */ new WeakMap;
56109
56726
  var NONE = 0;
56110
56727
  var ASSUMED = 1;
56111
56728
  var PROVEN = 2;
56112
- function isRecursive(inst, stack, resolve4) {
56729
+ function isRecursive(inst, stack, resolve5) {
56113
56730
  const cached2 = recursive.get(inst);
56114
56731
  if (cached2 !== undefined)
56115
56732
  return cached2 ? PROVEN : NONE;
@@ -56119,7 +56736,7 @@ function isRecursive(inst, stack, resolve4) {
56119
56736
  let result = NONE;
56120
56737
  const check = (child) => {
56121
56738
  if (result !== PROVEN && child?._zod) {
56122
- const answer = isRecursive(child, stack, resolve4);
56739
+ const answer = isRecursive(child, stack, resolve5);
56123
56740
  if (answer > result)
56124
56741
  result = answer;
56125
56742
  }
@@ -56130,7 +56747,7 @@ function isRecursive(inst, stack, resolve4) {
56130
56747
  const desc = Object.getOwnPropertyDescriptor(sh, key);
56131
56748
  if (spread && !desc.enumerable)
56132
56749
  continue;
56133
- const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve4) : NONE;
56750
+ const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve5) : NONE;
56134
56751
  if (child > answer)
56135
56752
  answer = child;
56136
56753
  }
@@ -56193,7 +56810,7 @@ function isRecursive(inst, stack, resolve4) {
56193
56810
  check(def.output);
56194
56811
  break;
56195
56812
  case "lazy": {
56196
- const inner = def._cachedInner ?? (resolve4 ? inst._zod.innerType : undefined);
56813
+ const inner = def._cachedInner ?? (resolve5 ? inst._zod.innerType : undefined);
56197
56814
  merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
56198
56815
  break;
56199
56816
  }
@@ -68039,7 +68656,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, undefi
68039
68656
  // node_modules/zod/v4/classic/parse.js
68040
68657
  var parse3 = /* @__PURE__ */ _parse(ZodRealError);
68041
68658
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
68042
- var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
68659
+ var safeParse3 = /* @__PURE__ */ _safeParse(ZodRealError);
68043
68660
  var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
68044
68661
  var encode2 = /* @__PURE__ */ _encode(ZodRealError);
68045
68662
  var decode2 = /* @__PURE__ */ _decode(ZodRealError);
@@ -68179,7 +68796,7 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
68179
68796
  return await parseAsync2(this, data, params, { callee: _parseAsync2 });
68180
68797
  },
68181
68798
  safeParse(data, params) {
68182
- return safeParse2(this, data, params);
68799
+ return safeParse3(this, data, params);
68183
68800
  },
68184
68801
  async safeParseAsync(data, params) {
68185
68802
  return safeParseAsync2(this, data, params);
@@ -71043,27 +71660,16 @@ var zCreateElicitationRequest = preserveCustomPayload(intersection(union([
71043
71660
  })
71044
71661
  })), "mode", ["form", "url"]);
71045
71662
  var zMcpServerAcpId = string2();
71046
- var zConnectMcpRequest = object({
71047
- serverId: zMcpServerAcpId,
71048
- _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
71049
- return;
71050
- })
71051
- });
71052
- var zMcpConnectionId = string2();
71663
+ var zMcpRequestId = string2();
71053
71664
  var zMessageMcpRequest = object({
71054
- connectionId: zMcpConnectionId,
71665
+ serverId: zMcpServerAcpId,
71666
+ requestId: zMcpRequestId,
71055
71667
  method: string2(),
71056
71668
  params: record(string2(), unknown()).nullish(),
71057
71669
  _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
71058
71670
  return;
71059
71671
  })
71060
71672
  });
71061
- var zDisconnectMcpRequest = object({
71062
- connectionId: zMcpConnectionId,
71063
- _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
71064
- return;
71065
- })
71066
- });
71067
71673
  var zExtRequest = unknown();
71068
71674
  var zAgentRequest = object({
71069
71675
  id: zRequestId,
@@ -71078,9 +71684,7 @@ var zAgentRequest = object({
71078
71684
  zWaitForTerminalExitRequest,
71079
71685
  zKillTerminalRequest,
71080
71686
  zCreateElicitationRequest,
71081
- zConnectMcpRequest,
71082
71687
  zMessageMcpRequest,
71083
- zDisconnectMcpRequest,
71084
71688
  zExtRequest
71085
71689
  ]).nullish()
71086
71690
  });
@@ -71776,7 +72380,6 @@ var zCloseNesResponse = object({
71776
72380
  })
71777
72381
  });
71778
72382
  var zExtResponse = unknown();
71779
- var zMessageMcpResponse = unknown();
71780
72383
  var zErrorCode = union([
71781
72384
  literal(-32700),
71782
72385
  literal(-32600),
@@ -71822,8 +72425,7 @@ var zAgentResponse = union([
71822
72425
  zStartNesResponse,
71823
72426
  zSuggestNesResponse,
71824
72427
  zCloseNesResponse,
71825
- zExtResponse,
71826
- zMessageMcpResponse
72428
+ zExtResponse
71827
72429
  ])
71828
72430
  }),
71829
72431
  object({
@@ -72041,6 +72643,108 @@ var zCompactionSummaryChunk = object({
72041
72643
  return;
72042
72644
  })
72043
72645
  });
72646
+ var zSessionCancelCapabilities = object({
72647
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72648
+ return;
72649
+ })
72650
+ });
72651
+ var zSubagentSessionCapabilities = object({
72652
+ cancel: defaultOnError(zSessionCancelCapabilities.nullish(), () => {
72653
+ return;
72654
+ }),
72655
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72656
+ return;
72657
+ })
72658
+ });
72659
+ var zRunningStateUpdate = object({
72660
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72661
+ return;
72662
+ })
72663
+ });
72664
+ var zIdleStateUpdate = object({
72665
+ stopReason: defaultOnError(zStopReason.nullish(), () => {
72666
+ return;
72667
+ }),
72668
+ usage: defaultOnError(zUsage.nullish(), () => {
72669
+ return;
72670
+ }),
72671
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72672
+ return;
72673
+ })
72674
+ });
72675
+ var zRequiresActionStateUpdate = object({
72676
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72677
+ return;
72678
+ })
72679
+ });
72680
+ var zUnknownStateUpdate = object({
72681
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72682
+ return;
72683
+ })
72684
+ });
72685
+ var zStateUpdate = preserveCustomPayload(union([
72686
+ zRunningStateUpdate.and(object({
72687
+ state: literal("running")
72688
+ })),
72689
+ zIdleStateUpdate.and(object({
72690
+ state: literal("idle")
72691
+ })),
72692
+ zRequiresActionStateUpdate.and(object({
72693
+ state: literal("requires_action")
72694
+ })),
72695
+ zUnknownStateUpdate.and(object({
72696
+ state: literal("unknown")
72697
+ })),
72698
+ excludeKnownTags(object({
72699
+ state: string2()
72700
+ }), "state", ["idle", "requires_action", "running", "unknown"])
72701
+ ]), "state", ["idle", "requires_action", "running", "unknown"]);
72702
+ var zSubagentUpdate = object({
72703
+ sessionId: zSessionId,
72704
+ title: defaultOnError(string2().nullish(), () => {
72705
+ return;
72706
+ }),
72707
+ description: defaultOnError(string2().nullish(), () => {
72708
+ return;
72709
+ }),
72710
+ capabilities: defaultOnError(zSubagentSessionCapabilities.nullish(), () => {
72711
+ return;
72712
+ }),
72713
+ state: defaultOnError(zStateUpdate.nullish(), () => {
72714
+ return;
72715
+ }),
72716
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72717
+ return;
72718
+ })
72719
+ });
72720
+ var zSessionMessage = object({
72721
+ messageId: zMessageId,
72722
+ senderSessionId: defaultOnError(zSessionId.nullish(), () => {
72723
+ return;
72724
+ }),
72725
+ recipientSessionId: defaultOnError(zSessionId.nullish(), () => {
72726
+ return;
72727
+ }),
72728
+ content: defaultOnError(vecSkipError(zContentBlock).nullish(), () => {
72729
+ return;
72730
+ }),
72731
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72732
+ return;
72733
+ })
72734
+ });
72735
+ var zSessionMessageChunk = object({
72736
+ messageId: zMessageId,
72737
+ senderSessionId: defaultOnError(zSessionId.nullish(), () => {
72738
+ return;
72739
+ }),
72740
+ recipientSessionId: defaultOnError(zSessionId.nullish(), () => {
72741
+ return;
72742
+ }),
72743
+ content: zContentBlock,
72744
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72745
+ return;
72746
+ })
72747
+ });
72044
72748
  var zSessionUpdate = union([
72045
72749
  zContentChunk.and(object({
72046
72750
  sessionUpdate: literal("user_message_chunk")
@@ -72089,6 +72793,15 @@ var zSessionUpdate = union([
72089
72793
  })),
72090
72794
  zCompactionSummaryChunk.and(object({
72091
72795
  sessionUpdate: literal("compaction_summary_chunk")
72796
+ })),
72797
+ zSubagentUpdate.and(object({
72798
+ sessionUpdate: literal("subagent_update")
72799
+ })),
72800
+ zSessionMessage.and(object({
72801
+ sessionUpdate: literal("session_message")
72802
+ })),
72803
+ zSessionMessageChunk.and(object({
72804
+ sessionUpdate: literal("session_message_chunk")
72092
72805
  }))
72093
72806
  ]);
72094
72807
  var zSessionNotification = object({
@@ -72104,23 +72817,12 @@ var zCompleteElicitationNotification = object({
72104
72817
  return;
72105
72818
  })
72106
72819
  });
72107
- var zMessageMcpNotification = object({
72108
- connectionId: zMcpConnectionId,
72109
- method: string2(),
72110
- params: defaultOnError(record(string2(), unknown()).nullish(), () => {
72111
- return;
72112
- }),
72113
- _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72114
- return;
72115
- })
72116
- });
72117
72820
  var zExtNotification = unknown();
72118
72821
  var zAgentNotification = object({
72119
72822
  method: string2(),
72120
72823
  params: union([
72121
72824
  zSessionNotification,
72122
72825
  zCompleteElicitationNotification,
72123
- zMessageMcpNotification,
72124
72826
  zExtNotification
72125
72827
  ]).nullish()
72126
72828
  });
@@ -72160,6 +72862,11 @@ var zClientSessionCapabilities = object({
72160
72862
  return;
72161
72863
  })
72162
72864
  });
72865
+ var zSubagentCapabilities = object({
72866
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72867
+ return;
72868
+ })
72869
+ });
72163
72870
  var zPlanCapabilities = object({
72164
72871
  _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72165
72872
  return;
@@ -72227,6 +72934,9 @@ var zClientCapabilities = object({
72227
72934
  session: defaultOnError(zClientSessionCapabilities.nullish(), () => {
72228
72935
  return;
72229
72936
  }),
72937
+ subagents: defaultOnError(zSubagentCapabilities.nullish(), () => {
72938
+ return;
72939
+ }),
72230
72940
  plan: defaultOnError(zPlanCapabilities.nullish(), () => {
72231
72941
  return;
72232
72942
  }),
@@ -72580,7 +73290,6 @@ var zClientRequest = object({
72580
73290
  zStartNesRequest,
72581
73291
  zSuggestNesRequest,
72582
73292
  zCloseNesRequest,
72583
- zMessageMcpRequest,
72584
73293
  zExtRequest
72585
73294
  ]).nullish()
72586
73295
  });
@@ -72695,17 +73404,29 @@ var zCreateElicitationResponse = preserveCustomPayload(intersection(union([
72695
73404
  return;
72696
73405
  })
72697
73406
  })), "action", ["accept", "cancel", "decline"]);
72698
- var zConnectMcpResponse = object({
72699
- connectionId: zMcpConnectionId,
72700
- _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72701
- return;
72702
- })
73407
+ var zMcpError = looseObject({
73408
+ code: int().min(-2147483648, {
73409
+ error: "Invalid value: Expected int32 to be >= -2147483648"
73410
+ }).max(2147483647, {
73411
+ error: "Invalid value: Expected int32 to be <= 2147483647"
73412
+ }),
73413
+ message: string2(),
73414
+ data: unknown().optional()
72703
73415
  });
72704
- var zDisconnectMcpResponse = object({
72705
- _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
72706
- return;
73416
+ var zMessageMcpResponse = union([
73417
+ object({
73418
+ result: unknown(),
73419
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
73420
+ return;
73421
+ })
73422
+ }),
73423
+ object({
73424
+ error: zMcpError,
73425
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
73426
+ return;
73427
+ })
72707
73428
  })
72708
- });
73429
+ ]);
72709
73430
  var zClientResponse = union([
72710
73431
  object({
72711
73432
  id: zRequestId,
@@ -72719,8 +73440,6 @@ var zClientResponse = union([
72719
73440
  zWaitForTerminalExitResponse,
72720
73441
  zKillTerminalResponse,
72721
73442
  zCreateElicitationResponse,
72722
- zConnectMcpResponse,
72723
- zDisconnectMcpResponse,
72724
73443
  zMessageMcpResponse,
72725
73444
  zExtResponse
72726
73445
  ])
@@ -72809,6 +73528,15 @@ var zRejectNesNotification = object({
72809
73528
  return;
72810
73529
  })
72811
73530
  });
73531
+ var zMessageMcpNotification = object({
73532
+ serverId: zMcpServerAcpId,
73533
+ requestId: zMcpRequestId,
73534
+ method: string2(),
73535
+ params: record(string2(), unknown()).nullish(),
73536
+ _meta: defaultOnError(record(string2(), unknown()).nullish(), () => {
73537
+ return;
73538
+ })
73539
+ });
72812
73540
  var zClientNotification = object({
72813
73541
  method: string2(),
72814
73542
  params: union([
@@ -73176,11 +73904,11 @@ class Connection {
73176
73904
  prepareRequest(method, params, mapResponse, options = {}) {
73177
73905
  const id = this.nextRequestId++;
73178
73906
  let cancel = () => {};
73179
- const response = new Promise((resolve4, reject) => {
73907
+ const response = new Promise((resolve5, reject) => {
73180
73908
  const pendingResponse = {
73181
73909
  resolve: (value) => {
73182
73910
  try {
73183
- resolve4(mapResponse ? mapResponse(value) : value);
73911
+ resolve5(mapResponse ? mapResponse(value) : value);
73184
73912
  } catch (error62) {
73185
73913
  reject(error62);
73186
73914
  }
@@ -73231,8 +73959,8 @@ class Connection {
73231
73959
  this.stream = stream;
73232
73960
  this.staticHandlers = handlers;
73233
73961
  this.allowBatches = options?.allowBatches ?? true;
73234
- this.closedPromise = new Promise((resolve4) => {
73235
- this.abortController.signal.addEventListener("abort", () => resolve4());
73962
+ this.closedPromise = new Promise((resolve5) => {
73963
+ this.abortController.signal.addEventListener("abort", () => resolve5());
73236
73964
  });
73237
73965
  this.receive();
73238
73966
  }
@@ -73826,6 +74554,10 @@ var zGuardElicitationPropertySchemaInteger = zIntegerPropertySchema.and(object({
73826
74554
  var zGuardElicitationPropertySchemaBoolean = zBooleanPropertySchema.and(object({ type: literal("boolean") }));
73827
74555
  var zGuardElicitationPropertySchemaArray = zMultiSelectPropertySchema.and(object({ type: literal("array") }));
73828
74556
  var zGuardMultiSelectItemsString = zStringMultiSelectItems.and(object({ type: literal("string") }));
74557
+ var zGuardStateUpdateRunning = zRunningStateUpdate.and(object({ state: literal("running") }));
74558
+ var zGuardStateUpdateIdle = zIdleStateUpdate.and(object({ state: literal("idle") }));
74559
+ var zGuardStateUpdateRequiresAction = zRequiresActionStateUpdate.and(object({ state: literal("requires_action") }));
74560
+ var zGuardStateUpdateUnknown = zUnknownStateUpdate.and(object({ state: literal("unknown") }));
73829
74561
  var zGuardCreateElicitationResponseAccept = zElicitationAcceptAction.and(object({ action: literal("accept") }));
73830
74562
  var zGuardCreateElicitationResponseDecline = object({
73831
74563
  action: literal("decline")
@@ -74120,8 +74852,8 @@ class AsyncQueue {
74120
74852
  if (this.failed) {
74121
74853
  return Promise.reject(this.failure);
74122
74854
  }
74123
- return new Promise((resolve4, reject) => {
74124
- this.waiters.push({ resolve: resolve4, reject });
74855
+ return new Promise((resolve5, reject) => {
74856
+ this.waiters.push({ resolve: resolve5, reject });
74125
74857
  });
74126
74858
  }
74127
74859
  }
@@ -74849,7 +75581,7 @@ function classifyBlock2(info) {
74849
75581
  }
74850
75582
 
74851
75583
  // src/device-login.ts
74852
- import { spawn as spawn5 } from "child_process";
75584
+ import { spawn as spawn6 } from "child_process";
74853
75585
  class DeviceLoginError2 extends Error {
74854
75586
  }
74855
75587
  async function runDeviceLogin2(apiUrl) {
@@ -74867,7 +75599,7 @@ async function runDeviceLogin2(apiUrl) {
74867
75599
  `);
74868
75600
  try {
74869
75601
  const [cmd, args] = process.platform === "win32" ? ["cmd", ["/c", "start", "", url2]] : [process.platform === "darwin" ? "open" : "xdg-open", [url2]];
74870
- const child = spawn5(cmd, args, { stdio: "ignore", detached: true });
75602
+ const child = spawn6(cmd, args, { stdio: "ignore", detached: true });
74871
75603
  child.on("error", () => {});
74872
75604
  child.unref();
74873
75605
  } catch {}
@@ -74897,7 +75629,7 @@ async function runDeviceLogin2(apiUrl) {
74897
75629
  }
74898
75630
 
74899
75631
  // src/acp.ts
74900
- var log2 = (...a) => process.stderr.write(`[acp] ${a.join(" ")}
75632
+ var log3 = (...a) => process.stderr.write(`[acp] ${a.join(" ")}
74901
75633
  `);
74902
75634
  var ACP_KIND = { create: "edit", edit: "edit", read: "read", search: "search", shell: "execute" };
74903
75635
  var toolTitle = (info) => {
@@ -74973,7 +75705,7 @@ class TodoforaiAgent {
74973
75705
  }
74974
75706
  this.api = new ApiClient(this.apiUrl, this.apiKey);
74975
75707
  this.ws = ws;
74976
- log2(`ready (${this.apiUrl})`);
75708
+ log3(`ready (${this.apiUrl})`);
74977
75709
  })();
74978
75710
  }
74979
75711
  async requireAuth() {
@@ -75018,7 +75750,7 @@ class TodoforaiAgent {
75018
75750
  const agent2 = await this.resolveAgent(cwd);
75019
75751
  const todoId = randomUUID2();
75020
75752
  this.sessions.set(todoId, { todoId, projectId, agent: agent2 });
75021
- log2(`session ${todoId} agent=${agent2.name} cwd=${cwd}`);
75753
+ log3(`session ${todoId} agent=${agent2.name} cwd=${cwd}`);
75022
75754
  return { sessionId: todoId, modes: await this.modes(agent2) };
75023
75755
  }
75024
75756
  async setSessionMode(p) {
@@ -75029,7 +75761,7 @@ class TodoforaiAgent {
75029
75761
  if (!agent2)
75030
75762
  throw RequestError.invalidParams(`unknown agent ${p.modeId}`);
75031
75763
  s.agent = agent2;
75032
- log2(`session ${s.todoId} agent=${agent2.name}`);
75764
+ log3(`session ${s.todoId} agent=${agent2.name}`);
75033
75765
  this.conn.sessionUpdate({ sessionId: p.sessionId, update: { sessionUpdate: "current_mode_update", currentModeId: agent2.id } });
75034
75766
  return {};
75035
75767
  }
@@ -75039,7 +75771,7 @@ class TodoforaiAgent {
75039
75771
  return;
75040
75772
  s.turn.cancelled = true;
75041
75773
  if (s.turn.started && !await this.ws.sendInterrupt(s.projectId, s.todoId))
75042
- log2("interrupt not delivered (socket down)");
75774
+ log3("interrupt not delivered (socket down)");
75043
75775
  }
75044
75776
  async prompt(p) {
75045
75777
  const s = this.sessions.get(p.sessionId);
@@ -75054,7 +75786,7 @@ ${b.resource.text}
75054
75786
  </file>
75055
75787
  ` : "").join("");
75056
75788
  const sessionId = p.sessionId;
75057
- const update = (u) => this.conn.sessionUpdate({ sessionId, update: u }).catch((e) => log2("update failed", e?.message));
75789
+ const update = (u) => this.conn.sessionUpdate({ sessionId, update: u }).catch((e) => log3("update failed", e?.message));
75058
75790
  const blocks4 = new Map;
75059
75791
  const view = (id) => blocks4.get(id) ?? blocks4.set(id, new BlockView).get(id);
75060
75792
  const announce = (id, b) => {
@@ -75088,9 +75820,9 @@ ${b.resource.text}
75088
75820
  return;
75089
75821
  const ok = choice === "allow_once" || choice === "allow_remember" ? await this.ws.sendBlockApproval(s.todoId, messageId, id, choice, choice === "allow_remember" ? patterns : undefined) : await this.ws.sendBlockDeny(s.todoId, messageId, id);
75090
75822
  if (!ok)
75091
- log2(`approval for ${id} not delivered (socket down)`);
75823
+ log3(`approval for ${id} not delivered (socket down)`);
75092
75824
  } catch (e) {
75093
- log2("permission request failed", e?.message);
75825
+ log3("permission request failed", e?.message);
75094
75826
  }
75095
75827
  };
75096
75828
  const onEvent = (type, payload) => {
@@ -75166,18 +75898,18 @@ ${b.resource.text}
75166
75898
  async function runAcp(apiUrl, apiKey, opts) {
75167
75899
  console.log = (...a) => process.stderr.write(a.map(String).join(" ") + `
75168
75900
  `);
75169
- const eof = new Promise((resolve4) => {
75170
- process.stdin.once("end", resolve4);
75171
- process.stdin.once("close", resolve4);
75172
- process.stdin.once("error", resolve4);
75901
+ const eof = new Promise((resolve5) => {
75902
+ process.stdin.once("end", resolve5);
75903
+ process.stdin.once("close", resolve5);
75904
+ process.stdin.once("error", resolve5);
75173
75905
  });
75174
75906
  const stream = ndJsonStream2(Writable.toWeb(process.stdout), Readable.toWeb(process.stdin));
75175
75907
  let agent2;
75176
75908
  new AgentSideConnection((conn) => agent2 = new TodoforaiAgent(conn, apiUrl, apiKey, opts), stream);
75177
75909
  if (apiKey)
75178
- agent2.connect().catch((e) => log2("connect failed:", e?.message));
75910
+ agent2.connect().catch((e) => log3("connect failed:", e?.message));
75179
75911
  else
75180
- log2("not logged in — waiting for authenticate");
75912
+ log3("not logged in — waiting for authenticate");
75181
75913
  await eof;
75182
75914
  await agent2.close();
75183
75915
  }
@@ -75270,13 +76002,15 @@ function installSignalHandlers() {
75270
76002
  }
75271
76003
 
75272
76004
  // src/index.ts
76005
+ var ownPkg;
75273
76006
  try {
75274
- const pkgPath = path4.resolve(fileURLToPath(import.meta.url), "../../package.json");
75275
- checkForUpdates(JSON.parse(readFileSync3(pkgPath, "utf-8")));
76007
+ ownPkg = JSON.parse(readFileSync5(path4.resolve(fileURLToPath(import.meta.url), "../../package.json"), "utf-8"));
76008
+ if (process.argv[2] !== "update")
76009
+ backgroundUpdate(ownPkg);
75276
76010
  } catch {}
75277
76011
  var aliasTodoId = (alias) => typeof alias === "string" && alias.includes(":") ? alias.slice(0, alias.indexOf(":")) : undefined;
75278
76012
  function formatPathWithTilde(path5) {
75279
- const home = homedir3();
76013
+ const home = homedir5();
75280
76014
  return path5.startsWith(home) ? path5.replace(home, "~") : path5;
75281
76015
  }
75282
76016
  function promptArg(words) {
@@ -75386,6 +76120,10 @@ async function main() {
75386
76120
  console.log(VERSION);
75387
76121
  process.exit(0);
75388
76122
  }
76123
+ if (positionals[0] === "update") {
76124
+ const r = ownPkg ? await selfUpdate(ownPkg) : "unsupported";
76125
+ process.exit(r === "updated" || r === "current" ? 0 : 1);
76126
+ }
75389
76127
  if (positionals[0] === "status" && args.help) {
75390
76128
  printStatusHelp();
75391
76129
  process.exit(0);
@@ -75422,11 +76160,19 @@ async function main() {
75422
76160
  printNotifyHelp();
75423
76161
  process.exit(0);
75424
76162
  }
76163
+ if (positionals[0] === "import" && args.help) {
76164
+ printImportHelp();
76165
+ process.exit(0);
76166
+ }
76167
+ if (positionals[0] === "import" && args["dry-run"]) {
76168
+ await importCommand(null, positionals, args);
76169
+ return;
76170
+ }
75425
76171
  if ((positionals[0] === "list" || positionals[0] === "ls") && args.help) {
75426
76172
  printListTodosHelp();
75427
76173
  process.exit(0);
75428
76174
  }
75429
- if (args.help && !["list", "ls", "agent", "todo", "project", "brand", "device", "inbox", "notify"].includes(positionals[0])) {
76175
+ if (args.help && !["list", "ls", "agent", "todo", "project", "brand", "device", "inbox", "notify", "import"].includes(positionals[0])) {
75430
76176
  printUsage();
75431
76177
  process.exit(0);
75432
76178
  }
@@ -75455,7 +76201,7 @@ async function main() {
75455
76201
  }
75456
76202
  if (args["reset-config"]) {
75457
76203
  const { unlinkSync } = await import("fs");
75458
- if (existsSync2(cfg.path)) {
76204
+ if (existsSync4(cfg.path)) {
75459
76205
  unlinkSync(cfg.path);
75460
76206
  console.log(`Configuration reset: ${formatPathWithTilde(cfg.path)}`);
75461
76207
  } else
@@ -75565,6 +76311,10 @@ async function main() {
75565
76311
  await notifyCommand(api2, positionals, args, scopedProject);
75566
76312
  return;
75567
76313
  }
76314
+ if (positionals[0] === "import") {
76315
+ await importCommand(api2, positionals, args, scopedProject, cfgScope.data.default_agent_settings?.id);
76316
+ return;
76317
+ }
75568
76318
  if (positionals[0] === "delete") {
75569
76319
  const todoId = positionals[1];
75570
76320
  if (!todoId) {
@@ -75678,13 +76428,13 @@ async function main() {
75678
76428
  }
75679
76429
  name = "stdin";
75680
76430
  } else {
75681
- const abs = resolve4(filePath);
75682
- if (!existsSync2(abs)) {
76431
+ const abs = resolve5(filePath);
76432
+ if (!existsSync4(abs)) {
75683
76433
  process.stderr.write(`${RED3}File not found: ${filePath}${RESET2}
75684
76434
  `);
75685
76435
  process.exit(1);
75686
76436
  }
75687
- blob = new Blob([readFileSync3(abs)], { type: getMimeTypeFromFilename(abs) || undefined });
76437
+ blob = new Blob([readFileSync5(abs)], { type: getMimeTypeFromFilename(abs) || undefined });
75688
76438
  name = path4.basename(filePath);
75689
76439
  }
75690
76440
  const res = await api2.showFile(todoId, blob, name, {
@@ -76016,7 +76766,7 @@ Resumed: ${CYAN2}${getFrontendUrl(apiUrl, todoId)}${RESET2}
76016
76766
  const wsReady = ws ? ws.connect() : null;
76017
76767
  const bridgeReady = !args["no-bridge"] && !args["no-watch"] && !args.isolated ? ensureBridgeRunning2(apiUrl, apiKey) : null;
76018
76768
  const isolatedTodoId = args.isolated ? randomUUID3() : undefined;
76019
- const mayfly = isolatedTodoId ? await spawnMayflyBridge(apiUrl, isolatedTodoId, realpathSync2(resolve4(args.path || ".")), { debug: !!args.debug, apiKey }) : null;
76769
+ const mayfly = isolatedTodoId ? await spawnMayflyBridge(apiUrl, isolatedTodoId, realpathSync2(resolve5(args.path || ".")), { debug: !!args.debug, apiKey }) : null;
76020
76770
  if (mayfly) {
76021
76771
  process.stderr.write(`${DIM2}Isolated bridge:${RESET2} ${CYAN2}mayfly-${isolatedTodoId}${RESET2}
76022
76772
  `);
@@ -76048,7 +76798,7 @@ Resumed: ${CYAN2}${getFrontendUrl(apiUrl, todoId)}${RESET2}
76048
76798
  cfgScope.setDefaultAgent(getDisplayName(preMatchedAgent), preMatchedAgent);
76049
76799
  } else {
76050
76800
  const pathArg = args.path || ".";
76051
- const resolved = realpathSync2(resolve4(pathArg));
76801
+ const resolved = realpathSync2(resolve5(pathArg));
76052
76802
  const matches = await api2.listAgentSettings({ workspacePath: resolved });
76053
76803
  if (matches.length > 0) {
76054
76804
  preMatchedAgent = matches[0];
@@ -76121,7 +76871,7 @@ Resumed: ${CYAN2}${getFrontendUrl(apiUrl, todoId)}${RESET2}
76121
76871
  if (args.model)
76122
76872
  agent2 = { ...agent2, model: args.model };
76123
76873
  if (args["raw-sysmsg"]) {
76124
- const sysmsg = readFileSync3(resolve4(args["raw-sysmsg"]), "utf-8");
76874
+ const sysmsg = readFileSync5(resolve5(args["raw-sysmsg"]), "utf-8");
76125
76875
  agent2 = { ...agent2, systemMessage: sysmsg, systemMessageMode: "raw" };
76126
76876
  }
76127
76877
  if (args["allow-all"]) {