@workser/cli 0.6.13 → 0.6.15

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.
package/dist/index.js CHANGED
@@ -3663,6 +3663,137 @@ var import_picocolors2 = __toESM(require_picocolors(), 1);
3663
3663
 
3664
3664
  // src/help-content.ts
3665
3665
  var HELP_TOPICS = [
3666
+ {
3667
+ topic: "agent-cloud",
3668
+ title: "Ship an agent inside the app",
3669
+ summary: "Create an AI agent that runs on Workser and can be called from this project's apps.",
3670
+ commands: ["agent-cloud"],
3671
+ source: "skills/workser/reference/agent-cloud.md",
3672
+ body: `# Ship an agent inside the app
3673
+
3674
+ \`workser agent-cloud\` creates an AI agent that runs on **Workser's**
3675
+ infrastructure, keeps its own memory and tools, and can be called from the web,
3676
+ mobile, API or Python apps in this project.
3677
+
3678
+ **This is not \`workser agent\`.** That one hands a subtask to a coding agent on
3679
+ this machine \u2014 a teammate helping you build. This one is a thing the project
3680
+ *ships*: it works for the user after you are gone.
3681
+
3682
+ \`\`\`
3683
+ workser agent-cloud list
3684
+ workser agent-cloud create "Order desk" --instructions "..."
3685
+ workser agent-cloud show <agentId>
3686
+ workser agent-cloud run <agentId> "<what to do>"
3687
+ workser agent-cloud runs <agentId> # recent runs
3688
+ workser agent-cloud runs <runId> # one run, with what it cost
3689
+ \`\`\`
3690
+
3691
+ Every call is scoped to the project this folder belongs to.
3692
+
3693
+ ## Creating one is not finishing one
3694
+
3695
+ An agent created with a name and a sentence knows nothing about the business.
3696
+ Teaching it is the actual work, and it is all here:
3697
+
3698
+ \`\`\`
3699
+ workser agent-cloud set <id> system_prompt="..." handle="orderdesk"
3700
+ workser agent-cloud add <id> skill name="Refunds" instructions_md="..."
3701
+ workser agent-cloud add <id> knowledge name="Price list" content_text="..."
3702
+ workser agent-cloud add <id> tool display_name="Send email" provider="gmail" \\
3703
+ provider_tool_id="GMAIL_SEND_EMAIL"
3704
+ workser agent-cloud add <id> secret key="STRIPE_KEY" value="..."
3705
+ workser agent-cloud add <id> subagent subagent_id=<otherId> name="researcher"
3706
+ workser agent-cloud get <id> skill # what it has
3707
+ workser agent-cloud remove <id> skill <itemId>
3708
+ \`\`\`
3709
+
3710
+ \`add\` takes \`key=value\` pairs and REFUSES a field it does not know, rather than
3711
+ sending it. That matters: the API silently drops unknown fields, so a typo
3712
+ would otherwise be accepted, dropped, and reported as success \u2014 leaving an
3713
+ agent that had been told nothing.
3714
+
3715
+ ## Nothing takes effect until you publish
3716
+
3717
+ **This is the step to not forget.** The runtime resolves the PUBLISHED version
3718
+ of an agent and never the draft, so every \`set\` and \`add\` above is inert until:
3719
+
3720
+ \`\`\`
3721
+ workser agent-cloud publish <id> --note "taught it refunds"
3722
+ \`\`\`
3723
+
3724
+ Before publishing, try the setup without putting it live:
3725
+
3726
+ \`\`\`
3727
+ workser agent-cloud try <id> "a customer wants a refund on order 1042"
3728
+ \`\`\`
3729
+
3730
+ A \`try\` runs the draft, costs the same as a real run, and changes nothing that
3731
+ customers can reach.
3732
+
3733
+ ## Choosing how it thinks and what it runs on
3734
+
3735
+ \`\`\`
3736
+ workser agent-cloud models # cheapest first, on Workser credit
3737
+ workser agent-cloud models --all # includes ones needing your own key
3738
+ workser agent-cloud set <id> default_provider=openrouter default_model=...
3739
+
3740
+ workser agent-cloud machines # video, data analysis, design, ...
3741
+ \`\`\`
3742
+
3743
+ A model marked "needs your own key" will make \`publish\` FAIL unless a matching
3744
+ secret is stored first. Add the key with \`add <id> secret\` before setting it.
3745
+
3746
+ ## When to reach for this
3747
+
3748
+ When the user describes a job that **keeps happening** and needs judgement:
3749
+ "check every order for stock and email me the problems", "read the LINE
3750
+ messages and file them", "reconcile these invoices". That is an agent.
3751
+
3752
+ A one-off transformation is not an agent \u2014 write the code. A fixed sequence of
3753
+ steps with no judgement in it is not an agent either \u2014 that is \`workser
3754
+ workflow\`.
3755
+
3756
+ ## Calling it from the app you are building
3757
+
3758
+ Do NOT shell out to the CLI from app code. Use the SDK, which streams:
3759
+
3760
+ \`\`\`ts
3761
+ import { workser } from '@workser/app';
3762
+
3763
+ const run = await workser.agents.run(agentId, { message }, {
3764
+ referenceUserId: user.id, // who it is acting for
3765
+ });
3766
+
3767
+ for await (const event of workser.agents.stream(run.id)) {
3768
+ // event.type, event.data \u2014 forward these to the browser
3769
+ }
3770
+ \`\`\`
3771
+
3772
+ \`stream()\` reconnects itself through dropped connections, so the person
3773
+ watching sees the agent think. See the \`workser-sdk\` skill, \`reference/agents.md\`.
3774
+
3775
+ ## Things that will bite you
3776
+
3777
+ 1. **A run costs money by the minute.** It is metered \u2014 runtime, workspace, and
3778
+ a per-run fee \u2014 so a loop that starts agents is a loop that spends. Cancel
3779
+ what you abandon: \`workser agent-cloud runs <runId>\` shows the cost.
3780
+
3781
+ 2. **Instructions are the product.** The agent does what its instructions say,
3782
+ in the user's own words. Write them the way you would brief a new colleague:
3783
+ what to do, what to leave alone, when to ask. Vague instructions are the
3784
+ single biggest cause of an agent that "doesn't work".
3785
+
3786
+ 3. **Free plans cannot run agents at all**, and a trial has a small allowance.
3787
+ A \`402\` with \`spend_limit_reached\` is not a bug \u2014 tell the user what it says
3788
+ and point them at their plan.
3789
+
3790
+ 4. **Say who it is for.** An agent acting for one of the app's customers needs
3791
+ \`referenceUserId\`, or its memory and audit trail belong to nobody.
3792
+
3793
+ 5. **Do not invent an agent the user did not ask for.** Creating one is cheap;
3794
+ an agent nobody wanted, quietly costing money per run, is not.
3795
+ `
3796
+ },
3666
3797
  {
3667
3798
  topic: "analysis",
3668
3799
  title: "Analysis \u2014 running Python on this project's data",
@@ -7459,8 +7590,366 @@ function formatRole(r) {
7459
7590
  return `${label} ${agent} ${enabled} ${ready}${tail}`;
7460
7591
  }
7461
7592
 
7462
- // src/commands/verify.ts
7593
+ // src/commands/agent-cloud.ts
7463
7594
  var import_picocolors17 = __toESM(require_picocolors(), 1);
7595
+ function registerAgentCloud(program3) {
7596
+ const cloud = program3.command("agent-cloud").description(
7597
+ "Agents that run in the cloud and can be called from this project's apps (not the local coding agents \u2014 that's `workser agent`)"
7598
+ );
7599
+ cloud.command("list").description("List this project's cloud agents").action(
7600
+ action(async ({ ctx }) => {
7601
+ const res = await api(ctx, "/v1/agent-cloud");
7602
+ const agents = res?.agents ?? res ?? [];
7603
+ ok(res, () => {
7604
+ if (!agents.length) {
7605
+ line(import_picocolors17.default.dim("No cloud agents yet."));
7606
+ line(
7607
+ import_picocolors17.default.dim("Create one: ") + import_picocolors17.default.bold('workser agent-cloud create "Order desk" --instructions "..."')
7608
+ );
7609
+ return;
7610
+ }
7611
+ for (const a of agents) {
7612
+ line(
7613
+ `${import_picocolors17.default.bold(a.name ?? a.id)} ${import_picocolors17.default.dim(a.id)}` + (a.status ? ` ${import_picocolors17.default.dim(a.status)}` : "")
7614
+ );
7615
+ if (a.description) line(" " + import_picocolors17.default.dim(a.description));
7616
+ }
7617
+ });
7618
+ })
7619
+ );
7620
+ cloud.command("create <name>").description("Create a cloud agent in this project").option("--description <text>", "What it is for, in the owner's words").option(
7621
+ "--instructions <text>",
7622
+ "The agent's standing instructions \u2014 what it should always do"
7623
+ ).action(
7624
+ action(async ({ ctx, args, opts }) => {
7625
+ const res = await api(ctx, "/v1/agent-cloud", {
7626
+ method: "POST",
7627
+ body: {
7628
+ name: args[0],
7629
+ description: opts.description,
7630
+ instructions: opts.instructions
7631
+ }
7632
+ });
7633
+ ok(res, () => {
7634
+ line(import_picocolors17.default.green("Created ") + import_picocolors17.default.bold(res?.name ?? args[0]));
7635
+ if (res?.id) line(import_picocolors17.default.dim(res.id));
7636
+ line("");
7637
+ line(
7638
+ import_picocolors17.default.dim("Give it work: ") + import_picocolors17.default.bold(`workser agent-cloud run ${res?.id ?? "<id>"} "..."`)
7639
+ );
7640
+ });
7641
+ })
7642
+ );
7643
+ cloud.command("show <agentId>").description("One cloud agent, with its configuration").action(
7644
+ action(async ({ ctx, args }) => {
7645
+ const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}`);
7646
+ ok(res, () => {
7647
+ line(import_picocolors17.default.bold(res?.name ?? args[0]));
7648
+ if (res?.description) line(import_picocolors17.default.dim(res.description));
7649
+ if (res?.instructions) {
7650
+ line("");
7651
+ line(import_picocolors17.default.bold("instructions:"));
7652
+ line(res.instructions);
7653
+ }
7654
+ });
7655
+ })
7656
+ );
7657
+ cloud.command("run <agentId> <message>").description("Give a cloud agent something to do").action(
7658
+ action(async ({ ctx, args }) => {
7659
+ const res = await api(
7660
+ ctx,
7661
+ `/v1/agent-cloud/${encodeURIComponent(args[0])}/runs`,
7662
+ { method: "POST", body: { input: { message: args[1] } } }
7663
+ );
7664
+ ok(res, () => {
7665
+ line(import_picocolors17.default.green("Started run ") + import_picocolors17.default.bold(res?.id ?? ""));
7666
+ line(
7667
+ import_picocolors17.default.dim("Follow it: ") + import_picocolors17.default.bold(`workser agent-cloud runs ${res?.id ?? "<runId>"}`)
7668
+ );
7669
+ });
7670
+ })
7671
+ );
7672
+ cloud.command("runs [agentIdOrRunId]").description("Recent runs for an agent, or one run in detail").option("--limit <n>", "How many to list", "10").action(
7673
+ action(async ({ ctx, args, opts }) => {
7674
+ const id = args[0];
7675
+ if (!id) {
7676
+ warn("Give an agent id to list its runs, or a run id to inspect one.");
7677
+ return;
7678
+ }
7679
+ try {
7680
+ const run = await api(
7681
+ ctx,
7682
+ `/v1/agent-cloud/runs/${encodeURIComponent(id)}`
7683
+ );
7684
+ ok(run, () => printRun(run));
7685
+ return;
7686
+ } catch {
7687
+ }
7688
+ const res = await api(
7689
+ ctx,
7690
+ `/v1/agent-cloud/${encodeURIComponent(id)}/runs`,
7691
+ { query: { limit: opts.limit } }
7692
+ );
7693
+ const runs = res?.runs ?? res ?? [];
7694
+ ok(res, () => {
7695
+ if (!runs.length) {
7696
+ line(import_picocolors17.default.dim("No runs yet."));
7697
+ return;
7698
+ }
7699
+ for (const r of runs) printRun(r, true);
7700
+ });
7701
+ })
7702
+ );
7703
+ const COLLECTIONS = {
7704
+ skill: {
7705
+ path: "skills",
7706
+ key: "skills",
7707
+ label: "skill",
7708
+ fields: ["name", "description", "instructions_md"],
7709
+ required: ["name"]
7710
+ },
7711
+ tool: {
7712
+ path: "tools",
7713
+ key: "tools",
7714
+ label: "action",
7715
+ fields: ["display_name", "provider", "provider_tool_id", "description"],
7716
+ required: ["display_name"]
7717
+ },
7718
+ mcp: {
7719
+ path: "mcp-servers",
7720
+ key: "servers",
7721
+ label: "MCP server",
7722
+ fields: ["name", "url"],
7723
+ required: ["name", "url"]
7724
+ },
7725
+ knowledge: {
7726
+ path: "resources",
7727
+ key: "resources",
7728
+ label: "reference material",
7729
+ fields: ["name", "content_text"],
7730
+ required: ["name"]
7731
+ },
7732
+ secret: {
7733
+ path: "secrets",
7734
+ key: "secrets",
7735
+ label: "stored key",
7736
+ fields: ["key", "value", "description"],
7737
+ required: ["key", "value"]
7738
+ },
7739
+ subagent: {
7740
+ path: "subagents",
7741
+ key: "subagents",
7742
+ label: "team member",
7743
+ fields: ["subagent_id", "name", "description"],
7744
+ required: ["subagent_id", "name"]
7745
+ },
7746
+ workflow: {
7747
+ path: "workflows",
7748
+ key: "workflows",
7749
+ label: "workflow",
7750
+ fields: ["workflow_id", "description"],
7751
+ required: ["workflow_id"]
7752
+ }
7753
+ };
7754
+ const kinds = Object.keys(COLLECTIONS).join(" | ");
7755
+ cloud.command("get <agentId> <kind>").description(`What an agent has been given (${kinds})`).action(
7756
+ action(async ({ ctx, args }) => {
7757
+ const spec = COLLECTIONS[args[1]];
7758
+ if (!spec) throw new Error(`Unknown kind "${args[1]}". One of: ${kinds}`);
7759
+ const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}/${spec.path}`);
7760
+ const items = res?.[spec.key] ?? [];
7761
+ ok(res, () => {
7762
+ if (!items.length) {
7763
+ line(import_picocolors17.default.dim(`No ${spec.label} yet.`));
7764
+ return;
7765
+ }
7766
+ for (const i of items) {
7767
+ const title = i.name ?? i.display_name ?? i.key ?? i.workflow_id ?? i.id;
7768
+ line(`${import_picocolors17.default.bold(title)} ${import_picocolors17.default.dim(i.id)}`);
7769
+ if (i.description) line(" " + import_picocolors17.default.dim(i.description));
7770
+ if (i.is_enabled === false) line(" " + import_picocolors17.default.yellow("turned off"));
7771
+ }
7772
+ });
7773
+ })
7774
+ );
7775
+ cloud.command("add <agentId> <kind> [pairs...]").description(
7776
+ `Give an agent something (${kinds}). Pairs are key=value, e.g. name="Refunds"`
7777
+ ).action(
7778
+ action(async ({ ctx, args }) => {
7779
+ const spec = COLLECTIONS[args[1]];
7780
+ if (!spec) throw new Error(`Unknown kind "${args[1]}". One of: ${kinds}`);
7781
+ const body = parsePairs(args[2] ?? [], spec.fields);
7782
+ const missing = spec.required.filter((f) => !body[f]);
7783
+ if (missing.length) {
7784
+ throw new Error(
7785
+ `A ${spec.label} needs ${missing.join(" and ")}. Accepted: ${spec.fields.join(", ")}`
7786
+ );
7787
+ }
7788
+ const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}/${spec.path}`, {
7789
+ method: "POST",
7790
+ body
7791
+ });
7792
+ ok(res, () => {
7793
+ line(import_picocolors17.default.green(`Added the ${spec.label}.`) + " " + import_picocolors17.default.dim(res?.id ?? ""));
7794
+ line(
7795
+ import_picocolors17.default.dim("Not live yet \u2014 run ") + import_picocolors17.default.bold(`workser agent-cloud publish ${args[0]}`) + import_picocolors17.default.dim(" when the setup is ready.")
7796
+ );
7797
+ });
7798
+ })
7799
+ );
7800
+ cloud.command("remove <agentId> <kind> <itemId>").description(`Take something away from an agent (${kinds})`).action(
7801
+ action(async ({ ctx, args }) => {
7802
+ const spec = COLLECTIONS[args[1]];
7803
+ if (!spec) throw new Error(`Unknown kind "${args[1]}". One of: ${kinds}`);
7804
+ const res = await api(
7805
+ ctx,
7806
+ `/v1/agent-cloud/${encodeURIComponent(args[0])}/${spec.path}/${encodeURIComponent(args[2])}`,
7807
+ { method: "DELETE" }
7808
+ );
7809
+ ok(res, () => line(import_picocolors17.default.green(`Removed the ${spec.label}.`)));
7810
+ })
7811
+ );
7812
+ cloud.command("set <agentId> [pairs...]").description(
7813
+ "Change the brief or the model. Pairs: name, description, system_prompt, handle, default_provider, default_model"
7814
+ ).action(
7815
+ action(async ({ ctx, args }) => {
7816
+ const body = parsePairs(args[1] ?? [], [
7817
+ "name",
7818
+ "description",
7819
+ "system_prompt",
7820
+ "handle",
7821
+ "default_provider",
7822
+ "default_model"
7823
+ ]);
7824
+ if (!Object.keys(body).length) {
7825
+ throw new Error(
7826
+ 'Nothing to change. Example: workser agent-cloud set <id> system_prompt="Always check stock first"'
7827
+ );
7828
+ }
7829
+ const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}`, {
7830
+ method: "PATCH",
7831
+ body
7832
+ });
7833
+ ok(res, () => {
7834
+ line(import_picocolors17.default.green("Saved."));
7835
+ line(
7836
+ import_picocolors17.default.dim("Not live yet \u2014 run ") + import_picocolors17.default.bold(`workser agent-cloud publish ${args[0]}`) + import_picocolors17.default.dim(".")
7837
+ );
7838
+ });
7839
+ })
7840
+ );
7841
+ cloud.command("publish <agentId>").description("Put the current setup live \u2014 nothing takes effect until this runs").option("--note <text>", "What changed, for the version history").action(
7842
+ action(async ({ ctx, args, opts }) => {
7843
+ const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}/publish`, {
7844
+ method: "POST",
7845
+ body: { changelog: opts.note }
7846
+ });
7847
+ ok(
7848
+ res,
7849
+ () => line(import_picocolors17.default.green(`Live${res?.version ? ` \u2014 version ${res.version}` : ""}.`))
7850
+ );
7851
+ })
7852
+ );
7853
+ cloud.command("try <agentId> <message>").description("Run the current setup WITHOUT publishing it").action(
7854
+ action(async ({ ctx, args }) => {
7855
+ const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}/test-runs`, {
7856
+ method: "POST",
7857
+ body: { input: { message: args[1] } }
7858
+ });
7859
+ ok(res, () => {
7860
+ line(import_picocolors17.default.green("Trying it \u2014 nothing has gone live."));
7861
+ if (res?.run_id) {
7862
+ line(
7863
+ import_picocolors17.default.dim("Watch it: ") + import_picocolors17.default.bold(`workser agent-cloud runs ${res.run_id}`)
7864
+ );
7865
+ }
7866
+ });
7867
+ })
7868
+ );
7869
+ cloud.command("machines").description("The pre-built machines an agent can run on").action(
7870
+ action(async ({ ctx }) => {
7871
+ const res = await api(ctx, "/v1/agent-cloud/catalog/machines");
7872
+ ok(res, () => {
7873
+ for (const m of res?.machines ?? []) {
7874
+ line(`${import_picocolors17.default.bold(m.label)} ${import_picocolors17.default.dim(m.alias)}`);
7875
+ line(" " + import_picocolors17.default.dim(m.description));
7876
+ }
7877
+ });
7878
+ })
7879
+ );
7880
+ cloud.command("models").description("Models this organisation can run an agent on, cheapest first").option("--all", "Include models that need your own provider key").action(
7881
+ action(async ({ ctx, opts }) => {
7882
+ const res = await api(ctx, "/v1/agent-cloud/catalog/models/live");
7883
+ const models = (res?.models ?? []).filter(
7884
+ (m) => opts.all || m.credit_tier === "PLATFORM_CREDITS"
7885
+ );
7886
+ ok(res, () => {
7887
+ if (!models.length) {
7888
+ warn("The live model list could not be read.");
7889
+ return;
7890
+ }
7891
+ for (const m of models.slice(0, 40)) {
7892
+ const price = typeof m.input_price_per_million_usd === "number" ? `$${m.input_price_per_million_usd.toFixed(2)}/M in` : "price unknown";
7893
+ const byok = m.credit_tier === "PLATFORM_CREDITS" ? "" : import_picocolors17.default.yellow(" needs your own key");
7894
+ line(`${import_picocolors17.default.bold(m.id)} ${import_picocolors17.default.dim(price)}${byok}`);
7895
+ }
7896
+ });
7897
+ })
7898
+ );
7899
+ }
7900
+ function printRun(run, compact = false) {
7901
+ const status = String(run?.status ?? "").toLowerCase();
7902
+ const colour2 = status === "completed" ? import_picocolors17.default.green : status === "failed" ? import_picocolors17.default.red : import_picocolors17.default.yellow;
7903
+ line(
7904
+ `${colour2(status || "unknown")} ${import_picocolors17.default.bold(run?.id ?? "")}` + (run?.duration_ms ? ` ${import_picocolors17.default.dim(formatDuration(run.duration_ms))}` : "")
7905
+ );
7906
+ const breakdown = run?.cost_breakdown;
7907
+ if (breakdown) {
7908
+ if (!breakdown.settled) {
7909
+ line(" " + import_picocolors17.default.dim("cost: still being worked out"));
7910
+ } else {
7911
+ line(" " + import_picocolors17.default.dim(`cost: $${Number(breakdown.total_usd).toFixed(4)}`));
7912
+ line(
7913
+ " " + import_picocolors17.default.dim(
7914
+ `model $${Number(breakdown.model_usd).toFixed(4)} \xB7 infrastructure $${Number(breakdown.infrastructure_usd).toFixed(4)}`
7915
+ )
7916
+ );
7917
+ }
7918
+ } else if (run?.cost_usd !== void 0 && run?.cost_usd !== null) {
7919
+ line(" " + import_picocolors17.default.dim(`model cost: $${Number(run.cost_usd).toFixed(4)}`));
7920
+ }
7921
+ if (!compact && run?.output) {
7922
+ line("");
7923
+ line(typeof run.output === "string" ? run.output : JSON.stringify(run.output, null, 2));
7924
+ }
7925
+ if (run?.error?.message) line(" " + import_picocolors17.default.red(run.error.message));
7926
+ }
7927
+ function formatDuration(ms) {
7928
+ if (ms < 1e3) return `${ms}ms`;
7929
+ const seconds = Math.round(ms / 1e3);
7930
+ if (seconds < 60) return `${seconds}s`;
7931
+ const minutes = Math.floor(seconds / 60);
7932
+ return `${minutes}m ${seconds % 60}s`;
7933
+ }
7934
+ function parsePairs(pairs, allowed) {
7935
+ const out = {};
7936
+ for (const raw of pairs) {
7937
+ const at = raw.indexOf("=");
7938
+ if (at < 1) {
7939
+ throw new Error(`"${raw}" is not a key=value pair.`);
7940
+ }
7941
+ const key = raw.slice(0, at).trim();
7942
+ const value = raw.slice(at + 1);
7943
+ if (!allowed.includes(key)) {
7944
+ throw new Error(`"${key}" is not a field here. Accepted: ${allowed.join(", ")}`);
7945
+ }
7946
+ if (value) out[key] = value;
7947
+ }
7948
+ return out;
7949
+ }
7950
+
7951
+ // src/commands/verify.ts
7952
+ var import_picocolors18 = __toESM(require_picocolors(), 1);
7464
7953
  function registerVerify(program3) {
7465
7954
  program3.command("verify").description(
7466
7955
  "Run the project's checks (typecheck/lint/build) \u2014 use before declaring a task done"
@@ -7482,23 +7971,23 @@ function registerVerify(program3) {
7482
7971
  function printVerify(res) {
7483
7972
  if (!res) return;
7484
7973
  if (!res.checks?.length) {
7485
- line(import_picocolors17.default.dim(res.note ?? "No checks detected."));
7974
+ line(import_picocolors18.default.dim(res.note ?? "No checks detected."));
7486
7975
  return;
7487
7976
  }
7488
7977
  for (const c of res.checks) {
7489
7978
  line(
7490
- ` ${c.ok ? import_picocolors17.default.green("\u2713") : import_picocolors17.default.red("\u2717")} ${c.name}${c.ok ? "" : import_picocolors17.default.dim(` (exit ${c.exitCode})`)}`
7979
+ ` ${c.ok ? import_picocolors18.default.green("\u2713") : import_picocolors18.default.red("\u2717")} ${c.name}${c.ok ? "" : import_picocolors18.default.dim(` (exit ${c.exitCode})`)}`
7491
7980
  );
7492
7981
  }
7493
7982
  if (res.ok) success("All checks passed");
7494
7983
  else
7495
7984
  line(
7496
- import_picocolors17.default.red("Some checks failed \u2014 fix the errors above and re-run ") + import_picocolors17.default.bold("workser verify") + import_picocolors17.default.red(".")
7985
+ import_picocolors18.default.red("Some checks failed \u2014 fix the errors above and re-run ") + import_picocolors18.default.bold("workser verify") + import_picocolors18.default.red(".")
7497
7986
  );
7498
7987
  }
7499
7988
 
7500
7989
  // src/commands/checkpoint.ts
7501
- var import_picocolors18 = __toESM(require_picocolors(), 1);
7990
+ var import_picocolors19 = __toESM(require_picocolors(), 1);
7502
7991
  function registerCheckpoint(program3) {
7503
7992
  program3.command("checkpoint [label]").description(
7504
7993
  "Save the current state of this folder so you can come back to it"
@@ -7515,8 +8004,8 @@ function registerCheckpoint(program3) {
7515
8004
  ok(res, () => {
7516
8005
  const p = res?.point;
7517
8006
  success(`Saved a checkpoint${p?.label ? `: ${p.label}` : ""}`);
7518
- if (p?.ref) line(import_picocolors18.default.dim(` ${p.ref.slice(0, 7)}`));
7519
- line(import_picocolors18.default.dim(" Come back to it with `workser restore`."));
8007
+ if (p?.ref) line(import_picocolors19.default.dim(` ${p.ref.slice(0, 7)}`));
8008
+ line(import_picocolors19.default.dim(" Come back to it with `workser restore`."));
7520
8009
  });
7521
8010
  })
7522
8011
  );
@@ -7542,12 +8031,12 @@ function registerCheckpoint(program3) {
7542
8031
  );
7543
8032
  if (res?.filesChanged) {
7544
8033
  line(
7545
- import_picocolors18.default.dim(
8034
+ import_picocolors19.default.dim(
7546
8035
  ` ${res.filesChanged} file${res.filesChanged === 1 ? "" : "s"} changed`
7547
8036
  )
7548
8037
  );
7549
8038
  }
7550
- line(import_picocolors18.default.dim(" This is reversible: `workser restore` again."));
8039
+ line(import_picocolors19.default.dim(" This is reversible: `workser restore` again."));
7551
8040
  });
7552
8041
  })
