@todoforai/cli 0.1.16 → 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 (2) hide show
  1. package/dist/todoai.js +154 -160
  2. package/package.json +1 -1
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"
@@ -44427,12 +44399,134 @@ Cancelled
44427
44399
 
44428
44400
  // src/agent.ts
44429
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
44430
44521
  function getAgentWorkspacePaths(agent) {
44431
44522
  const paths = [];
44432
44523
  for (const ec of Object.values(agent.edgesMcpConfigs || {})) {
44433
44524
  const tc = ec?.todoai_edge || ec?.todoai || {};
44434
44525
  paths.push(...tc.workspacePaths || []);
44435
44526
  }
44527
+ for (const dc of Object.values(agent.devicesConfig || {})) {
44528
+ paths.push(...dc?.workspacePaths || []);
44529
+ }
44436
44530
  return paths;
44437
44531
  }
44438
44532
  async function autoCreateAgent(api, resolvedPath) {
@@ -44443,10 +44537,20 @@ async function autoCreateAgent(api, resolvedPath) {
44443
44537
  throw new Error(`Failed to create agent: ${JSON.stringify(resp)}`);
44444
44538
  const agentSettingsId = resp.agentSettingsId || agentId;
44445
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
+ }
44446
44550
  const edges = await api.listEdges();
44447
44551
  const edgeId = Array.isArray(edges) && edges.length ? edges[0].id : null;
44448
44552
  if (!edgeId)
44449
- throw new Error("No edge available to configure workspace path");
44553
+ throw new Error("No bridge device or edge available to configure workspace path");
44450
44554
  await api.setAgentEdgeMcpConfig(agentId, agentSettingsId, edgeId, "todoai_edge", { workspacePaths: [resolvedPath] });
44451
44555
  const matches = await api.listAgentSettings({ workspacePath: resolvedPath });
44452
44556
  if (matches.length)
@@ -46122,116 +46226,6 @@ async function listTodosCommand(api, defaultProjectId, argv) {
46122
46226
  `);
46123
46227
  }
46124
46228
 
46125
- // src/ensure-bridge.ts
46126
- import { spawn, spawnSync } from "child_process";
46127
- import fs2 from "fs";
46128
- import path3 from "path";
46129
- import os3 from "os";
46130
- function hasBridge() {
46131
- const probe = spawnSync("todoforai-bridge", ["--version"], { stdio: "ignore" });
46132
- return probe.status === 0;
46133
- }
46134
- function isLocalHost(hostname) {
46135
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
46136
- }
46137
- function parseApiUrl(apiUrl) {
46138
- try {
46139
- return new URL(apiUrl);
46140
- } catch {
46141
- return null;
46142
- }
46143
- }
46144
- function bridgeProfile(apiUrl) {
46145
- const url = parseApiUrl(apiUrl);
46146
- if (!url)
46147
- return null;
46148
- if (isLocalHost(url.hostname))
46149
- return "dev";
46150
- if (!url.hostname || url.hostname === "api.todofor.ai")
46151
- return null;
46152
- return `api_${url.hostname.replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "")}`;
46153
- }
46154
- function withProfile(args, apiUrl) {
46155
- const profile = bridgeProfile(apiUrl);
46156
- return profile ? [...args, "--profile", profile] : args;
46157
- }
46158
- function bridgeRunArgs(apiUrl) {
46159
- const url = parseApiUrl(apiUrl);
46160
- if (!url)
46161
- return [];
46162
- if (isLocalHost(url.hostname)) {
46163
- const args = ["--host", url.hostname];
46164
- if (url.port)
46165
- args.push("--port", url.port);
46166
- return withProfile(args, apiUrl);
46167
- }
46168
- if (url.hostname && url.hostname !== "api.todofor.ai")
46169
- return withProfile(["--host", url.hostname], apiUrl);
46170
- return [];
46171
- }
46172
- function bridgeLoginArgs(apiUrl) {
46173
- const url = parseApiUrl(apiUrl);
46174
- if (!url)
46175
- return ["login"];
46176
- if (url.hostname && url.hostname !== "api.todofor.ai")
46177
- return withProfile(["login", "--host", url.hostname], apiUrl);
46178
- return ["login"];
46179
- }
46180
- function bridgeWhoamiArgs(apiUrl) {
46181
- return withProfile(["whoami"], apiUrl);
46182
- }
46183
- function ensureBridgeCredentials(apiUrl) {
46184
- const whoami = spawnSync("todoforai-bridge", bridgeWhoamiArgs(apiUrl), { stdio: "ignore" });
46185
- if (whoami.status === 0)
46186
- return true;
46187
- console.error("\x1B[2mBridge credentials not found. Starting `todoforai-bridge login`...\x1B[0m");
46188
- const login = spawnSync("todoforai-bridge", bridgeLoginArgs(apiUrl), { stdio: "inherit" });
46189
- return login.status === 0;
46190
- }
46191
- function ensureBridgeRunning(apiUrl, _apiKey) {
46192
- if (!hasBridge()) {
46193
- 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");
46194
- return;
46195
- }
46196
- if (!ensureBridgeCredentials(apiUrl)) {
46197
- console.error("\x1B[33mBridge not started: `todoforai-bridge login` did not complete successfully.\x1B[0m");
46198
- return;
46199
- }
46200
- const logDir = path3.join(os3.homedir(), ".todoforai");
46201
- fs2.mkdirSync(logDir, { recursive: true });
46202
- const logFile = path3.join(logDir, "bridge.log");
46203
- const out = fs2.openSync(logFile, "a");
46204
- const child = spawn("todoforai-bridge", bridgeRunArgs(apiUrl), {
46205
- detached: true,
46206
- stdio: ["ignore", out, out]
46207
- });
46208
- child.on("error", (err) => {
46209
- console.error(`\x1B[33mFailed to start bridge: ${err.message}\x1B[0m`);
46210
- });
46211
- let exited = false;
46212
- let exitCode = null;
46213
- child.on("exit", (code) => {
46214
- exited = true;
46215
- exitCode = code;
46216
- });
46217
- child.unref();
46218
- const pid = child.pid;
46219
- if (!pid)
46220
- return;
46221
- const shortLog = logFile.replace(os3.homedir(), "~");
46222
- setTimeout(() => {
46223
- if (!exited) {
46224
- console.error(`\x1B[2mStarted bridge (pid ${pid}), logs: ${shortLog}\x1B[0m`);
46225
- return;
46226
- }
46227
- if (exitCode === 0) {
46228
- console.error(`\x1B[2mBridge exited cleanly. Logs: ${shortLog}\x1B[0m`);
46229
- } else {
46230
- console.error(`\x1B[33mBridge exited early (exit ${exitCode}). Check logs: ${shortLog}. Another instance may already be running.\x1B[0m`);
46231
- }
46232
- }, 500);
46233
- }
46234
-
46235
46229
  // src/index.ts
46236
46230
  try {
46237
46231
  const pkgPath = path4.resolve(fileURLToPath(import.meta.url), "../../package.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@todoforai/cli",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "todoforai-cli": "dist/todoai.js",