@tendrilapp/cli 0.1.46 → 0.1.47

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.
Files changed (2) hide show
  1. package/dist/tendril.js +44 -7
  2. package/package.json +1 -1
package/dist/tendril.js CHANGED
@@ -9188,7 +9188,12 @@ function figmaRestCheck() {
9188
9188
  return {
9189
9189
  name: "figma-rest",
9190
9190
  ok: true,
9191
- detail: `Figma is not connected for REST recording \u2014 large component sets then pay the MCP daily call quota. Run ${tendrilCommand("figma-connect")} and click Allow once (agents: the tendril_figma_connect tool).`
9191
+ // ok stays true recording works without it but the field
9192
+ // taught that agents scan flags, not prose: the how-to rides the
9193
+ // remediation channel so a not-connected machine is never a
9194
+ // silently green row (first Windows channel run, 2026-08-26).
9195
+ detail: "Figma is not connected for REST recording on this machine \u2014 large component sets then pay the MCP daily call quota (informational; recording still works)",
9196
+ remediation: `Connect once and the quota problem disappears for pixels+geometry: ${tendrilCommand("figma-connect")}, one Allow click in the browser (agents: tendril_figma_connect, relay the link, then tendril_figma_connect_wait).`
9192
9197
  };
9193
9198
  }
9194
9199
  const daysLeft = Math.floor((Date.parse(tokens.tokenExpiresAt) - Date.now()) / 864e5);
