@todoforai/cli 0.1.56 → 0.1.57
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 +51 -17
- package/package.json +1 -1
package/dist/todoforai-cli.js
CHANGED
|
@@ -42939,6 +42939,12 @@ class ApiClient {
|
|
|
42939
42939
|
sendFeedMessage(msg) {
|
|
42940
42940
|
return this.request("POST", "/api/v1/feed/message", msg);
|
|
42941
42941
|
}
|
|
42942
|
+
getProjectMembers(projectId) {
|
|
42943
|
+
return this.request("GET", `/api/v1/projects/${projectId}/members`);
|
|
42944
|
+
}
|
|
42945
|
+
sendMemberMessage(msg) {
|
|
42946
|
+
return this.request("POST", "/api/v1/feed/message/member", msg);
|
|
42947
|
+
}
|
|
42942
42948
|
listProjectSurfaces(projectId) {
|
|
42943
42949
|
return this.request("GET", `/api/v1/projects/${projectId}/surfaces`);
|
|
42944
42950
|
}
|
|
@@ -43882,7 +43888,7 @@ function manualAnswersOf(sources) {
|
|
|
43882
43888
|
return out;
|
|
43883
43889
|
}
|
|
43884
43890
|
var manualSamples = (answers) => Object.entries(answers).filter(([, a]) => a.trim()).map(([prompt, text]) => ({ prompt, text: text.trim() }));
|
|
43885
|
-
var senderLabel = (s) => s.kind === "team" ? `${s.name} · TODO for AI team` : `${s.name} · your agent`;
|
|
43891
|
+
var senderLabel = (s) => s.kind === "team" ? `${s.name} · TODO for AI team` : s.kind === "member" ? `${s.name} · teammate` : `${s.name} · your agent`;
|
|
43886
43892
|
// ../packages/shared-fbe/src/templateBody.ts
|
|
43887
43893
|
var USER_HEADINGS = new Set([
|
|
43888
43894
|
"your task",
|
|
@@ -44861,7 +44867,7 @@ var tool_catalog_default = {
|
|
|
44861
44867
|
installer: "npm",
|
|
44862
44868
|
label: "TODOforAI",
|
|
44863
44869
|
summary: "Create and follow up on your TODOs, and show results in the chat.",
|
|
44864
|
-
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
|
|
44870
|
+
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.',
|
|
44865
44871
|
installCmd: "npm install -g @todoforai/cli",
|
|
44866
44872
|
versionCmd: "tfa-cli --version 2>/dev/null | sed -n 1p",
|
|
44867
44873
|
preinstallCloud: true,
|
|
@@ -44987,7 +44993,8 @@ var tool_catalog_default = {
|
|
|
44987
44993
|
installer: "system",
|
|
44988
44994
|
label: "Google Cloud",
|
|
44989
44995
|
summary: "Manage your Google Cloud projects and services.",
|
|
44990
|
-
|
|
44996
|
+
needsPython: true,
|
|
44997
|
+
installCmd: `curl -fsSL https://dl.google.com/dl/cloudsdk/channels/rapid/google-cloud-sdk.tar.gz | tar -xzC "$HOME" && CLOUDSDK_PYTHON="$py" "$HOME/google-cloud-sdk/install.sh" --quiet --install-python false --usage-reporting false --path-update false --command-completion false && 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"`,
|
|
44991
44998
|
statusCmd: `gcloud auth list --filter=status:ACTIVE --format="value(account)" 2>/dev/null | tr -d '\\r' | grep -m1 .`,
|
|
44992
44999
|
loginCmd: "gcloud auth login --no-launch-browser",
|
|
44993
45000
|
loginNeedsPty: true,
|
|
@@ -46116,7 +46123,7 @@ import { parseArgs } from "util";
|
|
|
46116
46123
|
// package.json
|
|
46117
46124
|
var package_default = {
|
|
46118
46125
|
name: "@todoforai/cli",
|
|
46119
|
-
version: "0.1.
|
|
46126
|
+
version: "0.1.57",
|
|
46120
46127
|
type: "module",
|
|
46121
46128
|
bin: {
|
|
46122
46129
|
"todoforai-cli": "bin/todoforai-cli.js",
|
|
@@ -46186,7 +46193,7 @@ Examples:
|
|
|
46186
46193
|
tfa-cli recommend --template <id> # Add a template as a recommendation card
|
|
46187
46194
|
tfa-cli inbox [needs-you|messages|activity] [--unread] # Read the notification feed (the bell)
|
|
46188
46195
|
tfa-cli inbox seen [tab] # Mark notifications read
|
|
46189
|
-
tfa-cli notify "Title" "message" [--href /t/<id>] # Note to
|
|
46196
|
+
tfa-cli notify [--to <email>] "Title" "message" [--href /t/<id>] # Note to your own user, or --to a project member (Messages tab + phone push)
|
|
46190
46197
|
tfa-cli claim mint --seed <projectId> [--emails a@x,b@y] [--ttl <sec>] # Mint /claim/<token> links for a project you own
|
|
46191
46198
|
tfa-cli next [--direction "<text>"] # Analyzer growth recommendation cards
|
|
46192
46199
|
tfa-cli <command> help # Details per command
|
|
@@ -46304,6 +46311,7 @@ function parseCliArgs() {
|
|
|
46304
46311
|
ttl: { type: "string" },
|
|
46305
46312
|
subject: { type: "string" },
|
|
46306
46313
|
href: { type: "string" },
|
|
46314
|
+
to: { type: "string" },
|
|
46307
46315
|
unread: { type: "boolean", default: false },
|
|
46308
46316
|
limit: { type: "string" },
|
|
46309
46317
|
resume: { type: "string", short: "r" },
|
|
@@ -49524,6 +49532,7 @@ tfa-cli project — edit the current project
|
|
|
49524
49532
|
|
|
49525
49533
|
Usage:
|
|
49526
49534
|
tfa-cli project list Projects you can access (* = default)
|
|
49535
|
+
tfa-cli project members Who is on it (notify --to <email> reaches them)
|
|
49527
49536
|
tfa-cli project set <field=value>… name=… description=…
|
|
49528
49537
|
(isPublic refused from an agent shell)
|
|
49529
49538
|
tfa-cli project default Make it the project you land on at /
|
|
@@ -49625,6 +49634,17 @@ async function projectCommand(api, positionals, args, projectId) {
|
|
|
49625
49634
|
}
|
|
49626
49635
|
if (!projectId)
|
|
49627
49636
|
fail(NO_PROJECT);
|
|
49637
|
+
if (sub === "members") {
|
|
49638
|
+
const members = await api.getProjectMembers(projectId);
|
|
49639
|
+
if (args.json) {
|
|
49640
|
+
console.log(JSON.stringify(members, null, 2));
|
|
49641
|
+
return;
|
|
49642
|
+
}
|
|
49643
|
+
for (const m of members)
|
|
49644
|
+
process.stderr.write(` ${m.name ?? ""} ${m.email ?? ""} ${DIM}${m.id}${RESET}
|
|
49645
|
+
`);
|
|
49646
|
+
return;
|
|
49647
|
+
}
|
|
49628
49648
|
if (sub === "set") {
|
|
49629
49649
|
if (!rest.length)
|
|
49630
49650
|
fail("Usage: tfa-cli project set <field=value>…");
|
|
@@ -50557,16 +50577,19 @@ Filters (same as the bell's chips):
|
|
|
50557
50577
|
}
|
|
50558
50578
|
function printNotifyHelp() {
|
|
50559
50579
|
process.stderr.write(`
|
|
50560
|
-
tfa-cli notify — leave a note
|
|
50580
|
+
tfa-cli notify — leave a note in someone's Messages inbox (+ phone push)
|
|
50561
50581
|
|
|
50562
50582
|
Usage:
|
|
50563
50583
|
tfa-cli notify "Title" "message" [--href /t/<todo-id>] [--subject <key>] [--json]
|
|
50584
|
+
tfa-cli notify --to <email> "Title" "message" [--project <id>]
|
|
50564
50585
|
echo "message" | tfa-cli notify "Title"
|
|
50565
50586
|
|
|
50566
|
-
Recipient:
|
|
50567
|
-
|
|
50587
|
+
Recipient: your own user by default. --to <email> reaches a TEAMMATE: someone who is a member
|
|
50588
|
+
of the current project (--project, $TODOFORAI_PROJECT_ID or your default), shown as from you.
|
|
50589
|
+
Anyone else is refused. List them with: tfa-cli project members
|
|
50568
50590
|
--subject dedupes: the same subject is delivered once (default: hash of title+message,
|
|
50569
|
-
so a retry never double-notifies). --href must be an in-app path.
|
|
50591
|
+
so a retry never double-notifies). --href must be an in-app path.
|
|
50592
|
+
Limits: 10 notes/day to yourself, 20/day to teammates.
|
|
50570
50593
|
`);
|
|
50571
50594
|
}
|
|
50572
50595
|
function tierArg(name) {
|
|
@@ -50618,12 +50641,22 @@ async function inboxCommand(api, positionals, args) {
|
|
|
50618
50641
|
console.log(` ${DIM}${e.href}${RESET}`);
|
|
50619
50642
|
}
|
|
50620
50643
|
}
|
|
50621
|
-
var
|
|
50622
|
-
async function notifyCommand(api, positionals, args) {
|
|
50623
|
-
const
|
|
50624
|
-
const bad = argv.find((a) => RECIPIENT_FLAGS.some((f) => a === f || a.startsWith(`${f}=`)));
|
|
50644
|
+
var OTHER_RECIPIENT_FLAGS = ["--email", "--user", "--recipient", "--cc"];
|
|
50645
|
+
async function notifyCommand(api, positionals, args, projectId) {
|
|
50646
|
+
const bad = process.argv.slice(2).find((a) => OTHER_RECIPIENT_FLAGS.some((f) => a === f || a.startsWith(`${f}=`)));
|
|
50625
50647
|
if (bad) {
|
|
50626
|
-
process.stderr.write(`${RED}
|
|
50648
|
+
process.stderr.write(`${RED}Unknown option ${bad.split("=")[0]}: use --to <email> for a project teammate${RESET}
|
|
50649
|
+
`);
|
|
50650
|
+
process.exit(2);
|
|
50651
|
+
}
|
|
50652
|
+
const to = args.to === undefined ? undefined : String(args.to).trim();
|
|
50653
|
+
if (to === "") {
|
|
50654
|
+
process.stderr.write(`${RED}--to is empty: pass a teammate's email, or drop --to to notify your own user${RESET}
|
|
50655
|
+
`);
|
|
50656
|
+
process.exit(2);
|
|
50657
|
+
}
|
|
50658
|
+
if (to && !projectId) {
|
|
50659
|
+
process.stderr.write(`${RED}--to needs a project: pass --project <id> (the recipient must be a member of it)${RESET}
|
|
50627
50660
|
`);
|
|
50628
50661
|
process.exit(2);
|
|
50629
50662
|
}
|
|
@@ -50635,12 +50668,13 @@ async function notifyCommand(api, positionals, args) {
|
|
|
50635
50668
|
}
|
|
50636
50669
|
const subject = args.subject || createHash("sha256").update(`${title}
|
|
50637
50670
|
${message}`).digest("hex").slice(0, 16);
|
|
50638
|
-
const
|
|
50671
|
+
const msg = { subject, title, message, ...args.href ? { href: String(args.href) } : {} };
|
|
50672
|
+
const row = await (to ? api.sendMemberMessage({ ...msg, projectId, to }) : api.sendFeedMessage(msg));
|
|
50639
50673
|
if (args.json) {
|
|
50640
50674
|
console.log(JSON.stringify(row));
|
|
50641
50675
|
return;
|
|
50642
50676
|
}
|
|
50643
|
-
process.stderr.write(row.created !== false ? `${GREEN}✅ Delivered to your own user's Messages inbox
|
|
50677
|
+
process.stderr.write(row.created !== false ? `${GREEN}✅ Delivered to ${to ?? "your own user"}'s Messages inbox${RESET} ${DIM}(subject ${subject})${RESET}
|
|
50644
50678
|
` : `${DIM}Already sent (subject ${subject}) — nothing new delivered${RESET}
|
|
50645
50679
|
`);
|
|
50646
50680
|
}
|
|
@@ -75353,7 +75387,7 @@ async function main() {
|
|
|
75353
75387
|
return;
|
|
75354
75388
|
}
|
|
75355
75389
|
if (positionals[0] === "notify") {
|
|
75356
|
-
await notifyCommand(api2, positionals, args);
|
|
75390
|
+
await notifyCommand(api2, positionals, args, scopedProject);
|
|
75357
75391
|
return;
|
|
75358
75392
|
}
|
|
75359
75393
|
if (positionals[0] === "delete") {
|