@todoforai/edge 0.13.21 → 0.13.23
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/index.js +184 -33
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -48153,6 +48153,27 @@ class ApiClient {
|
|
|
48153
48153
|
throw new Error(`API ${method} ${endpoint} failed: ${res.status} ${await res.text()}`);
|
|
48154
48154
|
return res.json();
|
|
48155
48155
|
}
|
|
48156
|
+
async trpcQuery(path2, input) {
|
|
48157
|
+
const base = this.apiUrl.replace(/\/api\/v1\/?$/, "").replace(/\/$/, "");
|
|
48158
|
+
const params = new URLSearchParams({
|
|
48159
|
+
batch: "1",
|
|
48160
|
+
input: JSON.stringify({ 0: input })
|
|
48161
|
+
});
|
|
48162
|
+
const res = await fetch(`${base}/trpc/api/${path2}?${params}`, {
|
|
48163
|
+
method: "GET",
|
|
48164
|
+
headers: this.headers,
|
|
48165
|
+
signal: AbortSignal.timeout(30000)
|
|
48166
|
+
});
|
|
48167
|
+
const text = await res.text();
|
|
48168
|
+
if (!res.ok)
|
|
48169
|
+
throw new Error(`API tRPC ${path2} failed: ${res.status} ${text}`);
|
|
48170
|
+
const payload = JSON.parse(text);
|
|
48171
|
+
const item = Array.isArray(payload) ? payload[0] : payload;
|
|
48172
|
+
if (item?.error)
|
|
48173
|
+
throw new Error(`API tRPC ${path2} failed: ${item.error.message || JSON.stringify(item.error)}`);
|
|
48174
|
+
const data = item?.result?.data;
|
|
48175
|
+
return data?.json !== undefined ? data.json : data;
|
|
48176
|
+
}
|
|
48156
48177
|
async validateApiKey() {
|
|
48157
48178
|
if (!this.apiKey)
|
|
48158
48179
|
return { valid: false, error: "No API key provided" };
|
|
@@ -48191,9 +48212,10 @@ class ApiClient {
|
|
|
48191
48212
|
createTodo(projectId, content, agentSettings) {
|
|
48192
48213
|
return this.request("POST", `/api/v1/projects/${projectId}/todos`, { content, agentSettings });
|
|
48193
48214
|
}
|
|
48194
|
-
listTodos(projectId) {
|
|
48195
|
-
|
|
48196
|
-
|
|
48215
|
+
listTodos(projectId, opts) {
|
|
48216
|
+
if (!projectId)
|
|
48217
|
+
return this.request("GET", "/api/v1/todos");
|
|
48218
|
+
return this.trpcQuery("todo.list", { projectId, ...opts });
|
|
48197
48219
|
}
|
|
48198
48220
|
getTodo(todoId) {
|
|
48199
48221
|
return this.request("GET", `/api/v1/todos/${todoId}`);
|
|
@@ -48245,6 +48267,12 @@ class ApiClient {
|
|
|
48245
48267
|
listEdges() {
|
|
48246
48268
|
return this.request("GET", "/api/v1/edges");
|
|
48247
48269
|
}
|
|
48270
|
+
setAgentDeviceConfig(agentId, agentSettingsId, deviceId, config) {
|
|
48271
|
+
return this.request("PUT", `/api/v1/agents/${agentId}/device-config`, { agentSettingsId, deviceId, config });
|
|
48272
|
+
}
|
|
48273
|
+
listDevices() {
|
|
48274
|
+
return this.request("GET", "/api/v1/devices");
|
|
48275
|
+
}
|
|
48248
48276
|
startFromTemplate(projectId, templateId, opts) {
|
|
48249
48277
|
return this.request("POST", `/api/v1/projects/${projectId}/todos/from-template`, {
|
|
48250
48278
|
templateId,
|
|
@@ -48767,12 +48795,13 @@ var tool_catalog_default = {
|
|
|
48767
48795
|
installer: "npm",
|
|
48768
48796
|
label: "Gmail",
|
|
48769
48797
|
statusCmd: "zele whoami",
|
|
48770
|
-
loginCmd: "zele login",
|
|
48798
|
+
loginCmd: "zele login --method google",
|
|
48771
48799
|
credentialPaths: [
|
|
48772
48800
|
"~/.zele/sqlite.db"
|
|
48773
48801
|
],
|
|
48774
48802
|
capabilities: "Read inbox, search/send/reply email, email addresses — multi-account Gmail, OAuth browser login for setup.",
|
|
48775
|
-
versionCmd: "zele --version 2>/dev/null | head -1"
|
|
48803
|
+
versionCmd: "zele --version 2>/dev/null | head -1",
|
|
48804
|
+
preinstallCloud: true
|
|
48776
48805
|
},
|
|
48777
48806
|
xurl: {
|
|
48778
48807
|
category: "social",
|
|
@@ -48802,6 +48831,20 @@ var tool_catalog_default = {
|
|
|
48802
48831
|
description: "Authenticated LinkedIn Voyager API CLI. Cookie auth: `linkedin-api auth <li_at> <jsessionid>` (from browser DevTools).",
|
|
48803
48832
|
versionCmd: "linkedin-api --version 2>/dev/null | head -1"
|
|
48804
48833
|
},
|
|
48834
|
+
"figma-api": {
|
|
48835
|
+
category: "development",
|
|
48836
|
+
pkg: "@todoforai/figma-api",
|
|
48837
|
+
installer: "npm",
|
|
48838
|
+
label: "Figma",
|
|
48839
|
+
statusCmd: `figma-api me 2>/dev/null | grep -oP '"email":\\s*"\\K[^"]+' | head -1`,
|
|
48840
|
+
loginCmd: "figma-api auth",
|
|
48841
|
+
credentialPaths: [
|
|
48842
|
+
"~/.config/figma-api/credentials.json"
|
|
48843
|
+
],
|
|
48844
|
+
capabilities: "Read+write Figma REST API: files/nodes JSON, render images (png/svg/pdf), comments & reactions, components/styles/variables, dev resources, webhooks, projects, library analytics — full subcommand-per-endpoint CLI.",
|
|
48845
|
+
description: "Authenticated Figma REST API CLI. Auth: `figma-api auth <token>` (PAT from figma.com/settings). File commands take a file key or Figma URL. Read files/nodes/images/comments/components/styles/variables; write comments/dev-resources/webhooks. Canvas writes (frames/text/shapes) use `figma-api run` via the plugin bridge. Run `figma-api <cmd> --help` for params/scopes.",
|
|
48846
|
+
versionCmd: "figma-api --version 2>/dev/null | head -1"
|
|
48847
|
+
},
|
|
48805
48848
|
"tiktok-uploader": {
|
|
48806
48849
|
category: "social",
|
|
48807
48850
|
pkg: "tiktok-uploader",
|
|
@@ -48812,7 +48855,8 @@ var tool_catalog_default = {
|
|
|
48812
48855
|
"~/.tiktok/cookies.txt"
|
|
48813
48856
|
],
|
|
48814
48857
|
capabilities: "Upload videos, batch uploads, schedule posts, custom covers, hashtags & mentions",
|
|
48815
|
-
versionCmd: "pip show tiktok-uploader 2>/dev/null | grep -oP 'Version: \\K.*'"
|
|
48858
|
+
versionCmd: "pip show tiktok-uploader 2>/dev/null | grep -oP 'Version: \\K.*'",
|
|
48859
|
+
statusCmd: "test -f ~/.tiktok/cookies.txt && echo authenticated"
|
|
48816
48860
|
},
|
|
48817
48861
|
instagrapi: {
|
|
48818
48862
|
category: "social",
|
|
@@ -48820,7 +48864,8 @@ var tool_catalog_default = {
|
|
|
48820
48864
|
installer: "pip",
|
|
48821
48865
|
label: "Instagram",
|
|
48822
48866
|
capabilities: "Upload photos & reels, post stories, send DMs, like & comment, manage followers",
|
|
48823
|
-
versionCmd: "pip show instagrapi 2>/dev/null | grep -oP 'Version: \\K.*'"
|
|
48867
|
+
versionCmd: "pip show instagrapi 2>/dev/null | grep -oP 'Version: \\K.*'",
|
|
48868
|
+
statusCmd: "python3 -c 'import instagrapi' 2>/dev/null && echo installed"
|
|
48824
48869
|
},
|
|
48825
48870
|
mudslide: {
|
|
48826
48871
|
category: "messaging",
|
|
@@ -48835,7 +48880,7 @@ var tool_catalog_default = {
|
|
|
48835
48880
|
capabilities: "Send messages, send images & files, send locations & polls, group management, QR code login",
|
|
48836
48881
|
versionCmd: "mudslide --version 2>/dev/null | head -1"
|
|
48837
48882
|
},
|
|
48838
|
-
slack: {
|
|
48883
|
+
"slack-cli": {
|
|
48839
48884
|
category: "development",
|
|
48840
48885
|
pkg: "slack-cli",
|
|
48841
48886
|
installer: "binary",
|
|
@@ -48887,7 +48932,8 @@ var tool_catalog_default = {
|
|
|
48887
48932
|
"~/.config/telegram-send/telegram-send.conf"
|
|
48888
48933
|
],
|
|
48889
48934
|
capabilities: "Send messages, send files & images, send video & audio, Markdown/HTML formatting, channel & group support",
|
|
48890
|
-
versionCmd: "telegram-send --version 2>/dev/null | head -1"
|
|
48935
|
+
versionCmd: "telegram-send --version 2>/dev/null | head -1",
|
|
48936
|
+
statusCmd: "test -f ~/.config/telegram-send/telegram-send.conf && echo authenticated"
|
|
48891
48937
|
},
|
|
48892
48938
|
"meta-ads": {
|
|
48893
48939
|
category: "marketing",
|
|
@@ -48904,7 +48950,12 @@ var tool_catalog_default = {
|
|
|
48904
48950
|
installer: "npm",
|
|
48905
48951
|
label: "ElevenLabs",
|
|
48906
48952
|
capabilities: "Text-to-speech, voice cloning, multiple languages. Needs ELEVENLABS_API_KEY.",
|
|
48907
|
-
versionCmd: "elevenlabs-api --version 2>/dev/null | head -1"
|
|
48953
|
+
versionCmd: "elevenlabs-api --version 2>/dev/null | head -1",
|
|
48954
|
+
statusCmd: 'test -f ~/.config/todoforai/elevenlabs.json && echo authenticated || test -n "$ELEVENLABS_API_KEY" && echo authenticated',
|
|
48955
|
+
loginCmd: "elevenlabs-api auth <api_key>",
|
|
48956
|
+
credentialPaths: [
|
|
48957
|
+
"~/.config/todoforai/elevenlabs.json"
|
|
48958
|
+
]
|
|
48908
48959
|
},
|
|
48909
48960
|
"codex-imagegen-api": {
|
|
48910
48961
|
category: "media",
|
|
@@ -48912,7 +48963,11 @@ var tool_catalog_default = {
|
|
|
48912
48963
|
installer: "npm",
|
|
48913
48964
|
label: "Image Gen",
|
|
48914
48965
|
capabilities: "AI image generation & editing via TODOFORAI backend (gpt-image)",
|
|
48915
|
-
versionCmd: "codex-imagegen-api --version 2>/dev/null | head -1"
|
|
48966
|
+
versionCmd: "codex-imagegen-api --version 2>/dev/null | head -1",
|
|
48967
|
+
statusCmd: 'test -f ~/.config/todoforai/credentials.json && echo authenticated || test -n "$TODOFORAI_API_KEY" && echo authenticated',
|
|
48968
|
+
credentialPaths: [
|
|
48969
|
+
"~/.config/todoforai/credentials.json"
|
|
48970
|
+
]
|
|
48916
48971
|
},
|
|
48917
48972
|
"suno-api": {
|
|
48918
48973
|
category: "media",
|
|
@@ -48920,7 +48975,8 @@ var tool_catalog_default = {
|
|
|
48920
48975
|
installer: "npm",
|
|
48921
48976
|
label: "Suno",
|
|
48922
48977
|
capabilities: "AI music generation, custom lyrics, multiple genres. Needs SUNO_API_KEY.",
|
|
48923
|
-
versionCmd: "suno-api --version 2>/dev/null | head -1"
|
|
48978
|
+
versionCmd: "suno-api --version 2>/dev/null | head -1",
|
|
48979
|
+
statusCmd: 'test -n "$SUNO_API_KEY" && echo authenticated'
|
|
48924
48980
|
},
|
|
48925
48981
|
ntn: {
|
|
48926
48982
|
category: "utility",
|
|
@@ -48941,7 +48997,12 @@ var tool_catalog_default = {
|
|
|
48941
48997
|
installer: "npm",
|
|
48942
48998
|
label: "Perplexity",
|
|
48943
48999
|
capabilities: "AI-powered web search, chat completions, async chat, embeddings and agent runs",
|
|
48944
|
-
versionCmd: "perplexity-api --version 2>/dev/null | head -1"
|
|
49000
|
+
versionCmd: "perplexity-api --version 2>/dev/null | head -1",
|
|
49001
|
+
statusCmd: 'test -f ~/.config/todoforai/perplexity.json && echo authenticated || test -n "$PERPLEXITY_API_KEY" && echo authenticated',
|
|
49002
|
+
loginCmd: "perplexity-api auth <api_key>",
|
|
49003
|
+
credentialPaths: [
|
|
49004
|
+
"~/.config/todoforai/perplexity.json"
|
|
49005
|
+
]
|
|
48945
49006
|
},
|
|
48946
49007
|
gh: {
|
|
48947
49008
|
category: "development",
|
|
@@ -49094,7 +49155,8 @@ var tool_catalog_default = {
|
|
|
49094
49155
|
"~/.config/shopify/config.json"
|
|
49095
49156
|
],
|
|
49096
49157
|
capabilities: "Theme development, app scaffolding, store management",
|
|
49097
|
-
versionCmd: "shopify version 2>/dev/null | head -1"
|
|
49158
|
+
versionCmd: "shopify version 2>/dev/null | head -1",
|
|
49159
|
+
statusCmd: "test -f ~/.config/shopify/config.json && echo authenticated"
|
|
49098
49160
|
},
|
|
49099
49161
|
"shop-app": {
|
|
49100
49162
|
category: "ecommerce",
|
|
@@ -49111,7 +49173,8 @@ var tool_catalog_default = {
|
|
|
49111
49173
|
installer: "npm",
|
|
49112
49174
|
label: "Datadog",
|
|
49113
49175
|
capabilities: "CI test visibility, sourcemap uploads, deployment tracking. Needs DATADOG_API_KEY.",
|
|
49114
|
-
versionCmd: "datadog-ci version 2>/dev/null | head -1"
|
|
49176
|
+
versionCmd: "datadog-ci version 2>/dev/null | head -1",
|
|
49177
|
+
statusCmd: 'test -n "$DATADOG_API_KEY" && echo authenticated'
|
|
49115
49178
|
},
|
|
49116
49179
|
"sentry-cli": {
|
|
49117
49180
|
category: "monitoring",
|
|
@@ -49132,10 +49195,11 @@ var tool_catalog_default = {
|
|
|
49132
49195
|
pkg: "@todoforai/cli",
|
|
49133
49196
|
installer: "bun",
|
|
49134
49197
|
label: "TODOforAI",
|
|
49198
|
+
binName: "todoforai-cli",
|
|
49135
49199
|
capabilities: "Create/list/inspect/update TODOs, run templates & workflows, platform API access",
|
|
49136
|
-
description: '`
|
|
49200
|
+
description: "Reach the user's OWN TODOforAI tasks — NOT code `// TODO` comments. Use whenever the user asks about their tasks/todos/account on the platform: `todoforai-cli list` (`--status open`) to browse, `todoforai-cli \"prompt\"` to create, `todoforai-cli --inspect <id>[:<msg-id>]` to read a TODO's full chat/data (read-only), `status/addmessage/delete` to manage, `--template` for registry workflows. Never claim you lack access to platform TODOs — they're reachable here.",
|
|
49137
49201
|
installCmd: "bun add -g @todoforai/cli",
|
|
49138
|
-
versionCmd: "
|
|
49202
|
+
versionCmd: "todoforai-cli --version 2>/dev/null | head -1",
|
|
49139
49203
|
internal: true
|
|
49140
49204
|
},
|
|
49141
49205
|
newman: {
|
|
@@ -49232,6 +49296,20 @@ var tool_catalog_default = {
|
|
|
49232
49296
|
},
|
|
49233
49297
|
versionCmd: "rclone version 2>/dev/null | head -1"
|
|
49234
49298
|
},
|
|
49299
|
+
rdt: {
|
|
49300
|
+
category: "social",
|
|
49301
|
+
pkg: "rdt-cli",
|
|
49302
|
+
installer: "pip",
|
|
49303
|
+
label: "Reddit",
|
|
49304
|
+
statusCmd: `rdt status 2>&1 | grep -oP 'username":\\s*"\\K[^"]+' | head -1`,
|
|
49305
|
+
loginCmd: "rdt login",
|
|
49306
|
+
credentialPaths: [
|
|
49307
|
+
"~/.config/rdt-cli/credential.json"
|
|
49308
|
+
],
|
|
49309
|
+
capabilities: "Search & browse subreddits, read posts & comments, post comments, upvote & save, view user profiles & comments, export results — Reddit in your terminal.",
|
|
49310
|
+
description: 'Reddit CLI. Read/research: `rdt search "<query>" -r <sub> --json -c`, `rdt sub <name>`, `rdt read <postId>`, `rdt user-comments <user>`. Write (needs login): `rdt comment <postId> "<text>"`, `rdt upvote`, `rdt save`. `rdt status` for auth. Cookie auth via `rdt login` (extracts browser cookies).',
|
|
49311
|
+
versionCmd: "rdt --version 2>/dev/null | head -1"
|
|
49312
|
+
},
|
|
49235
49313
|
pymupdf: {
|
|
49236
49314
|
category: "utility",
|
|
49237
49315
|
pkg: "pymupdf",
|
|
@@ -49243,7 +49321,7 @@ var tool_catalog_default = {
|
|
|
49243
49321
|
},
|
|
49244
49322
|
"agent-browser": {
|
|
49245
49323
|
category: "development",
|
|
49246
|
-
pkg: "agent-browser",
|
|
49324
|
+
pkg: "agent-browser@0.30.1",
|
|
49247
49325
|
installer: "npm",
|
|
49248
49326
|
preinstallCloud: true,
|
|
49249
49327
|
label: "Browser",
|
|
@@ -49251,6 +49329,41 @@ var tool_catalog_default = {
|
|
|
49251
49329
|
description: "Default browser. On a PC with a display prefer a visible window the user can watch/interact with (needed for CAPTCHA/MFA/login): launch a separate Chrome with `google-chrome --remote-debugging-port=9222 --user-data-dir=$HOME/.config/google-chrome-cdp >/tmp/chrome-cdp.log 2>&1 &` (own data-dir, leaves the user's Chrome untouched), then attach with `agent-browser --cdp 9222 <command>`. Use headless only on the cloud or when no display is available.",
|
|
49252
49330
|
versionCmd: "agent-browser --version 2>/dev/null | head -1"
|
|
49253
49331
|
},
|
|
49332
|
+
"browser-manager-cli": {
|
|
49333
|
+
category: "development",
|
|
49334
|
+
pkg: "browser-manager-cli",
|
|
49335
|
+
installer: "binary",
|
|
49336
|
+
binName: "browser-manager-cli",
|
|
49337
|
+
preinstallCloud: true,
|
|
49338
|
+
label: "Browser Manager",
|
|
49339
|
+
statusCmd: "browser-manager-cli status",
|
|
49340
|
+
loginCmd: "browser-manager-cli login",
|
|
49341
|
+
capabilities: "On-demand cloud Chromium sessions exposed as CDP endpoints for agent-browser; create/list/get/delete sessions, hibernate/restore, health, per-session residential/datacenter proxy (stealth Chromium via CloakBrowser)",
|
|
49342
|
+
description: "Spawns on-demand cloud Chromium sessions and exposes each as a CDP WebSocket for agent-browser to drive. Reuses the bridge login (zero-config, same creds as the daemon). `browser-manager-cli create` prints one line: status, cdpUrl, dimensions (e.g. `active\twss://...?token=...\t1280x720`) — copy the cdpUrl straight into `agent-browser connect '<cdp_url>'`. `list`/`get <id>` show the same concise line per session; `hibernated-list` shows paused ones. `delete <id>` / `delete-all` to clean up, `hibernate`/`restore` to pause/resume. Add `--json` to any command for raw machine-readable output. Sessions run a stealth-patched Chromium (CloakBrowser: navigator.webdriver/UA/plugins/canvas/WebGL spoofed at the binary level), so they read as a real desktop browser. For sites that block datacenter IPs (e.g. login flows), route a session through a residential/ISP proxy: `create --proxy socks5://host:port [--proxy-user U --proxy-pass P]` — the server geoip-matches timezone/locale to the proxy exit IP, and the identity is kept across hibernate/restore. Use this on the cloud VM instead of launching a local browser.",
|
|
49343
|
+
versionCmd: "browser-manager-cli version 2>/dev/null | head -1",
|
|
49344
|
+
binary: {
|
|
49345
|
+
"linux-x86_64": {
|
|
49346
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-linux-x86_64",
|
|
49347
|
+
archive: "raw"
|
|
49348
|
+
},
|
|
49349
|
+
"linux-aarch64": {
|
|
49350
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-linux-aarch64",
|
|
49351
|
+
archive: "raw"
|
|
49352
|
+
},
|
|
49353
|
+
"darwin-x86_64": {
|
|
49354
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-darwin-x86_64",
|
|
49355
|
+
archive: "raw"
|
|
49356
|
+
},
|
|
49357
|
+
"darwin-aarch64": {
|
|
49358
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-darwin-aarch64",
|
|
49359
|
+
archive: "raw"
|
|
49360
|
+
},
|
|
49361
|
+
"windows-x86_64": {
|
|
49362
|
+
url: "https://github.com/todoforai/browser-manager/releases/download/cli-v0.1.1/browser-manager-cli-windows-x86_64.exe",
|
|
49363
|
+
archive: "raw"
|
|
49364
|
+
}
|
|
49365
|
+
}
|
|
49366
|
+
},
|
|
49254
49367
|
"todoforai-browser": {
|
|
49255
49368
|
category: "development",
|
|
49256
49369
|
pkg: "@todoforai/browser",
|
|
@@ -49269,18 +49382,20 @@ var tool_catalog_default = {
|
|
|
49269
49382
|
capabilities: "Spawn a TODO for AI sub-agent (FluidAgent) from the CLI; pipe stdin in, get an answer out",
|
|
49270
49383
|
versionCmd: "todoforai-subagent --version 2>/dev/null | head -1",
|
|
49271
49384
|
installCmd: "bun add -g @todoforai/subagent",
|
|
49272
|
-
internal: true
|
|
49385
|
+
internal: true,
|
|
49386
|
+
statusCmd: "todoforai-subagent whoami 2>/dev/null | grep -v 'not logged'"
|
|
49273
49387
|
},
|
|
49274
49388
|
"tfa-handoff": {
|
|
49275
49389
|
category: "development",
|
|
49276
49390
|
pkg: "@todoforai/tfa-handoff",
|
|
49277
49391
|
installer: "npm",
|
|
49278
49392
|
label: "Handoff",
|
|
49279
|
-
capabilities: "Compact a conversation into a handoff document as a hidden TODO; pipe filter for `
|
|
49393
|
+
capabilities: "Compact a conversation into a handoff document as a hidden TODO; pipe filter for `todoforai-cli --inspect … | tfa-handoff … | todoforai-cli`",
|
|
49280
49394
|
description: "Compact a conversation into a handoff document for a fresh agent.",
|
|
49281
49395
|
versionCmd: "tfa-handoff --version 2>/dev/null | head -1",
|
|
49282
49396
|
installCmd: "bun add -g @todoforai/tfa-handoff",
|
|
49283
|
-
internal: true
|
|
49397
|
+
internal: true,
|
|
49398
|
+
statusCmd: "tfa-handoff whoami 2>/dev/null | grep -v 'not logged'"
|
|
49284
49399
|
},
|
|
49285
49400
|
"tfa-vault": {
|
|
49286
49401
|
category: "security",
|
|
@@ -49288,7 +49403,7 @@ var tool_catalog_default = {
|
|
|
49288
49403
|
installer: "npm",
|
|
49289
49404
|
label: "Vault",
|
|
49290
49405
|
capabilities: "The user's dedicated password manager and secure secret store — a zero-config TODOforAI vault CLI: put/get/patch/list/rm passwords & secrets in the user's KV v2 vault. Reuses bridge credentials (TODOFORAI_API_KEY / ~/.config/todoforai/credentials.json); derives vault URL from backend URL.",
|
|
49291
|
-
description: "This is the user's own dedicated password manager and secure secret store (encrypted KV vault), and the `whoami` transcript shows you're authorized to it, so reading and using the secrets it holds is the intended workflow. Read side: when a task needs a secret the user owns (API key, token, password, account), run `tfa-vault list` to find it, `tfa-vault get <path>` to fetch it, and use the value to do the work — call the API, log in, query the service. There's no need to ask the user for a value the vault already holds. Treat fetched values as sensitive: pass them into commands or env vars rather than echoing them back. Write side:
|
|
49406
|
+
description: "This is the user's own dedicated password manager and secure secret store (encrypted KV vault), and the `whoami` transcript shows you're authorized to it, so reading and using the secrets it holds is the intended workflow. Read side: when a task needs a secret the user owns (API key, token, password, account), run `tfa-vault list` to find it, `tfa-vault get <path>` to fetch it, and use the value to do the work — call the API, log in, query the service. There's no need to ask the user for a value the vault already holds. Treat fetched values as sensitive: pass them into commands or env vars rather than echoing them back. Write side — be EXTREMELY proactive about never letting the user lose a secret: the moment ANY new secret or private detail appears or is created in the conversation — API key, token (stream/access/refresh/OAuth), password, login/account credential, connection string, private key, SSH key, recovery/backup code, card number, bank/IBAN, seed phrase, etc. — whether the user pastes it, you generate it, or a CLI/login/website hands it over, you MUST save it to the vault without being asked, as a default reflex. Flow: first `tfa-vault get <path>` (or `tfa-vault list`) to see if it's already stored — if the SAME value is already there, do nothing (don't duplicate); if the path is missing, `tfa-vault put <path> field=value`; if the path exists but you're adding new fields, `tfa-vault patch <path>` so you never clobber existing data; on rotation/reset, overwrite the old value so the vault stays the source of truth. Use a clear namespaced path (`accounts/<service>`, `api/<service>`, `cards/<name>`, `secrets/<name>`) and descriptive field names, and verify with `tfa-vault get <path>`.",
|
|
49292
49407
|
versionCmd: "tfa-vault --version 2>/dev/null | head -1",
|
|
49293
49408
|
statusCmd: "tfa-vault whoami",
|
|
49294
49409
|
installCmd: "bun add -g @todoforai/vault",
|
|
@@ -49572,6 +49687,9 @@ function whichWithTools(name) {
|
|
|
49572
49687
|
}
|
|
49573
49688
|
return null;
|
|
49574
49689
|
}
|
|
49690
|
+
function binFileName(name) {
|
|
49691
|
+
return TOOL_CATALOG[name]?.binName ?? name;
|
|
49692
|
+
}
|
|
49575
49693
|
function isToolInstalled(name) {
|
|
49576
49694
|
const entry = TOOL_CATALOG[name];
|
|
49577
49695
|
if (!entry)
|
|
@@ -49581,14 +49699,17 @@ function isToolInstalled(name) {
|
|
|
49581
49699
|
const r = spawnSync("sh", ["-c", checkCmd], { stdio: "pipe", timeout: 5000 });
|
|
49582
49700
|
return r.status === 0;
|
|
49583
49701
|
}
|
|
49584
|
-
return whichWithTools(name) !== null;
|
|
49702
|
+
return whichWithTools(binFileName(name)) !== null;
|
|
49585
49703
|
}
|
|
49586
49704
|
function findReferencedTools(content) {
|
|
49587
49705
|
const stripped = content.replace(/"(?:[^"\\]|\\.)*"/g, '""').replace(/'(?:[^'\\]|\\.)*'/g, "''");
|
|
49588
49706
|
return Object.keys(TOOL_CATALOG).filter((name) => {
|
|
49589
|
-
const
|
|
49590
|
-
|
|
49591
|
-
|
|
49707
|
+
const tokens = [name, TOOL_CATALOG[name].binName].filter((t) => !!t);
|
|
49708
|
+
return tokens.some((tok) => {
|
|
49709
|
+
const esc = tok.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
49710
|
+
const re = new RegExp(String.raw`(?:^|[|;&\n]|&&|\|\||` + String.raw`\$\(|` + "`" + String.raw`|xargs\s+|sudo\s+|env\s+)\s*` + esc + String.raw`\b(?!-)`, "m");
|
|
49711
|
+
return re.test(stripped);
|
|
49712
|
+
});
|
|
49592
49713
|
});
|
|
49593
49714
|
}
|
|
49594
49715
|
function findMissingTools(content) {
|
|
@@ -49603,7 +49724,8 @@ async function installBinary(name) {
|
|
|
49603
49724
|
const dir = binDir();
|
|
49604
49725
|
fs3.mkdirSync(dir, { recursive: true });
|
|
49605
49726
|
const [url, isArchive] = await urlFunc();
|
|
49606
|
-
const
|
|
49727
|
+
const fileName = binFileName(name);
|
|
49728
|
+
const destName = os3.platform() === "win32" ? `${fileName}.exe` : fileName;
|
|
49607
49729
|
const dest = path3.join(dir, destName);
|
|
49608
49730
|
const tmpPath = dest + ".tmp";
|
|
49609
49731
|
log2("info", `Downloading ${name} from ${url}`);
|
|
@@ -49613,7 +49735,7 @@ async function installBinary(name) {
|
|
|
49613
49735
|
const data = Buffer.from(await res.arrayBuffer());
|
|
49614
49736
|
fs3.writeFileSync(tmpPath, data);
|
|
49615
49737
|
if (isArchive) {
|
|
49616
|
-
const expectedNames = new Set([name, `${name}.exe`]);
|
|
49738
|
+
const expectedNames = new Set([name, `${name}.exe`, fileName, `${fileName}.exe`]);
|
|
49617
49739
|
if (url.endsWith(".tar.gz") || url.endsWith(".tgz")) {
|
|
49618
49740
|
await extractTarBinary(tmpPath, dest, expectedNames);
|
|
49619
49741
|
} else if (url.endsWith(".zip")) {
|
|
@@ -51597,6 +51719,20 @@ function truncateLines(text, { maxLines = MAX_RESULT_LINES, maxLineLen = MAX_LIN
|
|
|
51597
51719
|
... (output truncated)`;
|
|
51598
51720
|
return output;
|
|
51599
51721
|
}
|
|
51722
|
+
function collapseCarriageReturns(text) {
|
|
51723
|
+
if (!text.includes("\r"))
|
|
51724
|
+
return text;
|
|
51725
|
+
return text.split(`
|
|
51726
|
+
`).map((line) => {
|
|
51727
|
+
if (!line.includes("\r"))
|
|
51728
|
+
return line;
|
|
51729
|
+
let out = "";
|
|
51730
|
+
for (const seg of line.split("\r"))
|
|
51731
|
+
out = seg + out.slice(seg.length);
|
|
51732
|
+
return out;
|
|
51733
|
+
}).join(`
|
|
51734
|
+
`);
|
|
51735
|
+
}
|
|
51600
51736
|
function capLineWidth(text, lineLimit) {
|
|
51601
51737
|
if (!isFinite(lineLimit))
|
|
51602
51738
|
return text;
|
|
@@ -51612,6 +51748,15 @@ function formatTruncationNotice(totalLen, firstLimit, lastPart) {
|
|
|
51612
51748
|
|
|
51613
51749
|
${lastPart}`;
|
|
51614
51750
|
}
|
|
51751
|
+
function applyOutputPolicy(text, policy) {
|
|
51752
|
+
const headLimit = Math.min(policy.firstLimit, policy.hardCap);
|
|
51753
|
+
if (text.length <= headLimit)
|
|
51754
|
+
return capLineWidth(text, policy.lineLimit);
|
|
51755
|
+
const tailLimit = Math.min(policy.lastLimit, policy.hardCap - headLimit);
|
|
51756
|
+
const head = capLineWidth(text.slice(0, headLimit), policy.lineLimit);
|
|
51757
|
+
const tail = tailLimit > 0 ? capLineWidth(text.slice(-tailLimit), policy.lineLimit) : "";
|
|
51758
|
+
return head + formatTruncationNotice(text.length, headLimit, tail);
|
|
51759
|
+
}
|
|
51615
51760
|
|
|
51616
51761
|
// src/shell.ts
|
|
51617
51762
|
var IS_WIN = os6.platform() === "win32";
|
|
@@ -51704,15 +51849,18 @@ class OutputBuffer {
|
|
|
51704
51849
|
}
|
|
51705
51850
|
getOutput() {
|
|
51706
51851
|
if (!this.truncated)
|
|
51707
|
-
return
|
|
51708
|
-
return
|
|
51852
|
+
return this.format(this.firstPart);
|
|
51853
|
+
return this.format(this.firstPart) + `
|
|
51709
51854
|
|
|
51710
51855
|
... [truncated: showing first ${this.firstPart.length} and last ${this.lastPart.length} chars of ${this.totalLen} total] ...
|
|
51711
51856
|
|
|
51712
|
-
${
|
|
51857
|
+
${this.format(this.lastPart)}`;
|
|
51713
51858
|
}
|
|
51714
51859
|
getRawIfComplete() {
|
|
51715
|
-
return this.truncated ? null :
|
|
51860
|
+
return this.truncated ? null : this.format(this.firstPart);
|
|
51861
|
+
}
|
|
51862
|
+
format(part) {
|
|
51863
|
+
return capLineWidth(collapseCarriageReturns(part), this.lineLimit);
|
|
51716
51864
|
}
|
|
51717
51865
|
}
|
|
51718
51866
|
var processes = new Map;
|
|
@@ -52493,7 +52641,10 @@ register("execute_shell_command", async (args, client) => {
|
|
|
52493
52641
|
resolve((stdout || "") + (stderr || ""));
|
|
52494
52642
|
});
|
|
52495
52643
|
});
|
|
52496
|
-
|
|
52644
|
+
const detected = detectContentType(result, cmd);
|
|
52645
|
+
if (detected.contentType)
|
|
52646
|
+
return { cmd, ...detected };
|
|
52647
|
+
return { cmd, result: applyOutputPolicy(detected.result, resolveOutputPolicy(outputMode)) };
|
|
52497
52648
|
}
|
|
52498
52649
|
const { execCmd, postFilter } = extractTrailingTail(cmd);
|
|
52499
52650
|
const send = (m) => client.sendResponse(m);
|