@@ -14893,7 +14898,10 @@ async function runRecordPlan(opts) {
14893
14898
  const restClause = channeled ? ` REST channel active: ~${restRequests} paced REST request(s) + ${restRepsRemaining} unmetered downloads carry the pixels+geometry \u2014 they spend NO MCP quota.` : "";
14894
14899
  const callSentence = channeled ? `${posesRemaining} pose(s) still need their MCP emission call${setLevelClause} = ${callsNeeded} Figma MCP calls` : posesRemaining === poses ? `${poses} poses \xD7 ${FIGMA_CALLS_PER_REP} calls per pose${setLevelClause} = ${callsNeeded} Figma calls` : `${posesRemaining} poses still to record \xD7 ${FIGMA_CALLS_PER_REP} calls per pose${setLevelClause} = ${callsNeeded} Figma calls (${poses - posesRemaining} of ${poses} already on disk)`;
14895
14900
  const planningSpent = variantScope === "selection" ? poses : 1;
14896
- const arithmetic = `${callSentence}${channeled ? "." : ` (up to ${posesRemaining * FIGMA_CALLS_PER_REP_WORST + setLevelRemaining} if screenshots or assets need a second fetch).`}${restClause} ALREADY SPENT on planning, and counting against the same allowance: ~${planningSpent} get_metadata call(s)${variantScope === "selection" ? " \u2014 a selection-scoped plan pays one per node handed in, not one for the set" : ""}.`;
14901
+ const connectWouldHelp = channelNote?.reason === "no-credential";
14902
+ const callsIfConnected = posesRemaining + setLevelRemaining + 4;
14903
+ const connectDelta = connectWouldHelp ? ` CONNECT FIGMA AND THIS DROPS TO ~${callsIfConnected}: one Allow click (tendril_figma_connect) puts pixels+geometry on Figma REST \u2014 per-minute paced, no daily cap \u2014 then re-run this exact plan.` : "";
14904
+ const arithmetic = `${callSentence}${channeled ? "." : ` (up to ${posesRemaining * FIGMA_CALLS_PER_REP_WORST + setLevelRemaining} if screenshots or assets need a second fetch).`}${restClause}${connectDelta} ALREADY SPENT on planning, and counting against the same allowance: ~${planningSpent} get_metadata call(s)${variantScope === "selection" ? " \u2014 a selection-scoped plan pays one per node handed in, not one for the set" : ""}.`;
14897
14905
  const multiDay = callsNeeded > MULTI_DAY_CALL_THRESHOLD;
14898
14906
  const feasibilityCheck = {
14899
14907
  arithmetic,
@@ -14906,6 +14914,20 @@ async function runRecordPlan(opts) {
14906
14914
  surface: multiDay ? "This set exceeds every daily allowance we have heard of, so it CANNOT finish in one day. State the verdict to the user in plain numbers BEFORE recording anything and let them choose from `options` \u2014 do not start on the assumption it will fit." : "Say nothing about cost if the division fits inside one day's allowance \u2014 a set that comfortably fits is not worth the user's attention. Surface the verdict and `options` only when it does not fit.",
14907
14915
  verdictTemplate: `${callSentence}. Your <seat> seat on <plan> allows <allowance>/day. This set needs about <days> day(s) at that rate.`,
14908
14916
  options: [
14917
+ // CONNECT FIRST (measured on the first field run of the REST
14918
+ // channel, 2026-08-26): the plan's restChannel note said "not
14919
+ // connected" while these options offered only ways to pay the
14920
+ // full MCP bill — the agent dutifully rendered pace/sample/seat
14921
+ // and never mentioned the one click that removes the problem.
14922
+ // The remedy that dissolves the bill outranks the ones that
14923
+ // ration it, so it is option ONE, present whenever it applies.
14924
+ ...!channeled && connectWouldHelp ? [
14925
+ {
14926
+ id: "connect-figma",
14927
+ decidedBy: "user clicks Allow once in the browser \u2014 and you START it: call tendril_figma_connect, relay the link, tendril_figma_connect_wait",
14928
+ text: `Connect Figma on this machine (read-only, revocable, one Allow click). Pixels+geometry then travel over Figma's REST API \u2014 per-minute paced, NO daily cap \u2014 and this set's MCP bill drops from ${callsNeeded} to ~${callsIfConnected} calls. After the connect completes, RE-RUN THIS EXACT PLAN: the channel is assignable until the first envelope is ingested.`
14929
+ }
14930
+ ] : [],
14909
14931
  {
14910
14932
  id: "pace",
14911
14933
  decidedBy: "user, and you can carry it out",
@@ -14986,11 +15008,15 @@ async function runRecordPlan(opts) {
14986
15008
  `);
14987
15009
  process.stdout.write(` ask Figma whoami (free \u2014 exempt from tool-call limits) for this seat's daily allowance, divide ${callsNeeded} by it, and say how many DAYS this needs before recording
14988
15010
  `);
14989
- process.stdout.write(` (a) pace it across days \u2014 the set persists after every pose, so a rate limit costs waiting, never recorded work
15011
+ if (connectWouldHelp) {
15012
+ process.stdout.write(` (a) CONNECT FIGMA \u2014 one Allow click (\`${tendrilCommand("figma-connect")}\`) drops this set to ~${callsIfConnected} calls, then re-run this exact plan
15013
+ `);
15014
+ }
15015
+ process.stdout.write(` (${connectWouldHelp ? "b" : "a"}) pace it across days \u2014 the set persists after every pose, so a rate limit costs waiting, never recorded work
14990
15016
  `);
14991
- process.stdout.write(` (b) record fewer poses \u2014 YOUR call, not an agent's: delete recording-set.json and re-plan with --sample (buys calls with coverage)
15017
+ process.stdout.write(` (${connectWouldHelp ? "c" : "b"}) record fewer poses \u2014 YOUR call, not an agent's: delete recording-set.json and re-plan with --sample (buys calls with coverage)
14992
15018
  `);
14993
- process.stdout.write(` (c) a seat or plan with a larger daily allowance
15019
+ process.stdout.write(` (${connectWouldHelp ? "d" : "c"}) a seat or plan with a larger daily allowance
14994
15020
  `);
14995
15021
  } else {
14996
15022
  process.stdout.write(`FEASIBILITY: check ${callsNeeded} against this seat's daily Figma allowance (ask whoami \u2014 it is free) before recording; it only needs raising if it does not fit
@@ -15053,11 +15079,22 @@ async function assignRestChannel(setDir, manifest, resumed) {
15053
15079
  if (anything) return void 0;
15054
15080
  }
15055
15081
  if (current.figmaFile === void 0) {
15056
- return { active: false, note: "REST channel unavailable: the plan carries no --figma-file key \u2014 pass it (from the design URL) to record pixels+geometry over Figma REST and escape the MCP daily limit" };
15082
+ return {
15083
+ active: false,
15084
+ reason: "no-figma-file",
15085
+ note: "REST channel unavailable: the plan carries no --figma-file key \u2014 pass it (from the design URL) to record pixels+geometry over Figma REST and escape the MCP daily limit"
15086
+ };
15057
15087
  }
15058
15088
  const client = await figmaRestClient();
15059
15089
  if (!client.ok) {
15060
- return client.kind === "no-credential" ? { active: false, note: client.refusal } : { active: false, note: `REST channel unavailable (${client.kind}): ${client.refusal} \u2014 recording proceeds over MCP` };
15090
+ return client.kind === "no-credential" ? {
15091
+ active: false,
15092
+ reason: "no-credential",
15093
+ // The FIRST FIELD RUN taught this note to instruct, not
15094
+ // mention: the agent rendered the feasibility options and
15095
+ // never offered the connect, because nothing told it to.
15096
+ note: "Figma is not connected on THIS machine, so recording stays on the daily-limited MCP transport. AGENTS: offer the connect NOW, before any recording call \u2014 call tendril_figma_connect, relay the link (the user clicks Allow once), tendril_figma_connect_wait, then RE-RUN THIS EXACT PLAN: the channel stays assignable until the first envelope is ingested, and the bill drops to roughly one call per pose."
15097
+ } : { active: false, reason: client.kind, note: `REST channel unavailable (${client.kind}): ${client.refusal} \u2014 recording proceeds over MCP` };
15061
15098
  }
15062
15099
  const ids = current.reps.map((r) => r.nodeId);
15063
15100
  const docs = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tendrilapp/cli",
3
- "version": "0.1.46",
3
+ "version": "0.1.47",
4
4
  "description": "Figma design systems → verified React components. CLI ruler + MCP server.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",