connection-centric 0.4.0 → 0.5.0

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/commands.mjs +27 -7
  2. package/package.json +1 -1
package/commands.mjs CHANGED
@@ -18,7 +18,7 @@ export const CLI_VERSION = JSON.parse(readFileSync(new URL("./package.json", imp
18
18
  export const VERBS = ["list", "show", "make", "edit", "delete", "archive", "unarchive", "close", "reopen", "not-yet", "grant", "revoke", "appoint", "remove",
19
19
  "issue", "acknowledge", "add", "revise", "restore", "download", "messages", "mark-read", "send", "forward", "react", "unreact", "history", "readers",
20
20
  "pin", "unpin", "mute", "unmute", "private", "open-to-company", "set-picture", "remove-picture", "set-photo", "remove-photo",
21
- "approve", "reject", "withdraw", "rotate-key", "dormant", "reactivate", "report", "record-pack", "audit", "question", "correct", "disconnect"];
21
+ "approve", "reject", "withdraw", "rotate-key", "dormant", "reactivate", "report", "record-pack", "audit", "question", "correct", "disconnect", "transcript"];
22
22
 
23
23
  // What a value names, read by kind. Things are found by id, or by an exact name only one thing the person can see has.
24
24
  const THINGS = ["project", "company", "container", "channel", "task", "document", "folder", "zone", "identity", "membership", "admin", "connected-tool"];
@@ -40,7 +40,7 @@ const enc = encodeURIComponent;
40
40
  const qs = (o) => { const p = new URLSearchParams(Object.entries(o).filter(([, v]) => v != null && v !== false).map(([k, v]) => [k, v === true ? "1" : String(v)])); return p.size ? `?${p}` : ""; };
41
41
  // Rule 9: what a list or a place prints, the same everywhere.
42
42
  const listed = (items, more = null) => ({ items, more });
43
- const meShown = async (c) => { const m = await c.get("/api/me"); return { identity: m.identity, assistant: m.assistant, opened_directs: m.opened_directs, application: m.application, operator: m.operator, containers: m.containers.length }; };
43
+ const meShown = async (c) => { const m = await c.get("/api/me"); return { identity: m.identity, assistant: m.assistant, speech: m.speech, opened_directs: m.opened_directs, application: m.application, operator: m.operator, containers: m.containers.length }; };
44
44
  const newest = (x, y) => (y.last?.id ?? 0) - (x.last?.id ?? 0); // a place with nothing in it yet goes last
45
45
 
46
46
  // Rule 11: a moment is shown in India's time, ISO 8601 with +05:30; a day stays YYYY-MM-DD. Field names stay the API's.
@@ -170,9 +170,16 @@ export const COMMANDS = [
170
170
  } },
171
171
 
172
172
  // ── work ──
173
- { noun: "task", verb: "list", flags: { in: IN, state: { kind: "choice", of: ["open", "closed"] }, zone: { kind: "zone" }, before: { kind: "words", about: "with --state closed: the next page, from the more: of the one before" } },
174
- about: "A container's tasks: open ones first, soonest due, then the most important; done ones newest first, a page at a time.",
173
+ { noun: "task", verb: "list", flags: { in: { ...IN, need: false }, mine: { kind: "bool", about: "your own open tasks in every project instead, as Home groups them: needs you, overdue, this week, waiting; 200 at most, with the counts of each" },
174
+ state: { kind: "choice", of: ["open", "closed"] }, zone: { kind: "zone" }, before: { kind: "words", about: "with --state closed: the next page, from the more: of the one before" } },
175
+ about: "A container's tasks: open ones first, soonest due, then the most important; done ones newest first, a page at a time. Or, with --mine, your own across every project.",
175
176
  run: async (c, a) => {
177
+ if (a.mine) {
178
+ if (a.in || a.state || a.zone || a.before) refuse("--mine is every project's open tasks of yours: leave --in, --state, --zone and --before off");
179
+ const r = await c.get("/api/me/tasks");
180
+ return { ...listed(r.tasks), counts: r.counts };
181
+ }
182
+ if (!a.in) refuse("task list needs --in, or --mine");
176
183
  if (a.before && a.state !== "closed") refuse("--before pages done tasks: with --state closed");
177
184
  const l = await c.get(`/api/containers/${a.in}/tasks${qs({ state: a.state, zone_id: a.zone, before: a.before })}`);
178
185
  return listed(l, a.state === "closed" && l.length >= 100 ? l.at(-1).done_key : null); // the server's page of done ones (DONE_PAGE)
@@ -355,6 +362,17 @@ export const COMMANDS = [
355
362
  run: (c, a) => (a.name === undefined && a.folder === undefined ? refuse("say what changes: --name or --folder") : c.patch(`/api/documents/${a.document}`, { name: a.name, folder_id: a.folder })) },
356
363
  { noun: "document", verb: "delete", target: { name: "document", kind: "document" }, flags: {}, about: "Deletes a document, leaving a tombstone: staff only.",
357
364
  run: (c, a) => c.del(`/api/documents/${a.document}`) },
365
+ // A voice note's Transcript (CONTEXT.md, issue 307): asked for by someone with Speech on, made once and kept for everyone
366
+ // who can hear the note; taken away by the note's sender alone, which the app asks about first (--dry-run).
367
+ { noun: "document", verb: "transcript", target: { name: "document", kind: "document" }, flags: { remove: { kind: "bool", about: "take it away: the note's sender alone" }, "dry-run": { ...DRY, about: "with --remove: what would go" } },
368
+ about: "A voice note's Transcript: asked for, and made once, with Speech on; with --remove, taken away by the note's sender.",
369
+ run: async (c, a) => {
370
+ if (a["dry-run"] && !a.remove) refuse("--dry-run is for --remove");
371
+ if (!a.remove) return c.post(`/api/documents/${a.document}/transcript`);
372
+ if (!a["dry-run"]) return c.del(`/api/documents/${a.document}/transcript`);
373
+ const tr = revisionOf(await c.get(`/api/documents/${a.document}`))?.transcript;
374
+ return tr ? { dry_run: true, would_remove: { document: a.document, transcript: tr.text } } : refuse("it has no transcript to remove");
375
+ } },
358
376
  { noun: "document", verb: "download", target: { name: "document", kind: "document" }, flags: { revision: { kind: "int", about: "which revision; the current one if left out" }, out: { kind: "path", about: "where to write it; the file's own name here if left out" } },
359
377
  about: "Writes the exact bytes kept for a revision to this computer, after checking them against the hash Centric kept.",
360
378
  async run(c, a) {
@@ -463,12 +481,14 @@ export const COMMANDS = [
463
481
 
464
482
  // ── me and the assistant ──
465
483
  { noun: "me", verb: "edit", flags: { "display-name": { kind: "words", about: "what you call yourself, everywhere you work" }, assistant: { kind: "choice", of: ["on", "off"], about: "your own switch for Centric's assistant (ADR 0002)" },
466
- language: { kind: "choice", of: ["en", "gu", "hi"], about: "what your assistant and your digest answer in" } },
467
- about: "Changes your display name, switches your assistant on or off, or sets its language.",
484
+ language: { kind: "choice", of: ["en", "gu", "hi"], about: "what your assistant and your digest answer in" },
485
+ speech: { kind: "choice", of: ["on", "off"], about: "your own switch for read aloud, transcripts and dictation (ADR 0019)" } },
486
+ about: "Changes your display name, switches your assistant or speech on or off, or sets the assistant's language.",
468
487
  async run(c, a) {
469
- if (a["display-name"] === undefined && a.assistant === undefined && a.language === undefined) refuse("say what changes: --display-name, --assistant or --language");
488
+ if (a["display-name"] === undefined && a.assistant === undefined && a.language === undefined && a.speech === undefined) refuse("say what changes: --display-name, --assistant, --language or --speech");
470
489
  if (a["display-name"] !== undefined) await c.patch("/api/me", { display_name: a["display-name"] });
471
490
  if (a.assistant !== undefined || a.language !== undefined) await c.patch("/api/me/assistant", { on: a.assistant && a.assistant === "on", lang: a.language });
491
+ if (a.speech !== undefined) await c.patch("/api/me/speech", { on: a.speech === "on" });
472
492
  return meShown(c);
473
493
  } },
474
494
  { noun: "me", verb: "set-photo", flags: { path: { ...PATH, about: "a square JPEG, PNG or WebP, 300 KB at most" } }, about: "Sets the photo shown beside your name.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "connection-centric",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "The centric command: what a person does in Connection-Centric, done as them from a terminal, a script, or a program such as Claude Code.",
5
5
  "type": "module",
6
6
  "bin": {