7553
8042
  );
@@ -7564,25 +8053,25 @@ function registerCheckpoint(program3) {
7564
8053
  function printPoints(points) {
7565
8054
  if (!points.length) {
7566
8055
  info("No checkpoints yet for this folder.");
7567
- line(import_picocolors18.default.dim(" Take one with `workser checkpoint`."));
8056
+ line(import_picocolors19.default.dim(" Take one with `workser checkpoint`."));
7568
8057
  return;
7569
8058
  }
7570
- line(import_picocolors18.default.bold("Checkpoints"));
8059
+ line(import_picocolors19.default.bold("Checkpoints"));
7571
8060
  for (const p of points) {
7572
8061
  const when = p.at ? new Date(p.at).toLocaleString() : "";
7573
8062
  line(
7574
- ` ${import_picocolors18.default.dim(p.ref.slice(0, 7))} ${p.label}${when ? import_picocolors18.default.dim(` ${when}`) : ""}`
8063
+ ` ${import_picocolors19.default.dim(p.ref.slice(0, 7))} ${p.label}${when ? import_picocolors19.default.dim(` ${when}`) : ""}`
7575
8064
  );
7576
8065
  }
7577
8066
  line(
7578
- import_picocolors18.default.dim(
8067
+ import_picocolors19.default.dim(
7579
8068
  "\nGo back with `workser restore <ref>`, or just `workser restore` for the newest."
7580
8069
  )
7581
8070
  );
7582
8071
  }
7583
8072
 
7584
8073
  // src/commands/sync.ts
7585
- var import_picocolors19 = __toESM(require_picocolors(), 1);
8074
+ var import_picocolors20 = __toESM(require_picocolors(), 1);
7586
8075
  function registerSync(program3) {
7587
8076
  program3.command("sync").description(
7588
8077
  "Reconcile this folder with the copy Workser holds (pull, then push)"
@@ -7609,7 +8098,7 @@ function registerSync(program3) {
7609
8098
  warn(res?.message ?? "Couldn't sync this folder.");
7610
8099
  if (res?.state === "diverged") {
7611
8100
  line(
7612
- import_picocolors19.default.dim(
8101
+ import_picocolors20.default.dim(
7613
8102
  " This folder and Workser's copy have both changed. Open Workser to resolve it."
7614
8103
  )
7615
8104
  );
@@ -7621,7 +8110,7 @@ function registerSync(program3) {
7621
8110
  return;
7622
8111
  }
7623
8112
  success("Synced");
7624
- if (res?.ref) line(import_picocolors19.default.dim(` ${String(res.ref).slice(0, 7)}`));
8113
+ if (res?.ref) line(import_picocolors20.default.dim(` ${String(res.ref).slice(0, 7)}`));
7625
8114
  });
7626
8115
  if (refused) process.exitCode = 1;
7627
8116
  })
@@ -7629,7 +8118,7 @@ function registerSync(program3) {
7629
8118
  }
7630
8119
 
7631
8120
  // src/commands/workflow.ts
7632
- var import_picocolors20 = __toESM(require_picocolors(), 1);
8121
+ var import_picocolors21 = __toESM(require_picocolors(), 1);
7633
8122
  function registerWorkflow(program3) {
7634
8123
  const wf = program3.command("workflow").description("Create, run, and inspect workflow automations for the project");
7635
8124
  wf.command("list").description("List the project's workflows").action(
@@ -7637,10 +8126,10 @@ function registerWorkflow(program3) {
7637
8126
  const projectId = requireProject(ctx);
7638
8127
  const items = await api(ctx, `/v1/projects/${projectId}/workflows`);
7639
8128
  ok(items, () => {
7640
- if (!items?.length) return line(import_picocolors20.default.dim("No workflows yet. `workser workflow create`."));
8129
+ if (!items?.length) return line(import_picocolors21.default.dim("No workflows yet. `workser workflow create`."));
7641
8130
  for (const w of items) {
7642
- const status = w.is_active ? import_picocolors20.default.green("active") : import_picocolors20.default.dim("inactive");
7643
- line(`${w.id} ${import_picocolors20.default.bold(w.name ?? "Untitled")} ${status}`);
8131
+ const status = w.is_active ? import_picocolors21.default.green("active") : import_picocolors21.default.dim("inactive");
8132
+ line(`${w.id} ${import_picocolors21.default.bold(w.name ?? "Untitled")} ${status}`);
7644
8133
  }
7645
8134
  });
7646
8135
  })
@@ -7652,7 +8141,7 @@ function registerWorkflow(program3) {
7652
8141
  const res = await api(ctx, `/v1/projects/${projectId}/workflows`, {
7653
8142
  body: { name: args[0], ...extra }
7654
8143
  });
7655
- ok(res, () => line(`Created workflow ${import_picocolors20.default.bold(res.id)}.`));
8144
+ ok(res, () => line(`Created workflow ${import_picocolors21.default.bold(res.id)}.`));
7656
8145
  })
7657
8146
  );
7658
8147
  wf.command("get <id>").description("Show a workflow's full definition").action(
@@ -7687,8 +8176,8 @@ function registerWorkflow(program3) {
7687
8176
  action(async ({ ctx, args }) => {
7688
8177
  const items = await api(ctx, `/v1/workflows/${args[0]}/executions`);
7689
8178
  ok(items, () => {
7690
- if (!items?.length) return line(import_picocolors20.default.dim("No runs yet."));
7691
- for (const e of items) line(`${e.id} ${e.status ?? ""} ${import_picocolors20.default.dim(e.started_at ?? "")}`);
8179
+ if (!items?.length) return line(import_picocolors21.default.dim("No runs yet."));
8180
+ for (const e of items) line(`${e.id} ${e.status ?? ""} ${import_picocolors21.default.dim(e.started_at ?? "")}`);
7692
8181
  });
7693
8182
  })
7694
8183
  );
@@ -7696,15 +8185,15 @@ function registerWorkflow(program3) {
7696
8185
  action(async ({ ctx, args }) => {
7697
8186
  const items = await api(ctx, `/v1/node-types`, { query: { q: args[0] } });
7698
8187
  ok(items, () => {
7699
- if (!items?.length) return line(import_picocolors20.default.dim("No matching node types."));
7700
- for (const n of items) line(`${n.name ?? n.type} ${import_picocolors20.default.dim(n.category ?? "")}`);
8188
+ if (!items?.length) return line(import_picocolors21.default.dim("No matching node types."));
8189
+ for (const n of items) line(`${n.name ?? n.type} ${import_picocolors21.default.dim(n.category ?? "")}`);
7701
8190
  });
7702
8191
  })
7703
8192
  );
7704
8193
  }
7705
8194
 
7706
8195
  // src/commands/connection.ts
7707
- var import_picocolors21 = __toESM(require_picocolors(), 1);
8196
+ var import_picocolors22 = __toESM(require_picocolors(), 1);
7708
8197
  function registerConnection(program3) {
7709
8198
  const connection = program3.command("connection").description("Connect and use third-party app connections (Gmail, Slack, Stripe, ...)");
7710
8199
  connection.command("list").description("List connectable toolkits and this project's existing connections").option("--toolkit <slug>", "filter connections to one toolkit").action(
@@ -7717,8 +8206,8 @@ function registerConnection(program3) {
7717
8206
  ok({ catalog, connections }, () => {
7718
8207
  const connected = new Set((connections ?? []).map((c) => c.toolkit ?? c.composio_app));
7719
8208
  for (const t of catalog ?? []) {
7720
- const status = connected.has(t.slug) ? import_picocolors21.default.green("connected") : import_picocolors21.default.dim("not connected");
7721
- line(`${t.slug} ${import_picocolors21.default.bold(t.name ?? t.slug)} ${status}`);
8209
+ const status = connected.has(t.slug) ? import_picocolors22.default.green("connected") : import_picocolors22.default.dim("not connected");
8210
+ line(`${t.slug} ${import_picocolors22.default.bold(t.name ?? t.slug)} ${status}`);
7722
8211
  }
7723
8212
  });
7724
8213
  })
@@ -7730,9 +8219,9 @@ function registerConnection(program3) {
7730
8219
  query: { q: args[0], toolkit: opts.toolkit, limit: opts.limit }
7731
8220
  });
7732
8221
  ok(items, () => {
7733
- if (!items?.length) return line(import_picocolors21.default.dim("No matching actions."));
8222
+ if (!items?.length) return line(import_picocolors22.default.dim("No matching actions."));
7734
8223
  for (const t of items) {
7735
- line(`${t.slug} ${import_picocolors21.default.dim(`[${t.toolkit}]`)} ${t.description ?? ""}`);
8224
+ line(`${t.slug} ${import_picocolors22.default.dim(`[${t.toolkit}]`)} ${t.description ?? ""}`);
7736
8225
  }
7737
8226
  });
7738
8227
  })
