@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.
- package/README.md +28 -32
- package/dist/todoforai-cli.js +899 -149
- package/package.json +8 -2
package/dist/todoforai-cli.js
CHANGED
|
@@ -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
|
|
42679
|
-
import { resolve as
|
|
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
|
|
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
|
-
|
|
42688
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
42689
|
+
function installer() {
|
|
42690
|
+
let real;
|
|
42689
42691
|
try {
|
|
42690
|
-
|
|
42692
|
+
real = fs.realpathSync(process.argv[1] || "");
|
|
42691
42693
|
} catch {
|
|
42692
|
-
return
|
|
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 ||
|
|
42736
|
+
if (!process.stderr.isTTY || process.env.CI || process.env.NO_UPDATE_NOTIFIER || !installer())
|
|
42709
42737
|
return;
|
|
42710
|
-
|
|
42711
|
-
|
|
42712
|
-
|
|
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
|
-
|
|
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
|
-
|
|
42725
|
-
|
|
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
|
-
|
|
42728
|
-
|
|
42729
|
-
|
|
42730
|
-
|
|
42731
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
44711
|
-
description: "MCP servers as CLI: `mcporter list
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
|
|
50006
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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((
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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: () =>
|
|
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: () =>
|
|
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
|
|
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
|
|
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 (!
|
|
55709
|
+
if (!collect2(iss, "l"))
|
|
55093
55710
|
result.issues.push(iss);
|
|
55094
55711
|
}
|
|
55095
55712
|
for (const iss of right.issues) {
|
|
55096
|
-
if (!
|
|
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,
|
|
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,
|
|
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,
|
|
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 ?? (
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
72699
|
-
|
|
72700
|
-
|
|
72701
|
-
|
|
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
|
|
72705
|
-
|
|
72706
|
-
|
|
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((
|
|
73907
|
+
const response = new Promise((resolve5, reject) => {
|
|
73180
73908
|
const pendingResponse = {
|
|
73181
73909
|
resolve: (value) => {
|
|
73182
73910
|
try {
|
|
73183
|
-
|
|
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((
|
|
73235
|
-
this.abortController.signal.addEventListener("abort", () =>
|
|
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((
|
|
74124
|
-
this.waiters.push({ resolve:
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) =>
|
|
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
|
-
|
|
75823
|
+
log3(`approval for ${id} not delivered (socket down)`);
|
|
75092
75824
|
} catch (e) {
|
|
75093
|
-
|
|
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((
|
|
75170
|
-
process.stdin.once("end",
|
|
75171
|
-
process.stdin.once("close",
|
|
75172
|
-
process.stdin.once("error",
|
|
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) =>
|
|
75910
|
+
agent2.connect().catch((e) => log3("connect failed:", e?.message));
|
|
75179
75911
|
else
|
|
75180
|
-
|
|
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
|
-
|
|
75275
|
-
|
|
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 =
|
|
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 (
|
|
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 =
|
|
75682
|
-
if (!
|
|
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([
|
|
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(
|
|
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(
|
|
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 =
|
|
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"]) {
|