@todoforai/cli 0.1.60 → 0.1.62
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/todoforai-cli.js +230 -76
- package/package.json +1 -1
package/dist/todoforai-cli.js
CHANGED
|
@@ -43055,6 +43055,19 @@ class ApiClient {
|
|
|
43055
43055
|
throw new Error(`API GET /resources/show failed: ${res.status} ${await res.text()}`);
|
|
43056
43056
|
return res.json();
|
|
43057
43057
|
}
|
|
43058
|
+
async shareShow(todoId, key) {
|
|
43059
|
+
const url = `${this.apiUrl}${restBasePath(this.apiKey)}/resources/show/${encodeURIComponent(todoId)}/${encodeURIComponent(key)}/share`;
|
|
43060
|
+
const res = await fetch(url, { method: "POST", headers: { "x-api-key": this.apiKey }, signal: AbortSignal.timeout(30000) });
|
|
43061
|
+
if (!res.ok)
|
|
43062
|
+
throw new Error(`API POST /resources/show/share failed: ${res.status} ${await res.text()}`);
|
|
43063
|
+
return res.json();
|
|
43064
|
+
}
|
|
43065
|
+
async unshareShow(todoId, key) {
|
|
43066
|
+
const url = `${this.apiUrl}${restBasePath(this.apiKey)}/resources/show/${encodeURIComponent(todoId)}/${encodeURIComponent(key)}/share`;
|
|
43067
|
+
const res = await fetch(url, { method: "DELETE", headers: { "x-api-key": this.apiKey }, signal: AbortSignal.timeout(30000) });
|
|
43068
|
+
if (!res.ok)
|
|
43069
|
+
throw new Error(`API DELETE /resources/show/share failed: ${res.status} ${await res.text()}`);
|
|
43070
|
+
}
|
|
43058
43071
|
async removeShow(todoId, key) {
|
|
43059
43072
|
const url = `${this.apiUrl}${restBasePath(this.apiKey)}/resources/show/${encodeURIComponent(todoId)}/${encodeURIComponent(key)}`;
|
|
43060
43073
|
const res = await fetch(url, {
|
|
@@ -43597,6 +43610,11 @@ function qualifiedModelIds(listing, filter) {
|
|
|
43597
43610
|
return q ? ids.filter((id) => id.toLowerCase().includes(q)) : ids;
|
|
43598
43611
|
}
|
|
43599
43612
|
// ../packages/shared-fbe/src/billing.ts
|
|
43613
|
+
var HOBBY_ALLOWED = new Set([
|
|
43614
|
+
"anthropic/claude-sonnet-5.5",
|
|
43615
|
+
"anthropic/claude-sonnet-5",
|
|
43616
|
+
"anthropic/claude-haiku-4.5"
|
|
43617
|
+
]);
|
|
43600
43618
|
var USAGE_WINDOWS = {
|
|
43601
43619
|
SESSION_MS: 5 * 60 * 60 * 1000,
|
|
43602
43620
|
WEEK_MS: 7 * 24 * 60 * 60 * 1000,
|
|
@@ -43901,6 +43919,15 @@ function manualAnswersOf(sources) {
|
|
|
43901
43919
|
}
|
|
43902
43920
|
var manualSamples = (answers) => Object.entries(answers).filter(([, a]) => a.trim()).map(([prompt, text]) => ({ prompt, text: text.trim() }));
|
|
43903
43921
|
var senderLabel = (s) => s.kind === "team" ? `${s.name} · TODO for AI team` : s.kind === "member" ? `${s.name} · teammate` : `${s.name} · your agent`;
|
|
43922
|
+
// ../packages/shared-fbe/src/jarvisEvents.ts
|
|
43923
|
+
var STATE = {
|
|
43924
|
+
["READY" /* READY */]: "agent ended its run and handed back; not opened yet",
|
|
43925
|
+
["READY_CHECKED" /* READY_CHECKED */]: "agent ended its run and handed back; its window was opened",
|
|
43926
|
+
["DONE" /* DONE */]: "done and closed",
|
|
43927
|
+
["ERROR" /* ERROR */]: "failed; not opened yet",
|
|
43928
|
+
["ERROR_CHECKED" /* ERROR_CHECKED */]: "failed; its window was opened",
|
|
43929
|
+
["WAITING_FOR_USER" /* WAITING_FOR_USER */]: "blocked, waiting on the user's answer or approval"
|
|
43930
|
+
};
|
|
43904
43931
|
// ../packages/shared-fbe/src/templateBody.ts
|
|
43905
43932
|
var USER_HEADINGS = new Set([
|
|
43906
43933
|
"your task",
|
|
@@ -44478,6 +44505,7 @@ var tool_catalog_default = {
|
|
|
44478
44505
|
versionCmd: "linkedin-api --version 2>/dev/null | sed -n 1p"
|
|
44479
44506
|
},
|
|
44480
44507
|
"figma-api": {
|
|
44508
|
+
preinstallCloud: true,
|
|
44481
44509
|
category: "design",
|
|
44482
44510
|
pkg: "@todoforai/figma-api",
|
|
44483
44511
|
installer: "npm",
|
|
@@ -44612,6 +44640,20 @@ var tool_catalog_default = {
|
|
|
44612
44640
|
],
|
|
44613
44641
|
description: "AI music generation, custom lyrics, multiple genres."
|
|
44614
44642
|
},
|
|
44643
|
+
"tfa-suno": {
|
|
44644
|
+
preinstallCloud: true,
|
|
44645
|
+
category: "media",
|
|
44646
|
+
pkg: "@todoforai/suno-api",
|
|
44647
|
+
installer: "npm",
|
|
44648
|
+
label: "Suno (TODOforAI)",
|
|
44649
|
+
summary: "Generate music and songs from a prompt, billed to your TODOforAI credit.",
|
|
44650
|
+
platformAuth: true,
|
|
44651
|
+
versionCmd: "tfa-suno --version 2>/dev/null | sed -n 1p",
|
|
44652
|
+
credentialPaths: [
|
|
44653
|
+
"~/.config/todoforai/credentials.json"
|
|
44654
|
+
],
|
|
44655
|
+
description: "Suno music generation via TODOforAI — no Suno key needed, billed to the user's TODOforAI credit (generate $0.12 for 2 songs, refunded if the task fails). Same commands as suno-api: `generate [prompt] [--customMode --lyrics <file> --style --title] [--instrumental] [--model V6]` polls until done and prints audio URLs; `--no-poll` + `details <taskId> [--wait]`; `stems`, `midi`, `lyrics-ts`, `replace-section`. Audio URLs expire after 14 days — download the mp3s you keep. Prefer this over suno-api unless the user has their own sunoapi.org key."
|
|
44656
|
+
},
|
|
44615
44657
|
ntn: {
|
|
44616
44658
|
preinstallCloud: true,
|
|
44617
44659
|
category: "utility",
|
|
@@ -44672,6 +44714,9 @@ var tool_catalog_default = {
|
|
|
44672
44714
|
preinstallCloud: true
|
|
44673
44715
|
},
|
|
44674
44716
|
glab: {
|
|
44717
|
+
preinstallCloud: true,
|
|
44718
|
+
cloudInstallCmd: "curl -fsSL https://gitlab.com/gitlab-org/cli/-/releases/v1.119.0/downloads/glab_1.119.0_linux_amd64.tar.gz | tar -xz -C /tmp bin/glab && install -m0755 /tmp/bin/glab /usr/local/bin/glab",
|
|
44719
|
+
cloudVerifyCmd: "glab --version",
|
|
44675
44720
|
category: "development",
|
|
44676
44721
|
pkg: "glab",
|
|
44677
44722
|
installer: "binary",
|
|
@@ -44703,6 +44748,7 @@ var tool_catalog_default = {
|
|
|
44703
44748
|
canStreamLogin: true
|
|
44704
44749
|
},
|
|
44705
44750
|
eas: {
|
|
44751
|
+
preinstallCloud: true,
|
|
44706
44752
|
category: "deployment",
|
|
44707
44753
|
pkg: "eas-cli",
|
|
44708
44754
|
installer: "npm",
|
|
@@ -44718,6 +44764,7 @@ var tool_catalog_default = {
|
|
|
44718
44764
|
versionCmd: "eas --version 2>/dev/null | sed -n 1p"
|
|
44719
44765
|
},
|
|
44720
44766
|
netlify: {
|
|
44767
|
+
preinstallCloud: true,
|
|
44721
44768
|
category: "deployment",
|
|
44722
44769
|
pkg: "netlify-cli",
|
|
44723
44770
|
installer: "npm",
|
|
@@ -44783,6 +44830,9 @@ var tool_catalog_default = {
|
|
|
44783
44830
|
canStreamLogin: true
|
|
44784
44831
|
},
|
|
44785
44832
|
flyctl: {
|
|
44833
|
+
preinstallCloud: true,
|
|
44834
|
+
cloudInstallCmd: "curl -fsSL https://github.com/superfly/flyctl/releases/download/v0.4.108/flyctl_0.4.108_Linux_x86_64.tar.gz | tar -xz -C /usr/local/bin flyctl",
|
|
44835
|
+
cloudVerifyCmd: "flyctl version",
|
|
44786
44836
|
category: "cloud",
|
|
44787
44837
|
pkg: "flyctl",
|
|
44788
44838
|
installer: "binary",
|
|
@@ -44810,6 +44860,7 @@ var tool_catalog_default = {
|
|
|
44810
44860
|
versionCmd: "supabase --version 2>/dev/null | sed -n 1p"
|
|
44811
44861
|
},
|
|
44812
44862
|
railway: {
|
|
44863
|
+
preinstallCloud: true,
|
|
44813
44864
|
category: "cloud",
|
|
44814
44865
|
pkg: "@railway/cli",
|
|
44815
44866
|
installer: "npm",
|
|
@@ -44851,6 +44902,7 @@ var tool_catalog_default = {
|
|
|
44851
44902
|
versionCmd: "shop-app --version 2>/dev/null | sed -n 1p"
|
|
44852
44903
|
},
|
|
44853
44904
|
"datadog-ci": {
|
|
44905
|
+
preinstallCloud: true,
|
|
44854
44906
|
category: "monitoring",
|
|
44855
44907
|
pkg: "@datadog/datadog-ci",
|
|
44856
44908
|
installer: "npm",
|
|
@@ -44879,7 +44931,7 @@ var tool_catalog_default = {
|
|
|
44879
44931
|
installer: "npm",
|
|
44880
44932
|
label: "TODOforAI",
|
|
44881
44933
|
summary: "Create and follow up on your TODOs, and show results in the chat.",
|
|
44882
|
-
description: 'Manage the user\'s OWN TODOforAI tasks (not code `// TODO` comments). Delegate/spin off work: `tfa-cli "prompt"` creates a real TODO with its own agent and chat (`-n` wait for completion, `--no-watch` fire-and-forget, `--project/--agent/--model`, `--resume <id>`, `addmessage <id> "text"`). Inspect: `list [--status open]`, `--inspect <id>`. Edit any todo without opening it: `status <id> DONE|READY|ARCHIVED|POSTPONED|CANCELLED|DELETED` (close, reopen, shelve, trash — `todo restore <id>` undoes a delete) and `todo set <id|-> title=… group=… star=true schedule=<unix-ms> agent=… brand=…` (own todo fields). Both take ONE id, so a loop over `list --json | jq -r \'.items[].id\'` is how you close, retitle, refile or archive MANY todos at once; `project set|settings|groups …` (name, settings, todo groups), `agent create|update <agent> model=… sysmsg=…` (permissions/MCP/device wiring and delete are refused from an agent shell). Surface results into chat: `show <file|-> [todo-id]` (renders by mimetype; `--card <name>` via project renderer; `--alias <name>` updates in place), `open <url>` embeds a live preview. Notifications: `inbox [needs-you|messages|activity] [--unread]` reads the user\'s bell feed (what finished/failed/needs them while away), `inbox seen [tab]` marks it read; `notify "Title" "message" [--href /t/<id>]` leaves a note in the user\'s Messages tab + phone push (shown as from you); `--to <email>` reaches a member of the current project instead (`project members` lists them, 20/day) — nobody else; same text is delivered once, max 10/day to the user, use for things they must see later (not chat replies). This is the ONLY way to display a local file (image, pdf, html) in the chat: markdown `` with a local/relative path does NOT resolve to workspace files or attachments and 404s in the browser. `--template` for registry workflows.',
|
|
44934
|
+
description: 'Manage the user\'s OWN TODOforAI tasks (not code `// TODO` comments). Delegate/spin off work: `tfa-cli "prompt"` creates a real TODO with its own agent and chat (`-n` wait for completion, `--no-watch` fire-and-forget, `--project/--agent/--model`, `--resume <id>`, `addmessage <id> "text"`). Inspect: `list [--status open]`, `--inspect <id>`. Edit any todo without opening it: `status <id> DONE|READY|ARCHIVED|POSTPONED|CANCELLED|DELETED` (close, reopen, shelve, trash — `todo restore <id>` undoes a delete) and `todo set <id|-> title=… group=… star=true schedule=<unix-ms> agent=… brand=…` (own todo fields). Both take ONE id, so a loop over `list --json | jq -r \'.items[].id\'` is how you close, retitle, refile or archive MANY todos at once; `project set|settings|groups …` (name, settings, todo groups), `agent create|update <agent> model=… sysmsg=…` (permissions/MCP/device wiring and delete are refused from an agent shell). Surface results into chat: `show <file|-> [todo-id]` (renders by mimetype, private to the todo\'s readers; `--card <name>` via project renderer; `--alias <name>` updates in place, `--alias <todoId>:<name>` updates another todo\'s artifact; `show share <ref>` makes it public and prints the link, `show unshare <ref>` makes it private again), `open <url>` embeds a live preview. Pick by where the output lives: read once → plain reply; interactive, this chat only → `html_snippet`; kept/revised later → `show --alias`, then `show share` only if someone outside needs a link; format the user asked for (pptx, docx…) → `show` the file. Notifications: `inbox [needs-you|messages|activity] [--unread]` reads the user\'s bell feed (what finished/failed/needs them while away), `inbox seen [tab]` marks it read; `notify "Title" "message" [--href /t/<id>]` leaves a note in the user\'s Messages tab + phone push (shown as from you); `--to <email>` reaches a member of the current project instead (`project members` lists them, 20/day) — nobody else; same text is delivered once, max 10/day to the user, use for things they must see later (not chat replies). This is the ONLY way to display a local file (image, pdf, html) in the chat: markdown `` with a local/relative path does NOT resolve to workspace files or attachments and 404s in the browser. `--template` for registry workflows.',
|
|
44883
44935
|
installCmd: "npm install -g @todoforai/cli",
|
|
44884
44936
|
versionCmd: "tfa-cli --version 2>/dev/null | sed -n 1p",
|
|
44885
44937
|
preinstallCloud: true,
|
|
@@ -45006,7 +45058,7 @@ var tool_catalog_default = {
|
|
|
45006
45058
|
label: "Google Cloud",
|
|
45007
45059
|
summary: "Manage your Google Cloud projects and services.",
|
|
45008
45060
|
needsPython: true,
|
|
45009
|
-
installCmd: `curl -fsSL https://dl.google.com/dl/cloudsdk/channels/rapid/google-cloud-
|
|
45061
|
+
installCmd: `case "$(uname -s)-$(uname -m)" in Darwin-arm64) p=darwin-arm;; Darwin-*) p=darwin-x86_64;; Linux-aarch64|Linux-arm64) p=linux-arm;; *) p=linux-x86_64;; esac && tmp="$HOME/.gcloud-new.$$" && rm -rf "$tmp" && mkdir -p "$tmp" && curl -fsSL "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-$p.tar.gz" | tar -xzC "$tmp" && rm -rf "$HOME/google-cloud-sdk" && mv "$tmp/google-cloud-sdk" "$HOME/google-cloud-sdk" && rm -rf "$tmp" && mkdir -p "$HOME/.todoforai/tools/bin" && rm -f "$HOME/.todoforai/tools/bin/gcloud" && printf '#!/bin/sh\\nCLOUDSDK_PYTHON="\${CLOUDSDK_PYTHON:-%s}" exec "$HOME/google-cloud-sdk/bin/gcloud" "$@"\\n' "$py" > "$HOME/.todoforai/tools/bin/gcloud" && chmod +x "$HOME/.todoforai/tools/bin/gcloud"`,
|
|
45010
45062
|
statusCmd: `gcloud auth list --filter=status:ACTIVE --format="value(account)" 2>/dev/null | tr -d '\\r' | grep -m1 .`,
|
|
45011
45063
|
loginCmd: "gcloud auth login --no-launch-browser",
|
|
45012
45064
|
loginNeedsPty: true,
|
|
@@ -45015,8 +45067,7 @@ var tool_catalog_default = {
|
|
|
45015
45067
|
credentialPaths: ["~/.config/gcloud"],
|
|
45016
45068
|
description: "Official Google Cloud CLI. `gcloud auth login --no-launch-browser` prints the OAuth URL and waits for the pasted verification code.",
|
|
45017
45069
|
versionCmd: "gcloud --version 2>/dev/null | sed -n 1p",
|
|
45018
|
-
uninstallCmd: 'rm -rf "$HOME/google-cloud-sdk" "$HOME/.todoforai/tools/bin/gcloud"; hash -r 2>/dev/null; ! command -v gcloud >/dev/null 2>&1 || { echo "gcloud is still on PATH: $(command -v gcloud)"; exit 1; }'
|
|
45019
|
-
updateCmd: "gcloud components update --quiet"
|
|
45070
|
+
uninstallCmd: 'rm -rf "$HOME/google-cloud-sdk" "$HOME/.todoforai/tools/bin/gcloud"; hash -r 2>/dev/null; ! command -v gcloud >/dev/null 2>&1 || { echo "gcloud is still on PATH: $(command -v gcloud)"; exit 1; }'
|
|
45020
45071
|
},
|
|
45021
45072
|
az: {
|
|
45022
45073
|
category: "cloud",
|
|
@@ -45150,19 +45201,6 @@ var tool_catalog_default = {
|
|
|
45150
45201
|
},
|
|
45151
45202
|
preinstallJarvis: true
|
|
45152
45203
|
},
|
|
45153
|
-
"todoforai-browser": {
|
|
45154
|
-
category: "development",
|
|
45155
|
-
pkg: "@todoforai/browser",
|
|
45156
|
-
aliases: ["tfa-browser"],
|
|
45157
|
-
installer: "npm",
|
|
45158
|
-
preinstallCloud: true,
|
|
45159
|
-
label: "Browser (Extension)",
|
|
45160
|
-
summary: "Drive your own browser through the TODOforAI extension.",
|
|
45161
|
-
versionCmd: `node -p "require(require('fs').realpathSync(require('child_process').execSync('command -v todoforai-browser',{encoding:'utf8'}).trim()).replace(/\\/dist\\/index\\.js$/, '/package.json')).version" 2>/dev/null`,
|
|
45162
|
-
internal: true,
|
|
45163
|
-
preinstallJarvis: true,
|
|
45164
|
-
description: "Browser automation via extension (non-headless), web scraping, accessibility tree snapshots, screenshots, PDF generation"
|
|
45165
|
-
},
|
|
45166
45204
|
"tfa-explore": {
|
|
45167
45205
|
preinstallCloud: true,
|
|
45168
45206
|
category: "development",
|
|
@@ -45633,6 +45671,20 @@ var tool_catalog_default = {
|
|
|
45633
45671
|
description: "WordPress REST API CLI. `wordpress-api auth --site https://example.com --user <user> --password '<application password>'` (application password, not the login password). Reading published content needs no auth. `posts list|get|create|update|delete`, `pages`, `media`, `categories`. `posts create` saves a draft unless --status publish. On Elementor/JetEngine sites content.rendered comes back empty — fetch the post's public URL for the body.",
|
|
45634
45672
|
versionCmd: "wordpress-api --version 2>/dev/null | sed -n 1p"
|
|
45635
45673
|
},
|
|
45674
|
+
"mailchimp-api": {
|
|
45675
|
+
category: "marketing",
|
|
45676
|
+
pkg: "@todoforai/mailchimp-api",
|
|
45677
|
+
installer: "npm",
|
|
45678
|
+
label: "Mailchimp",
|
|
45679
|
+
summary: "Manage Mailchimp audiences, contacts, email campaigns and reports.",
|
|
45680
|
+
loginCmd: "mailchimp-api auth --api-key <api_key>",
|
|
45681
|
+
statusCmd: `mailchimp-api whoami 2>/dev/null | sed -n 's/.*"account_name"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m1 .`,
|
|
45682
|
+
credentialPaths: [
|
|
45683
|
+
"~/.config/mailchimp-api/credentials.json"
|
|
45684
|
+
],
|
|
45685
|
+
versionCmd: "mailchimp-api --version 2>/dev/null | sed -n 1p",
|
|
45686
|
+
description: "Independent CLI over the official Mailchimp Marketing API: 155 endpoint commands for lists (email audiences), members (contacts; email or MD5), tags, segments, merge fields, interests, notes/events, campaigns/content/tests/scheduling, templates, reports, assets, landing pages, classic automations, journey triggers, webhooks and batches. JSON output; --data JSON|@file|-; --schema; --all pagination. Every write requires --yes; use --dry-run first. Raw request METHOD /path covers other Marketing endpoints. API-key auth, not OAuth onboarding. Plan/API restrictions apply; no Transactional/Mandrill or Open Commerce. Run --help for limits and consent cautions."
|
|
45687
|
+
},
|
|
45636
45688
|
"facebook-pages-api": {
|
|
45637
45689
|
preinstallCloud: true,
|
|
45638
45690
|
category: "social",
|
|
@@ -45647,8 +45699,10 @@ var tool_catalog_default = {
|
|
|
45647
45699
|
versionCmd: "facebook-pages-api --version 2>/dev/null | sed -n 1p"
|
|
45648
45700
|
},
|
|
45649
45701
|
"ews-api": {
|
|
45702
|
+
preinstallCloud: true,
|
|
45650
45703
|
category: "email",
|
|
45651
45704
|
pkg: "ews-api",
|
|
45705
|
+
packages: ["ews-api==0.2.0"],
|
|
45652
45706
|
installer: "pip",
|
|
45653
45707
|
label: "Exchange (EWS)",
|
|
45654
45708
|
summary: "Read and write mail on a company Exchange server.",
|
|
@@ -45676,6 +45730,7 @@ var tool_catalog_default = {
|
|
|
45676
45730
|
canStreamLogin: true
|
|
45677
45731
|
},
|
|
45678
45732
|
neonctl: {
|
|
45733
|
+
preinstallCloud: true,
|
|
45679
45734
|
category: "database",
|
|
45680
45735
|
pkg: "neonctl",
|
|
45681
45736
|
installer: "npm",
|
|
@@ -45698,7 +45753,7 @@ var tool_catalog_default = {
|
|
|
45698
45753
|
label: "Microsoft 365",
|
|
45699
45754
|
summary: "Work with Microsoft 365 mail, Teams, SharePoint and users.",
|
|
45700
45755
|
statusCmd: `m365 status --output text 2>/dev/null | tr -d '"' | grep -vi 'logged out' | grep -m1 .`,
|
|
45701
|
-
loginCmd: "m365 login --authType deviceCode --appId
|
|
45756
|
+
loginCmd: "m365 login --authType deviceCode --appId 14d82eec-204b-4c2f-b7e8-296a70dab67e",
|
|
45702
45757
|
deviceCodePattern: "enter the code ([A-Z0-9]{8,}) to authenticate",
|
|
45703
45758
|
oauthUrlPattern: "open the page (https://\\S+) and enter",
|
|
45704
45759
|
credentialPaths: ["~/.cli-m365-msal.json", "~/.cli-m365-connection.json"],
|
|
@@ -45737,6 +45792,7 @@ var tool_catalog_default = {
|
|
|
45737
45792
|
versionCmd: "posthog-cli --version 2>/dev/null | sed -n 1p"
|
|
45738
45793
|
},
|
|
45739
45794
|
canva: {
|
|
45795
|
+
preinstallCloud: true,
|
|
45740
45796
|
category: "design",
|
|
45741
45797
|
pkg: "@canva/cli",
|
|
45742
45798
|
installer: "npm",
|
|
@@ -45752,6 +45808,7 @@ var tool_catalog_default = {
|
|
|
45752
45808
|
oauthUrlPattern: "OPEN_URL: (https://www\\.canva\\.com/api/oauth/authorize\\S+)"
|
|
45753
45809
|
},
|
|
45754
45810
|
webflow: {
|
|
45811
|
+
preinstallCloud: true,
|
|
45755
45812
|
category: "development",
|
|
45756
45813
|
pkg: "@webflow/webflow-cli",
|
|
45757
45814
|
installer: "npm",
|
|
@@ -45766,6 +45823,7 @@ var tool_catalog_default = {
|
|
|
45766
45823
|
versionCmd: "webflow --version 2>/dev/null | sed -n 1p"
|
|
45767
45824
|
},
|
|
45768
45825
|
readwise: {
|
|
45826
|
+
preinstallCloud: true,
|
|
45769
45827
|
category: "productivity",
|
|
45770
45828
|
pkg: "@readwise/cli",
|
|
45771
45829
|
installer: "npm",
|
|
@@ -45836,6 +45894,7 @@ var tool_catalog_default = {
|
|
|
45836
45894
|
versionCmd: "exa --version 2>/dev/null | sed -n 1p"
|
|
45837
45895
|
},
|
|
45838
45896
|
mobbin: {
|
|
45897
|
+
preinstallCloud: true,
|
|
45839
45898
|
category: "design",
|
|
45840
45899
|
pkg: "mobbin",
|
|
45841
45900
|
installer: "npm",
|
|
@@ -45866,6 +45925,7 @@ var tool_catalog_default = {
|
|
|
45866
45925
|
versionCmd: "{ python -c 'import sys; from importlib.metadata import version; print(version(sys.argv[1]))' blender-mcp || python3 -c 'import sys; from importlib.metadata import version; print(version(sys.argv[1]))' blender-mcp; } 2>/dev/null"
|
|
45867
45926
|
},
|
|
45868
45927
|
"google-ads": {
|
|
45928
|
+
preinstallCloud: true,
|
|
45869
45929
|
category: "marketing",
|
|
45870
45930
|
pkg: "google-ads",
|
|
45871
45931
|
packages: [
|
|
@@ -45935,6 +45995,7 @@ var model_promos_default = {
|
|
|
45935
45995
|
{ family: "gpt-5-6-sol", rate: 0.85, starts: "2026-08-26", ends: "2026-09-13" },
|
|
45936
45996
|
{ family: "gpt-5-6-sol", rate: 0.8, starts: "2026-09-14", ends: "2026-11-21" },
|
|
45937
45997
|
{ family: "gpt-6-sol", rate: 0.8, starts: "2026-09-22", ends: "2026-11-21" },
|
|
45998
|
+
{ family: "gpt-6-1-sol", rate: 0.8, starts: "2026-09-29", ends: "2026-11-21" },
|
|
45938
45999
|
{ family: "gpt-6-luna", rate: 0.8, starts: "2026-09-22", ends: "2026-11-21" },
|
|
45939
46000
|
{ family: "gpt-6-astra", rate: 0.85, starts: "2026-09-05", ends: "2026-09-13", boostable: false },
|
|
45940
46001
|
{ family: "gpt-6-astra", rate: 0.8, starts: "2026-09-14", ends: "2026-11-21", boostable: false },
|
|
@@ -46135,7 +46196,7 @@ import { parseArgs } from "util";
|
|
|
46135
46196
|
// package.json
|
|
46136
46197
|
var package_default = {
|
|
46137
46198
|
name: "@todoforai/cli",
|
|
46138
|
-
version: "0.1.
|
|
46199
|
+
version: "0.1.62",
|
|
46139
46200
|
type: "module",
|
|
46140
46201
|
bin: {
|
|
46141
46202
|
"todoforai-cli": "bin/todoforai-cli.js",
|
|
@@ -46247,15 +46308,27 @@ Usage:
|
|
|
46247
46308
|
tfa-cli show <file|-> [todo-id] Render a file by mimetype (- reads stdin)
|
|
46248
46309
|
[--title T] [--alias A] [--mime M] [--card <name>] [--link] [--json]
|
|
46249
46310
|
--link: compact download chip instead of inline render
|
|
46250
|
-
Prints "<todoId>:<alias|id>
|
|
46251
|
-
--alias updates the block in place
|
|
46252
|
-
|
|
46311
|
+
Prints "<todoId>:<alias|id>". Private: visible to whoever can read the todo.
|
|
46312
|
+
Re-showing with the same --alias updates the block in place (new version)
|
|
46313
|
+
--alias <todoId>:<alias> updates that todo's block instead,
|
|
46314
|
+
so a later chat can revise an artifact made elsewhere
|
|
46315
|
+
tfa-cli show share <ref|alias> Make it public; prints its link (serves the latest version)
|
|
46316
|
+
tfa-cli show unshare <ref|alias> Make it private again (the link stops working)
|
|
46317
|
+
tfa-cli show rm <ref|alias> Take it down (block, link, every version)
|
|
46253
46318
|
tfa-cli show list [todo-id] List show blocks (ref, title, mime/url, card)
|
|
46254
46319
|
[--project <id>] [--card <name>] [--json]
|
|
46255
46320
|
no todo-id + --project (or $TODOFORAI_PROJECT_ID) = every todo
|
|
46256
46321
|
tfa-cli open <url> [todo-id] Live http(s) url as a preview [--title T] [--alias A] [--json]
|
|
46257
46322
|
|
|
46258
46323
|
todo-id defaults to $TODOFORAI_TODO_ID (agent shell) or the last todo this CLI touched.
|
|
46324
|
+
|
|
46325
|
+
When to use what:
|
|
46326
|
+
read once, move on → plain chat reply
|
|
46327
|
+
interactive, this chat only → html_snippet (can exec/connect/chat back)
|
|
46328
|
+
keep / revise later → show <file> --alias <name> (versioned, private)
|
|
46329
|
+
someone outside needs it → show share <alias> (public link, revocable)
|
|
46330
|
+
a live web page → open <url>
|
|
46331
|
+
a format the user asked for → show the file (pptx, docx, xlsx, pdf…)
|
|
46259
46332
|
`);
|
|
46260
46333
|
}
|
|
46261
46334
|
var STATUS_HELP = {
|
|
@@ -46314,7 +46387,6 @@ function parseCliArgs() {
|
|
|
46314
46387
|
link: { type: "boolean", default: false },
|
|
46315
46388
|
direction: { type: "string" },
|
|
46316
46389
|
url: { type: "string" },
|
|
46317
|
-
"pasted-file": { type: "string" },
|
|
46318
46390
|
account: { type: "string" },
|
|
46319
46391
|
"from-company": { type: "boolean", default: false },
|
|
46320
46392
|
"dry-run": { type: "boolean", default: false },
|
|
@@ -48309,7 +48381,7 @@ var createBuilder = (self, _styler, _isEmpty) => {
|
|
|
48309
48381
|
return applyStyle(builder, "" + arguments_[0]);
|
|
48310
48382
|
}
|
|
48311
48383
|
if (arguments_.length === 2) {
|
|
48312
|
-
return applyStyle(builder, arguments_[0]
|
|
48384
|
+
return applyStyle(builder, `${arguments_[0] ?? ""} ${arguments_[1] ?? ""}`);
|
|
48313
48385
|
}
|
|
48314
48386
|
return applyStyle(builder, arguments_.join(" "));
|
|
48315
48387
|
};
|
|
@@ -49499,7 +49571,7 @@ var ADAPTERS = { Gmail: gmail, Outlook: outlook, Chat: chat };
|
|
|
49499
49571
|
var DEVICE_CHANNELS = Object.keys(ADAPTERS);
|
|
49500
49572
|
function checkChannel(channel) {
|
|
49501
49573
|
const a = ADAPTERS[channel];
|
|
49502
|
-
return a ? a.check() : `${channel} is not read on the device (server-side: pass --url
|
|
49574
|
+
return a ? a.check() : `${channel} is not read on the device (server-side: pass --url)`;
|
|
49503
49575
|
}
|
|
49504
49576
|
function collectChannel(channel, max = 40) {
|
|
49505
49577
|
const a = ADAPTERS[channel];
|
|
@@ -49779,12 +49851,12 @@ Usage:
|
|
|
49779
49851
|
tfa-cli brand rename <name>
|
|
49780
49852
|
tfa-cli brand voice Learned profile + sources
|
|
49781
49853
|
tfa-cli brand voice answers [<q>=<a>…] Show / set the Manual source: answers to the style questions
|
|
49782
|
-
tfa-cli brand voice collect <channel> [--url U | --
|
|
49854
|
+
tfa-cli brand voice collect <channel> [--url U | --max N]
|
|
49783
49855
|
Add a writing sample source.
|
|
49784
49856
|
On this device (signed-in CLI, reply pairs):
|
|
49785
49857
|
Gmail (zele) Outlook (outlook-api) Chat (tfa-memory)
|
|
49786
|
-
Server-side (--url
|
|
49787
|
-
X LinkedIn Facebook Instagram
|
|
49858
|
+
Server-side (--url):
|
|
49859
|
+
X LinkedIn Facebook Instagram
|
|
49788
49860
|
--dry-run print the samples as JSONL, store nothing
|
|
49789
49861
|
tfa-cli brand voice check [<channel>|--all] Can this device read the channel? tool, login, sample count
|
|
49790
49862
|
tfa-cli brand voice remove <channel>
|
|
@@ -49792,7 +49864,6 @@ Usage:
|
|
|
49792
49864
|
tfa-cli brand voice correct "<what is off>" Tell the learner what it got wrong; profile is updated
|
|
49793
49865
|
in one pass and the correction is kept for every re-learn
|
|
49794
49866
|
|
|
49795
|
-
--pasted-file - reads stdin. Delete is UI-only.
|
|
49796
49867
|
|
|
49797
49868
|
Questions the UI asks (keys for 'answers'):
|
|
49798
49869
|
"What makes you different from competitors?"
|
|
@@ -49892,7 +49963,7 @@ async function voiceDeviceCommand(rest, args) {
|
|
|
49892
49963
|
async function voiceCommand(api, projectId, rest, args) {
|
|
49893
49964
|
const [verb, ...vargs] = rest;
|
|
49894
49965
|
if (verb === "collect" && !vargs[0])
|
|
49895
|
-
fail("Usage: tfa-cli brand voice collect <channel> [--url U | --
|
|
49966
|
+
fail("Usage: tfa-cli brand voice collect <channel> [--url U | --account <page-id> | --max N] [--dry-run]");
|
|
49896
49967
|
if (verb === "answers") {
|
|
49897
49968
|
const answers = manualAnswersOf((await api.listVoiceSources(projectId)).sources);
|
|
49898
49969
|
if (vargs.length) {
|
|
@@ -49938,12 +50009,7 @@ ${DIM}match ${profile.match}/100 · source ${profile.source}${RESET}
|
|
|
49938
50009
|
}
|
|
49939
50010
|
if (verb === "collect") {
|
|
49940
50011
|
const channel = vargs[0];
|
|
49941
|
-
|
|
49942
|
-
if (args["pasted-file"]) {
|
|
49943
|
-
const { readFileSync: readFileSync3 } = await import("node:fs");
|
|
49944
|
-
pasted = readFileSync3(args["pasted-file"] === "-" ? 0 : args["pasted-file"], "utf8");
|
|
49945
|
-
}
|
|
49946
|
-
const onDevice = !pasted && !args.url && ADAPTERS[channel];
|
|
50012
|
+
const onDevice = !args.url && ADAPTERS[channel];
|
|
49947
50013
|
if (onDevice) {
|
|
49948
50014
|
const reason = checkChannel(channel);
|
|
49949
50015
|
if (reason)
|
|
@@ -49958,7 +50024,7 @@ ${DIM}match ${profile.match}/100 · source ${profile.source}${RESET}
|
|
|
49958
50024
|
`);
|
|
49959
50025
|
return;
|
|
49960
50026
|
}
|
|
49961
|
-
const { sources } = await api.collectVoiceSource(projectId, channel, { url: args.url,
|
|
50027
|
+
const { sources } = await api.collectVoiceSource(projectId, channel, { url: args.url, account: args.account });
|
|
49962
50028
|
process.stderr.write(`${GREEN}✅ ${channel} collected (${sources.length} source(s))${RESET}
|
|
49963
50029
|
`);
|
|
49964
50030
|
return;
|
|
@@ -56031,7 +56097,7 @@ class $ZodCyclicError extends Error {
|
|
|
56031
56097
|
this.name = "ZodCyclicError";
|
|
56032
56098
|
}
|
|
56033
56099
|
}
|
|
56034
|
-
var
|
|
56100
|
+
var STATE2 = "~memo";
|
|
56035
56101
|
var NO_ISSUES = [];
|
|
56036
56102
|
function isRef(value) {
|
|
56037
56103
|
return value !== null && typeof value === "object";
|
|
@@ -56241,10 +56307,10 @@ var memo = {
|
|
|
56241
56307
|
const input = payload.value;
|
|
56242
56308
|
if (!isRef(input))
|
|
56243
56309
|
return base(payload, ctx);
|
|
56244
|
-
let state = ctx[
|
|
56310
|
+
let state = ctx[STATE2];
|
|
56245
56311
|
if (!state) {
|
|
56246
56312
|
state = { buckets: new WeakMap, backEdges: undefined };
|
|
56247
|
-
ctx[
|
|
56313
|
+
ctx[STATE2] = state;
|
|
56248
56314
|
}
|
|
56249
56315
|
let bucket;
|
|
56250
56316
|
if (lastCtx === ctx) {
|
|
@@ -56293,7 +56359,7 @@ function memoizer() {
|
|
|
56293
56359
|
return memo;
|
|
56294
56360
|
}
|
|
56295
56361
|
function isBackEdge(ctx, value) {
|
|
56296
|
-
const backEdges = ctx[
|
|
56362
|
+
const backEdges = ctx[STATE2]?.backEdges;
|
|
56297
56363
|
return backEdges !== undefined && isRef(value) && backEdges.has(value);
|
|
56298
56364
|
}
|
|
56299
56365
|
// node_modules/zod/v4/locales/index.js
|
|
@@ -73532,53 +73598,124 @@ function protocolErrorResponse(error62) {
|
|
|
73532
73598
|
};
|
|
73533
73599
|
}
|
|
73534
73600
|
|
|
73601
|
+
// node_modules/@agentclientprotocol/sdk/dist/stream-limits.js
|
|
73602
|
+
var DEFAULT_MAX_MESSAGE_BYTES = 32 * 1024 * 1024;
|
|
73603
|
+
|
|
73604
|
+
class MessageTooLargeError extends Error {
|
|
73605
|
+
maxMessageBytes;
|
|
73606
|
+
constructor(maxMessageBytes) {
|
|
73607
|
+
super(`Incoming ACP data exceeds the configured ${maxMessageBytes} byte limit`);
|
|
73608
|
+
this.maxMessageBytes = maxMessageBytes;
|
|
73609
|
+
this.name = "MessageTooLargeError";
|
|
73610
|
+
}
|
|
73611
|
+
}
|
|
73612
|
+
function resolveMaxMessageBytes(value) {
|
|
73613
|
+
const maxMessageBytes = value ?? DEFAULT_MAX_MESSAGE_BYTES;
|
|
73614
|
+
if (!Number.isSafeInteger(maxMessageBytes) || maxMessageBytes <= 0) {
|
|
73615
|
+
throw new RangeError("maxMessageBytes must be a positive safe integer");
|
|
73616
|
+
}
|
|
73617
|
+
return maxMessageBytes;
|
|
73618
|
+
}
|
|
73619
|
+
|
|
73620
|
+
class MessageBuffer {
|
|
73621
|
+
#buffer = new Uint8Array(0);
|
|
73622
|
+
#length = 0;
|
|
73623
|
+
#maxMessageBytes;
|
|
73624
|
+
constructor(maxMessageBytes) {
|
|
73625
|
+
this.#maxMessageBytes = resolveMaxMessageBytes(maxMessageBytes);
|
|
73626
|
+
}
|
|
73627
|
+
get byteLength() {
|
|
73628
|
+
return this.#length;
|
|
73629
|
+
}
|
|
73630
|
+
get lastByte() {
|
|
73631
|
+
return this.#buffer[this.#length - 1];
|
|
73632
|
+
}
|
|
73633
|
+
#checkAppend(byteLength) {
|
|
73634
|
+
if (byteLength > this.#maxMessageBytes - this.#length) {
|
|
73635
|
+
this.clear();
|
|
73636
|
+
throw new MessageTooLargeError(this.#maxMessageBytes);
|
|
73637
|
+
}
|
|
73638
|
+
}
|
|
73639
|
+
append(bytes) {
|
|
73640
|
+
this.#checkAppend(bytes.byteLength);
|
|
73641
|
+
const length = this.#length + bytes.byteLength;
|
|
73642
|
+
if (length > this.#buffer.byteLength) {
|
|
73643
|
+
const capacity = Math.min(this.#maxMessageBytes, Math.max(length, this.#buffer.byteLength * 2, 1024));
|
|
73644
|
+
const buffer = new Uint8Array(capacity);
|
|
73645
|
+
buffer.set(this.#buffer.subarray(0, this.#length));
|
|
73646
|
+
this.#buffer = buffer;
|
|
73647
|
+
}
|
|
73648
|
+
this.#buffer.set(bytes, this.#length);
|
|
73649
|
+
this.#length = length;
|
|
73650
|
+
}
|
|
73651
|
+
take() {
|
|
73652
|
+
const bytes = this.#buffer.subarray(0, this.#length);
|
|
73653
|
+
this.clear();
|
|
73654
|
+
return bytes;
|
|
73655
|
+
}
|
|
73656
|
+
clear() {
|
|
73657
|
+
this.#buffer = new Uint8Array(0);
|
|
73658
|
+
this.#length = 0;
|
|
73659
|
+
}
|
|
73660
|
+
}
|
|
73661
|
+
|
|
73535
73662
|
// node_modules/@agentclientprotocol/sdk/dist/line-buffer.js
|
|
73536
73663
|
var newline = 10;
|
|
73537
73664
|
|
|
73538
73665
|
class LineBuffer {
|
|
73539
|
-
#pending
|
|
73540
|
-
|
|
73541
|
-
|
|
73666
|
+
#pending;
|
|
73667
|
+
#maxMessageBytes;
|
|
73668
|
+
constructor(maxMessageBytes) {
|
|
73669
|
+
this.#maxMessageBytes = resolveMaxMessageBytes(maxMessageBytes);
|
|
73670
|
+
this.#pending = new MessageBuffer(Math.min(Number.MAX_SAFE_INTEGER, this.#maxMessageBytes + 1));
|
|
73671
|
+
}
|
|
73672
|
+
*push(chunk) {
|
|
73542
73673
|
let start = 0;
|
|
73543
73674
|
let newlineIndex = chunk.indexOf(newline, start);
|
|
73544
73675
|
while (newlineIndex !== -1) {
|
|
73545
|
-
|
|
73676
|
+
yield this.#takeLine(chunk.subarray(start, newlineIndex));
|
|
73546
73677
|
start = newlineIndex + 1;
|
|
73547
73678
|
newlineIndex = chunk.indexOf(newline, start);
|
|
73548
73679
|
}
|
|
73549
73680
|
if (start < chunk.byteLength) {
|
|
73550
|
-
|
|
73681
|
+
const tail = chunk.subarray(start);
|
|
73682
|
+
this.#checkLine(tail);
|
|
73683
|
+
this.#pending.append(tail);
|
|
73551
73684
|
}
|
|
73552
|
-
return lines;
|
|
73553
73685
|
}
|
|
73554
73686
|
flush() {
|
|
73555
|
-
if (this.#pending.
|
|
73687
|
+
if (this.#pending.byteLength === 0) {
|
|
73556
73688
|
return;
|
|
73557
73689
|
}
|
|
73558
|
-
return this.#
|
|
73690
|
+
return stripCarriageReturn(this.#pending.take());
|
|
73691
|
+
}
|
|
73692
|
+
clear() {
|
|
73693
|
+
this.#pending.clear();
|
|
73559
73694
|
}
|
|
73560
73695
|
#takeLine(tail) {
|
|
73561
|
-
|
|
73562
|
-
|
|
73563
|
-
|
|
73564
|
-
let total = tail.byteLength;
|
|
73565
|
-
for (const part of this.#pending) {
|
|
73566
|
-
total += part.byteLength;
|
|
73696
|
+
this.#checkLine(tail);
|
|
73697
|
+
if (this.#pending.byteLength === 0) {
|
|
73698
|
+
return stripCarriageReturn(tail);
|
|
73567
73699
|
}
|
|
73568
|
-
|
|
73569
|
-
|
|
73570
|
-
|
|
73571
|
-
|
|
73572
|
-
|
|
73700
|
+
this.#pending.append(tail);
|
|
73701
|
+
return stripCarriageReturn(this.#pending.take());
|
|
73702
|
+
}
|
|
73703
|
+
#checkLine(tail) {
|
|
73704
|
+
const lastByte = tail.byteLength > 0 ? tail[tail.byteLength - 1] : this.#pending.lastByte;
|
|
73705
|
+
const byteLength = this.#pending.byteLength + tail.byteLength - (lastByte === 13 ? 1 : 0);
|
|
73706
|
+
if (byteLength > this.#maxMessageBytes) {
|
|
73707
|
+
this.clear();
|
|
73708
|
+
throw new MessageTooLargeError(this.#maxMessageBytes);
|
|
73573
73709
|
}
|
|
73574
|
-
line.set(tail, offset);
|
|
73575
|
-
this.#pending = [];
|
|
73576
|
-
return line;
|
|
73577
73710
|
}
|
|
73578
73711
|
}
|
|
73712
|
+
function stripCarriageReturn(line) {
|
|
73713
|
+
return line[line.byteLength - 1] === 13 ? line.subarray(0, -1) : line;
|
|
73714
|
+
}
|
|
73579
73715
|
|
|
73580
73716
|
// node_modules/@agentclientprotocol/sdk/dist/stream.js
|
|
73581
|
-
function ndJsonStream(output2, input2) {
|
|
73717
|
+
function ndJsonStream(output2, input2, options = {}) {
|
|
73718
|
+
const maxMessageBytes = resolveMaxMessageBytes(options.maxMessageBytes);
|
|
73582
73719
|
const textEncoder = new TextEncoder;
|
|
73583
73720
|
const textDecoder = new TextDecoder;
|
|
73584
73721
|
let cancelled = false;
|
|
@@ -73600,7 +73737,7 @@ function ndJsonStream(output2, input2) {
|
|
|
73600
73737
|
};
|
|
73601
73738
|
const readable = new ReadableStream({
|
|
73602
73739
|
async start(controller) {
|
|
73603
|
-
const lines = new LineBuffer;
|
|
73740
|
+
const lines = new LineBuffer(maxMessageBytes);
|
|
73604
73741
|
const enqueueLine = async (lineBytes) => {
|
|
73605
73742
|
const trimmedLine = textDecoder.decode(lineBytes).trim();
|
|
73606
73743
|
if (!trimmedLine) {
|
|
@@ -73652,8 +73789,10 @@ function ndJsonStream(output2, input2) {
|
|
|
73652
73789
|
return;
|
|
73653
73790
|
}
|
|
73654
73791
|
controller.error(err);
|
|
73792
|
+
reader.cancel(err).catch(() => {});
|
|
73655
73793
|
return;
|
|
73656
73794
|
} finally {
|
|
73795
|
+
lines.clear();
|
|
73657
73796
|
if (inputReader === reader) {
|
|
73658
73797
|
inputReader = undefined;
|
|
73659
73798
|
}
|
|
@@ -73695,8 +73834,8 @@ var zGuardCreateElicitationResponseCancel = object({
|
|
|
73695
73834
|
action: literal("cancel")
|
|
73696
73835
|
});
|
|
73697
73836
|
// node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
73698
|
-
function ndJsonStream2(output2, input2) {
|
|
73699
|
-
return ndJsonStream(output2, input2);
|
|
73837
|
+
function ndJsonStream2(output2, input2, options) {
|
|
73838
|
+
return ndJsonStream(output2, input2, options);
|
|
73700
73839
|
}
|
|
73701
73840
|
function emptyObjectResponse(response) {
|
|
73702
73841
|
return response ?? {};
|
|
@@ -75135,6 +75274,7 @@ try {
|
|
|
75135
75274
|
const pkgPath = path4.resolve(fileURLToPath(import.meta.url), "../../package.json");
|
|
75136
75275
|
checkForUpdates(JSON.parse(readFileSync3(pkgPath, "utf-8")));
|
|
75137
75276
|
} catch {}
|
|
75277
|
+
var aliasTodoId = (alias) => typeof alias === "string" && alias.includes(":") ? alias.slice(0, alias.indexOf(":")) : undefined;
|
|
75138
75278
|
function formatPathWithTilde(path5) {
|
|
75139
75279
|
const home = homedir3();
|
|
75140
75280
|
return path5.startsWith(home) ? path5.replace(home, "~") : path5;
|
|
@@ -75479,14 +75619,16 @@ async function main() {
|
|
|
75479
75619
|
const kind = it.url ? `url ${it.url}` : it.mime || "";
|
|
75480
75620
|
const card = it.cardRef ? ` card=${it.cardRef}` : "";
|
|
75481
75621
|
const link = it.display === "link" ? " link" : "";
|
|
75482
|
-
|
|
75622
|
+
const shared = it.shareUrl ? ` ${it.shareUrl}` : "";
|
|
75623
|
+
console.log(`${it.ref} ${it.title || it.filename || ""} ${kind}${card}${link}${shared}`);
|
|
75483
75624
|
}
|
|
75484
75625
|
return;
|
|
75485
75626
|
}
|
|
75486
|
-
|
|
75627
|
+
const showSub = positionals[1];
|
|
75628
|
+
if (positionals[0] === "show" && (showSub === "rm" || showSub === "share" || showSub === "unshare")) {
|
|
75487
75629
|
const arg = positionals[2];
|
|
75488
75630
|
if (!arg) {
|
|
75489
|
-
process.stderr.write(`${RED3}Usage: tfa-cli show
|
|
75631
|
+
process.stderr.write(`${RED3}Usage: tfa-cli show ${showSub} <ref|alias>${RESET2}
|
|
75490
75632
|
`);
|
|
75491
75633
|
process.exit(2);
|
|
75492
75634
|
}
|
|
@@ -75494,18 +75636,30 @@ async function main() {
|
|
|
75494
75636
|
const todoId = sep >= 0 ? arg.slice(0, sep) : getEnv("TODO_ID") || cfgScope.data.last_todo_id;
|
|
75495
75637
|
const key = sep >= 0 ? arg.slice(sep + 1) : arg;
|
|
75496
75638
|
if (!todoId || !key) {
|
|
75497
|
-
process.stderr.write(`${RED3}show
|
|
75639
|
+
process.stderr.write(`${RED3}show ${showSub}: need <todoId>:<alias> (no current todo)${RESET2}
|
|
75498
75640
|
`);
|
|
75499
75641
|
process.exit(2);
|
|
75500
75642
|
}
|
|
75501
|
-
|
|
75502
|
-
|
|
75643
|
+
if (showSub === "rm") {
|
|
75644
|
+
await api2.removeShow(todoId, key);
|
|
75645
|
+
process.stderr.write(`${GREEN2}\u2705 removed ${todoId}:${key}${RESET2}
|
|
75503
75646
|
`);
|
|
75647
|
+
} else if (showSub === "share") {
|
|
75648
|
+
const res = await api2.shareShow(todoId, key);
|
|
75649
|
+
if (args.json)
|
|
75650
|
+
console.log(JSON.stringify(res, null, 2));
|
|
75651
|
+
else
|
|
75652
|
+
console.log(res.url);
|
|
75653
|
+
} else {
|
|
75654
|
+
await api2.unshareShow(todoId, key);
|
|
75655
|
+
process.stderr.write(`${GREEN2}\u2705 ${todoId}:${key} is private again${RESET2}
|
|
75656
|
+
`);
|
|
75657
|
+
}
|
|
75504
75658
|
return;
|
|
75505
75659
|
}
|
|
75506
75660
|
if (positionals[0] === "show") {
|
|
75507
75661
|
const [, filePath, todoArg] = positionals;
|
|
75508
|
-
const todoId = todoArg || getEnv("TODO_ID") || cfgScope.data.last_todo_id;
|
|
75662
|
+
const todoId = todoArg || aliasTodoId(args.alias) || getEnv("TODO_ID") || cfgScope.data.last_todo_id;
|
|
75509
75663
|
if (!filePath || !todoId) {
|
|
75510
75664
|
process.stderr.write(`${RED3}Usage: tfa-cli show <file|-> [todo-id] [--title T] [--alias A] [--mime M] [--card <name>] [--link]${RESET2}
|
|
75511
75665
|
`);
|
|
@@ -75543,12 +75697,12 @@ async function main() {
|
|
|
75543
75697
|
if (args.json)
|
|
75544
75698
|
console.log(JSON.stringify(res, null, 2));
|
|
75545
75699
|
else
|
|
75546
|
-
console.log(res.
|
|
75700
|
+
console.log(res.shareUrl ? `${res.ref} ${res.shareUrl}` : res.ref);
|
|
75547
75701
|
return;
|
|
75548
75702
|
}
|
|
75549
75703
|
if (positionals[0] === "open") {
|
|
75550
75704
|
const [, url2, todoArg] = positionals;
|
|
75551
|
-
const todoId = todoArg || getEnv("TODO_ID") || cfgScope.data.last_todo_id;
|
|
75705
|
+
const todoId = todoArg || aliasTodoId(args.alias) || getEnv("TODO_ID") || cfgScope.data.last_todo_id;
|
|
75552
75706
|
if (!url2 || !todoId) {
|
|
75553
75707
|
process.stderr.write(`${RED3}Usage: tfa-cli open <url> [todo-id]${RESET2}
|
|
75554
75708
|
`);
|