@@ -7749,7 +8238,7 @@ function registerConnection(program3) {
7749
8238
  });
7750
8239
  ok(
7751
8240
  res,
7752
- () => res.oauth_url ? line(`Open this URL to finish connecting: ${import_picocolors21.default.underline(res.oauth_url)}`) : line(`Connection ${res.connection_id} is ${res.status}.`)
8241
+ () => res.oauth_url ? line(`Open this URL to finish connecting: ${import_picocolors22.default.underline(res.oauth_url)}`) : line(`Connection ${res.connection_id} is ${res.status}.`)
7753
8242
  );
7754
8243
  })
7755
8244
  );
@@ -7767,8 +8256,8 @@ function registerConnection(program3) {
7767
8256
  const projectId = requireProject(ctx);
7768
8257
  const items = await api(ctx, `/v1/projects/${projectId}/integrations/${args[0]}/tools`);
7769
8258
  ok(items, () => {
7770
- if (!items?.length) return line(import_picocolors21.default.dim("No tools found."));
7771
- for (const t of items) line(`${t.slug} ${import_picocolors21.default.dim(t.description ?? "")}`);
8259
+ if (!items?.length) return line(import_picocolors22.default.dim("No tools found."));
8260
+ for (const t of items) line(`${t.slug} ${import_picocolors22.default.dim(t.description ?? "")}`);
7772
8261
  });
7773
8262
  })
7774
8263
  );
@@ -7784,7 +8273,7 @@ function registerConnection(program3) {
7784
8273
  }
7785
8274
 
7786
8275
  // src/commands/tool.ts
