@todoforai/cli 0.1.72 → 0.1.73

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.
@@ -43281,6 +43281,10 @@ class ApiClient {
43281
43281
  const { projectId, ...body } = input;
43282
43282
  return this.request("POST", `/api/v1/projects/${projectId}/recommendations`, body);
43283
43283
  }
43284
+ async feedIgnore(input) {
43285
+ const { projectId, ...body } = input;
43286
+ return this.request("POST", `/api/v1/projects/${projectId}/feed/ignored`, body);
43287
+ }
43284
43288
  async getRegistrySpec(specId) {
43285
43289
  const base = this.apiUrl.replace(/\/api\/v1\/?$/, "").replace(/\/$/, "");
43286
43290
  const res = await fetch(`${base}/cookie/v1/registry/templates/${specId}`);
@@ -44637,32 +44641,15 @@ To materialize growth recommendations, propose todos on the project board. A pro
44637
44641
 
44638
44642
  Exactly ONE \`api_recommend_template\` call per proposal: it carries both what the todo is and where it lands on the board.
44639
44643
 
44640
- 1. WHAT IT IS. Pass \`name\` + \`body\`, written for THIS business, and optionally \`description\`, \`short\` and \`categories\`.
44644
+ 1. WHAT IT IS. Pass \`name\`, \`description\` and \`body\`, written for THIS business.
44641
44645
  - Reuse an existing registry template instead ONLY when it already fits this business closely with no meaningful edits: pass its id as \`templateId\` and omit \`name\`/\`body\`. If it needs tailoring, write yours inline. Do not recommend a generic playbook that ignores this company's specifics.
44642
44646
 
44643
- Language: match the business. Write user-facing text such as names, bodies and notes in the language the company itself communicates in. When the company is international or unclear, use English. Only the frame stays in English. The heading lines \`Your task:\`, \`Steps:\` and \`Data needed:\` are parsed, so keep them exactly as-is. Everything else follows the business's language.
44644
-
44645
- The body is read by a PERSON deciding whether to run it, so it must be understandable at a glance. The executing agent is capable and has the business context at run time, so it will elaborate and figure out the details itself. Write a minimal brief, not a playbook. Include ONLY what the agent could not figure out on its own: the business-specific direction such as company, competitor, segment, channel and the metric to move, plus any hard constraint. Cut everything else, including background, caveats, generic how-to and restated context.
44646
-
44647
- Hard limits: body ≤80 words total. One sentence of persona. One-sentence task. 2-4 steps, each a short fragment of at most 8 words naming WHAT, not how. Data needed is a comma-separated list. If a sentence wouldn't change what the agent does, delete it.
44648
-
44649
- \`name\`: 3-6 words, action-first like "Win Reddit comparison threads", with no company name prefix. Give \`description\` and \`short\` one tight sentence each.
44647
+ A person reads it at a glance and decides whether to run it, so use as few words as possible. The executing agent is capable, reads the business context at run time and asks for anything it is missing, so give no steps, no list of inputs and no background.
44648
+ - \`name\`: 3-6 words, action-first like "Win Reddit comparison threads", with no company name prefix.
44649
+ - \`description\`: one plain sentence of at most 15 words saying what the user gets, such as "Three vs-Gmail pages, drafted and ready to publish." Never repeat the name.
44650
+ - \`body\`: one sentence naming the expert to act as, such as "You are an SEO writer for email products." Nothing else: no headings, no task, no steps.
44650
44651
 
44651
- Example body at the right density (adapt specifics, keep the brevity):
44652
- "You are a B2B outbound specialist for dev-tool companies.
44653
- Your task:
44654
- Land Acme in 10 agency partner conversations this month.
44655
- Steps:
44656
- - Shortlist 30 EU automation agencies
44657
- - Draft one-line personalized openers
44658
- - Send, track replies in a sheet
44659
- Data needed:
44660
- Acme pricing page, current partner list, founder's LinkedIn"
44661
-
44662
- Body structure (REQUIRED). The body is split into the agent's system prompt and the first user turn by section headings, so follow this exactly:
44663
- - Start with the persona, expertise and any Rules as plain prose at the top with no heading. This becomes the agent's system prompt.
44664
- - Then write the request using these exact standalone heading lines, letters only, each on its own line and ending with a colon: \`Your task:\`, \`Steps:\`, \`Data needed:\`. Everything under these headings becomes the first user turn.
44665
- - Headings must match exactly or the split breaks. Write \`Your task:\`, not \`Your task (SEO):\`. Put the business-specific detail in the body text under each heading, never in the heading itself.
44652
+ Language: write the name, description, body and note in the language the company itself communicates in. When the company is international or unclear, use English.
44666
44653
 
44667
44654
  2. WHERE IT LANDS, in that same call. It becomes a PROPOSED todo on the project and never a running todo:
44668
44655
  Give it a one-line \`note\` of roughly 15 words at most giving the WHY for THIS business, which becomes the proposal's tooltip, a \`priority\` of high, medium or low. Leave \`group\` empty: proposals land on the board without a group, and you never create, rename or archive groups. Project and business context default to the current session, so pass them only when targeting a different one. The proposal appears as a ✧ row on the board for the user to review before any credits are spent. Re-proposing the same \`templateId\` refreshes that open proposal instead of duplicating it. An inline proposal is always a new one, so check the board you just read before repeating a move that is already there. Dismissed proposals since your last run are fed back to you. Don't re-propose those, steer elsewhere.
@@ -50445,7 +50432,7 @@ var package_default = {
50445
50432
  type: "git",
50446
50433
  url: "git+https://github.com/todoforai/cli.git"
50447
50434
  },
50448
- version: "0.1.72",
50435
+ version: "0.1.73",
50449
50436
  type: "module",
50450
50437
  bin: {
50451
50438
  "todoforai-cli": "bin/todoforai-cli.js",
@@ -50515,6 +50502,7 @@ Examples:
50515
50502
  tfa-cli open <url> [todo-id] # Live url preview in the chat
50516
50503
  tfa-cli connect <key>… [--reason "why"] # Sign-in card for connectors on this machine (several keys = one choice)
50517
50504
  tfa-cli recommend --template <id> | --title "…" [--info] [--source "label|ref|url"] # ✧ proposal card, or an ⓘ info row
50505
+ tfa-cli ignore --title "…" [--source "label|ref|url|from"] [--note "why"] # Log an inbound item as noise (folded under the Feed card)
50518
50506
  tfa-cli inbox [needs-you|messages|activity] [--unread] # Read the notification feed (the bell)
50519
50507
  tfa-cli inbox seen [tab] # Mark notifications read
50520
50508
  tfa-cli notify [--to <email>] "Title" "message" [--href /t/<id>] [--url <link>] # Note to your own user, or --to a project member (Messages tab + phone push)
@@ -80418,6 +80406,28 @@ async function main() {
80418
80406
  console.log(res.ref);
80419
80407
  return;
80420
80408
  }
80409
+ if (positionals[0] === "ignore") {
80410
+ const title = args.title?.trim();
80411
+ if (!title) {
80412
+ process.stderr.write(`${RED3}Usage: tfa-cli ignore --title "..." [--source "label|ref|url|from"] [--note "why"] [--project <id>]${RESET2}
80413
+ `);
80414
+ process.exit(2);
80415
+ }
80416
+ const source = args.source ? (() => {
80417
+ const [label, ref, url2, from] = String(args.source).split("|");
80418
+ return label && ref ? { label, ref, ...url2 ? { url: url2 } : {}, ...from ? { from } : {} } : undefined;
80419
+ })() : undefined;
80420
+ const projectId2 = args.project || getEnv("PROJECT_ID") || cfgScope.data.default_project_id;
80421
+ if (!projectId2) {
80422
+ process.stderr.write(`${RED3}No project found \u2014 pass --project <id>${RESET2}
80423
+ `);
80424
+ process.exit(2);
80425
+ }
80426
+ await api2.feedIgnore({ projectId: projectId2, title, ...source ? { source } : {}, ...args.note ? { why: args.note } : {} });
80427
+ process.stderr.write(`${DIM2}ignored: ${title}${RESET2}
80428
+ `);
80429
+ return;
80430
+ }
80421
80431
  if (positionals[0] === "recommend") {
80422
80432
  const templateId = args.template || positionals[1];
80423
80433
  const inlineTitle = !templateId && args.title?.trim();
@@ -80457,7 +80467,15 @@ async function main() {
80457
80467
  }
80458
80468
  const rec = await api2.recommend({
80459
80469
  projectId: projectId2,
80460
- ...templateId ? { specId: templateId } : { template: { name: inlineTitle, body: args.note || inlineTitle } },
80470
+ ...templateId ? { specId: templateId } : { template: {
80471
+ name: inlineTitle,
80472
+ description: args.note || (source ? `From ${source.label}` : inlineTitle),
80473
+ body: `Handle this item: ${inlineTitle}${args.note ? `
80474
+
80475
+ ${args.note}` : ""}${source?.url ? `
80476
+
80477
+ Original: ${source.url}` : ""}`
80478
+ } },
80461
80479
  ...args.info ? { todoKind: "info" } : {},
80462
80480
  ...source ? { source } : {},
80463
80481
  ...args.title ? { title: args.title } : {},
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/todoforai/cli.git"
9
9
  },
10
- "version": "0.1.72",
10
+ "version": "0.1.73",
11
11
  "type": "module",
12
12
  "bin": {
13
13
  "todoforai-cli": "bin/todoforai-cli.js",