@workser/cli 0.6.12 → 0.6.14
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/AGENTS.md +7 -0
- package/dist/index.js +549 -248
- package/package.json +1 -1
- package/skills/workser/SKILL.md +16 -14
- package/skills/workser/reference/cloud-agents.md +77 -0
package/dist/index.js
CHANGED
|
@@ -3583,6 +3583,7 @@ function ownerOnly(opts) {
|
|
|
3583
3583
|
}
|
|
3584
3584
|
|
|
3585
3585
|
// src/output.ts
|
|
3586
|
+
var OUT_OF_SCOPE_EXIT = 7;
|
|
3586
3587
|
var mode = "text";
|
|
3587
3588
|
var quiet = false;
|
|
3588
3589
|
function configureOutput(opts) {
|
|
@@ -3633,7 +3634,13 @@ function fail(err) {
|
|
|
3633
3634
|
} else if (e.status === 401 || e.code === "unauthorized") {
|
|
3634
3635
|
process.stderr.write(import_picocolors.default.dim(" Run `workser login` to authenticate.\n"));
|
|
3635
3636
|
} else if (e.code === "no_project") {
|
|
3636
|
-
process.stderr.write(import_picocolors.default.dim("
|
|
3637
|
+
process.stderr.write(import_picocolors.default.dim(" cd into the project's folder, or open it in Workser.\n"));
|
|
3638
|
+
} else if (e.code === "out_of_scope") {
|
|
3639
|
+
process.stderr.write(
|
|
3640
|
+
import_picocolors.default.dim(
|
|
3641
|
+
" You can move between your organization's projects; another organization's are not reachable.\n"
|
|
3642
|
+
)
|
|
3643
|
+
);
|
|
3637
3644
|
} else if (e.code === "awaiting_approval") {
|
|
3638
3645
|
process.stderr.write(import_picocolors.default.dim(" Approve the action in Workser Orbit, then retry.\n"));
|
|
3639
3646
|
} else if (e.code === "owner_only") {
|
|
@@ -3647,6 +3654,7 @@ function exitCodeFor(e) {
|
|
|
3647
3654
|
if (e.status === 401 || e.code === "unauthorized") return 3;
|
|
3648
3655
|
if (e.code === "awaiting_approval") return 5;
|
|
3649
3656
|
if (e.code === "owner_only") return OWNER_ONLY_EXIT;
|
|
3657
|
+
if (e.code === "out_of_scope") return OUT_OF_SCOPE_EXIT;
|
|
3650
3658
|
return 1;
|
|
3651
3659
|
}
|
|
3652
3660
|
|
|
@@ -4063,6 +4071,84 @@ Two things worth knowing:
|
|
|
4063
4071
|
|
|
4064
4072
|
An app that has never been published has no address, so there is nothing to
|
|
4065
4073
|
check. That is reported as a note, not as a pass.
|
|
4074
|
+
`
|
|
4075
|
+
},
|
|
4076
|
+
{
|
|
4077
|
+
topic: "cloud-agents",
|
|
4078
|
+
title: "Ship an agent inside the app",
|
|
4079
|
+
summary: "Create an AI agent that runs on Workser and can be called from this project's apps.",
|
|
4080
|
+
commands: ["cloud-agent"],
|
|
4081
|
+
source: "skills/workser/reference/cloud-agents.md",
|
|
4082
|
+
body: `# Ship an agent inside the app
|
|
4083
|
+
|
|
4084
|
+
\`workser cloud-agent\` creates an AI agent that runs on **Workser's**
|
|
4085
|
+
infrastructure, keeps its own memory and tools, and can be called from the web,
|
|
4086
|
+
mobile, API or Python apps in this project.
|
|
4087
|
+
|
|
4088
|
+
**This is not \`workser agent\`.** That one hands a subtask to a coding agent on
|
|
4089
|
+
this machine \u2014 a teammate helping you build. This one is a thing the project
|
|
4090
|
+
*ships*: it works for the user after you are gone.
|
|
4091
|
+
|
|
4092
|
+
\`\`\`
|
|
4093
|
+
workser cloud-agent list
|
|
4094
|
+
workser cloud-agent create "Order desk" --instructions "..."
|
|
4095
|
+
workser cloud-agent show <agentId>
|
|
4096
|
+
workser cloud-agent run <agentId> "<what to do>"
|
|
4097
|
+
workser cloud-agent runs <agentId> # recent runs
|
|
4098
|
+
workser cloud-agent runs <runId> # one run, with what it cost
|
|
4099
|
+
\`\`\`
|
|
4100
|
+
|
|
4101
|
+
Every call is scoped to the project this folder belongs to.
|
|
4102
|
+
|
|
4103
|
+
## When to reach for this
|
|
4104
|
+
|
|
4105
|
+
When the user describes a job that **keeps happening** and needs judgement:
|
|
4106
|
+
"check every order for stock and email me the problems", "read the LINE
|
|
4107
|
+
messages and file them", "reconcile these invoices". That is an agent.
|
|
4108
|
+
|
|
4109
|
+
A one-off transformation is not an agent \u2014 write the code. A fixed sequence of
|
|
4110
|
+
steps with no judgement in it is not an agent either \u2014 that is \`workser
|
|
4111
|
+
workflow\`.
|
|
4112
|
+
|
|
4113
|
+
## Calling it from the app you are building
|
|
4114
|
+
|
|
4115
|
+
Do NOT shell out to the CLI from app code. Use the SDK, which streams:
|
|
4116
|
+
|
|
4117
|
+
\`\`\`ts
|
|
4118
|
+
import { workser } from '@workser/app';
|
|
4119
|
+
|
|
4120
|
+
const run = await workser.agents.run(agentId, { message }, {
|
|
4121
|
+
referenceUserId: user.id, // who it is acting for
|
|
4122
|
+
});
|
|
4123
|
+
|
|
4124
|
+
for await (const event of workser.agents.stream(run.id)) {
|
|
4125
|
+
// event.type, event.data \u2014 forward these to the browser
|
|
4126
|
+
}
|
|
4127
|
+
\`\`\`
|
|
4128
|
+
|
|
4129
|
+
\`stream()\` reconnects itself through dropped connections, so the person
|
|
4130
|
+
watching sees the agent think. See the \`workser-sdk\` skill, \`reference/agents.md\`.
|
|
4131
|
+
|
|
4132
|
+
## Things that will bite you
|
|
4133
|
+
|
|
4134
|
+
1. **A run costs money by the minute.** It is metered \u2014 runtime, workspace, and
|
|
4135
|
+
a per-run fee \u2014 so a loop that starts agents is a loop that spends. Cancel
|
|
4136
|
+
what you abandon: \`workser cloud-agent runs <runId>\` shows the cost.
|
|
4137
|
+
|
|
4138
|
+
2. **Instructions are the product.** The agent does what its instructions say,
|
|
4139
|
+
in the user's own words. Write them the way you would brief a new colleague:
|
|
4140
|
+
what to do, what to leave alone, when to ask. Vague instructions are the
|
|
4141
|
+
single biggest cause of an agent that "doesn't work".
|
|
4142
|
+
|
|
4143
|
+
3. **Free plans cannot run agents at all**, and a trial has a small allowance.
|
|
4144
|
+
A \`402\` with \`spend_limit_reached\` is not a bug \u2014 tell the user what it says
|
|
4145
|
+
and point them at their plan.
|
|
4146
|
+
|
|
4147
|
+
4. **Say who it is for.** An agent acting for one of the app's customers needs
|
|
4148
|
+
\`referenceUserId\`, or its memory and audit trail belong to nobody.
|
|
4149
|
+
|
|
4150
|
+
5. **Do not invent an agent the user did not ask for.** Creating one is cheap;
|
|
4151
|
+
an agent nobody wanted, quietly costing money per run, is not.
|
|
4066
4152
|
`
|
|
4067
4153
|
},
|
|
4068
4154
|
{
|
|
@@ -5624,6 +5710,9 @@ async function api(ctx, path, opts = {}) {
|
|
|
5624
5710
|
if (ctx.mode === "daemon" && ctx.runId) {
|
|
5625
5711
|
headers["x-workser-run-id"] = ctx.runId;
|
|
5626
5712
|
}
|
|
5713
|
+
if (ctx.mode === "daemon" && ctx.cwd) {
|
|
5714
|
+
headers["x-workser-cwd"] = encodeURIComponent(ctx.cwd);
|
|
5715
|
+
}
|
|
5627
5716
|
if (opts.body !== void 0) headers["content-type"] = "application/json";
|
|
5628
5717
|
const method = opts.method ?? (opts.body !== void 0 ? "POST" : "GET");
|
|
5629
5718
|
const bodyText = opts.body !== void 0 ? JSON.stringify(opts.body) : void 0;
|
|
@@ -5709,6 +5798,12 @@ function registerStatus(program3) {
|
|
|
5709
5798
|
` project: ${data.project?.name ?? "\u2014"}` + (data.project?.id ? import_picocolors3.default.dim(` (${data.project.id})`) : "")
|
|
5710
5799
|
);
|
|
5711
5800
|
if (ctx.projectRoot) line(` folder: ${import_picocolors3.default.dim(ctx.projectRoot)}`);
|
|
5801
|
+
if (data.scope) {
|
|
5802
|
+
const why = data.scope.source === "folder" ? "this folder" : data.scope.source === "active" ? "the project open in Workser" : null;
|
|
5803
|
+
line(
|
|
5804
|
+
data.scope.orgId ? ` org: ${data.scope.orgId}` + (why ? import_picocolors3.default.dim(` (from ${why})`) : "") : ` org: ${import_picocolors3.default.yellow("unscoped \u2014 every project is reachable")}`
|
|
5805
|
+
);
|
|
5806
|
+
}
|
|
5712
5807
|
if (ctx.appId) {
|
|
5713
5808
|
line(
|
|
5714
5809
|
` app: ${ctx.appName ?? "\u2014"}` + import_picocolors3.default.dim(` (${ctx.appId})`)
|
|
@@ -5921,7 +6016,7 @@ function registerProject(program3) {
|
|
|
5921
6016
|
});
|
|
5922
6017
|
})
|
|
5923
6018
|
);
|
|
5924
|
-
project.command("list").description("List the
|
|
6019
|
+
project.command("list").description("List the projects in your organization").action(
|
|
5925
6020
|
action(async ({ ctx }) => {
|
|
5926
6021
|
const items = await api(ctx, `/v1/projects`);
|
|
5927
6022
|
ok(items, () => {
|
|
@@ -5930,6 +6025,11 @@ function registerProject(program3) {
|
|
|
5930
6025
|
const pinned = ctx.projectId && p.id === ctx.projectId ? import_picocolors4.default.green("\u25CF ") : " ";
|
|
5931
6026
|
line(`${pinned}${p.name ?? "\u2014"}${p.id ? import_picocolors4.default.dim(` (${p.id})`) : ""}`);
|
|
5932
6027
|
}
|
|
6028
|
+
line(
|
|
6029
|
+
import_picocolors4.default.dim(
|
|
6030
|
+
"\nYour organization's projects. Other organizations are not reachable from here."
|
|
6031
|
+
)
|
|
6032
|
+
);
|
|
5933
6033
|
});
|
|
5934
6034
|
})
|
|
5935
6035
|
);
|
|
@@ -7437,8 +7537,154 @@ function formatRole(r) {
|
|
|
7437
7537
|
return `${label} ${agent} ${enabled} ${ready}${tail}`;
|
|
7438
7538
|
}
|
|
7439
7539
|
|
|
7440
|
-
// src/commands/
|
|
7540
|
+
// src/commands/cloud-agent.ts
|
|
7441
7541
|
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
7542
|
+
function registerCloudAgent(program3) {
|
|
7543
|
+
const cloud = program3.command("cloud-agent").description(
|
|
7544
|
+
"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`)"
|
|
7545
|
+
);
|
|
7546
|
+
cloud.command("list").description("List this project's cloud agents").action(
|
|
7547
|
+
action(async ({ ctx }) => {
|
|
7548
|
+
const res = await api(ctx, "/v1/cloud-agents");
|
|
7549
|
+
const agents = res?.agents ?? res ?? [];
|
|
7550
|
+
ok(res, () => {
|
|
7551
|
+
if (!agents.length) {
|
|
7552
|
+
line(import_picocolors17.default.dim("No cloud agents yet."));
|
|
7553
|
+
line(
|
|
7554
|
+
import_picocolors17.default.dim("Create one: ") + import_picocolors17.default.bold('workser cloud-agent create "Order desk" --instructions "..."')
|
|
7555
|
+
);
|
|
7556
|
+
return;
|
|
7557
|
+
}
|
|
7558
|
+
for (const a of agents) {
|
|
7559
|
+
line(
|
|
7560
|
+
`${import_picocolors17.default.bold(a.name ?? a.id)} ${import_picocolors17.default.dim(a.id)}` + (a.status ? ` ${import_picocolors17.default.dim(a.status)}` : "")
|
|
7561
|
+
);
|
|
7562
|
+
if (a.description) line(" " + import_picocolors17.default.dim(a.description));
|
|
7563
|
+
}
|
|
7564
|
+
});
|
|
7565
|
+
})
|
|
7566
|
+
);
|
|
7567
|
+
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(
|
|
7568
|
+
"--instructions <text>",
|
|
7569
|
+
"The agent's standing instructions \u2014 what it should always do"
|
|
7570
|
+
).action(
|
|
7571
|
+
action(async ({ ctx, args, opts }) => {
|
|
7572
|
+
const res = await api(ctx, "/v1/cloud-agents", {
|
|
7573
|
+
method: "POST",
|
|
7574
|
+
body: {
|
|
7575
|
+
name: args[0],
|
|
7576
|
+
description: opts.description,
|
|
7577
|
+
instructions: opts.instructions
|
|
7578
|
+
}
|
|
7579
|
+
});
|
|
7580
|
+
ok(res, () => {
|
|
7581
|
+
line(import_picocolors17.default.green("Created ") + import_picocolors17.default.bold(res?.name ?? args[0]));
|
|
7582
|
+
if (res?.id) line(import_picocolors17.default.dim(res.id));
|
|
7583
|
+
line("");
|
|
7584
|
+
line(
|
|
7585
|
+
import_picocolors17.default.dim("Give it work: ") + import_picocolors17.default.bold(`workser cloud-agent run ${res?.id ?? "<id>"} "..."`)
|
|
7586
|
+
);
|
|
7587
|
+
});
|
|
7588
|
+
})
|
|
7589
|
+
);
|
|
7590
|
+
cloud.command("show <agentId>").description("One cloud agent, with its configuration").action(
|
|
7591
|
+
action(async ({ ctx, args }) => {
|
|
7592
|
+
const res = await api(ctx, `/v1/cloud-agents/${encodeURIComponent(args[0])}`);
|
|
7593
|
+
ok(res, () => {
|
|
7594
|
+
line(import_picocolors17.default.bold(res?.name ?? args[0]));
|
|
7595
|
+
if (res?.description) line(import_picocolors17.default.dim(res.description));
|
|
7596
|
+
if (res?.instructions) {
|
|
7597
|
+
line("");
|
|
7598
|
+
line(import_picocolors17.default.bold("instructions:"));
|
|
7599
|
+
line(res.instructions);
|
|
7600
|
+
}
|
|
7601
|
+
});
|
|
7602
|
+
})
|
|
7603
|
+
);
|
|
7604
|
+
cloud.command("run <agentId> <message>").description("Give a cloud agent something to do").action(
|
|
7605
|
+
action(async ({ ctx, args }) => {
|
|
7606
|
+
const res = await api(
|
|
7607
|
+
ctx,
|
|
7608
|
+
`/v1/cloud-agents/${encodeURIComponent(args[0])}/runs`,
|
|
7609
|
+
{ method: "POST", body: { input: { message: args[1] } } }
|
|
7610
|
+
);
|
|
7611
|
+
ok(res, () => {
|
|
7612
|
+
line(import_picocolors17.default.green("Started run ") + import_picocolors17.default.bold(res?.id ?? ""));
|
|
7613
|
+
line(
|
|
7614
|
+
import_picocolors17.default.dim("Follow it: ") + import_picocolors17.default.bold(`workser cloud-agent runs ${res?.id ?? "<runId>"}`)
|
|
7615
|
+
);
|
|
7616
|
+
});
|
|
7617
|
+
})
|
|
7618
|
+
);
|
|
7619
|
+
cloud.command("runs [agentIdOrRunId]").description("Recent runs for an agent, or one run in detail").option("--limit <n>", "How many to list", "10").action(
|
|
7620
|
+
action(async ({ ctx, args, opts }) => {
|
|
7621
|
+
const id = args[0];
|
|
7622
|
+
if (!id) {
|
|
7623
|
+
warn("Give an agent id to list its runs, or a run id to inspect one.");
|
|
7624
|
+
return;
|
|
7625
|
+
}
|
|
7626
|
+
try {
|
|
7627
|
+
const run = await api(
|
|
7628
|
+
ctx,
|
|
7629
|
+
`/v1/cloud-agents/runs/${encodeURIComponent(id)}`
|
|
7630
|
+
);
|
|
7631
|
+
ok(run, () => printRun(run));
|
|
7632
|
+
return;
|
|
7633
|
+
} catch {
|
|
7634
|
+
}
|
|
7635
|
+
const res = await api(
|
|
7636
|
+
ctx,
|
|
7637
|
+
`/v1/cloud-agents/${encodeURIComponent(id)}/runs`,
|
|
7638
|
+
{ query: { limit: opts.limit } }
|
|
7639
|
+
);
|
|
7640
|
+
const runs = res?.runs ?? res ?? [];
|
|
7641
|
+
ok(res, () => {
|
|
7642
|
+
if (!runs.length) {
|
|
7643
|
+
line(import_picocolors17.default.dim("No runs yet."));
|
|
7644
|
+
return;
|
|
7645
|
+
}
|
|
7646
|
+
for (const r of runs) printRun(r, true);
|
|
7647
|
+
});
|
|
7648
|
+
})
|
|
7649
|
+
);
|
|
7650
|
+
}
|
|
7651
|
+
function printRun(run, compact = false) {
|
|
7652
|
+
const status = String(run?.status ?? "").toLowerCase();
|
|
7653
|
+
const colour2 = status === "completed" ? import_picocolors17.default.green : status === "failed" ? import_picocolors17.default.red : import_picocolors17.default.yellow;
|
|
7654
|
+
line(
|
|
7655
|
+
`${colour2(status || "unknown")} ${import_picocolors17.default.bold(run?.id ?? "")}` + (run?.duration_ms ? ` ${import_picocolors17.default.dim(formatDuration(run.duration_ms))}` : "")
|
|
7656
|
+
);
|
|
7657
|
+
const breakdown = run?.cost_breakdown;
|
|
7658
|
+
if (breakdown) {
|
|
7659
|
+
if (!breakdown.settled) {
|
|
7660
|
+
line(" " + import_picocolors17.default.dim("cost: still being worked out"));
|
|
7661
|
+
} else {
|
|
7662
|
+
line(" " + import_picocolors17.default.dim(`cost: $${Number(breakdown.total_usd).toFixed(4)}`));
|
|
7663
|
+
line(
|
|
7664
|
+
" " + import_picocolors17.default.dim(
|
|
7665
|
+
`model $${Number(breakdown.model_usd).toFixed(4)} \xB7 infrastructure $${Number(breakdown.infrastructure_usd).toFixed(4)}`
|
|
7666
|
+
)
|
|
7667
|
+
);
|
|
7668
|
+
}
|
|
7669
|
+
} else if (run?.cost_usd !== void 0 && run?.cost_usd !== null) {
|
|
7670
|
+
line(" " + import_picocolors17.default.dim(`model cost: $${Number(run.cost_usd).toFixed(4)}`));
|
|
7671
|
+
}
|
|
7672
|
+
if (!compact && run?.output) {
|
|
7673
|
+
line("");
|
|
7674
|
+
line(typeof run.output === "string" ? run.output : JSON.stringify(run.output, null, 2));
|
|
7675
|
+
}
|
|
7676
|
+
if (run?.error?.message) line(" " + import_picocolors17.default.red(run.error.message));
|
|
7677
|
+
}
|
|
7678
|
+
function formatDuration(ms) {
|
|
7679
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
7680
|
+
const seconds = Math.round(ms / 1e3);
|
|
7681
|
+
if (seconds < 60) return `${seconds}s`;
|
|
7682
|
+
const minutes = Math.floor(seconds / 60);
|
|
7683
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
7684
|
+
}
|
|
7685
|
+
|
|
7686
|
+
// src/commands/verify.ts
|
|
7687
|
+
var import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
7442
7688
|
function registerVerify(program3) {
|
|
7443
7689
|
program3.command("verify").description(
|
|
7444
7690
|
"Run the project's checks (typecheck/lint/build) \u2014 use before declaring a task done"
|
|
@@ -7460,23 +7706,23 @@ function registerVerify(program3) {
|
|
|
7460
7706
|
function printVerify(res) {
|
|
7461
7707
|
if (!res) return;
|
|
7462
7708
|
if (!res.checks?.length) {
|
|
7463
|
-
line(
|
|
7709
|
+
line(import_picocolors18.default.dim(res.note ?? "No checks detected."));
|
|
7464
7710
|
return;
|
|
7465
7711
|
}
|
|
7466
7712
|
for (const c of res.checks) {
|
|
7467
7713
|
line(
|
|
7468
|
-
` ${c.ok ?
|
|
7714
|
+
` ${c.ok ? import_picocolors18.default.green("\u2713") : import_picocolors18.default.red("\u2717")} ${c.name}${c.ok ? "" : import_picocolors18.default.dim(` (exit ${c.exitCode})`)}`
|
|
7469
7715
|
);
|
|
7470
7716
|
}
|
|
7471
7717
|
if (res.ok) success("All checks passed");
|
|
7472
7718
|
else
|
|
7473
7719
|
line(
|
|
7474
|
-
|
|
7720
|
+
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(".")
|
|
7475
7721
|
);
|
|
7476
7722
|
}
|
|
7477
7723
|
|
|
7478
7724
|
// src/commands/checkpoint.ts
|
|
7479
|
-
var
|
|
7725
|
+
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
7480
7726
|
function registerCheckpoint(program3) {
|
|
7481
7727
|
program3.command("checkpoint [label]").description(
|
|
7482
7728
|
"Save the current state of this folder so you can come back to it"
|
|
@@ -7493,8 +7739,8 @@ function registerCheckpoint(program3) {
|
|
|
7493
7739
|
ok(res, () => {
|
|
7494
7740
|
const p = res?.point;
|
|
7495
7741
|
success(`Saved a checkpoint${p?.label ? `: ${p.label}` : ""}`);
|
|
7496
|
-
if (p?.ref) line(
|
|
7497
|
-
line(
|
|
7742
|
+
if (p?.ref) line(import_picocolors19.default.dim(` ${p.ref.slice(0, 7)}`));
|
|
7743
|
+
line(import_picocolors19.default.dim(" Come back to it with `workser restore`."));
|
|
7498
7744
|
});
|
|
7499
7745
|
})
|
|
7500
7746
|
);
|
|
@@ -7520,12 +7766,12 @@ function registerCheckpoint(program3) {
|
|
|
7520
7766
|
);
|
|
7521
7767
|
if (res?.filesChanged) {
|
|
7522
7768
|
line(
|
|
7523
|
-
|
|
7769
|
+
import_picocolors19.default.dim(
|
|
7524
7770
|
` ${res.filesChanged} file${res.filesChanged === 1 ? "" : "s"} changed`
|
|
7525
7771
|
)
|
|
7526
7772
|
);
|
|
7527
7773
|
}
|
|
7528
|
-
line(
|
|
7774
|
+
line(import_picocolors19.default.dim(" This is reversible: `workser restore` again."));
|
|
7529
7775
|
});
|
|
7530
7776
|
})
|
|
7531
7777
|
);
|
|
@@ -7542,25 +7788,25 @@ function registerCheckpoint(program3) {
|
|
|
7542
7788
|
function printPoints(points) {
|
|
7543
7789
|
if (!points.length) {
|
|
7544
7790
|
info("No checkpoints yet for this folder.");
|
|
7545
|
-
line(
|
|
7791
|
+
line(import_picocolors19.default.dim(" Take one with `workser checkpoint`."));
|
|
7546
7792
|
return;
|
|
7547
7793
|
}
|
|
7548
|
-
line(
|
|
7794
|
+
line(import_picocolors19.default.bold("Checkpoints"));
|
|
7549
7795
|
for (const p of points) {
|
|
7550
7796
|
const when = p.at ? new Date(p.at).toLocaleString() : "";
|
|
7551
7797
|
line(
|
|
7552
|
-
` ${
|
|
7798
|
+
` ${import_picocolors19.default.dim(p.ref.slice(0, 7))} ${p.label}${when ? import_picocolors19.default.dim(` ${when}`) : ""}`
|
|
7553
7799
|
);
|
|
7554
7800
|
}
|
|
7555
7801
|
line(
|
|
7556
|
-
|
|
7802
|
+
import_picocolors19.default.dim(
|
|
7557
7803
|
"\nGo back with `workser restore <ref>`, or just `workser restore` for the newest."
|
|
7558
7804
|
)
|
|
7559
7805
|
);
|
|
7560
7806
|
}
|
|
7561
7807
|
|
|
7562
7808
|
// src/commands/sync.ts
|
|
7563
|
-
var
|
|
7809
|
+
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
7564
7810
|
function registerSync(program3) {
|
|
7565
7811
|
program3.command("sync").description(
|
|
7566
7812
|
"Reconcile this folder with the copy Workser holds (pull, then push)"
|
|
@@ -7587,7 +7833,7 @@ function registerSync(program3) {
|
|
|
7587
7833
|
warn(res?.message ?? "Couldn't sync this folder.");
|
|
7588
7834
|
if (res?.state === "diverged") {
|
|
7589
7835
|
line(
|
|
7590
|
-
|
|
7836
|
+
import_picocolors20.default.dim(
|
|
7591
7837
|
" This folder and Workser's copy have both changed. Open Workser to resolve it."
|
|
7592
7838
|
)
|
|
7593
7839
|
);
|
|
@@ -7599,7 +7845,7 @@ function registerSync(program3) {
|
|
|
7599
7845
|
return;
|
|
7600
7846
|
}
|
|
7601
7847
|
success("Synced");
|
|
7602
|
-
if (res?.ref) line(
|
|
7848
|
+
if (res?.ref) line(import_picocolors20.default.dim(` ${String(res.ref).slice(0, 7)}`));
|
|
7603
7849
|
});
|
|
7604
7850
|
if (refused) process.exitCode = 1;
|
|
7605
7851
|
})
|
|
@@ -7607,7 +7853,7 @@ function registerSync(program3) {
|
|
|
7607
7853
|
}
|
|
7608
7854
|
|
|
7609
7855
|
// src/commands/workflow.ts
|
|
7610
|
-
var
|
|
7856
|
+
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
7611
7857
|
function registerWorkflow(program3) {
|
|
7612
7858
|
const wf = program3.command("workflow").description("Create, run, and inspect workflow automations for the project");
|
|
7613
7859
|
wf.command("list").description("List the project's workflows").action(
|
|
@@ -7615,10 +7861,10 @@ function registerWorkflow(program3) {
|
|
|
7615
7861
|
const projectId = requireProject(ctx);
|
|
7616
7862
|
const items = await api(ctx, `/v1/projects/${projectId}/workflows`);
|
|
7617
7863
|
ok(items, () => {
|
|
7618
|
-
if (!items?.length) return line(
|
|
7864
|
+
if (!items?.length) return line(import_picocolors21.default.dim("No workflows yet. `workser workflow create`."));
|
|
7619
7865
|
for (const w of items) {
|
|
7620
|
-
const status = w.is_active ?
|
|
7621
|
-
line(`${w.id} ${
|
|
7866
|
+
const status = w.is_active ? import_picocolors21.default.green("active") : import_picocolors21.default.dim("inactive");
|
|
7867
|
+
line(`${w.id} ${import_picocolors21.default.bold(w.name ?? "Untitled")} ${status}`);
|
|
7622
7868
|
}
|
|
7623
7869
|
});
|
|
7624
7870
|
})
|
|
@@ -7630,7 +7876,7 @@ function registerWorkflow(program3) {
|
|
|
7630
7876
|
const res = await api(ctx, `/v1/projects/${projectId}/workflows`, {
|
|
7631
7877
|
body: { name: args[0], ...extra }
|
|
7632
7878
|
});
|
|
7633
|
-
ok(res, () => line(`Created workflow ${
|
|
7879
|
+
ok(res, () => line(`Created workflow ${import_picocolors21.default.bold(res.id)}.`));
|
|
7634
7880
|
})
|
|
7635
7881
|
);
|
|
7636
7882
|
wf.command("get <id>").description("Show a workflow's full definition").action(
|
|
@@ -7665,8 +7911,8 @@ function registerWorkflow(program3) {
|
|
|
7665
7911
|
action(async ({ ctx, args }) => {
|
|
7666
7912
|
const items = await api(ctx, `/v1/workflows/${args[0]}/executions`);
|
|
7667
7913
|
ok(items, () => {
|
|
7668
|
-
if (!items?.length) return line(
|
|
7669
|
-
for (const e of items) line(`${e.id} ${e.status ?? ""} ${
|
|
7914
|
+
if (!items?.length) return line(import_picocolors21.default.dim("No runs yet."));
|
|
7915
|
+
for (const e of items) line(`${e.id} ${e.status ?? ""} ${import_picocolors21.default.dim(e.started_at ?? "")}`);
|
|
7670
7916
|
});
|
|
7671
7917
|
})
|
|
7672
7918
|
);
|
|
@@ -7674,15 +7920,15 @@ function registerWorkflow(program3) {
|
|
|
7674
7920
|
action(async ({ ctx, args }) => {
|
|
7675
7921
|
const items = await api(ctx, `/v1/node-types`, { query: { q: args[0] } });
|
|
7676
7922
|
ok(items, () => {
|
|
7677
|
-
if (!items?.length) return line(
|
|
7678
|
-
for (const n of items) line(`${n.name ?? n.type} ${
|
|
7923
|
+
if (!items?.length) return line(import_picocolors21.default.dim("No matching node types."));
|
|
7924
|
+
for (const n of items) line(`${n.name ?? n.type} ${import_picocolors21.default.dim(n.category ?? "")}`);
|
|
7679
7925
|
});
|
|
7680
7926
|
})
|
|
7681
7927
|
);
|
|
7682
7928
|
}
|
|
7683
7929
|
|
|
7684
7930
|
// src/commands/connection.ts
|
|
7685
|
-
var
|
|
7931
|
+
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
7686
7932
|
function registerConnection(program3) {
|
|
7687
7933
|
const connection = program3.command("connection").description("Connect and use third-party app connections (Gmail, Slack, Stripe, ...)");
|
|
7688
7934
|
connection.command("list").description("List connectable toolkits and this project's existing connections").option("--toolkit <slug>", "filter connections to one toolkit").action(
|
|
@@ -7695,8 +7941,8 @@ function registerConnection(program3) {
|
|
|
7695
7941
|
ok({ catalog, connections }, () => {
|
|
7696
7942
|
const connected = new Set((connections ?? []).map((c) => c.toolkit ?? c.composio_app));
|
|
7697
7943
|
for (const t of catalog ?? []) {
|
|
7698
|
-
const status = connected.has(t.slug) ?
|
|
7699
|
-
line(`${t.slug} ${
|
|
7944
|
+
const status = connected.has(t.slug) ? import_picocolors22.default.green("connected") : import_picocolors22.default.dim("not connected");
|
|
7945
|
+
line(`${t.slug} ${import_picocolors22.default.bold(t.name ?? t.slug)} ${status}`);
|
|
7700
7946
|
}
|
|
7701
7947
|
});
|
|
7702
7948
|
})
|
|
@@ -7708,9 +7954,9 @@ function registerConnection(program3) {
|
|
|
7708
7954
|
query: { q: args[0], toolkit: opts.toolkit, limit: opts.limit }
|
|
7709
7955
|
});
|
|
7710
7956
|
ok(items, () => {
|
|
7711
|
-
if (!items?.length) return line(
|
|
7957
|
+
if (!items?.length) return line(import_picocolors22.default.dim("No matching actions."));
|
|
7712
7958
|
for (const t of items) {
|
|
7713
|
-
line(`${t.slug} ${
|
|
7959
|
+
line(`${t.slug} ${import_picocolors22.default.dim(`[${t.toolkit}]`)} ${t.description ?? ""}`);
|
|
7714
7960
|
}
|
|
7715
7961
|
});
|
|
7716
7962
|
})
|
|
@@ -7727,7 +7973,7 @@ function registerConnection(program3) {
|
|
|
7727
7973
|
});
|
|
7728
7974
|
ok(
|
|
7729
7975
|
res,
|
|
7730
|
-
() => res.oauth_url ? line(`Open this URL to finish connecting: ${
|
|
7976
|
+
() => 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}.`)
|
|
7731
7977
|
);
|
|
7732
7978
|
})
|
|
7733
7979
|
);
|
|
@@ -7745,8 +7991,8 @@ function registerConnection(program3) {
|
|
|
7745
7991
|
const projectId = requireProject(ctx);
|
|
7746
7992
|
const items = await api(ctx, `/v1/projects/${projectId}/integrations/${args[0]}/tools`);
|
|
7747
7993
|
ok(items, () => {
|
|
7748
|
-
if (!items?.length) return line(
|
|
7749
|
-
for (const t of items) line(`${t.slug} ${
|
|
7994
|
+
if (!items?.length) return line(import_picocolors22.default.dim("No tools found."));
|
|
7995
|
+
for (const t of items) line(`${t.slug} ${import_picocolors22.default.dim(t.description ?? "")}`);
|
|
7750
7996
|
});
|
|
7751
7997
|
})
|
|
7752
7998
|
);
|
|
@@ -7762,7 +8008,7 @@ function registerConnection(program3) {
|
|
|
7762
8008
|
}
|
|
7763
8009
|
|
|
7764
8010
|
// src/commands/tool.ts
|
|
7765
|
-
var
|
|
8011
|
+
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
7766
8012
|
function registerTool(program3) {
|
|
7767
8013
|
const tool = program3.command("tool").description(
|
|
7768
8014
|
"Computer-use tools: filesystem, shell, screenshot, input control, clipboard, notifications, basic browser"
|
|
@@ -7771,7 +8017,7 @@ function registerTool(program3) {
|
|
|
7771
8017
|
action(async ({ ctx }) => {
|
|
7772
8018
|
const tools = await api(ctx, "/v1/tool/list");
|
|
7773
8019
|
ok(tools, () => {
|
|
7774
|
-
if (!tools?.length) return line(
|
|
8020
|
+
if (!tools?.length) return line(import_picocolors23.default.dim("No tools available."));
|
|
7775
8021
|
const byCategory = /* @__PURE__ */ new Map();
|
|
7776
8022
|
for (const t of tools) {
|
|
7777
8023
|
const list = byCategory.get(t.category) ?? [];
|
|
@@ -7779,9 +8025,9 @@ function registerTool(program3) {
|
|
|
7779
8025
|
byCategory.set(t.category, list);
|
|
7780
8026
|
}
|
|
7781
8027
|
for (const [category, items] of byCategory) {
|
|
7782
|
-
line(
|
|
8028
|
+
line(import_picocolors23.default.bold(category) + ":");
|
|
7783
8029
|
for (const t of items) {
|
|
7784
|
-
line(` ${t.name} ${
|
|
8030
|
+
line(` ${t.name} ${import_picocolors23.default.dim(t.description ?? "")}`);
|
|
7785
8031
|
}
|
|
7786
8032
|
}
|
|
7787
8033
|
});
|
|
@@ -7799,7 +8045,7 @@ function registerTool(program3) {
|
|
|
7799
8045
|
}
|
|
7800
8046
|
|
|
7801
8047
|
// src/commands/memory.ts
|
|
7802
|
-
var
|
|
8048
|
+
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
7803
8049
|
function registerMemory(program3) {
|
|
7804
8050
|
const memory = program3.command("memory").description("Durable, cross-conversation project memory (shared with cloud agents on the same project)");
|
|
7805
8051
|
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(
|
|
@@ -7823,9 +8069,9 @@ function registerMemory(program3) {
|
|
|
7823
8069
|
});
|
|
7824
8070
|
ok(res, () => {
|
|
7825
8071
|
const results = res?.results ?? res ?? [];
|
|
7826
|
-
if (!results?.length) return line(
|
|
8072
|
+
if (!results?.length) return line(import_picocolors24.default.dim("No matching memories."));
|
|
7827
8073
|
for (const r of results) {
|
|
7828
|
-
line(`${
|
|
8074
|
+
line(`${import_picocolors24.default.dim(r.id ?? "?")} ${r.memory ?? r.content ?? ""}`);
|
|
7829
8075
|
}
|
|
7830
8076
|
});
|
|
7831
8077
|
})
|
|
@@ -7841,8 +8087,52 @@ function registerMemory(program3) {
|
|
|
7841
8087
|
);
|
|
7842
8088
|
}
|
|
7843
8089
|
|
|
8090
|
+
// src/commands/note.ts
|
|
8091
|
+
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
8092
|
+
function registerNote(program3) {
|
|
8093
|
+
program3.command("note <text>").description("Leave a fact the rest of the team will need").addHelpText(
|
|
8094
|
+
"after",
|
|
8095
|
+
'\nFor things that are true about the WORK, not about your step:\n workser note "the API base path is /api/v2, not /api"\n workser note "added STRIPE_KEY to local, preview and production"\n\nWhat your own step did goes in `workser task done --summary` instead.\n'
|
|
8096
|
+
).option(
|
|
8097
|
+
"--task <id>",
|
|
8098
|
+
"the plan to leave it on (default: the plan this step belongs to)"
|
|
8099
|
+
).action(
|
|
8100
|
+
action(async ({ ctx, args, opts }) => {
|
|
8101
|
+
const text = typeof args[0] === "string" ? args[0].trim() : "";
|
|
8102
|
+
if (!text) {
|
|
8103
|
+
info("Nothing to note \u2014 give it a sentence.");
|
|
8104
|
+
return;
|
|
8105
|
+
}
|
|
8106
|
+
const taskId = opts.task || ctx.parentTaskId || ctx.projectTaskId;
|
|
8107
|
+
if (!taskId) {
|
|
8108
|
+
info(
|
|
8109
|
+
"No plan to leave this on. Run it from inside a step, or pass --task <id>."
|
|
8110
|
+
);
|
|
8111
|
+
return;
|
|
8112
|
+
}
|
|
8113
|
+
const res = await api(ctx, "/v1/team-notes", {
|
|
8114
|
+
body: {
|
|
8115
|
+
cwd: ctx.cwd,
|
|
8116
|
+
taskId,
|
|
8117
|
+
text,
|
|
8118
|
+
role: ctx.agentRole,
|
|
8119
|
+
agent: ctx.agentType
|
|
8120
|
+
}
|
|
8121
|
+
}).catch(() => null);
|
|
8122
|
+
if (!res) {
|
|
8123
|
+
info("Couldn't save that note \u2014 carrying on.");
|
|
8124
|
+
return;
|
|
8125
|
+
}
|
|
8126
|
+
ok(res, () => {
|
|
8127
|
+
success("Noted for the team.");
|
|
8128
|
+
line(import_picocolors25.default.dim(` ${text}`));
|
|
8129
|
+
});
|
|
8130
|
+
})
|
|
8131
|
+
);
|
|
8132
|
+
}
|
|
8133
|
+
|
|
7844
8134
|
// src/commands/business.ts
|
|
7845
|
-
var
|
|
8135
|
+
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
7846
8136
|
var RESOURCE_PATHS = {
|
|
7847
8137
|
"business-config": "business-config",
|
|
7848
8138
|
"business-settings": "business-settings",
|
|
@@ -7902,7 +8192,7 @@ function registerBusiness(program3) {
|
|
|
7902
8192
|
const projectId = requireProject(ctx);
|
|
7903
8193
|
const [resource] = args;
|
|
7904
8194
|
const res = await api(ctx, businessPath(projectId, resource), { body: JSON.parse(opts.body) });
|
|
7905
|
-
ok(res, () => line(`Created ${resource} ${
|
|
8195
|
+
ok(res, () => line(`Created ${resource} ${import_picocolors26.default.bold(res?.id ?? "")}.`));
|
|
7906
8196
|
})
|
|
7907
8197
|
);
|
|
7908
8198
|
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(
|
|
@@ -7944,7 +8234,7 @@ function businessPath(projectId, resource, subpath) {
|
|
|
7944
8234
|
}
|
|
7945
8235
|
|
|
7946
8236
|
// src/commands/artifact.ts
|
|
7947
|
-
var
|
|
8237
|
+
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
7948
8238
|
import { existsSync as existsSync2, statSync } from "fs";
|
|
7949
8239
|
import { resolve as resolve3, basename as basename3 } from "path";
|
|
7950
8240
|
var KINDS = [
|
|
@@ -8041,7 +8331,7 @@ function registerArtifact(program3) {
|
|
|
8041
8331
|
ok(
|
|
8042
8332
|
res,
|
|
8043
8333
|
() => success(
|
|
8044
|
-
`Recorded ${
|
|
8334
|
+
`Recorded ${import_picocolors27.default.bold(res?.title ?? "artifact")}${res?.kind ? import_picocolors27.default.dim(` (${res.kind})`) : ""}`
|
|
8045
8335
|
)
|
|
8046
8336
|
);
|
|
8047
8337
|
})
|
|
@@ -8073,13 +8363,13 @@ function registerArtifact(program3) {
|
|
|
8073
8363
|
artifact.command("run").description("Show the task/conversation this agent run is attached to").action(
|
|
8074
8364
|
action(async ({ ctx }) => {
|
|
8075
8365
|
const res = await api(ctx, `/v1/runs/${runTarget(ctx)}`);
|
|
8076
|
-
ok(res, () =>
|
|
8366
|
+
ok(res, () => printRun2(res));
|
|
8077
8367
|
})
|
|
8078
8368
|
);
|
|
8079
8369
|
}
|
|
8080
8370
|
function printArtifacts(rows) {
|
|
8081
8371
|
if (!rows.length) {
|
|
8082
|
-
line(
|
|
8372
|
+
line(import_picocolors27.default.dim("Nothing produced yet."));
|
|
8083
8373
|
return;
|
|
8084
8374
|
}
|
|
8085
8375
|
const byStep = /* @__PURE__ */ new Map();
|
|
@@ -8089,26 +8379,26 @@ function printArtifacts(rows) {
|
|
|
8089
8379
|
byStep.set(r.subtask_id, list);
|
|
8090
8380
|
}
|
|
8091
8381
|
for (const [stepId, items] of byStep) {
|
|
8092
|
-
line(
|
|
8382
|
+
line(import_picocolors27.default.bold(`step ${stepId}`));
|
|
8093
8383
|
for (const a of items) {
|
|
8094
|
-
const flag = a.promoted_at ?
|
|
8384
|
+
const flag = a.promoted_at ? import_picocolors27.default.green(" *") : " ";
|
|
8095
8385
|
const where = a.local_path || a.cloud_url || "";
|
|
8096
8386
|
line(
|
|
8097
|
-
`${flag} ${
|
|
8387
|
+
`${flag} ${import_picocolors27.default.dim(`[${a.kind}]`)} ${a.title ?? "(untitled)"}` + (where ? import_picocolors27.default.dim(` ${where}`) : "")
|
|
8098
8388
|
);
|
|
8099
|
-
if (a.description) line(
|
|
8389
|
+
if (a.description) line(import_picocolors27.default.dim(` ${a.description}`));
|
|
8100
8390
|
}
|
|
8101
8391
|
line("");
|
|
8102
8392
|
}
|
|
8103
|
-
line(
|
|
8393
|
+
line(import_picocolors27.default.dim("* = handed over as a deliverable; the rest is working material."));
|
|
8104
8394
|
}
|
|
8105
|
-
function
|
|
8395
|
+
function printRun2(run) {
|
|
8106
8396
|
if (!run) return;
|
|
8107
|
-
line(` run ${
|
|
8397
|
+
line(` run ${import_picocolors27.default.bold(run.runId)}`);
|
|
8108
8398
|
if (run.taskId) line(` task ${run.taskId}`);
|
|
8109
8399
|
if (run.conversationId) line(` chat ${run.conversationId}`);
|
|
8110
8400
|
if (run.projectId) line(` project ${run.projectId}`);
|
|
8111
|
-
if (run.cwd) line(` folder ${
|
|
8401
|
+
if (run.cwd) line(` folder ${import_picocolors27.default.dim(run.cwd)}`);
|
|
8112
8402
|
}
|
|
8113
8403
|
|
|
8114
8404
|
// src/commands/image.ts
|
|
@@ -8289,7 +8579,7 @@ function registerAudio(program3) {
|
|
|
8289
8579
|
}
|
|
8290
8580
|
|
|
8291
8581
|
// src/commands/ask.ts
|
|
8292
|
-
var
|
|
8582
|
+
var import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
8293
8583
|
var TYPES = [
|
|
8294
8584
|
"input",
|
|
8295
8585
|
"choice",
|
|
@@ -8367,7 +8657,7 @@ function registerAsk(program3) {
|
|
|
8367
8657
|
code: "bad_request"
|
|
8368
8658
|
});
|
|
8369
8659
|
}
|
|
8370
|
-
info(
|
|
8660
|
+
info(import_picocolors28.default.dim("Waiting for the user to answer\u2026"));
|
|
8371
8661
|
const res = await api(ctx, `/v1/runs/${runTarget(ctx)}/ask`, {
|
|
8372
8662
|
body: {
|
|
8373
8663
|
type,
|
|
@@ -8395,12 +8685,12 @@ function deriveTitle(message) {
|
|
|
8395
8685
|
function printAnswer(res) {
|
|
8396
8686
|
if (!res) return;
|
|
8397
8687
|
if (res.status === "answered") {
|
|
8398
|
-
line(` ${
|
|
8688
|
+
line(` ${import_picocolors28.default.green("answered")}`);
|
|
8399
8689
|
const value = extract(res.response);
|
|
8400
8690
|
if (value) line(` ${value}`);
|
|
8401
8691
|
return;
|
|
8402
8692
|
}
|
|
8403
|
-
line(` ${
|
|
8693
|
+
line(` ${import_picocolors28.default.yellow(res.status)} ${import_picocolors28.default.dim(res.reason ?? "")}`);
|
|
8404
8694
|
}
|
|
8405
8695
|
function extract(response) {
|
|
8406
8696
|
if (response == null) return "";
|
|
@@ -8419,7 +8709,7 @@ function extract(response) {
|
|
|
8419
8709
|
}
|
|
8420
8710
|
|
|
8421
8711
|
// src/commands/search.ts
|
|
8422
|
-
var
|
|
8712
|
+
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
8423
8713
|
function registerSearch(program3) {
|
|
8424
8714
|
program3.command("search <query>").description("Search the web (Google-grounded, server-side)").option("-n, --max-results <n>", "max results", "5").action(
|
|
8425
8715
|
action(async ({ ctx, args, opts }) => {
|
|
@@ -8432,9 +8722,9 @@ function registerSearch(program3) {
|
|
|
8432
8722
|
line("");
|
|
8433
8723
|
}
|
|
8434
8724
|
const results = res?.results ?? [];
|
|
8435
|
-
if (!results.length) return line(
|
|
8725
|
+
if (!results.length) return line(import_picocolors29.default.dim("No results."));
|
|
8436
8726
|
for (const r of results) {
|
|
8437
|
-
line(`${r.title ||
|
|
8727
|
+
line(`${r.title || import_picocolors29.default.dim("(untitled)")} ${import_picocolors29.default.dim(r.url)}`);
|
|
8438
8728
|
}
|
|
8439
8729
|
});
|
|
8440
8730
|
})
|
|
@@ -8442,7 +8732,7 @@ function registerSearch(program3) {
|
|
|
8442
8732
|
}
|
|
8443
8733
|
|
|
8444
8734
|
// src/commands/board.ts
|
|
8445
|
-
var
|
|
8735
|
+
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
8446
8736
|
|
|
8447
8737
|
// src/commands/record-step.ts
|
|
8448
8738
|
async function recordEntityStep(ctx, opts) {
|
|
@@ -8481,7 +8771,7 @@ function registerBoard(program3) {
|
|
|
8481
8771
|
}
|
|
8482
8772
|
ok(rows, () => {
|
|
8483
8773
|
if (!rows.length) {
|
|
8484
|
-
line(
|
|
8774
|
+
line(import_picocolors30.default.dim("No cards on the Board yet."));
|
|
8485
8775
|
return;
|
|
8486
8776
|
}
|
|
8487
8777
|
for (const r of rows) line(formatRow(r));
|
|
@@ -8496,7 +8786,7 @@ function registerBoard(program3) {
|
|
|
8496
8786
|
`/v1/projects/${projectId}/work-items/${args[0]}`
|
|
8497
8787
|
);
|
|
8498
8788
|
ok(row, () => {
|
|
8499
|
-
line(`${
|
|
8789
|
+
line(`${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.id)}`);
|
|
8500
8790
|
line(`${statusTag(row.status)} priority ${row.priority}`);
|
|
8501
8791
|
if (row.ownerHuman) line(`owner: ${row.ownerHuman}`);
|
|
8502
8792
|
if (row.labels?.length) line(`labels: ${row.labels.join(", ")}`);
|
|
@@ -8537,7 +8827,7 @@ ${row.description}`);
|
|
|
8537
8827
|
refId: row?.id,
|
|
8538
8828
|
output: { workItem: row }
|
|
8539
8829
|
});
|
|
8540
|
-
ok(row, () => line(`Created work item ${
|
|
8830
|
+
ok(row, () => line(`Created work item ${import_picocolors30.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
8541
8831
|
})
|
|
8542
8832
|
);
|
|
8543
8833
|
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(
|
|
@@ -8571,7 +8861,7 @@ ${row.description}`);
|
|
|
8571
8861
|
);
|
|
8572
8862
|
}
|
|
8573
8863
|
const row = await patchItem(ctx, projectId, String(args[0]), body);
|
|
8574
|
-
ok(row, () => line(`Updated ${
|
|
8864
|
+
ok(row, () => line(`Updated ${import_picocolors30.default.bold(row.id)} \u2014 ${row.title} ${statusTag(row.status)}`));
|
|
8575
8865
|
})
|
|
8576
8866
|
);
|
|
8577
8867
|
board.command("move <id> <status>").description(
|
|
@@ -8582,14 +8872,14 @@ ${row.description}`);
|
|
|
8582
8872
|
const status = String(args[1]);
|
|
8583
8873
|
assertStatus(status);
|
|
8584
8874
|
const row = await patchItem(ctx, projectId, String(args[0]), { status });
|
|
8585
|
-
ok(row, () => line(`Moved ${
|
|
8875
|
+
ok(row, () => line(`Moved ${import_picocolors30.default.bold(row.title)} \u2192 ${statusTag(row.status)}`));
|
|
8586
8876
|
})
|
|
8587
8877
|
);
|
|
8588
8878
|
board.command("close <id>").description("Shorthand for `board move <id> done`").action(
|
|
8589
8879
|
action(async ({ ctx, args }) => {
|
|
8590
8880
|
const projectId = requireProject(ctx);
|
|
8591
8881
|
const row = await patchItem(ctx, projectId, String(args[0]), { status: "done" });
|
|
8592
|
-
ok(row, () => line(`Closed ${
|
|
8882
|
+
ok(row, () => line(`Closed ${import_picocolors30.default.bold(row.title)} ${statusTag(row.status)}`));
|
|
8593
8883
|
})
|
|
8594
8884
|
);
|
|
8595
8885
|
}
|
|
@@ -8622,23 +8912,23 @@ function assertPriority(value) {
|
|
|
8622
8912
|
}
|
|
8623
8913
|
}
|
|
8624
8914
|
function formatRow(r) {
|
|
8625
|
-
const labels = r.labels?.length ?
|
|
8626
|
-
const owner = r.ownerHuman ?
|
|
8627
|
-
return `${
|
|
8915
|
+
const labels = r.labels?.length ? import_picocolors30.default.dim(` [${r.labels.join(", ")}]`) : "";
|
|
8916
|
+
const owner = r.ownerHuman ? import_picocolors30.default.dim(` @${r.ownerHuman}`) : "";
|
|
8917
|
+
return `${import_picocolors30.default.dim(r.id)} ${statusTag(r.status)} ${r.title}${labels}${owner}`;
|
|
8628
8918
|
}
|
|
8629
8919
|
function statusTag(status) {
|
|
8630
8920
|
const label = status.padEnd(11);
|
|
8631
|
-
if (status === "done") return
|
|
8632
|
-
if (status === "in-progress") return
|
|
8633
|
-
if (status === "in-review") return
|
|
8634
|
-
return
|
|
8921
|
+
if (status === "done") return import_picocolors30.default.green(label);
|
|
8922
|
+
if (status === "in-progress") return import_picocolors30.default.yellow(label);
|
|
8923
|
+
if (status === "in-review") return import_picocolors30.default.cyan(label);
|
|
8924
|
+
return import_picocolors30.default.dim(label);
|
|
8635
8925
|
}
|
|
8636
8926
|
function collect2(value, previous) {
|
|
8637
8927
|
return [...previous, value];
|
|
8638
8928
|
}
|
|
8639
8929
|
|
|
8640
8930
|
// src/commands/task.ts
|
|
8641
|
-
var
|
|
8931
|
+
var import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
8642
8932
|
|
|
8643
8933
|
// src/subtask-attachments.ts
|
|
8644
8934
|
var MAX_REF_NOTE = 500;
|
|
@@ -8752,7 +9042,7 @@ function registerTask(program3) {
|
|
|
8752
9042
|
}) ?? [];
|
|
8753
9043
|
ok(rows, () => {
|
|
8754
9044
|
if (!rows.length) {
|
|
8755
|
-
line(
|
|
9045
|
+
line(import_picocolors31.default.dim("No tasks on the board yet."));
|
|
8756
9046
|
return;
|
|
8757
9047
|
}
|
|
8758
9048
|
for (const r of rows) line(formatRow2(r));
|
|
@@ -8861,10 +9151,10 @@ function registerTask(program3) {
|
|
|
8861
9151
|
};
|
|
8862
9152
|
ok(result, () => {
|
|
8863
9153
|
line(
|
|
8864
|
-
`${
|
|
9154
|
+
`${import_picocolors31.default.green("opened")} ${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.key ?? row.id)}`
|
|
8865
9155
|
);
|
|
8866
9156
|
if (channelMessage)
|
|
8867
|
-
line(
|
|
9157
|
+
line(import_picocolors31.default.dim("posted to the channel as Project Manager"));
|
|
8868
9158
|
if (channelMessageError) {
|
|
8869
9159
|
warn(
|
|
8870
9160
|
`Task opened, but its Project Manager card could not be posted: ${channelMessageError.message}`
|
|
@@ -8943,12 +9233,12 @@ function registerTask(program3) {
|
|
|
8943
9233
|
) : null;
|
|
8944
9234
|
ok(runner ?? row, () => {
|
|
8945
9235
|
line(
|
|
8946
|
-
`${
|
|
9236
|
+
`${import_picocolors31.default.green("added")} ${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.key ?? row.id)}`
|
|
8947
9237
|
);
|
|
8948
|
-
if (row.role) line(
|
|
9238
|
+
if (row.role) line(import_picocolors31.default.dim(`role: ${row.role}`));
|
|
8949
9239
|
if (runner) {
|
|
8950
9240
|
line(
|
|
8951
|
-
|
|
9241
|
+
import_picocolors31.default.dim(
|
|
8952
9242
|
`runs on: ${[opts.agent, opts.model, opts.effort].filter(Boolean).join(" \xB7 ")}`
|
|
8953
9243
|
)
|
|
8954
9244
|
);
|
|
@@ -8966,7 +9256,7 @@ function registerTask(program3) {
|
|
|
8966
9256
|
const rows = row.subtasks ?? [];
|
|
8967
9257
|
ok(rows, () => {
|
|
8968
9258
|
if (!rows.length) {
|
|
8969
|
-
line(
|
|
9259
|
+
line(import_picocolors31.default.dim("No subtasks yet."));
|
|
8970
9260
|
return;
|
|
8971
9261
|
}
|
|
8972
9262
|
rows.forEach((r, i) => line(formatSubtask(r, i + 1)));
|
|
@@ -9014,7 +9304,7 @@ function registerTask(program3) {
|
|
|
9014
9304
|
}
|
|
9015
9305
|
}
|
|
9016
9306
|
);
|
|
9017
|
-
ok(row, () => line(`${
|
|
9307
|
+
ok(row, () => line(`${import_picocolors31.default.green("updated")} ${import_picocolors31.default.bold(row.title)}`));
|
|
9018
9308
|
})
|
|
9019
9309
|
);
|
|
9020
9310
|
subtask.command("remove <id>").description("Remove a subtask (only before the work starts)").action(
|
|
@@ -9022,7 +9312,7 @@ function registerTask(program3) {
|
|
|
9022
9312
|
await api(ctx, `/v1/project-tasks/${encodeURIComponent(args[0])}`, {
|
|
9023
9313
|
method: "DELETE"
|
|
9024
9314
|
});
|
|
9025
|
-
ok({ removed: args[0] }, () => line(
|
|
9315
|
+
ok({ removed: args[0] }, () => line(import_picocolors31.default.green("removed")));
|
|
9026
9316
|
})
|
|
9027
9317
|
);
|
|
9028
9318
|
task.command("move <id> <status>").description(
|
|
@@ -9037,7 +9327,7 @@ function registerTask(program3) {
|
|
|
9037
9327
|
);
|
|
9038
9328
|
ok(
|
|
9039
9329
|
row,
|
|
9040
|
-
() => line(`${
|
|
9330
|
+
() => line(`${import_picocolors31.default.green("moved")} ${import_picocolors31.default.bold(row.title)} \u2192 ${args[1]}`)
|
|
9041
9331
|
);
|
|
9042
9332
|
})
|
|
9043
9333
|
);
|
|
@@ -9053,18 +9343,18 @@ function registerTask(program3) {
|
|
|
9053
9343
|
);
|
|
9054
9344
|
ok(row, () => {
|
|
9055
9345
|
if (!row?.queued) {
|
|
9056
|
-
line(
|
|
9346
|
+
line(import_picocolors31.default.yellow("could not resume it \u2014 check the step id"));
|
|
9057
9347
|
return;
|
|
9058
9348
|
}
|
|
9059
9349
|
const started = row.started ?? 0;
|
|
9060
9350
|
if (started > 0) {
|
|
9061
9351
|
line(
|
|
9062
|
-
`${
|
|
9352
|
+
`${import_picocolors31.default.green("resumed")} \u2014 ${started} step${started === 1 ? "" : "s"} started`
|
|
9063
9353
|
);
|
|
9064
9354
|
return;
|
|
9065
9355
|
}
|
|
9066
9356
|
line(
|
|
9067
|
-
`${
|
|
9357
|
+
`${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.`
|
|
9068
9358
|
);
|
|
9069
9359
|
});
|
|
9070
9360
|
})
|
|
@@ -9078,11 +9368,11 @@ function registerTask(program3) {
|
|
|
9078
9368
|
);
|
|
9079
9369
|
ok(row, () => {
|
|
9080
9370
|
if (row?.reopened) {
|
|
9081
|
-
line(`${
|
|
9371
|
+
line(`${import_picocolors31.default.green("sent back")} \u2014 it will be picked up again`);
|
|
9082
9372
|
return;
|
|
9083
9373
|
}
|
|
9084
9374
|
line(
|
|
9085
|
-
|
|
9375
|
+
import_picocolors31.default.yellow(
|
|
9086
9376
|
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"
|
|
9087
9377
|
)
|
|
9088
9378
|
);
|
|
@@ -9099,7 +9389,7 @@ function registerTask(program3) {
|
|
|
9099
9389
|
`/v1/project-tasks/${encodeURIComponent(id)}/dispatch-check`,
|
|
9100
9390
|
{ method: "POST" }
|
|
9101
9391
|
);
|
|
9102
|
-
ok(row, () => line(
|
|
9392
|
+
ok(row, () => line(import_picocolors31.default.green("approved \u2014 you may start")));
|
|
9103
9393
|
})
|
|
9104
9394
|
);
|
|
9105
9395
|
task.command("start [id]").description(
|
|
@@ -9114,13 +9404,13 @@ function registerTask(program3) {
|
|
|
9114
9404
|
const started = row?.started ?? null;
|
|
9115
9405
|
if (started && started > 0) {
|
|
9116
9406
|
line(
|
|
9117
|
-
|
|
9407
|
+
import_picocolors31.default.green(
|
|
9118
9408
|
`started ${started} step${started === 1 ? "" : "s"} \u2014 they are running now`
|
|
9119
9409
|
)
|
|
9120
9410
|
);
|
|
9121
9411
|
return;
|
|
9122
9412
|
}
|
|
9123
|
-
line(
|
|
9413
|
+
line(import_picocolors31.default.yellow(row?.note ?? "Nothing started."));
|
|
9124
9414
|
});
|
|
9125
9415
|
})
|
|
9126
9416
|
);
|
|
@@ -9135,7 +9425,7 @@ function registerTask(program3) {
|
|
|
9135
9425
|
);
|
|
9136
9426
|
ok({ awaiting: row2.approval_state === "awaiting", task: row2 }, () => {
|
|
9137
9427
|
line(
|
|
9138
|
-
row2.approval_state === "awaiting" ?
|
|
9428
|
+
row2.approval_state === "awaiting" ? import_picocolors31.default.yellow(
|
|
9139
9429
|
"The plan is waiting on the owner. They see it in the task."
|
|
9140
9430
|
) : `Already ${row2.approval_state}.`
|
|
9141
9431
|
);
|
|
@@ -9160,7 +9450,7 @@ function registerTask(program3) {
|
|
|
9160
9450
|
);
|
|
9161
9451
|
ok(
|
|
9162
9452
|
row,
|
|
9163
|
-
() => line(`${
|
|
9453
|
+
() => line(`${import_picocolors31.default.green(row.approval_state)} ${import_picocolors31.default.bold(row.title)}`)
|
|
9164
9454
|
);
|
|
9165
9455
|
})
|
|
9166
9456
|
);
|
|
@@ -9176,7 +9466,7 @@ function registerTask(program3) {
|
|
|
9176
9466
|
`/v1/project-tasks/${encodeURIComponent(id)}/move`,
|
|
9177
9467
|
{ body: { status: "ready" } }
|
|
9178
9468
|
);
|
|
9179
|
-
ok(row, () => line(`${
|
|
9469
|
+
ok(row, () => line(`${import_picocolors31.default.green("ready")} ${import_picocolors31.default.bold(row.title)}`));
|
|
9180
9470
|
})
|
|
9181
9471
|
);
|
|
9182
9472
|
}
|
|
@@ -9221,24 +9511,24 @@ function assertOneOf(flag, value, allowed) {
|
|
|
9221
9511
|
}
|
|
9222
9512
|
}
|
|
9223
9513
|
function formatRow2(r) {
|
|
9224
|
-
const key =
|
|
9225
|
-
const steps = r.subtaskTotal ?
|
|
9226
|
-
const gate = r.approval_state === "awaiting" ?
|
|
9514
|
+
const key = import_picocolors31.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
|
|
9515
|
+
const steps = r.subtaskTotal ? import_picocolors31.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
|
|
9516
|
+
const gate = r.approval_state === "awaiting" ? import_picocolors31.default.yellow(" awaiting approval") : "";
|
|
9227
9517
|
return `${key} ${statusTag2(r.status)} ${r.title}${steps}${gate}`;
|
|
9228
9518
|
}
|
|
9229
9519
|
function formatSubtask(r, index) {
|
|
9230
|
-
const n =
|
|
9231
|
-
const role = r.role ?
|
|
9232
|
-
const scope = r.scope_paths?.length ?
|
|
9520
|
+
const n = import_picocolors31.default.dim(String(index).padStart(2, "0"));
|
|
9521
|
+
const role = r.role ? import_picocolors31.default.dim(` [${r.role}]`) : "";
|
|
9522
|
+
const scope = r.scope_paths?.length ? import_picocolors31.default.dim(` owns: ${r.scope_paths.join(", ")}`) : "";
|
|
9233
9523
|
const head = `${n} ${statusTag2(r.status)} ${r.title}${role}${scope}`;
|
|
9234
9524
|
const summary = (r.result_summary ?? "").trim();
|
|
9235
9525
|
if (!summary) return head;
|
|
9236
9526
|
const wrapped = summary.split("\n").map((l) => ` ${l}`).join("\n");
|
|
9237
9527
|
return `${head}
|
|
9238
|
-
${
|
|
9528
|
+
${import_picocolors31.default.dim(wrapped)}`;
|
|
9239
9529
|
}
|
|
9240
9530
|
function printTask(row, goal) {
|
|
9241
|
-
line(`${
|
|
9531
|
+
line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.key ?? row.id)}`);
|
|
9242
9532
|
line(`${statusTag2(row.status)} approval: ${row.approval_state}`);
|
|
9243
9533
|
if (row.summary) line(`
|
|
9244
9534
|
${row.summary}`);
|
|
@@ -9251,53 +9541,53 @@ touches: ${row.targets.map((t) => t.appName ?? t.ref ?? t.kind).join(", ")}`
|
|
|
9251
9541
|
}
|
|
9252
9542
|
if (row.subtasks?.length) {
|
|
9253
9543
|
line(`
|
|
9254
|
-
${
|
|
9544
|
+
${import_picocolors31.default.bold("subtasks")}`);
|
|
9255
9545
|
row.subtasks.forEach((s, i) => line(formatSubtask(s, i + 1)));
|
|
9256
9546
|
line(
|
|
9257
|
-
|
|
9547
|
+
import_picocolors31.default.dim(
|
|
9258
9548
|
`
|
|
9259
9549
|
Run \`workser artifact list\` to see what these subtasks produced,`
|
|
9260
9550
|
)
|
|
9261
9551
|
);
|
|
9262
9552
|
line(
|
|
9263
|
-
|
|
9553
|
+
import_picocolors31.default.dim(
|
|
9264
9554
|
`or \`workser artifact list --step <id>\` for one subtask's output alone.`
|
|
9265
9555
|
)
|
|
9266
9556
|
);
|
|
9267
9557
|
} else {
|
|
9268
|
-
line(
|
|
9558
|
+
line(import_picocolors31.default.dim("\nNo subtasks yet."));
|
|
9269
9559
|
}
|
|
9270
9560
|
}
|
|
9271
9561
|
function printGoalContext(row, goal) {
|
|
9272
9562
|
const mine = row.phase ?? null;
|
|
9273
9563
|
line(`
|
|
9274
|
-
${
|
|
9275
|
-
if (goal.outcome) line(
|
|
9564
|
+
${import_picocolors31.default.bold("part of")}: ${goal.title}`);
|
|
9565
|
+
if (goal.outcome) line(import_picocolors31.default.dim(`done means: ${goal.outcome}`));
|
|
9276
9566
|
const progress = goal.progress ?? [];
|
|
9277
9567
|
for (const p of progress) {
|
|
9278
9568
|
const where = p.total === 0 ? "not started" : `${p.done} of ${p.total} done`;
|
|
9279
|
-
const here = mine && p.name === mine ?
|
|
9280
|
-
const mark = p.state === "done" ?
|
|
9569
|
+
const here = mine && p.name === mine ? import_picocolors31.default.cyan(" <- this task") : "";
|
|
9570
|
+
const mark = p.state === "done" ? import_picocolors31.default.green("*") : import_picocolors31.default.dim("-");
|
|
9281
9571
|
line(` ${mark} ${p.name} \u2014 ${where}${here}`);
|
|
9282
9572
|
}
|
|
9283
9573
|
const next = progress.find((p) => p.state !== "done");
|
|
9284
9574
|
const running = progress.some((p) => p.state === "working");
|
|
9285
9575
|
if (next && !running) {
|
|
9286
9576
|
line(
|
|
9287
|
-
|
|
9577
|
+
import_picocolors31.default.dim(
|
|
9288
9578
|
`
|
|
9289
9579
|
Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to them in a sentence rather than starting it unasked.`
|
|
9290
9580
|
)
|
|
9291
9581
|
);
|
|
9292
9582
|
} else if (!next) {
|
|
9293
9583
|
line(
|
|
9294
|
-
|
|
9584
|
+
import_picocolors31.default.dim(
|
|
9295
9585
|
"\nEvery part of this plan is done. Say so, and offer to wrap it up."
|
|
9296
9586
|
)
|
|
9297
9587
|
);
|
|
9298
9588
|
}
|
|
9299
9589
|
line(
|
|
9300
|
-
|
|
9590
|
+
import_picocolors31.default.dim(
|
|
9301
9591
|
"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."
|
|
9302
9592
|
)
|
|
9303
9593
|
);
|
|
@@ -9305,22 +9595,22 @@ Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to t
|
|
|
9305
9595
|
function statusTag2(status) {
|
|
9306
9596
|
switch (status) {
|
|
9307
9597
|
case "ready":
|
|
9308
|
-
return
|
|
9598
|
+
return import_picocolors31.default.green("[ready]");
|
|
9309
9599
|
case "working":
|
|
9310
|
-
return
|
|
9600
|
+
return import_picocolors31.default.blue("[working]");
|
|
9311
9601
|
case "checking":
|
|
9312
|
-
return
|
|
9602
|
+
return import_picocolors31.default.cyan("[checking]");
|
|
9313
9603
|
case "accepted":
|
|
9314
|
-
return
|
|
9604
|
+
return import_picocolors31.default.green("[accepted]");
|
|
9315
9605
|
case "archived":
|
|
9316
|
-
return
|
|
9606
|
+
return import_picocolors31.default.dim("[archived]");
|
|
9317
9607
|
default:
|
|
9318
|
-
return
|
|
9608
|
+
return import_picocolors31.default.dim("[todo]");
|
|
9319
9609
|
}
|
|
9320
9610
|
}
|
|
9321
9611
|
|
|
9322
9612
|
// src/commands/goal.ts
|
|
9323
|
-
var
|
|
9613
|
+
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
9324
9614
|
var STATUSES3 = ["proposed", "agreed", "working", "delivered", "abandoned"];
|
|
9325
9615
|
function registerGoal(program3) {
|
|
9326
9616
|
const goal = program3.command("goal").description("Business goals and the phases that deliver them");
|
|
@@ -9332,7 +9622,7 @@ function registerGoal(program3) {
|
|
|
9332
9622
|
}) ?? [];
|
|
9333
9623
|
ok(rows, () => {
|
|
9334
9624
|
if (!rows.length) {
|
|
9335
|
-
line(
|
|
9625
|
+
line(import_picocolors32.default.dim("No goals yet \u2014 every task here stands on its own."));
|
|
9336
9626
|
return;
|
|
9337
9627
|
}
|
|
9338
9628
|
for (const g of rows) line(formatGoal(g));
|
|
@@ -9409,10 +9699,10 @@ function registerGoal(program3) {
|
|
|
9409
9699
|
}
|
|
9410
9700
|
});
|
|
9411
9701
|
ok(row, () => {
|
|
9412
|
-
success(`Proposed ${
|
|
9702
|
+
success(`Proposed ${import_picocolors32.default.bold(row?.title ?? "goal")}`);
|
|
9413
9703
|
printGoal(row);
|
|
9414
9704
|
line(
|
|
9415
|
-
|
|
9705
|
+
import_picocolors32.default.dim(
|
|
9416
9706
|
"\nNothing has been created yet. The owner agrees the shape first."
|
|
9417
9707
|
)
|
|
9418
9708
|
);
|
|
@@ -9441,7 +9731,7 @@ function registerGoal(program3) {
|
|
|
9441
9731
|
ok(
|
|
9442
9732
|
row,
|
|
9443
9733
|
() => line(
|
|
9444
|
-
row?.recorded ? met === true ?
|
|
9734
|
+
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(
|
|
9445
9735
|
"couldn't record it \u2014 check the goal id, the phase name and the criterion id"
|
|
9446
9736
|
)
|
|
9447
9737
|
)
|
|
@@ -9484,7 +9774,7 @@ function registerGoal(program3) {
|
|
|
9484
9774
|
}
|
|
9485
9775
|
ok({ goalId, phase, filed }, () => {
|
|
9486
9776
|
success(
|
|
9487
|
-
`Filed ${filed.length} ${filed.length === 1 ? "task" : "tasks"} under ${
|
|
9777
|
+
`Filed ${filed.length} ${filed.length === 1 ? "task" : "tasks"} under ${import_picocolors32.default.bold(phase)}`
|
|
9488
9778
|
);
|
|
9489
9779
|
});
|
|
9490
9780
|
})
|
|
@@ -9516,42 +9806,42 @@ function registerGoal(program3) {
|
|
|
9516
9806
|
function appScope(g) {
|
|
9517
9807
|
const n = g.appIds?.length ?? 0;
|
|
9518
9808
|
if (!n) return "";
|
|
9519
|
-
return
|
|
9809
|
+
return import_picocolors32.default.dim(` ${n} part${n === 1 ? "" : "s"} of the system`);
|
|
9520
9810
|
}
|
|
9521
9811
|
function formatGoal(g) {
|
|
9522
|
-
const where = g.currentPhase && g.status !== "delivered" ?
|
|
9523
|
-
const count = g.taskTotal != null ?
|
|
9524
|
-
return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${
|
|
9812
|
+
const where = g.currentPhase && g.status !== "delivered" ? import_picocolors32.default.dim(` now: ${g.currentPhase}`) : "";
|
|
9813
|
+
const count = g.taskTotal != null ? import_picocolors32.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
|
|
9814
|
+
return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${import_picocolors32.default.dim(g.id)}`;
|
|
9525
9815
|
}
|
|
9526
9816
|
function printGoal(g) {
|
|
9527
9817
|
if (!g) return;
|
|
9528
|
-
line(`${
|
|
9818
|
+
line(`${import_picocolors32.default.bold(g.title)} ${import_picocolors32.default.dim(g.id)}`);
|
|
9529
9819
|
line(statusTag3(g.status));
|
|
9530
9820
|
if (g.outcome) line(`
|
|
9531
9821
|
done means: ${g.outcome}`);
|
|
9532
9822
|
const progress = g.progress ?? [];
|
|
9533
9823
|
if (!progress.length) {
|
|
9534
|
-
line(
|
|
9824
|
+
line(import_picocolors32.default.dim("\nNo phases agreed yet."));
|
|
9535
9825
|
return;
|
|
9536
9826
|
}
|
|
9537
9827
|
line(`
|
|
9538
|
-
${
|
|
9828
|
+
${import_picocolors32.default.bold("phases")}`);
|
|
9539
9829
|
for (const p of progress) {
|
|
9540
|
-
const bar2 = p.total > 0 ? `${p.done}/${p.total} done` :
|
|
9541
|
-
const mark = p.state === "done" ?
|
|
9830
|
+
const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors32.default.dim("nothing filed yet");
|
|
9831
|
+
const mark = p.state === "done" ? import_picocolors32.default.green("done") : p.state === "working" ? import_picocolors32.default.blue("working") : import_picocolors32.default.dim("waiting");
|
|
9542
9832
|
line(
|
|
9543
|
-
` ${
|
|
9833
|
+
` ${import_picocolors32.default.dim(String(p.index).padStart(2, "0"))} ${p.name} ${mark} ${import_picocolors32.default.dim(bar2)}`
|
|
9544
9834
|
);
|
|
9545
9835
|
for (const c of p.criteria ?? []) {
|
|
9546
|
-
const tick = c.met === true ?
|
|
9547
|
-
line(` ${tick} ${c.text} ${
|
|
9548
|
-
if (c.note) line(
|
|
9836
|
+
const tick = c.met === true ? import_picocolors32.default.green("\u2713") : c.met === false ? import_picocolors32.default.red("\u2717") : import_picocolors32.default.dim("\xB7");
|
|
9837
|
+
line(` ${tick} ${c.text} ${import_picocolors32.default.dim(c.id)}`);
|
|
9838
|
+
if (c.note) line(import_picocolors32.default.dim(` ${c.note}`));
|
|
9549
9839
|
}
|
|
9550
9840
|
}
|
|
9551
9841
|
const current = progress.find((p) => p.name === g.currentPhase);
|
|
9552
9842
|
if (current) {
|
|
9553
9843
|
line(
|
|
9554
|
-
|
|
9844
|
+
import_picocolors32.default.dim(
|
|
9555
9845
|
`
|
|
9556
9846
|
${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current.index} of ${progress.length}).`
|
|
9557
9847
|
)
|
|
@@ -9561,15 +9851,15 @@ ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current
|
|
|
9561
9851
|
function statusTag3(status) {
|
|
9562
9852
|
switch (status) {
|
|
9563
9853
|
case "agreed":
|
|
9564
|
-
return
|
|
9854
|
+
return import_picocolors32.default.cyan("[agreed]");
|
|
9565
9855
|
case "working":
|
|
9566
|
-
return
|
|
9856
|
+
return import_picocolors32.default.blue("[working]");
|
|
9567
9857
|
case "delivered":
|
|
9568
|
-
return
|
|
9858
|
+
return import_picocolors32.default.green("[delivered]");
|
|
9569
9859
|
case "abandoned":
|
|
9570
|
-
return
|
|
9860
|
+
return import_picocolors32.default.dim("[abandoned]");
|
|
9571
9861
|
default:
|
|
9572
|
-
return
|
|
9862
|
+
return import_picocolors32.default.yellow("[proposed]");
|
|
9573
9863
|
}
|
|
9574
9864
|
}
|
|
9575
9865
|
|
|
@@ -9622,7 +9912,15 @@ var READS = [
|
|
|
9622
9912
|
// have `create` subcommands — these write the project's RECORD, not the
|
|
9623
9913
|
// project. What stops a reviewer editing code is its filesystem mode, and
|
|
9624
9914
|
// that is untouched.
|
|
9625
|
-
"artifact"
|
|
9915
|
+
"artifact",
|
|
9916
|
+
// LEAVING A FACT FOR THE TEAM IS NOT CHANGING THE PROJECT — the same
|
|
9917
|
+
// argument as `artifact` directly above, and it belongs in READS rather than
|
|
9918
|
+
// BUILDS on purpose. The roles that DISCOVER things are the reading ones: a
|
|
9919
|
+
// tester that found the real cause, an analyst that found the actual column
|
|
9920
|
+
// name, a security engineer that found where a key is read from. A shared
|
|
9921
|
+
// memory only builders could write to would be missing most of what is worth
|
|
9922
|
+
// sharing. See the daemon's `team-memory.ts`.
|
|
9923
|
+
"note"
|
|
9626
9924
|
];
|
|
9627
9925
|
var BUILDS = [
|
|
9628
9926
|
...READS,
|
|
@@ -9642,6 +9940,7 @@ var BUILDS = [
|
|
|
9642
9940
|
];
|
|
9643
9941
|
var ROLE_VERBS = {
|
|
9644
9942
|
pm: [...READS, "ask", "app"],
|
|
9943
|
+
// `note` reaches this via READS.
|
|
9645
9944
|
architect: [...BUILDS, "versions"],
|
|
9646
9945
|
web: BUILDS,
|
|
9647
9946
|
api: BUILDS,
|
|
@@ -9744,7 +10043,7 @@ function stripLeadingGlobalOptions(argv) {
|
|
|
9744
10043
|
}
|
|
9745
10044
|
|
|
9746
10045
|
// src/commands/decision.ts
|
|
9747
|
-
var
|
|
10046
|
+
var import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
9748
10047
|
function registerDecision(program3) {
|
|
9749
10048
|
const decision = program3.command("decision").description("Read and record the project's architecture decisions");
|
|
9750
10049
|
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(
|
|
@@ -9757,11 +10056,11 @@ function registerDecision(program3) {
|
|
|
9757
10056
|
rows = applyLimit(rows, opts.limit);
|
|
9758
10057
|
ok(rows, () => {
|
|
9759
10058
|
if (!rows.length) {
|
|
9760
|
-
line(
|
|
10059
|
+
line(import_picocolors33.default.dim("No decisions recorded yet."));
|
|
9761
10060
|
return;
|
|
9762
10061
|
}
|
|
9763
10062
|
for (const r of rows) {
|
|
9764
|
-
line(`${
|
|
10063
|
+
line(`${import_picocolors33.default.dim(r.id)} ${import_picocolors33.default.dim(shortDate(r.createdAt))} ${r.title}`);
|
|
9765
10064
|
line(` ${truncate(r.decision, 100)}`);
|
|
9766
10065
|
}
|
|
9767
10066
|
});
|
|
@@ -9775,16 +10074,16 @@ function registerDecision(program3) {
|
|
|
9775
10074
|
`/v1/projects/${projectId}/architecture-decisions/${args[0]}`
|
|
9776
10075
|
);
|
|
9777
10076
|
ok(row, () => {
|
|
9778
|
-
line(`${
|
|
9779
|
-
line(
|
|
10077
|
+
line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
|
|
10078
|
+
line(import_picocolors33.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
|
|
9780
10079
|
line(`
|
|
9781
|
-
${
|
|
10080
|
+
${import_picocolors33.default.bold("Context")}
|
|
9782
10081
|
${row.context}`);
|
|
9783
10082
|
line(`
|
|
9784
|
-
${
|
|
10083
|
+
${import_picocolors33.default.bold("Decision")}
|
|
9785
10084
|
${row.decision}`);
|
|
9786
10085
|
if (row.consequences) line(`
|
|
9787
|
-
${
|
|
10086
|
+
${import_picocolors33.default.bold("Consequences")}
|
|
9788
10087
|
${row.consequences}`);
|
|
9789
10088
|
});
|
|
9790
10089
|
})
|
|
@@ -9813,7 +10112,7 @@ ${row.consequences}`);
|
|
|
9813
10112
|
refId: row?.id,
|
|
9814
10113
|
output: { decision: row }
|
|
9815
10114
|
});
|
|
9816
|
-
ok(row, () => line(`Recorded decision ${
|
|
10115
|
+
ok(row, () => line(`Recorded decision ${import_picocolors33.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
9817
10116
|
})
|
|
9818
10117
|
);
|
|
9819
10118
|
const requirement = program3.command("requirement").description("Read and record the project's requirements");
|
|
@@ -9825,11 +10124,11 @@ ${row.consequences}`);
|
|
|
9825
10124
|
rows = applyLimit(rows, opts.limit);
|
|
9826
10125
|
ok(rows, () => {
|
|
9827
10126
|
if (!rows.length) {
|
|
9828
|
-
line(
|
|
10127
|
+
line(import_picocolors33.default.dim("No requirements recorded yet."));
|
|
9829
10128
|
return;
|
|
9830
10129
|
}
|
|
9831
10130
|
for (const r of rows) {
|
|
9832
|
-
line(`${
|
|
10131
|
+
line(`${import_picocolors33.default.dim(r.id)} ${r.status.padEnd(9)} ${r.title}`);
|
|
9833
10132
|
}
|
|
9834
10133
|
});
|
|
9835
10134
|
})
|
|
@@ -9842,8 +10141,8 @@ ${row.consequences}`);
|
|
|
9842
10141
|
`/v1/projects/${projectId}/requirements/${args[0]}`
|
|
9843
10142
|
);
|
|
9844
10143
|
ok(row, () => {
|
|
9845
|
-
line(`${
|
|
9846
|
-
line(
|
|
10144
|
+
line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
|
|
10145
|
+
line(import_picocolors33.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
|
|
9847
10146
|
line(`
|
|
9848
10147
|
${row.body}`);
|
|
9849
10148
|
});
|
|
@@ -9869,7 +10168,7 @@ ${row.body}`);
|
|
|
9869
10168
|
refId: row?.id,
|
|
9870
10169
|
output: { requirement: row }
|
|
9871
10170
|
});
|
|
9872
|
-
ok(row, () => line(`Recorded requirement ${
|
|
10171
|
+
ok(row, () => line(`Recorded requirement ${import_picocolors33.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
9873
10172
|
})
|
|
9874
10173
|
);
|
|
9875
10174
|
requirement.command("update <id>").description(
|
|
@@ -9898,7 +10197,7 @@ ${row.body}`);
|
|
|
9898
10197
|
code: "bad_request"
|
|
9899
10198
|
});
|
|
9900
10199
|
}
|
|
9901
|
-
ok(row, () => line(`Updated requirement ${
|
|
10200
|
+
ok(row, () => line(`Updated requirement ${import_picocolors33.default.bold(row.id)} \u2014 ${row.title} (${row.status})`));
|
|
9902
10201
|
})
|
|
9903
10202
|
);
|
|
9904
10203
|
}
|
|
@@ -9921,7 +10220,7 @@ function shortDate(iso) {
|
|
|
9921
10220
|
}
|
|
9922
10221
|
|
|
9923
10222
|
// src/commands/doc.ts
|
|
9924
|
-
var
|
|
10223
|
+
var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
9925
10224
|
|
|
9926
10225
|
// src/mermaid-fences.ts
|
|
9927
10226
|
function hasDiagram(code) {
|
|
@@ -9966,13 +10265,13 @@ function registerDoc(program3) {
|
|
|
9966
10265
|
}) ?? [];
|
|
9967
10266
|
ok(rows, () => {
|
|
9968
10267
|
if (!rows.length) {
|
|
9969
|
-
line(
|
|
10268
|
+
line(import_picocolors34.default.dim("No documents yet."));
|
|
9970
10269
|
return;
|
|
9971
10270
|
}
|
|
9972
10271
|
for (const r of rows) {
|
|
9973
|
-
const link = r.workItemId ?
|
|
9974
|
-
const file = r.filePath ?
|
|
9975
|
-
line(`${
|
|
10272
|
+
const link = r.workItemId ? import_picocolors34.default.dim(` \u21B3 ${r.workItemId}`) : "";
|
|
10273
|
+
const file = r.filePath ? import_picocolors34.default.dim(` ${r.filePath}`) : "";
|
|
10274
|
+
line(`${import_picocolors34.default.dim(r.id)} ${r.title}${link}${file}`);
|
|
9976
10275
|
}
|
|
9977
10276
|
});
|
|
9978
10277
|
})
|
|
@@ -9986,17 +10285,17 @@ function registerDoc(program3) {
|
|
|
9986
10285
|
);
|
|
9987
10286
|
if (opts.markdown) {
|
|
9988
10287
|
ok({ id: row.id, title: row.title, filePath: row.filePath }, () => {
|
|
9989
|
-
line(`${
|
|
10288
|
+
line(`${import_picocolors34.default.bold(row.title)} ${import_picocolors34.default.dim(row.id)}`);
|
|
9990
10289
|
line(
|
|
9991
|
-
row.filePath ? `Read it at ${
|
|
10290
|
+
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.")
|
|
9992
10291
|
);
|
|
9993
10292
|
});
|
|
9994
10293
|
return;
|
|
9995
10294
|
}
|
|
9996
10295
|
ok(row, () => {
|
|
9997
|
-
line(`${
|
|
9998
|
-
if (row.workItemId) line(
|
|
9999
|
-
if (row.filePath) line(
|
|
10296
|
+
line(`${import_picocolors34.default.bold(row.title)} ${import_picocolors34.default.dim(row.id)}`);
|
|
10297
|
+
if (row.workItemId) line(import_picocolors34.default.dim(`linked to work item ${row.workItemId}`));
|
|
10298
|
+
if (row.filePath) line(import_picocolors34.default.dim(`markdown mirror: ${row.filePath}`));
|
|
10000
10299
|
line("");
|
|
10001
10300
|
line(row.contentJson);
|
|
10002
10301
|
});
|
|
@@ -10025,7 +10324,7 @@ function registerDoc(program3) {
|
|
|
10025
10324
|
refId: row?.id,
|
|
10026
10325
|
output: { document: row }
|
|
10027
10326
|
});
|
|
10028
|
-
ok(row, () => line(`Created document ${
|
|
10327
|
+
ok(row, () => line(`Created document ${import_picocolors34.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
10029
10328
|
})
|
|
10030
10329
|
);
|
|
10031
10330
|
doc.command("diagram <id>").description(
|
|
@@ -10051,19 +10350,19 @@ function registerDoc(program3) {
|
|
|
10051
10350
|
diagrams: diagrams.map((code) => ({ kind: diagramKind(code), code }))
|
|
10052
10351
|
};
|
|
10053
10352
|
ok(payload, () => {
|
|
10054
|
-
line(`${
|
|
10353
|
+
line(`${import_picocolors34.default.bold(row.title)} ${import_picocolors34.default.dim(row.id)}`);
|
|
10055
10354
|
if (markdown === null) {
|
|
10056
10355
|
line(
|
|
10057
|
-
|
|
10356
|
+
import_picocolors34.default.dim(
|
|
10058
10357
|
row.filePath ? `Could not read ${row.filePath} from this folder.` : "This document has no markdown mirror on disk yet."
|
|
10059
10358
|
)
|
|
10060
10359
|
);
|
|
10061
10360
|
} else if (!diagrams.length) {
|
|
10062
|
-
line(
|
|
10361
|
+
line(import_picocolors34.default.dim("No diagrams in this document."));
|
|
10063
10362
|
} else {
|
|
10064
10363
|
for (const [i, code] of diagrams.entries()) {
|
|
10065
10364
|
const kind = diagramKind(code) ?? "diagram";
|
|
10066
|
-
line(`${
|
|
10365
|
+
line(`${import_picocolors34.default.dim(String(i + 1))} ${kind} ${import_picocolors34.default.dim(`${code.split("\n").length} lines`)}`);
|
|
10067
10366
|
}
|
|
10068
10367
|
}
|
|
10069
10368
|
});
|
|
@@ -10099,7 +10398,7 @@ function registerDoc(program3) {
|
|
|
10099
10398
|
code: "bad_request"
|
|
10100
10399
|
});
|
|
10101
10400
|
}
|
|
10102
|
-
ok(row, () => line(`Updated document ${
|
|
10401
|
+
ok(row, () => line(`Updated document ${import_picocolors34.default.bold(row.id)} \u2014 ${row.title}`));
|
|
10103
10402
|
})
|
|
10104
10403
|
);
|
|
10105
10404
|
}
|
|
@@ -10113,7 +10412,7 @@ function readMirror(cwd, filePath) {
|
|
|
10113
10412
|
}
|
|
10114
10413
|
|
|
10115
10414
|
// src/commands/design.ts
|
|
10116
|
-
var
|
|
10415
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
10117
10416
|
function registerDesign(program3) {
|
|
10118
10417
|
const design = program3.command("design").description("Read the project's brand (colours, fonts, logo)");
|
|
10119
10418
|
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(
|
|
@@ -10127,11 +10426,11 @@ function registerDesign(program3) {
|
|
|
10127
10426
|
if (opts.raw) {
|
|
10128
10427
|
ok(files, () => {
|
|
10129
10428
|
if (!files.length) {
|
|
10130
|
-
line(
|
|
10429
|
+
line(import_picocolors35.default.dim("No brand set for this project."));
|
|
10131
10430
|
return;
|
|
10132
10431
|
}
|
|
10133
10432
|
for (const f of files) {
|
|
10134
|
-
line(
|
|
10433
|
+
line(import_picocolors35.default.bold(f.path));
|
|
10135
10434
|
line(f.contents);
|
|
10136
10435
|
line("");
|
|
10137
10436
|
}
|
|
@@ -10148,21 +10447,21 @@ function registerDesign(program3) {
|
|
|
10148
10447
|
} : { hasBrand: false, colors: {}, fonts: {}, brand: {}, files: [] };
|
|
10149
10448
|
ok(summary, () => {
|
|
10150
10449
|
if (!tokens) {
|
|
10151
|
-
line(
|
|
10450
|
+
line(import_picocolors35.default.dim("No brand set for this project \u2014 choose sensible styling yourself."));
|
|
10152
10451
|
return;
|
|
10153
10452
|
}
|
|
10154
10453
|
for (const [name, value] of Object.entries(tokens.brand)) {
|
|
10155
|
-
line(`${
|
|
10454
|
+
line(`${import_picocolors35.default.dim(name.padEnd(12))} ${value}`);
|
|
10156
10455
|
}
|
|
10157
10456
|
for (const [name, value] of Object.entries(tokens.color)) {
|
|
10158
|
-
line(`${
|
|
10457
|
+
line(`${import_picocolors35.default.dim(`color.${name}`.padEnd(12))} ${value}`);
|
|
10159
10458
|
}
|
|
10160
10459
|
for (const [name, value] of Object.entries(tokens.font)) {
|
|
10161
|
-
line(`${
|
|
10460
|
+
line(`${import_picocolors35.default.dim(`font.${name}`.padEnd(12))} ${value}`);
|
|
10162
10461
|
}
|
|
10163
10462
|
line("");
|
|
10164
10463
|
line(
|
|
10165
|
-
|
|
10464
|
+
import_picocolors35.default.dim(
|
|
10166
10465
|
`Generated into the working tree as ${files.map((f) => f.path).join(", ")} \u2014 wire those in, never edit them.`
|
|
10167
10466
|
)
|
|
10168
10467
|
);
|
|
@@ -10193,7 +10492,7 @@ function unwrap(group) {
|
|
|
10193
10492
|
}
|
|
10194
10493
|
|
|
10195
10494
|
// src/commands/api.ts
|
|
10196
|
-
var
|
|
10495
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
10197
10496
|
import { readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
10198
10497
|
import { join as join3, relative, sep } from "path";
|
|
10199
10498
|
|
|
@@ -10307,10 +10606,10 @@ function registerApi(program3) {
|
|
|
10307
10606
|
const appId = requireApp2(opts.app);
|
|
10308
10607
|
const res = await api(ctx, `/v1/apps/${encodeURIComponent(appId)}/api/requests`);
|
|
10309
10608
|
ok(res, () => {
|
|
10310
|
-
for (const note of res?.notes ?? []) line(
|
|
10609
|
+
for (const note of res?.notes ?? []) line(import_picocolors36.default.dim(note));
|
|
10311
10610
|
for (const r of res?.requests ?? []) {
|
|
10312
10611
|
line(
|
|
10313
|
-
`${
|
|
10612
|
+
`${import_picocolors36.default.dim(r.method.padEnd(6))}${r.path}${r.note ? import_picocolors36.default.dim(` ${r.note}`) : ""}`
|
|
10314
10613
|
);
|
|
10315
10614
|
}
|
|
10316
10615
|
});
|
|
@@ -10344,14 +10643,14 @@ function registerApi(program3) {
|
|
|
10344
10643
|
);
|
|
10345
10644
|
ok(res, () => {
|
|
10346
10645
|
if (!res?.ok) {
|
|
10347
|
-
line(
|
|
10646
|
+
line(import_picocolors36.default.red(res?.error ?? "The service did not answer."));
|
|
10348
10647
|
return;
|
|
10349
10648
|
}
|
|
10350
10649
|
const code = `${res.status}${res.statusText ? ` ${res.statusText}` : ""}`;
|
|
10351
|
-
const colour2 = res.status && res.status < 300 ?
|
|
10352
|
-
line(`${colour2(code)} ${
|
|
10650
|
+
const colour2 = res.status && res.status < 300 ? import_picocolors36.default.green : res.status && res.status < 500 ? import_picocolors36.default.yellow : import_picocolors36.default.red;
|
|
10651
|
+
line(`${colour2(code)} ${import_picocolors36.default.dim(`${res.durationMs}ms ${res.url}`)}`);
|
|
10353
10652
|
if (res.body) line(res.body);
|
|
10354
|
-
if (res.truncated) line(
|
|
10653
|
+
if (res.truncated) line(import_picocolors36.default.dim("(answer truncated)"));
|
|
10355
10654
|
});
|
|
10356
10655
|
if (!res?.ok) process.exitCode = 1;
|
|
10357
10656
|
})
|
|
@@ -10371,15 +10670,15 @@ function registerApi(program3) {
|
|
|
10371
10670
|
for (const r of report.routes) {
|
|
10372
10671
|
const known = report.missing.some((m) => m.path === r.path);
|
|
10373
10672
|
line(
|
|
10374
|
-
`${known ?
|
|
10673
|
+
`${known ? import_picocolors36.default.yellow("undocumented") : import_picocolors36.default.green("documented ")} ${r.path}${import_picocolors36.default.dim(` ${r.file}`)}`
|
|
10375
10674
|
);
|
|
10376
10675
|
}
|
|
10377
10676
|
for (const p of report.stale) {
|
|
10378
|
-
line(`${
|
|
10677
|
+
line(`${import_picocolors36.default.dim("in spec only ")} ${p}`);
|
|
10379
10678
|
}
|
|
10380
10679
|
line("");
|
|
10381
10680
|
if (report.ok && specFile) success(summary);
|
|
10382
|
-
else line(
|
|
10681
|
+
else line(import_picocolors36.default.yellow(summary));
|
|
10383
10682
|
});
|
|
10384
10683
|
if (opts.check && !report.ok) {
|
|
10385
10684
|
throw new WorkserError(summary, { code: "bad_request" });
|
|
@@ -10450,7 +10749,7 @@ function listRepoFiles(root, maxDepth = 8) {
|
|
|
10450
10749
|
}
|
|
10451
10750
|
|
|
10452
10751
|
// src/commands/analysis.ts
|
|
10453
|
-
var
|
|
10752
|
+
var import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
10454
10753
|
import { readFileSync as readFileSync4 } from "fs";
|
|
10455
10754
|
function registerAnalysis(program3) {
|
|
10456
10755
|
const cmd = program3.command("analysis").description("Run Python analysis locally, recorded in the task");
|
|
@@ -10460,14 +10759,14 @@ function registerAnalysis(program3) {
|
|
|
10460
10759
|
const res = await api(ctx, path);
|
|
10461
10760
|
ok(res, () => {
|
|
10462
10761
|
line(
|
|
10463
|
-
`${res?.available ?
|
|
10762
|
+
`${res?.available ? import_picocolors37.default.green("python") : import_picocolors37.default.red("python")} ${res?.version ?? "not found"} ${import_picocolors37.default.dim(res?.python ?? "")}`
|
|
10464
10763
|
);
|
|
10465
10764
|
for (const lib of res?.libraries ?? []) {
|
|
10466
10765
|
line(
|
|
10467
|
-
`${lib.present ?
|
|
10766
|
+
`${lib.present ? import_picocolors37.default.green(lib.name) : import_picocolors37.default.yellow(lib.name)}${import_picocolors37.default.dim(lib.present ? "" : " missing")}`
|
|
10468
10767
|
);
|
|
10469
10768
|
}
|
|
10470
|
-
for (const note of res?.notes ?? []) line(
|
|
10769
|
+
for (const note of res?.notes ?? []) line(import_picocolors37.default.dim(note));
|
|
10471
10770
|
});
|
|
10472
10771
|
if (!res?.available) process.exitCode = 1;
|
|
10473
10772
|
})
|
|
@@ -10489,15 +10788,15 @@ function registerAnalysis(program3) {
|
|
|
10489
10788
|
);
|
|
10490
10789
|
ok(res, () => {
|
|
10491
10790
|
if (res?.stdout) line(res.stdout.replace(/\n$/, ""));
|
|
10492
|
-
if (res?.stderr) line(
|
|
10493
|
-
if (res?.truncated) line(
|
|
10791
|
+
if (res?.stderr) line(import_picocolors37.default.dim(res.stderr.replace(/\n$/, "")));
|
|
10792
|
+
if (res?.truncated) line(import_picocolors37.default.dim("(output truncated)"));
|
|
10494
10793
|
const took = `${Math.round((res?.durationMs ?? 0) / 100) / 10}s`;
|
|
10495
10794
|
line(
|
|
10496
|
-
res?.ok ?
|
|
10795
|
+
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}`)
|
|
10497
10796
|
);
|
|
10498
10797
|
if (res && !res.sandboxed) {
|
|
10499
10798
|
line(
|
|
10500
|
-
|
|
10799
|
+
import_picocolors37.default.dim(
|
|
10501
10800
|
"This platform has no OS sandbox, so the script ran with your own file access."
|
|
10502
10801
|
)
|
|
10503
10802
|
);
|
|
@@ -10525,7 +10824,7 @@ function readCode(file, inline) {
|
|
|
10525
10824
|
}
|
|
10526
10825
|
|
|
10527
10826
|
// src/commands/scan.ts
|
|
10528
|
-
var
|
|
10827
|
+
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
10529
10828
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
10530
10829
|
import { existsSync as existsSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
10531
10830
|
import { join as join4, relative as relative2, sep as sep2 } from "path";
|
|
@@ -10809,22 +11108,22 @@ function runPermissions(cwd, findings, checked, skipped) {
|
|
|
10809
11108
|
}
|
|
10810
11109
|
function print2(report, summary) {
|
|
10811
11110
|
for (const s of report.skipped) {
|
|
10812
|
-
line(`${
|
|
11111
|
+
line(`${import_picocolors38.default.yellow("not checked")} ${s.check}${import_picocolors38.default.dim(` \u2014 ${s.reason}`)}`);
|
|
10813
11112
|
}
|
|
10814
11113
|
for (const f of report.findings) {
|
|
10815
|
-
const where = f.file ?
|
|
11114
|
+
const where = f.file ? import_picocolors38.default.dim(` ${f.file}${f.line ? `:${f.line}` : ""}`) : "";
|
|
10816
11115
|
line(`${severityTag(f.severity)} ${f.title}${where}`);
|
|
10817
|
-
line(` ${
|
|
11116
|
+
line(` ${import_picocolors38.default.dim(f.fix)}`);
|
|
10818
11117
|
}
|
|
10819
11118
|
if (report.findings.length || report.skipped.length) line("");
|
|
10820
11119
|
if (report.ok && !report.skipped.length) success(summary);
|
|
10821
|
-
else if (report.ok) line(
|
|
10822
|
-
else line(
|
|
11120
|
+
else if (report.ok) line(import_picocolors38.default.yellow(summary));
|
|
11121
|
+
else line(import_picocolors38.default.red(summary));
|
|
10823
11122
|
}
|
|
10824
11123
|
function severityTag(severity) {
|
|
10825
|
-
if (severity === "high") return
|
|
10826
|
-
if (severity === "medium") return
|
|
10827
|
-
return
|
|
11124
|
+
if (severity === "high") return import_picocolors38.default.red("serious ");
|
|
11125
|
+
if (severity === "medium") return import_picocolors38.default.yellow("worth fixing");
|
|
11126
|
+
return import_picocolors38.default.dim("minor ");
|
|
10828
11127
|
}
|
|
10829
11128
|
function git(cwd, args) {
|
|
10830
11129
|
try {
|
|
@@ -10885,7 +11184,7 @@ function listRepoFiles2(root, maxDepth = 8) {
|
|
|
10885
11184
|
}
|
|
10886
11185
|
|
|
10887
11186
|
// src/commands/health.ts
|
|
10888
|
-
var
|
|
11187
|
+
var import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
10889
11188
|
function registerHealth(program3) {
|
|
10890
11189
|
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(
|
|
10891
11190
|
action(async ({ ctx, opts }) => {
|
|
@@ -10899,16 +11198,16 @@ function registerHealth(program3) {
|
|
|
10899
11198
|
}
|
|
10900
11199
|
function print3(res) {
|
|
10901
11200
|
if (!res?.checks?.length) {
|
|
10902
|
-
line(
|
|
11201
|
+
line(import_picocolors39.default.dim(res?.note ?? "Nothing to check."));
|
|
10903
11202
|
return;
|
|
10904
11203
|
}
|
|
10905
11204
|
for (const c of res.checks) {
|
|
10906
|
-
const mark = c.ok ?
|
|
10907
|
-
const timing =
|
|
10908
|
-
const detail = c.ok ? timing :
|
|
10909
|
-
line(` ${mark} ${c.appName} ${
|
|
11205
|
+
const mark = c.ok ? import_picocolors39.default.green("up ") : import_picocolors39.default.red("down");
|
|
11206
|
+
const timing = import_picocolors39.default.dim(`${c.ms}ms`);
|
|
11207
|
+
const detail = c.ok ? timing : import_picocolors39.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
|
|
11208
|
+
line(` ${mark} ${c.appName} ${import_picocolors39.default.dim(`(${c.environment})`)} ${c.url} ${detail}`);
|
|
10910
11209
|
if (c.incidentOpened) {
|
|
10911
|
-
line(
|
|
11210
|
+
line(import_picocolors39.default.yellow(` An incident has been opened on the board for this.`));
|
|
10912
11211
|
}
|
|
10913
11212
|
}
|
|
10914
11213
|
const down = res.checks.filter((c) => !c.ok);
|
|
@@ -10921,14 +11220,14 @@ function print3(res) {
|
|
|
10921
11220
|
}
|
|
10922
11221
|
const production = down.filter((c) => c.environment === "production").length;
|
|
10923
11222
|
line(
|
|
10924
|
-
|
|
11223
|
+
import_picocolors39.default.red(
|
|
10925
11224
|
`${down.length} of ${res.checks.length} not answering` + (production ? ` \u2014 ${production} customer-facing.` : " (preview only).")
|
|
10926
11225
|
)
|
|
10927
11226
|
);
|
|
10928
11227
|
}
|
|
10929
11228
|
|
|
10930
11229
|
// src/commands/urls.ts
|
|
10931
|
-
var
|
|
11230
|
+
var import_picocolors40 = __toESM(require_picocolors(), 1);
|
|
10932
11231
|
function registerUrls(program3) {
|
|
10933
11232
|
program3.command("urls").description("The stable preview and production addresses of every app in this project").option("--app <webAppId>", "just one app").action(
|
|
10934
11233
|
action(async ({ ctx, opts }) => {
|
|
@@ -10942,20 +11241,20 @@ function registerUrls(program3) {
|
|
|
10942
11241
|
const summary = urlsSummary(rows);
|
|
10943
11242
|
ok({ rows, summary }, () => {
|
|
10944
11243
|
for (const row of rows) {
|
|
10945
|
-
const label =
|
|
10946
|
-
const value = row.url ?
|
|
11244
|
+
const label = import_picocolors40.default.dim(row.environment.padEnd(10));
|
|
11245
|
+
const value = row.url ? import_picocolors40.default.cyan(row.url) : import_picocolors40.default.dim(row.note ?? "not published");
|
|
10947
11246
|
line(` ${row.appName.padEnd(22)} ${label} ${value}`);
|
|
10948
11247
|
}
|
|
10949
11248
|
line("");
|
|
10950
11249
|
if (rows.some((r) => r.url)) success(summary);
|
|
10951
|
-
else line(
|
|
11250
|
+
else line(import_picocolors40.default.yellow(summary));
|
|
10952
11251
|
});
|
|
10953
11252
|
})
|
|
10954
11253
|
);
|
|
10955
11254
|
}
|
|
10956
11255
|
|
|
10957
11256
|
// src/commands/deployments.ts
|
|
10958
|
-
var
|
|
11257
|
+
var import_picocolors41 = __toESM(require_picocolors(), 1);
|
|
10959
11258
|
function registerDeployments(program3) {
|
|
10960
11259
|
const cmd = program3.command("deployments").description("Deployment history, and putting a build in front of customers");
|
|
10961
11260
|
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(
|
|
@@ -10973,7 +11272,7 @@ function registerDeployments(program3) {
|
|
|
10973
11272
|
ok(res, () => {
|
|
10974
11273
|
if (!items.length) {
|
|
10975
11274
|
return line(
|
|
10976
|
-
|
|
11275
|
+
import_picocolors41.default.dim(
|
|
10977
11276
|
environment ? `Nothing has been deployed to ${environment} yet.` : "Nothing has been deployed yet. `workser deploy` builds the first one."
|
|
10978
11277
|
)
|
|
10979
11278
|
);
|
|
@@ -10993,13 +11292,13 @@ function registerDeployments(program3) {
|
|
|
10993
11292
|
).catch(() => null) : null;
|
|
10994
11293
|
ok({ ...dep, logs }, () => {
|
|
10995
11294
|
line(formatDeployment(dep));
|
|
10996
|
-
if (dep?.error_message) line(
|
|
11295
|
+
if (dep?.error_message) line(import_picocolors41.default.red(` ${dep.error_message}`));
|
|
10997
11296
|
const events = logs?.events ?? [];
|
|
10998
11297
|
for (const e of events) {
|
|
10999
|
-
line(` ${
|
|
11298
|
+
line(` ${import_picocolors41.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
|
|
11000
11299
|
}
|
|
11001
11300
|
if (opts.logs && !events.length) {
|
|
11002
|
-
line(
|
|
11301
|
+
line(import_picocolors41.default.dim(" That build produced no output."));
|
|
11003
11302
|
}
|
|
11004
11303
|
});
|
|
11005
11304
|
})
|
|
@@ -11043,16 +11342,16 @@ function printPromoted(res, version) {
|
|
|
11043
11342
|
const what = version === null ? "the latest build" : `version ${version}`;
|
|
11044
11343
|
const url = res.url ?? res.vercel_url;
|
|
11045
11344
|
success(`Production is being rebuilt from ${what}.`);
|
|
11046
|
-
if (url) line(
|
|
11047
|
-
line(
|
|
11345
|
+
if (url) line(import_picocolors41.default.dim(`It will be at ${url}`));
|
|
11346
|
+
line(import_picocolors41.default.dim("`workser deploy status` follows it."));
|
|
11048
11347
|
}
|
|
11049
11348
|
function formatDeployment(d) {
|
|
11050
11349
|
if (!d) return "";
|
|
11051
|
-
const version = d.version !== void 0 ?
|
|
11052
|
-
const env =
|
|
11350
|
+
const version = d.version !== void 0 ? import_picocolors41.default.yellow(`v${d.version}`) : import_picocolors41.default.dim("v?");
|
|
11351
|
+
const env = import_picocolors41.default.dim((d.environment ?? "?").padEnd(10));
|
|
11053
11352
|
const app = d.webAppName ? `${d.webAppName} ` : "";
|
|
11054
|
-
const when =
|
|
11055
|
-
const url = d.url ? " " +
|
|
11353
|
+
const when = import_picocolors41.default.dim(formatTime2(d.created_at));
|
|
11354
|
+
const url = d.url ? " " + import_picocolors41.default.cyan(d.url) : "";
|
|
11056
11355
|
return `${version} ${env} ${colorStatus(d.status ?? "")} ${app}${when}${url}`;
|
|
11057
11356
|
}
|
|
11058
11357
|
function formatTime2(t) {
|
|
@@ -11062,7 +11361,7 @@ function formatTime2(t) {
|
|
|
11062
11361
|
}
|
|
11063
11362
|
|
|
11064
11363
|
// src/commands/usage.ts
|
|
11065
|
-
var
|
|
11364
|
+
var import_picocolors42 = __toESM(require_picocolors(), 1);
|
|
11066
11365
|
|
|
11067
11366
|
// src/usage.ts
|
|
11068
11367
|
var NEAR_LIMIT_FRACTION = 0.8;
|
|
@@ -11157,7 +11456,7 @@ function registerUsage(program3) {
|
|
|
11157
11456
|
function print4(report) {
|
|
11158
11457
|
const dims = report.dimensions ?? [];
|
|
11159
11458
|
if (!dims.length) {
|
|
11160
|
-
return line(
|
|
11459
|
+
return line(import_picocolors42.default.dim("Nothing to measure for this project yet."));
|
|
11161
11460
|
}
|
|
11162
11461
|
const width = Math.max(...dims.map((d) => d.label.length));
|
|
11163
11462
|
for (const d of dims) {
|
|
@@ -11166,23 +11465,23 @@ function print4(report) {
|
|
|
11166
11465
|
line("");
|
|
11167
11466
|
const summary = usageSummary(report);
|
|
11168
11467
|
const worst = dims.map(usageState);
|
|
11169
|
-
if (worst.includes("over")) line(
|
|
11468
|
+
if (worst.includes("over")) line(import_picocolors42.default.red(summary));
|
|
11170
11469
|
else if (worst.includes("near") || worst.includes("unknown"))
|
|
11171
|
-
line(
|
|
11470
|
+
line(import_picocolors42.default.yellow(summary));
|
|
11172
11471
|
else success(summary);
|
|
11173
11472
|
}
|
|
11174
11473
|
function gauge(d, _labelWidth) {
|
|
11175
11474
|
const drawn = bar(d);
|
|
11176
|
-
return drawn ? ` ${
|
|
11475
|
+
return drawn ? ` ${import_picocolors42.default.dim(drawn)}` : "";
|
|
11177
11476
|
}
|
|
11178
11477
|
function colour(d) {
|
|
11179
11478
|
switch (usageState(d)) {
|
|
11180
11479
|
case "over":
|
|
11181
|
-
return d.kind === "hard" ?
|
|
11480
|
+
return d.kind === "hard" ? import_picocolors42.default.red : import_picocolors42.default.yellow;
|
|
11182
11481
|
case "near":
|
|
11183
|
-
return
|
|
11482
|
+
return import_picocolors42.default.yellow;
|
|
11184
11483
|
case "unknown":
|
|
11185
|
-
return
|
|
11484
|
+
return import_picocolors42.default.dim;
|
|
11186
11485
|
default:
|
|
11187
11486
|
return (s) => s;
|
|
11188
11487
|
}
|
|
@@ -11190,7 +11489,7 @@ function colour(d) {
|
|
|
11190
11489
|
|
|
11191
11490
|
// src/index.ts
|
|
11192
11491
|
var pkg = {
|
|
11193
|
-
version: true ? "0.6.
|
|
11492
|
+
version: true ? "0.6.14" : "0.0.0-dev"
|
|
11194
11493
|
};
|
|
11195
11494
|
var program2 = new Command();
|
|
11196
11495
|
program2.name("workser").description(
|
|
@@ -11223,6 +11522,7 @@ registerDomain(program2);
|
|
|
11223
11522
|
registerOpen(program2);
|
|
11224
11523
|
registerDoctor(program2);
|
|
11225
11524
|
registerAgent(program2);
|
|
11525
|
+
registerCloudAgent(program2);
|
|
11226
11526
|
registerVerify(program2);
|
|
11227
11527
|
registerApi(program2);
|
|
11228
11528
|
registerAnalysis(program2);
|
|
@@ -11237,6 +11537,7 @@ registerWorkflow(program2);
|
|
|
11237
11537
|
registerConnection(program2);
|
|
11238
11538
|
registerTool(program2);
|
|
11239
11539
|
registerMemory(program2);
|
|
11540
|
+
registerNote(program2);
|
|
11240
11541
|
registerBusiness(program2);
|
|
11241
11542
|
registerArtifact(program2);
|
|
11242
11543
|
registerImage(program2);
|