7787
- var import_picocolors22 = __toESM(require_picocolors(), 1);
8276
+ var import_picocolors23 = __toESM(require_picocolors(), 1);
7788
8277
  function registerTool(program3) {
7789
8278
  const tool = program3.command("tool").description(
7790
8279
  "Computer-use tools: filesystem, shell, screenshot, input control, clipboard, notifications, basic browser"
@@ -7793,7 +8282,7 @@ function registerTool(program3) {
7793
8282
  action(async ({ ctx }) => {
7794
8283
  const tools = await api(ctx, "/v1/tool/list");
7795
8284
  ok(tools, () => {
7796
- if (!tools?.length) return line(import_picocolors22.default.dim("No tools available."));
8285
+ if (!tools?.length) return line(import_picocolors23.default.dim("No tools available."));
7797
8286
  const byCategory = /* @__PURE__ */ new Map();
7798
8287
  for (const t of tools) {
7799
8288
  const list = byCategory.get(t.category) ?? [];
@@ -7801,9 +8290,9 @@ function registerTool(program3) {
7801
8290
  byCategory.set(t.category, list);
7802
8291
  }
7803
8292
  for (const [category, items] of byCategory) {
7804
- line(import_picocolors22.default.bold(category) + ":");
8293
+ line(import_picocolors23.default.bold(category) + ":");
7805
8294
  for (const t of items) {
7806
- line(` ${t.name} ${import_picocolors22.default.dim(t.description ?? "")}`);
8295
+ line(` ${t.name} ${import_picocolors23.default.dim(t.description ?? "")}`);
7807
8296
  }
7808
8297
  }
7809
8298
  });
@@ -7821,7 +8310,7 @@ function registerTool(program3) {
7821
8310
  }
7822
8311
 
7823
8312
  // src/commands/memory.ts
7824
- var import_picocolors23 = __toESM(require_picocolors(), 1);
8313
+ var import_picocolors24 = __toESM(require_picocolors(), 1);
7825
8314
  function registerMemory(program3) {
7826
8315
  const memory = program3.command("memory").description("Durable, cross-conversation project memory (shared with cloud agents on the same project)");
7827
8316
  memory.command("add <content>").description("Store something worth remembering across future conversations").option("--metadata <json>", "extra metadata for filtering, as a JSON string").option("--id <customId>", "custom id for dedup/updates").action(
@@ -7845,9 +8334,9 @@ function registerMemory(program3) {
7845
8334
  });
7846
8335
  ok(res, () => {
7847
8336
  const results = res?.results ?? res ?? [];
7848
- if (!results?.length) return line(import_picocolors23.default.dim("No matching memories."));
8337
+ if (!results?.length) return line(import_picocolors24.default.dim("No matching memories."));
7849
8338
  for (const r of results) {
7850
- line(`${import_picocolors23.default.dim(r.id ?? "?")} ${r.memory ?? r.content ?? ""}`);
8339
+ line(`${import_picocolors24.default.dim(r.id ?? "?")} ${r.memory ?? r.content ?? ""}`);
7851
8340
  }
7852
8341
  });
7853
8342
  })
@@ -7864,7 +8353,7 @@ function registerMemory(program3) {
7864
8353
  }
7865
8354
 
7866
8355
  // src/commands/note.ts
7867
- var import_picocolors24 = __toESM(require_picocolors(), 1);
8356
+ var import_picocolors25 = __toESM(require_picocolors(), 1);
7868
8357
  function registerNote(program3) {
7869
8358
  program3.command("note <text>").description("Leave a fact the rest of the team will need").addHelpText(
7870
8359
  "after",
@@ -7901,14 +8390,14 @@ function registerNote(program3) {
7901
8390
  }
7902
8391
  ok(res, () => {
7903
8392
  success("Noted for the team.");
7904
- line(import_picocolors24.default.dim(` ${text}`));
8393
+ line(import_picocolors25.default.dim(` ${text}`));
7905
8394
  });
7906
8395
  })
7907
8396
  );
7908
8397
  }
7909
8398
 
7910
8399
  // src/commands/business.ts
7911
- var import_picocolors25 = __toESM(require_picocolors(), 1);
8400
+ var import_picocolors26 = __toESM(require_picocolors(), 1);
7912
8401
  var RESOURCE_PATHS = {
7913
8402
  "business-config": "business-config",
7914
8403
  "business-settings": "business-settings",
@@ -7968,7 +8457,7 @@ function registerBusiness(program3) {
7968
8457
  const projectId = requireProject(ctx);
7969
8458
  const [resource] = args;
7970
8459
  const res = await api(ctx, businessPath(projectId, resource), { body: JSON.parse(opts.body) });
7971
- ok(res, () => line(`Created ${resource} ${import_picocolors25.default.bold(res?.id ?? "")}.`));
8460
+ ok(res, () => line(`Created ${resource} ${import_picocolors26.default.bold(res?.id ?? "")}.`));
7972
8461
  })
7973
8462
  );
7974
8463
  biz.command("update <resource> <id>").description("Update a record by id (PATCH/PUT \u2014 matches the underlying route)").option("--body <json>", "changed fields as a JSON object string", "{}").action(
@@ -8010,7 +8499,7 @@ function businessPath(projectId, resource, subpath) {
8010
8499
  }
8011
8500
 
8012
8501
  // src/commands/artifact.ts
8013
- var import_picocolors26 = __toESM(require_picocolors(), 1);
8502
+ var import_picocolors27 = __toESM(require_picocolors(), 1);
8014
8503
  import { existsSync as existsSync2, statSync } from "fs";
8015
8504
  import { resolve as resolve3, basename as basename3 } from "path";
8016
8505
  var KINDS = [
@@ -8107,7 +8596,7 @@ function registerArtifact(program3) {
8107
8596
  ok(
8108
8597
  res,
8109
8598
  () => success(
8110
- `Recorded ${import_picocolors26.default.bold(res?.title ?? "artifact")}${res?.kind ? import_picocolors26.default.dim(` (${res.kind})`) : ""}`
8599
+ `Recorded ${import_picocolors27.default.bold(res?.title ?? "artifact")}${res?.kind ? import_picocolors27.default.dim(` (${res.kind})`) : ""}`
8111
8600
  )
8112
8601
  );
8113
8602
  })
@@ -8139,13 +8628,13 @@ function registerArtifact(program3) {
8139
8628
  artifact.command("run").description("Show the task/conversation this agent run is attached to").action(
8140
8629
  action(async ({ ctx }) => {
8141
8630
  const res = await api(ctx, `/v1/runs/${runTarget(ctx)}`);
8142
- ok(res, () => printRun(res));
8631
+ ok(res, () => printRun2(res));
8143
8632
  })
8144
8633
  );
8145
8634
  }
8146
8635
  function printArtifacts(rows) {
8147
8636
  if (!rows.length) {
8148
- line(import_picocolors26.default.dim("Nothing produced yet."));
8637
+ line(import_picocolors27.default.dim("Nothing produced yet."));
8149
8638
  return;
8150
8639
  }
8151
8640
  const byStep = /* @__PURE__ */ new Map();
@@ -8155,26 +8644,26 @@ function printArtifacts(rows) {
8155
8644
  byStep.set(r.subtask_id, list);
8156
8645
  }
8157
8646
  for (const [stepId, items] of byStep) {
8158
- line(import_picocolors26.default.bold(`step ${stepId}`));
8647
+ line(import_picocolors27.default.bold(`step ${stepId}`));
8159
8648
  for (const a of items) {
8160
- const flag = a.promoted_at ? import_picocolors26.default.green(" *") : " ";
8649
+ const flag = a.promoted_at ? import_picocolors27.default.green(" *") : " ";
8161
8650
  const where = a.local_path || a.cloud_url || "";
8162
8651
  line(
8163
- `${flag} ${import_picocolors26.default.dim(`[${a.kind}]`)} ${a.title ?? "(untitled)"}` + (where ? import_picocolors26.default.dim(` ${where}`) : "")
8652
+ `${flag} ${import_picocolors27.default.dim(`[${a.kind}]`)} ${a.title ?? "(untitled)"}` + (where ? import_picocolors27.default.dim(` ${where}`) : "")
8164
8653
  );
8165
- if (a.description) line(import_picocolors26.default.dim(` ${a.description}`));
8654
+ if (a.description) line(import_picocolors27.default.dim(` ${a.description}`));
8166
8655
  }
8167
8656
  line("");
8168
8657
  }
8169
- line(import_picocolors26.default.dim("* = handed over as a deliverable; the rest is working material."));
8658
+ line(import_picocolors27.default.dim("* = handed over as a deliverable; the rest is working material."));
8170
8659
  }
8171
- function printRun(run) {
8660
+ function printRun2(run) {
8172
8661
  if (!run) return;
8173
- line(` run ${import_picocolors26.default.bold(run.runId)}`);
8662
+ line(` run ${import_picocolors27.default.bold(run.runId)}`);
8174
8663
  if (run.taskId) line(` task ${run.taskId}`);
8175
8664
  if (run.conversationId) line(` chat ${run.conversationId}`);
8176
8665
  if (run.projectId) line(` project ${run.projectId}`);
8177
- if (run.cwd) line(` folder ${import_picocolors26.default.dim(run.cwd)}`);
8666
+ if (run.cwd) line(` folder ${import_picocolors27.default.dim(run.cwd)}`);
8178
8667
  }
8179
8668
 
8180
8669
  // src/commands/image.ts
@@ -8355,7 +8844,7 @@ function registerAudio(program3) {
8355
8844
  }
8356
8845
 
8357
8846
  // src/commands/ask.ts
8358
- var import_picocolors27 = __toESM(require_picocolors(), 1);
8847
+ var import_picocolors28 = __toESM(require_picocolors(), 1);
8359
8848
  var TYPES = [
8360
8849
  "input",
8361
8850
  "choice",
@@ -8433,7 +8922,7 @@ function registerAsk(program3) {
8433
8922
  code: "bad_request"
8434
8923
  });
8435
8924
  }
8436
- info(import_picocolors27.default.dim("Waiting for the user to answer\u2026"));
8925
+ info(import_picocolors28.default.dim("Waiting for the user to answer\u2026"));
8437
8926
  const res = await api(ctx, `/v1/runs/${runTarget(ctx)}/ask`, {
8438
8927
  body: {
8439
8928
  type,
@@ -8461,12 +8950,12 @@ function deriveTitle(message) {
8461
8950
  function printAnswer(res) {
8462
8951
  if (!res) return;
8463
8952
  if (res.status === "answered") {
8464
- line(` ${import_picocolors27.default.green("answered")}`);
8953
+ line(` ${import_picocolors28.default.green("answered")}`);
8465
8954
  const value = extract(res.response);
8466
8955
  if (value) line(` ${value}`);
8467
8956
  return;
8468
8957
  }
8469
- line(` ${import_picocolors27.default.yellow(res.status)} ${import_picocolors27.default.dim(res.reason ?? "")}`);
8958
+ line(` ${import_picocolors28.default.yellow(res.status)} ${import_picocolors28.default.dim(res.reason ?? "")}`);
8470
8959
  }
8471
8960
  function extract(response) {
8472
8961
  if (response == null) return "";
@@ -8485,7 +8974,7 @@ function extract(response) {
8485
8974
  }
8486
8975
 
8487
8976
  // src/commands/search.ts
8488
- var import_picocolors28 = __toESM(require_picocolors(), 1);
8977
+ var import_picocolors29 = __toESM(require_picocolors(), 1);
8489
8978
  function registerSearch(program3) {
8490
8979
  program3.command("search <query>").description("Search the web (Google-grounded, server-side)").option("-n, --max-results <n>", "max results", "5").action(
8491
8980
  action(async ({ ctx, args, opts }) => {
@@ -8498,9 +8987,9 @@ function registerSearch(program3) {
8498
8987
  line("");
8499
8988
  }
8500
8989
  const results = res?.results ?? [];
8501
- if (!results.length) return line(import_picocolors28.default.dim("No results."));
8990
+ if (!results.length) return line(import_picocolors29.default.dim("No results."));
8502
8991
  for (const r of results) {
8503
- line(`${r.title || import_picocolors28.default.dim("(untitled)")} ${import_picocolors28.default.dim(r.url)}`);
8992
+ line(`${r.title || import_picocolors29.default.dim("(untitled)")} ${import_picocolors29.default.dim(r.url)}`);
8504
8993
  }
8505
8994
  });
8506
8995
  })
@@ -8508,7 +8997,7 @@ function registerSearch(program3) {
8508
8997
  }
8509
8998
 
8510
8999
  // src/commands/board.ts
8511
- var import_picocolors29 = __toESM(require_picocolors(), 1);
9000
+ var import_picocolors30 = __toESM(require_picocolors(), 1);
8512
9001
 
8513
9002
  // src/commands/record-step.ts
8514
9003
  async function recordEntityStep(ctx, opts) {
@@ -8547,7 +9036,7 @@ function registerBoard(program3) {
8547
9036
  }
8548
9037
  ok(rows, () => {
8549
9038
  if (!rows.length) {
8550
- line(import_picocolors29.default.dim("No cards on the Board yet."));
9039
+ line(import_picocolors30.default.dim("No cards on the Board yet."));
8551
9040
  return;
8552
9041
  }
8553
9042
  for (const r of rows) line(formatRow(r));
@@ -8562,7 +9051,7 @@ function registerBoard(program3) {
8562
9051
  `/v1/projects/${projectId}/work-items/${args[0]}`
8563
9052
  );
8564
9053
  ok(row, () => {
8565
- line(`${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.id)}`);
9054
+ line(`${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.id)}`);
8566
9055
  line(`${statusTag(row.status)} priority ${row.priority}`);
8567
9056
  if (row.ownerHuman) line(`owner: ${row.ownerHuman}`);
8568
9057
  if (row.labels?.length) line(`labels: ${row.labels.join(", ")}`);
@@ -8603,7 +9092,7 @@ ${row.description}`);
8603
9092
  refId: row?.id,
8604
9093
  output: { workItem: row }
8605
9094
  });
8606
- ok(row, () => line(`Created work item ${import_picocolors29.default.bold(row?.id ?? "")} \u2014 ${title}`));
9095
+ ok(row, () => line(`Created work item ${import_picocolors30.default.bold(row?.id ?? "")} \u2014 ${title}`));
8607
9096
  })
8608
9097
  );
8609
9098
  board.command("update <id>").description("Change fields on a card \u2014 pass only what changes").option("--title <text>", "new title").option("--description <text>", "new description").option("--status <value>", STATUSES.join(" | ")).option("--priority <value>", PRIORITIES.join(" | ")).option(
@@ -8637,7 +9126,7 @@ ${row.description}`);
8637
9126
  );
8638
9127
  }
8639
9128
  const row = await patchItem(ctx, projectId, String(args[0]), body);
8640
- ok(row, () => line(`Updated ${import_picocolors29.default.bold(row.id)} \u2014 ${row.title} ${statusTag(row.status)}`));
9129
+ ok(row, () => line(`Updated ${import_picocolors30.default.bold(row.id)} \u2014 ${row.title} ${statusTag(row.status)}`));
8641
9130
  })
8642
9131
  );
8643
9132
  board.command("move <id> <status>").description(
@@ -8648,14 +9137,14 @@ ${row.description}`);
8648
9137
  const status = String(args[1]);
8649
9138
  assertStatus(status);
8650
9139
  const row = await patchItem(ctx, projectId, String(args[0]), { status });
8651
- ok(row, () => line(`Moved ${import_picocolors29.default.bold(row.title)} \u2192 ${statusTag(row.status)}`));
9140
+ ok(row, () => line(`Moved ${import_picocolors30.default.bold(row.title)} \u2192 ${statusTag(row.status)}`));
8652
9141
  })
8653
9142
  );
8654
9143
  board.command("close <id>").description("Shorthand for `board move <id> done`").action(
8655
9144
  action(async ({ ctx, args }) => {
8656
9145
  const projectId = requireProject(ctx);
8657
9146
  const row = await patchItem(ctx, projectId, String(args[0]), { status: "done" });
8658
- ok(row, () => line(`Closed ${import_picocolors29.default.bold(row.title)} ${statusTag(row.status)}`));
9147
+ ok(row, () => line(`Closed ${import_picocolors30.default.bold(row.title)} ${statusTag(row.status)}`));
8659
9148
  })
8660
9149
  );
8661
9150
  }
@@ -8688,23 +9177,23 @@ function assertPriority(value) {
8688
9177
  }
8689
9178
  }
8690
9179
  function formatRow(r) {
8691
- const labels = r.labels?.length ? import_picocolors29.default.dim(` [${r.labels.join(", ")}]`) : "";
8692
- const owner = r.ownerHuman ? import_picocolors29.default.dim(` @${r.ownerHuman}`) : "";
8693
- return `${import_picocolors29.default.dim(r.id)} ${statusTag(r.status)} ${r.title}${labels}${owner}`;
9180
+ const labels = r.labels?.length ? import_picocolors30.default.dim(` [${r.labels.join(", ")}]`) : "";
9181
+ const owner = r.ownerHuman ? import_picocolors30.default.dim(` @${r.ownerHuman}`) : "";
9182
+ return `${import_picocolors30.default.dim(r.id)} ${statusTag(r.status)} ${r.title}${labels}${owner}`;
8694
9183
  }
8695
9184
  function statusTag(status) {
8696
9185
  const label = status.padEnd(11);
8697
- if (status === "done") return import_picocolors29.default.green(label);
8698
- if (status === "in-progress") return import_picocolors29.default.yellow(label);
8699
- if (status === "in-review") return import_picocolors29.default.cyan(label);
8700
- return import_picocolors29.default.dim(label);
9186
+ if (status === "done") return import_picocolors30.default.green(label);
9187
+ if (status === "in-progress") return import_picocolors30.default.yellow(label);
9188
+ if (status === "in-review") return import_picocolors30.default.cyan(label);
9189
+ return import_picocolors30.default.dim(label);
8701
9190
  }
8702
9191
  function collect2(value, previous) {
8703
9192
  return [...previous, value];
8704
9193
  }
8705
9194
 
8706
9195
  // src/commands/task.ts
8707
- var import_picocolors30 = __toESM(require_picocolors(), 1);
9196
+ var import_picocolors31 = __toESM(require_picocolors(), 1);
8708
9197
 
8709
9198
  // src/subtask-attachments.ts
8710
9199
  var MAX_REF_NOTE = 500;
@@ -8818,7 +9307,7 @@ function registerTask(program3) {
8818
9307
  }) ?? [];
8819
9308
  ok(rows, () => {
8820
9309
  if (!rows.length) {
8821
- line(import_picocolors30.default.dim("No tasks on the board yet."));
9310
+ line(import_picocolors31.default.dim("No tasks on the board yet."));
8822
9311
  return;
8823
9312
  }
8824
9313
  for (const r of rows) line(formatRow2(r));
@@ -8927,10 +9416,10 @@ function registerTask(program3) {
8927
9416
  };
8928
9417
  ok(result, () => {
8929
9418
  line(
8930
- `${import_picocolors30.default.green("opened")} ${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.key ?? row.id)}`
9419
+ `${import_picocolors31.default.green("opened")} ${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.key ?? row.id)}`
8931
9420
  );
8932
9421
  if (channelMessage)
8933
- line(import_picocolors30.default.dim("posted to the channel as Project Manager"));
9422
+ line(import_picocolors31.default.dim("posted to the channel as Project Manager"));
8934
9423
  if (channelMessageError) {
8935
9424
  warn(
8936
9425
  `Task opened, but its Project Manager card could not be posted: ${channelMessageError.message}`
@@ -9009,12 +9498,12 @@ function registerTask(program3) {
9009
9498
  ) : null;
9010
9499
  ok(runner ?? row, () => {
9011
9500
  line(
9012
- `${import_picocolors30.default.green("added")} ${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.key ?? row.id)}`
9501
+ `${import_picocolors31.default.green("added")} ${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.key ?? row.id)}`
9013
9502
  );
9014
- if (row.role) line(import_picocolors30.default.dim(`role: ${row.role}`));
9503
+ if (row.role) line(import_picocolors31.default.dim(`role: ${row.role}`));
9015
9504
  if (runner) {
9016
9505
  line(
9017
- import_picocolors30.default.dim(
9506
+ import_picocolors31.default.dim(
9018
9507
  `runs on: ${[opts.agent, opts.model, opts.effort].filter(Boolean).join(" \xB7 ")}`
9019
9508
  )
9020
9509
  );
@@ -9032,7 +9521,7 @@ function registerTask(program3) {
9032
9521
  const rows = row.subtasks ?? [];
9033
9522
  ok(rows, () => {
9034
9523
  if (!rows.length) {
9035
- line(import_picocolors30.default.dim("No subtasks yet."));
9524
+ line(import_picocolors31.default.dim("No subtasks yet."));
9036
9525
  return;
9037
9526
  }
9038
9527
  rows.forEach((r, i) => line(formatSubtask(r, i + 1)));
@@ -9080,7 +9569,7 @@ function registerTask(program3) {
9080
9569
  }
9081
9570
  }
9082
9571
  );
9083
- ok(row, () => line(`${import_picocolors30.default.green("updated")} ${import_picocolors30.default.bold(row.title)}`));
9572
+ ok(row, () => line(`${import_picocolors31.default.green("updated")} ${import_picocolors31.default.bold(row.title)}`));
9084
9573
  })
9085
9574
  );
9086
9575
  subtask.command("remove <id>").description("Remove a subtask (only before the work starts)").action(
@@ -9088,7 +9577,7 @@ function registerTask(program3) {
9088
9577
  await api(ctx, `/v1/project-tasks/${encodeURIComponent(args[0])}`, {
9089
9578
  method: "DELETE"
9090
9579
  });
9091
- ok({ removed: args[0] }, () => line(import_picocolors30.default.green("removed")));
9580
+ ok({ removed: args[0] }, () => line(import_picocolors31.default.green("removed")));
9092
9581
  })
9093
9582
  );
9094
9583
  task.command("move <id> <status>").description(
@@ -9103,7 +9592,7 @@ function registerTask(program3) {
9103
9592
  );
9104
9593
  ok(
9105
9594
  row,
9106
- () => line(`${import_picocolors30.default.green("moved")} ${import_picocolors30.default.bold(row.title)} \u2192 ${args[1]}`)
9595
+ () => line(`${import_picocolors31.default.green("moved")} ${import_picocolors31.default.bold(row.title)} \u2192 ${args[1]}`)
9107
9596
  );
9108
9597
  })
9109
9598
  );
@@ -9119,18 +9608,18 @@ function registerTask(program3) {
9119
9608
  );
9120
9609
  ok(row, () => {
9121
9610
  if (!row?.queued) {
9122
- line(import_picocolors30.default.yellow("could not resume it \u2014 check the step id"));
9611
+ line(import_picocolors31.default.yellow("could not resume it \u2014 check the step id"));
9123
9612
  return;
9124
9613
  }
9125
9614
  const started = row.started ?? 0;
9126
9615
  if (started > 0) {
9127
9616
  line(
9128
- `${import_picocolors30.default.green("resumed")} \u2014 ${started} step${started === 1 ? "" : "s"} started`
9617
+ `${import_picocolors31.default.green("resumed")} \u2014 ${started} step${started === 1 ? "" : "s"} started`
9129
9618
  );
9130
9619
  return;
9131
9620
  }
9132
9621
  line(
9133
- `${import_picocolors30.default.green("resumed")} \u2014 it is queued, but nothing started yet. Check the plan is approved and that no step is blocking the rest.`
9622
+ `${import_picocolors31.default.green("resumed")} \u2014 it is queued, but nothing started yet. Check the plan is approved and that no step is blocking the rest.`
9134
9623
  );
9135
9624
  });
9136
9625
  })
@@ -9144,11 +9633,11 @@ function registerTask(program3) {
9144
9633
  );
9145
9634
  ok(row, () => {
9146
9635
  if (row?.reopened) {
9147
- line(`${import_picocolors30.default.green("sent back")} \u2014 it will be picked up again`);
9636
+ line(`${import_picocolors31.default.green("sent back")} \u2014 it will be picked up again`);
9148
9637
  return;
9149
9638
  }
9150
9639
  line(
9151
- import_picocolors30.default.yellow(
9640
+ import_picocolors31.default.yellow(
9152
9641
  row?.reason === "already_open" ? "already waiting to be picked up \u2014 nothing to send back" : row?.reason === "still_working" ? "still working \u2014 let it finish before sending it back" : "could not send that step back"
9153
9642
  )
9154
9643
  );
@@ -9165,7 +9654,7 @@ function registerTask(program3) {
9165
9654
  `/v1/project-tasks/${encodeURIComponent(id)}/dispatch-check`,
9166
9655
  { method: "POST" }
9167
9656
  );
9168
- ok(row, () => line(import_picocolors30.default.green("approved \u2014 you may start")));
9657
+ ok(row, () => line(import_picocolors31.default.green("approved \u2014 you may start")));
9169
9658
  })
9170
9659
  );
9171
9660
  task.command("start [id]").description(
@@ -9180,13 +9669,13 @@ function registerTask(program3) {
9180
9669
  const started = row?.started ?? null;
9181
9670
  if (started && started > 0) {
9182
9671
  line(
9183
- import_picocolors30.default.green(
9672
+ import_picocolors31.default.green(
9184
9673
  `started ${started} step${started === 1 ? "" : "s"} \u2014 they are running now`
9185
9674
  )
9186
9675
  );
9187
9676
  return;
9188
9677
  }
9189
- line(import_picocolors30.default.yellow(row?.note ?? "Nothing started."));
9678
+ line(import_picocolors31.default.yellow(row?.note ?? "Nothing started."));
9190
9679
  });
9191
9680
  })
9192
9681
  );
@@ -9201,7 +9690,7 @@ function registerTask(program3) {
9201
9690
  );
9202
9691
  ok({ awaiting: row2.approval_state === "awaiting", task: row2 }, () => {
9203
9692
  line(
9204
- row2.approval_state === "awaiting" ? import_picocolors30.default.yellow(
9693
+ row2.approval_state === "awaiting" ? import_picocolors31.default.yellow(
9205
9694
  "The plan is waiting on the owner. They see it in the task."
9206
9695
  ) : `Already ${row2.approval_state}.`
9207
9696
  );
@@ -9226,7 +9715,7 @@ function registerTask(program3) {
9226
9715
  );
9227
9716
  ok(
9228
9717
  row,
9229
- () => line(`${import_picocolors30.default.green(row.approval_state)} ${import_picocolors30.default.bold(row.title)}`)
9718
+ () => line(`${import_picocolors31.default.green(row.approval_state)} ${import_picocolors31.default.bold(row.title)}`)
9230
9719
  );
9231
9720
  })
9232
9721
  );
@@ -9242,7 +9731,7 @@ function registerTask(program3) {
9242
9731
  `/v1/project-tasks/${encodeURIComponent(id)}/move`,
9243
9732
  { body: { status: "ready" } }
9244
9733
  );
9245
- ok(row, () => line(`${import_picocolors30.default.green("ready")} ${import_picocolors30.default.bold(row.title)}`));
9734
+ ok(row, () => line(`${import_picocolors31.default.green("ready")} ${import_picocolors31.default.bold(row.title)}`));
9246
9735
  })
9247
9736
  );
9248
9737
  }
@@ -9287,24 +9776,24 @@ function assertOneOf(flag, value, allowed) {
9287
9776
  }
9288
9777
  }
9289
9778
  function formatRow2(r) {
9290
- const key = import_picocolors30.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
9291
- const steps = r.subtaskTotal ? import_picocolors30.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
9292
- const gate = r.approval_state === "awaiting" ? import_picocolors30.default.yellow(" awaiting approval") : "";
9779
+ const key = import_picocolors31.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
9780
+ const steps = r.subtaskTotal ? import_picocolors31.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
9781
+ const gate = r.approval_state === "awaiting" ? import_picocolors31.default.yellow(" awaiting approval") : "";
9293
9782
  return `${key} ${statusTag2(r.status)} ${r.title}${steps}${gate}`;
9294
9783
  }
9295
9784
  function formatSubtask(r, index) {
9296
- const n = import_picocolors30.default.dim(String(index).padStart(2, "0"));
9297
- const role = r.role ? import_picocolors30.default.dim(` [${r.role}]`) : "";
9298
- const scope = r.scope_paths?.length ? import_picocolors30.default.dim(` owns: ${r.scope_paths.join(", ")}`) : "";
9785
+ const n = import_picocolors31.default.dim(String(index).padStart(2, "0"));
9786
+ const role = r.role ? import_picocolors31.default.dim(` [${r.role}]`) : "";
9787
+ const scope = r.scope_paths?.length ? import_picocolors31.default.dim(` owns: ${r.scope_paths.join(", ")}`) : "";
9299
9788
  const head = `${n} ${statusTag2(r.status)} ${r.title}${role}${scope}`;
9300
9789
  const summary = (r.result_summary ?? "").trim();
9301
9790
  if (!summary) return head;
9302
9791
  const wrapped = summary.split("\n").map((l) => ` ${l}`).join("\n");
9303
9792
  return `${head}
9304
- ${import_picocolors30.default.dim(wrapped)}`;
9793
+ ${import_picocolors31.default.dim(wrapped)}`;
9305
9794
  }
9306
9795
  function printTask(row, goal) {
9307
- line(`${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.key ?? row.id)}`);
9796
+ line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.key ?? row.id)}`);
9308
9797
  line(`${statusTag2(row.status)} approval: ${row.approval_state}`);
9309
9798
  if (row.summary) line(`
9310
9799
  ${row.summary}`);
@@ -9317,53 +9806,53 @@ touches: ${row.targets.map((t) => t.appName ?? t.ref ?? t.kind).join(", ")}`
9317
9806
  }
9318
9807
  if (row.subtasks?.length) {
9319
9808
  line(`
9320
- ${import_picocolors30.default.bold("subtasks")}`);
9809
+ ${import_picocolors31.default.bold("subtasks")}`);
9321
9810
  row.subtasks.forEach((s, i) => line(formatSubtask(s, i + 1)));
9322
9811
  line(
9323
- import_picocolors30.default.dim(
9812
+ import_picocolors31.default.dim(
9324
9813
  `
9325
9814
  Run \`workser artifact list\` to see what these subtasks produced,`
9326
9815
  )
9327
9816
  );
