@workser/cli 0.6.8 → 0.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -0
- package/dist/index.js +509 -297
- package/package.json +1 -1
- package/skills/workser/SKILL.md +5 -9
- package/skills/workser/reference/key.md +40 -0
- package/skills/workser/reference/sdlc-entities.md +11 -0
package/dist/index.js
CHANGED
|
@@ -4636,6 +4636,47 @@ workser audio understand "transcribe this" --file ./voicemail.m4a -t transcribe
|
|
|
4636
4636
|
- **This is billed to the project's organization**, same as image generation \u2014 it's
|
|
4637
4637
|
a real provider call, not free introspection. Don't loop it over every file in a
|
|
4638
4638
|
folder "just in case"; use it when you actually need to know what's in one.
|
|
4639
|
+
`
|
|
4640
|
+
},
|
|
4641
|
+
{
|
|
4642
|
+
topic: "key",
|
|
4643
|
+
title: "Managed keys \u2014 list and rotate this app's Workser-issued credentials",
|
|
4644
|
+
summary: "See this app's AI Gateway and auth keys (redacted), and rotate one without opening Orbit.",
|
|
4645
|
+
commands: ["key"],
|
|
4646
|
+
source: "skills/workser/reference/key.md",
|
|
4647
|
+
body: `# Managed keys \u2014 list and rotate this app's Workser-issued credentials
|
|
4648
|
+
|
|
4649
|
+
\`\`\`
|
|
4650
|
+
workser key list [--app <webAppId>]
|
|
4651
|
+
workser key rotate <key> [--app <webAppId>] [--env production|preview]
|
|
4652
|
+
\`\`\`
|
|
4653
|
+
|
|
4654
|
+
App-scoped, not project-scoped: run from the app's own folder and \`--app\` is
|
|
4655
|
+
picked up automatically; from anywhere else, pass \`--app <webAppId>\` \u2014 a
|
|
4656
|
+
mistake here is the wrong app's key, so there is no "primary app" default the
|
|
4657
|
+
way \`env\` has one.
|
|
4658
|
+
|
|
4659
|
+
## What's rotatable
|
|
4660
|
+
|
|
4661
|
+
Only credentials with a real rotation handler:
|
|
4662
|
+
|
|
4663
|
+
- \`AI_GATEWAY_API_KEY\` \u2014 the deployed agent's key into the Workser AI
|
|
4664
|
+
Gateway. Split by environment (\`--env production\` or \`--env preview\`
|
|
4665
|
+
required), so rotating one never touches the other.
|
|
4666
|
+
- \`BETTER_AUTH_SECRET\` \u2014 a single value, no \`--env\` needed.
|
|
4667
|
+
|
|
4668
|
+
Every other Workser-managed value (\`DATABASE_URL\`, the internal service
|
|
4669
|
+
keys) has no rotation handler yet \u2014 each belongs to a different subsystem
|
|
4670
|
+
with its own cutover semantics, and \`key rotate\` refuses rather than fake
|
|
4671
|
+
one.
|
|
4672
|
+
|
|
4673
|
+
## After rotating
|
|
4674
|
+
|
|
4675
|
+
The old value stops authorizing immediately, server-side. An already-running
|
|
4676
|
+
deployment keeps using whatever it was built with until it's redeployed \u2014
|
|
4677
|
+
run \`workser deploy\` (\`--prod\` for the production key) to pick up the new
|
|
4678
|
+
value. \`key rotate\` prints the new secret exactly once; it is never shown
|
|
4679
|
+
again or stored anywhere in the clear.
|
|
4639
4680
|
`
|
|
4640
4681
|
},
|
|
4641
4682
|
{
|
|
@@ -4865,6 +4906,17 @@ workser doc create "Checkout \u2014 implementation plan" --markdown "$(cat plan.
|
|
|
4865
4906
|
workser decision create "Carts live server-side" --context "\u2026" --decision "\u2026" --json
|
|
4866
4907
|
\`\`\`
|
|
4867
4908
|
|
|
4909
|
+
**A wrong row is edited, not replaced.** If a subtask's title, teammate, note or
|
|
4910
|
+
scope is wrong after you created it, fix that same row:
|
|
4911
|
+
|
|
4912
|
+
\`\`\`bash
|
|
4913
|
+
workser task subtask update <id> --title "\u2026" --role api --note "\u2026" --scope "src/api"
|
|
4914
|
+
\`\`\`
|
|
4915
|
+
|
|
4916
|
+
Never tell the user a subtask is locked, and never file a second one alongside
|
|
4917
|
+
the wrong one \u2014 a plan with a duplicate phase in it is a plan nobody can read
|
|
4918
|
+
the progress of.
|
|
4919
|
+
|
|
4868
4920
|
**Don't pass \`--work-item\` for a multi-phase plan.** A linked document renders on
|
|
4869
4921
|
its card and is *hidden* from the Docs panel; a plan spanning three phases
|
|
4870
4922
|
belongs to the project, not to phase 1.
|
|
@@ -5511,6 +5563,10 @@ function requireProject(ctx) {
|
|
|
5511
5563
|
}
|
|
5512
5564
|
return ctx.projectId;
|
|
5513
5565
|
}
|
|
5566
|
+
function appTarget(ctx, explicit) {
|
|
5567
|
+
const said = typeof explicit === "string" ? explicit.trim() : "";
|
|
5568
|
+
return said || ctx.appId || void 0;
|
|
5569
|
+
}
|
|
5514
5570
|
|
|
5515
5571
|
// src/run.ts
|
|
5516
5572
|
function action(fn) {
|
|
@@ -6791,8 +6847,71 @@ function formatEnvValue(value) {
|
|
|
6791
6847
|
return /[\s"'#]/.test(value) ? JSON.stringify(value) : value;
|
|
6792
6848
|
}
|
|
6793
6849
|
|
|
6794
|
-
// src/commands/
|
|
6850
|
+
// src/commands/key.ts
|
|
6795
6851
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
6852
|
+
function requireApp(ctx, explicit) {
|
|
6853
|
+
const appId = appTarget(ctx, explicit);
|
|
6854
|
+
if (!appId) {
|
|
6855
|
+
throw new WorkserError(
|
|
6856
|
+
"No app to target.\n\n \u2022 Run this from the app's own folder (its ID is picked up automatically), or\n \u2022 pass --app <webAppId> \u2014 `workser project show` lists an app's ID.",
|
|
6857
|
+
{ code: "no_app" }
|
|
6858
|
+
);
|
|
6859
|
+
}
|
|
6860
|
+
return appId;
|
|
6861
|
+
}
|
|
6862
|
+
function registerKey(program3) {
|
|
6863
|
+
const key = program3.command("key").description("Manage this app's Workser-issued credentials (AI Gateway, auth secret)");
|
|
6864
|
+
key.command("list").description("List this app's managed keys (redacted \u2014 never the secret)").option("--app <webAppId>", "Which app (default: the one this folder is linked to)").action(
|
|
6865
|
+
action(async ({ ctx, opts }) => {
|
|
6866
|
+
const appId = requireApp(ctx, opts.app);
|
|
6867
|
+
const items = await api(ctx, `/v1/apps/${appId}/keys`);
|
|
6868
|
+
ok(items, () => {
|
|
6869
|
+
if (!items?.length) {
|
|
6870
|
+
return line(import_picocolors10.default.dim("No managed keys yet \u2014 they're created the first time this app deploys."));
|
|
6871
|
+
}
|
|
6872
|
+
for (const item of items) {
|
|
6873
|
+
const lastUsed = item.last_used_at ? `last used ${item.last_used_at}` : "never used yet";
|
|
6874
|
+
line(`${import_picocolors10.default.bold(item.environment)} ${item.prefix}\u2026 ${import_picocolors10.default.dim(`(${lastUsed})`)}`);
|
|
6875
|
+
}
|
|
6876
|
+
});
|
|
6877
|
+
})
|
|
6878
|
+
);
|
|
6879
|
+
key.command("rotate <key>").description("Rotate a managed key (AI_GATEWAY_API_KEY, BETTER_AUTH_SECRET)").option("--app <webAppId>", "Which app (default: the one this folder is linked to)").option("--env <environment>", "production or preview \u2014 required for AI_GATEWAY_API_KEY").action(
|
|
6880
|
+
action(async ({ ctx, args, opts }) => {
|
|
6881
|
+
const appId = requireApp(ctx, opts.app);
|
|
6882
|
+
const keyName = args[0];
|
|
6883
|
+
const environment = typeof opts.env === "string" ? opts.env : void 0;
|
|
6884
|
+
if (environment && environment !== "production" && environment !== "preview") {
|
|
6885
|
+
throw new WorkserError(
|
|
6886
|
+
`--env must be "production" or "preview", got "${environment}".`,
|
|
6887
|
+
{ code: "bad_input" }
|
|
6888
|
+
);
|
|
6889
|
+
}
|
|
6890
|
+
const res = await api(
|
|
6891
|
+
ctx,
|
|
6892
|
+
`/v1/apps/${appId}/keys/${encodeURIComponent(keyName)}/rotate`,
|
|
6893
|
+
{ body: { environment } }
|
|
6894
|
+
);
|
|
6895
|
+
ok(res, () => {
|
|
6896
|
+
success(`Rotated ${import_picocolors10.default.bold(keyName)}${res?.environment ? ` (${res.environment})` : ""}.`);
|
|
6897
|
+
if (res?.key) {
|
|
6898
|
+
line("");
|
|
6899
|
+
line(import_picocolors10.default.bold("New value \u2014 shown once, not stored anywhere in the clear:"));
|
|
6900
|
+
line(import_picocolors10.default.yellow(res.key));
|
|
6901
|
+
}
|
|
6902
|
+
line("");
|
|
6903
|
+
line(
|
|
6904
|
+
import_picocolors10.default.dim(
|
|
6905
|
+
"The old value stopped working immediately. If this app is already deployed, redeploy so it picks up the new one: workser deploy" + (res?.environment === "production" ? " --prod" : "")
|
|
6906
|
+
)
|
|
6907
|
+
);
|
|
6908
|
+
});
|
|
6909
|
+
})
|
|
6910
|
+
);
|
|
6911
|
+
}
|
|
6912
|
+
|
|
6913
|
+
// src/commands/deploy.ts
|
|
6914
|
+
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
6796
6915
|
var TERMINAL = /* @__PURE__ */ new Set(["ready", "live", "success", "error", "failed", "canceled"]);
|
|
6797
6916
|
function registerDeploy(program3) {
|
|
6798
6917
|
const deploy = program3.command("deploy").description("Deploy the current project to Workser (git \u2192 Vercel) and return a live URL").option("--prod", "deploy to production (same as --env production)", false).option(
|
|
@@ -6843,7 +6962,7 @@ async function watchDeploy(ctx, id) {
|
|
|
6843
6962
|
for (; ; ) {
|
|
6844
6963
|
const dep = await api(ctx, `/v1/deployments/${encodeURIComponent(id)}`);
|
|
6845
6964
|
if (!isJson() && dep.status !== last) {
|
|
6846
|
-
line(` ${colorStatus(dep.status)}${dep.url ? " " +
|
|
6965
|
+
line(` ${colorStatus(dep.status)}${dep.url ? " " + import_picocolors11.default.cyan(dep.url) : ""}`);
|
|
6847
6966
|
last = dep.status;
|
|
6848
6967
|
}
|
|
6849
6968
|
if (TERMINAL.has(String(dep.status).toLowerCase())) return dep;
|
|
@@ -6853,12 +6972,12 @@ async function watchDeploy(ctx, id) {
|
|
|
6853
6972
|
function printDeploy(dep) {
|
|
6854
6973
|
if (!dep) return;
|
|
6855
6974
|
const ready = ["ready", "live", "success"].includes(String(dep.status).toLowerCase());
|
|
6856
|
-
if (ready && dep.url) success(`Live at ${
|
|
6857
|
-
else line(`deploy ${colorStatus(dep.status)} ${
|
|
6975
|
+
if (ready && dep.url) success(`Live at ${import_picocolors11.default.cyan(dep.url)}`);
|
|
6976
|
+
else line(`deploy ${colorStatus(dep.status)} ${import_picocolors11.default.dim(`(${dep.id ?? "?"})`)}${dep.url ? " " + dep.url : ""}`);
|
|
6858
6977
|
}
|
|
6859
6978
|
|
|
6860
6979
|
// src/commands/versions.ts
|
|
6861
|
-
var
|
|
6980
|
+
var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
6862
6981
|
function registerVersions(program3) {
|
|
6863
6982
|
program3.command("versions").description("List the Workser-managed versions of the project (deploy history)").option("--app <webAppId>", "which app (defaults to the primary app)").option(
|
|
6864
6983
|
"--env <environment>",
|
|
@@ -6877,7 +6996,7 @@ function registerVersions(program3) {
|
|
|
6877
6996
|
}
|
|
6878
6997
|
});
|
|
6879
6998
|
ok(items, () => {
|
|
6880
|
-
if (!items?.length) return line(
|
|
6999
|
+
if (!items?.length) return line(import_picocolors12.default.dim("No versions yet. `workser deploy` to create one."));
|
|
6881
7000
|
for (const v of items) {
|
|
6882
7001
|
line(formatVersion(v));
|
|
6883
7002
|
}
|
|
@@ -6886,11 +7005,11 @@ function registerVersions(program3) {
|
|
|
6886
7005
|
);
|
|
6887
7006
|
}
|
|
6888
7007
|
function formatVersion(v) {
|
|
6889
|
-
const ref =
|
|
6890
|
-
const when =
|
|
6891
|
-
const msg = (v.message ?? "").trim() ||
|
|
6892
|
-
const badge = v.deployed ? " " +
|
|
6893
|
-
const url = v.url ? " " +
|
|
7008
|
+
const ref = import_picocolors12.default.yellow(shortRef(v.ref));
|
|
7009
|
+
const when = import_picocolors12.default.dim(formatTime(v.createdAt));
|
|
7010
|
+
const msg = (v.message ?? "").trim() || import_picocolors12.default.dim("(no message)");
|
|
7011
|
+
const badge = v.deployed ? " " + import_picocolors12.default.green(v.deployedEnvironment ? `live in ${v.deployedEnvironment}` : "deployed") : "";
|
|
7012
|
+
const url = v.url ? " " + import_picocolors12.default.cyan(v.url) : "";
|
|
6894
7013
|
return `${ref} ${when} ${msg}${badge}${url}`;
|
|
6895
7014
|
}
|
|
6896
7015
|
function shortRef(ref) {
|
|
@@ -6904,7 +7023,7 @@ function formatTime(t) {
|
|
|
6904
7023
|
}
|
|
6905
7024
|
|
|
6906
7025
|
// src/commands/logs.ts
|
|
6907
|
-
var
|
|
7026
|
+
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
6908
7027
|
function registerLogs(program3) {
|
|
6909
7028
|
program3.command("logs").description("Show the build logs of the latest deployment").option("-n, --lines <n>", "number of lines", "100").option("-f, --follow", "keep streaming new logs", false).option("--app <webAppId>", "which app (defaults to the primary app)").option("--env <environment>", "preview or production (default: whichever deployed last)").action(
|
|
6910
7029
|
action(async ({ ctx, opts }) => {
|
|
@@ -6938,10 +7057,10 @@ function registerLogs(program3) {
|
|
|
6938
7057
|
function print(res) {
|
|
6939
7058
|
const entries = res?.entries ?? [];
|
|
6940
7059
|
for (const e of entries) line(formatLog(e));
|
|
6941
|
-
if (!entries.length && res?.note) line(
|
|
7060
|
+
if (!entries.length && res?.note) line(import_picocolors13.default.dim(res.note));
|
|
6942
7061
|
if (entries.length && res?.deploymentId) {
|
|
6943
7062
|
const where = res.environment ? ` (${res.environment})` : "";
|
|
6944
|
-
line(
|
|
7063
|
+
line(import_picocolors13.default.dim(`\u2014 build ${res.deploymentId}${where}`));
|
|
6945
7064
|
}
|
|
6946
7065
|
}
|
|
6947
7066
|
function formatLog(e) {
|
|
@@ -6950,7 +7069,7 @@ function formatLog(e) {
|
|
|
6950
7069
|
}
|
|
6951
7070
|
|
|
6952
7071
|
// src/commands/domain.ts
|
|
6953
|
-
var
|
|
7072
|
+
var import_picocolors14 = __toESM(require_picocolors(), 1);
|
|
6954
7073
|
|
|
6955
7074
|
// src/reserved-domains.ts
|
|
6956
7075
|
var RESERVED_APEX = [
|
|
@@ -7013,9 +7132,9 @@ function registerDomain(program3) {
|
|
|
7013
7132
|
{ method: "POST", body: { domain: host } }
|
|
7014
7133
|
);
|
|
7015
7134
|
ok(result, () => {
|
|
7016
|
-
line(`${
|
|
7135
|
+
line(`${import_picocolors14.default.green("Attached")} ${host}`);
|
|
7017
7136
|
line(
|
|
7018
|
-
|
|
7137
|
+
import_picocolors14.default.dim(
|
|
7019
7138
|
"It goes live once DNS points at us. Run `workser domain list` to see its status."
|
|
7020
7139
|
)
|
|
7021
7140
|
);
|
|
@@ -7031,7 +7150,7 @@ function registerDomain(program3) {
|
|
|
7031
7150
|
opts.app ? `/v1/projects/${projectId}/web-apps/${opts.app}/domains/${encodeURIComponent(host)}` : `/v1/projects/${projectId}/domains/${encodeURIComponent(host)}`,
|
|
7032
7151
|
{ method: "DELETE" }
|
|
7033
7152
|
);
|
|
7034
|
-
ok(result, () => line(`${
|
|
7153
|
+
ok(result, () => line(`${import_picocolors14.default.yellow("Detached")} ${host}`));
|
|
7035
7154
|
})
|
|
7036
7155
|
);
|
|
7037
7156
|
domain.command("list").description("List domains attached to the project").action(
|
|
@@ -7039,8 +7158,8 @@ function registerDomain(program3) {
|
|
|
7039
7158
|
const projectId = requireProject(ctx);
|
|
7040
7159
|
const items = await api(ctx, `/v1/projects/${projectId}/domains`);
|
|
7041
7160
|
ok(items, () => {
|
|
7042
|
-
if (!items?.length) return line(
|
|
7043
|
-
for (const d of items) line(`${d.domain}${
|
|
7161
|
+
if (!items?.length) return line(import_picocolors14.default.dim("No custom domains."));
|
|
7162
|
+
for (const d of items) line(`${d.domain}${import_picocolors14.default.dim(" " + (d.status ?? ""))}`);
|
|
7044
7163
|
});
|
|
7045
7164
|
})
|
|
7046
7165
|
);
|
|
@@ -7072,7 +7191,7 @@ function openUrl(url) {
|
|
|
7072
7191
|
}
|
|
7073
7192
|
|
|
7074
7193
|
// src/commands/doctor.ts
|
|
7075
|
-
var
|
|
7194
|
+
var import_picocolors15 = __toESM(require_picocolors(), 1);
|
|
7076
7195
|
import { spawnSync } from "child_process";
|
|
7077
7196
|
function registerDoctor(program3) {
|
|
7078
7197
|
program3.command("doctor").description("Print the resolved endpoint, mode, token presence (masked), and current project").action(
|
|
@@ -7106,29 +7225,29 @@ function registerDoctor(program3) {
|
|
|
7106
7225
|
workspace: session.workspaceName ?? null
|
|
7107
7226
|
};
|
|
7108
7227
|
ok(report, () => {
|
|
7109
|
-
line(
|
|
7110
|
-
line(` endpoint: ${ctx.endpoint} ${
|
|
7228
|
+
line(import_picocolors15.default.bold("workser doctor"));
|
|
7229
|
+
line(` endpoint: ${ctx.endpoint} ${import_picocolors15.default.dim(`(${endpointSource})`)}`);
|
|
7111
7230
|
line(
|
|
7112
|
-
` env: ${env === "prod" ?
|
|
7231
|
+
` env: ${env === "prod" ? import_picocolors15.default.yellow(env) : env}` + import_picocolors15.default.dim(process.env.WORKSER_ENV ? " ($WORKSER_ENV)" : " (default)")
|
|
7113
7232
|
);
|
|
7114
7233
|
line(` mode: ${ctx.mode}`);
|
|
7115
7234
|
line(
|
|
7116
|
-
` token: ${ctx.token ? `${maskToken(ctx.token)} ${
|
|
7235
|
+
` token: ${ctx.token ? `${maskToken(ctx.token)} ${import_picocolors15.default.dim(`(${tokenSource})`)}` : import_picocolors15.default.yellow("none \u2014 run `workser login`")}`
|
|
7117
7236
|
);
|
|
7118
7237
|
line(
|
|
7119
|
-
` project: ${ctx.projectId ??
|
|
7238
|
+
` project: ${ctx.projectId ?? import_picocolors15.default.dim("none")}` + (link?.name ? ` ${import_picocolors15.default.dim(`(${link.name})`)}` : "") + (projectSource ? import_picocolors15.default.dim(` [${projectSource}]`) : "")
|
|
7120
7239
|
);
|
|
7121
7240
|
line(` cwd: ${ctx.cwd}`);
|
|
7122
|
-
line(` git: ${git2 ??
|
|
7241
|
+
line(` git: ${git2 ?? import_picocolors15.default.dim("not on this shell's PATH")}`);
|
|
7123
7242
|
if (!git2) {
|
|
7124
7243
|
line("");
|
|
7125
7244
|
line(
|
|
7126
|
-
|
|
7245
|
+
import_picocolors15.default.dim(
|
|
7127
7246
|
" Workser brings its own git, so syncing and publishing still work."
|
|
7128
7247
|
)
|
|
7129
7248
|
);
|
|
7130
7249
|
line(
|
|
7131
|
-
|
|
7250
|
+
import_picocolors15.default.dim(
|
|
7132
7251
|
` Only needed if you want to run git yourself here. ${GIT_INSTALL_HINT}`
|
|
7133
7252
|
)
|
|
7134
7253
|
);
|
|
@@ -7136,16 +7255,16 @@ function registerDoctor(program3) {
|
|
|
7136
7255
|
if (envIgnored) {
|
|
7137
7256
|
line("");
|
|
7138
7257
|
line(
|
|
7139
|
-
|
|
7258
|
+
import_picocolors15.default.yellow(
|
|
7140
7259
|
` WORKSER_ENV=${env} is not in effect \u2014 ${endpointSource} wins.`
|
|
7141
7260
|
)
|
|
7142
7261
|
);
|
|
7143
7262
|
line(
|
|
7144
|
-
|
|
7263
|
+
import_picocolors15.default.dim(
|
|
7145
7264
|
` Re-run \`workser login\` to switch (the saved token is tied to ${ctx.endpoint}),`
|
|
7146
7265
|
)
|
|
7147
7266
|
);
|
|
7148
|
-
line(
|
|
7267
|
+
line(import_picocolors15.default.dim(` or pass --endpoint ${ENV_BASE_URLS[env]}.`));
|
|
7149
7268
|
}
|
|
7150
7269
|
});
|
|
7151
7270
|
})
|
|
@@ -7175,7 +7294,32 @@ function maskToken(token) {
|
|
|
7175
7294
|
}
|
|
7176
7295
|
|
|
7177
7296
|
// src/commands/agent.ts
|
|
7178
|
-
var
|
|
7297
|
+
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
7298
|
+
|
|
7299
|
+
// src/model-policy.ts
|
|
7300
|
+
var DELEGATION_BLOCKED_MODELS = [
|
|
7301
|
+
{
|
|
7302
|
+
match: "fable",
|
|
7303
|
+
label: "Claude Fable 5",
|
|
7304
|
+
reason: "it is the most expensive model available and no delegated run is worth it \u2014 ask the owner if you think this one is"
|
|
7305
|
+
}
|
|
7306
|
+
];
|
|
7307
|
+
function blockedDelegationModel(model) {
|
|
7308
|
+
const value = (model ?? "").trim().toLowerCase();
|
|
7309
|
+
if (!value) return null;
|
|
7310
|
+
return DELEGATION_BLOCKED_MODELS.find((entry) => value.includes(entry.match)) ?? null;
|
|
7311
|
+
}
|
|
7312
|
+
function assertDelegatableModel(flag, model) {
|
|
7313
|
+
const blocked = blockedDelegationModel(model);
|
|
7314
|
+
if (!blocked || !model) return;
|
|
7315
|
+
throw new WorkserError(
|
|
7316
|
+
`${flag} "${model}" can't be chosen for a delegated run: ${blocked.reason}.
|
|
7317
|
+
Pick another model, or leave ${flag} off to use the agent's own default.`,
|
|
7318
|
+
{ code: "bad_request" }
|
|
7319
|
+
);
|
|
7320
|
+
}
|
|
7321
|
+
|
|
7322
|
+
// src/commands/agent.ts
|
|
7179
7323
|
var SPAWNABLE_AGENTS = ["claude_code", "codex", "kimi", "opencode", "grok"];
|
|
7180
7324
|
function registerAgent(program3) {
|
|
7181
7325
|
const agent = program3.command("agent").description("Delegate focused subtasks to your configured agent roles (each runs isolated)");
|
|
@@ -7183,20 +7327,20 @@ function registerAgent(program3) {
|
|
|
7183
7327
|
action(async ({ ctx }) => {
|
|
7184
7328
|
const cfg = await api(ctx, "/v1/agents");
|
|
7185
7329
|
ok(cfg, () => {
|
|
7186
|
-
line(
|
|
7187
|
-
line(
|
|
7330
|
+
line(import_picocolors16.default.bold("main agent:") + " " + (cfg?.mainAgent ?? import_picocolors16.default.dim("none")));
|
|
7331
|
+
line(import_picocolors16.default.bold("backup agent:") + " " + (cfg?.backupAgent ?? import_picocolors16.default.dim("none")));
|
|
7188
7332
|
if (cfg?.effectiveMainAgent && cfg.effectiveMainAgent !== cfg.mainAgent) {
|
|
7189
7333
|
line(
|
|
7190
|
-
|
|
7334
|
+
import_picocolors16.default.yellow(
|
|
7191
7335
|
` \u2937 failover active: runs use ${cfg.effectiveMainAgent} (main not available)`
|
|
7192
7336
|
)
|
|
7193
7337
|
);
|
|
7194
7338
|
}
|
|
7195
7339
|
const roles = cfg?.roles ?? [];
|
|
7196
7340
|
if (!roles.length) {
|
|
7197
|
-
line(
|
|
7341
|
+
line(import_picocolors16.default.dim("No subagents configured. Add them in the Workser Orbit Agents screen."));
|
|
7198
7342
|
} else {
|
|
7199
|
-
line(
|
|
7343
|
+
line(import_picocolors16.default.bold("subagents:"));
|
|
7200
7344
|
for (const r of roles) line(" " + formatRole(r));
|
|
7201
7345
|
}
|
|
7202
7346
|
const detected = cfg?.detected ?? [];
|
|
@@ -7204,7 +7348,7 @@ function registerAgent(program3) {
|
|
|
7204
7348
|
(d) => d?.installed && d?.authed !== false
|
|
7205
7349
|
);
|
|
7206
7350
|
line(
|
|
7207
|
-
|
|
7351
|
+
import_picocolors16.default.bold("spawnable (workser agent spawn <agent>):") + " " + (spawnable.length ? spawnable.map((d) => toContractId(d.id)).join(", ") : import_picocolors16.default.dim("none connected"))
|
|
7208
7352
|
);
|
|
7209
7353
|
});
|
|
7210
7354
|
})
|
|
@@ -7218,8 +7362,8 @@ function registerAgent(program3) {
|
|
|
7218
7362
|
backupAgent: cfg?.backupAgent ?? null
|
|
7219
7363
|
},
|
|
7220
7364
|
() => {
|
|
7221
|
-
line(
|
|
7222
|
-
line(
|
|
7365
|
+
line(import_picocolors16.default.bold("main agent:") + " " + (cfg?.mainAgent ?? import_picocolors16.default.dim("none")));
|
|
7366
|
+
line(import_picocolors16.default.bold("backup agent:") + " " + (cfg?.backupAgent ?? import_picocolors16.default.dim("none")));
|
|
7223
7367
|
}
|
|
7224
7368
|
);
|
|
7225
7369
|
})
|
|
@@ -7251,6 +7395,7 @@ function registerAgent(program3) {
|
|
|
7251
7395
|
action(async ({ ctx, args, opts }) => {
|
|
7252
7396
|
const spawnAgent = args[0];
|
|
7253
7397
|
const task = args[1].join(" ");
|
|
7398
|
+
assertDelegatableModel("--model", opts.model);
|
|
7254
7399
|
const res = await api(ctx, "/v1/agents/run", {
|
|
7255
7400
|
body: {
|
|
7256
7401
|
agent: spawnAgent,
|
|
@@ -7279,21 +7424,21 @@ function toContractId(id) {
|
|
|
7279
7424
|
return id === "claude" ? "claude_code" : id;
|
|
7280
7425
|
}
|
|
7281
7426
|
function formatRole(r) {
|
|
7282
|
-
const label =
|
|
7283
|
-
const agent =
|
|
7284
|
-
const enabled = r.enabled === false ?
|
|
7427
|
+
const label = import_picocolors16.default.yellow(r.role);
|
|
7428
|
+
const agent = import_picocolors16.default.dim("\xB7 " + (r.agent ?? "?"));
|
|
7429
|
+
const enabled = r.enabled === false ? import_picocolors16.default.red("disabled") : import_picocolors16.default.green("enabled");
|
|
7285
7430
|
const runnable = r.installed && r.authed !== false;
|
|
7286
|
-
const ready = runnable ?
|
|
7431
|
+
const ready = runnable ? import_picocolors16.default.green("runnable") : import_picocolors16.default.dim("not runnable");
|
|
7287
7432
|
const extras = [];
|
|
7288
7433
|
if (r.model) extras.push(`model ${r.model}`);
|
|
7289
7434
|
if (Array.isArray(r.apps) && r.apps.length) extras.push(`apps: ${r.apps.join(",")}`);
|
|
7290
7435
|
if (Array.isArray(r.mcp) && r.mcp.length) extras.push(`mcp: ${r.mcp.length}`);
|
|
7291
|
-
const tail = extras.length ? " " +
|
|
7436
|
+
const tail = extras.length ? " " + import_picocolors16.default.dim(extras.join(" \xB7 ")) : "";
|
|
7292
7437
|
return `${label} ${agent} ${enabled} ${ready}${tail}`;
|
|
7293
7438
|
}
|
|
7294
7439
|
|
|
7295
7440
|
// src/commands/verify.ts
|
|
7296
|
-
var
|
|
7441
|
+
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
7297
7442
|
function registerVerify(program3) {
|
|
7298
7443
|
program3.command("verify").description(
|
|
7299
7444
|
"Run the project's checks (typecheck/lint/build) \u2014 use before declaring a task done"
|
|
@@ -7315,23 +7460,23 @@ function registerVerify(program3) {
|
|
|
7315
7460
|
function printVerify(res) {
|
|
7316
7461
|
if (!res) return;
|
|
7317
7462
|
if (!res.checks?.length) {
|
|
7318
|
-
line(
|
|
7463
|
+
line(import_picocolors17.default.dim(res.note ?? "No checks detected."));
|
|
7319
7464
|
return;
|
|
7320
7465
|
}
|
|
7321
7466
|
for (const c of res.checks) {
|
|
7322
7467
|
line(
|
|
7323
|
-
` ${c.ok ?
|
|
7468
|
+
` ${c.ok ? import_picocolors17.default.green("\u2713") : import_picocolors17.default.red("\u2717")} ${c.name}${c.ok ? "" : import_picocolors17.default.dim(` (exit ${c.exitCode})`)}`
|
|
7324
7469
|
);
|
|
7325
7470
|
}
|
|
7326
7471
|
if (res.ok) success("All checks passed");
|
|
7327
7472
|
else
|
|
7328
7473
|
line(
|
|
7329
|
-
|
|
7474
|
+
import_picocolors17.default.red("Some checks failed \u2014 fix the errors above and re-run ") + import_picocolors17.default.bold("workser verify") + import_picocolors17.default.red(".")
|
|
7330
7475
|
);
|
|
7331
7476
|
}
|
|
7332
7477
|
|
|
7333
7478
|
// src/commands/checkpoint.ts
|
|
7334
|
-
var
|
|
7479
|
+
var import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
7335
7480
|
function registerCheckpoint(program3) {
|
|
7336
7481
|
program3.command("checkpoint [label]").description(
|
|
7337
7482
|
"Save the current state of this folder so you can come back to it"
|
|
@@ -7348,8 +7493,8 @@ function registerCheckpoint(program3) {
|
|
|
7348
7493
|
ok(res, () => {
|
|
7349
7494
|
const p = res?.point;
|
|
7350
7495
|
success(`Saved a checkpoint${p?.label ? `: ${p.label}` : ""}`);
|
|
7351
|
-
if (p?.ref) line(
|
|
7352
|
-
line(
|
|
7496
|
+
if (p?.ref) line(import_picocolors18.default.dim(` ${p.ref.slice(0, 7)}`));
|
|
7497
|
+
line(import_picocolors18.default.dim(" Come back to it with `workser restore`."));
|
|
7353
7498
|
});
|
|
7354
7499
|
})
|
|
7355
7500
|
);
|
|
@@ -7375,12 +7520,12 @@ function registerCheckpoint(program3) {
|
|
|
7375
7520
|
);
|
|
7376
7521
|
if (res?.filesChanged) {
|
|
7377
7522
|
line(
|
|
7378
|
-
|
|
7523
|
+
import_picocolors18.default.dim(
|
|
7379
7524
|
` ${res.filesChanged} file${res.filesChanged === 1 ? "" : "s"} changed`
|
|
7380
7525
|
)
|
|
7381
7526
|
);
|
|
7382
7527
|
}
|
|
7383
|
-
line(
|
|
7528
|
+
line(import_picocolors18.default.dim(" This is reversible: `workser restore` again."));
|
|
7384
7529
|
});
|
|
7385
7530
|
})
|
|
7386
7531
|
);
|
|
@@ -7397,25 +7542,25 @@ function registerCheckpoint(program3) {
|
|
|
7397
7542
|
function printPoints(points) {
|
|
7398
7543
|
if (!points.length) {
|
|
7399
7544
|
info("No checkpoints yet for this folder.");
|
|
7400
|
-
line(
|
|
7545
|
+
line(import_picocolors18.default.dim(" Take one with `workser checkpoint`."));
|
|
7401
7546
|
return;
|
|
7402
7547
|
}
|
|
7403
|
-
line(
|
|
7548
|
+
line(import_picocolors18.default.bold("Checkpoints"));
|
|
7404
7549
|
for (const p of points) {
|
|
7405
7550
|
const when = p.at ? new Date(p.at).toLocaleString() : "";
|
|
7406
7551
|
line(
|
|
7407
|
-
` ${
|
|
7552
|
+
` ${import_picocolors18.default.dim(p.ref.slice(0, 7))} ${p.label}${when ? import_picocolors18.default.dim(` ${when}`) : ""}`
|
|
7408
7553
|
);
|
|
7409
7554
|
}
|
|
7410
7555
|
line(
|
|
7411
|
-
|
|
7556
|
+
import_picocolors18.default.dim(
|
|
7412
7557
|
"\nGo back with `workser restore <ref>`, or just `workser restore` for the newest."
|
|
7413
7558
|
)
|
|
7414
7559
|
);
|
|
7415
7560
|
}
|
|
7416
7561
|
|
|
7417
7562
|
// src/commands/sync.ts
|
|
7418
|
-
var
|
|
7563
|
+
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
7419
7564
|
function registerSync(program3) {
|
|
7420
7565
|
program3.command("sync").description(
|
|
7421
7566
|
"Reconcile this folder with the copy Workser holds (pull, then push)"
|
|
@@ -7442,7 +7587,7 @@ function registerSync(program3) {
|
|
|
7442
7587
|
warn(res?.message ?? "Couldn't sync this folder.");
|
|
7443
7588
|
if (res?.state === "diverged") {
|
|
7444
7589
|
line(
|
|
7445
|
-
|
|
7590
|
+
import_picocolors19.default.dim(
|
|
7446
7591
|
" This folder and Workser's copy have both changed. Open Workser to resolve it."
|
|
7447
7592
|
)
|
|
7448
7593
|
);
|
|
@@ -7454,7 +7599,7 @@ function registerSync(program3) {
|
|
|
7454
7599
|
return;
|
|
7455
7600
|
}
|
|
7456
7601
|
success("Synced");
|
|
7457
|
-
if (res?.ref) line(
|
|
7602
|
+
if (res?.ref) line(import_picocolors19.default.dim(` ${String(res.ref).slice(0, 7)}`));
|
|
7458
7603
|
});
|
|
7459
7604
|
if (refused) process.exitCode = 1;
|
|
7460
7605
|
})
|
|
@@ -7462,7 +7607,7 @@ function registerSync(program3) {
|
|
|
7462
7607
|
}
|
|
7463
7608
|
|
|
7464
7609
|
// src/commands/workflow.ts
|
|
7465
|
-
var
|
|
7610
|
+
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
7466
7611
|
function registerWorkflow(program3) {
|
|
7467
7612
|
const wf = program3.command("workflow").description("Create, run, and inspect workflow automations for the project");
|
|
7468
7613
|
wf.command("list").description("List the project's workflows").action(
|
|
@@ -7470,10 +7615,10 @@ function registerWorkflow(program3) {
|
|
|
7470
7615
|
const projectId = requireProject(ctx);
|
|
7471
7616
|
const items = await api(ctx, `/v1/projects/${projectId}/workflows`);
|
|
7472
7617
|
ok(items, () => {
|
|
7473
|
-
if (!items?.length) return line(
|
|
7618
|
+
if (!items?.length) return line(import_picocolors20.default.dim("No workflows yet. `workser workflow create`."));
|
|
7474
7619
|
for (const w of items) {
|
|
7475
|
-
const status = w.is_active ?
|
|
7476
|
-
line(`${w.id} ${
|
|
7620
|
+
const status = w.is_active ? import_picocolors20.default.green("active") : import_picocolors20.default.dim("inactive");
|
|
7621
|
+
line(`${w.id} ${import_picocolors20.default.bold(w.name ?? "Untitled")} ${status}`);
|
|
7477
7622
|
}
|
|
7478
7623
|
});
|
|
7479
7624
|
})
|
|
@@ -7485,7 +7630,7 @@ function registerWorkflow(program3) {
|
|
|
7485
7630
|
const res = await api(ctx, `/v1/projects/${projectId}/workflows`, {
|
|
7486
7631
|
body: { name: args[0], ...extra }
|
|
7487
7632
|
});
|
|
7488
|
-
ok(res, () => line(`Created workflow ${
|
|
7633
|
+
ok(res, () => line(`Created workflow ${import_picocolors20.default.bold(res.id)}.`));
|
|
7489
7634
|
})
|
|
7490
7635
|
);
|
|
7491
7636
|
wf.command("get <id>").description("Show a workflow's full definition").action(
|
|
@@ -7520,8 +7665,8 @@ function registerWorkflow(program3) {
|
|
|
7520
7665
|
action(async ({ ctx, args }) => {
|
|
7521
7666
|
const items = await api(ctx, `/v1/workflows/${args[0]}/executions`);
|
|
7522
7667
|
ok(items, () => {
|
|
7523
|
-
if (!items?.length) return line(
|
|
7524
|
-
for (const e of items) line(`${e.id} ${e.status ?? ""} ${
|
|
7668
|
+
if (!items?.length) return line(import_picocolors20.default.dim("No runs yet."));
|
|
7669
|
+
for (const e of items) line(`${e.id} ${e.status ?? ""} ${import_picocolors20.default.dim(e.started_at ?? "")}`);
|
|
7525
7670
|
});
|
|
7526
7671
|
})
|
|
7527
7672
|
);
|
|
@@ -7529,15 +7674,15 @@ function registerWorkflow(program3) {
|
|
|
7529
7674
|
action(async ({ ctx, args }) => {
|
|
7530
7675
|
const items = await api(ctx, `/v1/node-types`, { query: { q: args[0] } });
|
|
7531
7676
|
ok(items, () => {
|
|
7532
|
-
if (!items?.length) return line(
|
|
7533
|
-
for (const n of items) line(`${n.name ?? n.type} ${
|
|
7677
|
+
if (!items?.length) return line(import_picocolors20.default.dim("No matching node types."));
|
|
7678
|
+
for (const n of items) line(`${n.name ?? n.type} ${import_picocolors20.default.dim(n.category ?? "")}`);
|
|
7534
7679
|
});
|
|
7535
7680
|
})
|
|
7536
7681
|
);
|
|
7537
7682
|
}
|
|
7538
7683
|
|
|
7539
7684
|
// src/commands/connection.ts
|
|
7540
|
-
var
|
|
7685
|
+
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
7541
7686
|
function registerConnection(program3) {
|
|
7542
7687
|
const connection = program3.command("connection").description("Connect and use third-party app connections (Gmail, Slack, Stripe, ...)");
|
|
7543
7688
|
connection.command("list").description("List connectable toolkits and this project's existing connections").option("--toolkit <slug>", "filter connections to one toolkit").action(
|
|
@@ -7550,8 +7695,8 @@ function registerConnection(program3) {
|
|
|
7550
7695
|
ok({ catalog, connections }, () => {
|
|
7551
7696
|
const connected = new Set((connections ?? []).map((c) => c.toolkit ?? c.composio_app));
|
|
7552
7697
|
for (const t of catalog ?? []) {
|
|
7553
|
-
const status = connected.has(t.slug) ?
|
|
7554
|
-
line(`${t.slug} ${
|
|
7698
|
+
const status = connected.has(t.slug) ? import_picocolors21.default.green("connected") : import_picocolors21.default.dim("not connected");
|
|
7699
|
+
line(`${t.slug} ${import_picocolors21.default.bold(t.name ?? t.slug)} ${status}`);
|
|
7555
7700
|
}
|
|
7556
7701
|
});
|
|
7557
7702
|
})
|
|
@@ -7563,9 +7708,9 @@ function registerConnection(program3) {
|
|
|
7563
7708
|
query: { q: args[0], toolkit: opts.toolkit, limit: opts.limit }
|
|
7564
7709
|
});
|
|
7565
7710
|
ok(items, () => {
|
|
7566
|
-
if (!items?.length) return line(
|
|
7711
|
+
if (!items?.length) return line(import_picocolors21.default.dim("No matching actions."));
|
|
7567
7712
|
for (const t of items) {
|
|
7568
|
-
line(`${t.slug} ${
|
|
7713
|
+
line(`${t.slug} ${import_picocolors21.default.dim(`[${t.toolkit}]`)} ${t.description ?? ""}`);
|
|
7569
7714
|
}
|
|
7570
7715
|
});
|
|
7571
7716
|
})
|
|
@@ -7582,7 +7727,7 @@ function registerConnection(program3) {
|
|
|
7582
7727
|
});
|
|
7583
7728
|
ok(
|
|
7584
7729
|
res,
|
|
7585
|
-
() => res.oauth_url ? line(`Open this URL to finish connecting: ${
|
|
7730
|
+
() => res.oauth_url ? line(`Open this URL to finish connecting: ${import_picocolors21.default.underline(res.oauth_url)}`) : line(`Connection ${res.connection_id} is ${res.status}.`)
|
|
7586
7731
|
);
|
|
7587
7732
|
})
|
|
7588
7733
|
);
|
|
@@ -7600,8 +7745,8 @@ function registerConnection(program3) {
|
|
|
7600
7745
|
const projectId = requireProject(ctx);
|
|
7601
7746
|
const items = await api(ctx, `/v1/projects/${projectId}/integrations/${args[0]}/tools`);
|
|
7602
7747
|
ok(items, () => {
|
|
7603
|
-
if (!items?.length) return line(
|
|
7604
|
-
for (const t of items) line(`${t.slug} ${
|
|
7748
|
+
if (!items?.length) return line(import_picocolors21.default.dim("No tools found."));
|
|
7749
|
+
for (const t of items) line(`${t.slug} ${import_picocolors21.default.dim(t.description ?? "")}`);
|
|
7605
7750
|
});
|
|
7606
7751
|
})
|
|
7607
7752
|
);
|
|
@@ -7617,7 +7762,7 @@ function registerConnection(program3) {
|
|
|
7617
7762
|
}
|
|
7618
7763
|
|
|
7619
7764
|
// src/commands/tool.ts
|
|
7620
|
-
var
|
|
7765
|
+
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
7621
7766
|
function registerTool(program3) {
|
|
7622
7767
|
const tool = program3.command("tool").description(
|
|
7623
7768
|
"Computer-use tools: filesystem, shell, screenshot, input control, clipboard, notifications, basic browser"
|
|
@@ -7626,7 +7771,7 @@ function registerTool(program3) {
|
|
|
7626
7771
|
action(async ({ ctx }) => {
|
|
7627
7772
|
const tools = await api(ctx, "/v1/tool/list");
|
|
7628
7773
|
ok(tools, () => {
|
|
7629
|
-
if (!tools?.length) return line(
|
|
7774
|
+
if (!tools?.length) return line(import_picocolors22.default.dim("No tools available."));
|
|
7630
7775
|
const byCategory = /* @__PURE__ */ new Map();
|
|
7631
7776
|
for (const t of tools) {
|
|
7632
7777
|
const list = byCategory.get(t.category) ?? [];
|
|
@@ -7634,9 +7779,9 @@ function registerTool(program3) {
|
|
|
7634
7779
|
byCategory.set(t.category, list);
|
|
7635
7780
|
}
|
|
7636
7781
|
for (const [category, items] of byCategory) {
|
|
7637
|
-
line(
|
|
7782
|
+
line(import_picocolors22.default.bold(category) + ":");
|
|
7638
7783
|
for (const t of items) {
|
|
7639
|
-
line(` ${t.name} ${
|
|
7784
|
+
line(` ${t.name} ${import_picocolors22.default.dim(t.description ?? "")}`);
|
|
7640
7785
|
}
|
|
7641
7786
|
}
|
|
7642
7787
|
});
|
|
@@ -7654,7 +7799,7 @@ function registerTool(program3) {
|
|
|
7654
7799
|
}
|
|
7655
7800
|
|
|
7656
7801
|
// src/commands/memory.ts
|
|
7657
|
-
var
|
|
7802
|
+
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
7658
7803
|
function registerMemory(program3) {
|
|
7659
7804
|
const memory = program3.command("memory").description("Durable, cross-conversation project memory (shared with cloud agents on the same project)");
|
|
7660
7805
|
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(
|
|
@@ -7678,9 +7823,9 @@ function registerMemory(program3) {
|
|
|
7678
7823
|
});
|
|
7679
7824
|
ok(res, () => {
|
|
7680
7825
|
const results = res?.results ?? res ?? [];
|
|
7681
|
-
if (!results?.length) return line(
|
|
7826
|
+
if (!results?.length) return line(import_picocolors23.default.dim("No matching memories."));
|
|
7682
7827
|
for (const r of results) {
|
|
7683
|
-
line(`${
|
|
7828
|
+
line(`${import_picocolors23.default.dim(r.id ?? "?")} ${r.memory ?? r.content ?? ""}`);
|
|
7684
7829
|
}
|
|
7685
7830
|
});
|
|
7686
7831
|
})
|
|
@@ -7697,7 +7842,7 @@ function registerMemory(program3) {
|
|
|
7697
7842
|
}
|
|
7698
7843
|
|
|
7699
7844
|
// src/commands/business.ts
|
|
7700
|
-
var
|
|
7845
|
+
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
7701
7846
|
var RESOURCE_PATHS = {
|
|
7702
7847
|
"business-config": "business-config",
|
|
7703
7848
|
"business-settings": "business-settings",
|
|
@@ -7757,7 +7902,7 @@ function registerBusiness(program3) {
|
|
|
7757
7902
|
const projectId = requireProject(ctx);
|
|
7758
7903
|
const [resource] = args;
|
|
7759
7904
|
const res = await api(ctx, businessPath(projectId, resource), { body: JSON.parse(opts.body) });
|
|
7760
|
-
ok(res, () => line(`Created ${resource} ${
|
|
7905
|
+
ok(res, () => line(`Created ${resource} ${import_picocolors24.default.bold(res?.id ?? "")}.`));
|
|
7761
7906
|
})
|
|
7762
7907
|
);
|
|
7763
7908
|
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(
|
|
@@ -7799,7 +7944,7 @@ function businessPath(projectId, resource, subpath) {
|
|
|
7799
7944
|
}
|
|
7800
7945
|
|
|
7801
7946
|
// src/commands/artifact.ts
|
|
7802
|
-
var
|
|
7947
|
+
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
7803
7948
|
import { existsSync as existsSync2, statSync } from "fs";
|
|
7804
7949
|
import { resolve as resolve3, basename as basename3 } from "path";
|
|
7805
7950
|
var KINDS = [
|
|
@@ -7896,7 +8041,7 @@ function registerArtifact(program3) {
|
|
|
7896
8041
|
ok(
|
|
7897
8042
|
res,
|
|
7898
8043
|
() => success(
|
|
7899
|
-
`Recorded ${
|
|
8044
|
+
`Recorded ${import_picocolors25.default.bold(res?.title ?? "artifact")}${res?.kind ? import_picocolors25.default.dim(` (${res.kind})`) : ""}`
|
|
7900
8045
|
)
|
|
7901
8046
|
);
|
|
7902
8047
|
})
|
|
@@ -7934,7 +8079,7 @@ function registerArtifact(program3) {
|
|
|
7934
8079
|
}
|
|
7935
8080
|
function printArtifacts(rows) {
|
|
7936
8081
|
if (!rows.length) {
|
|
7937
|
-
line(
|
|
8082
|
+
line(import_picocolors25.default.dim("Nothing produced yet."));
|
|
7938
8083
|
return;
|
|
7939
8084
|
}
|
|
7940
8085
|
const byStep = /* @__PURE__ */ new Map();
|
|
@@ -7944,26 +8089,26 @@ function printArtifacts(rows) {
|
|
|
7944
8089
|
byStep.set(r.subtask_id, list);
|
|
7945
8090
|
}
|
|
7946
8091
|
for (const [stepId, items] of byStep) {
|
|
7947
|
-
line(
|
|
8092
|
+
line(import_picocolors25.default.bold(`step ${stepId}`));
|
|
7948
8093
|
for (const a of items) {
|
|
7949
|
-
const flag = a.promoted_at ?
|
|
8094
|
+
const flag = a.promoted_at ? import_picocolors25.default.green(" *") : " ";
|
|
7950
8095
|
const where = a.local_path || a.cloud_url || "";
|
|
7951
8096
|
line(
|
|
7952
|
-
`${flag} ${
|
|
8097
|
+
`${flag} ${import_picocolors25.default.dim(`[${a.kind}]`)} ${a.title ?? "(untitled)"}` + (where ? import_picocolors25.default.dim(` ${where}`) : "")
|
|
7953
8098
|
);
|
|
7954
|
-
if (a.description) line(
|
|
8099
|
+
if (a.description) line(import_picocolors25.default.dim(` ${a.description}`));
|
|
7955
8100
|
}
|
|
7956
8101
|
line("");
|
|
7957
8102
|
}
|
|
7958
|
-
line(
|
|
8103
|
+
line(import_picocolors25.default.dim("* = handed over as a deliverable; the rest is working material."));
|
|
7959
8104
|
}
|
|
7960
8105
|
function printRun(run) {
|
|
7961
8106
|
if (!run) return;
|
|
7962
|
-
line(` run ${
|
|
8107
|
+
line(` run ${import_picocolors25.default.bold(run.runId)}`);
|
|
7963
8108
|
if (run.taskId) line(` task ${run.taskId}`);
|
|
7964
8109
|
if (run.conversationId) line(` chat ${run.conversationId}`);
|
|
7965
8110
|
if (run.projectId) line(` project ${run.projectId}`);
|
|
7966
|
-
if (run.cwd) line(` folder ${
|
|
8111
|
+
if (run.cwd) line(` folder ${import_picocolors25.default.dim(run.cwd)}`);
|
|
7967
8112
|
}
|
|
7968
8113
|
|
|
7969
8114
|
// src/commands/image.ts
|
|
@@ -8144,7 +8289,7 @@ function registerAudio(program3) {
|
|
|
8144
8289
|
}
|
|
8145
8290
|
|
|
8146
8291
|
// src/commands/ask.ts
|
|
8147
|
-
var
|
|
8292
|
+
var import_picocolors26 = __toESM(require_picocolors(), 1);
|
|
8148
8293
|
var TYPES = [
|
|
8149
8294
|
"input",
|
|
8150
8295
|
"choice",
|
|
@@ -8222,7 +8367,7 @@ function registerAsk(program3) {
|
|
|
8222
8367
|
code: "bad_request"
|
|
8223
8368
|
});
|
|
8224
8369
|
}
|
|
8225
|
-
info(
|
|
8370
|
+
info(import_picocolors26.default.dim("Waiting for the user to answer\u2026"));
|
|
8226
8371
|
const res = await api(ctx, `/v1/runs/${runTarget(ctx)}/ask`, {
|
|
8227
8372
|
body: {
|
|
8228
8373
|
type,
|
|
@@ -8250,12 +8395,12 @@ function deriveTitle(message) {
|
|
|
8250
8395
|
function printAnswer(res) {
|
|
8251
8396
|
if (!res) return;
|
|
8252
8397
|
if (res.status === "answered") {
|
|
8253
|
-
line(` ${
|
|
8398
|
+
line(` ${import_picocolors26.default.green("answered")}`);
|
|
8254
8399
|
const value = extract(res.response);
|
|
8255
8400
|
if (value) line(` ${value}`);
|
|
8256
8401
|
return;
|
|
8257
8402
|
}
|
|
8258
|
-
line(` ${
|
|
8403
|
+
line(` ${import_picocolors26.default.yellow(res.status)} ${import_picocolors26.default.dim(res.reason ?? "")}`);
|
|
8259
8404
|
}
|
|
8260
8405
|
function extract(response) {
|
|
8261
8406
|
if (response == null) return "";
|
|
@@ -8274,7 +8419,7 @@ function extract(response) {
|
|
|
8274
8419
|
}
|
|
8275
8420
|
|
|
8276
8421
|
// src/commands/search.ts
|
|
8277
|
-
var
|
|
8422
|
+
var import_picocolors27 = __toESM(require_picocolors(), 1);
|
|
8278
8423
|
function registerSearch(program3) {
|
|
8279
8424
|
program3.command("search <query>").description("Search the web (Google-grounded, server-side)").option("-n, --max-results <n>", "max results", "5").action(
|
|
8280
8425
|
action(async ({ ctx, args, opts }) => {
|
|
@@ -8287,9 +8432,9 @@ function registerSearch(program3) {
|
|
|
8287
8432
|
line("");
|
|
8288
8433
|
}
|
|
8289
8434
|
const results = res?.results ?? [];
|
|
8290
|
-
if (!results.length) return line(
|
|
8435
|
+
if (!results.length) return line(import_picocolors27.default.dim("No results."));
|
|
8291
8436
|
for (const r of results) {
|
|
8292
|
-
line(`${r.title ||
|
|
8437
|
+
line(`${r.title || import_picocolors27.default.dim("(untitled)")} ${import_picocolors27.default.dim(r.url)}`);
|
|
8293
8438
|
}
|
|
8294
8439
|
});
|
|
8295
8440
|
})
|
|
@@ -8297,7 +8442,7 @@ function registerSearch(program3) {
|
|
|
8297
8442
|
}
|
|
8298
8443
|
|
|
8299
8444
|
// src/commands/board.ts
|
|
8300
|
-
var
|
|
8445
|
+
var import_picocolors28 = __toESM(require_picocolors(), 1);
|
|
8301
8446
|
|
|
8302
8447
|
// src/commands/record-step.ts
|
|
8303
8448
|
async function recordEntityStep(ctx, opts) {
|
|
@@ -8336,7 +8481,7 @@ function registerBoard(program3) {
|
|
|
8336
8481
|
}
|
|
8337
8482
|
ok(rows, () => {
|
|
8338
8483
|
if (!rows.length) {
|
|
8339
|
-
line(
|
|
8484
|
+
line(import_picocolors28.default.dim("No cards on the Board yet."));
|
|
8340
8485
|
return;
|
|
8341
8486
|
}
|
|
8342
8487
|
for (const r of rows) line(formatRow(r));
|
|
@@ -8351,7 +8496,7 @@ function registerBoard(program3) {
|
|
|
8351
8496
|
`/v1/projects/${projectId}/work-items/${args[0]}`
|
|
8352
8497
|
);
|
|
8353
8498
|
ok(row, () => {
|
|
8354
|
-
line(`${
|
|
8499
|
+
line(`${import_picocolors28.default.bold(row.title)} ${import_picocolors28.default.dim(row.id)}`);
|
|
8355
8500
|
line(`${statusTag(row.status)} priority ${row.priority}`);
|
|
8356
8501
|
if (row.ownerHuman) line(`owner: ${row.ownerHuman}`);
|
|
8357
8502
|
if (row.labels?.length) line(`labels: ${row.labels.join(", ")}`);
|
|
@@ -8392,7 +8537,7 @@ ${row.description}`);
|
|
|
8392
8537
|
refId: row?.id,
|
|
8393
8538
|
output: { workItem: row }
|
|
8394
8539
|
});
|
|
8395
|
-
ok(row, () => line(`Created work item ${
|
|
8540
|
+
ok(row, () => line(`Created work item ${import_picocolors28.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
8396
8541
|
})
|
|
8397
8542
|
);
|
|
8398
8543
|
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(
|
|
@@ -8426,7 +8571,7 @@ ${row.description}`);
|
|
|
8426
8571
|
);
|
|
8427
8572
|
}
|
|
8428
8573
|
const row = await patchItem(ctx, projectId, String(args[0]), body);
|
|
8429
|
-
ok(row, () => line(`Updated ${
|
|
8574
|
+
ok(row, () => line(`Updated ${import_picocolors28.default.bold(row.id)} \u2014 ${row.title} ${statusTag(row.status)}`));
|
|
8430
8575
|
})
|
|
8431
8576
|
);
|
|
8432
8577
|
board.command("move <id> <status>").description(
|
|
@@ -8437,14 +8582,14 @@ ${row.description}`);
|
|
|
8437
8582
|
const status = String(args[1]);
|
|
8438
8583
|
assertStatus(status);
|
|
8439
8584
|
const row = await patchItem(ctx, projectId, String(args[0]), { status });
|
|
8440
|
-
ok(row, () => line(`Moved ${
|
|
8585
|
+
ok(row, () => line(`Moved ${import_picocolors28.default.bold(row.title)} \u2192 ${statusTag(row.status)}`));
|
|
8441
8586
|
})
|
|
8442
8587
|
);
|
|
8443
8588
|
board.command("close <id>").description("Shorthand for `board move <id> done`").action(
|
|
8444
8589
|
action(async ({ ctx, args }) => {
|
|
8445
8590
|
const projectId = requireProject(ctx);
|
|
8446
8591
|
const row = await patchItem(ctx, projectId, String(args[0]), { status: "done" });
|
|
8447
|
-
ok(row, () => line(`Closed ${
|
|
8592
|
+
ok(row, () => line(`Closed ${import_picocolors28.default.bold(row.title)} ${statusTag(row.status)}`));
|
|
8448
8593
|
})
|
|
8449
8594
|
);
|
|
8450
8595
|
}
|
|
@@ -8477,23 +8622,23 @@ function assertPriority(value) {
|
|
|
8477
8622
|
}
|
|
8478
8623
|
}
|
|
8479
8624
|
function formatRow(r) {
|
|
8480
|
-
const labels = r.labels?.length ?
|
|
8481
|
-
const owner = r.ownerHuman ?
|
|
8482
|
-
return `${
|
|
8625
|
+
const labels = r.labels?.length ? import_picocolors28.default.dim(` [${r.labels.join(", ")}]`) : "";
|
|
8626
|
+
const owner = r.ownerHuman ? import_picocolors28.default.dim(` @${r.ownerHuman}`) : "";
|
|
8627
|
+
return `${import_picocolors28.default.dim(r.id)} ${statusTag(r.status)} ${r.title}${labels}${owner}`;
|
|
8483
8628
|
}
|
|
8484
8629
|
function statusTag(status) {
|
|
8485
8630
|
const label = status.padEnd(11);
|
|
8486
|
-
if (status === "done") return
|
|
8487
|
-
if (status === "in-progress") return
|
|
8488
|
-
if (status === "in-review") return
|
|
8489
|
-
return
|
|
8631
|
+
if (status === "done") return import_picocolors28.default.green(label);
|
|
8632
|
+
if (status === "in-progress") return import_picocolors28.default.yellow(label);
|
|
8633
|
+
if (status === "in-review") return import_picocolors28.default.cyan(label);
|
|
8634
|
+
return import_picocolors28.default.dim(label);
|
|
8490
8635
|
}
|
|
8491
8636
|
function collect2(value, previous) {
|
|
8492
8637
|
return [...previous, value];
|
|
8493
8638
|
}
|
|
8494
8639
|
|
|
8495
8640
|
// src/commands/task.ts
|
|
8496
|
-
var
|
|
8641
|
+
var import_picocolors29 = __toESM(require_picocolors(), 1);
|
|
8497
8642
|
var STATUSES2 = [
|
|
8498
8643
|
"todo",
|
|
8499
8644
|
"working",
|
|
@@ -8502,7 +8647,30 @@ var STATUSES2 = [
|
|
|
8502
8647
|
"accepted",
|
|
8503
8648
|
"archived"
|
|
8504
8649
|
];
|
|
8505
|
-
var ROLES = [
|
|
8650
|
+
var ROLES = [
|
|
8651
|
+
"pm",
|
|
8652
|
+
"architect",
|
|
8653
|
+
"designer",
|
|
8654
|
+
"web",
|
|
8655
|
+
"api",
|
|
8656
|
+
"mobile",
|
|
8657
|
+
"python",
|
|
8658
|
+
"automation",
|
|
8659
|
+
"qa",
|
|
8660
|
+
"devops",
|
|
8661
|
+
"sre",
|
|
8662
|
+
"security",
|
|
8663
|
+
"analyst"
|
|
8664
|
+
];
|
|
8665
|
+
var AGENTS = [
|
|
8666
|
+
"claude_code",
|
|
8667
|
+
"codex",
|
|
8668
|
+
"workser_code",
|
|
8669
|
+
"opencode",
|
|
8670
|
+
"cursor",
|
|
8671
|
+
"gemini"
|
|
8672
|
+
];
|
|
8673
|
+
var EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
8506
8674
|
var KINDS2 = [
|
|
8507
8675
|
"data_reports",
|
|
8508
8676
|
"web",
|
|
@@ -8511,6 +8679,7 @@ var KINDS2 = [
|
|
|
8511
8679
|
"automation",
|
|
8512
8680
|
"docs"
|
|
8513
8681
|
];
|
|
8682
|
+
var KIND_HELP = "what it produces (web app \u2192 web \xB7 phone app \u2192 mobile \xB7 api or ai-agent \u2192 service \xB7 worker or scheduled job \u2192 automation \xB7 report or analysis \u2192 data_reports \xB7 written page \u2192 docs)";
|
|
8514
8683
|
function registerTask(program3) {
|
|
8515
8684
|
const task = program3.command("task").description("The project's tasks and their subtasks (AI Tech Team)");
|
|
8516
8685
|
task.command("list").description("List the board's tasks \u2014 run this before starting anything").option(
|
|
@@ -8530,7 +8699,7 @@ function registerTask(program3) {
|
|
|
8530
8699
|
}) ?? [];
|
|
8531
8700
|
ok(rows, () => {
|
|
8532
8701
|
if (!rows.length) {
|
|
8533
|
-
line(
|
|
8702
|
+
line(import_picocolors29.default.dim("No tasks on the board yet."));
|
|
8534
8703
|
return;
|
|
8535
8704
|
}
|
|
8536
8705
|
for (const r of rows) line(formatRow2(r));
|
|
@@ -8554,7 +8723,7 @@ function registerTask(program3) {
|
|
|
8554
8723
|
ok({ ...row, goal }, () => printTask(row, goal));
|
|
8555
8724
|
})
|
|
8556
8725
|
);
|
|
8557
|
-
task.command("create <title>").description("Open a new root task for the project team").option("--note <text>", "context, constraints and expected outcome").option("--kind <value>",
|
|
8726
|
+
task.command("create <title>").description("Open a new root task for the project team").option("--note <text>", "context, constraints and expected outcome").option("--kind <value>", KIND_HELP).option("--label <value...>", "labels to put on the task").option("--app <id...>", "apps the task touches").option("--infra <ref...>", "shared setup it touches").option("--goal <id>", "the business goal this delivers part of").option(
|
|
8558
8727
|
"--phase <name>",
|
|
8559
8728
|
"which slice of that goal \u2014 must match one of its phase names"
|
|
8560
8729
|
).action(
|
|
@@ -8623,10 +8792,10 @@ function registerTask(program3) {
|
|
|
8623
8792
|
};
|
|
8624
8793
|
ok(result, () => {
|
|
8625
8794
|
line(
|
|
8626
|
-
`${
|
|
8795
|
+
`${import_picocolors29.default.green("opened")} ${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.key ?? row.id)}`
|
|
8627
8796
|
);
|
|
8628
8797
|
if (channelMessage)
|
|
8629
|
-
line(
|
|
8798
|
+
line(import_picocolors29.default.dim("posted to the channel as Project Manager"));
|
|
8630
8799
|
if (channelMessageError) {
|
|
8631
8800
|
warn(
|
|
8632
8801
|
`Task opened, but its Project Manager card could not be posted: ${channelMessageError.message}`
|
|
@@ -8641,7 +8810,7 @@ function registerTask(program3) {
|
|
|
8641
8810
|
).option(
|
|
8642
8811
|
"--task <id>",
|
|
8643
8812
|
"the parent task (defaults to the task this run is inside)"
|
|
8644
|
-
).option("--role <value>", `who does it (${ROLES.join(" | ")})`).option("--kind <value>",
|
|
8813
|
+
).option("--role <value>", `who does it (${ROLES.join(" | ")})`).option("--kind <value>", KIND_HELP).option("--note <text>", "one sentence on what this subtask does").option(
|
|
8645
8814
|
"--app <id...>",
|
|
8646
8815
|
"the app this subtask is for \u2014 one id runs it inside that app's folder; leave it off and it runs at the project, seeing every app"
|
|
8647
8816
|
).option(
|
|
@@ -8650,11 +8819,18 @@ function registerTask(program3) {
|
|
|
8650
8819
|
).option("--scope <path...>", "files or folders THIS subtask owns").option(
|
|
8651
8820
|
"--depends-on <id...>",
|
|
8652
8821
|
"subtasks that must finish first (key or id)"
|
|
8653
|
-
).
|
|
8822
|
+
).option(
|
|
8823
|
+
"--agent <id>",
|
|
8824
|
+
`run this step on a specific CLI (${AGENTS.join(" | ")}) instead of the role's own`
|
|
8825
|
+
).option("--model <id>", "the model that CLI should use for this step").option("--effort <level>", `how hard it thinks (${EFFORTS.join(" | ")})`).action(
|
|
8654
8826
|
action(async ({ ctx, args, opts }) => {
|
|
8655
8827
|
const parent = resolveTaskId(ctx, opts.task);
|
|
8656
8828
|
if (opts.role !== void 0) assertOneOf("--role", opts.role, ROLES);
|
|
8657
8829
|
if (opts.kind !== void 0) assertOneOf("--kind", opts.kind, KINDS2);
|
|
8830
|
+
if (opts.agent !== void 0) assertOneOf("--agent", opts.agent, AGENTS);
|
|
8831
|
+
if (opts.effort !== void 0)
|
|
8832
|
+
assertOneOf("--effort", opts.effort, EFFORTS);
|
|
8833
|
+
assertDelegatableModel("--model", opts.model);
|
|
8658
8834
|
const dependsOn = await resolveDeps(ctx, parent, opts.dependsOn ?? []);
|
|
8659
8835
|
const row = await api(ctx, "/v1/project-tasks", {
|
|
8660
8836
|
body: {
|
|
@@ -8677,11 +8853,30 @@ function registerTask(program3) {
|
|
|
8677
8853
|
]
|
|
8678
8854
|
}
|
|
8679
8855
|
});
|
|
8680
|
-
|
|
8856
|
+
const runner = opts.agent !== void 0 || opts.model !== void 0 || opts.effort !== void 0 ? await api(
|
|
8857
|
+
ctx,
|
|
8858
|
+
`/v1/project-tasks/${encodeURIComponent(row.id)}`,
|
|
8859
|
+
{
|
|
8860
|
+
method: "PATCH",
|
|
8861
|
+
body: {
|
|
8862
|
+
agentOverride: opts.agent,
|
|
8863
|
+
agentModelOverride: opts.model,
|
|
8864
|
+
agentEffortOverride: opts.effort
|
|
8865
|
+
}
|
|
8866
|
+
}
|
|
8867
|
+
) : null;
|
|
8868
|
+
ok(runner ?? row, () => {
|
|
8681
8869
|
line(
|
|
8682
|
-
`${
|
|
8870
|
+
`${import_picocolors29.default.green("added")} ${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.key ?? row.id)}`
|
|
8683
8871
|
);
|
|
8684
|
-
if (row.role) line(
|
|
8872
|
+
if (row.role) line(import_picocolors29.default.dim(`role: ${row.role}`));
|
|
8873
|
+
if (runner) {
|
|
8874
|
+
line(
|
|
8875
|
+
import_picocolors29.default.dim(
|
|
8876
|
+
`runs on: ${[opts.agent, opts.model, opts.effort].filter(Boolean).join(" \xB7 ")}`
|
|
8877
|
+
)
|
|
8878
|
+
);
|
|
8879
|
+
}
|
|
8685
8880
|
});
|
|
8686
8881
|
})
|
|
8687
8882
|
);
|
|
@@ -8695,17 +8890,30 @@ function registerTask(program3) {
|
|
|
8695
8890
|
const rows = row.subtasks ?? [];
|
|
8696
8891
|
ok(rows, () => {
|
|
8697
8892
|
if (!rows.length) {
|
|
8698
|
-
line(
|
|
8893
|
+
line(import_picocolors29.default.dim("No subtasks yet."));
|
|
8699
8894
|
return;
|
|
8700
8895
|
}
|
|
8701
8896
|
rows.forEach((r, i) => line(formatSubtask(r, i + 1)));
|
|
8702
8897
|
});
|
|
8703
8898
|
})
|
|
8704
8899
|
);
|
|
8705
|
-
subtask.command("update <id>").description("Change a subtask \u2014 its title, its role, what it touches").option("--title <text>").option("--note <text>").option("--role <value>", ROLES.join(" | ")).option("--kind <value>", KINDS2.join(" | ")).option("--scope <path...>", "replaces the subtask's scope entirely").
|
|
8900
|
+
subtask.command("update <id>").description("Change a subtask \u2014 its title, its role, what it touches").option("--title <text>").option("--note <text>").option("--role <value>", ROLES.join(" | ")).option("--kind <value>", KINDS2.join(" | ")).option("--scope <path...>", "replaces the subtask's scope entirely").option(
|
|
8901
|
+
"--agent <id>",
|
|
8902
|
+
`run this step on a specific CLI (${AGENTS.join(" | ")}); "default" hands it back to the role's own`
|
|
8903
|
+
).option("--model <id>", 'the model that CLI should use; "default" clears it').option(
|
|
8904
|
+
"--effort <level>",
|
|
8905
|
+
`how hard it thinks (${EFFORTS.join(" | ")}); "default" clears it`
|
|
8906
|
+
).action(
|
|
8706
8907
|
action(async ({ ctx, args, opts }) => {
|
|
8707
8908
|
if (opts.role !== void 0) assertOneOf("--role", opts.role, ROLES);
|
|
8708
8909
|
if (opts.kind !== void 0) assertOneOf("--kind", opts.kind, KINDS2);
|
|
8910
|
+
if (opts.agent !== void 0 && opts.agent !== "default")
|
|
8911
|
+
assertOneOf("--agent", opts.agent, AGENTS);
|
|
8912
|
+
if (opts.effort !== void 0 && opts.effort !== "default")
|
|
8913
|
+
assertOneOf("--effort", opts.effort, EFFORTS);
|
|
8914
|
+
if (opts.model !== "default")
|
|
8915
|
+
assertDelegatableModel("--model", opts.model);
|
|
8916
|
+
const clearable = (value) => value === void 0 ? void 0 : value === "default" ? null : value;
|
|
8709
8917
|
const row = await api(
|
|
8710
8918
|
ctx,
|
|
8711
8919
|
`/v1/project-tasks/${encodeURIComponent(args[0])}`,
|
|
@@ -8716,11 +8924,14 @@ function registerTask(program3) {
|
|
|
8716
8924
|
summary: opts.note,
|
|
8717
8925
|
role: opts.role,
|
|
8718
8926
|
category: opts.kind,
|
|
8719
|
-
scopePaths: opts.scope
|
|
8927
|
+
scopePaths: opts.scope,
|
|
8928
|
+
agentOverride: clearable(opts.agent),
|
|
8929
|
+
agentModelOverride: clearable(opts.model),
|
|
8930
|
+
agentEffortOverride: clearable(opts.effort)
|
|
8720
8931
|
}
|
|
8721
8932
|
}
|
|
8722
8933
|
);
|
|
8723
|
-
ok(row, () => line(`${
|
|
8934
|
+
ok(row, () => line(`${import_picocolors29.default.green("updated")} ${import_picocolors29.default.bold(row.title)}`));
|
|
8724
8935
|
})
|
|
8725
8936
|
);
|
|
8726
8937
|
subtask.command("remove <id>").description("Remove a subtask (only before the work starts)").action(
|
|
@@ -8728,7 +8939,7 @@ function registerTask(program3) {
|
|
|
8728
8939
|
await api(ctx, `/v1/project-tasks/${encodeURIComponent(args[0])}`, {
|
|
8729
8940
|
method: "DELETE"
|
|
8730
8941
|
});
|
|
8731
|
-
ok({ removed: args[0] }, () => line(
|
|
8942
|
+
ok({ removed: args[0] }, () => line(import_picocolors29.default.green("removed")));
|
|
8732
8943
|
})
|
|
8733
8944
|
);
|
|
8734
8945
|
task.command("move <id> <status>").description(
|
|
@@ -8743,7 +8954,7 @@ function registerTask(program3) {
|
|
|
8743
8954
|
);
|
|
8744
8955
|
ok(
|
|
8745
8956
|
row,
|
|
8746
|
-
() => line(`${
|
|
8957
|
+
() => line(`${import_picocolors29.default.green("moved")} ${import_picocolors29.default.bold(row.title)} \u2192 ${args[1]}`)
|
|
8747
8958
|
);
|
|
8748
8959
|
})
|
|
8749
8960
|
);
|
|
@@ -8759,18 +8970,18 @@ function registerTask(program3) {
|
|
|
8759
8970
|
);
|
|
8760
8971
|
ok(row, () => {
|
|
8761
8972
|
if (!row?.queued) {
|
|
8762
|
-
line(
|
|
8973
|
+
line(import_picocolors29.default.yellow("could not resume it \u2014 check the step id"));
|
|
8763
8974
|
return;
|
|
8764
8975
|
}
|
|
8765
8976
|
const started = row.started ?? 0;
|
|
8766
8977
|
if (started > 0) {
|
|
8767
8978
|
line(
|
|
8768
|
-
`${
|
|
8979
|
+
`${import_picocolors29.default.green("resumed")} \u2014 ${started} step${started === 1 ? "" : "s"} started`
|
|
8769
8980
|
);
|
|
8770
8981
|
return;
|
|
8771
8982
|
}
|
|
8772
8983
|
line(
|
|
8773
|
-
`${
|
|
8984
|
+
`${import_picocolors29.default.green("resumed")} \u2014 it is queued, but nothing started yet. Check the plan is approved and that no step is blocking the rest.`
|
|
8774
8985
|
);
|
|
8775
8986
|
});
|
|
8776
8987
|
})
|
|
@@ -8784,11 +8995,11 @@ function registerTask(program3) {
|
|
|
8784
8995
|
);
|
|
8785
8996
|
ok(row, () => {
|
|
8786
8997
|
if (row?.reopened) {
|
|
8787
|
-
line(`${
|
|
8998
|
+
line(`${import_picocolors29.default.green("sent back")} \u2014 it will be picked up again`);
|
|
8788
8999
|
return;
|
|
8789
9000
|
}
|
|
8790
9001
|
line(
|
|
8791
|
-
|
|
9002
|
+
import_picocolors29.default.yellow(
|
|
8792
9003
|
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"
|
|
8793
9004
|
)
|
|
8794
9005
|
);
|
|
@@ -8805,7 +9016,7 @@ function registerTask(program3) {
|
|
|
8805
9016
|
`/v1/project-tasks/${encodeURIComponent(id)}/dispatch-check`,
|
|
8806
9017
|
{ method: "POST" }
|
|
8807
9018
|
);
|
|
8808
|
-
ok(row, () => line(
|
|
9019
|
+
ok(row, () => line(import_picocolors29.default.green("approved \u2014 you may start")));
|
|
8809
9020
|
})
|
|
8810
9021
|
);
|
|
8811
9022
|
task.command("start [id]").description(
|
|
@@ -8820,13 +9031,13 @@ function registerTask(program3) {
|
|
|
8820
9031
|
const started = row?.started ?? null;
|
|
8821
9032
|
if (started && started > 0) {
|
|
8822
9033
|
line(
|
|
8823
|
-
|
|
9034
|
+
import_picocolors29.default.green(
|
|
8824
9035
|
`started ${started} step${started === 1 ? "" : "s"} \u2014 they are running now`
|
|
8825
9036
|
)
|
|
8826
9037
|
);
|
|
8827
9038
|
return;
|
|
8828
9039
|
}
|
|
8829
|
-
line(
|
|
9040
|
+
line(import_picocolors29.default.yellow(row?.note ?? "Nothing started."));
|
|
8830
9041
|
});
|
|
8831
9042
|
})
|
|
8832
9043
|
);
|
|
@@ -8841,7 +9052,7 @@ function registerTask(program3) {
|
|
|
8841
9052
|
);
|
|
8842
9053
|
ok({ awaiting: row2.approval_state === "awaiting", task: row2 }, () => {
|
|
8843
9054
|
line(
|
|
8844
|
-
row2.approval_state === "awaiting" ?
|
|
9055
|
+
row2.approval_state === "awaiting" ? import_picocolors29.default.yellow(
|
|
8845
9056
|
"The plan is waiting on the owner. They see it in the task."
|
|
8846
9057
|
) : `Already ${row2.approval_state}.`
|
|
8847
9058
|
);
|
|
@@ -8866,7 +9077,7 @@ function registerTask(program3) {
|
|
|
8866
9077
|
);
|
|
8867
9078
|
ok(
|
|
8868
9079
|
row,
|
|
8869
|
-
() => line(`${
|
|
9080
|
+
() => line(`${import_picocolors29.default.green(row.approval_state)} ${import_picocolors29.default.bold(row.title)}`)
|
|
8870
9081
|
);
|
|
8871
9082
|
})
|
|
8872
9083
|
);
|
|
@@ -8882,7 +9093,7 @@ function registerTask(program3) {
|
|
|
8882
9093
|
`/v1/project-tasks/${encodeURIComponent(id)}/move`,
|
|
8883
9094
|
{ body: { status: "ready" } }
|
|
8884
9095
|
);
|
|
8885
|
-
ok(row, () => line(`${
|
|
9096
|
+
ok(row, () => line(`${import_picocolors29.default.green("ready")} ${import_picocolors29.default.bold(row.title)}`));
|
|
8886
9097
|
})
|
|
8887
9098
|
);
|
|
8888
9099
|
}
|
|
@@ -8927,24 +9138,24 @@ function assertOneOf(flag, value, allowed) {
|
|
|
8927
9138
|
}
|
|
8928
9139
|
}
|
|
8929
9140
|
function formatRow2(r) {
|
|
8930
|
-
const key =
|
|
8931
|
-
const steps = r.subtaskTotal ?
|
|
8932
|
-
const gate = r.approval_state === "awaiting" ?
|
|
9141
|
+
const key = import_picocolors29.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
|
|
9142
|
+
const steps = r.subtaskTotal ? import_picocolors29.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
|
|
9143
|
+
const gate = r.approval_state === "awaiting" ? import_picocolors29.default.yellow(" awaiting approval") : "";
|
|
8933
9144
|
return `${key} ${statusTag2(r.status)} ${r.title}${steps}${gate}`;
|
|
8934
9145
|
}
|
|
8935
9146
|
function formatSubtask(r, index) {
|
|
8936
|
-
const n =
|
|
8937
|
-
const role = r.role ?
|
|
8938
|
-
const scope = r.scope_paths?.length ?
|
|
9147
|
+
const n = import_picocolors29.default.dim(String(index).padStart(2, "0"));
|
|
9148
|
+
const role = r.role ? import_picocolors29.default.dim(` [${r.role}]`) : "";
|
|
9149
|
+
const scope = r.scope_paths?.length ? import_picocolors29.default.dim(` owns: ${r.scope_paths.join(", ")}`) : "";
|
|
8939
9150
|
const head = `${n} ${statusTag2(r.status)} ${r.title}${role}${scope}`;
|
|
8940
9151
|
const summary = (r.result_summary ?? "").trim();
|
|
8941
9152
|
if (!summary) return head;
|
|
8942
9153
|
const wrapped = summary.split("\n").map((l) => ` ${l}`).join("\n");
|
|
8943
9154
|
return `${head}
|
|
8944
|
-
${
|
|
9155
|
+
${import_picocolors29.default.dim(wrapped)}`;
|
|
8945
9156
|
}
|
|
8946
9157
|
function printTask(row, goal) {
|
|
8947
|
-
line(`${
|
|
9158
|
+
line(`${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.key ?? row.id)}`);
|
|
8948
9159
|
line(`${statusTag2(row.status)} approval: ${row.approval_state}`);
|
|
8949
9160
|
if (row.summary) line(`
|
|
8950
9161
|
${row.summary}`);
|
|
@@ -8957,53 +9168,53 @@ touches: ${row.targets.map((t) => t.appName ?? t.ref ?? t.kind).join(", ")}`
|
|
|
8957
9168
|
}
|
|
8958
9169
|
if (row.subtasks?.length) {
|
|
8959
9170
|
line(`
|
|
8960
|
-
${
|
|
9171
|
+
${import_picocolors29.default.bold("subtasks")}`);
|
|
8961
9172
|
row.subtasks.forEach((s, i) => line(formatSubtask(s, i + 1)));
|
|
8962
9173
|
line(
|
|
8963
|
-
|
|
9174
|
+
import_picocolors29.default.dim(
|
|
8964
9175
|
`
|
|
8965
9176
|
Run \`workser artifact list\` to see what these subtasks produced,`
|
|
8966
9177
|
)
|
|
8967
9178
|
);
|
|
8968
9179
|
line(
|
|
8969
|
-
|
|
9180
|
+
import_picocolors29.default.dim(
|
|
8970
9181
|
`or \`workser artifact list --step <id>\` for one subtask's output alone.`
|
|
8971
9182
|
)
|
|
8972
9183
|
);
|
|
8973
9184
|
} else {
|
|
8974
|
-
line(
|
|
9185
|
+
line(import_picocolors29.default.dim("\nNo subtasks yet."));
|
|
8975
9186
|
}
|
|
8976
9187
|
}
|
|
8977
9188
|
function printGoalContext(row, goal) {
|
|
8978
9189
|
const mine = row.phase ?? null;
|
|
8979
9190
|
line(`
|
|
8980
|
-
${
|
|
8981
|
-
if (goal.outcome) line(
|
|
9191
|
+
${import_picocolors29.default.bold("part of")}: ${goal.title}`);
|
|
9192
|
+
if (goal.outcome) line(import_picocolors29.default.dim(`done means: ${goal.outcome}`));
|
|
8982
9193
|
const progress = goal.progress ?? [];
|
|
8983
9194
|
for (const p of progress) {
|
|
8984
9195
|
const where = p.total === 0 ? "not started" : `${p.done} of ${p.total} done`;
|
|
8985
|
-
const here = mine && p.name === mine ?
|
|
8986
|
-
const mark = p.state === "done" ?
|
|
9196
|
+
const here = mine && p.name === mine ? import_picocolors29.default.cyan(" <- this task") : "";
|
|
9197
|
+
const mark = p.state === "done" ? import_picocolors29.default.green("*") : import_picocolors29.default.dim("-");
|
|
8987
9198
|
line(` ${mark} ${p.name} \u2014 ${where}${here}`);
|
|
8988
9199
|
}
|
|
8989
9200
|
const next = progress.find((p) => p.state !== "done");
|
|
8990
9201
|
const running = progress.some((p) => p.state === "working");
|
|
8991
9202
|
if (next && !running) {
|
|
8992
9203
|
line(
|
|
8993
|
-
|
|
9204
|
+
import_picocolors29.default.dim(
|
|
8994
9205
|
`
|
|
8995
9206
|
Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to them in a sentence rather than starting it unasked.`
|
|
8996
9207
|
)
|
|
8997
9208
|
);
|
|
8998
9209
|
} else if (!next) {
|
|
8999
9210
|
line(
|
|
9000
|
-
|
|
9211
|
+
import_picocolors29.default.dim(
|
|
9001
9212
|
"\nEvery part of this plan is done. Say so, and offer to wrap it up."
|
|
9002
9213
|
)
|
|
9003
9214
|
);
|
|
9004
9215
|
}
|
|
9005
9216
|
line(
|
|
9006
|
-
|
|
9217
|
+
import_picocolors29.default.dim(
|
|
9007
9218
|
"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."
|
|
9008
9219
|
)
|
|
9009
9220
|
);
|
|
@@ -9011,22 +9222,22 @@ Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to t
|
|
|
9011
9222
|
function statusTag2(status) {
|
|
9012
9223
|
switch (status) {
|
|
9013
9224
|
case "ready":
|
|
9014
|
-
return
|
|
9225
|
+
return import_picocolors29.default.green("[ready]");
|
|
9015
9226
|
case "working":
|
|
9016
|
-
return
|
|
9227
|
+
return import_picocolors29.default.blue("[working]");
|
|
9017
9228
|
case "checking":
|
|
9018
|
-
return
|
|
9229
|
+
return import_picocolors29.default.cyan("[checking]");
|
|
9019
9230
|
case "accepted":
|
|
9020
|
-
return
|
|
9231
|
+
return import_picocolors29.default.green("[accepted]");
|
|
9021
9232
|
case "archived":
|
|
9022
|
-
return
|
|
9233
|
+
return import_picocolors29.default.dim("[archived]");
|
|
9023
9234
|
default:
|
|
9024
|
-
return
|
|
9235
|
+
return import_picocolors29.default.dim("[todo]");
|
|
9025
9236
|
}
|
|
9026
9237
|
}
|
|
9027
9238
|
|
|
9028
9239
|
// src/commands/goal.ts
|
|
9029
|
-
var
|
|
9240
|
+
var import_picocolors30 = __toESM(require_picocolors(), 1);
|
|
9030
9241
|
var STATUSES3 = ["proposed", "agreed", "working", "delivered", "abandoned"];
|
|
9031
9242
|
function registerGoal(program3) {
|
|
9032
9243
|
const goal = program3.command("goal").description("Business goals and the phases that deliver them");
|
|
@@ -9038,7 +9249,7 @@ function registerGoal(program3) {
|
|
|
9038
9249
|
}) ?? [];
|
|
9039
9250
|
ok(rows, () => {
|
|
9040
9251
|
if (!rows.length) {
|
|
9041
|
-
line(
|
|
9252
|
+
line(import_picocolors30.default.dim("No goals yet \u2014 every task here stands on its own."));
|
|
9042
9253
|
return;
|
|
9043
9254
|
}
|
|
9044
9255
|
for (const g of rows) line(formatGoal(g));
|
|
@@ -9115,10 +9326,10 @@ function registerGoal(program3) {
|
|
|
9115
9326
|
}
|
|
9116
9327
|
});
|
|
9117
9328
|
ok(row, () => {
|
|
9118
|
-
success(`Proposed ${
|
|
9329
|
+
success(`Proposed ${import_picocolors30.default.bold(row?.title ?? "goal")}`);
|
|
9119
9330
|
printGoal(row);
|
|
9120
9331
|
line(
|
|
9121
|
-
|
|
9332
|
+
import_picocolors30.default.dim(
|
|
9122
9333
|
"\nNothing has been created yet. The owner agrees the shape first."
|
|
9123
9334
|
)
|
|
9124
9335
|
);
|
|
@@ -9147,7 +9358,7 @@ function registerGoal(program3) {
|
|
|
9147
9358
|
ok(
|
|
9148
9359
|
row,
|
|
9149
9360
|
() => line(
|
|
9150
|
-
row?.recorded ? met === true ?
|
|
9361
|
+
row?.recorded ? met === true ? import_picocolors30.default.green("recorded \u2014 met") : met === false ? import_picocolors30.default.yellow("recorded \u2014 not met") : import_picocolors30.default.dim("recorded \u2014 back to unchecked") : import_picocolors30.default.yellow(
|
|
9151
9362
|
"couldn't record it \u2014 check the goal id, the phase name and the criterion id"
|
|
9152
9363
|
)
|
|
9153
9364
|
)
|
|
@@ -9181,42 +9392,42 @@ function registerGoal(program3) {
|
|
|
9181
9392
|
function appScope(g) {
|
|
9182
9393
|
const n = g.appIds?.length ?? 0;
|
|
9183
9394
|
if (!n) return "";
|
|
9184
|
-
return
|
|
9395
|
+
return import_picocolors30.default.dim(` ${n} part${n === 1 ? "" : "s"} of the system`);
|
|
9185
9396
|
}
|
|
9186
9397
|
function formatGoal(g) {
|
|
9187
|
-
const where = g.currentPhase && g.status !== "delivered" ?
|
|
9188
|
-
const count = g.taskTotal != null ?
|
|
9189
|
-
return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${
|
|
9398
|
+
const where = g.currentPhase && g.status !== "delivered" ? import_picocolors30.default.dim(` now: ${g.currentPhase}`) : "";
|
|
9399
|
+
const count = g.taskTotal != null ? import_picocolors30.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
|
|
9400
|
+
return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${import_picocolors30.default.dim(g.id)}`;
|
|
9190
9401
|
}
|
|
9191
9402
|
function printGoal(g) {
|
|
9192
9403
|
if (!g) return;
|
|
9193
|
-
line(`${
|
|
9404
|
+
line(`${import_picocolors30.default.bold(g.title)} ${import_picocolors30.default.dim(g.id)}`);
|
|
9194
9405
|
line(statusTag3(g.status));
|
|
9195
9406
|
if (g.outcome) line(`
|
|
9196
9407
|
done means: ${g.outcome}`);
|
|
9197
9408
|
const progress = g.progress ?? [];
|
|
9198
9409
|
if (!progress.length) {
|
|
9199
|
-
line(
|
|
9410
|
+
line(import_picocolors30.default.dim("\nNo phases agreed yet."));
|
|
9200
9411
|
return;
|
|
9201
9412
|
}
|
|
9202
9413
|
line(`
|
|
9203
|
-
${
|
|
9414
|
+
${import_picocolors30.default.bold("phases")}`);
|
|
9204
9415
|
for (const p of progress) {
|
|
9205
|
-
const bar2 = p.total > 0 ? `${p.done}/${p.total} done` :
|
|
9206
|
-
const mark = p.state === "done" ?
|
|
9416
|
+
const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors30.default.dim("nothing filed yet");
|
|
9417
|
+
const mark = p.state === "done" ? import_picocolors30.default.green("done") : p.state === "working" ? import_picocolors30.default.blue("working") : import_picocolors30.default.dim("waiting");
|
|
9207
9418
|
line(
|
|
9208
|
-
` ${
|
|
9419
|
+
` ${import_picocolors30.default.dim(String(p.index).padStart(2, "0"))} ${p.name} ${mark} ${import_picocolors30.default.dim(bar2)}`
|
|
9209
9420
|
);
|
|
9210
9421
|
for (const c of p.criteria ?? []) {
|
|
9211
|
-
const tick = c.met === true ?
|
|
9212
|
-
line(` ${tick} ${c.text} ${
|
|
9213
|
-
if (c.note) line(
|
|
9422
|
+
const tick = c.met === true ? import_picocolors30.default.green("\u2713") : c.met === false ? import_picocolors30.default.red("\u2717") : import_picocolors30.default.dim("\xB7");
|
|
9423
|
+
line(` ${tick} ${c.text} ${import_picocolors30.default.dim(c.id)}`);
|
|
9424
|
+
if (c.note) line(import_picocolors30.default.dim(` ${c.note}`));
|
|
9214
9425
|
}
|
|
9215
9426
|
}
|
|
9216
9427
|
const current = progress.find((p) => p.name === g.currentPhase);
|
|
9217
9428
|
if (current) {
|
|
9218
9429
|
line(
|
|
9219
|
-
|
|
9430
|
+
import_picocolors30.default.dim(
|
|
9220
9431
|
`
|
|
9221
9432
|
${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current.index} of ${progress.length}).`
|
|
9222
9433
|
)
|
|
@@ -9226,15 +9437,15 @@ ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current
|
|
|
9226
9437
|
function statusTag3(status) {
|
|
9227
9438
|
switch (status) {
|
|
9228
9439
|
case "agreed":
|
|
9229
|
-
return
|
|
9440
|
+
return import_picocolors30.default.cyan("[agreed]");
|
|
9230
9441
|
case "working":
|
|
9231
|
-
return
|
|
9442
|
+
return import_picocolors30.default.blue("[working]");
|
|
9232
9443
|
case "delivered":
|
|
9233
|
-
return
|
|
9444
|
+
return import_picocolors30.default.green("[delivered]");
|
|
9234
9445
|
case "abandoned":
|
|
9235
|
-
return
|
|
9446
|
+
return import_picocolors30.default.dim("[abandoned]");
|
|
9236
9447
|
default:
|
|
9237
|
-
return
|
|
9448
|
+
return import_picocolors30.default.yellow("[proposed]");
|
|
9238
9449
|
}
|
|
9239
9450
|
}
|
|
9240
9451
|
|
|
@@ -9409,7 +9620,7 @@ function stripLeadingGlobalOptions(argv) {
|
|
|
9409
9620
|
}
|
|
9410
9621
|
|
|
9411
9622
|
// src/commands/decision.ts
|
|
9412
|
-
var
|
|
9623
|
+
var import_picocolors31 = __toESM(require_picocolors(), 1);
|
|
9413
9624
|
function registerDecision(program3) {
|
|
9414
9625
|
const decision = program3.command("decision").description("Read and record the project's architecture decisions");
|
|
9415
9626
|
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(
|
|
@@ -9422,11 +9633,11 @@ function registerDecision(program3) {
|
|
|
9422
9633
|
rows = applyLimit(rows, opts.limit);
|
|
9423
9634
|
ok(rows, () => {
|
|
9424
9635
|
if (!rows.length) {
|
|
9425
|
-
line(
|
|
9636
|
+
line(import_picocolors31.default.dim("No decisions recorded yet."));
|
|
9426
9637
|
return;
|
|
9427
9638
|
}
|
|
9428
9639
|
for (const r of rows) {
|
|
9429
|
-
line(`${
|
|
9640
|
+
line(`${import_picocolors31.default.dim(r.id)} ${import_picocolors31.default.dim(shortDate(r.createdAt))} ${r.title}`);
|
|
9430
9641
|
line(` ${truncate(r.decision, 100)}`);
|
|
9431
9642
|
}
|
|
9432
9643
|
});
|
|
@@ -9440,16 +9651,16 @@ function registerDecision(program3) {
|
|
|
9440
9651
|
`/v1/projects/${projectId}/architecture-decisions/${args[0]}`
|
|
9441
9652
|
);
|
|
9442
9653
|
ok(row, () => {
|
|
9443
|
-
line(`${
|
|
9444
|
-
line(
|
|
9654
|
+
line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
|
|
9655
|
+
line(import_picocolors31.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
|
|
9445
9656
|
line(`
|
|
9446
|
-
${
|
|
9657
|
+
${import_picocolors31.default.bold("Context")}
|
|
9447
9658
|
${row.context}`);
|
|
9448
9659
|
line(`
|
|
9449
|
-
${
|
|
9660
|
+
${import_picocolors31.default.bold("Decision")}
|
|
9450
9661
|
${row.decision}`);
|
|
9451
9662
|
if (row.consequences) line(`
|
|
9452
|
-
${
|
|
9663
|
+
${import_picocolors31.default.bold("Consequences")}
|
|
9453
9664
|
${row.consequences}`);
|
|
9454
9665
|
});
|
|
9455
9666
|
})
|
|
@@ -9478,7 +9689,7 @@ ${row.consequences}`);
|
|
|
9478
9689
|
refId: row?.id,
|
|
9479
9690
|
output: { decision: row }
|
|
9480
9691
|
});
|
|
9481
|
-
ok(row, () => line(`Recorded decision ${
|
|
9692
|
+
ok(row, () => line(`Recorded decision ${import_picocolors31.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
9482
9693
|
})
|
|
9483
9694
|
);
|
|
9484
9695
|
const requirement = program3.command("requirement").description("Read and record the project's requirements");
|
|
@@ -9490,11 +9701,11 @@ ${row.consequences}`);
|
|
|
9490
9701
|
rows = applyLimit(rows, opts.limit);
|
|
9491
9702
|
ok(rows, () => {
|
|
9492
9703
|
if (!rows.length) {
|
|
9493
|
-
line(
|
|
9704
|
+
line(import_picocolors31.default.dim("No requirements recorded yet."));
|
|
9494
9705
|
return;
|
|
9495
9706
|
}
|
|
9496
9707
|
for (const r of rows) {
|
|
9497
|
-
line(`${
|
|
9708
|
+
line(`${import_picocolors31.default.dim(r.id)} ${r.status.padEnd(9)} ${r.title}`);
|
|
9498
9709
|
}
|
|
9499
9710
|
});
|
|
9500
9711
|
})
|
|
@@ -9507,8 +9718,8 @@ ${row.consequences}`);
|
|
|
9507
9718
|
`/v1/projects/${projectId}/requirements/${args[0]}`
|
|
9508
9719
|
);
|
|
9509
9720
|
ok(row, () => {
|
|
9510
|
-
line(`${
|
|
9511
|
-
line(
|
|
9721
|
+
line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
|
|
9722
|
+
line(import_picocolors31.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
|
|
9512
9723
|
line(`
|
|
9513
9724
|
${row.body}`);
|
|
9514
9725
|
});
|
|
@@ -9534,7 +9745,7 @@ ${row.body}`);
|
|
|
9534
9745
|
refId: row?.id,
|
|
9535
9746
|
output: { requirement: row }
|
|
9536
9747
|
});
|
|
9537
|
-
ok(row, () => line(`Recorded requirement ${
|
|
9748
|
+
ok(row, () => line(`Recorded requirement ${import_picocolors31.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
9538
9749
|
})
|
|
9539
9750
|
);
|
|
9540
9751
|
requirement.command("update <id>").description(
|
|
@@ -9563,7 +9774,7 @@ ${row.body}`);
|
|
|
9563
9774
|
code: "bad_request"
|
|
9564
9775
|
});
|
|
9565
9776
|
}
|
|
9566
|
-
ok(row, () => line(`Updated requirement ${
|
|
9777
|
+
ok(row, () => line(`Updated requirement ${import_picocolors31.default.bold(row.id)} \u2014 ${row.title} (${row.status})`));
|
|
9567
9778
|
})
|
|
9568
9779
|
);
|
|
9569
9780
|
}
|
|
@@ -9586,7 +9797,7 @@ function shortDate(iso) {
|
|
|
9586
9797
|
}
|
|
9587
9798
|
|
|
9588
9799
|
// src/commands/doc.ts
|
|
9589
|
-
var
|
|
9800
|
+
var import_picocolors32 = __toESM(require_picocolors(), 1);
|
|
9590
9801
|
|
|
9591
9802
|
// src/mermaid-fences.ts
|
|
9592
9803
|
function hasDiagram(code) {
|
|
@@ -9631,13 +9842,13 @@ function registerDoc(program3) {
|
|
|
9631
9842
|
}) ?? [];
|
|
9632
9843
|
ok(rows, () => {
|
|
9633
9844
|
if (!rows.length) {
|
|
9634
|
-
line(
|
|
9845
|
+
line(import_picocolors32.default.dim("No documents yet."));
|
|
9635
9846
|
return;
|
|
9636
9847
|
}
|
|
9637
9848
|
for (const r of rows) {
|
|
9638
|
-
const link = r.workItemId ?
|
|
9639
|
-
const file = r.filePath ?
|
|
9640
|
-
line(`${
|
|
9849
|
+
const link = r.workItemId ? import_picocolors32.default.dim(` \u21B3 ${r.workItemId}`) : "";
|
|
9850
|
+
const file = r.filePath ? import_picocolors32.default.dim(` ${r.filePath}`) : "";
|
|
9851
|
+
line(`${import_picocolors32.default.dim(r.id)} ${r.title}${link}${file}`);
|
|
9641
9852
|
}
|
|
9642
9853
|
});
|
|
9643
9854
|
})
|
|
@@ -9651,17 +9862,17 @@ function registerDoc(program3) {
|
|
|
9651
9862
|
);
|
|
9652
9863
|
if (opts.markdown) {
|
|
9653
9864
|
ok({ id: row.id, title: row.title, filePath: row.filePath }, () => {
|
|
9654
|
-
line(`${
|
|
9865
|
+
line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
|
|
9655
9866
|
line(
|
|
9656
|
-
row.filePath ? `Read it at ${
|
|
9867
|
+
row.filePath ? `Read it at ${import_picocolors32.default.bold(row.filePath)} (relative to the project folder).` : import_picocolors32.default.dim("This document has no markdown mirror on disk yet.")
|
|
9657
9868
|
);
|
|
9658
9869
|
});
|
|
9659
9870
|
return;
|
|
9660
9871
|
}
|
|
9661
9872
|
ok(row, () => {
|
|
9662
|
-
line(`${
|
|
9663
|
-
if (row.workItemId) line(
|
|
9664
|
-
if (row.filePath) line(
|
|
9873
|
+
line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
|
|
9874
|
+
if (row.workItemId) line(import_picocolors32.default.dim(`linked to work item ${row.workItemId}`));
|
|
9875
|
+
if (row.filePath) line(import_picocolors32.default.dim(`markdown mirror: ${row.filePath}`));
|
|
9665
9876
|
line("");
|
|
9666
9877
|
line(row.contentJson);
|
|
9667
9878
|
});
|
|
@@ -9690,7 +9901,7 @@ function registerDoc(program3) {
|
|
|
9690
9901
|
refId: row?.id,
|
|
9691
9902
|
output: { document: row }
|
|
9692
9903
|
});
|
|
9693
|
-
ok(row, () => line(`Created document ${
|
|
9904
|
+
ok(row, () => line(`Created document ${import_picocolors32.default.bold(row?.id ?? "")} \u2014 ${title}`));
|
|
9694
9905
|
})
|
|
9695
9906
|
);
|
|
9696
9907
|
doc.command("diagram <id>").description(
|
|
@@ -9716,19 +9927,19 @@ function registerDoc(program3) {
|
|
|
9716
9927
|
diagrams: diagrams.map((code) => ({ kind: diagramKind(code), code }))
|
|
9717
9928
|
};
|
|
9718
9929
|
ok(payload, () => {
|
|
9719
|
-
line(`${
|
|
9930
|
+
line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
|
|
9720
9931
|
if (markdown === null) {
|
|
9721
9932
|
line(
|
|
9722
|
-
|
|
9933
|
+
import_picocolors32.default.dim(
|
|
9723
9934
|
row.filePath ? `Could not read ${row.filePath} from this folder.` : "This document has no markdown mirror on disk yet."
|
|
9724
9935
|
)
|
|
9725
9936
|
);
|
|
9726
9937
|
} else if (!diagrams.length) {
|
|
9727
|
-
line(
|
|
9938
|
+
line(import_picocolors32.default.dim("No diagrams in this document."));
|
|
9728
9939
|
} else {
|
|
9729
9940
|
for (const [i, code] of diagrams.entries()) {
|
|
9730
9941
|
const kind = diagramKind(code) ?? "diagram";
|
|
9731
|
-
line(`${
|
|
9942
|
+
line(`${import_picocolors32.default.dim(String(i + 1))} ${kind} ${import_picocolors32.default.dim(`${code.split("\n").length} lines`)}`);
|
|
9732
9943
|
}
|
|
9733
9944
|
}
|
|
9734
9945
|
});
|
|
@@ -9764,7 +9975,7 @@ function registerDoc(program3) {
|
|
|
9764
9975
|
code: "bad_request"
|
|
9765
9976
|
});
|
|
9766
9977
|
}
|
|
9767
|
-
ok(row, () => line(`Updated document ${
|
|
9978
|
+
ok(row, () => line(`Updated document ${import_picocolors32.default.bold(row.id)} \u2014 ${row.title}`));
|
|
9768
9979
|
})
|
|
9769
9980
|
);
|
|
9770
9981
|
}
|
|
@@ -9778,7 +9989,7 @@ function readMirror(cwd, filePath) {
|
|
|
9778
9989
|
}
|
|
9779
9990
|
|
|
9780
9991
|
// src/commands/design.ts
|
|
9781
|
-
var
|
|
9992
|
+
var import_picocolors33 = __toESM(require_picocolors(), 1);
|
|
9782
9993
|
function registerDesign(program3) {
|
|
9783
9994
|
const design = program3.command("design").description("Read the project's brand (colours, fonts, logo)");
|
|
9784
9995
|
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(
|
|
@@ -9792,11 +10003,11 @@ function registerDesign(program3) {
|
|
|
9792
10003
|
if (opts.raw) {
|
|
9793
10004
|
ok(files, () => {
|
|
9794
10005
|
if (!files.length) {
|
|
9795
|
-
line(
|
|
10006
|
+
line(import_picocolors33.default.dim("No brand set for this project."));
|
|
9796
10007
|
return;
|
|
9797
10008
|
}
|
|
9798
10009
|
for (const f of files) {
|
|
9799
|
-
line(
|
|
10010
|
+
line(import_picocolors33.default.bold(f.path));
|
|
9800
10011
|
line(f.contents);
|
|
9801
10012
|
line("");
|
|
9802
10013
|
}
|
|
@@ -9813,21 +10024,21 @@ function registerDesign(program3) {
|
|
|
9813
10024
|
} : { hasBrand: false, colors: {}, fonts: {}, brand: {}, files: [] };
|
|
9814
10025
|
ok(summary, () => {
|
|
9815
10026
|
if (!tokens) {
|
|
9816
|
-
line(
|
|
10027
|
+
line(import_picocolors33.default.dim("No brand set for this project \u2014 choose sensible styling yourself."));
|
|
9817
10028
|
return;
|
|
9818
10029
|
}
|
|
9819
10030
|
for (const [name, value] of Object.entries(tokens.brand)) {
|
|
9820
|
-
line(`${
|
|
10031
|
+
line(`${import_picocolors33.default.dim(name.padEnd(12))} ${value}`);
|
|
9821
10032
|
}
|
|
9822
10033
|
for (const [name, value] of Object.entries(tokens.color)) {
|
|
9823
|
-
line(`${
|
|
10034
|
+
line(`${import_picocolors33.default.dim(`color.${name}`.padEnd(12))} ${value}`);
|
|
9824
10035
|
}
|
|
9825
10036
|
for (const [name, value] of Object.entries(tokens.font)) {
|
|
9826
|
-
line(`${
|
|
10037
|
+
line(`${import_picocolors33.default.dim(`font.${name}`.padEnd(12))} ${value}`);
|
|
9827
10038
|
}
|
|
9828
10039
|
line("");
|
|
9829
10040
|
line(
|
|
9830
|
-
|
|
10041
|
+
import_picocolors33.default.dim(
|
|
9831
10042
|
`Generated into the working tree as ${files.map((f) => f.path).join(", ")} \u2014 wire those in, never edit them.`
|
|
9832
10043
|
)
|
|
9833
10044
|
);
|
|
@@ -9858,7 +10069,7 @@ function unwrap(group) {
|
|
|
9858
10069
|
}
|
|
9859
10070
|
|
|
9860
10071
|
// src/commands/api.ts
|
|
9861
|
-
var
|
|
10072
|
+
var import_picocolors34 = __toESM(require_picocolors(), 1);
|
|
9862
10073
|
import { readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
9863
10074
|
import { join as join3, relative, sep } from "path";
|
|
9864
10075
|
|
|
@@ -9969,13 +10180,13 @@ function registerApi(program3) {
|
|
|
9969
10180
|
const cmd = program3.command("api").description("Call this service and check it describes its own routes");
|
|
9970
10181
|
cmd.command("list").description("The requests saved with this service, in api/requests.json").option("--app <webAppId>", "the service, when this folder holds more than one").action(
|
|
9971
10182
|
action(async ({ ctx, opts }) => {
|
|
9972
|
-
const appId =
|
|
10183
|
+
const appId = requireApp2(opts.app);
|
|
9973
10184
|
const res = await api(ctx, `/v1/apps/${encodeURIComponent(appId)}/api/requests`);
|
|
9974
10185
|
ok(res, () => {
|
|
9975
|
-
for (const note of res?.notes ?? []) line(
|
|
10186
|
+
for (const note of res?.notes ?? []) line(import_picocolors34.default.dim(note));
|
|
9976
10187
|
for (const r of res?.requests ?? []) {
|
|
9977
10188
|
line(
|
|
9978
|
-
`${
|
|
10189
|
+
`${import_picocolors34.default.dim(r.method.padEnd(6))}${r.path}${r.note ? import_picocolors34.default.dim(` ${r.note}`) : ""}`
|
|
9979
10190
|
);
|
|
9980
10191
|
}
|
|
9981
10192
|
});
|
|
@@ -9993,7 +10204,7 @@ function registerApi(program3) {
|
|
|
9993
10204
|
"local (default), preview or production \u2014 the host comes from here, never from the path"
|
|
9994
10205
|
).action(
|
|
9995
10206
|
action(async ({ ctx, args, opts }) => {
|
|
9996
|
-
const appId =
|
|
10207
|
+
const appId = requireApp2(opts.app);
|
|
9997
10208
|
const res = await api(
|
|
9998
10209
|
ctx,
|
|
9999
10210
|
`/v1/apps/${encodeURIComponent(appId)}/api/call`,
|
|
@@ -10009,14 +10220,14 @@ function registerApi(program3) {
|
|
|
10009
10220
|
);
|
|
10010
10221
|
ok(res, () => {
|
|
10011
10222
|
if (!res?.ok) {
|
|
10012
|
-
line(
|
|
10223
|
+
line(import_picocolors34.default.red(res?.error ?? "The service did not answer."));
|
|
10013
10224
|
return;
|
|
10014
10225
|
}
|
|
10015
10226
|
const code = `${res.status}${res.statusText ? ` ${res.statusText}` : ""}`;
|
|
10016
|
-
const colour2 = res.status && res.status < 300 ?
|
|
10017
|
-
line(`${colour2(code)} ${
|
|
10227
|
+
const colour2 = res.status && res.status < 300 ? import_picocolors34.default.green : res.status && res.status < 500 ? import_picocolors34.default.yellow : import_picocolors34.default.red;
|
|
10228
|
+
line(`${colour2(code)} ${import_picocolors34.default.dim(`${res.durationMs}ms ${res.url}`)}`);
|
|
10018
10229
|
if (res.body) line(res.body);
|
|
10019
|
-
if (res.truncated) line(
|
|
10230
|
+
if (res.truncated) line(import_picocolors34.default.dim("(answer truncated)"));
|
|
10020
10231
|
});
|
|
10021
10232
|
if (!res?.ok) process.exitCode = 1;
|
|
10022
10233
|
})
|
|
@@ -10036,15 +10247,15 @@ function registerApi(program3) {
|
|
|
10036
10247
|
for (const r of report.routes) {
|
|
10037
10248
|
const known = report.missing.some((m) => m.path === r.path);
|
|
10038
10249
|
line(
|
|
10039
|
-
`${known ?
|
|
10250
|
+
`${known ? import_picocolors34.default.yellow("undocumented") : import_picocolors34.default.green("documented ")} ${r.path}${import_picocolors34.default.dim(` ${r.file}`)}`
|
|
10040
10251
|
);
|
|
10041
10252
|
}
|
|
10042
10253
|
for (const p of report.stale) {
|
|
10043
|
-
line(`${
|
|
10254
|
+
line(`${import_picocolors34.default.dim("in spec only ")} ${p}`);
|
|
10044
10255
|
}
|
|
10045
10256
|
line("");
|
|
10046
10257
|
if (report.ok && specFile) success(summary);
|
|
10047
|
-
else line(
|
|
10258
|
+
else line(import_picocolors34.default.yellow(summary));
|
|
10048
10259
|
});
|
|
10049
10260
|
if (opts.check && !report.ok) {
|
|
10050
10261
|
throw new WorkserError(summary, { code: "bad_request" });
|
|
@@ -10060,7 +10271,7 @@ function collectHeader(raw, previous) {
|
|
|
10060
10271
|
if (at <= 0) return previous;
|
|
10061
10272
|
return { ...previous, [raw.slice(0, at).trim()]: raw.slice(at + 1).trim() };
|
|
10062
10273
|
}
|
|
10063
|
-
function
|
|
10274
|
+
function requireApp2(app) {
|
|
10064
10275
|
const value = typeof app === "string" ? app.trim() : "";
|
|
10065
10276
|
if (value) return value;
|
|
10066
10277
|
throw new WorkserError(
|
|
@@ -10115,7 +10326,7 @@ function listRepoFiles(root, maxDepth = 8) {
|
|
|
10115
10326
|
}
|
|
10116
10327
|
|
|
10117
10328
|
// src/commands/analysis.ts
|
|
10118
|
-
var
|
|
10329
|
+
var import_picocolors35 = __toESM(require_picocolors(), 1);
|
|
10119
10330
|
import { readFileSync as readFileSync4 } from "fs";
|
|
10120
10331
|
function registerAnalysis(program3) {
|
|
10121
10332
|
const cmd = program3.command("analysis").description("Run Python analysis locally, recorded in the task");
|
|
@@ -10125,14 +10336,14 @@ function registerAnalysis(program3) {
|
|
|
10125
10336
|
const res = await api(ctx, path);
|
|
10126
10337
|
ok(res, () => {
|
|
10127
10338
|
line(
|
|
10128
|
-
`${res?.available ?
|
|
10339
|
+
`${res?.available ? import_picocolors35.default.green("python") : import_picocolors35.default.red("python")} ${res?.version ?? "not found"} ${import_picocolors35.default.dim(res?.python ?? "")}`
|
|
10129
10340
|
);
|
|
10130
10341
|
for (const lib of res?.libraries ?? []) {
|
|
10131
10342
|
line(
|
|
10132
|
-
`${lib.present ?
|
|
10343
|
+
`${lib.present ? import_picocolors35.default.green(lib.name) : import_picocolors35.default.yellow(lib.name)}${import_picocolors35.default.dim(lib.present ? "" : " missing")}`
|
|
10133
10344
|
);
|
|
10134
10345
|
}
|
|
10135
|
-
for (const note of res?.notes ?? []) line(
|
|
10346
|
+
for (const note of res?.notes ?? []) line(import_picocolors35.default.dim(note));
|
|
10136
10347
|
});
|
|
10137
10348
|
if (!res?.available) process.exitCode = 1;
|
|
10138
10349
|
})
|
|
@@ -10154,15 +10365,15 @@ function registerAnalysis(program3) {
|
|
|
10154
10365
|
);
|
|
10155
10366
|
ok(res, () => {
|
|
10156
10367
|
if (res?.stdout) line(res.stdout.replace(/\n$/, ""));
|
|
10157
|
-
if (res?.stderr) line(
|
|
10158
|
-
if (res?.truncated) line(
|
|
10368
|
+
if (res?.stderr) line(import_picocolors35.default.dim(res.stderr.replace(/\n$/, "")));
|
|
10369
|
+
if (res?.truncated) line(import_picocolors35.default.dim("(output truncated)"));
|
|
10159
10370
|
const took = `${Math.round((res?.durationMs ?? 0) / 100) / 10}s`;
|
|
10160
10371
|
line(
|
|
10161
|
-
res?.ok ?
|
|
10372
|
+
res?.ok ? import_picocolors35.default.green(`\u2713 ${res.summary ?? "It finished."}`) + import_picocolors35.default.dim(` ${took}`) : import_picocolors35.default.yellow(res?.summary ?? "It did not finish.") + import_picocolors35.default.dim(` ${took}`)
|
|
10162
10373
|
);
|
|
10163
10374
|
if (res && !res.sandboxed) {
|
|
10164
10375
|
line(
|
|
10165
|
-
|
|
10376
|
+
import_picocolors35.default.dim(
|
|
10166
10377
|
"This platform has no OS sandbox, so the script ran with your own file access."
|
|
10167
10378
|
)
|
|
10168
10379
|
);
|
|
@@ -10190,7 +10401,7 @@ function readCode(file, inline) {
|
|
|
10190
10401
|
}
|
|
10191
10402
|
|
|
10192
10403
|
// src/commands/scan.ts
|
|
10193
|
-
var
|
|
10404
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
10194
10405
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
10195
10406
|
import { existsSync as existsSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
10196
10407
|
import { join as join4, relative as relative2, sep as sep2 } from "path";
|
|
@@ -10474,22 +10685,22 @@ function runPermissions(cwd, findings, checked, skipped) {
|
|
|
10474
10685
|
}
|
|
10475
10686
|
function print2(report, summary) {
|
|
10476
10687
|
for (const s of report.skipped) {
|
|
10477
|
-
line(`${
|
|
10688
|
+
line(`${import_picocolors36.default.yellow("not checked")} ${s.check}${import_picocolors36.default.dim(` \u2014 ${s.reason}`)}`);
|
|
10478
10689
|
}
|
|
10479
10690
|
for (const f of report.findings) {
|
|
10480
|
-
const where = f.file ?
|
|
10691
|
+
const where = f.file ? import_picocolors36.default.dim(` ${f.file}${f.line ? `:${f.line}` : ""}`) : "";
|
|
10481
10692
|
line(`${severityTag(f.severity)} ${f.title}${where}`);
|
|
10482
|
-
line(` ${
|
|
10693
|
+
line(` ${import_picocolors36.default.dim(f.fix)}`);
|
|
10483
10694
|
}
|
|
10484
10695
|
if (report.findings.length || report.skipped.length) line("");
|
|
10485
10696
|
if (report.ok && !report.skipped.length) success(summary);
|
|
10486
|
-
else if (report.ok) line(
|
|
10487
|
-
else line(
|
|
10697
|
+
else if (report.ok) line(import_picocolors36.default.yellow(summary));
|
|
10698
|
+
else line(import_picocolors36.default.red(summary));
|
|
10488
10699
|
}
|
|
10489
10700
|
function severityTag(severity) {
|
|
10490
|
-
if (severity === "high") return
|
|
10491
|
-
if (severity === "medium") return
|
|
10492
|
-
return
|
|
10701
|
+
if (severity === "high") return import_picocolors36.default.red("serious ");
|
|
10702
|
+
if (severity === "medium") return import_picocolors36.default.yellow("worth fixing");
|
|
10703
|
+
return import_picocolors36.default.dim("minor ");
|
|
10493
10704
|
}
|
|
10494
10705
|
function git(cwd, args) {
|
|
10495
10706
|
try {
|
|
@@ -10550,7 +10761,7 @@ function listRepoFiles2(root, maxDepth = 8) {
|
|
|
10550
10761
|
}
|
|
10551
10762
|
|
|
10552
10763
|
// src/commands/health.ts
|
|
10553
|
-
var
|
|
10764
|
+
var import_picocolors37 = __toESM(require_picocolors(), 1);
|
|
10554
10765
|
function registerHealth(program3) {
|
|
10555
10766
|
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(
|
|
10556
10767
|
action(async ({ ctx, opts }) => {
|
|
@@ -10564,16 +10775,16 @@ function registerHealth(program3) {
|
|
|
10564
10775
|
}
|
|
10565
10776
|
function print3(res) {
|
|
10566
10777
|
if (!res?.checks?.length) {
|
|
10567
|
-
line(
|
|
10778
|
+
line(import_picocolors37.default.dim(res?.note ?? "Nothing to check."));
|
|
10568
10779
|
return;
|
|
10569
10780
|
}
|
|
10570
10781
|
for (const c of res.checks) {
|
|
10571
|
-
const mark = c.ok ?
|
|
10572
|
-
const timing =
|
|
10573
|
-
const detail = c.ok ? timing :
|
|
10574
|
-
line(` ${mark} ${c.appName} ${
|
|
10782
|
+
const mark = c.ok ? import_picocolors37.default.green("up ") : import_picocolors37.default.red("down");
|
|
10783
|
+
const timing = import_picocolors37.default.dim(`${c.ms}ms`);
|
|
10784
|
+
const detail = c.ok ? timing : import_picocolors37.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
|
|
10785
|
+
line(` ${mark} ${c.appName} ${import_picocolors37.default.dim(`(${c.environment})`)} ${c.url} ${detail}`);
|
|
10575
10786
|
if (c.incidentOpened) {
|
|
10576
|
-
line(
|
|
10787
|
+
line(import_picocolors37.default.yellow(` An incident has been opened on the board for this.`));
|
|
10577
10788
|
}
|
|
10578
10789
|
}
|
|
10579
10790
|
const down = res.checks.filter((c) => !c.ok);
|
|
@@ -10586,14 +10797,14 @@ function print3(res) {
|
|
|
10586
10797
|
}
|
|
10587
10798
|
const production = down.filter((c) => c.environment === "production").length;
|
|
10588
10799
|
line(
|
|
10589
|
-
|
|
10800
|
+
import_picocolors37.default.red(
|
|
10590
10801
|
`${down.length} of ${res.checks.length} not answering` + (production ? ` \u2014 ${production} customer-facing.` : " (preview only).")
|
|
10591
10802
|
)
|
|
10592
10803
|
);
|
|
10593
10804
|
}
|
|
10594
10805
|
|
|
10595
10806
|
// src/commands/urls.ts
|
|
10596
|
-
var
|
|
10807
|
+
var import_picocolors38 = __toESM(require_picocolors(), 1);
|
|
10597
10808
|
function registerUrls(program3) {
|
|
10598
10809
|
program3.command("urls").description("The stable preview and production addresses of every app in this project").option("--app <webAppId>", "just one app").action(
|
|
10599
10810
|
action(async ({ ctx, opts }) => {
|
|
@@ -10607,20 +10818,20 @@ function registerUrls(program3) {
|
|
|
10607
10818
|
const summary = urlsSummary(rows);
|
|
10608
10819
|
ok({ rows, summary }, () => {
|
|
10609
10820
|
for (const row of rows) {
|
|
10610
|
-
const label =
|
|
10611
|
-
const value = row.url ?
|
|
10821
|
+
const label = import_picocolors38.default.dim(row.environment.padEnd(10));
|
|
10822
|
+
const value = row.url ? import_picocolors38.default.cyan(row.url) : import_picocolors38.default.dim(row.note ?? "not published");
|
|
10612
10823
|
line(` ${row.appName.padEnd(22)} ${label} ${value}`);
|
|
10613
10824
|
}
|
|
10614
10825
|
line("");
|
|
10615
10826
|
if (rows.some((r) => r.url)) success(summary);
|
|
10616
|
-
else line(
|
|
10827
|
+
else line(import_picocolors38.default.yellow(summary));
|
|
10617
10828
|
});
|
|
10618
10829
|
})
|
|
10619
10830
|
);
|
|
10620
10831
|
}
|
|
10621
10832
|
|
|
10622
10833
|
// src/commands/deployments.ts
|
|
10623
|
-
var
|
|
10834
|
+
var import_picocolors39 = __toESM(require_picocolors(), 1);
|
|
10624
10835
|
function registerDeployments(program3) {
|
|
10625
10836
|
const cmd = program3.command("deployments").description("Deployment history, and putting a build in front of customers");
|
|
10626
10837
|
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(
|
|
@@ -10638,7 +10849,7 @@ function registerDeployments(program3) {
|
|
|
10638
10849
|
ok(res, () => {
|
|
10639
10850
|
if (!items.length) {
|
|
10640
10851
|
return line(
|
|
10641
|
-
|
|
10852
|
+
import_picocolors39.default.dim(
|
|
10642
10853
|
environment ? `Nothing has been deployed to ${environment} yet.` : "Nothing has been deployed yet. `workser deploy` builds the first one."
|
|
10643
10854
|
)
|
|
10644
10855
|
);
|
|
@@ -10658,13 +10869,13 @@ function registerDeployments(program3) {
|
|
|
10658
10869
|
).catch(() => null) : null;
|
|
10659
10870
|
ok({ ...dep, logs }, () => {
|
|
10660
10871
|
line(formatDeployment(dep));
|
|
10661
|
-
if (dep?.error_message) line(
|
|
10872
|
+
if (dep?.error_message) line(import_picocolors39.default.red(` ${dep.error_message}`));
|
|
10662
10873
|
const events = logs?.events ?? [];
|
|
10663
10874
|
for (const e of events) {
|
|
10664
|
-
line(` ${
|
|
10875
|
+
line(` ${import_picocolors39.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
|
|
10665
10876
|
}
|
|
10666
10877
|
if (opts.logs && !events.length) {
|
|
10667
|
-
line(
|
|
10878
|
+
line(import_picocolors39.default.dim(" That build produced no output."));
|
|
10668
10879
|
}
|
|
10669
10880
|
});
|
|
10670
10881
|
})
|
|
@@ -10708,16 +10919,16 @@ function printPromoted(res, version) {
|
|
|
10708
10919
|
const what = version === null ? "the latest build" : `version ${version}`;
|
|
10709
10920
|
const url = res.url ?? res.vercel_url;
|
|
10710
10921
|
success(`Production is being rebuilt from ${what}.`);
|
|
10711
|
-
if (url) line(
|
|
10712
|
-
line(
|
|
10922
|
+
if (url) line(import_picocolors39.default.dim(`It will be at ${url}`));
|
|
10923
|
+
line(import_picocolors39.default.dim("`workser deploy status` follows it."));
|
|
10713
10924
|
}
|
|
10714
10925
|
function formatDeployment(d) {
|
|
10715
10926
|
if (!d) return "";
|
|
10716
|
-
const version = d.version !== void 0 ?
|
|
10717
|
-
const env =
|
|
10927
|
+
const version = d.version !== void 0 ? import_picocolors39.default.yellow(`v${d.version}`) : import_picocolors39.default.dim("v?");
|
|
10928
|
+
const env = import_picocolors39.default.dim((d.environment ?? "?").padEnd(10));
|
|
10718
10929
|
const app = d.webAppName ? `${d.webAppName} ` : "";
|
|
10719
|
-
const when =
|
|
10720
|
-
const url = d.url ? " " +
|
|
10930
|
+
const when = import_picocolors39.default.dim(formatTime2(d.created_at));
|
|
10931
|
+
const url = d.url ? " " + import_picocolors39.default.cyan(d.url) : "";
|
|
10721
10932
|
return `${version} ${env} ${colorStatus(d.status ?? "")} ${app}${when}${url}`;
|
|
10722
10933
|
}
|
|
10723
10934
|
function formatTime2(t) {
|
|
@@ -10727,7 +10938,7 @@ function formatTime2(t) {
|
|
|
10727
10938
|
}
|
|
10728
10939
|
|
|
10729
10940
|
// src/commands/usage.ts
|
|
10730
|
-
var
|
|
10941
|
+
var import_picocolors40 = __toESM(require_picocolors(), 1);
|
|
10731
10942
|
|
|
10732
10943
|
// src/usage.ts
|
|
10733
10944
|
var NEAR_LIMIT_FRACTION = 0.8;
|
|
@@ -10822,7 +11033,7 @@ function registerUsage(program3) {
|
|
|
10822
11033
|
function print4(report) {
|
|
10823
11034
|
const dims = report.dimensions ?? [];
|
|
10824
11035
|
if (!dims.length) {
|
|
10825
|
-
return line(
|
|
11036
|
+
return line(import_picocolors40.default.dim("Nothing to measure for this project yet."));
|
|
10826
11037
|
}
|
|
10827
11038
|
const width = Math.max(...dims.map((d) => d.label.length));
|
|
10828
11039
|
for (const d of dims) {
|
|
@@ -10831,23 +11042,23 @@ function print4(report) {
|
|
|
10831
11042
|
line("");
|
|
10832
11043
|
const summary = usageSummary(report);
|
|
10833
11044
|
const worst = dims.map(usageState);
|
|
10834
|
-
if (worst.includes("over")) line(
|
|
11045
|
+
if (worst.includes("over")) line(import_picocolors40.default.red(summary));
|
|
10835
11046
|
else if (worst.includes("near") || worst.includes("unknown"))
|
|
10836
|
-
line(
|
|
11047
|
+
line(import_picocolors40.default.yellow(summary));
|
|
10837
11048
|
else success(summary);
|
|
10838
11049
|
}
|
|
10839
11050
|
function gauge(d, _labelWidth) {
|
|
10840
11051
|
const drawn = bar(d);
|
|
10841
|
-
return drawn ? ` ${
|
|
11052
|
+
return drawn ? ` ${import_picocolors40.default.dim(drawn)}` : "";
|
|
10842
11053
|
}
|
|
10843
11054
|
function colour(d) {
|
|
10844
11055
|
switch (usageState(d)) {
|
|
10845
11056
|
case "over":
|
|
10846
|
-
return d.kind === "hard" ?
|
|
11057
|
+
return d.kind === "hard" ? import_picocolors40.default.red : import_picocolors40.default.yellow;
|
|
10847
11058
|
case "near":
|
|
10848
|
-
return
|
|
11059
|
+
return import_picocolors40.default.yellow;
|
|
10849
11060
|
case "unknown":
|
|
10850
|
-
return
|
|
11061
|
+
return import_picocolors40.default.dim;
|
|
10851
11062
|
default:
|
|
10852
11063
|
return (s) => s;
|
|
10853
11064
|
}
|
|
@@ -10855,7 +11066,7 @@ function colour(d) {
|
|
|
10855
11066
|
|
|
10856
11067
|
// src/index.ts
|
|
10857
11068
|
var pkg = {
|
|
10858
|
-
version: true ? "0.6.
|
|
11069
|
+
version: true ? "0.6.9" : "0.0.0-dev"
|
|
10859
11070
|
};
|
|
10860
11071
|
var program2 = new Command();
|
|
10861
11072
|
program2.name("workser").description(
|
|
@@ -10880,6 +11091,7 @@ registerAuth(program2);
|
|
|
10880
11091
|
registerStorage(program2);
|
|
10881
11092
|
registerNeon(program2);
|
|
10882
11093
|
registerEnv(program2);
|
|
11094
|
+
registerKey(program2);
|
|
10883
11095
|
registerDeploy(program2);
|
|
10884
11096
|
registerVersions(program2);
|
|
10885
11097
|
registerLogs(program2);
|