@todoforai/cli 0.1.15 → 0.1.17

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 (3) hide show
  1. package/README.md +9 -6
  2. package/dist/todoai.js +165 -106
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -6,11 +6,13 @@ CLI for [TODOforAI](https://todofor.ai) — create, watch, and inspect AI-powere
6
6
 
7
7
  ```bash
8
8
  bun install -g @todoforai/cli
9
+ # Install the native bridge once, if it is not already on PATH:
10
+ curl -fsSL https://raw.githubusercontent.com/todoforai/bridge/main/install.sh | sh
9
11
  ```
10
12
 
11
13
  ## Setup
12
14
 
13
- Just run `todoforai-cli` — on first use it opens a browser for **device login** and saves the API key to `~/.todoforai/credentials.json` (shared with the edge daemon).
15
+ Just run `todoforai-cli` — on first use it opens a browser for **device login** and saves the CLI API key in the shared TODOforAI credentials file. The bridge uses the same file for its own device credentials.
14
16
 
15
17
  ```bash
16
18
  todoforai-cli # prompts device login if no key found
@@ -19,15 +21,15 @@ todoforai-cli login # explicit login
19
21
 
20
22
  API URL resolution: `--api-url` flag → `TODOFORAI_API_URL` env → `https://api.todofor.ai`.
21
23
 
22
- Auth resolution: `--api-key` flag → `TODOFORAI_API_KEY` env → shared credentials (`~/.todoforai/credentials.json`) → device login.
24
+ Auth resolution: `--api-key` flag → `TODOFORAI_API_KEY` env → shared credentials file → device login.
23
25
 
24
26
  Project, agent, and last-todo state are stored **per API URL** under `per_api_url[<url>]` in the config — switching between e.g. `https://api.todofor.ai` and `http://localhost:4000` keeps each environment's defaults isolated. Legacy top-level fields are auto-migrated on first run.
25
27
 
26
- ## Edge daemon
28
+ ## Bridge
27
29
 
28
- The CLI talks to the backend over WebSocket; **shell execution, file I/O, and tool calls happen in the edge daemon** running locally. On every run `todoforai-cli` spawns a detached edge process if none is running (PID-locked at `~/.todoforai/edge-<hash>.lock`, logs at `~/.todoforai/edge.log`). It keeps running after the CLI exits, so long-running tasks survive `Ctrl+D`.
30
+ The CLI talks to the backend over WebSocket; **shell execution, file I/O, and tool calls happen in the bridge** running locally. On create/resume/template runs, `todoforai-cli` starts a detached `todoforai-bridge` process if needed (the bridge enforces its own single-instance lock, logs at `~/.todoforai/bridge.log`). If bridge credentials are missing, the CLI runs `todoforai-bridge login` in the foreground first so you can see and approve the device-login URL. The bridge keeps running after the CLI exits, so long-running tasks survive `Ctrl+D`.
29
31
 
30
- Disable with `--no-edge` if you manage the edge yourself (e.g. systemd, separate terminal).
32
+ Disable with `--no-bridge` if you manage the bridge yourself (e.g. systemd, separate terminal). `--no-edge` remains supported as a deprecated alias.
31
33
 
32
34
  ## Usage
33
35
 
@@ -82,7 +84,8 @@ todoforai-cli --resume <todo-id> # resume specific todo
82
84
  --dangerously-skip-permissions Auto-approve all blocks (CI/benchmarks)
83
85
  --allow-all Set permissions to allow all tools (no approval needed)
84
86
  --no-watch Create todo and exit
85
- --no-edge Do not auto-spawn edge daemon
87
+ --no-bridge Do not auto-spawn bridge
88
+ --no-edge Deprecated alias for --no-bridge
86
89
  --json Output as JSON
87
90
  --safe Validate API key upfront
88
91
  --debug, -d Debug output
package/dist/todoai.js CHANGED
@@ -41805,15 +41805,15 @@ var require_route = __commonJS((exports, module) => {
41805
41805
  };
41806
41806
  }
41807
41807
  function wrapConversion(toModel, graph) {
41808
- const path3 = [graph[toModel].parent, toModel];
41808
+ const path4 = [graph[toModel].parent, toModel];
41809
41809
  let fn = conversions[graph[toModel].parent][toModel];
41810
41810
  let cur = graph[toModel].parent;
41811
41811
  while (graph[cur].parent) {
41812
- path3.unshift(graph[cur].parent);
41812
+ path4.unshift(graph[cur].parent);
41813
41813
  fn = link(conversions[graph[cur].parent][cur], fn);
41814
41814
  cur = graph[cur].parent;
41815
41815
  }
41816
- fn.conversion = path3;
41816
+ fn.conversion = path4;
41817
41817
  return fn;
41818
41818
  }
41819
41819
  module.exports = function(fromModel) {
@@ -42039,7 +42039,7 @@ var require_has_flag = __commonJS((exports, module) => {
42039
42039
 
42040
42040
  // node_modules/supports-color/index.js
42041
42041
  var require_supports_color = __commonJS((exports, module) => {
42042
- var os3 = __require("os");
42042
+ var os4 = __require("os");
42043
42043
  var tty = __require("tty");
42044
42044
  var hasFlag = require_has_flag();
42045
42045
  var { env } = process;
@@ -42087,7 +42087,7 @@ var require_supports_color = __commonJS((exports, module) => {
42087
42087
  return min;
42088
42088
  }
42089
42089
  if (process.platform === "win32") {
42090
- const osRelease = os3.release().split(".");
42090
+ const osRelease = os4.release().split(".");
42091
42091
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
42092
42092
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
42093
42093
  }
@@ -42866,6 +42866,12 @@ class ApiClient {
42866
42866
  listEdges() {
42867
42867
  return this.request("GET", "/api/v1/edges");
42868
42868
  }
42869
+ setAgentDeviceConfig(agentId, agentSettingsId, deviceId, config) {
42870
+ return this.request("PUT", `/api/v1/agents/${agentId}/device-config`, { agentSettingsId, deviceId, config });
42871
+ }
42872
+ listDevices() {
42873
+ return this.request("GET", "/api/v1/devices");
42874
+ }
42869
42875
  startFromTemplate(projectId, templateId, opts) {
42870
42876
  return this.request("POST", `/api/v1/projects/${projectId}/todos/from-template`, {
42871
42877
  templateId,
@@ -43327,50 +43333,6 @@ var EDGE_TOOL_TYPES = new Set([
43327
43333
  "grep" /* Grep */,
43328
43334
  "list" /* List */
43329
43335
  ]);
43330
- var BROWSER_TOOL_TYPES = new Set([
43331
- "browser_interactable" /* BrowserInteractable */,
43332
- "browser_dom_tree" /* BrowserDomTree */,
43333
- "browser_navigate" /* BrowserNavigate */,
43334
- "browser_screenshot" /* BrowserScreenshot */,
43335
- "browser_click" /* BrowserClick */,
43336
- "browser_type" /* BrowserType */,
43337
- "browser_fill" /* BrowserFill */,
43338
- "browser_scroll" /* BrowserScroll */,
43339
- "browser_mouse_move" /* BrowserMouseMove */,
43340
- "browser_key" /* BrowserKey */,
43341
- "browser_evaluate" /* BrowserEvaluate */,
43342
- "browser_select" /* BrowserSelect */,
43343
- "browser_hover" /* BrowserHover */,
43344
- "browser_text_content" /* BrowserTextContent */,
43345
- "browser_back" /* BrowserBack */,
43346
- "browser_forward" /* BrowserForward */,
43347
- "browser_reload" /* BrowserReload */,
43348
- "browser_upload_file" /* BrowserUploadFile */,
43349
- "browser_find_text" /* BrowserFindText */,
43350
- "browser_find_role" /* BrowserFindRole */,
43351
- "browser_find_label" /* BrowserFindLabel */,
43352
- "browser_find_placeholder" /* BrowserFindPlaceholder */,
43353
- "browser_wait" /* BrowserWait */,
43354
- "browser_drag" /* BrowserDrag */,
43355
- "browser_dialog" /* BrowserDialog */,
43356
- "browser_network_wait" /* BrowserNetworkWait */,
43357
- "browser_check" /* BrowserCheck */,
43358
- "browser_uncheck" /* BrowserUncheck */,
43359
- "browser_focus" /* BrowserFocus */,
43360
- "browser_find_test_id" /* BrowserFindTestId */,
43361
- "browser_cookies" /* BrowserCookies */,
43362
- "browser_storage" /* BrowserStorage */,
43363
- "browser_pdf" /* BrowserPdf */,
43364
- "browser_clipboard_read" /* BrowserClipboardRead */,
43365
- "browser_clipboard_write" /* BrowserClipboardWrite */,
43366
- "browser_snapshot" /* BrowserSnapshot */,
43367
- "browser_iframe" /* BrowserIframe */,
43368
- "browser_console" /* BrowserConsole */,
43369
- "browser_scroll_into_view" /* BrowserScrollIntoView */,
43370
- "browser_network_requests" /* BrowserNetworkRequests */,
43371
- "browser_tap" /* BrowserTap */,
43372
- "browser_swipe" /* BrowserSwipe */
43373
- ]);
43374
43336
  var API_TOOL_TYPES = new Set([
43375
43337
  "api_get_current_context" /* ApiGetCurrentContext */,
43376
43338
  "api_get_todo" /* ApiGetTodo */,
@@ -43461,6 +43423,8 @@ var SERVER_TO_FRONTENDS = {
43461
43423
  frontend_file_chunk_result: (todoId) => `${"frontend:file_chunk_result" /* FRONTEND_FILE_CHUNK_RESULT */}:${todoId}`,
43462
43424
  status: (todoId) => `todo:${todoId}:status`,
43463
43425
  block_update: (todoId) => `todo:${todoId}:block_update`,
43426
+ context_summary_updated: (todoId) => `${"context:summary_updated" /* CONTEXT_SUMMARY_UPDATED */}:${todoId}`,
43427
+ context_info_updated: (todoId) => `${"context:info_updated" /* CONTEXT_INFO_UPDATED */}:${todoId}`,
43464
43428
  error_result: (todoId) => `${"block:error_result" /* BLOCK_ERROR_RESULT */}:${todoId}`,
43465
43429
  meta_result: (todoId) => `${"block:meta_result" /* BLOCK_META_RESULT */}:${todoId}`,
43466
43430
  file_changed: (edgeId, path3) => `${"block:file_changed" /* BLOCK_FILE_CHANGED */}:${edgeId}:${path3}`,
@@ -43863,6 +43827,14 @@ var TOPICS = {
43863
43827
  channel: (p) => SERVER_TO_FRONTENDS.resource.contentUpdated(p.userId),
43864
43828
  audience: "frontend"
43865
43829
  },
43830
+ ["context:summary_updated" /* CONTEXT_SUMMARY_UPDATED */]: {
43831
+ channel: (p) => SERVER_TO_FRONTENDS.todo.context_summary_updated(p.todoId),
43832
+ audience: "frontend"
43833
+ },
43834
+ ["context:info_updated" /* CONTEXT_INFO_UPDATED */]: {
43835
+ channel: (p) => SERVER_TO_FRONTENDS.todo.context_info_updated(p.todoId),
43836
+ audience: "frontend"
43837
+ },
43866
43838
  ["hexgrid:updated" /* HEXGRID_UPDATED */]: {
43867
43839
  channel: (p) => SERVER_TO_FRONTENDS.hexGrid.updated(p.projectId),
43868
43840
  audience: "frontend"
@@ -44008,7 +43980,8 @@ Options:
44008
43980
  --allow-all Set permissions to allow all tools (no approval needed)
44009
43981
  --raw-sysmsg <file> Use file contents verbatim as system prompt (new TODO only)
44010
43982
  --no-watch Create todo and exit
44011
- --no-edge Do not auto-spawn edge daemon
43983
+ --no-bridge Do not auto-spawn bridge
43984
+ --no-edge Deprecated alias for --no-bridge
44012
43985
  --json Output as JSON
44013
43986
  --detailed 'inspect --json': keep ids, timestamps, agentSettingsId, scheduledTimestamp
44014
43987
  --format-anthropic 'inspect --json': Anthropic-style shape (tool_result in next user msg); attachment sources are uri-typed, so not a 1:1 messages.create input
@@ -44062,6 +44035,7 @@ function parseCliArgs() {
44062
44035
  "allow-all": { type: "boolean", default: false },
44063
44036
  "raw-sysmsg": { type: "string" },
44064
44037
  "no-watch": { type: "boolean", default: false },
44038
+ "no-bridge": { type: "boolean", default: false },
44065
44039
  "no-edge": { type: "boolean", default: false },
44066
44040
  json: { type: "boolean", default: false },
44067
44041
  detailed: { type: "boolean", default: false },
@@ -44077,6 +44051,8 @@ function parseCliArgs() {
44077
44051
  allowPositionals: true,
44078
44052
  strict: false
44079
44053
  });
44054
+ if (values["no-edge"])
44055
+ values["no-bridge"] = true;
44080
44056
  return { values, positionals };
44081
44057
  }
44082
44058
 
@@ -44423,12 +44399,134 @@ Cancelled
44423
44399
 
44424
44400
  // src/agent.ts
44425
44401
  import { resolve, basename } from "path";
44402
+
44403
+ // src/ensure-bridge.ts
44404
+ import { spawn, spawnSync } from "child_process";
44405
+ import fs2 from "fs";
44406
+ import path3 from "path";
44407
+ import os3 from "os";
44408
+ function hasBridge() {
44409
+ const probe = spawnSync("todoforai-bridge", ["--version"], { stdio: "ignore" });
44410
+ return probe.status === 0;
44411
+ }
44412
+ function isLocalHost(hostname) {
44413
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
44414
+ }
44415
+ function parseApiUrl(apiUrl) {
44416
+ try {
44417
+ return new URL(apiUrl);
44418
+ } catch {
44419
+ return null;
44420
+ }
44421
+ }
44422
+ function bridgeProfile(apiUrl) {
44423
+ const url = parseApiUrl(apiUrl);
44424
+ if (!url)
44425
+ return null;
44426
+ if (isLocalHost(url.hostname))
44427
+ return "dev";
44428
+ if (!url.hostname || url.hostname === "api.todofor.ai")
44429
+ return null;
44430
+ return `api_${url.hostname.replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "")}`;
44431
+ }
44432
+ function withProfile(args, apiUrl) {
44433
+ const profile = bridgeProfile(apiUrl);
44434
+ return profile ? [...args, "--profile", profile] : args;
44435
+ }
44436
+ function bridgeRunArgs(apiUrl) {
44437
+ const url = parseApiUrl(apiUrl);
44438
+ if (!url)
44439
+ return [];
44440
+ if (isLocalHost(url.hostname)) {
44441
+ const args = ["--host", url.hostname];
44442
+ if (url.port)
44443
+ args.push("--port", url.port);
44444
+ return withProfile(args, apiUrl);
44445
+ }
44446
+ if (url.hostname && url.hostname !== "api.todofor.ai")
44447
+ return withProfile(["--host", url.hostname], apiUrl);
44448
+ return [];
44449
+ }
44450
+ function bridgeLoginArgs(apiUrl) {
44451
+ const url = parseApiUrl(apiUrl);
44452
+ if (!url)
44453
+ return ["login"];
44454
+ if (url.hostname && url.hostname !== "api.todofor.ai")
44455
+ return withProfile(["login", "--host", url.hostname], apiUrl);
44456
+ return ["login"];
44457
+ }
44458
+ function bridgeWhoamiArgs(apiUrl) {
44459
+ return withProfile(["whoami"], apiUrl);
44460
+ }
44461
+ function bridgeDeviceId(apiUrl) {
44462
+ const r = spawnSync("todoforai-bridge", bridgeWhoamiArgs(apiUrl), { encoding: "utf-8" });
44463
+ if (r.status !== 0)
44464
+ return null;
44465
+ 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);
44466
+ return m ? m[1] : null;
44467
+ }
44468
+ function ensureBridgeCredentials(apiUrl) {
44469
+ const whoami = spawnSync("todoforai-bridge", bridgeWhoamiArgs(apiUrl), { stdio: "ignore" });
44470
+ if (whoami.status === 0)
44471
+ return true;
44472
+ console.error("\x1B[2mBridge credentials not found. Starting `todoforai-bridge login`...\x1B[0m");
44473
+ const login = spawnSync("todoforai-bridge", bridgeLoginArgs(apiUrl), { stdio: "inherit" });
44474
+ return login.status === 0;
44475
+ }
44476
+ function ensureBridgeRunning(apiUrl, _apiKey) {
44477
+ if (!hasBridge()) {
44478
+ console.error("\x1B[2mBridge not started: `todoforai-bridge` was not found on PATH. Install TODOforAI Bridge, or pass --no-bridge (or deprecated --no-edge) to silence this.\x1B[0m");
44479
+ return;
44480
+ }
44481
+ if (!ensureBridgeCredentials(apiUrl)) {
44482
+ console.error("\x1B[33mBridge not started: `todoforai-bridge login` did not complete successfully.\x1B[0m");
44483
+ return;
44484
+ }
44485
+ const logDir = path3.join(os3.homedir(), ".todoforai");
44486
+ fs2.mkdirSync(logDir, { recursive: true });
44487
+ const logFile = path3.join(logDir, "bridge.log");
44488
+ const out = fs2.openSync(logFile, "a");
44489
+ const child = spawn("todoforai-bridge", bridgeRunArgs(apiUrl), {
44490
+ detached: true,
44491
+ stdio: ["ignore", out, out]
44492
+ });
44493
+ child.on("error", (err) => {
44494
+ console.error(`\x1B[33mFailed to start bridge: ${err.message}\x1B[0m`);
44495
+ });
44496
+ let exited = false;
44497
+ let exitCode = null;
44498
+ child.on("exit", (code) => {
44499
+ exited = true;
44500
+ exitCode = code;
44501
+ });
44502
+ child.unref();
44503
+ const pid = child.pid;
44504
+ if (!pid)
44505
+ return;
44506
+ const shortLog = logFile.replace(os3.homedir(), "~");
44507
+ setTimeout(() => {
44508
+ if (!exited) {
44509
+ console.error(`\x1B[2mStarted bridge (pid ${pid}), logs: ${shortLog}\x1B[0m`);
44510
+ return;
44511
+ }
44512
+ if (exitCode === 0) {
44513
+ console.error(`\x1B[2mBridge exited cleanly. Logs: ${shortLog}\x1B[0m`);
44514
+ } else {
44515
+ console.error(`\x1B[33mBridge exited early (exit ${exitCode}). Check logs: ${shortLog}. Another instance may already be running.\x1B[0m`);
44516
+ }
44517
+ }, 500);
44518
+ }
44519
+
44520
+ // src/agent.ts
44426
44521
  function getAgentWorkspacePaths(agent) {
44427
44522
  const paths = [];
44428
44523
  for (const ec of Object.values(agent.edgesMcpConfigs || {})) {
44429
44524
  const tc = ec?.todoai_edge || ec?.todoai || {};
44430
44525
  paths.push(...tc.workspacePaths || []);
44431
44526
  }
44527
+ for (const dc of Object.values(agent.devicesConfig || {})) {
44528
+ paths.push(...dc?.workspacePaths || []);
44529
+ }
44432
44530
  return paths;
44433
44531
  }
44434
44532
  async function autoCreateAgent(api, resolvedPath) {
@@ -44439,10 +44537,20 @@ async function autoCreateAgent(api, resolvedPath) {
44439
44537
  throw new Error(`Failed to create agent: ${JSON.stringify(resp)}`);
44440
44538
  const agentSettingsId = resp.agentSettingsId || agentId;
44441
44539
  await api.updateAgentSettings(agentId, agentSettingsId, { name: folderName });
44540
+ const deviceId = bridgeDeviceId(api.apiUrl);
44541
+ if (deviceId) {
44542
+ await api.setAgentDeviceConfig(agentId, agentSettingsId, deviceId, { workspacePaths: [resolvedPath] });
44543
+ const matches2 = await api.listAgentSettings({ workspacePath: resolvedPath });
44544
+ if (matches2.length)
44545
+ return matches2[0];
44546
+ resp.name = folderName;
44547
+ resp.devicesConfig = { [deviceId]: { workspacePaths: [resolvedPath] } };
44548
+ return resp;
44549
+ }
44442
44550
  const edges = await api.listEdges();
44443
44551
  const edgeId = Array.isArray(edges) && edges.length ? edges[0].id : null;
44444
44552
  if (!edgeId)
44445
- throw new Error("No edge available to configure workspace path");
44553
+ throw new Error("No bridge device or edge available to configure workspace path");
44446
44554
  await api.setAgentEdgeMcpConfig(agentId, agentSettingsId, edgeId, "todoai_edge", { workspacePaths: [resolvedPath] });
44447
44555
  const matches = await api.listAgentSettings({ workspacePath: resolvedPath });
44448
44556
  if (matches.length)
@@ -46118,55 +46226,6 @@ async function listTodosCommand(api, defaultProjectId, argv) {
46118
46226
  `);
46119
46227
  }
46120
46228
 
46121
- // src/ensure-edge.ts
46122
- import { spawn, spawnSync } from "child_process";
46123
- import fs2 from "fs";
46124
- import path3 from "path";
46125
- import os3 from "os";
46126
- function hasBunx() {
46127
- const probe = spawnSync(process.platform === "win32" ? "where" : "which", ["bunx"], { stdio: "ignore" });
46128
- return probe.status === 0;
46129
- }
46130
- function ensureEdgeRunning(apiUrl, apiKey) {
46131
- if (!hasBunx()) {
46132
- console.error("\x1B[2mEdge daemon not started: `bunx` is missing. Install Bun from https://bun.sh to enable it, or pass --no-edge to silence this.\x1B[0m");
46133
- return;
46134
- }
46135
- const logDir = path3.join(os3.homedir(), ".todoforai");
46136
- fs2.mkdirSync(logDir, { recursive: true });
46137
- const logFile = path3.join(logDir, "edge.log");
46138
- const out = fs2.openSync(logFile, "a");
46139
- const child = spawn("bunx", ["@todoforai/edge", "--api-url", apiUrl, "--api-key", apiKey], {
46140
- detached: true,
46141
- stdio: ["ignore", out, out]
46142
- });
46143
- child.on("error", (err) => {
46144
- console.error(`\x1B[33mFailed to start edge daemon: ${err.message}\x1B[0m`);
46145
- });
46146
- let exited = false;
46147
- let exitCode = null;
46148
- child.on("exit", (code) => {
46149
- exited = true;
46150
- exitCode = code;
46151
- });
46152
- child.unref();
46153
- const pid = child.pid;
46154
- if (!pid)
46155
- return;
46156
- const shortLog = logFile.replace(os3.homedir(), "~");
46157
- setTimeout(() => {
46158
- if (!exited) {
46159
- console.error(`\x1B[2mStarted edge daemon (pid ${pid}), logs: ${shortLog}\x1B[0m`);
46160
- return;
46161
- }
46162
- if (exitCode === 0) {
46163
- console.error(`\x1B[2mEdge daemon exited cleanly (another instance likely already running). Logs: ${shortLog}\x1B[0m`);
46164
- } else {
46165
- console.error(`\x1B[31mEdge daemon died (exit ${exitCode}). Check logs: ${shortLog}\x1B[0m`);
46166
- }
46167
- }, 500);
46168
- }
46169
-
46170
46229
  // src/index.ts
46171
46230
  try {
46172
46231
  const pkgPath = path4.resolve(fileURLToPath(import.meta.url), "../../package.json");
@@ -46448,8 +46507,8 @@ Cancelled by user (Ctrl+C)
46448
46507
  if (process.stderr.isTTY)
46449
46508
  printLogo();
46450
46509
  if (args.template) {
46451
- if (!args["no-edge"] && !args["no-watch"])
46452
- ensureEdgeRunning(apiUrl, apiKey);
46510
+ if (!args["no-bridge"] && !args["no-watch"])
46511
+ ensureBridgeRunning(apiUrl, apiKey);
46453
46512
  const templateId = args.template;
46454
46513
  const inputValues = {};
46455
46514
  for (const kv of args.input || []) {
@@ -46536,8 +46595,8 @@ ${"\u2500".repeat(40)}
46536
46595
  `);
46537
46596
  }
46538
46597
  if (args.resume || args.continue) {
46539
- if (!args["no-edge"])
46540
- ensureEdgeRunning(apiUrl, apiKey);
46598
+ if (!args["no-bridge"])
46599
+ ensureBridgeRunning(apiUrl, apiKey);
46541
46600
  const todoId = args.resume || cfgScope.data.last_todo_id;
46542
46601
  if (!todoId) {
46543
46602
  process.stderr.write(`Error: No recent todo found
@@ -46622,8 +46681,8 @@ Resumed: ${CYAN}${getFrontendUrl(apiUrl, projectId2, todoId)}${RESET}
46622
46681
  }
46623
46682
  process.stderr.write(`${DIM}Tip: ${randomTip()}${RESET}
46624
46683
  `);
46625
- if (!args["no-edge"] && !args["no-watch"])
46626
- ensureEdgeRunning(apiUrl, apiKey);
46684
+ if (!args["no-bridge"] && !args["no-watch"])
46685
+ ensureBridgeRunning(apiUrl, apiKey);
46627
46686
  let content;
46628
46687
  if (positionals.length > 0) {
46629
46688
  content = positionals.join(" ");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@todoforai/cli",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "todoforai-cli": "dist/todoai.js",