9328
9817
  line(
9329
- import_picocolors30.default.dim(
9818
+ import_picocolors31.default.dim(
9330
9819
  `or \`workser artifact list --step <id>\` for one subtask's output alone.`
9331
9820
  )
9332
9821
  );
9333
9822
  } else {
9334
- line(import_picocolors30.default.dim("\nNo subtasks yet."));
9823
+ line(import_picocolors31.default.dim("\nNo subtasks yet."));
9335
9824
  }
9336
9825
  }
9337
9826
  function printGoalContext(row, goal) {
9338
9827
  const mine = row.phase ?? null;
9339
9828
  line(`
9340
- ${import_picocolors30.default.bold("part of")}: ${goal.title}`);
9341
- if (goal.outcome) line(import_picocolors30.default.dim(`done means: ${goal.outcome}`));
9829
+ ${import_picocolors31.default.bold("part of")}: ${goal.title}`);
9830
+ if (goal.outcome) line(import_picocolors31.default.dim(`done means: ${goal.outcome}`));
9342
9831
  const progress = goal.progress ?? [];
9343
9832
  for (const p of progress) {
9344
9833
  const where = p.total === 0 ? "not started" : `${p.done} of ${p.total} done`;
9345
- const here = mine && p.name === mine ? import_picocolors30.default.cyan(" <- this task") : "";
9346
- const mark = p.state === "done" ? import_picocolors30.default.green("*") : import_picocolors30.default.dim("-");
9834
+ const here = mine && p.name === mine ? import_picocolors31.default.cyan(" <- this task") : "";
9835
+ const mark = p.state === "done" ? import_picocolors31.default.green("*") : import_picocolors31.default.dim("-");
9347
9836
  line(` ${mark} ${p.name} \u2014 ${where}${here}`);
9348
9837
  }
9349
9838
  const next = progress.find((p) => p.state !== "done");
9350
9839
  const running = progress.some((p) => p.state === "working");
9351
9840
  if (next && !running) {
9352
9841
  line(
9353
- import_picocolors30.default.dim(
9842
+ import_picocolors31.default.dim(
9354
9843
  `
9355
9844
  Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to them in a sentence rather than starting it unasked.`
9356
9845
  )
9357
9846
  );
9358
9847
  } else if (!next) {
9359
9848
  line(
9360
- import_picocolors30.default.dim(
9849
+ import_picocolors31.default.dim(
9361
9850
  "\nEvery part of this plan is done. Say so, and offer to wrap it up."
9362
9851
  )
9363
9852
  );
9364
9853
  }
9365
9854
  line(
9366
- import_picocolors30.default.dim(
9855
+ import_picocolors31.default.dim(
9367
9856
  "The plan is a reference for what was agreed, not a rule about what may run. Work can start on any part at any time if they ask for it."
9368
9857
  )
9369
9858
  );
@@ -9371,22 +9860,22 @@ Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to t
9371
9860
  function statusTag2(status) {
9372
9861
  switch (status) {
9373
9862
  case "ready":
9374
- return import_picocolors30.default.green("[ready]");
9863
+ return import_picocolors31.default.green("[ready]");
9375
9864
  case "working":
9376
- return import_picocolors30.default.blue("[working]");
9865
+ return import_picocolors31.default.blue("[working]");
9377
9866
  case "checking":
9378
- return import_picocolors30.default.cyan("[checking]");
9867
+ return import_picocolors31.default.cyan("[checking]");
9379
9868
  case "accepted":
9380
- return import_picocolors30.default.green("[accepted]");
9869
+ return import_picocolors31.default.green("[accepted]");
9381
9870
  case "archived":
9382
- return import_picocolors30.default.dim("[archived]");
9871
+ return import_picocolors31.default.dim("[archived]");
9383
9872
  default:
9384
- return import_picocolors30.default.dim("[todo]");
9873
+ return import_picocolors31.default.dim("[todo]");
9385
9874
  }
9386
9875
  }
9387
9876
 
9388
9877
  // src/commands/goal.ts
9389
- var import_picocolors31 = __toESM(require_picocolors(), 1);
9878
+ var import_picocolors32 = __toESM(require_picocolors(), 1);
9390
9879
  var STATUSES3 = ["proposed", "agreed", "working", "delivered", "abandoned"];
9391
9880
  function registerGoal(program3) {
9392
9881
  const goal = program3.command("goal").description("Business goals and the phases that deliver them");
@@ -9398,7 +9887,7 @@ function registerGoal(program3) {
9398
9887
  }) ?? [];
9399
9888
  ok(rows, () => {
9400
9889
  if (!rows.length) {
9401
- line(import_picocolors31.default.dim("No goals yet \u2014 every task here stands on its own."));
9890
+ line(import_picocolors32.default.dim("No goals yet \u2014 every task here stands on its own."));
9402
9891
  return;
9403
9892
  }
9404
9893
  for (const g of rows) line(formatGoal(g));
@@ -9475,10 +9964,10 @@ function registerGoal(program3) {
9475
9964
  }
9476
9965
  });
9477
9966
  ok(row, () => {
9478
- success(`Proposed ${import_picocolors31.default.bold(row?.title ?? "goal")}`);
9967
+ success(`Proposed ${import_picocolors32.default.bold(row?.title ?? "goal")}`);
9479
9968
  printGoal(row);
9480
9969
  line(
9481
- import_picocolors31.default.dim(
9970
+ import_picocolors32.default.dim(
9482
9971
  "\nNothing has been created yet. The owner agrees the shape first."
9483
9972
  )
9484
9973
  );
@@ -9507,7 +9996,7 @@ function registerGoal(program3) {
9507
9996
  ok(
9508
9997
  row,
9509
9998
  () => line(
9510
- row?.recorded ? met === true ? import_picocolors31.default.green("recorded \u2014 met") : met === false ? import_picocolors31.default.yellow("recorded \u2014 not met") : import_picocolors31.default.dim("recorded \u2014 back to unchecked") : import_picocolors31.default.yellow(
9999
+ row?.recorded ? met === true ? import_picocolors32.default.green("recorded \u2014 met") : met === false ? import_picocolors32.default.yellow("recorded \u2014 not met") : import_picocolors32.default.dim("recorded \u2014 back to unchecked") : import_picocolors32.default.yellow(
9511
10000
  "couldn't record it \u2014 check the goal id, the phase name and the criterion id"
9512
10001
  )
9513
10002
  )
@@ -9550,7 +10039,7 @@ function registerGoal(program3) {
9550
10039
  }
9551
10040
  ok({ goalId, phase, filed }, () => {
9552
10041
  success(
9553
- `Filed ${filed.length} ${filed.length === 1 ? "task" : "tasks"} under ${import_picocolors31.default.bold(phase)}`
10042
+ `Filed ${filed.length} ${filed.length === 1 ? "task" : "tasks"} under ${import_picocolors32.default.bold(phase)}`
9554
10043
  );
9555
10044
  });
9556
10045
  })
@@ -9582,42 +10071,42 @@ function registerGoal(program3) {
9582
10071
  function appScope(g) {
9583
10072
  const n = g.appIds?.length ?? 0;
9584
10073
  if (!n) return "";
9585
- return import_picocolors31.default.dim(` ${n} part${n === 1 ? "" : "s"} of the system`);
10074
+ return import_picocolors32.default.dim(` ${n} part${n === 1 ? "" : "s"} of the system`);
9586
10075
  }
9587
10076
  function formatGoal(g) {
9588
- const where = g.currentPhase && g.status !== "delivered" ? import_picocolors31.default.dim(` now: ${g.currentPhase}`) : "";
9589
- const count = g.taskTotal != null ? import_picocolors31.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
9590
- return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${import_picocolors31.default.dim(g.id)}`;
10077
+ const where = g.currentPhase && g.status !== "delivered" ? import_picocolors32.default.dim(` now: ${g.currentPhase}`) : "";
10078
+ const count = g.taskTotal != null ? import_picocolors32.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
10079
+ return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${import_picocolors32.default.dim(g.id)}`;
9591
10080
  }
9592
10081
  function printGoal(g) {
9593
10082
  if (!g) return;
9594
- line(`${import_picocolors31.default.bold(g.title)} ${import_picocolors31.default.dim(g.id)}`);
10083
+ line(`${import_picocolors32.default.bold(g.title)} ${import_picocolors32.default.dim(g.id)}`);
9595
10084
  line(statusTag3(g.status));
9596
10085
  if (g.outcome) line(`
9597
10086
  done means: ${g.outcome}`);
9598
10087
  const progress = g.progress ?? [];
9599
10088
  if (!progress.length) {
9600
- line(import_picocolors31.default.dim("\nNo phases agreed yet."));
10089
+ line(import_picocolors32.default.dim("\nNo phases agreed yet."));
9601
10090
  return;
9602
10091
  }
9603
10092
  line(`
9604
- ${import_picocolors31.default.bold("phases")}`);
10093
+ ${import_picocolors32.default.bold("phases")}`);
9605
10094
  for (const p of progress) {
9606
- const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors31.default.dim("nothing filed yet");
9607
- const mark = p.state === "done" ? import_picocolors31.default.green("done") : p.state === "working" ? import_picocolors31.default.blue("working") : import_picocolors31.default.dim("waiting");
10095
+ const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors32.default.dim("nothing filed yet");
10096
+ const mark = p.state === "done" ? import_picocolors32.default.green("done") : p.state === "working" ? import_picocolors32.default.blue("working") : import_picocolors32.default.dim("waiting");
9608
10097
  line(
9609
- ` ${import_picocolors31.default.dim(String(p.index).padStart(2, "0"))} ${p.name} ${mark} ${import_picocolors31.default.dim(bar2)}`
10098
+ ` ${import_picocolors32.default.dim(String(p.index).padStart(2, "0"))} ${p.name} ${mark} ${import_picocolors32.default.dim(bar2)}`
9610
10099
  );
9611
10100
  for (const c of p.criteria ?? []) {
9612
- const tick = c.met === true ? import_picocolors31.default.green("\u2713") : c.met === false ? import_picocolors31.default.red("\u2717") : import_picocolors31.default.dim("\xB7");
9613
- line(` ${tick} ${c.text} ${import_picocolors31.default.dim(c.id)}`);
9614
- if (c.note) line(import_picocolors31.default.dim(` ${c.note}`));
10101
+ const tick = c.met === true ? import_picocolors32.default.green("\u2713") : c.met === false ? import_picocolors32.default.red("\u2717") : import_picocolors32.default.dim("\xB7");
10102
+ line(` ${tick} ${c.text} ${import_picocolors32.default.dim(c.id)}`);
10103
+ if (c.note) line(import_picocolors32.default.dim(` ${c.note}`));
9615
10104
  }
9616
10105
  }
