@robbeverhelst/do 1.151.0 → 1.152.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/dist/do.js +283 -2
  2. package/package.json +1 -1
package/dist/do.js CHANGED
@@ -18050,6 +18050,60 @@ var linkGoogleInputSchema = exports_external.object({
18050
18050
  state: exports_external.string().min(1)
18051
18051
  });
18052
18052
 
18053
+ // ../../packages/schema/src/contracts/changes.ts
18054
+ var changeOpSchema = exports_external.enum(["created", "updated", "deleted"]);
18055
+ var CHANGE_ENTITY_SCOPES = {
18056
+ task: "tasks:read",
18057
+ project: "projects:read",
18058
+ area: "areas:read",
18059
+ routine: "routines:read",
18060
+ habit: "habits:read",
18061
+ occurrence: "occurrences:read",
18062
+ note: "notes:read",
18063
+ contact: "contacts:read",
18064
+ collection_item: "collections:read",
18065
+ inventory_item: "inventory:read",
18066
+ shopping_list: "shopping:read",
18067
+ recipe: "meals:read",
18068
+ meal_plan: "meals:read",
18069
+ event: "calendar:read",
18070
+ time_block: "calendar:read",
18071
+ place: "places:read"
18072
+ };
18073
+ var CHANGE_ENTITIES = Object.keys(CHANGE_ENTITY_SCOPES);
18074
+ var changeEntitySchema = exports_external.enum(CHANGE_ENTITIES);
18075
+ var changeSchema = exports_external.object({
18076
+ entity: changeEntitySchema,
18077
+ id: exports_external.string(),
18078
+ op: changeOpSchema,
18079
+ changedAt: exports_external.coerce.date()
18080
+ });
18081
+ var MAX_CHANGES_LIMIT = 500;
18082
+ var CHANGES_SINCE_NOW = "now";
18083
+ var CURSOR_RE = /^(\d+)-(\d+)$/;
18084
+ function parseChangeCursor(raw) {
18085
+ const m = CURSOR_RE.exec(raw);
18086
+ if (!m)
18087
+ return null;
18088
+ const txid = Number(m[1]);
18089
+ const seq = Number(m[2]);
18090
+ if (!Number.isSafeInteger(txid) || !Number.isSafeInteger(seq))
18091
+ return null;
18092
+ return { txid, seq };
18093
+ }
18094
+ var changesQuerySchema = exports_external.object({
18095
+ since: exports_external.string().refine((s) => s === CHANGES_SINCE_NOW || parseChangeCursor(s) !== null, {
18096
+ message: "since must be a cursor from a prior page's nextCursor, or 'now'"
18097
+ }).optional(),
18098
+ limit: exports_external.coerce.number().int().positive().transform((n) => Math.min(n, MAX_CHANGES_LIMIT)).optional(),
18099
+ entity: exports_external.string().transform((s) => s.split(",").map((e) => e.trim()).filter((e) => e.length > 0)).pipe(exports_external.array(changeEntitySchema).min(1)).optional()
18100
+ });
18101
+ var changesPageSchema = exports_external.object({
18102
+ data: exports_external.array(changeSchema),
18103
+ nextCursor: exports_external.string(),
18104
+ hasMore: exports_external.boolean()
18105
+ });
18106
+
18053
18107
  // ../../packages/schema/src/contracts/value-sets.ts
18054
18108
  var areaColorSchema = exports_external.enum(areaColor.enumValues);
18055
18109
  var reviewCadenceSchema = exports_external.enum(reviewCadence.enumValues);
@@ -19532,6 +19586,110 @@ var timeBlockRangeQuerySchema = exports_external.object({
19532
19586
  path: ["to"]
19533
19587
  });
19534
19588
 
