@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.
- package/dist/todoai.js +154 -160
- 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
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
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");
|