9617
10106
  const current = progress.find((p) => p.name === g.currentPhase);
9618
10107
  if (current) {
9619
10108
  line(
9620
- import_picocolors31.default.dim(
10109
+ import_picocolors32.default.dim(
9621
10110
  `
9622
10111
  ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current.index} of ${progress.length}).`
9623
10112
  )
@@ -9627,15 +10116,15 @@ ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current
9627
10116
  function statusTag3(status) {
9628
10117
  switch (status) {
9629
10118
  case "agreed":
9630
- return import_picocolors31.default.cyan("[agreed]");
10119
+ return import_picocolors32.default.cyan("[agreed]");
9631
10120
  case "working":
9632
- return import_picocolors31.default.blue("[working]");
10121
+ return import_picocolors32.default.blue("[working]");
9633
10122
  case "delivered":
9634
- return import_picocolors31.default.green("[delivered]");
10123
+ return import_picocolors32.default.green("[delivered]");
9635
10124
  case "abandoned":
9636
- return import_picocolors31.default.dim("[abandoned]");
10125
+ return import_picocolors32.default.dim("[abandoned]");
9637
10126
  default:
9638
- return import_picocolors31.default.yellow("[proposed]");
10127
+ return import_picocolors32.default.yellow("[proposed]");
9639
10128
  }
9640
10129
  }
9641
10130
 
@@ -9819,7 +10308,7 @@ function stripLeadingGlobalOptions(argv) {
9819
10308
  }
9820
10309
 
9821
10310
  // src/commands/decision.ts
9822
- var import_picocolors32 = __toESM(require_picocolors(), 1);
10311
+ var import_picocolors33 = __toESM(require_picocolors(), 1);
9823
10312
  function registerDecision(program3) {
9824
10313
  const decision = program3.command("decision").description("Read and record the project's architecture decisions");
9825
10314
  decision.command("list").description("Every decision on record \u2014 read this before changing how something works").option("--limit <n>", "cap the number returned (newest first)").action(
@@ -9832,11 +10321,11 @@ function registerDecision(program3) {
9832
10321
  rows = applyLimit(rows, opts.limit);
9833
10322
  ok(rows, () => {
9834
10323
  if (!rows.length) {
9835
- line(import_picocolors32.default.dim("No decisions recorded yet."));
10324
+ line(import_picocolors33.default.dim("No decisions recorded yet."));
9836
10325
  return;
9837
10326
  }
9838
10327
  for (const r of rows) {
9839
- line(`${import_picocolors32.default.dim(r.id)} ${import_picocolors32.default.dim(shortDate(r.createdAt))} ${r.title}`);
10328
+ line(`${import_picocolors33.default.dim(r.id)} ${import_picocolors33.default.dim(shortDate(r.createdAt))} ${r.title}`);
9840
10329
  line(` ${truncate(r.decision, 100)}`);
9841
10330
  }
9842
10331
  });
@@ -9850,16 +10339,16 @@ function registerDecision(program3) {
9850
10339
  `/v1/projects/${projectId}/architecture-decisions/${args[0]}`
9851
10340
  );
9852
10341
  ok(row, () => {
9853
- line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
9854
- line(import_picocolors32.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
10342
+ line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
10343
+ line(import_picocolors33.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9855
10344
  line(`
9856
- ${import_picocolors32.default.bold("Context")}
10345
+ ${import_picocolors33.default.bold("Context")}
9857
10346
  ${row.context}`);
9858
10347
  line(`
9859
- ${import_picocolors32.default.bold("Decision")}
10348
+ ${import_picocolors33.default.bold("Decision")}
9860
10349
  ${row.decision}`);
9861
10350
  if (row.consequences) line(`
9862
- ${import_picocolors32.default.bold("Consequences")}
10351
+ ${import_picocolors33.default.bold("Consequences")}
9863
10352
  ${row.consequences}`);
9864
10353
  });
9865
10354
  })
@@ -9888,7 +10377,7 @@ ${row.consequences}`);
9888
10377
  refId: row?.id,
9889
10378
  output: { decision: row }
9890
10379
  });
9891
- ok(row, () => line(`Recorded decision ${import_picocolors32.default.bold(row?.id ?? "")} \u2014 ${title}`));
10380
+ ok(row, () => line(`Recorded decision ${import_picocolors33.default.bold(row?.id ?? "")} \u2014 ${title}`));
9892
10381
  })
9893
10382
  );
9894
10383
  const requirement = program3.command("requirement").description("Read and record the project's requirements");
@@ -9900,11 +10389,11 @@ ${row.consequences}`);
9900
10389
  rows = applyLimit(rows, opts.limit);
9901
10390
  ok(rows, () => {
9902
10391
  if (!rows.length) {
9903
- line(import_picocolors32.default.dim("No requirements recorded yet."));
10392
+ line(import_picocolors33.default.dim("No requirements recorded yet."));
9904
10393
  return;
9905
10394
  }
9906
10395
  for (const r of rows) {
9907
- line(`${import_picocolors32.default.dim(r.id)} ${r.status.padEnd(9)} ${r.title}`);
10396
+ line(`${import_picocolors33.default.dim(r.id)} ${r.status.padEnd(9)} ${r.title}`);
9908
10397
  }
9909
10398
  });
9910
10399
  })
@@ -9917,8 +10406,8 @@ ${row.consequences}`);
9917
10406
  `/v1/projects/${projectId}/requirements/${args[0]}`
9918
10407
  );
9919
10408
  ok(row, () => {
9920
- line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
9921
- line(import_picocolors32.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
10409
+ line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
10410
+ line(import_picocolors33.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9922
10411
  line(`
9923
10412
  ${row.body}`);
9924
10413
  });
@@ -9944,7 +10433,7 @@ ${row.body}`);
9944
10433
  refId: row?.id,
9945
10434
  output: { requirement: row }
9946
10435
  });
9947
- ok(row, () => line(`Recorded requirement ${import_picocolors32.default.bold(row?.id ?? "")} \u2014 ${title}`));
10436
+ ok(row, () => line(`Recorded requirement ${import_picocolors33.default.bold(row?.id ?? "")} \u2014 ${title}`));
9948
10437
  })
9949
10438
  );
