@todoforai/tfa-surface 0.1.2 → 0.1.4

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/cli.js +74 -62
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -116,7 +116,7 @@ function resolveToken(opts = {}) {
116
116
  // package.json
117
117
  var package_default = {
118
118
  name: "@todoforai/tfa-surface",
119
- version: "0.1.2",
119
+ version: "0.1.4",
120
120
  description: "TODOforAI surface CLI — see and drive what is shown in the user's live UI (describe, todo/panel views, renderer cards, surface render, controls). Replaces tfa-frontend. Reuses bridge credentials.",
121
121
  type: "module",
122
122
  bin: {
@@ -156,22 +156,24 @@ Usage:
156
156
  tfa-surface <command> [args...]
157
157
 
158
158
  Discovery:
159
- describe What's open in the target frontend:
160
- todos, focus, panel surfaces, sidebar,
161
- embedded-browser CDP URL, show/card
162
- instances in loaded chats. YAML; --json
163
- for the raw structure.
159
+ describe Every surface in the target frontend — kind, id,
160
+ ref, focus; plus sidebar, embedded-browser CDP
161
+ URL and the show instances loaded in each todo.
162
+ YAML; --json for the raw structure.
164
163
 
165
- Todos (views):
166
- todo open <todoId> [--popout] Open a todo (full-page overlay); --popout
167
- forces a floating preview window.
168
- todo focus <todoId> Focus an open todo's window.
169
- todo close <todoId> Close an open todo view.
170
-
171
- Panels (surfaces inside a todo; --todo defaults to $TODOFORAI_TODO_ID):
172
- panel open <surface> [--todo <id>] [--url <url>]
173
- surface: changes|agents|preview|browser|terminal
174
- panel close [--todo <id>]
164
+ Surfaces — a ref is a todo id, <todoId>:<alias> (a shown artifact, live) or an http(s) url:
165
+ open overlay <todoId> The full-page todo (todos only).
166
+ open window <ref> [--detached] A floating preview window (any ref); --detached: out of
167
+ the grid, own size, resizable. connect:/stream: refs always are.
168
+ open panel <view> [--todo <id>] [--url <url>]
169
+ A todo's side panel: changes|agents|preview|browser|terminal
170
+ (--todo defaults to $TODOFORAI_TODO_ID).
171
+ open card <ref> [--id <id>] [--title <t>] [--group <slug>]
172
+ A card on the project board, for every member —
173
+ its own card, or a tile inside a group's card.
174
+ Persisted; the same --id updates in place.
175
+ close <kind> <id> overlay: no id · window: the ref · panel: the todo · card: its id
176
+ focus window <ref> Bring a window (or its docked tab) to front.
175
177
 
176
178
  Renderer cards (data plane — works headless, no frontend needed;
177
179
  --project defaults to $TODOFORAI_PROJECT_ID):
@@ -193,6 +195,7 @@ Content (inherited from tfa-frontend, broadcast to all tabs):
193
195
 
194
196
  Options:
195
197
  --frontend <tabId> Target frontend (overrides $TODOFORAI_FRONTEND_ID)
198
+ --id <surfaceId> Card id (open card); --group <slug> files it into a group card
196
199
  --api-url <url> Backend URL (default: env/credentials)
197
200
  --api-token <tok> Token (default: env/credentials)
198
201
  --json Machine-readable output
@@ -202,9 +205,13 @@ Options:
202
205
  Examples:
203
206
  tfa-surface describe
204
207
  tfa-surface card add kpi-tile dashboards/kpi.html --title "KPI tile"
205
- tfa-surface todo open 3f2a91... --popout
206
- tfa-surface panel open browser --url https://example.com
207
- agent-browser connect "$(tfa-surface describe --json | jq -r '.todos[0].browser.cdp')"
208
+ tfa-surface open window 3f2a91...
209
+ tfa-surface open window $TODOFORAI_TODO_ID:kpi # a shown artifact, in its own window
210
+ tfa-surface open window connect:<deviceId>/zele # a sign-in card for the user
211
+ tfa-surface open card $TODOFORAI_TODO_ID:kpi --title "Weekly KPIs" --group marketing
212
+ tfa-surface open panel browser --url https://example.com
213
+ tfa-surface close card weekly-kpis
214
+ agent-browser connect "$(tfa-surface describe --json | jq -r '.surfaces[] | select(.browser) | .browser.cdp' | head -1)"
208
215
  git diff --stat | tfa-surface show chat.panel $TODOFORAI_TODO_ID
209
216
 
210
217
  Exit codes: 0 ok · 1 error · 2 frontend not reachable / no frontend id`);
@@ -284,24 +291,18 @@ function printResult(ctx, data) {
284
291
  function printDescribe(d) {
285
292
  console.log(`frontend: ${d.frontendId} (${d.platform}, ${d.kind})`);
286
293
  console.log(`sidebar: ${d.sidebar}`);
287
- console.log(d.todos.length ? "todos:" : "todos: []");
288
- for (const t of d.todos) {
289
- const flags = [t.mode === "window" ? "window" : "", t.focused ? "focused" : ""].filter(Boolean).join(", ");
290
- console.log(` ${t.todoId}:${flags ? ` ${flags}` : ""}${t.title ? ` # ${t.title}` : ""}`);
291
- if (t.panel && t.panel !== "browser")
292
- console.log(` ${t.panel}`);
293
- if (t.browser)
294
- console.log(` browser: ${t.browser.open ? t.browser.url : "(idle)"} cdp: ${t.browser.cdp}`);
295
- if (t.shows?.length) {
294
+ console.log(d.surfaces.length ? "surfaces:" : "surfaces: []");
295
+ for (const s of d.surfaces) {
296
+ const flags = [s.focused ? "focused" : "", s.docked ? "docked" : "", s.size ? `detached ${s.size.w}x${s.size.h}` : "", s.view ?? "", s.group ? `in ${s.group}` : ""].filter(Boolean).join(", ");
297
+ const id = s.kind === "overlay" || s.id === s.ref ? "" : ` ${s.id}`;
298
+ console.log(` ${s.kind}${id}: ${s.ref}${flags ? ` ${flags}` : ""}${s.title ? ` # ${s.title}` : ""}`);
299
+ if (s.browser)
300
+ console.log(` browser: ${s.browser.open ? s.browser.url : "(idle)"} cdp: ${s.browser.cdp}`);
301
+ if (s.shows?.length) {
296
302
  console.log(" shows:");
297
- for (const s of t.shows) {
298
- const bits = [
299
- s.card ? `card=${s.card}` : "",
300
- s.mime || "",
301
- s.url ? `url ${s.url}` : "",
302
- s.title || ""
303
- ].filter(Boolean);
304
- console.log(` ${s.ref}${bits.length ? ` ${bits.join(" ")}` : ""}`);
303
+ for (const x of s.shows) {
304
+ const bits = [x.card ? `card=${x.card}` : "", x.mime || "", x.url ? `url ${x.url}` : "", x.title || ""].filter(Boolean);
305
+ console.log(` ${x.ref}${bits.length ? ` ${bits.join(" ")}` : ""}`);
305
306
  }
306
307
  }
307
308
  }
@@ -315,10 +316,12 @@ async function main() {
315
316
  project: { type: "string" },
316
317
  title: { type: "string" },
317
318
  description: { type: "string" },
318
- popout: { type: "boolean", default: false },
319
+ id: { type: "string" },
320
+ group: { type: "string" },
319
321
  "api-url": { type: "string" },
320
322
  "api-token": { type: "string" },
321
323
  json: { type: "boolean", default: false },
324
+ detached: { type: "boolean", default: false },
322
325
  help: { type: "boolean", short: "h", default: false },
323
326
  version: { type: "boolean", default: false }
324
327
  },
@@ -354,37 +357,46 @@ async function main() {
354
357
  printDescribe(result);
355
358
  break;
356
359
  }
357
- case "todo": {
358
- const [verb, todoId] = args;
359
- if (!verb || !todoId)
360
- die("usage: tfa-surface todo open|focus|close <todoId>");
361
- if (verb === "open") {
362
- const result = await uiCall(ctx, "todo.open", { todoId, ...values.popout ? { mode: "window" } : {} });
363
- console.log(ctx.json ? JSON.stringify(result) : `${result.created ? "opened" : "already open"} (${result.mode})`);
364
- } else if (verb === "focus" || verb === "close") {
365
- await uiCall(ctx, `todo.${verb}`, { todoId });
366
- console.log(ctx.json ? '{"ok":true}' : "ok");
367
- } else {
368
- die(`unknown todo verb: ${verb}`);
369
- }
370
- break;
371
- }
372
- case "panel": {
373
- const [verb, surface] = args;
374
- if (verb === "open") {
375
- if (!surface)
376
- die("usage: tfa-surface panel open changes|agents|preview|browser|terminal [--todo <id>] [--url <url>]");
377
- const result = await uiCall(ctx, "panel.open", { todoId: todoArg(), surface, ...values.url ? { url: values.url } : {} });
360
+ case "open": {
361
+ const [kind, arg] = args;
362
+ const usage = "usage: tfa-surface open overlay <todoId> | window <ref> [--detached] | panel <view> [--todo <id>] [--url <url>] | card <ref> [--id <id>] [--title <t>] [--group <slug>]";
363
+ if (kind === "overlay" || kind === "window") {
364
+ if (!arg)
365
+ die(usage);
366
+ const result = await uiCall(ctx, "surface.open", { kind, ref: arg, ...values.detached && { detached: true } });
367
+ console.log(ctx.json ? JSON.stringify(result) : `${result.created ? "opened" : "already open"} (${kind})`);
368
+ } else if (kind === "panel") {
369
+ if (!arg)
370
+ die(usage);
371
+ const result = await uiCall(ctx, "surface.open", { kind, id: todoArg(), view: arg, ref: values.url ?? arg });
378
372
  const pending = result?.browserReady === false;
379
373
  console.log(ctx.json ? JSON.stringify(result ?? { ok: true }) : pending ? "ok (browser opening — its CDP url appears in `device_list` shortly)" : "ok");
380
- } else if (verb === "close") {
381
- await uiCall(ctx, "panel.close", { todoId: todoArg() });
382
- console.log(ctx.json ? '{"ok":true}' : "ok");
374
+ } else if (kind === "card") {
375
+ if (!arg)
376
+ die(usage);
377
+ const result = await uiCall(ctx, "surface.open", {
378
+ kind,
379
+ ref: arg,
380
+ ...values.id ? { id: values.id } : {},
381
+ ...values.title !== undefined ? { title: values.title } : {},
382
+ ...values.group !== undefined ? { group: values.group } : {}
383
+ });
384
+ console.log(ctx.json ? JSON.stringify(result) : `card ${result.id} ${result.created ? "added to" : "updated on"} the board`);
383
385
  } else {
384
- die("usage: tfa-surface panel open|close ...");
386
+ die(usage);
385
387
  }
386
388
  break;
387
389
  }
390
+ case "close":
391
+ case "focus": {
392
+ const [kind, arg] = args;
393
+ const id = kind === "overlay" ? "" : kind === "panel" ? arg || todoArg() : arg;
394
+ if (!kind || kind !== "overlay" && !id)
395
+ die(`usage: tfa-surface ${cmd} overlay | window <ref> | panel [<todoId>] | card <id>`);
396
+ await uiCall(ctx, `surface.${cmd}`, { kind, id });
397
+ console.log(ctx.json ? '{"ok":true}' : "ok");
398
+ break;
399
+ }
388
400
  case "card": {
389
401
  const [verb, name] = args;
390
402
  const cardPath = (n) => `/resources/cards/${projectArg()}/${encodeURIComponent(n)}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@todoforai/tfa-surface",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "TODOforAI surface CLI — see and drive what is shown in the user's live UI (describe, todo/panel views, renderer cards, surface render, controls). Replaces tfa-frontend. Reuses bridge credentials.",
5
5
  "type": "module",
6
6
  "bin": {