19589
+ // ../../packages/schema/src/contracts/agent-chat.ts
19590
+ var agentConnectionSourceSchema = exports_external.enum(["space", "env"]);
19591
+ var agentConnectionSchema = exports_external.object({
19592
+ connected: exports_external.boolean(),
19593
+ source: agentConnectionSourceSchema.nullable(),
19594
+ endpoint: exports_external.string().nullable(),
19595
+ model: exports_external.string().nullable(),
19596
+ hasKey: exports_external.boolean(),
19597
+ agentId: exports_external.string().nullable(),
19598
+ autoFile: exports_external.boolean(),
19599
+ updatedAt: exports_external.coerce.date().nullable()
19600
+ });
19601
+ var agentEndpointSchema = exports_external.string().trim().max(2000).url().refine((value) => /^https?:\/\//i.test(value), "endpoint must be an http(s) URL");
19602
+ var saveAgentConnectionInputSchema = exports_external.object({
19603
+ endpoint: agentEndpointSchema,
19604
+ apiKey: exports_external.string().trim().min(1).max(4000).nullable().optional(),
19605
+ model: exports_external.string().trim().min(1).max(200).nullable().optional(),
19606
+ agentId: exports_external.string().trim().min(1).max(64).nullable().optional(),
19607
+ autoFile: exports_external.boolean().optional()
19608
+ }).strict();
19609
+ var agentPageContextSchema = exports_external.object({
19610
+ route: exports_external.string().trim().min(1).max(500).startsWith("/"),
19611
+ nodeId: exports_external.string().trim().min(1).max(64).nullable()
19612
+ }).strict();
19613
+ var agentChatInputSchema = exports_external.object({
19614
+ message: exports_external.string().trim().min(1).max(8000),
19615
+ context: agentPageContextSchema
19616
+ }).strict();
19617
+ var agentChatEventSchema = exports_external.discriminatedUnion("type", [
19618
+ exports_external.object({ type: exports_external.literal("delta"), text: exports_external.string() }),
19619
+ exports_external.object({ type: exports_external.literal("done") }),
19620
+ exports_external.object({ type: exports_external.literal("error"), message: exports_external.string() })
19621
+ ]);
19622
+ var agentChangeValueSchema = exports_external.union([
19623
+ exports_external.string(),
19624
+ exports_external.number(),
19625
+ exports_external.boolean(),
19626
+ exports_external.null(),
19627
+ exports_external.array(exports_external.string())
19628
+ ]);
19629
+ var agentChangeFieldSchema = exports_external.object({
19630
+ field: exports_external.string(),
19631
+ before: agentChangeValueSchema,
19632
+ after: agentChangeValueSchema,
19633
+ beforeLabel: exports_external.string().nullable().optional(),
19634
+ afterLabel: exports_external.string().nullable().optional()
19635
+ });
19636
+ var agentChangeSchema = exports_external.object({
19637
+ entity: changeEntitySchema,
19638
+ id: exports_external.string(),
19639
+ op: changeOpSchema,
19640
+ changedAt: exports_external.coerce.date(),
19641
+ title: exports_external.string().nullable(),
19642
+ actor: actorRefSchema,
19643
+ fields: exports_external.array(agentChangeFieldSchema).optional()
19644
+ });
19645
+ var agentChangesPageSchema = exports_external.object({
19646
+ data: exports_external.array(agentChangeSchema),
19647
+ nextCursor: exports_external.string()
19648
+ });
19649
+ var agentChangesQuerySchema = exports_external.object({
19650
+ since: exports_external.string().refine((s) => s === "now" || /^\d+-\d+$/.test(s), {
19651
+ message: "since must be a cursor from a prior page's nextCursor, or 'now'"
19652
+ })
19653
+ });
19654
+ var agentConfirmationKindSchema = exports_external.enum(["delete", "cancel", "google", "orca", "bulk"]);
19655
+ var agentConfirmationStatusSchema = exports_external.enum([
19656
+ "pending",
19657
+ "confirmed",
19658
+ "done",
19659
+ "failed",
19660
+ "declined"
19661
+ ]);
19662
+ var agentConfirmationSchema = exports_external.object({
19663
+ id: exports_external.string(),
19664
+ kind: agentConfirmationKindSchema,
19665
+ summary: exports_external.string(),
19666
+ items: exports_external.array(exports_external.object({ id: exports_external.string(), title: exports_external.string().nullable() })),
19667
+ method: exports_external.string(),
19668
+ path: exports_external.string(),
19669
+ status: agentConfirmationStatusSchema,
19670
+ agent: exports_external.object({ id: exports_external.string(), name: exports_external.string().nullable() }),
19671
+ createdAt: exports_external.coerce.date(),
19672
+ decidedAt: exports_external.coerce.date().nullable()
19673
+ });
19674
+ var agentUndoInputSchema = exports_external.object({
19675
+ id: exports_external.string().trim().min(1).max(64),
19676
+ since: exports_external.string().regex(/^\d+-\d+$/, "since must be a change-feed cursor")
19677
+ }).strict();
19678
+ var agentUndoResultSchema = exports_external.object({
19679
+ id: exports_external.string(),
19680
+ undone: exports_external.enum(["removed", "restored"])
19681
+ });
19682
+ var agentRedoResultSchema = exports_external.object({
19683
+ id: exports_external.string(),
19684
+ redone: exports_external.literal(true)
19685
+ });
19686
+ var agentFilingSchema = exports_external.object({
19687
+ confident: exports_external.boolean().default(false),
19688
+ areaId: exports_external.string().nullable().optional(),
19689
+ owner: exports_external.string().nullable().optional(),
19690
+ date: exports_external.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional()
19691
+ });
19692
+
19535
19693
  // ../../packages/schema/src/contracts/roles.ts
19536
19694
  var permissionSetSchema = createSelectSchema(permissionSets, {
19537
19695
  createdAt: exports_external.coerce.date(),
@@ -20631,7 +20789,7 @@ function parseCapture2(input, now) {
20631
20789
 
20632
20790
  // src/meta.ts
20633
20791
  var CLI_NAME = "do";
20634
- var VERSION = "1.151.0";
20792
+ var VERSION = "1.152.0";
20635
20793
  var API_PREFIX = "/api/v1";
20636
20794
  var DEFAULT_API_URL = "http://localhost:3001";
20637
20795
 
@@ -21530,6 +21688,68 @@ var COMMAND_SPECS = [
21530
21688
  returns: "None",
21531
21689
  notes: "Gated behind --allow-destructive + an orca:write key. Idempotent."
21532
21690
  },
21691
+ {
21692
+ path: ["agents", "list"],
21693
+ summary: "List the Space's Agents (id + name).",
21694
+ args: [],
21695
+ flags: [],
21696
+ scopes: ["agents:read"],
21697
+ returns: "AgentSummary",
21698
+ notes: "Creating an Agent and minting its keys stays a member's job in the app."
21699
+ },
21700
+ {
21701
+ path: ["agent", "connection", "get"],
21702
+ summary: "Show the agent runtime the Echo panel's chat goes to (never its key).",
21703
+ args: [],
21704
+ flags: [],
21705
+ scopes: ["agents:read"],
21706
+ returns: "AgentConnection",
21707
+ notes: "hasKey says whether a key is set; the key itself is write-only."
21708
+ },
21709
+ {
21710
+ path: ["agent", "connection", "set"],
21711
+ summary: "Point the Echo panel at an agent runtime (replaces the connection).",
21712
+ args: [],
21713
+ flags: [
21714
+ { name: "endpoint", type: "string", description: "The runtime's base URL (required)." },
21715
+ {
21716
+ name: "model",
21717
+ type: "string",
21718
+ description: "The model to ask for, if the runtime needs one."
21719
+ },
21720
+ {
21721
+ name: "agent",
21722
+ type: "string",
21723
+ description: "The Agent the runtime acts as: its id or name (see `agents list`)."
21724
+ },
21725
+ {
21726
+ name: "auto-file",
21727
+ type: "boolean",
21728
+ description: "Let Echo file new captures (needs --agent)."
21729
+ },
21730
+ { name: "no-auto-file", type: "boolean", description: "Stop Echo filing new captures." },
21731
+ {
21732
+ name: "key-stdin",
21733
+ type: "boolean",
21734
+ description: "Read the runtime's API key from stdin's first line instead of DO_AGENT_API_KEY."
21735
+ },
21736
+ { name: "clear-key", type: "boolean", description: "Remove the stored key." }
21737
+ ],
21738
+ scopes: ["agents:write"],
21739
+ returns: "AgentConnection",
21740
+ notes: "The runtime's key is read from DO_AGENT_API_KEY or, with --key-stdin, from stdin \u2014 never a flag. With neither, the stored key is kept. --model and --agent are replaced as sent (left out clears them). Owner/admin only (canManageSpace)."
21741
+ },
21742
+ {
21743
+ path: ["agent", "connection", "remove"],
21744
+ summary: "Forget the Space's agent connection (destructive).",
21745
+ args: [],
21746
+ flags: [
21747
+ { name: "allow-destructive", type: "boolean", description: "Required to actually remove." }
21748
+ ],
21749
+ scopes: ["agents:write"],
21750
+ returns: "None",
21751
+ notes: "Owner/admin only. An Agent's key gets a 428 confirmation_required until the member confirms in the Echo panel."
21752
+ },
21533
21753
  {
21534
21754
  path: ["settings", "get"],
21535
21755
  summary: "Show the caller's settings for the Space.",
@@ -22051,7 +22271,7 @@ var COMMAND_SPECS = [
22051
22271
  }
22052
22272
  ];
22053
22273
  function matchCommandSpec(positionals) {
22054
- for (const len of [2, 1]) {
22274
+ for (const len of [3, 2, 1]) {
22055
22275
  const candidate = positionals.slice(0, len);
22056
22276
  if (candidate.length < len)
22057
22277
  continue;
@@ -23217,6 +23437,35 @@ var HANDLERS = {
23217
23437
  const input = parseInput(logMetricInputSchema, { value, ...at ? { occurredAt: at } : {} });
23218
23438
  return { data: await requireClient().post(`/metrics/${key}`, input), render: renderRecord };
23219
23439
  },
23440
+ "agents list": async ({ requireClient }) => ({
23441
+ data: await requireClient().getPage("/agents"),
23442
+ render: renderList
23443
+ }),
23444
+ "agent connection get": async ({ requireClient }) => ({
23445
+ data: await requireClient().get("/agent/connection"),
23446
+ render: renderRecord
23447
+ }),
23448
+ "agent connection set": async ({ io, flags, requireClient }) => {
23449
+ const endpoint = flagString(flags, "endpoint");
23450
+ if (endpoint === undefined)
23451
+ throw usageError("agent connection set needs --endpoint <url>");
23452
+ const client = requireClient();
23453
+ const agent = flagString(flags, "agent");
23454
+ const autoFile = flagBool(flags, "auto-file") ? true : flagBool(flags, "no-auto-file") ? false : undefined;
23455
+ const body = parseInput(saveAgentConnectionInputSchema, {
23456
+ endpoint,
23457
+ model: flagString(flags, "model"),
23458
+ agentId: agent === undefined ? undefined : await resolveAgentId(client, agent),
23459
+ autoFile,
23460
+ apiKey: await readAgentKey(io, flags)
23461
+ });
23462
+ return { data: await client.put("/agent/connection", body), render: renderRecord };
23463
+ },
23464
+ "agent connection remove": async ({ flags, requireClient }) => {
23465
+ assertDestructiveAllowed(flags, "remove the agent connection");
23466
+ await requireClient().delete("/agent/connection");
23467
+ return { data: { ok: true, removed: "agent connection" }, render: renderRecord };
23468
+ },
23220
23469
  "settings get": async ({ requireClient }) => ({
23221
23470
  data: await requireClient().get("/settings"),
23222
23471
  render: renderRecord
@@ -23635,6 +23884,38 @@ function redact(secret) {
23635
23884
  return "********";
23636
23885
  return `${secret.slice(0, 6)}\u2026${secret.slice(-2)}`;
23637
23886
  }
23887
+ var AGENT_KEY_ENV = "DO_AGENT_API_KEY";
23888
+ async function readAgentKey(io, flags) {
23889
+ if (flagBool(flags, "clear-key"))
23890
+ return null;
23891
+ if (flagBool(flags, "key-stdin")) {
23892
+ let first;
23893
+ if (io.stdin) {
23894
+ for await (const line2 of io.stdin) {
23895
+ first = line2;
23896
+ break;
23897
+ }
23898
+ }
23899
+ const key = first?.trim();
23900
+ if (!key)
23901
+ throw usageError("--key-stdin read no key: pipe the key in on stdin");
23902
+ return key;
23903
+ }
23904
+ const fromEnv = io.env[AGENT_KEY_ENV]?.trim();
23905
+ return fromEnv ? fromEnv : undefined;
23906
+ }
23907
+ var ULID = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
23908
+ async function resolveAgentId(client, agent) {
23909
+ if (ULID.test(agent))
23910
+ return agent;
23911
+ const { data } = await client.getPage("/agents");
23912
+ const wanted = agent.trim().toLowerCase();
23913
+ const match = data.find((a) => a.name.toLowerCase() === wanted);
23914
+ if (!match) {
23915
+ throw new CliError("not_found", `no Agent named ${agent} \u2014 see \`do agents list\``, EXIT.NOT_FOUND);
23916
+ }
23917
+ return match.id;
23918
+ }
23638
23919
  function requireWrite(entity, op) {
23639
23920
  if (!entity.write) {
23640
23921
  throw usageError(`\`${entity.name}\` is read-only \u2014 \`${op}\` is not available`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robbeverhelst/do",
3
- "version": "1.151.0",
3
+ "version": "1.152.0",
4
4
  "private": false,
5
5
  "description": "do — the agent-drivable CLI over the public /api/v1 surface",
6
6
  "type": "module",