9950
10439
  requirement.command("update <id>").description(
@@ -9973,7 +10462,7 @@ ${row.body}`);
9973
10462
  code: "bad_request"
9974
10463
  });
9975
10464
  }
9976
- ok(row, () => line(`Updated requirement ${import_picocolors32.default.bold(row.id)} \u2014 ${row.title} (${row.status})`));
10465
+ ok(row, () => line(`Updated requirement ${import_picocolors33.default.bold(row.id)} \u2014 ${row.title} (${row.status})`));
9977
10466
  })
9978
10467
  );
9979
10468
  }
@@ -9996,7 +10485,7 @@ function shortDate(iso) {
9996
10485
  }
9997
10486
 
9998
10487
  // src/commands/doc.ts
9999
- var import_picocolors33 = __toESM(require_picocolors(), 1);
10488
+ var import_picocolors34 = __toESM(require_picocolors(), 1);
10000
10489
 
10001
10490
  // src/mermaid-fences.ts
10002
10491
  function hasDiagram(code) {
@@ -10041,13 +10530,13 @@ function registerDoc(program3) {
10041
10530
  }) ?? [];
10042
10531
  ok(rows, () => {
10043
10532
  if (!rows.length) {
10044
- line(import_picocolors33.default.dim("No documents yet."));
10533
+ line(import_picocolors34.default.dim("No documents yet."));
10045
10534
  return;
10046
10535
  }
10047
10536
  for (const r of rows) {
10048
- const link = r.workItemId ? import_picocolors33.default.dim(` \u21B3 ${r.workItemId}`) : "";
10049
- const file = r.filePath ? import_picocolors33.default.dim(` ${r.filePath}`) : "";
10050
- line(`${import_picocolors33.default.dim(r.id)} ${r.title}${link}${file}`);
10537
+ const link = r.workItemId ? import_picocolors34.default.dim(` \u21B3 ${r.workItemId}`) : "";
10538
+ const file = r.filePath ? import_picocolors34.default.dim(` ${r.filePath}`) : "";
10539
+ line(`${import_picocolors34.default.dim(r.id)} ${r.title}${link}${file}`);
10051
10540
  }
10052
10541
  });
10053
10542
  })
@@ -10061,17 +10550,17 @@ function registerDoc(program3) {
10061
10550
  );
10062
10551
  if (opts.markdown) {
10063
10552
  ok({ id: row.id, title: row.title, filePath: row.filePath }, () => {
10064
- line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
10553
+ line(`${import_picocolors34.default.bold(row.title)} ${import_picocolors34.default.dim(row.id)}`);
10065
10554
  line(
10066
- row.filePath ? `Read it at ${import_picocolors33.default.bold(row.filePath)} (relative to the project folder).` : import_picocolors33.default.dim("This document has no markdown mirror on disk yet.")
10555
+ row.filePath ? `Read it at ${import_picocolors34.default.bold(row.filePath)} (relative to the project folder).` : import_picocolors34.default.dim("This document has no markdown mirror on disk yet.")
10067
10556
  );
10068
10557
  });
10069
10558
  return;
10070
10559
  }
10071
10560
  ok(row, () => {
10072
- line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
10073
- if (row.workItemId) line(import_picocolors33.default.dim(`linked to work item ${row.workItemId}`));
10074
- if (row.filePath) line(import_picocolors33.default.dim(`markdown mirror: ${row.filePath}`));
10561
+ line(`${import_picocolors34.default.bold(row.title)} ${import_picocolors34.default.dim(row.id)}`);
10562
+ if (row.workItemId) line(import_picocolors34.default.dim(`linked to work item ${row.workItemId}`));
10563
+ if (row.filePath) line(import_picocolors34.default.dim(`markdown mirror: ${row.filePath}`));
10075
10564
  line("");
10076
10565
  line(row.contentJson);
10077
10566
  });
@@ -10100,7 +10589,7 @@ function registerDoc(program3) {
10100
10589
  refId: row?.id,
10101
10590
  output: { document: row }
10102
10591
  });
10103
- ok(row, () => line(`Created document ${import_picocolors33.default.bold(row?.id ?? "")} \u2014 ${title}`));
10592
+ ok(row, () => line(`Created document ${import_picocolors34.default.bold(row?.id ?? "")} \u2014 ${title}`));
10104
10593
  })
10105
10594
  );
10106
10595
  doc.command("diagram <id>").description(
@@ -10126,19 +10615,19 @@ function registerDoc(program3) {
10126
10615
  diagrams: diagrams.map((code) => ({ kind: diagramKind(code), code }))
10127
10616
  };
10128
10617
  ok(payload, () => {
10129
- line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
10618
+ line(`${import_picocolors34.default.bold(row.title)} ${import_picocolors34.default.dim(row.id)}`);
10130
10619
  if (markdown === null) {
10131
10620
  line(
10132
- import_picocolors33.default.dim(
10621
+ import_picocolors34.default.dim(
10133
10622
  row.filePath ? `Could not read ${row.filePath} from this folder.` : "This document has no markdown mirror on disk yet."
10134
10623
  )
10135
10624
  );
10136
10625
  } else if (!diagrams.length) {
10137
- line(import_picocolors33.default.dim("No diagrams in this document."));
10626
+ line(import_picocolors34.default.dim("No diagrams in this document."));
10138
10627
  } else {
10139
10628
  for (const [i, code] of diagrams.entries()) {
10140
10629
  const kind = diagramKind(code) ?? "diagram";
10141
- line(`${import_picocolors33.default.dim(String(i + 1))} ${kind} ${import_picocolors33.default.dim(`${code.split("\n").length} lines`)}`);
10630
+ line(`${import_picocolors34.default.dim(String(i + 1))} ${kind} ${import_picocolors34.default.dim(`${code.split("\n").length} lines`)}`);
10142
10631
  }
10143
10632
  }
10144
10633
  });
@@ -10174,7 +10663,7 @@ function registerDoc(program3) {
10174
10663
  code: "bad_request"
10175
10664
  });
10176
10665
  }
10177
- ok(row, () => line(`Updated document ${import_picocolors33.default.bold(row.id)} \u2014 ${row.title}`));
10666
+ ok(row, () => line(`Updated document ${import_picocolors34.default.bold(row.id)} \u2014 ${row.title}`));
10178
10667
  })
10179
10668
  );
10180
10669
  }
@@ -10188,7 +10677,7 @@ function readMirror(cwd, filePath) {
10188
10677
  }
10189
10678
 
10190
10679
  // src/commands/design.ts
10191
- var import_picocolors34 = __toESM(require_picocolors(), 1);
10680
+ var import_picocolors35 = __toESM(require_picocolors(), 1);
10192
10681
  function registerDesign(program3) {
10193
10682
  const design = program3.command("design").description("Read the project's brand (colours, fonts, logo)");
10194
10683
  design.command("show").description("Show this project's brand \u2014 read it before writing any UI").option("--raw", "print the generated token files verbatim instead of a summary").action(
@@ -10202,11 +10691,11 @@ function registerDesign(program3) {
10202
10691
  if (opts.raw) {
10203
10692
  ok(files, () => {
10204
10693
  if (!files.length) {
10205
- line(import_picocolors34.default.dim("No brand set for this project."));
10694
+ line(import_picocolors35.default.dim("No brand set for this project."));
10206
10695
  return;
10207
10696
  }
10208
10697
  for (const f of files) {
10209
- line(import_picocolors34.default.bold(f.path));
10698
+ line(import_picocolors35.default.bold(f.path));
10210
10699
  line(f.contents);
10211
10700
  line("");
10212
10701
  }
@@ -10223,21 +10712,21 @@ function registerDesign(program3) {
10223
10712
  } : { hasBrand: false, colors: {}, fonts: {}, brand: {}, files: [] };
10224
10713
  ok(summary, () => {
10225
10714
  if (!tokens) {
10226
- line(import_picocolors34.default.dim("No brand set for this project \u2014 choose sensible styling yourself."));
10715
+ line(import_picocolors35.default.dim("No brand set for this project \u2014 choose sensible styling yourself."));
10227
10716
  return;
10228
10717
  }
10229
10718
  for (const [name, value] of Object.entries(tokens.brand)) {
10230
- line(`${import_picocolors34.default.dim(name.padEnd(12))} ${value}`);
10719
+ line(`${import_picocolors35.default.dim(name.padEnd(12))} ${value}`);
10231
10720
  }
10232
10721
  for (const [name, value] of Object.entries(tokens.color)) {
10233
- line(`${import_picocolors34.default.dim(`color.${name}`.padEnd(12))} ${value}`);
10722
+ line(`${import_picocolors35.default.dim(`color.${name}`.padEnd(12))} ${value}`);
10234
10723
  }
10235
10724
  for (const [name, value] of Object.entries(tokens.font)) {
10236
- line(`${import_picocolors34.default.dim(`font.${name}`.padEnd(12))} ${value}`);
10725
+ line(`${import_picocolors35.default.dim(`font.${name}`.padEnd(12))} ${value}`);
10237
10726
  }
10238
10727
  line("");
10239
10728
  line(
10240
- import_picocolors34.default.dim(
10729
+ import_picocolors35.default.dim(
10241
10730
  `Generated into the working tree as ${files.map((f) => f.path).join(", ")} \u2014 wire those in, never edit them.`
10242
10731
  )
10243
10732
  );
@@ -10268,7 +10757,7 @@ function unwrap(group) {
10268
10757
  }
10269
10758
 
10270
10759
  // src/commands/api.ts
10271
- var import_picocolors35 = __toESM(require_picocolors(), 1);
10760
+ var import_picocolors36 = __toESM(require_picocolors(), 1);
10272
10761
  import { readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
10273
10762
  import { join as join3, relative, sep } from "path";
10274
10763
 
@@ -10382,10 +10871,10 @@ function registerApi(program3) {
10382
10871
  const appId = requireApp2(opts.app);
10383
10872
  const res = await api(ctx, `/v1/apps/${encodeURIComponent(appId)}/api/requests`);
10384
10873
  ok(res, () => {
10385
- for (const note of res?.notes ?? []) line(import_picocolors35.default.dim(note));
10874
+ for (const note of res?.notes ?? []) line(import_picocolors36.default.dim(note));
10386
10875
  for (const r of res?.requests ?? []) {
10387
10876
  line(
10388
- `${import_picocolors35.default.dim(r.method.padEnd(6))}${r.path}${r.note ? import_picocolors35.default.dim(` ${r.note}`) : ""}`
10877
+ `${import_picocolors36.default.dim(r.method.padEnd(6))}${r.path}${r.note ? import_picocolors36.default.dim(` ${r.note}`) : ""}`
10389
10878
  );
10390
10879
  }
10391
10880
  });
@@ -10419,14 +10908,14 @@ function registerApi(program3) {
10419
10908
  );
10420
10909
  ok(res, () => {
10421
10910
  if (!res?.ok) {
10422
- line(import_picocolors35.default.red(res?.error ?? "The service did not answer."));
10911
+ line(import_picocolors36.default.red(res?.error ?? "The service did not answer."));
10423
10912
  return;
10424
10913
  }
10425
10914
  const code = `${res.status}${res.statusText ? ` ${res.statusText}` : ""}`;
10426
- const colour2 = res.status && res.status < 300 ? import_picocolors35.default.green : res.status && res.status < 500 ? import_picocolors35.default.yellow : import_picocolors35.default.red;
10427
- line(`${colour2(code)} ${import_picocolors35.default.dim(`${res.durationMs}ms ${res.url}`)}`);
10915
+ const colour2 = res.status && res.status < 300 ? import_picocolors36.default.green : res.status && res.status < 500 ? import_picocolors36.default.yellow : import_picocolors36.default.red;
10916
+ line(`${colour2(code)} ${import_picocolors36.default.dim(`${res.durationMs}ms ${res.url}`)}`);
10428
10917
  if (res.body) line(res.body);
10429
- if (res.truncated) line(import_picocolors35.default.dim("(answer truncated)"));
10918
+ if (res.truncated) line(import_picocolors36.default.dim("(answer truncated)"));
10430
10919
  });
10431
10920
  if (!res?.ok) process.exitCode = 1;
10432
10921
  })
@@ -10446,15 +10935,15 @@ function registerApi(program3) {
10446
10935
  for (const r of report.routes) {
10447
10936
  const known = report.missing.some((m) => m.path === r.path);
10448
10937
  line(
10449
- `${known ? import_picocolors35.default.yellow("undocumented") : import_picocolors35.default.green("documented ")} ${r.path}${import_picocolors35.default.dim(` ${r.file}`)}`
10938
+ `${known ? import_picocolors36.default.yellow("undocumented") : import_picocolors36.default.green("documented ")} ${r.path}${import_picocolors36.default.dim(` ${r.file}`)}`
10450
10939
  );
10451
10940
  }
10452
10941
  for (const p of report.stale) {
10453
- line(`${import_picocolors35.default.dim("in spec only ")} ${p}`);
10942
+ line(`${import_picocolors36.default.dim("in spec only ")} ${p}`);
10454
10943
  }
10455
10944
  line("");
10456
10945
  if (report.ok && specFile) success(summary);
10457
- else line(import_picocolors35.default.yellow(summary));
10946
+ else line(import_picocolors36.default.yellow(summary));
10458
10947
  });
10459
10948
  if (opts.check && !report.ok) {
10460
10949
  throw new WorkserError(summary, { code: "bad_request" });
@@ -10525,7 +11014,7 @@ function listRepoFiles(root, maxDepth = 8) {
10525
11014
  }
10526
11015
 
10527
11016
  // src/commands/analysis.ts
10528
- var import_picocolors36 = __toESM(require_picocolors(), 1);
11017
+ var import_picocolors37 = __toESM(require_picocolors(), 1);
10529
11018
  import { readFileSync as readFileSync4 } from "fs";
10530
11019
  function registerAnalysis(program3) {
10531
11020
  const cmd = program3.command("analysis").description("Run Python analysis locally, recorded in the task");
@@ -10535,14 +11024,14 @@ function registerAnalysis(program3) {
10535
11024
  const res = await api(ctx, path);
10536
11025
  ok(res, () => {
10537
11026
  line(
10538
- `${res?.available ? import_picocolors36.default.green("python") : import_picocolors36.default.red("python")} ${res?.version ?? "not found"} ${import_picocolors36.default.dim(res?.python ?? "")}`
11027
+ `${res?.available ? import_picocolors37.default.green("python") : import_picocolors37.default.red("python")} ${res?.version ?? "not found"} ${import_picocolors37.default.dim(res?.python ?? "")}`
10539
11028
  );
10540
11029
  for (const lib of res?.libraries ?? []) {
10541
11030
  line(
10542
- `${lib.present ? import_picocolors36.default.green(lib.name) : import_picocolors36.default.yellow(lib.name)}${import_picocolors36.default.dim(lib.present ? "" : " missing")}`
11031
+ `${lib.present ? import_picocolors37.default.green(lib.name) : import_picocolors37.default.yellow(lib.name)}${import_picocolors37.default.dim(lib.present ? "" : " missing")}`
10543
11032
  );
10544
11033
  }
10545
- for (const note of res?.notes ?? []) line(import_picocolors36.default.dim(note));
11034
+ for (const note of res?.notes ?? []) line(import_picocolors37.default.dim(note));
10546
11035
  });
10547
11036
  if (!res?.available) process.exitCode = 1;
10548
11037
  })
@@ -10564,15 +11053,15 @@ function registerAnalysis(program3) {
10564
11053
  );
10565
11054
  ok(res, () => {
10566
11055
  if (res?.stdout) line(res.stdout.replace(/\n$/, ""));
10567
- if (res?.stderr) line(import_picocolors36.default.dim(res.stderr.replace(/\n$/, "")));
10568
- if (res?.truncated) line(import_picocolors36.default.dim("(output truncated)"));
11056
+ if (res?.stderr) line(import_picocolors37.default.dim(res.stderr.replace(/\n$/, "")));
11057
+ if (res?.truncated) line(import_picocolors37.default.dim("(output truncated)"));
10569
11058
  const took = `${Math.round((res?.durationMs ?? 0) / 100) / 10}s`;
10570
11059
  line(
10571
- res?.ok ? import_picocolors36.default.green(`\u2713 ${res.summary ?? "It finished."}`) + import_picocolors36.default.dim(` ${took}`) : import_picocolors36.default.yellow(res?.summary ?? "It did not finish.") + import_picocolors36.default.dim(` ${took}`)
11060
+ res?.ok ? import_picocolors37.default.green(`\u2713 ${res.summary ?? "It finished."}`) + import_picocolors37.default.dim(` ${took}`) : import_picocolors37.default.yellow(res?.summary ?? "It did not finish.") + import_picocolors37.default.dim(` ${took}`)
10572
11061
  );
10573
11062
  if (res && !res.sandboxed) {
10574
11063
  line(
10575
- import_picocolors36.default.dim(
11064
+ import_picocolors37.default.dim(
10576
11065
  "This platform has no OS sandbox, so the script ran with your own file access."
10577
11066
  )
10578
11067
  );
@@ -10600,7 +11089,7 @@ function readCode(file, inline) {
10600
11089
  }
10601
11090
 
10602
11091
  // src/commands/scan.ts
10603
- var import_picocolors37 = __toESM(require_picocolors(), 1);
11092
+ var import_picocolors38 = __toESM(require_picocolors(), 1);
10604
11093
  import { spawnSync as spawnSync2 } from "child_process";
10605
11094
  import { existsSync as existsSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
10606
11095
  import { join as join4, relative as relative2, sep as sep2 } from "path";
@@ -10884,22 +11373,22 @@ function runPermissions(cwd, findings, checked, skipped) {
10884
11373
  }
10885
11374
  function print2(report, summary) {
10886
11375
  for (const s of report.skipped) {
10887
- line(`${import_picocolors37.default.yellow("not checked")} ${s.check}${import_picocolors37.default.dim(` \u2014 ${s.reason}`)}`);
11376
+ line(`${import_picocolors38.default.yellow("not checked")} ${s.check}${import_picocolors38.default.dim(` \u2014 ${s.reason}`)}`);
10888
11377
  }
10889
11378
  for (const f of report.findings) {
10890
- const where = f.file ? import_picocolors37.default.dim(` ${f.file}${f.line ? `:${f.line}` : ""}`) : "";
11379
+ const where = f.file ? import_picocolors38.default.dim(` ${f.file}${f.line ? `:${f.line}` : ""}`) : "";
10891
11380
  line(`${severityTag(f.severity)} ${f.title}${where}`);
10892
- line(` ${import_picocolors37.default.dim(f.fix)}`);
11381
+ line(` ${import_picocolors38.default.dim(f.fix)}`);
10893
11382
  }
10894
11383
  if (report.findings.length || report.skipped.length) line("");
10895
11384
  if (report.ok && !report.skipped.length) success(summary);
10896
- else if (report.ok) line(import_picocolors37.default.yellow(summary));
10897
- else line(import_picocolors37.default.red(summary));
11385
+ else if (report.ok) line(import_picocolors38.default.yellow(summary));
11386
+ else line(import_picocolors38.default.red(summary));
10898
11387
  }
10899
11388
  function severityTag(severity) {
10900
- if (severity === "high") return import_picocolors37.default.red("serious ");
10901
- if (severity === "medium") return import_picocolors37.default.yellow("worth fixing");
10902
- return import_picocolors37.default.dim("minor ");
11389
+ if (severity === "high") return import_picocolors38.default.red("serious ");
11390
+ if (severity === "medium") return import_picocolors38.default.yellow("worth fixing");
11391
+ return import_picocolors38.default.dim("minor ");
10903
11392
  }
10904
11393
  function git(cwd, args) {
10905
11394
  try {
@@ -10960,7 +11449,7 @@ function listRepoFiles2(root, maxDepth = 8) {
10960
11449
  }
10961
11450
 
10962
11451
  // src/commands/health.ts
10963
- var import_picocolors38 = __toESM(require_picocolors(), 1);
11452
+ var import_picocolors39 = __toESM(require_picocolors(), 1);
10964
11453
  function registerHealth(program3) {
10965
11454
  program3.command("health").description("Check that the published apps in this project are still answering").option("--app <webAppId>", "check one app rather than all of them").action(
10966
11455
  action(async ({ ctx, opts }) => {
@@ -10974,16 +11463,16 @@ function registerHealth(program3) {
10974
11463
  }
10975
11464
  function print3(res) {
10976
11465
  if (!res?.checks?.length) {
10977
- line(import_picocolors38.default.dim(res?.note ?? "Nothing to check."));
11466
+ line(import_picocolors39.default.dim(res?.note ?? "Nothing to check."));
10978
11467
  return;
10979
11468
  }
10980
11469
  for (const c of res.checks) {
10981
- const mark = c.ok ? import_picocolors38.default.green("up ") : import_picocolors38.default.red("down");
10982
- const timing = import_picocolors38.default.dim(`${c.ms}ms`);
10983
- const detail = c.ok ? timing : import_picocolors38.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
10984
- line(` ${mark} ${c.appName} ${import_picocolors38.default.dim(`(${c.environment})`)} ${c.url} ${detail}`);
11470
+ const mark = c.ok ? import_picocolors39.default.green("up ") : import_picocolors39.default.red("down");
11471
+ const timing = import_picocolors39.default.dim(`${c.ms}ms`);
11472
+ const detail = c.ok ? timing : import_picocolors39.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
11473
+ line(` ${mark} ${c.appName} ${import_picocolors39.default.dim(`(${c.environment})`)} ${c.url} ${detail}`);
10985
11474
  if (c.incidentOpened) {
10986
- line(import_picocolors38.default.yellow(` An incident has been opened on the board for this.`));
11475
+ line(import_picocolors39.default.yellow(` An incident has been opened on the board for this.`));
10987
11476
  }
10988
11477
  }
10989
11478
  const down = res.checks.filter((c) => !c.ok);
@@ -10996,14 +11485,14 @@ function print3(res) {
10996
11485
  }
10997
11486
  const production = down.filter((c) => c.environment === "production").length;
10998
11487
  line(
10999
- import_picocolors38.default.red(
11488
+ import_picocolors39.default.red(
11000
11489
  `${down.length} of ${res.checks.length} not answering` + (production ? ` \u2014 ${production} customer-facing.` : " (preview only).")
11001
11490
  )
11002
11491
  );
11003
11492
  }
11004
11493
 
11005
11494
  // src/commands/urls.ts
11006
- var import_picocolors39 = __toESM(require_picocolors(), 1);
11495
+ var import_picocolors40 = __toESM(require_picocolors(), 1);
11007
11496
  function registerUrls(program3) {
11008
11497
  program3.command("urls").description("The stable preview and production addresses of every app in this project").option("--app <webAppId>", "just one app").action(
11009
11498
  action(async ({ ctx, opts }) => {
@@ -11017,20 +11506,20 @@ function registerUrls(program3) {
11017
11506
  const summary = urlsSummary(rows);
11018
11507
  ok({ rows, summary }, () => {
11019
11508
  for (const row of rows) {
11020
- const label = import_picocolors39.default.dim(row.environment.padEnd(10));
11021
- const value = row.url ? import_picocolors39.default.cyan(row.url) : import_picocolors39.default.dim(row.note ?? "not published");
11509
+ const label = import_picocolors40.default.dim(row.environment.padEnd(10));
11510
+ const value = row.url ? import_picocolors40.default.cyan(row.url) : import_picocolors40.default.dim(row.note ?? "not published");
11022
11511
  line(` ${row.appName.padEnd(22)} ${label} ${value}`);
11023
11512
  }
11024
11513
  line("");
11025
11514
  if (rows.some((r) => r.url)) success(summary);
11026
- else line(import_picocolors39.default.yellow(summary));
11515
+ else line(import_picocolors40.default.yellow(summary));
11027
11516
  });
11028
11517
  })
11029
11518
  );
11030
11519
  }
11031
11520
 
11032
11521
  // src/commands/deployments.ts
11033
- var import_picocolors40 = __toESM(require_picocolors(), 1);
11522
+ var import_picocolors41 = __toESM(require_picocolors(), 1);
11034
11523
  function registerDeployments(program3) {
11035
11524
  const cmd = program3.command("deployments").description("Deployment history, and putting a build in front of customers");
11036
11525
  cmd.command("list").description("What has been built, newest first").option("--app <webAppId>", "just one app (default: every app in the project)").option("--env <environment>", "preview or production").option("--limit <n>", "how many to show", "20").action(
@@ -11048,7 +11537,7 @@ function registerDeployments(program3) {
11048
11537
  ok(res, () => {
11049
11538
  if (!items.length) {
11050
11539
  return line(
11051
- import_picocolors40.default.dim(
11540
+ import_picocolors41.default.dim(
11052
11541
  environment ? `Nothing has been deployed to ${environment} yet.` : "Nothing has been deployed yet. `workser deploy` builds the first one."
11053
11542
  )
11054
11543
  );
@@ -11068,13 +11557,13 @@ function registerDeployments(program3) {
11068
11557
  ).catch(() => null) : null;
11069
11558
  ok({ ...dep, logs }, () => {
11070
11559
  line(formatDeployment(dep));
11071
- if (dep?.error_message) line(import_picocolors40.default.red(` ${dep.error_message}`));
11560
+ if (dep?.error_message) line(import_picocolors41.default.red(` ${dep.error_message}`));
11072
11561
  const events = logs?.events ?? [];
11073
11562
  for (const e of events) {
11074
- line(` ${import_picocolors40.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
11563
+ line(` ${import_picocolors41.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
11075
11564
  }
11076
11565
  if (opts.logs && !events.length) {
11077
- line(import_picocolors40.default.dim(" That build produced no output."));
11566
+ line(import_picocolors41.default.dim(" That build produced no output."));
11078
11567
  }
11079
11568
  });
11080
11569
  })
@@ -11118,16 +11607,16 @@ function printPromoted(res, version) {
11118
11607
  const what = version === null ? "the latest build" : `version ${version}`;
11119
11608
  const url = res.url ?? res.vercel_url;
11120
11609
  success(`Production is being rebuilt from ${what}.`);
11121
- if (url) line(import_picocolors40.default.dim(`It will be at ${url}`));
11122
- line(import_picocolors40.default.dim("`workser deploy status` follows it."));
11610
+ if (url) line(import_picocolors41.default.dim(`It will be at ${url}`));
11611
+ line(import_picocolors41.default.dim("`workser deploy status` follows it."));
11123
11612
  }
11124
11613
  function formatDeployment(d) {
11125
11614
  if (!d) return "";
11126
- const version = d.version !== void 0 ? import_picocolors40.default.yellow(`v${d.version}`) : import_picocolors40.default.dim("v?");
11127
- const env = import_picocolors40.default.dim((d.environment ?? "?").padEnd(10));
11615
+ const version = d.version !== void 0 ? import_picocolors41.default.yellow(`v${d.version}`) : import_picocolors41.default.dim("v?");
11616
+ const env = import_picocolors41.default.dim((d.environment ?? "?").padEnd(10));
11128
11617
  const app = d.webAppName ? `${d.webAppName} ` : "";
11129
- const when = import_picocolors40.default.dim(formatTime2(d.created_at));
11130
- const url = d.url ? " " + import_picocolors40.default.cyan(d.url) : "";
11618
+ const when = import_picocolors41.default.dim(formatTime2(d.created_at));
11619
+ const url = d.url ? " " + import_picocolors41.default.cyan(d.url) : "";
11131
11620
  return `${version} ${env} ${colorStatus(d.status ?? "")} ${app}${when}${url}`;
11132
11621
  }
11133
11622
  function formatTime2(t) {
@@ -11137,7 +11626,7 @@ function formatTime2(t) {
11137
11626
  }
11138
11627
 
11139
11628
  // src/commands/usage.ts
11140
- var import_picocolors41 = __toESM(require_picocolors(), 1);
11629
+ var import_picocolors42 = __toESM(require_picocolors(), 1);
11141
11630
 
11142
11631
  // src/usage.ts
11143
11632
  var NEAR_LIMIT_FRACTION = 0.8;
@@ -11232,7 +11721,7 @@ function registerUsage(program3) {
11232
11721
  function print4(report) {
11233
11722
  const dims = report.dimensions ?? [];
11234
11723
  if (!dims.length) {
11235
- return line(import_picocolors41.default.dim("Nothing to measure for this project yet."));
11724
+ return line(import_picocolors42.default.dim("Nothing to measure for this project yet."));
11236
11725
  }
11237
11726
  const width = Math.max(...dims.map((d) => d.label.length));
11238
11727
  for (const d of dims) {
@@ -11241,23 +11730,23 @@ function print4(report) {
11241
11730
  line("");
11242
11731
  const summary = usageSummary(report);
11243
11732
  const worst = dims.map(usageState);
11244
- if (worst.includes("over")) line(import_picocolors41.default.red(summary));
11733
+ if (worst.includes("over")) line(import_picocolors42.default.red(summary));
11245
11734
  else if (worst.includes("near") || worst.includes("unknown"))
11246
- line(import_picocolors41.default.yellow(summary));
11735
+ line(import_picocolors42.default.yellow(summary));
11247
11736
  else success(summary);
11248
11737
  }
11249
11738
  function gauge(d, _labelWidth) {
11250
11739
  const drawn = bar(d);
11251
- return drawn ? ` ${import_picocolors41.default.dim(drawn)}` : "";
11740
+ return drawn ? ` ${import_picocolors42.default.dim(drawn)}` : "";
11252
11741
  }
11253
11742
  function colour(d) {
11254
11743
  switch (usageState(d)) {
11255
11744
  case "over":
11256
- return d.kind === "hard" ? import_picocolors41.default.red : import_picocolors41.default.yellow;
11745
+ return d.kind === "hard" ? import_picocolors42.default.red : import_picocolors42.default.yellow;
11257
11746
  case "near":
11258
- return import_picocolors41.default.yellow;
11747
+ return import_picocolors42.default.yellow;
11259
11748
  case "unknown":
11260
- return import_picocolors41.default.dim;
11749
+ return import_picocolors42.default.dim;
11261
11750
  default:
11262
11751
  return (s) => s;
11263
11752
  }
@@ -11265,7 +11754,7 @@ function colour(d) {
11265
11754
 
11266
11755
  // src/index.ts
11267
11756
  var pkg = {
11268
- version: true ? "0.6.13" : "0.0.0-dev"
11757
+ version: true ? "0.6.15" : "0.0.0-dev"
11269
11758
  };
11270
11759
  var program2 = new Command();
11271
11760
  program2.name("workser").description(
@@ -11298,6 +11787,7 @@ registerDomain(program2);
11298
11787
  registerOpen(program2);
11299
11788
  registerDoctor(program2);
11300
11789
  registerAgent(program2);
11790
+ registerAgentCloud(program2);
11301
11791
  registerVerify(program2);
11302
11792
  registerApi(program2);
11303
11793
  registerAnalysis(program2);