@todoforai/cli 0.1.63 → 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 CHANGED
@@ -71,9 +71,11 @@ tfa-cli inbox # the bell: newest across all tabs
71
71
  tfa-cli inbox messages --unread # one filter: needs-you | messages | activity
72
72
  tfa-cli inbox seen # mark everything read
73
73
  tfa-cli notify "Deploy done" "v2 is live" --href /t/<todo-id> # note to YOUR user (Messages tab + phone push)
74
+ tfa-cli project members # who can be notified
75
+ tfa-cli notify --to anna@x.com "Review?" "PR is ready" --href /t/<todo-id> # note to ONE project member
74
76
  ```
75
77
 
76
- `notify` has no recipient option: it always goes to the user the key belongs to (never a teammate or other account), is shown as from the calling agent, delivers the same text once (`--subject` to control the dedupe key) and is capped at 10 new notes per day.
78
+ `notify` goes to your own user by default. `--to <email>` reaches one member of the current project (`--project <id>`, `$TODOFORAI_PROJECT_ID` or the default project); non-members are refused (404). It is shown as from you (or your agent). There is no broadcast / "all members" flag, so loop over `project members` to reach the whole team. `--subject` sets the dedupe key (the same text is delivered once), `--href` must be an in-app path. Caps: 10 new notes/day to yourself, 20/day to teammates.
77
79
 
78
80
  ## IDE integration (ACP)
79
81
 
@@ -44056,6 +44056,31 @@ var SERVER_TO_FRONTENDS = {
44056
44056
  }
44057
44057
  };
44058
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
+ }
44059
44084
  var MANUAL_CHANNEL = "Manual";
44060
44085
  function manualAnswersOf(sources) {
44061
44086
  const manual = sources?.find((s) => s.channel === MANUAL_CHANNEL);
@@ -44592,6 +44617,7 @@ var tool_catalog_default = {
44592
44617
  pkg: "zele",
44593
44618
  installer: "npm",
44594
44619
  label: "Gmail",
44620
+ voiceChannel: "Gmail",
44595
44621
  summary: "Read and send Gmail from your own account.",
44596
44622
  statusCmd: "zele whoami 2>/dev/null | grep -o 'email: *[^ ]*' | tr -d ' ' | paste -sd ' ' - | grep -m1 .",
44597
44623
  loginNeedsPty: true,
@@ -44627,6 +44653,7 @@ var tool_catalog_default = {
44627
44653
  pkg: "@xdevplatform/xurl",
44628
44654
  installer: "npm",
44629
44655
  label: "X",
44656
+ voiceChannel: "X",
44630
44657
  summary: "Post to X and read timelines, replies and DMs.",
44631
44658
  statusCmd: `xurl whoami 2>&1 | sed -n 's/.*"username"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
44632
44659
  loginCmd: "xurl auth oauth2",
@@ -44645,6 +44672,7 @@ var tool_catalog_default = {
44645
44672
  pkg: "@todoforai/linkedin-api",
44646
44673
  installer: "npm",
44647
44674
  label: "LinkedIn",
44675
+ voiceChannel: "LinkedIn",
44648
44676
  summary: "Read LinkedIn profiles and send messages and connection requests.",
44649
44677
  statusCmd: `linkedin-api whoami 2>/dev/null | sed -n 's/.*"publicId"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
44650
44678
  loginCmd: "linkedin-api auth <li_at> <jsessionid>",
@@ -44673,6 +44701,7 @@ var tool_catalog_default = {
44673
44701
  pkg: "slack-cli",
44674
44702
  installer: "binary",
44675
44703
  label: "Slack",
44704
+ voiceChannel: "Slack",
44676
44705
  summary: "Work with Slack workspaces and apps.",
44677
44706
  statusCmd: "slack-cli auth list 2>&1 | grep 'Team' >/dev/null && echo authenticated",
44678
44707
  loginCmd: "slack-cli login",
@@ -45838,6 +45867,7 @@ var tool_catalog_default = {
45838
45867
  pkg: "@todoforai/facebook-pages-api",
45839
45868
  installer: "npm",
45840
45869
  label: "Facebook Pages",
45870
+ voiceChannel: "Facebook",
45841
45871
  summary: "Post to your Facebook Page and handle comments.",
45842
45872
  statusCmd: `facebook-pages-api whoami 2>/dev/null | sed -n 's/.*"name"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
45843
45873
  loginCmd: "facebook-pages-api auth --page-id <id> --page-token <token>",
@@ -45866,6 +45896,7 @@ var tool_catalog_default = {
45866
45896
  pkg: "@todoforai/outlook-api",
45867
45897
  installer: "npm",
45868
45898
  label: "Outlook (Graph)",
45899
+ voiceChannel: "Outlook",
45869
45900
  summary: "Read and write your Outlook mail.",
45870
45901
  statusCmd: `outlook-api whoami 2>/dev/null | sed -n 's/.*"userPrincipalName"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' | grep -m10 .`,
45871
45902
  loginCmd: "outlook-api auth",
@@ -46349,7 +46380,7 @@ var package_default = {
46349
46380
  type: "git",
46350
46381
  url: "git+https://github.com/todoforai/cli.git"
46351
46382
  },
46352
- version: "0.1.63",
46383
+ version: "0.1.64",
46353
46384
  type: "module",
46354
46385
  bin: {
46355
46386
  "todoforai-cli": "bin/todoforai-cli.js",
@@ -50158,8 +50189,9 @@ ${profile.profile}
50158
50189
  ${DIM}match ${profile.match}/100 · source ${profile.source}${RESET}
50159
50190
  ` : `${DIM}(no voice learned yet)${RESET}
50160
50191
  `);
50161
- for (const s of sources)
50162
- process.stderr.write(` ${s.channel}${s.account ? ` ${s.label} ${DIM}(${s.account})${RESET}` : ""} ${DIM}${s.posts ?? "?"} posts · ${s.chars ?? "?"} chars${RESET}
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}
50163
50195
  `);
50164
50196
  return;
50165
50197
  }
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/todoforai/cli.git"
8
8
  },
9
- "version": "0.1.63",
9
+ "version": "0.1.64",
10
10
  "type": "module",
11
11
  "bin": {
12
12
  "todoforai-cli": "bin/todoforai-cli.js",