@workser/cli 0.6.16 → 0.6.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +806 -253
- package/package.json +1 -1
- package/skills/workser/SKILL.md +1 -0
package/dist/index.js
CHANGED
|
@@ -3663,6 +3663,158 @@ var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
|
3663
3663
|
|
|
3664
3664
|
// src/help-content.ts
|
|
3665
3665
|
var HELP_TOPICS = [
|
|
3666
|
+
{
|
|
3667
|
+
topic: "agent-cloud",
|
|
3668
|
+
title: "Ship an agent inside the app",
|
|
3669
|
+
summary: "Create an AI agent that runs on Workser and can be called from this project's apps.",
|
|
3670
|
+
commands: ["agent-cloud"],
|
|
3671
|
+
source: "skills/workser/reference/agent-cloud.md",
|
|
3672
|
+
body: `# Ship an agent inside the app
|
|
3673
|
+
|
|
3674
|
+
\`workser agent-cloud\` creates an AI agent that runs on **Workser's**
|
|
3675
|
+
infrastructure, keeps its own memory and tools, and can be called from the web,
|
|
3676
|
+
mobile, API or Python apps in this project.
|
|
3677
|
+
|
|
3678
|
+
**This is not \`workser agent\`.** That one hands a subtask to a coding agent on
|
|
3679
|
+
this machine \u2014 a teammate helping you build. This one is a thing the project
|
|
3680
|
+
*ships*: it works for the user after you are gone.
|
|
3681
|
+
|
|
3682
|
+
\`\`\`
|
|
3683
|
+
workser agent-cloud list
|
|
3684
|
+
workser agent-cloud create "Order desk" --instructions "..."
|
|
3685
|
+
workser agent-cloud show <agentId>
|
|
3686
|
+
workser agent-cloud run <agentId> "<what to do>"
|
|
3687
|
+
workser agent-cloud runs <agentId> # recent runs
|
|
3688
|
+
workser agent-cloud runs <runId> # one run, with what it cost
|
|
3689
|
+
\`\`\`
|
|
3690
|
+
|
|
3691
|
+
Every call is scoped to the project this folder belongs to.
|
|
3692
|
+
|
|
3693
|
+
## Creating one is not finishing one
|
|
3694
|
+
|
|
3695
|
+
An agent created with a name and a sentence knows nothing about the business.
|
|
3696
|
+
Teaching it is the actual work, and it is all here:
|
|
3697
|
+
|
|
3698
|
+
\`\`\`
|
|
3699
|
+
workser agent-cloud set <id> system_prompt="..." handle="orderdesk"
|
|
3700
|
+
workser agent-cloud add <id> skill name="Refunds" instructions_md="..."
|
|
3701
|
+
workser agent-cloud add <id> knowledge name="Price list" content_text="..."
|
|
3702
|
+
workser agent-cloud add <id> tool display_name="Send email" provider="gmail" \\
|
|
3703
|
+
provider_tool_id="GMAIL_SEND_EMAIL"
|
|
3704
|
+
workser agent-cloud add <id> secret key="STRIPE_KEY" value="..."
|
|
3705
|
+
workser agent-cloud add <id> subagent subagent_id=<otherId> name="researcher"
|
|
3706
|
+
workser agent-cloud get <id> skill # what it has
|
|
3707
|
+
workser agent-cloud remove <id> skill <itemId>
|
|
3708
|
+
\`\`\`
|
|
3709
|
+
|
|
3710
|
+
\`add\` takes \`key=value\` pairs and REFUSES a field it does not know, rather than
|
|
3711
|
+
sending it. That matters: the API silently drops unknown fields, so a typo
|
|
3712
|
+
would otherwise be accepted, dropped, and reported as success \u2014 leaving an
|
|
3713
|
+
agent that had been told nothing.
|
|
3714
|
+
|
|
3715
|
+
## Nothing takes effect until you publish
|
|
3716
|
+
|
|
3717
|
+
**This is the step to not forget.** The runtime resolves the PUBLISHED version
|
|
3718
|
+
of an agent and never the draft, so every \`set\` and \`add\` above is inert until:
|
|
3719
|
+
|
|
3720
|
+
\`\`\`
|
|
3721
|
+
workser agent-cloud publish <id> --note "taught it refunds"
|
|
3722
|
+
\`\`\`
|
|
3723
|
+
|
|
3724
|
+
Before publishing, try the setup without putting it live:
|
|
3725
|
+
|
|
3726
|
+
\`\`\`
|
|
3727
|
+
workser agent-cloud try <id> "a customer wants a refund on order 1042"
|
|
3728
|
+
\`\`\`
|
|
3729
|
+
|
|
3730
|
+
A \`try\` runs the draft, costs the same as a real run, and changes nothing that
|
|
3731
|
+
customers can reach.
|
|
3732
|
+
|
|
3733
|
+
## Choosing how it thinks and what it runs on
|
|
3734
|
+
|
|
3735
|
+
\`\`\`
|
|
3736
|
+
workser agent-cloud models # cheapest first, on Workser credit
|
|
3737
|
+
workser agent-cloud models --all # includes ones needing your own key
|
|
3738
|
+
workser agent-cloud set <id> default_provider=openrouter default_model=...
|
|
3739
|
+
|
|
3740
|
+
workser agent-cloud machines # video, data analysis, design, ...
|
|
3741
|
+
\`\`\`
|
|
3742
|
+
|
|
3743
|
+
A model marked "needs your own key" will make \`publish\` FAIL unless a matching
|
|
3744
|
+
secret is stored first. Add the key with \`add <id> secret\` before setting it.
|
|
3745
|
+
|
|
3746
|
+
## Agents need a paid plan \u2014 the trial does not include them
|
|
3747
|
+
|
|
3748
|
+
\`create\` and \`run\` both refuse with **402** on a free or trialling
|
|
3749
|
+
organisation. That is a rule, not a fault: every run buys model tokens and
|
|
3750
|
+
holds a machine, so it costs real money the moment it happens.
|
|
3751
|
+
|
|
3752
|
+
**When you hit it, hand the plan over \u2014 do not just describe it.** Workser
|
|
3753
|
+
files the refusal on the conversation as a step and an artifact the user can
|
|
3754
|
+
click, so the person you are helping gets something actionable rather than a
|
|
3755
|
+
paragraph. Say plainly what you were doing, that agents need a plan, and stop.
|
|
3756
|
+
|
|
3757
|
+
Do NOT:
|
|
3758
|
+
|
|
3759
|
+
- retry the call, or try a different agent \u2014 the answer is the same
|
|
3760
|
+
- try to work around it by running the job yourself as a coding agent; that is
|
|
3761
|
+
a different product and it will not be there when the user closes the window
|
|
3762
|
+
- guess at prices, discounts or trial extensions
|
|
3763
|
+
|
|
3764
|
+
If the user asks how much: it is per minute of run time plus the model, and the
|
|
3765
|
+
plan page has the current figures. You do not have them.
|
|
3766
|
+
|
|
3767
|
+
## When to reach for this
|
|
3768
|
+
|
|
3769
|
+
When the user describes a job that **keeps happening** and needs judgement:
|
|
3770
|
+
"check every order for stock and email me the problems", "read the LINE
|
|
3771
|
+
messages and file them", "reconcile these invoices". That is an agent.
|
|
3772
|
+
|
|
3773
|
+
A one-off transformation is not an agent \u2014 write the code. A fixed sequence of
|
|
3774
|
+
steps with no judgement in it is not an agent either \u2014 that is \`workser
|
|
3775
|
+
workflow\`.
|
|
3776
|
+
|
|
3777
|
+
## Calling it from the app you are building
|
|
3778
|
+
|
|
3779
|
+
Do NOT shell out to the CLI from app code. Use the SDK, which streams:
|
|
3780
|
+
|
|
3781
|
+
\`\`\`ts
|
|
3782
|
+
import { workser } from '@workser/app';
|
|
3783
|
+
|
|
3784
|
+
const run = await workser.agents.run(agentId, { message }, {
|
|
3785
|
+
referenceUserId: user.id, // who it is acting for
|
|
3786
|
+
});
|
|
3787
|
+
|
|
3788
|
+
for await (const event of workser.agents.stream(run.id)) {
|
|
3789
|
+
// event.type, event.data \u2014 forward these to the browser
|
|
3790
|
+
}
|
|
3791
|
+
\`\`\`
|
|
3792
|
+
|
|
3793
|
+
\`stream()\` reconnects itself through dropped connections, so the person
|
|
3794
|
+
watching sees the agent think. See the \`workser-sdk\` skill, \`reference/agents.md\`.
|
|
3795
|
+
|
|
3796
|
+
## Things that will bite you
|
|
3797
|
+
|
|
3798
|
+
1. **A run costs money by the minute.** It is metered \u2014 runtime, workspace, and
|
|
3799
|
+
a per-run fee \u2014 so a loop that starts agents is a loop that spends. Cancel
|
|
3800
|
+
what you abandon: \`workser agent-cloud runs <runId>\` shows the cost.
|
|
3801
|
+
|
|
3802
|
+
2. **Instructions are the product.** The agent does what its instructions say,
|
|
3803
|
+
in the user's own words. Write them the way you would brief a new colleague:
|
|
3804
|
+
what to do, what to leave alone, when to ask. Vague instructions are the
|
|
3805
|
+
single biggest cause of an agent that "doesn't work".
|
|
3806
|
+
|
|
3807
|
+
3. **Free plans cannot run agents at all**, and a trial has a small allowance.
|
|
3808
|
+
A \`402\` with \`spend_limit_reached\` is not a bug \u2014 tell the user what it says
|
|
3809
|
+
and point them at their plan.
|
|
3810
|
+
|
|
3811
|
+
4. **Say who it is for.** An agent acting for one of the app's customers needs
|
|
3812
|
+
\`referenceUserId\`, or its memory and audit trail belong to nobody.
|
|
3813
|
+
|
|
3814
|
+
5. **Do not invent an agent the user did not ask for.** Creating one is cheap;
|
|
3815
|
+
an agent nobody wanted, quietly costing money per run, is not.
|
|
3816
|
+
`
|
|
3817
|
+
},
|
|
3666
3818
|
{
|
|
3667
3819
|
topic: "analysis",
|
|
3668
3820
|
title: "Analysis \u2014 running Python on this project's data",
|
|
@@ -7459,8 +7611,366 @@ function formatRole(r) {
|
|
|
7459
7611
|
return `${label} ${agent} ${enabled} ${ready}${tail}`;
|
|
7460
7612
|
}
|
|
7461
7613
|
|
|
7462
|
-
// src/commands/
|
|
7614
|
+
// src/commands/agent-cloud.ts
|
|
7463
7615
|
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
7616
|
+
function registerAgentCloud(program3) {
|
|
7617
|
+
const cloud = program3.command("agent-cloud").description(
|
|
7618
|
+
"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`)"
|
|
7619
|
+
);
|
|
7620
|
+
cloud.command("list").description("List this project's cloud agents").action(
|
|
7621
|
+
action(async ({ ctx }) => {
|
|
7622
|
+
const res = await api(ctx, "/v1/agent-cloud");
|
|
7623
|
+
const agents = res?.agents ?? res ?? [];
|
|
7624
|
+
ok(res, () => {
|
|
7625
|
+
if (!agents.length) {
|
|
7626
|
+
line(import_picocolors17.default.dim("No cloud agents yet."));
|
|
7627
|
+
line(
|
|
7628
|
+
import_picocolors17.default.dim("Create one: ") + import_picocolors17.default.bold('workser agent-cloud create "Order desk" --instructions "..."')
|
|
7629
|
+
);
|
|
7630
|
+
return;
|
|
7631
|
+
}
|
|
7632
|
+
for (const a of agents) {
|
|
7633
|
+
line(
|
|
7634
|
+
`${import_picocolors17.default.bold(a.name ?? a.id)} ${import_picocolors17.default.dim(a.id)}` + (a.status ? ` ${import_picocolors17.default.dim(a.status)}` : "")
|
|
7635
|
+
);
|
|
7636
|
+
if (a.description) line(" " + import_picocolors17.default.dim(a.description));
|
|
7637
|
+
}
|
|
7638
|
+
});
|
|
7639
|
+
})
|
|
7640
|
+
);
|
|
7641
|
+
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(
|
|
7642
|
+
"--instructions <text>",
|
|
7643
|
+
"The agent's standing instructions \u2014 what it should always do"
|
|
7644
|
+
).action(
|
|
7645
|
+
action(async ({ ctx, args, opts }) => {
|
|
7646
|
+
const res = await api(ctx, "/v1/agent-cloud", {
|
|
7647
|
+
method: "POST",
|
|
7648
|
+
body: {
|
|
7649
|
+
name: args[0],
|
|
7650
|
+
description: opts.description,
|
|
7651
|
+
instructions: opts.instructions
|
|
7652
|
+
}
|
|
7653
|
+
});
|
|
7654
|
+
ok(res, () => {
|
|
7655
|
+
line(import_picocolors17.default.green("Created ") + import_picocolors17.default.bold(res?.name ?? args[0]));
|
|
7656
|
+
if (res?.id) line(import_picocolors17.default.dim(res.id));
|
|
7657
|
+
line("");
|
|
7658
|
+
line(
|
|
7659
|
+
import_picocolors17.default.dim("Give it work: ") + import_picocolors17.default.bold(`workser agent-cloud run ${res?.id ?? "<id>"} "..."`)
|
|
7660
|
+
);
|
|
7661
|
+
});
|
|
7662
|
+
})
|
|
7663
|
+
);
|
|
7664
|
+
cloud.command("show <agentId>").description("One cloud agent, with its configuration").action(
|
|
7665
|
+
action(async ({ ctx, args }) => {
|
|
7666
|
+
const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}`);
|
|
7667
|
+
ok(res, () => {
|
|
7668
|
+
line(import_picocolors17.default.bold(res?.name ?? args[0]));
|
|
7669
|
+
if (res?.description) line(import_picocolors17.default.dim(res.description));
|
|
7670
|
+
if (res?.instructions) {
|
|
7671
|
+
line("");
|
|
7672
|
+
line(import_picocolors17.default.bold("instructions:"));
|
|
7673
|
+
line(res.instructions);
|
|
7674
|
+
}
|
|
7675
|
+
});
|
|
7676
|
+
})
|
|
7677
|
+
);
|
|
7678
|
+
cloud.command("run <agentId> <message>").description("Give a cloud agent something to do").action(
|
|
7679
|
+
action(async ({ ctx, args }) => {
|
|
7680
|
+
const res = await api(
|
|
7681
|
+
ctx,
|
|
7682
|
+
`/v1/agent-cloud/${encodeURIComponent(args[0])}/runs`,
|
|
7683
|
+
{ method: "POST", body: { input: { message: args[1] } } }
|
|
7684
|
+
);
|
|
7685
|
+
ok(res, () => {
|
|
7686
|
+
line(import_picocolors17.default.green("Started run ") + import_picocolors17.default.bold(res?.id ?? ""));
|
|
7687
|
+
line(
|
|
7688
|
+
import_picocolors17.default.dim("Follow it: ") + import_picocolors17.default.bold(`workser agent-cloud runs ${res?.id ?? "<runId>"}`)
|
|
7689
|
+
);
|
|
7690
|
+
});
|
|
7691
|
+
})
|
|
7692
|
+
);
|
|
7693
|
+
cloud.command("runs [agentIdOrRunId]").description("Recent runs for an agent, or one run in detail").option("--limit <n>", "How many to list", "10").action(
|
|
7694
|
+
action(async ({ ctx, args, opts }) => {
|
|
7695
|
+
const id = args[0];
|
|
7696
|
+
if (!id) {
|
|
7697
|
+
warn("Give an agent id to list its runs, or a run id to inspect one.");
|
|
7698
|
+
return;
|
|
7699
|
+
}
|
|
7700
|
+
try {
|
|
7701
|
+
const run = await api(
|
|
7702
|
+
ctx,
|
|
7703
|
+
`/v1/agent-cloud/runs/${encodeURIComponent(id)}`
|
|
7704
|
+
);
|
|
7705
|
+
ok(run, () => printRun(run));
|
|
7706
|
+
return;
|
|
7707
|
+
} catch {
|
|
7708
|
+
}
|
|
7709
|
+
const res = await api(
|
|
7710
|
+
ctx,
|
|
7711
|
+
`/v1/agent-cloud/${encodeURIComponent(id)}/runs`,
|
|
7712
|
+
{ query: { limit: opts.limit } }
|
|
7713
|
+
);
|
|
7714
|
+
const runs = res?.runs ?? res ?? [];
|
|
7715
|
+
ok(res, () => {
|
|
7716
|
+
if (!runs.length) {
|
|
7717
|
+
line(import_picocolors17.default.dim("No runs yet."));
|
|
7718
|
+
return;
|
|
7719
|
+
}
|
|
7720
|
+
for (const r of runs) printRun(r, true);
|
|
7721
|
+
});
|
|
7722
|
+
})
|
|
7723
|
+
);
|
|
7724
|
+
const COLLECTIONS = {
|
|
7725
|
+
skill: {
|
|
7726
|
+
path: "skills",
|
|
7727
|
+
key: "skills",
|
|
7728
|
+
label: "skill",
|
|
7729
|
+
fields: ["name", "description", "instructions_md"],
|
|
7730
|
+
required: ["name"]
|
|
7731
|
+
},
|
|
7732
|
+
tool: {
|
|
7733
|
+
path: "tools",
|
|
7734
|
+
key: "tools",
|
|
7735
|
+
label: "action",
|
|
7736
|
+
fields: ["display_name", "provider", "provider_tool_id", "description"],
|
|
7737
|
+
required: ["display_name"]
|
|
7738
|
+
},
|
|
7739
|
+
mcp: {
|
|
7740
|
+
path: "mcp-servers",
|
|
7741
|
+
key: "servers",
|
|
7742
|
+
label: "MCP server",
|
|
7743
|
+
fields: ["name", "url"],
|
|
7744
|
+
required: ["name", "url"]
|
|
7745
|
+
},
|
|
7746
|
+
knowledge: {
|
|
7747
|
+
path: "resources",
|
|
7748
|
+
key: "resources",
|
|
7749
|
+
label: "reference material",
|
|
7750
|
+
fields: ["name", "content_text"],
|
|
7751
|
+
required: ["name"]
|
|
7752
|
+
},
|
|
7753
|
+
secret: {
|
|
7754
|
+
path: "secrets",
|
|
7755
|
+
key: "secrets",
|
|
7756
|
+
label: "stored key",
|
|
7757
|
+
fields: ["key", "value", "description"],
|
|
7758
|
+
required: ["key", "value"]
|
|
7759
|
+
},
|
|
7760
|
+
subagent: {
|
|
7761
|
+
path: "subagents",
|
|
7762
|
+
key: "subagents",
|
|
7763
|
+
label: "team member",
|
|
7764
|
+
fields: ["subagent_id", "name", "description"],
|
|
7765
|
+
required: ["subagent_id", "name"]
|
|
7766
|
+
},
|
|
7767
|
+
workflow: {
|
|
7768
|
+
path: "workflows",
|
|
7769
|
+
key: "workflows",
|
|
7770
|
+
label: "workflow",
|
|
7771
|
+
fields: ["workflow_id", "description"],
|
|
7772
|
+
required: ["workflow_id"]
|
|
7773
|
+
}
|
|
7774
|
+
};
|
|
7775
|
+
const kinds = Object.keys(COLLECTIONS).join(" | ");
|
|
7776
|
+
cloud.command("get <agentId> <kind>").description(`What an agent has been given (${kinds})`).action(
|
|
7777
|
+
action(async ({ ctx, args }) => {
|
|
7778
|
+
const spec = COLLECTIONS[args[1]];
|
|
7779
|
+
if (!spec) throw new Error(`Unknown kind "${args[1]}". One of: ${kinds}`);
|
|
7780
|
+
const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}/${spec.path}`);
|
|
7781
|
+
const items = res?.[spec.key] ?? [];
|
|
7782
|
+
ok(res, () => {
|
|
7783
|
+
if (!items.length) {
|
|
7784
|
+
line(import_picocolors17.default.dim(`No ${spec.label} yet.`));
|
|
7785
|
+
return;
|
|
7786
|
+
}
|
|
7787
|
+
for (const i of items) {
|
|
7788
|
+
const title = i.name ?? i.display_name ?? i.key ?? i.workflow_id ?? i.id;
|
|
7789
|
+
line(`${import_picocolors17.default.bold(title)} ${import_picocolors17.default.dim(i.id)}`);
|
|
7790
|
+
if (i.description) line(" " + import_picocolors17.default.dim(i.description));
|
|
7791
|
+
if (i.is_enabled === false) line(" " + import_picocolors17.default.yellow("turned off"));
|
|
7792
|
+
}
|
|
7793
|
+
});
|
|
7794
|
+
})
|
|
7795
|
+
);
|
|
7796
|
+
cloud.command("add <agentId> <kind> [pairs...]").description(
|
|
7797
|
+
`Give an agent something (${kinds}). Pairs are key=value, e.g. name="Refunds"`
|
|
7798
|
+
).action(
|
|
7799
|
+
action(async ({ ctx, args }) => {
|
|
7800
|
+
const spec = COLLECTIONS[args[1]];
|
|
7801
|
+
if (!spec) throw new Error(`Unknown kind "${args[1]}". One of: ${kinds}`);
|
|
7802
|
+
const body = parsePairs(args[2] ?? [], spec.fields);
|
|
7803
|
+
const missing = spec.required.filter((f) => !body[f]);
|
|
7804
|
+
if (missing.length) {
|
|
7805
|
+
throw new Error(
|
|
7806
|
+
`A ${spec.label} needs ${missing.join(" and ")}. Accepted: ${spec.fields.join(", ")}`
|
|
7807
|
+
);
|
|
7808
|
+
}
|
|
7809
|
+
const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}/${spec.path}`, {
|
|
7810
|
+
method: "POST",
|
|
7811
|
+
body
|
|
7812
|
+
});
|
|
7813
|
+
ok(res, () => {
|
|
7814
|
+
line(import_picocolors17.default.green(`Added the ${spec.label}.`) + " " + import_picocolors17.default.dim(res?.id ?? ""));
|
|
7815
|
+
line(
|
|
7816
|
+
import_picocolors17.default.dim("Not live yet \u2014 run ") + import_picocolors17.default.bold(`workser agent-cloud publish ${args[0]}`) + import_picocolors17.default.dim(" when the setup is ready.")
|
|
7817
|
+
);
|
|
7818
|
+
});
|
|
7819
|
+
})
|
|
7820
|
+
);
|
|
7821
|
+
cloud.command("remove <agentId> <kind> <itemId>").description(`Take something away from an agent (${kinds})`).action(
|
|
7822
|
+
action(async ({ ctx, args }) => {
|
|
7823
|
+
const spec = COLLECTIONS[args[1]];
|
|
7824
|
+
if (!spec) throw new Error(`Unknown kind "${args[1]}". One of: ${kinds}`);
|
|
7825
|
+
const res = await api(
|
|
7826
|
+
ctx,
|
|
7827
|
+
`/v1/agent-cloud/${encodeURIComponent(args[0])}/${spec.path}/${encodeURIComponent(args[2])}`,
|
|
7828
|
+
{ method: "DELETE" }
|
|
7829
|
+
);
|
|
7830
|
+
ok(res, () => line(import_picocolors17.default.green(`Removed the ${spec.label}.`)));
|
|
7831
|
+
})
|
|
7832
|
+
);
|
|
7833
|
+
cloud.command("set <agentId> [pairs...]").description(
|
|
7834
|
+
"Change the brief or the model. Pairs: name, description, system_prompt, handle, default_provider, default_model"
|
|
7835
|
+
).action(
|
|
7836
|
+
action(async ({ ctx, args }) => {
|
|
7837
|
+
const body = parsePairs(args[1] ?? [], [
|
|
7838
|
+
"name",
|
|
7839
|
+
"description",
|
|
7840
|
+
"system_prompt",
|
|
7841
|
+
"handle",
|
|
7842
|
+
"default_provider",
|
|
7843
|
+
"default_model"
|
|
7844
|
+
]);
|
|
7845
|
+
if (!Object.keys(body).length) {
|
|
7846
|
+
throw new Error(
|
|
7847
|
+
'Nothing to change. Example: workser agent-cloud set <id> system_prompt="Always check stock first"'
|
|
7848
|
+
);
|
|
7849
|
+
}
|
|
7850
|
+
const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}`, {
|
|
7851
|
+
method: "PATCH",
|
|
7852
|
+
body
|
|
7853
|
+
});
|
|
7854
|
+
ok(res, () => {
|
|
7855
|
+
line(import_picocolors17.default.green("Saved."));
|
|
7856
|
+
line(
|
|
7857
|
+
import_picocolors17.default.dim("Not live yet \u2014 run ") + import_picocolors17.default.bold(`workser agent-cloud publish ${args[0]}`) + import_picocolors17.default.dim(".")
|
|
7858
|
+
);
|
|
7859
|
+
});
|
|
7860
|
+
})
|
|
7861
|
+
);
|
|
7862
|
+
cloud.command("publish <agentId>").description("Put the current setup live \u2014 nothing takes effect until this runs").option("--note <text>", "What changed, for the version history").action(
|
|
7863
|
+
action(async ({ ctx, args, opts }) => {
|
|
7864
|
+
const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}/publish`, {
|
|
7865
|
+
method: "POST",
|
|
7866
|
+
body: { changelog: opts.note }
|
|
7867
|
+
});
|
|
7868
|
+
ok(
|
|
7869
|
+
res,
|
|
7870
|
+
() => line(import_picocolors17.default.green(`Live${res?.version ? ` \u2014 version ${res.version}` : ""}.`))
|
|
7871
|
+
);
|
|
7872
|
+
})
|
|
7873
|
+
);
|
|
7874
|
+
cloud.command("try <agentId> <message>").description("Run the current setup WITHOUT publishing it").action(
|
|
7875
|
+
action(async ({ ctx, args }) => {
|
|
7876
|
+
const res = await api(ctx, `/v1/agent-cloud/${encodeURIComponent(args[0])}/test-runs`, {
|
|
7877
|
+
method: "POST",
|
|
7878
|
+
body: { input: { message: args[1] } }
|
|
7879
|
+
});
|
|
7880
|
+
ok(res, () => {
|
|
7881
|
+
line(import_picocolors17.default.green("Trying it \u2014 nothing has gone live."));
|
|
7882
|
+
if (res?.run_id) {
|
|
7883
|
+
line(
|
|
7884
|
+
import_picocolors17.default.dim("Watch it: ") + import_picocolors17.default.bold(`workser agent-cloud runs ${res.run_id}`)
|
|
7885
|
+
);
|
|
7886
|
+
}
|
|
7887
|
+
});
|
|
7888
|
+
})
|
|
7889
|
+
);
|
|
7890
|
+
cloud.command("machines").description("The pre-built machines an agent can run on").action(
|
|
7891
|
+
action(async ({ ctx }) => {
|
|
7892
|
+
const res = await api(ctx, "/v1/agent-cloud/catalog/machines");
|
|
7893
|
+
ok(res, () => {
|
|
7894
|
+
for (const m of res?.machines ?? []) {
|
|
7895
|
+
line(`${import_picocolors17.default.bold(m.label)} ${import_picocolors17.default.dim(m.alias)}`);
|
|
7896
|
+
line(" " + import_picocolors17.default.dim(m.description));
|
|
7897
|
+
}
|
|
7898
|
+
});
|
|
7899
|
+
})
|
|
7900
|
+
);
|
|
7901
|
+
cloud.command("models").description("Models this organisation can run an agent on, cheapest first").option("--all", "Include models that need your own provider key").action(
|
|
7902
|
+
action(async ({ ctx, opts }) => {
|
|
7903
|
+
const res = await api(ctx, "/v1/agent-cloud/catalog/models/live");
|
|
7904
|
+
const models = (res?.models ?? []).filter(
|
|
7905
|
+
(m) => opts.all || m.credit_tier === "PLATFORM_CREDITS"
|
|
7906
|
+
);
|
|
7907
|
+
ok(res, () => {
|
|
7908
|
+
if (!models.length) {
|
|
7909
|
+
warn("The live model list could not be read.");
|
|
7910
|
+
return;
|
|
7911
|
+
}
|
|
7912
|
+
for (const m of models.slice(0, 40)) {
|
|
7913
|
+
const price = typeof m.input_price_per_million_usd === "number" ? `$${m.input_price_per_million_usd.toFixed(2)}/M in` : "price unknown";
|
|
7914
|
+
const byok = m.credit_tier === "PLATFORM_CREDITS" ? "" : import_picocolors17.default.yellow(" needs your own key");
|
|
7915
|
+
line(`${import_picocolors17.default.bold(m.id)} ${import_picocolors17.default.dim(price)}${byok}`);
|
|
7916
|
+
}
|
|
7917
|
+
});
|
|
7918
|
+
})
|
|
7919
|
+
);
|
|
7920
|
+
}
|
|
7921
|
+
function printRun(run, compact = false) {
|
|
7922
|
+
const status = String(run?.status ?? "").toLowerCase();
|
|
7923
|
+
const colour2 = status === "completed" ? import_picocolors17.default.green : status === "failed" ? import_picocolors17.default.red : import_picocolors17.default.yellow;
|
|
7924
|
+
line(
|
|
7925
|
+
`${colour2(status || "unknown")} ${import_picocolors17.default.bold(run?.id ?? "")}` + (run?.duration_ms ? ` ${import_picocolors17.default.dim(formatDuration(run.duration_ms))}` : "")
|
|
7926
|
+
);
|
|
7927
|
+
const breakdown = run?.cost_breakdown;
|
|
7928
|
+
if (breakdown) {
|
|
7929
|
+
if (!breakdown.settled) {
|
|
7930
|
+
line(" " + import_picocolors17.default.dim("cost: still being worked out"));
|
|
7931
|
+
} else {
|
|
7932
|
+
line(" " + import_picocolors17.default.dim(`cost: $${Number(breakdown.total_usd).toFixed(4)}`));
|
|
7933
|
+
line(
|
|
7934
|
+
" " + import_picocolors17.default.dim(
|
|
7935
|
+
`model $${Number(breakdown.model_usd).toFixed(4)} \xB7 infrastructure $${Number(breakdown.infrastructure_usd).toFixed(4)}`
|
|
7936
|
+
)
|
|
7937
|
+
);
|
|
7938
|
+
}
|
|
7939
|
+
} else if (run?.cost_usd !== void 0 && run?.cost_usd !== null) {
|
|
7940
|
+
line(" " + import_picocolors17.default.dim(`model cost: $${Number(run.cost_usd).toFixed(4)}`));
|
|
7941
|
+
}
|
|
7942
|
+
if (!compact && run?.output) {
|
|
7943
|
+
line("");
|
|
7944
|
+
line(typeof run.output === "string" ? run.output : JSON.stringify(run.output, null, 2));
|
|
7945
|
+
}
|
|
7946
|
+
if (run?.error?.message) line(" " + import_picocolors17.default.red(run.error.message));
|
|
7947
|
+
}
|
|
7948
|
+
function formatDuration(ms) {
|
|
7949
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
7950
|
+
const seconds = Math.round(ms / 1e3);
|
|
7951
|
+
if (seconds < 60) return `${seconds}s`;
|
|
7952
|
+
const minutes = Math.floor(seconds / 60);
|
|
7953
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
7954
|
+
}
|
|
7955
|
+
function parsePairs(pairs, allowed) {
|
|
7956
|
+
const out = {};
|
|
7957
|
+
for (const raw of pairs) {
|
|
7958
|
+
const at = raw.indexOf("=");
|
|
7959
|
+
if (at < 1) {
|
|
7960
|
+
throw new Error(`"${raw}" is not a key=value pair.`);
|
|
7961
|
+
}
|
|
7962
|
+
const key = raw.slice(0, at).trim();
|
|
7963
|
+
const value = raw.slice(at + 1);
|
|
7964
|
+
if (!allowed.includes(key)) {
|
|
7965
|
+
throw new Error(`"${key}" is not a field here. Accepted: ${allowed.join(", ")}`);
|
|
7966
|
+
}
|
|
7967
|
+
if (value) out[key] = value;
|
|
7968
|
+
}
|
|
7969
|
+
return out;
|
|
7970
|
+
}
|
|
7971
|
+
|
|
7972
|
+
// src/commands/verify.ts
|
|
7973
|
+
var import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
7464
7974
|
function registerVerify(program3) {
|
|
7465
7975
|
program3.command("verify").description(
|
|
7466
7976
|
"Run the project's checks (typecheck/lint/build) \u2014 use before declaring a task done"
|
|
@@ -7482,23 +7992,23 @@ function registerVerify(program3) {
|
|
|
7482
7992
|
function printVerify(res) {
|
|
7483
7993
|
if (!res) return;
|
|
7484
7994
|
if (!res.checks?.length) {
|
|
7485
|
-
line(
|
|
7995
|
+
line(import_picocolors18.default.dim(res.note ?? "No checks detected."));
|
|
7486
7996
|
return;
|
|
7487
7997
|
}
|
|
7488
7998
|
for (const c of res.checks) {
|
|
7489
7999
|
line(
|
|
7490
|
-
` ${c.ok ?
|
|
8000
|
+
` ${c.ok ? import_picocolors18.default.green("\u2713") : import_picocolors18.default.red("\u2717")} ${c.name}${c.ok ? "" : import_picocolors18.default.dim(` (exit ${c.exitCode})`)}`
|
|
7491
8001
|
);
|
|
7492
8002
|
}
|
|
7493
8003
|
if (res.ok) success("All checks passed");
|
|
7494
8004
|
else
|
|
7495
8005
|
line(
|
|
7496
|
-
|
|
8006
|
+
import_picocolors18.default.red("Some checks failed \u2014 fix the errors above and re-run ") + import_picocolors18.default.bold("workser verify") + import_picocolors18.default.red(".")
|
|
7497
8007
|
);
|
|
7498
8008
|
}
|
|
7499
8009
|
|
|
7500
8010
|
// src/commands/checkpoint.ts
|
|
7501
|
-
var
|
|
8011
|
+
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
7502
8012
|
function registerCheckpoint(program3) {
|
|
7503
8013
|
program3.command("checkpoint [label]").description(
|
|
7504
8014
|
"Save the current state of this folder so you can come back to it"
|
|
@@ -7515,8 +8025,8 @@ function registerCheckpoint(program3) {
|
|
|
7515
8025
|
ok(res, () => {
|
|
7516
8026
|
const p = res?.point;
|
|
7517
8027
|
success(`Saved a checkpoint${p?.label ? `: ${p.label}` : ""}`);
|
|
7518
|
-
if (p?.ref) line(
|
|
7519
|
-
line(
|
|
8028
|
+
if (p?.ref) line(import_picocolors19.default.dim(` ${p.ref.slice(0, 7)}`));
|
|
8029
|
+
line(import_picocolors19.default.dim(" Come back to it with `workser restore`."));
|
|
7520
8030
|
});
|
|
7521
8031
|
})
|
|
7522
8032
|
);
|
|
@@ -7542,12 +8052,12 @@ function registerCheckpoint(program3) {
|
|
|
7542
8052
|
);
|
|
7543
8053
|
if (res?.filesChanged) {
|
|
7544
8054
|
line(
|
|
7545
|
-
|
|
8055
|
+
import_picocolors19.default.dim(
|
|
7546
8056
|
` ${res.filesChanged} file${res.filesChanged === 1 ? "" : "s"} changed`
|
|
7547
8057
|
)
|
|
7548
8058
|
);
|
|
7549
8059
|
}
|
|
7550
|
-
line(
|
|
8060
|
+
line(import_picocolors19.default.dim(" This is reversible: `workser restore` again."));
|
|
7551
8061
|
});
|
|
7552
8062
|
})
|
|
7553
8063
|
);
|
|
@@ -7564,25 +8074,25 @@ function registerCheckpoint(program3) {
|
|
|
7564
8074
|
function printPoints(points) {
|
|
7565
8075
|
if (!points.length) {
|
|
7566
8076
|
info("No checkpoints yet for this folder.");
|
|
7567
|
-
line(
|
|
8077
|
+
line(import_picocolors19.default.dim(" Take one with `workser checkpoint`."));
|
|
7568
8078
|
return;
|
|
7569
8079
|
}
|
|
7570
|
-
line(
|
|
8080
|
+
line(import_picocolors19.default.bold("Checkpoints"));
|
|
7571
8081
|
for (const p of points) {
|
|
7572
8082
|
const when = p.at ? new Date(p.at).toLocaleString() : "";
|
|
7573
8083
|
line(
|
|
7574
|
-
` ${
|
|
8084
|
+
` ${import_picocolors19.default.dim(p.ref.slice(0, 7))} ${p.label}${when ? import_picocolors19.default.dim(` ${when}`) : ""}`
|
|
7575
8085
|
);
|
|
7576
8086
|
}
|
|
7577
8087
|
line(
|
|
7578
|
-
|
|
8088
|
+
import_picocolors19.default.dim(
|
|
7579
8089
|
"\nGo back with `workser restore <ref>`, or just `workser restore` for the newest."
|
|
7580
8090
|
)
|
|
7581
8091
|
);
|
|
7582
8092
|
}
|
|
7583
8093
|
|
|
7584
8094
|
// src/commands/sync.ts
|
|
7585
|
-
var
|
|
8095
|
+
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
7586
8096
|
function registerSync(program3) {
|
|
7587
8097
|
program3.command("sync").description(
|
|
7588
8098
|
"Reconcile this folder with the copy Workser holds (pull, then push)"
|
|
@@ -7609,7 +8119,7 @@ function registerSync(program3) {
|
|
|
7609
8119
|
warn(res?.message ?? "Couldn't sync this folder.");
|
|
7610
8120
|
if (res?.state === "diverged") {
|
|
7611
8121
|
line(
|
|
7612
|
-
|
|
8122
|
+
import_picocolors20.default.dim(
|
|
7613
8123
|
" This folder and Workser's copy have both changed. Open Workser to resolve it."
|
|
7614
8124
|
)
|
|
7615
8125
|
);
|
|
@@ -7621,7 +8131,7 @@ function registerSync(program3) {
|
|
|
7621
8131
|
return;
|
|
7622
8132
|
}
|
|
7623
8133
|
success("Synced");
|
|
7624
|
-
if (res?.ref) line(
|
|
8134
|
+
if (res?.ref) line(import_picocolors20.default.dim(` ${String(res.ref).slice(0, 7)}`));
|
|
7625
8135
|
});
|
|
7626
8136
|
if (refused) process.exitCode = 1;
|
|
7627
8137
|
})
|
|
@@ -7629,7 +8139,7 @@ function registerSync(program3) {
|
|
|
7629
8139
|
}
|
|
7630
8140
|
|
|
7631
8141
|
// src/commands/workflow.ts
|
|
7632
|
-
var
|
|
8142
|
+
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
7633
8143
|
function registerWorkflow(program3) {
|
|
7634
8144
|
const wf = program3.command("workflow").description("Create, run, and inspect workflow automations for the project");
|
|
7635
8145
|
wf.command("list").description("List the project's workflows").action(
|
|
@@ -7637,10 +8147,10 @@ function registerWorkflow(program3) {
|
|
|
7637
8147
|
const projectId = requireProject(ctx);
|
|
7638
8148
|
const items = await api(ctx, `/v1/projects/${projectId}/workflows`);
|
|
7639
8149
|
ok(items, () => {
|
|
7640
|
-
if (!items?.length) return line(
|
|
8150
|
+
if (!items?.length) return line(import_picocolors21.default.dim("No workflows yet. `workser workflow create`."));
|
|
7641
8151
|
for (const w of items) {
|
|
7642
|
-
const status = w.is_active ?
|
|
7643
|
-
line(`${w.id} ${
|
|
8152
|
+
const status = w.is_active ? import_picocolors21.default.green("active") : import_picocolors21.default.dim("inactive");
|
|
8153
|
+
line(`${w.id} ${import_picocolors21.default.bold(w.name ?? "Untitled")} ${status}`);
|
|
7644
8154
|
}
|
|
7645
8155
|
});
|
|
7646
8156
|
})
|
|
@@ -7652,7 +8162,7 @@ function registerWorkflow(program3) {
|
|
|
7652
8162
|
const res = await api(ctx, `/v1/projects/${projectId}/workflows`, {
|
|
7653
8163
|
body: { name: args[0], ...extra }
|
|
7654
8164
|
});
|
|
7655
|
-
ok(res, () => line(`Created workflow ${
|
|
8165
|
+
ok(res, () => line(`Created workflow ${import_picocolors21.default.bold(res.id)}.`));
|
|
7656
8166
|
})
|
|
7657
8167
|
);
|
|
7658
8168
|
wf.command("get <id>").description("Show a workflow's full definition").action(
|
|
@@ -7687,8 +8197,8 @@ function registerWorkflow(program3) {
|
|
|
7687
8197
|
action(async ({ ctx, args }) => {
|
|
7688
8198
|
const items = await api(ctx, `/v1/workflows/${args[0]}/executions`);
|
|
7689
8199
|
ok(items, () => {
|
|
7690
|
-
if (!items?.length) return line(
|
|
7691
|
-
for (const e of items) line(`${e.id} ${e.status ?? ""} ${
|
|
8200
|
+
if (!items?.length) return line(import_picocolors21.default.dim("No runs yet."));
|
|
8201
|
+
for (const e of items) line(`${e.id} ${e.status ?? ""} ${import_picocolors21.default.dim(e.started_at ?? "")}`);
|
|
7692
8202
|
});
|
|
7693
8203
|
})
|
|
7694
8204
|
);
|
|
@@ -7696,15 +8206,15 @@ function registerWorkflow(program3) {
|
|
|
7696
8206
|
action(async ({ ctx, args }) => {
|
|
7697
8207
|
const items = await api(ctx, `/v1/node-types`, { query: { q: args[0] } });
|
|
7698
8208
|
ok(items, () => {
|
|
7699
|
-
if (!items?.length) return line(
|
|
7700
|
-
for (const n of items) line(`${n.name ?? n.type} ${
|
|
8209
|
+
if (!items?.length) return line(import_picocolors21.default.dim("No matching node types."));
|
|
8210
|
+
for (const n of items) line(`${n.name ?? n.type} ${import_picocolors21.default.dim(n.category ?? "")}`);
|
|
7701
8211
|
});
|
|
7702
8212
|
})
|
|
7703
8213
|
);
|
|
7704
8214
|
}
|
|
7705
8215
|
|
|
7706
8216
|
// src/commands/connection.ts
|
|
7707
|
-
var
|
|
8217
|
+
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
7708
8218
|
function registerConnection(program3) {
|
|
7709
8219
|
const connection = program3.command("connection").description("Connect and use third-party app connections (Gmail, Slack, Stripe, ...)");
|
|
7710
8220
|
connection.command("list").description("List connectable toolkits and this project's existing connections").option("--toolkit <slug>", "filter connections to one toolkit").action(
|
|
@@ -7717,8 +8227,8 @@ function registerConnection(program3) {
|
|
|
7717
8227
|
ok({ catalog, connections }, () => {
|
|
7718
8228
|
const connected = new Set((connections ?? []).map((c) => c.toolkit ?? c.composio_app));
|
|
7719
8229
|
for (const t of catalog ?? []) {
|
|
7720
|
-
const status = connected.has(t.slug) ?
|
|
7721
|
-
line(`${t.slug} ${
|
|
8230
|
+
const status = connected.has(t.slug) ? import_picocolors22.default.green("connected") : import_picocolors22.default.dim("not connected");
|
|
8231
|
+
line(`${t.slug} ${import_picocolors22.default.bold(t.name ?? t.slug)} ${status}`);
|
|
7722
8232
|
}
|
|
7723
8233
|
});
|
|
7724
8234
|
})
|
|
@@ -7730,9 +8240,9 @@ function registerConnection(program3) {
|
|
|
7730
8240
|
query: { q: args[0], toolkit: opts.toolkit, limit: opts.limit }
|
|
7731
8241
|
});
|
|
7732
8242
|
ok(items, () => {
|
|
7733
|
-
if (!items?.length) return line(
|
|
8243
|
+
if (!items?.length) return line(import_picocolors22.default.dim("No matching actions."));
|
|
7734
8244
|
for (const t of items) {
|
|
7735
|
-
line(`${t.slug} ${
|
|
8245
|
+
line(`${t.slug} ${import_picocolors22.default.dim(`[${t.toolkit}]`)} ${t.description ?? ""}`);
|
|
7736
8246
|
}
|
|
7737
8247
|
});
|
|
7738
8248
|
})
|
|
@@ -7749,7 +8259,7 @@ function registerConnection(program3) {
|
|
|
7749
8259
|
});
|
|
7750
8260
|
ok(
|
|
7751
8261
|
res,
|
|
7752
|
-
() => res.oauth_url ? line(`Open this URL to finish connecting: ${
|
|
8262
|
+
() => res.oauth_url ? line(`Open this URL to finish connecting: ${import_picocolors22.default.underline(res.oauth_url)}`) : line(`Connection ${res.connection_id} is ${res.status}.`)
|
|
7753
8263
|
);
|
|
7754
8264
|
})
|
|
7755
8265
|
);
|
|
@@ -7767,8 +8277,8 @@ function registerConnection(program3) {
|
|
|
7767
8277
|
const projectId = requireProject(ctx);
|
|
7768
8278
|
const items = await api(ctx, `/v1/projects/${projectId}/integrations/${args[0]}/tools`);
|
|
7769
8279
|
ok(items, () => {
|
|
7770
|
-
if (!items?.length) return line(
|
|
7771
|
-
for (const t of items) line(`${t.slug} ${
|
|
8280
|
+
if (!items?.length) return line(import_picocolors22.default.dim("No tools found."));
|
|
8281
|
+
for (const t of items) line(`${t.slug} ${import_picocolors22.default.dim(t.description ?? "")}`);
|
|
7772
8282
|
});
|
|
7773
8283
|
})
|
|
7774
8284
|
);
|
|
@@ -7784,7 +8294,7 @@ function registerConnection(program3) {
|
|
|
7784
8294
|
}
|
|
7785
8295
|
|
|
7786
8296
|
// src/commands/tool.ts
|
|
7787
|
-
var
|
|
8297
|
+
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
7788
8298
|
function registerTool(program3) {
|
|
7789
8299
|
const tool = program3.command("tool").description(
|
|
7790
8300
|
"Computer-use tools: filesystem, shell, screenshot, input control, clipboard, notifications, basic browser"
|
|
@@ -7793,7 +8303,7 @@ function registerTool(program3) {
|
|
|
7793
8303
|
action(async ({ ctx }) => {
|
|
7794
8304
|
const tools = await api(ctx, "/v1/tool/list");
|
|
7795
8305
|
ok(tools, () => {
|
|
7796
|
-
if (!tools?.length) return line(
|
|
8306
|
+
if (!tools?.length) return line(import_picocolors23.default.dim("No tools available."));
|
|
7797
8307
|
const byCategory = /* @__PURE__ */ new Map();
|
|
7798
8308
|
for (const t of tools) {
|
|
7799
8309
|
const list = byCategory.get(t.category) ?? [];
|
|
@@ -7801,9 +8311,9 @@ function registerTool(program3) {
|
|
|
7801
8311
|
byCategory.set(t.category, list);
|
|
7802
8312
|
}
|
|
7803
8313
|
for (const [category, items] of byCategory) {
|
|
7804
|
-
line(
|
|
8314
|
+
line(import_picocolors23.default.bold(category) + ":");
|
|
7805
8315
|
for (const t of items) {
|
|
7806
|
-
line(` ${t.name} ${
|
|
8316
|
+
line(` ${t.name} ${import_picocolors23.default.dim(t.description ?? "")}`);
|
|
7807
8317
|
}
|
|
7808
8318
|
}
|
|
7809
8319
|
});
|
|
@@ -7821,7 +8331,7 @@ function registerTool(program3) {
|
|
|
7821
8331
|
}
|
|
7822
8332
|
|
|
7823
8333
|
// src/commands/memory.ts
|
|
7824
|
-
var
|
|
8334
|
+
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
7825
8335
|
function registerMemory(program3) {
|
|
7826
8336
|
const memory = program3.command("memory").description("Durable, cross-conversation project memory (shared with cloud agents on the same project)");
|
|
7827
8337
|
memory.command("add <content>").description("Store something worth remembering across future conversations").option("--metadata <json>", "extra metadata for filtering, as a JSON string").option("--id <customId>", "custom id for dedup/updates").action(
|
|
@@ -7845,9 +8355,9 @@ function registerMemory(program3) {
|
|
|
7845
8355
|
});
|
|
7846
8356
|
ok(res, () => {
|
|
7847
8357
|
const results = res?.results ?? res ?? [];
|
|
7848
|
-
if (!results?.length) return line(
|
|
8358
|
+
if (!results?.length) return line(import_picocolors24.default.dim("No matching memories."));
|
|
7849
8359
|
for (const r of results) {
|
|
7850
|
-
line(`${
|
|
8360
|
+
line(`${import_picocolors24.default.dim(r.id ?? "?")} ${memoryText(r)}`);
|
|
7851
8361
|
}
|
|
7852
8362
|
});
|
|
7853
8363
|
})
|
|
@@ -7867,11 +8377,11 @@ function memoryText(r) {
|
|
|
7867
8377
|
if (typeof text === "string" && text.trim()) return text;
|
|
7868
8378
|
const title = r?.documents?.[0]?.title;
|
|
7869
8379
|
if (typeof title === "string" && title.trim()) return title;
|
|
7870
|
-
return
|
|
8380
|
+
return import_picocolors24.default.dim("(no readable text on this row)");
|
|
7871
8381
|
}
|
|
7872
8382
|
|
|
7873
8383
|
// src/commands/note.ts
|
|
7874
|
-
var
|
|
8384
|
+
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
7875
8385
|
function registerNote(program3) {
|
|
7876
8386
|
program3.command("note <text>").description("Leave a fact the rest of the team will need").addHelpText(
|
|
7877
8387
|
"after",
|
|
@@ -7908,14 +8418,14 @@ function registerNote(program3) {
|
|
|
7908
8418
|
}
|
|
7909
8419
|
ok(res, () => {
|
|
7910
8420
|
success("Noted for the team.");
|
|
7911
|
-
line(
|
|
8421
|
+
line(import_picocolors25.default.dim(` ${text}`));
|
|
7912
8422
|
});
|
|
7913
8423
|
})
|
|
7914
8424
|
);
|
|
7915
8425
|
}
|
|
7916
8426
|
|
|
7917
8427
|
// src/commands/business.ts
|
|
7918
|
-
var
|
|
8428
|
+
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
7919
8429
|
var RESOURCE_PATHS = {
|
|
7920
8430
|
"business-config": "business-config",
|
|
7921
8431
|
"business-settings": "business-settings",
|
|
@@ -7975,7 +8485,7 @@ function registerBusiness(program3) {
|
|
|
7975
8485
|
const projectId = requireProject(ctx);
|
|
7976
8486
|
const [resource] = args;
|
|
7977
8487
|
const res = await api(ctx, businessPath(projectId, resource), { body: JSON.parse(opts.body) });
|
|
7978
|
-
ok(res, () => line(`Created ${resource} ${
|
|
8488
|
+
ok(res, () => line(`Created ${resource} ${import_picocolors26.default.bold(res?.id ?? "")}.`));
|
|
7979
8489
|
})
|
|
7980
8490
|
);
|
|
7981
8491
|
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(
|
|
@@ -8017,7 +8527,7 @@ function businessPath(projectId, resource, subpath) {
|
|
|
8017
8527
|
}
|
|
8018
8528
|
|
|
8019
8529
|
// src/commands/artifact.ts
|
|
8020
|
-
var
|
|
8530
|
+
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
8021
8531
|
import { existsSync as existsSync2, statSync } from "fs";
|
|
8022
8532
|
import { resolve as resolve3, basename as basename3 } from "path";
|
|
8023
8533
|
var KINDS = [
|
|
@@ -8114,7 +8624,7 @@ function registerArtifact(program3) {
|
|
|
8114
8624
|
ok(
|
|
8115
8625
|
res,
|
|
8116
8626
|
() => success(
|
|
8117
|
-
`Recorded ${
|
|
8627
|
+
`Recorded ${import_picocolors27.default.bold(res?.title ?? "artifact")}${res?.kind ? import_picocolors27.default.dim(` (${res.kind})`) : ""}`
|
|
8118
8628
|
)
|
|
8119
8629
|
);
|
|
8120
8630
|
})
|
|
@@ -8146,13 +8656,13 @@ function registerArtifact(program3) {
|
|
|
8146
8656
|
artifact.command("run").description("Show the task/conversation this agent run is attached to").action(
|
|
8147
8657
|
action(async ({ ctx }) => {
|
|
8148
8658
|
const res = await api(ctx, `/v1/runs/${runTarget(ctx)}`);
|
|
8149
|
-
ok(res, () =>
|
|
8659
|
+
ok(res, () => printRun2(res));
|
|
8150
8660
|
})
|
|
8151
8661
|
);
|
|
8152
8662
|
}
|
|
8153
8663
|
function printArtifacts(rows) {
|
|
8154
8664
|
if (!rows.length) {
|
|
8155
|
-
line(
|
|
8665
|
+
line(import_picocolors27.default.dim("Nothing produced yet."));
|
|
8156
8666
|
return;
|
|
8157
8667
|
}
|
|
8158
8668
|
const byStep = /* @__PURE__ */ new Map();
|
|
@@ -8162,26 +8672,26 @@ function printArtifacts(rows) {
|
|
|
8162
8672
|
byStep.set(r.subtask_id, list);
|
|
8163
8673
|
}
|
|
8164
8674
|
for (const [stepId, items] of byStep) {
|
|
8165
|
-
line(
|
|
8675
|
+
line(import_picocolors27.default.bold(`step ${stepId}`));
|
|
8166
8676
|
for (const a of items) {
|
|
8167
|
-
const flag = a.promoted_at ?
|
|
8677
|
+
const flag = a.promoted_at ? import_picocolors27.default.green(" *") : " ";
|
|
8168
8678
|
const where = a.local_path || a.cloud_url || "";
|
|
8169
8679
|
line(
|
|
8170
|
-
`${flag} ${
|
|
8680
|
+
`${flag} ${import_picocolors27.default.dim(`[${a.kind}]`)} ${a.title ?? "(untitled)"}` + (where ? import_picocolors27.default.dim(` ${where}`) : "")
|
|
8171
8681
|
);
|
|
8172
|
-
if (a.description) line(
|
|
8682
|
+
if (a.description) line(import_picocolors27.default.dim(` ${a.description}`));
|
|
8173
8683
|
}
|
|
8174
8684
|
line("");
|
|
8175
8685
|
}
|
|
8176
|
-
line(
|
|
8686
|
+
line(import_picocolors27.default.dim("* = handed over as a deliverable; the rest is working material."));
|
|
8177
8687
|
}
|
|
8178
|
-
function
|
|
8688
|
+
function printRun2(run) {
|
|
8179
8689
|
if (!run) return;
|
|
8180
|
-
line(` run ${
|
|
8690
|
+
line(` run ${import_picocolors27.default.bold(run.runId)}`);
|
|
8181
8691
|
if (run.taskId) line(` task ${run.taskId}`);
|
|
8182
8692
|
if (run.conversationId) line(` chat ${run.conversationId}`);
|
|
8183
8693
|
if (run.projectId) line(` project ${run.projectId}`);
|
|
8184
|
-
if (run.cwd) line(` folder ${
|
|
8694
|
+
if (run.cwd) line(` folder ${import_picocolors27.default.dim(run.cwd)}`);
|
|
8185
8695
|
}
|
|
8186
8696
|
|
|
8187
8697
|
// src/commands/image.ts
|
|
@@ -8259,7 +8769,7 @@ function registerImage(program3) {
|
|
|
8259
8769
|
);
|
|
8260
8770
|
const res = await api(
|
|
8261
8771
|
ctx,
|
|
8262
|
-
`/projects/${projectId}/images/generate`,
|
|
8772
|
+
`/v1/projects/${projectId}/images/generate`,
|
|
8263
8773
|
{
|
|
8264
8774
|
method: "POST",
|
|
8265
8775
|
body: {
|
|
@@ -8299,7 +8809,7 @@ function registerImage(program3) {
|
|
|
8299
8809
|
action(async ({ ctx, opts, args }) => {
|
|
8300
8810
|
const projectId = requireProject(ctx);
|
|
8301
8811
|
const source = await resolveMediaSource({ url: opts.url, file: opts.file });
|
|
8302
|
-
const res = await api(ctx, `/projects/${projectId}/images/understand`, {
|
|
8812
|
+
const res = await api(ctx, `/v1/projects/${projectId}/images/understand`, {
|
|
8303
8813
|
method: "POST",
|
|
8304
8814
|
body: { source, query: args[0], task: opts.task }
|
|
8305
8815
|
});
|
|
@@ -8332,7 +8842,7 @@ function registerVideo(program3) {
|
|
|
8332
8842
|
action(async ({ ctx, opts, args }) => {
|
|
8333
8843
|
const projectId = requireProject(ctx);
|
|
8334
8844
|
const source = await resolveMediaSource({ url: opts.url, file: opts.file });
|
|
8335
|
-
const res = await api(ctx, `/projects/${projectId}/video/understand`, {
|
|
8845
|
+
const res = await api(ctx, `/v1/projects/${projectId}/video/understand`, {
|
|
8336
8846
|
method: "POST",
|
|
8337
8847
|
body: { source, query: args[0], task: opts.task }
|
|
8338
8848
|
});
|
|
@@ -8352,7 +8862,7 @@ function registerAudio(program3) {
|
|
|
8352
8862
|
action(async ({ ctx, opts, args }) => {
|
|
8353
8863
|
const projectId = requireProject(ctx);
|
|
8354
8864
|
const source = await resolveMediaSource({ url: opts.url, file: opts.file });
|
|
8355
|
-
const res = await api(ctx, `/projects/${projectId}/audio/understand`, {
|
|
8865
|
+
const res = await api(ctx, `/v1/projects/${projectId}/audio/understand`, {
|
|
8356
8866
|
method: "POST",
|
|
8357
8867
|
body: { source, query: args[0], task: opts.task }
|
|
8358
8868
|
});
|
|
@@ -8362,7 +8872,7 @@ function registerAudio(program3) {
|
|
|
8362
8872
|
}
|
|
8363
8873
|
|
|
8364
8874
|
// src/commands/ask.ts
|
|
8365
|
-
var
|
|
8875
|
+
var import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
8366
8876
|
var TYPES = [
|
|
8367
8877
|
"input",
|
|
8368
8878
|
"choice",
|
|
@@ -8440,7 +8950,7 @@ function registerAsk(program3) {
|
|
|
8440
8950
|
code: "bad_request"
|
|
8441
8951
|
});
|
|
8442
8952
|
}
|
|
8443
|
-
info(
|
|
8953
|
+
info(import_picocolors28.default.dim("Waiting for the user to answer\u2026"));
|
|
8444
8954
|
const res = await api(ctx, `/v1/runs/${runTarget(ctx)}/ask`, {
|
|
8445
8955
|
body: {
|
|
8446
8956
|
type,
|
|
@@ -8468,12 +8978,12 @@ function deriveTitle(message) {
|
|
|
8468
8978
|
function printAnswer(res) {
|
|
8469
8979
|
if (!res) return;
|
|
8470
8980
|
if (res.status === "answered") {
|
|
8471
|
-
line(` ${
|
|
8981
|
+
line(` ${import_picocolors28.default.green("answered")}`);
|
|
8472
8982
|
const value = extract(res.response);
|
|
8473
8983
|
if (value) line(` ${value}`);
|
|
8474
8984
|
return;
|
|
8475
8985
|
}
|
|
8476
|
-
line(` ${
|
|
8986
|
+
line(` ${import_picocolors28.default.yellow(res.status)} ${import_picocolors28.default.dim(res.reason ?? "")}`);
|
|
8477
8987
|
}
|
|
8478
8988
|
function extract(response) {
|
|
8479
8989
|
if (response == null) return "";
|
|
@@ -8492,7 +9002,7 @@ function extract(response) {
|
|
|
8492
9002
|
}
|
|
8493
9003
|
|
|
8494
9004
|
// src/commands/search.ts
|
|
8495
|
-
var
|
|
9005
|
+
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
8496
9006
|
function registerSearch(program3) {
|
|
8497
9007
|
program3.command("search <query>").description("Search the web (Google-grounded, server-side)").option("-n, --max-results <n>", "max results", "5").action(
|
|
8498
9008
|
action(async ({ ctx, args, opts }) => {
|
|
@@ -8505,9 +9015,9 @@ function registerSearch(program3) {
|
|
|
8505
9015
|
line("");
|
|
8506
9016
|
}
|
|
8507
9017
|
const results = res?.results ?? [];
|
|
8508
|
-
if (!results.length) return line(
|
|
9018
|
+
if (!results.length) return line(import_picocolors29.default.dim("No results."));
|
|
8509
9019
|
for (const r of results) {
|
|
8510
|
-
line(`${r.title ||
|
|
9020
|
+
line(`${r.title || import_picocolors29.default.dim("(untitled)")} ${import_picocolors29.default.dim(r.url)}`);
|
|
8511
9021
|
}
|
|
8512
9022
|
});
|
|
8513
9023
|
})
|
|
@@ -8515,7 +9025,7 @@ function registerSearch(program3) {
|
|
|
8515
9025
|
}
|
|
8516
9026
|
|
|
8517
9027
|
// src/commands/board.ts
|
|
8518
|
-
var
|
|
9028
|
+
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
8519
9029
|
|
|
8520
9030
|
// src/commands/record-step.ts
|
|
8521
9031
|
async function recordEntityStep(ctx, opts) {
|
|
@@ -8554,7 +9064,7 @@ function registerBoard(program3) {
|
|
|
8554
9064
|
}
|
|
8555
9065
|
ok(rows, () => {
|
|
8556
9066
|
if (!rows.length) {
|
|
8557
|
-
line(
|
|
9067
|
+
line(import_picocolors30.default.dim("No cards on the Board yet."));
|
|
8558
9068
|
return;
|
|
8559
9069
|
}
|
|
8560
9070
|
for (const r of rows) line(formatRow(r));
|
|
@@ -8569,7 +9079,7 @@ function registerBoard(program3) {
|
|
|
8569
9079
|
`/v1/projects/${projectId}/work-items/${args[0]}`
|
|
8570
9080
|
);
|
|
8571
9081
|
ok(row, () => {
|
|
8572
|
-
line(`${
|
|
9082
|
+
line(`${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.id)}`);
|
|
8573
9083
|
line(`${statusTag(row.status)} priority ${row.priority}`);
|
|
8574
9084
|
if (row.ownerHuman) line(`owner: ${row.ownerHuman}`);
|
|
8575
9085
|
if (row.labels?.length) line(`labels: ${row.labels.join(", ")}`);
|
|
@@ -8610,7 +9120,7 @@ ${row.description}`);
|
|
|
8610
9120
|
refId: row?.id,
|
|
8611
9121
|
output: { workItem: row }
|
|
8612
9122
|
});
|
|
8613
|
-
ok(row, () => line(`Created work item ${
|
|
9123
|
+
ok(row, () => line(`Created work item ${import_picocolors30.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
8614
9124
|
})
|
|
8615
9125
|
);
|
|
8616
9126
|
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(
|
|
@@ -8644,7 +9154,7 @@ ${row.description}`);
|
|
|
8644
9154
|
);
|
|
8645
9155
|
}
|
|
8646
9156
|
const row = await patchItem(ctx, projectId, String(args[0]), body);
|
|
8647
|
-
ok(row, () => line(`Updated ${
|
|
9157
|
+
ok(row, () => line(`Updated ${import_picocolors30.default.bold(row.id)} \u2014 ${row.title} ${statusTag(row.status)}`));
|
|
8648
9158
|
})
|
|
8649
9159
|
);
|
|
8650
9160
|
board.command("move <id> <status>").description(
|
|
@@ -8655,14 +9165,14 @@ ${row.description}`);
|
|
|
8655
9165
|
const status = String(args[1]);
|
|
8656
9166
|
assertStatus(status);
|
|
8657
9167
|
const row = await patchItem(ctx, projectId, String(args[0]), { status });
|
|
8658
|
-
ok(row, () => line(`Moved ${
|
|
9168
|
+
ok(row, () => line(`Moved ${import_picocolors30.default.bold(row.title)} \u2192 ${statusTag(row.status)}`));
|
|
8659
9169
|
})
|
|
8660
9170
|
);
|
|
8661
9171
|
board.command("close <id>").description("Shorthand for `board move <id> done`").action(
|
|
8662
9172
|
action(async ({ ctx, args }) => {
|
|
8663
9173
|
const projectId = requireProject(ctx);
|
|
8664
9174
|
const row = await patchItem(ctx, projectId, String(args[0]), { status: "done" });
|
|
8665
|
-
ok(row, () => line(`Closed ${
|
|
9175
|
+
ok(row, () => line(`Closed ${import_picocolors30.default.bold(row.title)} ${statusTag(row.status)}`));
|
|
8666
9176
|
})
|
|
8667
9177
|
);
|
|
8668
9178
|
}
|
|
@@ -8695,23 +9205,23 @@ function assertPriority(value) {
|
|
|
8695
9205
|
}
|
|
8696
9206
|
}
|
|
8697
9207
|
function formatRow(r) {
|
|
8698
|
-
const labels = r.labels?.length ?
|
|
8699
|
-
const owner = r.ownerHuman ?
|
|
8700
|
-
return `${
|
|
9208
|
+
const labels = r.labels?.length ? import_picocolors30.default.dim(` [${r.labels.join(", ")}]`) : "";
|
|
9209
|
+
const owner = r.ownerHuman ? import_picocolors30.default.dim(` @${r.ownerHuman}`) : "";
|
|
9210
|
+
return `${import_picocolors30.default.dim(r.id)} ${statusTag(r.status)} ${r.title}${labels}${owner}`;
|
|
8701
9211
|
}
|
|
8702
9212
|
function statusTag(status) {
|
|
8703
9213
|
const label = status.padEnd(11);
|
|
8704
|
-
if (status === "done") return
|
|
8705
|
-
if (status === "in-progress") return
|
|
8706
|
-
if (status === "in-review") return
|
|
8707
|
-
return
|
|
9214
|
+
if (status === "done") return import_picocolors30.default.green(label);
|
|
9215
|
+
if (status === "in-progress") return import_picocolors30.default.yellow(label);
|
|
9216
|
+
if (status === "in-review") return import_picocolors30.default.cyan(label);
|
|
9217
|
+
return import_picocolors30.default.dim(label);
|
|
8708
9218
|
}
|
|
8709
9219
|
function collect2(value, previous) {
|
|
8710
9220
|
return [...previous, value];
|
|
8711
9221
|
}
|
|
8712
9222
|
|
|
8713
9223
|
// src/commands/task.ts
|
|
8714
|
-
var
|
|
9224
|
+
var import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
8715
9225
|
|
|
8716
9226
|
// src/subtask-attachments.ts
|
|
8717
9227
|
var MAX_REF_NOTE = 500;
|
|
@@ -8773,6 +9283,7 @@ var STATUSES2 = [
|
|
|
8773
9283
|
];
|
|
8774
9284
|
var PRIORITIES2 = ["urgent", "high", "normal", "low"];
|
|
8775
9285
|
var SIZES = ["small", "standard"];
|
|
9286
|
+
var ESTIMATES = ["10m", "30m", "45m", "1h", "1h+"];
|
|
8776
9287
|
var ROLES = [
|
|
8777
9288
|
"pm",
|
|
8778
9289
|
"architect",
|
|
@@ -8825,7 +9336,7 @@ function registerTask(program3) {
|
|
|
8825
9336
|
}) ?? [];
|
|
8826
9337
|
ok(rows, () => {
|
|
8827
9338
|
if (!rows.length) {
|
|
8828
|
-
line(
|
|
9339
|
+
line(import_picocolors31.default.dim("No tasks on the board yet."));
|
|
8829
9340
|
return;
|
|
8830
9341
|
}
|
|
8831
9342
|
for (const r of rows) line(formatRow2(r));
|
|
@@ -8855,6 +9366,9 @@ function registerTask(program3) {
|
|
|
8855
9366
|
).option("--priority <value>", `how urgent (${PRIORITIES2.join(" | ")})`).option(
|
|
8856
9367
|
"--size <value>",
|
|
8857
9368
|
`small lets the channel start it without asking; standard asks (${SIZES.join(" | ")})`
|
|
9369
|
+
).option(
|
|
9370
|
+
"--estimate <value>",
|
|
9371
|
+
`roughly how long this should take, shown on the plan (${ESTIMATES.join(" | ")})`
|
|
8858
9372
|
).option(
|
|
8859
9373
|
"--status <value>",
|
|
8860
9374
|
`start it somewhere other than 'todo' \u2014 use 'backlog' for a later phase's work (${STATUSES2.join(" | ")})`
|
|
@@ -8865,6 +9379,8 @@ function registerTask(program3) {
|
|
|
8865
9379
|
if (opts.priority !== void 0)
|
|
8866
9380
|
assertOneOf("--priority", opts.priority, PRIORITIES2);
|
|
8867
9381
|
if (opts.size !== void 0) assertOneOf("--size", opts.size, SIZES);
|
|
9382
|
+
if (opts.estimate !== void 0)
|
|
9383
|
+
assertOneOf("--estimate", opts.estimate, ESTIMATES);
|
|
8868
9384
|
if (opts.status !== void 0)
|
|
8869
9385
|
assertOneOf("--status", opts.status, STATUSES2);
|
|
8870
9386
|
const hasChannelOrigin = Boolean(
|
|
@@ -8882,6 +9398,7 @@ function registerTask(program3) {
|
|
|
8882
9398
|
phase: opts.phase,
|
|
8883
9399
|
priority: opts.priority,
|
|
8884
9400
|
size: opts.size,
|
|
9401
|
+
estimate: opts.estimate,
|
|
8885
9402
|
// `backlog` for a later phase's work: written down so the owner can
|
|
8886
9403
|
// read the whole plan, with nothing for the runner to pick up.
|
|
8887
9404
|
status: opts.status,
|
|
@@ -8934,10 +9451,10 @@ function registerTask(program3) {
|
|
|
8934
9451
|
};
|
|
8935
9452
|
ok(result, () => {
|
|
8936
9453
|
line(
|
|
8937
|
-
`${
|
|
9454
|
+
`${import_picocolors31.default.green("opened")} ${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.key ?? row.id)}`
|
|
8938
9455
|
);
|
|
8939
9456
|
if (channelMessage)
|
|
8940
|
-
line(
|
|
9457
|
+
line(import_picocolors31.default.dim("posted to the channel as Project Manager"));
|
|
8941
9458
|
if (channelMessageError) {
|
|
8942
9459
|
warn(
|
|
8943
9460
|
`Task opened, but its Project Manager card could not be posted: ${channelMessageError.message}`
|
|
@@ -9016,12 +9533,12 @@ function registerTask(program3) {
|
|
|
9016
9533
|
) : null;
|
|
9017
9534
|
ok(runner ?? row, () => {
|
|
9018
9535
|
line(
|
|
9019
|
-
`${
|
|
9536
|
+
`${import_picocolors31.default.green("added")} ${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.key ?? row.id)}`
|
|
9020
9537
|
);
|
|
9021
|
-
if (row.role) line(
|
|
9538
|
+
if (row.role) line(import_picocolors31.default.dim(`role: ${row.role}`));
|
|
9022
9539
|
if (runner) {
|
|
9023
9540
|
line(
|
|
9024
|
-
|
|
9541
|
+
import_picocolors31.default.dim(
|
|
9025
9542
|
`runs on: ${[opts.agent, opts.model, opts.effort].filter(Boolean).join(" \xB7 ")}`
|
|
9026
9543
|
)
|
|
9027
9544
|
);
|
|
@@ -9039,7 +9556,7 @@ function registerTask(program3) {
|
|
|
9039
9556
|
const rows = row.subtasks ?? [];
|
|
9040
9557
|
ok(rows, () => {
|
|
9041
9558
|
if (!rows.length) {
|
|
9042
|
-
line(
|
|
9559
|
+
line(import_picocolors31.default.dim("No subtasks yet."));
|
|
9043
9560
|
return;
|
|
9044
9561
|
}
|
|
9045
9562
|
rows.forEach((r, i) => line(formatSubtask(r, i + 1)));
|
|
@@ -9087,7 +9604,7 @@ function registerTask(program3) {
|
|
|
9087
9604
|
}
|
|
9088
9605
|
}
|
|
9089
9606
|
);
|
|
9090
|
-
ok(row, () => line(`${
|
|
9607
|
+
ok(row, () => line(`${import_picocolors31.default.green("updated")} ${import_picocolors31.default.bold(row.title)}`));
|
|
9091
9608
|
})
|
|
9092
9609
|
);
|
|
9093
9610
|
subtask.command("remove <id>").description("Remove a subtask (only before the work starts)").action(
|
|
@@ -9095,7 +9612,7 @@ function registerTask(program3) {
|
|
|
9095
9612
|
await api(ctx, `/v1/project-tasks/${encodeURIComponent(args[0])}`, {
|
|
9096
9613
|
method: "DELETE"
|
|
9097
9614
|
});
|
|
9098
|
-
ok({ removed: args[0] }, () => line(
|
|
9615
|
+
ok({ removed: args[0] }, () => line(import_picocolors31.default.green("removed")));
|
|
9099
9616
|
})
|
|
9100
9617
|
);
|
|
9101
9618
|
task.command("move <id> <status>").description(
|
|
@@ -9110,7 +9627,7 @@ function registerTask(program3) {
|
|
|
9110
9627
|
);
|
|
9111
9628
|
ok(
|
|
9112
9629
|
row,
|
|
9113
|
-
() => line(`${
|
|
9630
|
+
() => line(`${import_picocolors31.default.green("moved")} ${import_picocolors31.default.bold(row.title)} \u2192 ${args[1]}`)
|
|
9114
9631
|
);
|
|
9115
9632
|
})
|
|
9116
9633
|
);
|
|
@@ -9126,18 +9643,18 @@ function registerTask(program3) {
|
|
|
9126
9643
|
);
|
|
9127
9644
|
ok(row, () => {
|
|
9128
9645
|
if (!row?.queued) {
|
|
9129
|
-
line(
|
|
9646
|
+
line(import_picocolors31.default.yellow("could not resume it \u2014 check the step id"));
|
|
9130
9647
|
return;
|
|
9131
9648
|
}
|
|
9132
9649
|
const started = row.started ?? 0;
|
|
9133
9650
|
if (started > 0) {
|
|
9134
9651
|
line(
|
|
9135
|
-
`${
|
|
9652
|
+
`${import_picocolors31.default.green("resumed")} \u2014 ${started} step${started === 1 ? "" : "s"} started`
|
|
9136
9653
|
);
|
|
9137
9654
|
return;
|
|
9138
9655
|
}
|
|
9139
9656
|
line(
|
|
9140
|
-
`${
|
|
9657
|
+
`${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.`
|
|
9141
9658
|
);
|
|
9142
9659
|
});
|
|
9143
9660
|
})
|
|
@@ -9151,11 +9668,11 @@ function registerTask(program3) {
|
|
|
9151
9668
|
);
|
|
9152
9669
|
ok(row, () => {
|
|
9153
9670
|
if (row?.reopened) {
|
|
9154
|
-
line(`${
|
|
9671
|
+
line(`${import_picocolors31.default.green("sent back")} \u2014 it will be picked up again`);
|
|
9155
9672
|
return;
|
|
9156
9673
|
}
|
|
9157
9674
|
line(
|
|
9158
|
-
|
|
9675
|
+
import_picocolors31.default.yellow(
|
|
9159
9676
|
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"
|
|
9160
9677
|
)
|
|
9161
9678
|
);
|
|
@@ -9172,7 +9689,7 @@ function registerTask(program3) {
|
|
|
9172
9689
|
`/v1/project-tasks/${encodeURIComponent(id)}/dispatch-check`,
|
|
9173
9690
|
{ method: "POST" }
|
|
9174
9691
|
);
|
|
9175
|
-
ok(row, () => line(
|
|
9692
|
+
ok(row, () => line(import_picocolors31.default.green("approved \u2014 you may start")));
|
|
9176
9693
|
})
|
|
9177
9694
|
);
|
|
9178
9695
|
task.command("start [id]").description(
|
|
@@ -9187,13 +9704,13 @@ function registerTask(program3) {
|
|
|
9187
9704
|
const started = row?.started ?? null;
|
|
9188
9705
|
if (started && started > 0) {
|
|
9189
9706
|
line(
|
|
9190
|
-
|
|
9707
|
+
import_picocolors31.default.green(
|
|
9191
9708
|
`started ${started} step${started === 1 ? "" : "s"} \u2014 they are running now`
|
|
9192
9709
|
)
|
|
9193
9710
|
);
|
|
9194
9711
|
return;
|
|
9195
9712
|
}
|
|
9196
|
-
line(
|
|
9713
|
+
line(import_picocolors31.default.yellow(row?.note ?? "Nothing started."));
|
|
9197
9714
|
});
|
|
9198
9715
|
})
|
|
9199
9716
|
);
|
|
@@ -9208,7 +9725,7 @@ function registerTask(program3) {
|
|
|
9208
9725
|
);
|
|
9209
9726
|
ok({ awaiting: row2.approval_state === "awaiting", task: row2 }, () => {
|
|
9210
9727
|
line(
|
|
9211
|
-
row2.approval_state === "awaiting" ?
|
|
9728
|
+
row2.approval_state === "awaiting" ? import_picocolors31.default.yellow(
|
|
9212
9729
|
"The plan is waiting on the owner. They see it in the task."
|
|
9213
9730
|
) : `Already ${row2.approval_state}.`
|
|
9214
9731
|
);
|
|
@@ -9233,7 +9750,7 @@ function registerTask(program3) {
|
|
|
9233
9750
|
);
|
|
9234
9751
|
ok(
|
|
9235
9752
|
row,
|
|
9236
|
-
() => line(`${
|
|
9753
|
+
() => line(`${import_picocolors31.default.green(row.approval_state)} ${import_picocolors31.default.bold(row.title)}`)
|
|
9237
9754
|
);
|
|
9238
9755
|
})
|
|
9239
9756
|
);
|
|
@@ -9249,7 +9766,7 @@ function registerTask(program3) {
|
|
|
9249
9766
|
`/v1/project-tasks/${encodeURIComponent(id)}/move`,
|
|
9250
9767
|
{ body: { status: "ready" } }
|
|
9251
9768
|
);
|
|
9252
|
-
ok(row, () => line(`${
|
|
9769
|
+
ok(row, () => line(`${import_picocolors31.default.green("ready")} ${import_picocolors31.default.bold(row.title)}`));
|
|
9253
9770
|
})
|
|
9254
9771
|
);
|
|
9255
9772
|
}
|
|
@@ -9294,24 +9811,24 @@ function assertOneOf(flag, value, allowed) {
|
|
|
9294
9811
|
}
|
|
9295
9812
|
}
|
|
9296
9813
|
function formatRow2(r) {
|
|
9297
|
-
const key =
|
|
9298
|
-
const steps = r.subtaskTotal ?
|
|
9299
|
-
const gate = r.approval_state === "awaiting" ?
|
|
9814
|
+
const key = import_picocolors31.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
|
|
9815
|
+
const steps = r.subtaskTotal ? import_picocolors31.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
|
|
9816
|
+
const gate = r.approval_state === "awaiting" ? import_picocolors31.default.yellow(" awaiting approval") : "";
|
|
9300
9817
|
return `${key} ${statusTag2(r.status)} ${r.title}${steps}${gate}`;
|
|
9301
9818
|
}
|
|
9302
9819
|
function formatSubtask(r, index) {
|
|
9303
|
-
const n =
|
|
9304
|
-
const role = r.role ?
|
|
9305
|
-
const scope = r.scope_paths?.length ?
|
|
9820
|
+
const n = import_picocolors31.default.dim(String(index).padStart(2, "0"));
|
|
9821
|
+
const role = r.role ? import_picocolors31.default.dim(` [${r.role}]`) : "";
|
|
9822
|
+
const scope = r.scope_paths?.length ? import_picocolors31.default.dim(` owns: ${r.scope_paths.join(", ")}`) : "";
|
|
9306
9823
|
const head = `${n} ${statusTag2(r.status)} ${r.title}${role}${scope}`;
|
|
9307
9824
|
const summary = (r.result_summary ?? "").trim();
|
|
9308
9825
|
if (!summary) return head;
|
|
9309
9826
|
const wrapped = summary.split("\n").map((l) => ` ${l}`).join("\n");
|
|
9310
9827
|
return `${head}
|
|
9311
|
-
${
|
|
9828
|
+
${import_picocolors31.default.dim(wrapped)}`;
|
|
9312
9829
|
}
|
|
9313
9830
|
function printTask(row, goal) {
|
|
9314
|
-
line(`${
|
|
9831
|
+
line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.key ?? row.id)}`);
|
|
9315
9832
|
line(`${statusTag2(row.status)} approval: ${row.approval_state}`);
|
|
9316
9833
|
if (row.summary) line(`
|
|
9317
9834
|
${row.summary}`);
|
|
@@ -9324,53 +9841,53 @@ touches: ${row.targets.map((t) => t.appName ?? t.ref ?? t.kind).join(", ")}`
|
|
|
9324
9841
|
}
|
|
9325
9842
|
if (row.subtasks?.length) {
|
|
9326
9843
|
line(`
|
|
9327
|
-
${
|
|
9844
|
+
${import_picocolors31.default.bold("subtasks")}`);
|
|
9328
9845
|
row.subtasks.forEach((s, i) => line(formatSubtask(s, i + 1)));
|
|
9329
9846
|
line(
|
|
9330
|
-
|
|
9847
|
+
import_picocolors31.default.dim(
|
|
9331
9848
|
`
|
|
9332
9849
|
Run \`workser artifact list\` to see what these subtasks produced,`
|
|
9333
9850
|
)
|
|
9334
9851
|
);
|
|
9335
9852
|
line(
|
|
9336
|
-
|
|
9853
|
+
import_picocolors31.default.dim(
|
|
9337
9854
|
`or \`workser artifact list --step <id>\` for one subtask's output alone.`
|
|
9338
9855
|
)
|
|
9339
9856
|
);
|
|
9340
9857
|
} else {
|
|
9341
|
-
line(
|
|
9858
|
+
line(import_picocolors31.default.dim("\nNo subtasks yet."));
|
|
9342
9859
|
}
|
|
9343
9860
|
}
|
|
9344
9861
|
function printGoalContext(row, goal) {
|
|
9345
9862
|
const mine = row.phase ?? null;
|
|
9346
9863
|
line(`
|
|
9347
|
-
${
|
|
9348
|
-
if (goal.outcome) line(
|
|
9864
|
+
${import_picocolors31.default.bold("part of")}: ${goal.title}`);
|
|
9865
|
+
if (goal.outcome) line(import_picocolors31.default.dim(`done means: ${goal.outcome}`));
|
|
9349
9866
|
const progress = goal.progress ?? [];
|
|
9350
9867
|
for (const p of progress) {
|
|
9351
9868
|
const where = p.total === 0 ? "not started" : `${p.done} of ${p.total} done`;
|
|
9352
|
-
const here = mine && p.name === mine ?
|
|
9353
|
-
const mark = p.state === "done" ?
|
|
9869
|
+
const here = mine && p.name === mine ? import_picocolors31.default.cyan(" <- this task") : "";
|
|
9870
|
+
const mark = p.state === "done" ? import_picocolors31.default.green("*") : import_picocolors31.default.dim("-");
|
|
9354
9871
|
line(` ${mark} ${p.name} \u2014 ${where}${here}`);
|
|
9355
9872
|
}
|
|
9356
9873
|
const next = progress.find((p) => p.state !== "done");
|
|
9357
9874
|
const running = progress.some((p) => p.state === "working");
|
|
9358
9875
|
if (next && !running) {
|
|
9359
9876
|
line(
|
|
9360
|
-
|
|
9877
|
+
import_picocolors31.default.dim(
|
|
9361
9878
|
`
|
|
9362
9879
|
Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to them in a sentence rather than starting it unasked.`
|
|
9363
9880
|
)
|
|
9364
9881
|
);
|
|
9365
9882
|
} else if (!next) {
|
|
9366
9883
|
line(
|
|
9367
|
-
|
|
9884
|
+
import_picocolors31.default.dim(
|
|
9368
9885
|
"\nEvery part of this plan is done. Say so, and offer to wrap it up."
|
|
9369
9886
|
)
|
|
9370
9887
|
);
|
|
9371
9888
|
}
|
|
9372
9889
|
line(
|
|
9373
|
-
|
|
9890
|
+
import_picocolors31.default.dim(
|
|
9374
9891
|
"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."
|
|
9375
9892
|
)
|
|
9376
9893
|
);
|
|
@@ -9378,22 +9895,22 @@ Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to t
|
|
|
9378
9895
|
function statusTag2(status) {
|
|
9379
9896
|
switch (status) {
|
|
9380
9897
|
case "ready":
|
|
9381
|
-
return
|
|
9898
|
+
return import_picocolors31.default.green("[ready]");
|
|
9382
9899
|
case "working":
|
|
9383
|
-
return
|
|
9900
|
+
return import_picocolors31.default.blue("[working]");
|
|
9384
9901
|
case "checking":
|
|
9385
|
-
return
|
|
9902
|
+
return import_picocolors31.default.cyan("[checking]");
|
|
9386
9903
|
case "accepted":
|
|
9387
|
-
return
|
|
9904
|
+
return import_picocolors31.default.green("[accepted]");
|
|
9388
9905
|
case "archived":
|
|
9389
|
-
return
|
|
9906
|
+
return import_picocolors31.default.dim("[archived]");
|
|
9390
9907
|
default:
|
|
9391
|
-
return
|
|
9908
|
+
return import_picocolors31.default.dim("[todo]");
|
|
9392
9909
|
}
|
|
9393
9910
|
}
|
|
9394
9911
|
|
|
9395
9912
|
// src/commands/goal.ts
|
|
9396
|
-
var
|
|
9913
|
+
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
9397
9914
|
var STATUSES3 = ["proposed", "agreed", "working", "delivered", "abandoned"];
|
|
9398
9915
|
function registerGoal(program3) {
|
|
9399
9916
|
const goal = program3.command("goal").description("Business goals and the phases that deliver them");
|
|
@@ -9405,7 +9922,7 @@ function registerGoal(program3) {
|
|
|
9405
9922
|
}) ?? [];
|
|
9406
9923
|
ok(rows, () => {
|
|
9407
9924
|
if (!rows.length) {
|
|
9408
|
-
line(
|
|
9925
|
+
line(import_picocolors32.default.dim("No goals yet \u2014 every task here stands on its own."));
|
|
9409
9926
|
return;
|
|
9410
9927
|
}
|
|
9411
9928
|
for (const g of rows) line(formatGoal(g));
|
|
@@ -9482,10 +9999,10 @@ function registerGoal(program3) {
|
|
|
9482
9999
|
}
|
|
9483
10000
|
});
|
|
9484
10001
|
ok(row, () => {
|
|
9485
|
-
success(`Proposed ${
|
|
10002
|
+
success(`Proposed ${import_picocolors32.default.bold(row?.title ?? "goal")}`);
|
|
9486
10003
|
printGoal(row);
|
|
9487
10004
|
line(
|
|
9488
|
-
|
|
10005
|
+
import_picocolors32.default.dim(
|
|
9489
10006
|
"\nNothing has been created yet. The owner agrees the shape first."
|
|
9490
10007
|
)
|
|
9491
10008
|
);
|
|
@@ -9514,7 +10031,7 @@ function registerGoal(program3) {
|
|
|
9514
10031
|
ok(
|
|
9515
10032
|
row,
|
|
9516
10033
|
() => line(
|
|
9517
|
-
row?.recorded ? met === true ?
|
|
10034
|
+
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(
|
|
9518
10035
|
"couldn't record it \u2014 check the goal id, the phase name and the criterion id"
|
|
9519
10036
|
)
|
|
9520
10037
|
)
|
|
@@ -9557,7 +10074,7 @@ function registerGoal(program3) {
|
|
|
9557
10074
|
}
|
|
9558
10075
|
ok({ goalId, phase, filed }, () => {
|
|
9559
10076
|
success(
|
|
9560
|
-
`Filed ${filed.length} ${filed.length === 1 ? "task" : "tasks"} under ${
|
|
10077
|
+
`Filed ${filed.length} ${filed.length === 1 ? "task" : "tasks"} under ${import_picocolors32.default.bold(phase)}`
|
|
9561
10078
|
);
|
|
9562
10079
|
});
|
|
9563
10080
|
})
|
|
@@ -9589,42 +10106,42 @@ function registerGoal(program3) {
|
|
|
9589
10106
|
function appScope(g) {
|
|
9590
10107
|
const n = g.appIds?.length ?? 0;
|
|
9591
10108
|
if (!n) return "";
|
|
9592
|
-
return
|
|
10109
|
+
return import_picocolors32.default.dim(` ${n} part${n === 1 ? "" : "s"} of the system`);
|
|
9593
10110
|
}
|
|
9594
10111
|
function formatGoal(g) {
|
|
9595
|
-
const where = g.currentPhase && g.status !== "delivered" ?
|
|
9596
|
-
const count = g.taskTotal != null ?
|
|
9597
|
-
return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${
|
|
10112
|
+
const where = g.currentPhase && g.status !== "delivered" ? import_picocolors32.default.dim(` now: ${g.currentPhase}`) : "";
|
|
10113
|
+
const count = g.taskTotal != null ? import_picocolors32.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
|
|
10114
|
+
return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${import_picocolors32.default.dim(g.id)}`;
|
|
9598
10115
|
}
|
|
9599
10116
|
function printGoal(g) {
|
|
9600
10117
|
if (!g) return;
|
|
9601
|
-
line(`${
|
|
10118
|
+
line(`${import_picocolors32.default.bold(g.title)} ${import_picocolors32.default.dim(g.id)}`);
|
|
9602
10119
|
line(statusTag3(g.status));
|
|
9603
10120
|
if (g.outcome) line(`
|
|
9604
10121
|
done means: ${g.outcome}`);
|
|
9605
10122
|
const progress = g.progress ?? [];
|
|
9606
10123
|
if (!progress.length) {
|
|
9607
|
-
line(
|
|
10124
|
+
line(import_picocolors32.default.dim("\nNo phases agreed yet."));
|
|
9608
10125
|
return;
|
|
9609
10126
|
}
|
|
9610
10127
|
line(`
|
|
9611
|
-
${
|
|
10128
|
+
${import_picocolors32.default.bold("phases")}`);
|
|
9612
10129
|
for (const p of progress) {
|
|
9613
|
-
const bar2 = p.total > 0 ? `${p.done}/${p.total} done` :
|
|
9614
|
-
const mark = p.state === "done" ?
|
|
10130
|
+
const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors32.default.dim("nothing filed yet");
|
|
10131
|
+
const mark = p.state === "done" ? import_picocolors32.default.green("done") : p.state === "working" ? import_picocolors32.default.blue("working") : import_picocolors32.default.dim("waiting");
|
|
9615
10132
|
line(
|
|
9616
|
-
` ${
|
|
10133
|
+
` ${import_picocolors32.default.dim(String(p.index).padStart(2, "0"))} ${p.name} ${mark} ${import_picocolors32.default.dim(bar2)}`
|
|
9617
10134
|
);
|
|
9618
10135
|
for (const c of p.criteria ?? []) {
|
|
9619
|
-
const tick = c.met === true ?
|
|
9620
|
-
line(` ${tick} ${c.text} ${
|
|
9621
|
-
if (c.note) line(
|
|
10136
|
+
const tick = c.met === true ? import_picocolors32.default.green("\u2713") : c.met === false ? import_picocolors32.default.red("\u2717") : import_picocolors32.default.dim("\xB7");
|
|
10137
|
+
line(` ${tick} ${c.text} ${import_picocolors32.default.dim(c.id)}`);
|
|
10138
|
+
if (c.note) line(import_picocolors32.default.dim(` ${c.note}`));
|
|
9622
10139
|
}
|
|
9623
10140
|
}
|
|
9624
10141
|
const current = progress.find((p) => p.name === g.currentPhase);
|
|
9625
10142
|
if (current) {
|
|
9626
10143
|
line(
|
|
9627
|
-
|
|
10144
|
+
import_picocolors32.default.dim(
|
|
9628
10145
|
`
|
|
9629
10146
|
${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current.index} of ${progress.length}).`
|
|
9630
10147
|
)
|
|
@@ -9634,15 +10151,15 @@ ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current
|
|
|
9634
10151
|
function statusTag3(status) {
|
|
9635
10152
|
switch (status) {
|
|
9636
10153
|
case "agreed":
|
|
9637
|
-
return
|
|
10154
|
+
return import_picocolors32.default.cyan("[agreed]");
|
|
9638
10155
|
case "working":
|
|
9639
|
-
return
|
|
10156
|
+
return import_picocolors32.default.blue("[working]");
|
|
9640
10157
|
case "delivered":
|
|
9641
|
-
return
|
|
10158
|
+
return import_picocolors32.default.green("[delivered]");
|
|
9642
10159
|
case "abandoned":
|
|
9643
|
-
return
|
|
10160
|
+
return import_picocolors32.default.dim("[abandoned]");
|
|
9644
10161
|
default:
|
|
9645
|
-
return
|
|
10162
|
+
return import_picocolors32.default.yellow("[proposed]");
|
|
9646
10163
|
}
|
|
9647
10164
|
}
|
|
9648
10165
|
|
|
@@ -9826,7 +10343,7 @@ function stripLeadingGlobalOptions(argv) {
|
|
|
9826
10343
|
}
|
|
9827
10344
|
|
|
9828
10345
|
// src/commands/decision.ts
|
|
9829
|
-
var
|
|
10346
|
+
var import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
9830
10347
|
function registerDecision(program3) {
|
|
9831
10348
|
const decision = program3.command("decision").description("Read and record the project's architecture decisions");
|
|
9832
10349
|
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(
|
|
@@ -9839,11 +10356,11 @@ function registerDecision(program3) {
|
|
|
9839
10356
|
rows = applyLimit(rows, opts.limit);
|
|
9840
10357
|
ok(rows, () => {
|
|
9841
10358
|
if (!rows.length) {
|
|
9842
|
-
line(
|
|
10359
|
+
line(import_picocolors33.default.dim("No decisions recorded yet."));
|
|
9843
10360
|
return;
|
|
9844
10361
|
}
|
|
9845
10362
|
for (const r of rows) {
|
|
9846
|
-
line(`${
|
|
10363
|
+
line(`${import_picocolors33.default.dim(r.id)} ${import_picocolors33.default.dim(shortDate(r.createdAt))} ${r.title}`);
|
|
9847
10364
|
line(` ${truncate(r.decision, 100)}`);
|
|
9848
10365
|
}
|
|
9849
10366
|
});
|
|
@@ -9857,16 +10374,16 @@ function registerDecision(program3) {
|
|
|
9857
10374
|
`/v1/projects/${projectId}/architecture-decisions/${args[0]}`
|
|
9858
10375
|
);
|
|
9859
10376
|
ok(row, () => {
|
|
9860
|
-
line(`${
|
|
9861
|
-
line(
|
|
10377
|
+
line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
|
|
10378
|
+
line(import_picocolors33.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
|
|
9862
10379
|
line(`
|
|
9863
|
-
${
|
|
10380
|
+
${import_picocolors33.default.bold("Context")}
|
|
9864
10381
|
${row.context}`);
|
|
9865
10382
|
line(`
|
|
9866
|
-
${
|
|
10383
|
+
${import_picocolors33.default.bold("Decision")}
|
|
9867
10384
|
${row.decision}`);
|
|
9868
10385
|
if (row.consequences) line(`
|
|
9869
|
-
${
|
|
10386
|
+
${import_picocolors33.default.bold("Consequences")}
|
|
9870
10387
|
${row.consequences}`);
|
|
9871
10388
|
});
|
|
9872
10389
|
})
|
|
@@ -9895,7 +10412,7 @@ ${row.consequences}`);
|
|
|
9895
10412
|
refId: row?.id,
|
|
9896
10413
|
output: { decision: row }
|
|
9897
10414
|
});
|
|
9898
|
-
ok(row, () => line(`Recorded decision ${
|
|
10415
|
+
ok(row, () => line(`Recorded decision ${import_picocolors33.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
9899
10416
|
})
|
|
9900
10417
|
);
|
|
9901
10418
|
const requirement = program3.command("requirement").description("Read and record the project's requirements");
|
|
@@ -9907,11 +10424,11 @@ ${row.consequences}`);
|
|
|
9907
10424
|
rows = applyLimit(rows, opts.limit);
|
|
9908
10425
|
ok(rows, () => {
|
|
9909
10426
|
if (!rows.length) {
|
|
9910
|
-
line(
|
|
10427
|
+
line(import_picocolors33.default.dim("No requirements recorded yet."));
|
|
9911
10428
|
return;
|
|
9912
10429
|
}
|
|
9913
10430
|
for (const r of rows) {
|
|
9914
|
-
line(`${
|
|
10431
|
+
line(`${import_picocolors33.default.dim(r.id)} ${r.status.padEnd(9)} ${r.title}`);
|
|
9915
10432
|
}
|
|
9916
10433
|
});
|
|
9917
10434
|
})
|
|
@@ -9924,8 +10441,8 @@ ${row.consequences}`);
|
|
|
9924
10441
|
`/v1/projects/${projectId}/requirements/${args[0]}`
|
|
9925
10442
|
);
|
|
9926
10443
|
ok(row, () => {
|
|
9927
|
-
line(`${
|
|
9928
|
-
line(
|
|
10444
|
+
line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
|
|
10445
|
+
line(import_picocolors33.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
|
|
9929
10446
|
line(`
|
|
9930
10447
|
${row.body}`);
|
|
9931
10448
|
});
|
|
@@ -9951,7 +10468,7 @@ ${row.body}`);
|
|
|
9951
10468
|
refId: row?.id,
|
|
9952
10469
|
output: { requirement: row }
|
|
9953
10470
|
});
|
|
9954
|
-
ok(row, () => line(`Recorded requirement ${
|
|
10471
|
+
ok(row, () => line(`Recorded requirement ${import_picocolors33.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
9955
10472
|
})
|
|
9956
10473
|
);
|
|
9957
10474
|
requirement.command("update <id>").description(
|
|
@@ -9980,7 +10497,7 @@ ${row.body}`);
|
|
|
9980
10497
|
code: "bad_request"
|
|
9981
10498
|
});
|
|
9982
10499
|
}
|
|
9983
|
-
ok(row, () => line(`Updated requirement ${
|
|
10500
|
+
ok(row, () => line(`Updated requirement ${import_picocolors33.default.bold(row.id)} \u2014 ${row.title} (${row.status})`));
|
|
9984
10501
|
})
|
|
9985
10502
|
);
|
|
9986
10503
|
}
|
|
@@ -10003,7 +10520,7 @@ function shortDate(iso) {
|
|
|
10003
10520
|
}
|
|
10004
10521
|
|
|
10005
10522
|
// src/commands/doc.ts
|
|
10006
|
-
var
|
|
10523
|
+
var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
10007
10524
|
|
|
10008
10525
|
// src/mermaid-fences.ts
|
|
10009
10526
|
function hasDiagram(code) {
|
|
@@ -10048,13 +10565,13 @@ function registerDoc(program3) {
|
|
|
10048
10565
|
}) ?? [];
|
|
10049
10566
|
ok(rows, () => {
|
|
10050
10567
|
if (!rows.length) {
|
|
10051
|
-
line(
|
|
10568
|
+
line(import_picocolors34.default.dim("No documents yet."));
|
|
10052
10569
|
return;
|
|
10053
10570
|
}
|
|
10054
10571
|
for (const r of rows) {
|
|
10055
|
-
const link = r.workItemId ?
|
|
10056
|
-
const file = r.filePath ?
|
|
10057
|
-
line(`${
|
|
10572
|
+
const link = r.workItemId ? import_picocolors34.default.dim(` \u21B3 ${r.workItemId}`) : "";
|
|
10573
|
+
const file = r.filePath ? import_picocolors34.default.dim(` ${r.filePath}`) : "";
|
|
10574
|
+
line(`${import_picocolors34.default.dim(r.id)} ${r.title}${link}${file}`);
|
|
10058
10575
|
}
|
|
10059
10576
|
});
|
|
10060
10577
|
})
|
|
@@ -10068,17 +10585,17 @@ function registerDoc(program3) {
|
|
|
10068
10585
|
);
|
|
10069
10586
|
if (opts.markdown) {
|
|
10070
10587
|
ok({ id: row.id, title: row.title, filePath: row.filePath }, () => {
|
|
10071
|
-
line(`${
|
|
10588
|
+
line(`${import_picocolors34.default.bold(row.title)} ${import_picocolors34.default.dim(row.id)}`);
|
|
10072
10589
|
line(
|
|
10073
|
-
row.filePath ? `Read it at ${
|
|
10590
|
+
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.")
|
|
10074
10591
|
);
|
|
10075
10592
|
});
|
|
10076
10593
|
return;
|
|
10077
10594
|
}
|
|
10078
10595
|
ok(row, () => {
|
|
10079
|
-
line(`${
|
|
10080
|
-
if (row.workItemId) line(
|
|
10081
|
-
if (row.filePath) line(
|
|
10596
|
+
line(`${import_picocolors34.default.bold(row.title)} ${import_picocolors34.default.dim(row.id)}`);
|
|
10597
|
+
if (row.workItemId) line(import_picocolors34.default.dim(`linked to work item ${row.workItemId}`));
|
|
10598
|
+
if (row.filePath) line(import_picocolors34.default.dim(`markdown mirror: ${row.filePath}`));
|
|
10082
10599
|
line("");
|
|
10083
10600
|
line(row.contentJson);
|
|
10084
10601
|
});
|
|
@@ -10107,7 +10624,7 @@ function registerDoc(program3) {
|
|
|
10107
10624
|
refId: row?.id,
|
|
10108
10625
|
output: { document: row }
|
|
10109
10626
|
});
|
|
10110
|
-
ok(row, () => line(`Created document ${
|
|
10627
|
+
ok(row, () => line(`Created document ${import_picocolors34.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
10111
10628
|
})
|
|
10112
10629
|
);
|
|
10113
10630
|
doc.command("diagram <id>").description(
|
|
@@ -10133,19 +10650,19 @@ function registerDoc(program3) {
|
|
|
10133
10650
|
diagrams: diagrams.map((code) => ({ kind: diagramKind(code), code }))
|
|
10134
10651
|
};
|
|
10135
10652
|
ok(payload, () => {
|
|
10136
|
-
line(`${
|
|
10653
|
+
line(`${import_picocolors34.default.bold(row.title)} ${import_picocolors34.default.dim(row.id)}`);
|
|
10137
10654
|
if (markdown === null) {
|
|
10138
10655
|
line(
|
|
10139
|
-
|
|
10656
|
+
import_picocolors34.default.dim(
|
|
10140
10657
|
row.filePath ? `Could not read ${row.filePath} from this folder.` : "This document has no markdown mirror on disk yet."
|
|
10141
10658
|
)
|
|
10142
10659
|
);
|
|
10143
10660
|
} else if (!diagrams.length) {
|
|
10144
|
-
line(
|
|
10661
|
+
line(import_picocolors34.default.dim("No diagrams in this document."));
|
|
10145
10662
|
} else {
|
|
10146
10663
|
for (const [i, code] of diagrams.entries()) {
|
|
10147
10664
|
const kind = diagramKind(code) ?? "diagram";
|
|
10148
|
-
line(`${
|
|
10665
|
+
line(`${import_picocolors34.default.dim(String(i + 1))} ${kind} ${import_picocolors34.default.dim(`${code.split("\n").length} lines`)}`);
|
|
10149
10666
|
}
|
|
10150
10667
|
}
|
|
10151
10668
|
});
|
|
@@ -10181,7 +10698,7 @@ function registerDoc(program3) {
|
|
|
10181
10698
|
code: "bad_request"
|
|
10182
10699
|
});
|
|
10183
10700
|
}
|
|
10184
|
-
ok(row, () => line(`Updated document ${
|
|
10701
|
+
ok(row, () => line(`Updated document ${import_picocolors34.default.bold(row.id)} \u2014 ${row.title}`));
|
|
10185
10702
|
})
|
|
10186
10703
|
);
|
|
10187
10704
|
}
|
|
@@ -10195,9 +10712,9 @@ function readMirror(cwd, filePath) {
|
|
|
10195
10712
|
}
|
|
10196
10713
|
|
|
10197
10714
|
// src/commands/design.ts
|
|
10198
|
-
var
|
|
10715
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
10199
10716
|
function registerDesign(program3) {
|
|
10200
|
-
const design = program3.command("design").description("
|
|
10717
|
+
const design = program3.command("design").description("The project's brand, and pictures of the screens you draw");
|
|
10201
10718
|
design.command("show").description("Show this project's brand \u2014 read it before writing any UI").option("--raw", "print the generated token files verbatim instead of a summary").action(
|
|
10202
10719
|
action(async ({ ctx, opts }) => {
|
|
10203
10720
|
const projectId = requireProject(ctx);
|
|
@@ -10209,11 +10726,11 @@ function registerDesign(program3) {
|
|
|
10209
10726
|
if (opts.raw) {
|
|
10210
10727
|
ok(files, () => {
|
|
10211
10728
|
if (!files.length) {
|
|
10212
|
-
line(
|
|
10729
|
+
line(import_picocolors35.default.dim("No brand set for this project."));
|
|
10213
10730
|
return;
|
|
10214
10731
|
}
|
|
10215
10732
|
for (const f of files) {
|
|
10216
|
-
line(
|
|
10733
|
+
line(import_picocolors35.default.bold(f.path));
|
|
10217
10734
|
line(f.contents);
|
|
10218
10735
|
line("");
|
|
10219
10736
|
}
|
|
@@ -10230,27 +10747,62 @@ function registerDesign(program3) {
|
|
|
10230
10747
|
} : { hasBrand: false, colors: {}, fonts: {}, brand: {}, files: [] };
|
|
10231
10748
|
ok(summary, () => {
|
|
10232
10749
|
if (!tokens) {
|
|
10233
|
-
line(
|
|
10750
|
+
line(import_picocolors35.default.dim("No brand set for this project \u2014 choose sensible styling yourself."));
|
|
10234
10751
|
return;
|
|
10235
10752
|
}
|
|
10236
10753
|
for (const [name, value] of Object.entries(tokens.brand)) {
|
|
10237
|
-
line(`${
|
|
10754
|
+
line(`${import_picocolors35.default.dim(name.padEnd(12))} ${value}`);
|
|
10238
10755
|
}
|
|
10239
10756
|
for (const [name, value] of Object.entries(tokens.color)) {
|
|
10240
|
-
line(`${
|
|
10757
|
+
line(`${import_picocolors35.default.dim(`color.${name}`.padEnd(12))} ${value}`);
|
|
10241
10758
|
}
|
|
10242
10759
|
for (const [name, value] of Object.entries(tokens.font)) {
|
|
10243
|
-
line(`${
|
|
10760
|
+
line(`${import_picocolors35.default.dim(`font.${name}`.padEnd(12))} ${value}`);
|
|
10244
10761
|
}
|
|
10245
10762
|
line("");
|
|
10246
10763
|
line(
|
|
10247
|
-
|
|
10764
|
+
import_picocolors35.default.dim(
|
|
10248
10765
|
`Generated into the working tree as ${files.map((f) => f.path).join(", ")} \u2014 wire those in, never edit them.`
|
|
10249
10766
|
)
|
|
10250
10767
|
);
|
|
10251
10768
|
});
|
|
10252
10769
|
})
|
|
10253
10770
|
);
|
|
10771
|
+
design.command("shot").argument("<files...>", "the HTML screens to photograph, relative to the project folder").description("Render a design screen to a PNG beside it, for surfaces that can't run a page").option("--width <px>", "artboard width (default 1440)", (v) => Number(v)).option("--height <px>", "artboard height (default 900)", (v) => Number(v)).action(
|
|
10772
|
+
action(async ({ ctx, args, opts }) => {
|
|
10773
|
+
const projectId = requireProject(ctx);
|
|
10774
|
+
const res = await api(ctx, "/v1/design-shot", {
|
|
10775
|
+
method: "POST",
|
|
10776
|
+
body: {
|
|
10777
|
+
projectId,
|
|
10778
|
+
files: args,
|
|
10779
|
+
width: opts.width,
|
|
10780
|
+
height: opts.height
|
|
10781
|
+
}
|
|
10782
|
+
});
|
|
10783
|
+
ok(res, () => {
|
|
10784
|
+
for (const shot of res.shots ?? []) {
|
|
10785
|
+
if (shot.out) {
|
|
10786
|
+
line(`${import_picocolors35.default.green("\u2713")} ${shot.file} ${import_picocolors35.default.dim("\u2192")} ${shot.out}`);
|
|
10787
|
+
} else {
|
|
10788
|
+
line(`${import_picocolors35.default.red("\u2717")} ${shot.file} ${import_picocolors35.default.dim(shot.error ?? "no image")}`);
|
|
10789
|
+
}
|
|
10790
|
+
}
|
|
10791
|
+
for (const path of res.refused ?? []) {
|
|
10792
|
+
line(import_picocolors35.default.dim(`skipped ${path} \u2014 not a page inside this project`));
|
|
10793
|
+
}
|
|
10794
|
+
const made = (res.shots ?? []).filter((s) => s.out).length;
|
|
10795
|
+
if (made) {
|
|
10796
|
+
line("");
|
|
10797
|
+
line(
|
|
10798
|
+
import_picocolors35.default.dim(
|
|
10799
|
+
`Record each one so it shows up: workser artifact add <file>.png --kind design -d "<what this screen is>"`
|
|
10800
|
+
)
|
|
10801
|
+
);
|
|
10802
|
+
}
|
|
10803
|
+
});
|
|
10804
|
+
})
|
|
10805
|
+
);
|
|
10254
10806
|
}
|
|
10255
10807
|
function parseTokens(files) {
|
|
10256
10808
|
const doc = files.find((f) => f.path.endsWith("tokens.json"));
|
|
@@ -10275,7 +10827,7 @@ function unwrap(group) {
|
|
|
10275
10827
|
}
|
|
10276
10828
|
|
|
10277
10829
|
// src/commands/api.ts
|
|
10278
|
-
var
|
|
10830
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
10279
10831
|
import { readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
10280
10832
|
import { join as join3, relative, sep } from "path";
|
|
10281
10833
|
|
|
@@ -10389,10 +10941,10 @@ function registerApi(program3) {
|
|
|
10389
10941
|
const appId = requireApp2(opts.app);
|
|
10390
10942
|
const res = await api(ctx, `/v1/apps/${encodeURIComponent(appId)}/api/requests`);
|
|
10391
10943
|
ok(res, () => {
|
|
10392
|
-
for (const note of res?.notes ?? []) line(
|
|
10944
|
+
for (const note of res?.notes ?? []) line(import_picocolors36.default.dim(note));
|
|
10393
10945
|
for (const r of res?.requests ?? []) {
|
|
10394
10946
|
line(
|
|
10395
|
-
`${
|
|
10947
|
+
`${import_picocolors36.default.dim(r.method.padEnd(6))}${r.path}${r.note ? import_picocolors36.default.dim(` ${r.note}`) : ""}`
|
|
10396
10948
|
);
|
|
10397
10949
|
}
|
|
10398
10950
|
});
|
|
@@ -10426,14 +10978,14 @@ function registerApi(program3) {
|
|
|
10426
10978
|
);
|
|
10427
10979
|
ok(res, () => {
|
|
10428
10980
|
if (!res?.ok) {
|
|
10429
|
-
line(
|
|
10981
|
+
line(import_picocolors36.default.red(res?.error ?? "The service did not answer."));
|
|
10430
10982
|
return;
|
|
10431
10983
|
}
|
|
10432
10984
|
const code = `${res.status}${res.statusText ? ` ${res.statusText}` : ""}`;
|
|
10433
|
-
const colour2 = res.status && res.status < 300 ?
|
|
10434
|
-
line(`${colour2(code)} ${
|
|
10985
|
+
const colour2 = res.status && res.status < 300 ? import_picocolors36.default.green : res.status && res.status < 500 ? import_picocolors36.default.yellow : import_picocolors36.default.red;
|
|
10986
|
+
line(`${colour2(code)} ${import_picocolors36.default.dim(`${res.durationMs}ms ${res.url}`)}`);
|
|
10435
10987
|
if (res.body) line(res.body);
|
|
10436
|
-
if (res.truncated) line(
|
|
10988
|
+
if (res.truncated) line(import_picocolors36.default.dim("(answer truncated)"));
|
|
10437
10989
|
});
|
|
10438
10990
|
if (!res?.ok) process.exitCode = 1;
|
|
10439
10991
|
})
|
|
@@ -10453,15 +11005,15 @@ function registerApi(program3) {
|
|
|
10453
11005
|
for (const r of report.routes) {
|
|
10454
11006
|
const known = report.missing.some((m) => m.path === r.path);
|
|
10455
11007
|
line(
|
|
10456
|
-
`${known ?
|
|
11008
|
+
`${known ? import_picocolors36.default.yellow("undocumented") : import_picocolors36.default.green("documented ")} ${r.path}${import_picocolors36.default.dim(` ${r.file}`)}`
|
|
10457
11009
|
);
|
|
10458
11010
|
}
|
|
10459
11011
|
for (const p of report.stale) {
|
|
10460
|
-
line(`${
|
|
11012
|
+
line(`${import_picocolors36.default.dim("in spec only ")} ${p}`);
|
|
10461
11013
|
}
|
|
10462
11014
|
line("");
|
|
10463
11015
|
if (report.ok && specFile) success(summary);
|
|
10464
|
-
else line(
|
|
11016
|
+
else line(import_picocolors36.default.yellow(summary));
|
|
10465
11017
|
});
|
|
10466
11018
|
if (opts.check && !report.ok) {
|
|
10467
11019
|
throw new WorkserError(summary, { code: "bad_request" });
|
|
@@ -10532,7 +11084,7 @@ function listRepoFiles(root, maxDepth = 8) {
|
|
|
10532
11084
|
}
|
|
10533
11085
|
|
|
10534
11086
|
// src/commands/analysis.ts
|
|
10535
|
-
var
|
|
11087
|
+
var import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
10536
11088
|
import { readFileSync as readFileSync4 } from "fs";
|
|
10537
11089
|
function registerAnalysis(program3) {
|
|
10538
11090
|
const cmd = program3.command("analysis").description("Run Python analysis locally, recorded in the task");
|
|
@@ -10542,14 +11094,14 @@ function registerAnalysis(program3) {
|
|
|
10542
11094
|
const res = await api(ctx, path);
|
|
10543
11095
|
ok(res, () => {
|
|
10544
11096
|
line(
|
|
10545
|
-
`${res?.available ?
|
|
11097
|
+
`${res?.available ? import_picocolors37.default.green("python") : import_picocolors37.default.red("python")} ${res?.version ?? "not found"} ${import_picocolors37.default.dim(res?.python ?? "")}`
|
|
10546
11098
|
);
|
|
10547
11099
|
for (const lib of res?.libraries ?? []) {
|
|
10548
11100
|
line(
|
|
10549
|
-
`${lib.present ?
|
|
11101
|
+
`${lib.present ? import_picocolors37.default.green(lib.name) : import_picocolors37.default.yellow(lib.name)}${import_picocolors37.default.dim(lib.present ? "" : " missing")}`
|
|
10550
11102
|
);
|
|
10551
11103
|
}
|
|
10552
|
-
for (const note of res?.notes ?? []) line(
|
|
11104
|
+
for (const note of res?.notes ?? []) line(import_picocolors37.default.dim(note));
|
|
10553
11105
|
});
|
|
10554
11106
|
if (!res?.available) process.exitCode = 1;
|
|
10555
11107
|
})
|
|
@@ -10571,15 +11123,15 @@ function registerAnalysis(program3) {
|
|
|
10571
11123
|
);
|
|
10572
11124
|
ok(res, () => {
|
|
10573
11125
|
if (res?.stdout) line(res.stdout.replace(/\n$/, ""));
|
|
10574
|
-
if (res?.stderr) line(
|
|
10575
|
-
if (res?.truncated) line(
|
|
11126
|
+
if (res?.stderr) line(import_picocolors37.default.dim(res.stderr.replace(/\n$/, "")));
|
|
11127
|
+
if (res?.truncated) line(import_picocolors37.default.dim("(output truncated)"));
|
|
10576
11128
|
const took = `${Math.round((res?.durationMs ?? 0) / 100) / 10}s`;
|
|
10577
11129
|
line(
|
|
10578
|
-
res?.ok ?
|
|
11130
|
+
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}`)
|
|
10579
11131
|
);
|
|
10580
11132
|
if (res && !res.sandboxed) {
|
|
10581
11133
|
line(
|
|
10582
|
-
|
|
11134
|
+
import_picocolors37.default.dim(
|
|
10583
11135
|
"This platform has no OS sandbox, so the script ran with your own file access."
|
|
10584
11136
|
)
|
|
10585
11137
|
);
|
|
@@ -10607,7 +11159,7 @@ function readCode(file, inline) {
|
|
|
10607
11159
|
}
|
|
10608
11160
|
|
|
10609
11161
|
// src/commands/scan.ts
|
|
10610
|
-
var
|
|
11162
|
+
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
10611
11163
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
10612
11164
|
import { existsSync as existsSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
10613
11165
|
import { join as join4, relative as relative2, sep as sep2 } from "path";
|
|
@@ -10891,22 +11443,22 @@ function runPermissions(cwd, findings, checked, skipped) {
|
|
|
10891
11443
|
}
|
|
10892
11444
|
function print2(report, summary) {
|
|
10893
11445
|
for (const s of report.skipped) {
|
|
10894
|
-
line(`${
|
|
11446
|
+
line(`${import_picocolors38.default.yellow("not checked")} ${s.check}${import_picocolors38.default.dim(` \u2014 ${s.reason}`)}`);
|
|
10895
11447
|
}
|
|
10896
11448
|
for (const f of report.findings) {
|
|
10897
|
-
const where = f.file ?
|
|
11449
|
+
const where = f.file ? import_picocolors38.default.dim(` ${f.file}${f.line ? `:${f.line}` : ""}`) : "";
|
|
10898
11450
|
line(`${severityTag(f.severity)} ${f.title}${where}`);
|
|
10899
|
-
line(` ${
|
|
11451
|
+
line(` ${import_picocolors38.default.dim(f.fix)}`);
|
|
10900
11452
|
}
|
|
10901
11453
|
if (report.findings.length || report.skipped.length) line("");
|
|
10902
11454
|
if (report.ok && !report.skipped.length) success(summary);
|
|
10903
|
-
else if (report.ok) line(
|
|
10904
|
-
else line(
|
|
11455
|
+
else if (report.ok) line(import_picocolors38.default.yellow(summary));
|
|
11456
|
+
else line(import_picocolors38.default.red(summary));
|
|
10905
11457
|
}
|
|
10906
11458
|
function severityTag(severity) {
|
|
10907
|
-
if (severity === "high") return
|
|
10908
|
-
if (severity === "medium") return
|
|
10909
|
-
return
|
|
11459
|
+
if (severity === "high") return import_picocolors38.default.red("serious ");
|
|
11460
|
+
if (severity === "medium") return import_picocolors38.default.yellow("worth fixing");
|
|
11461
|
+
return import_picocolors38.default.dim("minor ");
|
|
10910
11462
|
}
|
|
10911
11463
|
function git(cwd, args) {
|
|
10912
11464
|
try {
|
|
@@ -10967,7 +11519,7 @@ function listRepoFiles2(root, maxDepth = 8) {
|
|
|
10967
11519
|
}
|
|
10968
11520
|
|
|
10969
11521
|
// src/commands/health.ts
|
|
10970
|
-
var
|
|
11522
|
+
var import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
10971
11523
|
function registerHealth(program3) {
|
|
10972
11524
|
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(
|
|
10973
11525
|
action(async ({ ctx, opts }) => {
|
|
@@ -10981,16 +11533,16 @@ function registerHealth(program3) {
|
|
|
10981
11533
|
}
|
|
10982
11534
|
function print3(res) {
|
|
10983
11535
|
if (!res?.checks?.length) {
|
|
10984
|
-
line(
|
|
11536
|
+
line(import_picocolors39.default.dim(res?.note ?? "Nothing to check."));
|
|
10985
11537
|
return;
|
|
10986
11538
|
}
|
|
10987
11539
|
for (const c of res.checks) {
|
|
10988
|
-
const mark = c.ok ?
|
|
10989
|
-
const timing =
|
|
10990
|
-
const detail = c.ok ? timing :
|
|
10991
|
-
line(` ${mark} ${c.appName} ${
|
|
11540
|
+
const mark = c.ok ? import_picocolors39.default.green("up ") : import_picocolors39.default.red("down");
|
|
11541
|
+
const timing = import_picocolors39.default.dim(`${c.ms}ms`);
|
|
11542
|
+
const detail = c.ok ? timing : import_picocolors39.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
|
|
11543
|
+
line(` ${mark} ${c.appName} ${import_picocolors39.default.dim(`(${c.environment})`)} ${c.url} ${detail}`);
|
|
10992
11544
|
if (c.incidentOpened) {
|
|
10993
|
-
line(
|
|
11545
|
+
line(import_picocolors39.default.yellow(` An incident has been opened on the board for this.`));
|
|
10994
11546
|
}
|
|
10995
11547
|
}
|
|
10996
11548
|
const down = res.checks.filter((c) => !c.ok);
|
|
@@ -11003,14 +11555,14 @@ function print3(res) {
|
|
|
11003
11555
|
}
|
|
11004
11556
|
const production = down.filter((c) => c.environment === "production").length;
|
|
11005
11557
|
line(
|
|
11006
|
-
|
|
11558
|
+
import_picocolors39.default.red(
|
|
11007
11559
|
`${down.length} of ${res.checks.length} not answering` + (production ? ` \u2014 ${production} customer-facing.` : " (preview only).")
|
|
11008
11560
|
)
|
|
11009
11561
|
);
|
|
11010
11562
|
}
|
|
11011
11563
|
|
|
11012
11564
|
// src/commands/urls.ts
|
|
11013
|
-
var
|
|
11565
|
+
var import_picocolors40 = __toESM(require_picocolors(), 1);
|
|
11014
11566
|
function registerUrls(program3) {
|
|
11015
11567
|
program3.command("urls").description("The stable preview and production addresses of every app in this project").option("--app <webAppId>", "just one app").action(
|
|
11016
11568
|
action(async ({ ctx, opts }) => {
|
|
@@ -11024,20 +11576,20 @@ function registerUrls(program3) {
|
|
|
11024
11576
|
const summary = urlsSummary(rows);
|
|
11025
11577
|
ok({ rows, summary }, () => {
|
|
11026
11578
|
for (const row of rows) {
|
|
11027
|
-
const label =
|
|
11028
|
-
const value = row.url ?
|
|
11579
|
+
const label = import_picocolors40.default.dim(row.environment.padEnd(10));
|
|
11580
|
+
const value = row.url ? import_picocolors40.default.cyan(row.url) : import_picocolors40.default.dim(row.note ?? "not published");
|
|
11029
11581
|
line(` ${row.appName.padEnd(22)} ${label} ${value}`);
|
|
11030
11582
|
}
|
|
11031
11583
|
line("");
|
|
11032
11584
|
if (rows.some((r) => r.url)) success(summary);
|
|
11033
|
-
else line(
|
|
11585
|
+
else line(import_picocolors40.default.yellow(summary));
|
|
11034
11586
|
});
|
|
11035
11587
|
})
|
|
11036
11588
|
);
|
|
11037
11589
|
}
|
|
11038
11590
|
|
|
11039
11591
|
// src/commands/deployments.ts
|
|
11040
|
-
var
|
|
11592
|
+
var import_picocolors41 = __toESM(require_picocolors(), 1);
|
|
11041
11593
|
function registerDeployments(program3) {
|
|
11042
11594
|
const cmd = program3.command("deployments").description("Deployment history, and putting a build in front of customers");
|
|
11043
11595
|
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(
|
|
@@ -11055,7 +11607,7 @@ function registerDeployments(program3) {
|
|
|
11055
11607
|
ok(res, () => {
|
|
11056
11608
|
if (!items.length) {
|
|
11057
11609
|
return line(
|
|
11058
|
-
|
|
11610
|
+
import_picocolors41.default.dim(
|
|
11059
11611
|
environment ? `Nothing has been deployed to ${environment} yet.` : "Nothing has been deployed yet. `workser deploy` builds the first one."
|
|
11060
11612
|
)
|
|
11061
11613
|
);
|
|
@@ -11075,13 +11627,13 @@ function registerDeployments(program3) {
|
|
|
11075
11627
|
).catch(() => null) : null;
|
|
11076
11628
|
ok({ ...dep, logs }, () => {
|
|
11077
11629
|
line(formatDeployment(dep));
|
|
11078
|
-
if (dep?.error_message) line(
|
|
11630
|
+
if (dep?.error_message) line(import_picocolors41.default.red(` ${dep.error_message}`));
|
|
11079
11631
|
const events = logs?.events ?? [];
|
|
11080
11632
|
for (const e of events) {
|
|
11081
|
-
line(` ${
|
|
11633
|
+
line(` ${import_picocolors41.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
|
|
11082
11634
|
}
|
|
11083
11635
|
if (opts.logs && !events.length) {
|
|
11084
|
-
line(
|
|
11636
|
+
line(import_picocolors41.default.dim(" That build produced no output."));
|
|
11085
11637
|
}
|
|
11086
11638
|
});
|
|
11087
11639
|
})
|
|
@@ -11125,16 +11677,16 @@ function printPromoted(res, version) {
|
|
|
11125
11677
|
const what = version === null ? "the latest build" : `version ${version}`;
|
|
11126
11678
|
const url = res.url ?? res.vercel_url;
|
|
11127
11679
|
success(`Production is being rebuilt from ${what}.`);
|
|
11128
|
-
if (url) line(
|
|
11129
|
-
line(
|
|
11680
|
+
if (url) line(import_picocolors41.default.dim(`It will be at ${url}`));
|
|
11681
|
+
line(import_picocolors41.default.dim("`workser deploy status` follows it."));
|
|
11130
11682
|
}
|
|
11131
11683
|
function formatDeployment(d) {
|
|
11132
11684
|
if (!d) return "";
|
|
11133
|
-
const version = d.version !== void 0 ?
|
|
11134
|
-
const env =
|
|
11685
|
+
const version = d.version !== void 0 ? import_picocolors41.default.yellow(`v${d.version}`) : import_picocolors41.default.dim("v?");
|
|
11686
|
+
const env = import_picocolors41.default.dim((d.environment ?? "?").padEnd(10));
|
|
11135
11687
|
const app = d.webAppName ? `${d.webAppName} ` : "";
|
|
11136
|
-
const when =
|
|
11137
|
-
const url = d.url ? " " +
|
|
11688
|
+
const when = import_picocolors41.default.dim(formatTime2(d.created_at));
|
|
11689
|
+
const url = d.url ? " " + import_picocolors41.default.cyan(d.url) : "";
|
|
11138
11690
|
return `${version} ${env} ${colorStatus(d.status ?? "")} ${app}${when}${url}`;
|
|
11139
11691
|
}
|
|
11140
11692
|
function formatTime2(t) {
|
|
@@ -11144,7 +11696,7 @@ function formatTime2(t) {
|
|
|
11144
11696
|
}
|
|
11145
11697
|
|
|
11146
11698
|
// src/commands/usage.ts
|
|
11147
|
-
var
|
|
11699
|
+
var import_picocolors42 = __toESM(require_picocolors(), 1);
|
|
11148
11700
|
|
|
11149
11701
|
// src/usage.ts
|
|
11150
11702
|
var NEAR_LIMIT_FRACTION = 0.8;
|
|
@@ -11239,7 +11791,7 @@ function registerUsage(program3) {
|
|
|
11239
11791
|
function print4(report) {
|
|
11240
11792
|
const dims = report.dimensions ?? [];
|
|
11241
11793
|
if (!dims.length) {
|
|
11242
|
-
return line(
|
|
11794
|
+
return line(import_picocolors42.default.dim("Nothing to measure for this project yet."));
|
|
11243
11795
|
}
|
|
11244
11796
|
const width = Math.max(...dims.map((d) => d.label.length));
|
|
11245
11797
|
for (const d of dims) {
|
|
@@ -11248,23 +11800,23 @@ function print4(report) {
|
|
|
11248
11800
|
line("");
|
|
11249
11801
|
const summary = usageSummary(report);
|
|
11250
11802
|
const worst = dims.map(usageState);
|
|
11251
|
-
if (worst.includes("over")) line(
|
|
11803
|
+
if (worst.includes("over")) line(import_picocolors42.default.red(summary));
|
|
11252
11804
|
else if (worst.includes("near") || worst.includes("unknown"))
|
|
11253
|
-
line(
|
|
11805
|
+
line(import_picocolors42.default.yellow(summary));
|
|
11254
11806
|
else success(summary);
|
|
11255
11807
|
}
|
|
11256
11808
|
function gauge(d, _labelWidth) {
|
|
11257
11809
|
const drawn = bar(d);
|
|
11258
|
-
return drawn ? ` ${
|
|
11810
|
+
return drawn ? ` ${import_picocolors42.default.dim(drawn)}` : "";
|
|
11259
11811
|
}
|
|
11260
11812
|
function colour(d) {
|
|
11261
11813
|
switch (usageState(d)) {
|
|
11262
11814
|
case "over":
|
|
11263
|
-
return d.kind === "hard" ?
|
|
11815
|
+
return d.kind === "hard" ? import_picocolors42.default.red : import_picocolors42.default.yellow;
|
|
11264
11816
|
case "near":
|
|
11265
|
-
return
|
|
11817
|
+
return import_picocolors42.default.yellow;
|
|
11266
11818
|
case "unknown":
|
|
11267
|
-
return
|
|
11819
|
+
return import_picocolors42.default.dim;
|
|
11268
11820
|
default:
|
|
11269
11821
|
return (s) => s;
|
|
11270
11822
|
}
|
|
@@ -11272,7 +11824,7 @@ function colour(d) {
|
|
|
11272
11824
|
|
|
11273
11825
|
// src/index.ts
|
|
11274
11826
|
var pkg = {
|
|
11275
|
-
version: true ? "0.6.
|
|
11827
|
+
version: true ? "0.6.17" : "0.0.0-dev"
|
|
11276
11828
|
};
|
|
11277
11829
|
var program2 = new Command();
|
|
11278
11830
|
program2.name("workser").description(
|
|
@@ -11305,6 +11857,7 @@ registerDomain(program2);
|
|
|
11305
11857
|
registerOpen(program2);
|
|
11306
11858
|
registerDoctor(program2);
|
|
11307
11859
|
registerAgent(program2);
|
|
11860
|
+
registerAgentCloud(program2);
|
|
11308
11861
|
registerVerify(program2);
|
|
11309
11862
|
registerApi(program2);
|
|
11310
11863
|
registerAnalysis(program2);
|