@runcofactor/cli 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-22LMP5PX.js +255 -0
- package/dist/account-22LMP5PX.js.map +1 -0
- package/dist/{api-catalog-7HLEN7C2.js → api-catalog-WTFQNLK6.js} +5 -5
- package/dist/{attachment-OVNQD6Z2.js → attachment-U3NKVPEY.js} +5 -5
- package/dist/augmentor-5GMNAX4M.js +198 -0
- package/dist/augmentor-5GMNAX4M.js.map +1 -0
- package/dist/{auth-VUHL74FH.js → auth-VQG2CDUD.js} +3 -3
- package/dist/{chunk-PZ4LCN6K.js → chunk-3X3NW7QA.js} +2 -2
- package/dist/{chunk-VGTKUOYS.js → chunk-46IUJXSD.js} +2 -2
- package/dist/{chunk-YN763NWQ.js → chunk-7VMO2WOZ.js} +10 -4
- package/dist/chunk-7VMO2WOZ.js.map +1 -0
- package/dist/{chunk-Z5LUTUDN.js → chunk-CMGI7UZD.js} +3 -3
- package/dist/{chunk-EEN2TZUQ.js → chunk-FNPMWDUQ.js} +3 -3
- package/dist/{chunk-EJ4U242G.js → chunk-HDFYUFBI.js} +2 -2
- package/dist/{chunk-JZMJUPZP.js → chunk-JMJVGMXI.js} +2 -2
- package/dist/{chunk-JZMJUPZP.js.map → chunk-JMJVGMXI.js.map} +1 -1
- package/dist/{chunk-QGI4UCJX.js → chunk-JYGNMKZ5.js} +62 -35
- package/dist/chunk-JYGNMKZ5.js.map +1 -0
- package/dist/{chunk-CRHPDPRS.js → chunk-KCHKFYVX.js} +30 -8
- package/dist/{chunk-CRHPDPRS.js.map → chunk-KCHKFYVX.js.map} +1 -1
- package/dist/{chunk-ZD3KHESI.js → chunk-KRWRUU6R.js} +27 -7
- package/dist/chunk-KRWRUU6R.js.map +1 -0
- package/dist/{chunk-ENDHMYEJ.js → chunk-NHTEKEYE.js} +3 -3
- package/dist/{chunk-CQE46HSM.js → chunk-PRBRSIZP.js} +14 -8
- package/dist/chunk-PRBRSIZP.js.map +1 -0
- package/dist/{chunk-NL7CVG56.js → chunk-UETBLPKM.js} +57 -10
- package/dist/chunk-UETBLPKM.js.map +1 -0
- package/dist/{chunk-QQVWGWPI.js → chunk-VGYN2KU2.js} +8494 -1504
- package/dist/chunk-VGYN2KU2.js.map +1 -0
- package/dist/{chunk-ZTOE3ND3.js → chunk-XJ5YYYGC.js} +4 -4
- package/dist/{credential-LO2SEEHU.js → credential-E6KUHRGU.js} +5 -5
- package/dist/{credential-template-ZN7W7734.js → credential-template-4GPOPBGD.js} +5 -5
- package/dist/{debug-workflow-R3RYYAXK.js → debug-workflow-XCLCY6S7.js} +5 -5
- package/dist/{docs-DIAFBDXQ.js → docs-COCZYMW6.js} +95 -11
- package/dist/docs-COCZYMW6.js.map +1 -0
- package/dist/{doctor-NZPUSCRE.js → doctor-ERIVTCQS.js} +3 -3
- package/dist/{environment-RQVU4P5M.js → environment-7Y4BV6XY.js} +5 -5
- package/dist/{feature-flag-XG26RURR.js → feature-flag-MHONEX6T.js} +98 -12
- package/dist/feature-flag-MHONEX6T.js.map +1 -0
- package/dist/index.js +107 -51
- package/dist/index.js.map +1 -1
- package/dist/{init-EDNLKGPT.js → init-OROOM4HF.js} +5 -5
- package/dist/{install-FYZ3HNZK.js → install-OJFXHY6U.js} +5 -5
- package/dist/{issues-NNRVTJ4L.js → issues-32GONR6C.js} +5 -5
- package/dist/{knobs-A2BOBH22.js → knobs-UQGGY3CP.js} +7 -6
- package/dist/knobs-UQGGY3CP.js.map +1 -0
- package/dist/{list-F33VZ4BJ.js → list-ZMIKEC5P.js} +5 -5
- package/dist/{local-DQDTM3XA.js → local-PUD24GGQ.js} +7 -7
- package/dist/{login-BUMVIB36.js → login-BSO7YX2D.js} +5 -5
- package/dist/{mcp-B5Y5CDMQ.js → mcp-4LS7OJUT.js} +9 -9
- package/dist/{mcp-B5Y5CDMQ.js.map → mcp-4LS7OJUT.js.map} +1 -1
- package/dist/{pdf-extract-ABWV3L5X.js → pdf-extract-YHE54XU4.js} +2 -2
- package/dist/product-3JKSJCBC.js +346 -0
- package/dist/product-3JKSJCBC.js.map +1 -0
- package/dist/{property-NJ4SRXQG.js → property-K5DBL4UE.js} +5 -5
- package/dist/{psql-VBZFCMNR.js → psql-PQFUFTSE.js} +3 -3
- package/dist/{record-WAO36O7G.js → record-EIIYLFJ4.js} +6 -6
- package/dist/{redis-DHZXHL4S.js → redis-BU36EZZI.js} +3 -3
- package/dist/redis-BU36EZZI.js.map +1 -0
- package/dist/{release-STJKUKTE.js → release-LYC2P7DZ.js} +5 -5
- package/dist/{sandbox-DWSGLY7B.js → sandbox-CKHXXZHU.js} +51 -7
- package/dist/sandbox-CKHXXZHU.js.map +1 -0
- package/dist/{scenarios-HCIDY725.js → scenarios-2XJ2G3KR.js} +5 -5
- package/dist/{session-Y5RHU54D.js → session-UTOD5ZYH.js} +8 -9
- package/dist/session-UTOD5ZYH.js.map +1 -0
- package/dist/{skill-23WAHUOB.js → skill-GMAERMQL.js} +10 -10
- package/dist/{skill-23WAHUOB.js.map → skill-GMAERMQL.js.map} +1 -1
- package/dist/skills/debug-run/SKILL.md +7 -1
- package/dist/skills/debug-run/history/1.3.1.md +279 -0
- package/dist/skills/debug-run/version.json +1 -1
- package/dist/skills/optimize-cache/SKILL.md +29 -2
- package/dist/{spec-LM5XHOQ5.js → spec-2NP36U3Y.js} +5 -5
- package/dist/{src-22RI5VP2.js → src-4T6GHXVO.js} +2 -2
- package/dist/{src-NCJPUAE6.js → src-CG52HEE7.js} +10 -8
- package/dist/{src-Y3K7UJEF.js → src-PK5OZXCM.js} +2 -2
- package/dist/{src-BGDRMOKC.js → src-UEOOC425.js} +295 -102
- package/dist/src-UEOOC425.js.map +1 -0
- package/dist/{start-SWY55CZX.js → start-3C7EEFW2.js} +5 -5
- package/dist/{tag-YSU2XXPI.js → tag-JSHOMLBR.js} +6 -6
- package/dist/{task-NLBKLD7D.js → task-YGWVYTBJ.js} +5 -5
- package/dist/{test-suite-QCPWZ2LS.js → test-suite-LI7ZH367.js} +10 -8
- package/dist/{test-suite-QCPWZ2LS.js.map → test-suite-LI7ZH367.js.map} +1 -1
- package/dist/trace-UMLOSIIR.js +16 -0
- package/dist/{triage-TT4BMDBU.js → triage-ZWJG4NBJ.js} +6 -6
- package/dist/{upgrade-6ZUFETKX.js → upgrade-S7CGEK6H.js} +3 -3
- package/dist/{workflow-2CX3ZNOQ.js → workflow-T4HSAOGW.js} +86 -15
- package/dist/workflow-T4HSAOGW.js.map +1 -0
- package/dist/{workflow-cache-GXNE6SU2.js → workflow-cache-XVEZ36KF.js} +8 -8
- package/dist/{workflow-debug-PRX3DWGD.js → workflow-debug-T2BULXZ7.js} +9 -9
- package/dist/{workflow-proposals-BW327WGL.js → workflow-proposals-XXEZICN2.js} +5 -7
- package/dist/workflow-proposals-XXEZICN2.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-CQE46HSM.js.map +0 -1
- package/dist/chunk-NL7CVG56.js.map +0 -1
- package/dist/chunk-QGI4UCJX.js.map +0 -1
- package/dist/chunk-QQVWGWPI.js.map +0 -1
- package/dist/chunk-YN763NWQ.js.map +0 -1
- package/dist/chunk-ZD3KHESI.js.map +0 -1
- package/dist/docs-DIAFBDXQ.js.map +0 -1
- package/dist/feature-flag-XG26RURR.js.map +0 -1
- package/dist/knobs-A2BOBH22.js.map +0 -1
- package/dist/redis-DHZXHL4S.js.map +0 -1
- package/dist/sandbox-DWSGLY7B.js.map +0 -1
- package/dist/session-Y5RHU54D.js.map +0 -1
- package/dist/src-BGDRMOKC.js.map +0 -1
- package/dist/trace-A3ZY6K26.js +0 -16
- package/dist/workflow-2CX3ZNOQ.js.map +0 -1
- package/dist/workflow-proposals-BW327WGL.js.map +0 -1
- /package/dist/{api-catalog-7HLEN7C2.js.map → api-catalog-WTFQNLK6.js.map} +0 -0
- /package/dist/{attachment-OVNQD6Z2.js.map → attachment-U3NKVPEY.js.map} +0 -0
- /package/dist/{auth-VUHL74FH.js.map → auth-VQG2CDUD.js.map} +0 -0
- /package/dist/{chunk-PZ4LCN6K.js.map → chunk-3X3NW7QA.js.map} +0 -0
- /package/dist/{chunk-VGTKUOYS.js.map → chunk-46IUJXSD.js.map} +0 -0
- /package/dist/{chunk-Z5LUTUDN.js.map → chunk-CMGI7UZD.js.map} +0 -0
- /package/dist/{chunk-EEN2TZUQ.js.map → chunk-FNPMWDUQ.js.map} +0 -0
- /package/dist/{chunk-EJ4U242G.js.map → chunk-HDFYUFBI.js.map} +0 -0
- /package/dist/{chunk-ENDHMYEJ.js.map → chunk-NHTEKEYE.js.map} +0 -0
- /package/dist/{chunk-ZTOE3ND3.js.map → chunk-XJ5YYYGC.js.map} +0 -0
- /package/dist/{credential-LO2SEEHU.js.map → credential-E6KUHRGU.js.map} +0 -0
- /package/dist/{credential-template-ZN7W7734.js.map → credential-template-4GPOPBGD.js.map} +0 -0
- /package/dist/{debug-workflow-R3RYYAXK.js.map → debug-workflow-XCLCY6S7.js.map} +0 -0
- /package/dist/{doctor-NZPUSCRE.js.map → doctor-ERIVTCQS.js.map} +0 -0
- /package/dist/{environment-RQVU4P5M.js.map → environment-7Y4BV6XY.js.map} +0 -0
- /package/dist/{init-EDNLKGPT.js.map → init-OROOM4HF.js.map} +0 -0
- /package/dist/{install-FYZ3HNZK.js.map → install-OJFXHY6U.js.map} +0 -0
- /package/dist/{issues-NNRVTJ4L.js.map → issues-32GONR6C.js.map} +0 -0
- /package/dist/{list-F33VZ4BJ.js.map → list-ZMIKEC5P.js.map} +0 -0
- /package/dist/{local-DQDTM3XA.js.map → local-PUD24GGQ.js.map} +0 -0
- /package/dist/{login-BUMVIB36.js.map → login-BSO7YX2D.js.map} +0 -0
- /package/dist/{pdf-extract-ABWV3L5X.js.map → pdf-extract-YHE54XU4.js.map} +0 -0
- /package/dist/{property-NJ4SRXQG.js.map → property-K5DBL4UE.js.map} +0 -0
- /package/dist/{psql-VBZFCMNR.js.map → psql-PQFUFTSE.js.map} +0 -0
- /package/dist/{record-WAO36O7G.js.map → record-EIIYLFJ4.js.map} +0 -0
- /package/dist/{release-STJKUKTE.js.map → release-LYC2P7DZ.js.map} +0 -0
- /package/dist/{scenarios-HCIDY725.js.map → scenarios-2XJ2G3KR.js.map} +0 -0
- /package/dist/{spec-LM5XHOQ5.js.map → spec-2NP36U3Y.js.map} +0 -0
- /package/dist/{src-22RI5VP2.js.map → src-4T6GHXVO.js.map} +0 -0
- /package/dist/{src-NCJPUAE6.js.map → src-CG52HEE7.js.map} +0 -0
- /package/dist/{src-Y3K7UJEF.js.map → src-PK5OZXCM.js.map} +0 -0
- /package/dist/{start-SWY55CZX.js.map → start-3C7EEFW2.js.map} +0 -0
- /package/dist/{tag-YSU2XXPI.js.map → tag-JSHOMLBR.js.map} +0 -0
- /package/dist/{task-NLBKLD7D.js.map → task-YGWVYTBJ.js.map} +0 -0
- /package/dist/{trace-A3ZY6K26.js.map → trace-UMLOSIIR.js.map} +0 -0
- /package/dist/{triage-TT4BMDBU.js.map → triage-ZWJG4NBJ.js.map} +0 -0
- /package/dist/{upgrade-6ZUFETKX.js.map → upgrade-S7CGEK6H.js.map} +0 -0
- /package/dist/{workflow-cache-GXNE6SU2.js.map → workflow-cache-XVEZ36KF.js.map} +0 -0
- /package/dist/{workflow-debug-PRX3DWGD.js.map → workflow-debug-T2BULXZ7.js.map} +0 -0
|
@@ -2,14 +2,14 @@ import { createRequire as __cr } from "module"; const require = __cr(import.meta
|
|
|
2
2
|
import {
|
|
3
3
|
apiRequest,
|
|
4
4
|
promptInput
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-PRBRSIZP.js";
|
|
6
6
|
import "./chunk-3CZU7XCS.js";
|
|
7
7
|
import {
|
|
8
8
|
hasFlag
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-3X3NW7QA.js";
|
|
10
|
+
import "./chunk-JMJVGMXI.js";
|
|
11
11
|
import "./chunk-JWHYXEA2.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-JYGNMKZ5.js";
|
|
13
13
|
import "./chunk-VKVL7WBN.js";
|
|
14
14
|
|
|
15
15
|
// src/workflow-cache.ts
|
|
@@ -270,7 +270,7 @@ async function handleSubstrate(argv) {
|
|
|
270
270
|
process.exit(1);
|
|
271
271
|
}
|
|
272
272
|
const actionIndex = Number(actionIndexRaw);
|
|
273
|
-
const { SubstrateMaterializer } = await import("./src-
|
|
273
|
+
const { SubstrateMaterializer } = await import("./src-UEOOC425.js");
|
|
274
274
|
const path = await import("path");
|
|
275
275
|
const materializer = new SubstrateMaterializer({
|
|
276
276
|
traceZipPath: path.join(workspace, "browser", "trace.zip"),
|
|
@@ -306,8 +306,8 @@ async function handleLocator(argv) {
|
|
|
306
306
|
}
|
|
307
307
|
}
|
|
308
308
|
const actionIndex = Number(actionIndexRaw);
|
|
309
|
-
const { HeadlessDomSession, SubstrateMaterializer, LocatorVerifier, buildLocator } = await import("./src-
|
|
310
|
-
const { parseSnapshot } = await import("./src-
|
|
309
|
+
const { HeadlessDomSession, SubstrateMaterializer, LocatorVerifier, buildLocator } = await import("./src-UEOOC425.js");
|
|
310
|
+
const { parseSnapshot } = await import("./src-CG52HEE7.js");
|
|
311
311
|
const path = await import("path");
|
|
312
312
|
const session = new HeadlessDomSession();
|
|
313
313
|
const materializer = new SubstrateMaterializer({
|
|
@@ -383,4 +383,4 @@ export {
|
|
|
383
383
|
buildCacheClearBody,
|
|
384
384
|
handleWorkflowCache
|
|
385
385
|
};
|
|
386
|
-
//# sourceMappingURL=workflow-cache-
|
|
386
|
+
//# sourceMappingURL=workflow-cache-XVEZ36KF.js.map
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
runTrace
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XJ5YYYGC.js";
|
|
5
5
|
import {
|
|
6
6
|
apiRequest
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-PRBRSIZP.js";
|
|
8
8
|
import "./chunk-3CZU7XCS.js";
|
|
9
9
|
import {
|
|
10
10
|
getArgValue,
|
|
11
11
|
hasFlag
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-3X3NW7QA.js";
|
|
13
|
+
import "./chunk-JMJVGMXI.js";
|
|
14
|
+
import "./chunk-VGYN2KU2.js";
|
|
15
15
|
import "./chunk-JWHYXEA2.js";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-JYGNMKZ5.js";
|
|
17
17
|
import "./chunk-6LEZCKKV.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-KRWRUU6R.js";
|
|
19
19
|
import "./chunk-VKVL7WBN.js";
|
|
20
20
|
|
|
21
21
|
// src/workflow-debug.ts
|
|
@@ -875,7 +875,7 @@ async function handleMaterialize(argv, apiUrl, token) {
|
|
|
875
875
|
const runId = requireRunId(argv);
|
|
876
876
|
const workflowId = await resolveWorkflowId(argv, runId, apiUrl, token);
|
|
877
877
|
const outDir = getArgValue(argv, "--out") ?? `./diag-${runId}`;
|
|
878
|
-
const { assembleWorkspace } = await import("./src-
|
|
878
|
+
const { assembleWorkspace } = await import("./src-4T6GHXVO.js");
|
|
879
879
|
const dataUrl = `${apiUrl}/workflows/${encodeURIComponent(workflowId)}/runs/${encodeURIComponent(runId)}/debug/materialize-data`;
|
|
880
880
|
const dataRes = await fetch(dataUrl, { headers: { Authorization: `Bearer ${token}` } });
|
|
881
881
|
if (!dataRes.ok) {
|
|
@@ -925,4 +925,4 @@ async function handleMaterialize(argv, apiUrl, token) {
|
|
|
925
925
|
export {
|
|
926
926
|
handleWorkflowDebug
|
|
927
927
|
};
|
|
928
|
-
//# sourceMappingURL=workflow-debug-
|
|
928
|
+
//# sourceMappingURL=workflow-debug-T2BULXZ7.js.map
|
|
@@ -6,15 +6,15 @@ import {
|
|
|
6
6
|
} from "./chunk-JDBCZ3Z2.js";
|
|
7
7
|
import {
|
|
8
8
|
apiRequest
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PRBRSIZP.js";
|
|
10
10
|
import "./chunk-3CZU7XCS.js";
|
|
11
11
|
import {
|
|
12
12
|
getArgValue,
|
|
13
13
|
hasFlag
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-3X3NW7QA.js";
|
|
15
|
+
import "./chunk-JMJVGMXI.js";
|
|
16
16
|
import "./chunk-JWHYXEA2.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-JYGNMKZ5.js";
|
|
18
18
|
import "./chunk-VKVL7WBN.js";
|
|
19
19
|
|
|
20
20
|
// src/workflow-proposals.ts
|
|
@@ -321,7 +321,6 @@ async function handleRevert(argv, apiUrl, token) {
|
|
|
321
321
|
});
|
|
322
322
|
}
|
|
323
323
|
function buildDiffPayload(proposal, proposedSnap, diff) {
|
|
324
|
-
const byId = new Map(proposedSnap.nodes.map((n) => [n.id, n]));
|
|
325
324
|
return {
|
|
326
325
|
proposal: {
|
|
327
326
|
id: proposal.id,
|
|
@@ -374,10 +373,9 @@ function buildDiffPayload(proposal, proposedSnap, diff) {
|
|
|
374
373
|
}))
|
|
375
374
|
}
|
|
376
375
|
};
|
|
377
|
-
void byId;
|
|
378
376
|
}
|
|
379
377
|
export {
|
|
380
378
|
_internalsForTesting,
|
|
381
379
|
handleWorkflowProposals
|
|
382
380
|
};
|
|
383
|
-
//# sourceMappingURL=workflow-proposals-
|
|
381
|
+
//# sourceMappingURL=workflow-proposals-XXEZICN2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/workflow-proposals.ts","../src/proposals-format.ts"],"sourcesContent":["/**\n * `canary workflow proposals <verb>` — list / get / diff / accept / reject /\n * revert workflow proposals.\n *\n * Output mode auto-detects: JSON when piped (`!process.stdout.isTTY`), pretty\n * text when running interactively. `--json` and `--text` flags force either\n * mode. Designed so an agent can pipe JSON straight into `jq` without any\n * extra flag, and a human gets the readable report at a terminal.\n */\n\nimport process from 'node:process';\nimport {\n diffSnapshots,\n fromApiSnapshot,\n type SnapshotDiff,\n} from '@chatsdet/workflow-diff';\nimport { getArgValue, hasFlag } from './auth.js';\n\n/**\n * Like `getArgValue` but also accepts the `--key=value` form that many\n * agents emit by default. Falls back to the space-separated form. Matches\n * only exact `--key=` to avoid false-positives on `--status-filter=x` when\n * looking for `--status`.\n */\nfunction getArg(argv: string[], key: string): string | undefined {\n const prefix = `${key}=`;\n const eq = argv.find((a) => a.startsWith(prefix));\n if (eq) return eq.slice(prefix.length);\n return getArgValue(argv, key);\n}\n\n/** @internal — exported for unit tests only. */\nexport const _internalsForTesting = { getArg };\nimport { apiRequest } from './cli-helpers.js';\nimport { renderProposalList, renderProposalDiff } from './proposals-format.js';\n\n// ── Types ────────────────────────────────────────────────────────────────\n\nexport interface ProposalSummary {\n id: string;\n workflowId: string;\n title: string;\n description: string | null;\n source: 'agent' | 'user' | 'import' | 'api';\n status: 'pending' | 'accepted' | 'rejected' | 'stale';\n createdByUserId: string | null;\n decidedByUserId: string | null;\n decidedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ProposalDetail extends ProposalSummary {\n snapshotJson: {\n nodes?: Array<{\n id: string;\n nodeType: string;\n orderIndex?: number;\n configJson?: Record<string, unknown>;\n }>;\n edges?: Array<{\n id: string;\n sourceNodeId: string;\n targetNodeId: string;\n edgeType?: string | null;\n }>;\n };\n sourceMetadata: Record<string, unknown> | null;\n}\n\ninterface WorkflowDetail {\n id: string;\n nodes: Array<{\n id: string;\n nodeType: string;\n orderIndex?: number;\n configJson?: Record<string, unknown>;\n }>;\n edges: Array<{\n id: string;\n sourceNodeId: string;\n targetNodeId: string;\n edgeType?: string | null;\n }>;\n updatedAt?: string;\n}\n\n// ── Dispatcher ───────────────────────────────────────────────────────────\n\nexport async function handleWorkflowProposals(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n const [verb, ...rest] = argv;\n switch (verb) {\n case 'list':\n await handleList(rest, apiUrl, token);\n break;\n case 'get':\n await handleGet(rest, apiUrl, token);\n break;\n case 'diff':\n await handleDiff(rest, apiUrl, token);\n break;\n case 'accept':\n await handleAccept(rest, apiUrl, token);\n break;\n case 'reject':\n await handleReject(rest, apiUrl, token);\n break;\n case 'revert':\n await handleRevert(rest, apiUrl, token);\n break;\n default:\n printHelp();\n process.exit(verb ? 1 : 0);\n }\n}\n\nfunction printHelp() {\n console.error(\n [\n 'Usage: canary workflow proposals <verb> <workflowId> [<proposalId>] [options]',\n '',\n 'Verbs:',\n ' list <wf> list proposals for a workflow',\n ' get <wf> <pid> fetch a proposal (full snapshot)',\n ' diff <wf> <pid> show the diff against the current draft',\n ' accept <wf> <pid> apply the proposal (full or --select=id1,id2)',\n ' reject <wf> <pid> reject the proposal (no draft change)',\n ' revert <wf> <pid> revert a previously-accepted proposal to pending',\n '',\n 'Global options:',\n ' --json force JSON output',\n ' --text force pretty-text output (default when stdout is a TTY)',\n ' --status=<status> (list) filter by pending|accepted|rejected|stale|all',\n ' --include-unchanged (diff) also list rows that did not change',\n ' --select=<ids> (accept) comma-separated node ids to accept (default: all)',\n ].join('\\n'),\n );\n}\n\n// ── Output-mode helper ───────────────────────────────────────────────────\n\nfunction wantsJson(argv: string[]): boolean {\n if (hasFlag(argv, '--json')) return true;\n if (hasFlag(argv, '--text')) return false;\n return !process.stdout.isTTY;\n}\n\nfunction emit(argv: string[], textFallback: string, json: unknown): void {\n if (wantsJson(argv)) {\n console.log(JSON.stringify(json, null, 2));\n } else {\n console.log(textFallback);\n }\n}\n\nfunction requireArgs(\n argv: string[],\n n: number,\n verb: string,\n): asserts argv is string[] {\n if (argv.length < n) {\n console.error(\n `Error: canary workflow proposals ${verb} requires ${n} argument${n === 1 ? '' : 's'}`,\n );\n printHelp();\n process.exit(1);\n }\n}\n\n// ── Handlers ─────────────────────────────────────────────────────────────\n\nasync function handleList(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 1, 'list');\n const [workflowId] = argv;\n const status = getArg(argv, '--status') ?? 'pending';\n const query = status === 'all' ? '' : `?status=${encodeURIComponent(status)}`;\n\n const result = await apiRequest<{\n ok: boolean;\n data?: ProposalSummary[];\n error?: string;\n }>(apiUrl, token, 'GET', `/workflows/${workflowId}/proposals${query}`);\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'failed to list proposals'}`);\n process.exit(1);\n }\n\n const proposals = result.data ?? [];\n emit(argv, renderProposalList(proposals), {\n workflowId,\n count: proposals.length,\n proposals,\n });\n}\n\nasync function handleGet(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'get');\n const [workflowId, proposalId] = argv;\n\n const result = await apiRequest<{\n ok: boolean;\n data?: ProposalDetail;\n error?: string;\n }>(apiUrl, token, 'GET', `/workflows/${workflowId}/proposals/${proposalId}`);\n\n if (!result.ok || !result.data) {\n console.error(`Error: ${result.error ?? 'proposal not found'}`);\n process.exit(1);\n }\n\n const prop = result.data;\n const text = [\n `Proposal: ${prop.title}`,\n `Source: ${prop.source} Status: ${prop.status}`,\n `Created: ${prop.createdAt}`,\n `Nodes: ${prop.snapshotJson.nodes?.length ?? 0} Edges: ${prop.snapshotJson.edges?.length ?? 0}`,\n ].join('\\n');\n emit(argv, text, prop);\n}\n\nasync function handleDiff(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'diff');\n const [workflowId, proposalId] = argv;\n\n const [propRes, wfRes] = await Promise.all([\n apiRequest<{ ok: boolean; data?: ProposalDetail; error?: string }>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}/proposals/${proposalId}`,\n ),\n apiRequest<{ ok: boolean; workflow?: WorkflowDetail; error?: string }>(\n apiUrl,\n token,\n 'GET',\n `/workflows/${workflowId}`,\n ),\n ]);\n\n if (!propRes.ok || !propRes.data) {\n console.error(`Error: ${propRes.error ?? 'proposal not found'}`);\n process.exit(1);\n }\n if (!wfRes.workflow) {\n console.error(`Error: ${wfRes.error ?? 'workflow not found'}`);\n process.exit(1);\n }\n\n const proposal = propRes.data;\n const workflow = wfRes.workflow;\n\n const current = fromApiSnapshot({\n nodes: workflow.nodes,\n edges: workflow.edges,\n });\n const proposed = fromApiSnapshot(proposal.snapshotJson);\n const diff = diffSnapshots(current, proposed);\n\n const payload = buildDiffPayload(proposal, proposed, diff);\n const includeUnchanged = hasFlag(argv, '--include-unchanged');\n emit(argv, renderProposalDiff(payload, { includeUnchanged }), payload);\n}\n\nasync function handleAccept(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'accept');\n const [workflowId, proposalId] = argv;\n const selectArg = getArg(argv, '--select');\n const body: { selection?: { acceptedNodeIds: string[] } } = {};\n if (selectArg) {\n const ids = selectArg.split(',').map((s) => s.trim()).filter(Boolean);\n body.selection = { acceptedNodeIds: ids };\n }\n\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/accept`,\n selectArg ? body : undefined,\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'accept failed'}`);\n process.exit(1);\n }\n\n emit(\n argv,\n selectArg\n ? `Accepted ${body.selection!.acceptedNodeIds.length} changes from ${proposalId}.`\n : `Accepted proposal ${proposalId} in full.`,\n { ok: true, proposalId, workflowId, partial: Boolean(selectArg) },\n );\n}\n\nasync function handleReject(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'reject');\n const [workflowId, proposalId] = argv;\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/reject`,\n );\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'reject failed'}`);\n process.exit(1);\n }\n emit(argv, `Rejected proposal ${proposalId}.`, {\n ok: true,\n proposalId,\n workflowId,\n });\n}\n\nasync function handleRevert(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n requireArgs(argv, 2, 'revert');\n const [workflowId, proposalId] = argv;\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/revert`,\n );\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'revert failed'}`);\n process.exit(1);\n }\n emit(argv, `Reverted proposal ${proposalId} back to pending.`, {\n ok: true,\n proposalId,\n workflowId,\n });\n}\n\n// ── Diff payload shaper ──────────────────────────────────────────────────\n\nexport interface DiffPayload {\n proposal: {\n id: string;\n title: string;\n source: string;\n status: string;\n stale: boolean;\n createdAt: string;\n decidedAt: string | null;\n };\n summary: {\n addedNodes: number;\n removedNodes: number;\n changedNodes: number;\n addedEdges: number;\n removedEdges: number;\n touchedCount: number;\n isEmpty: boolean;\n };\n nodes: {\n added: Array<{\n id: string;\n nodeType: string;\n configJson: Record<string, unknown>;\n }>;\n removed: Array<{\n id: string;\n nodeType: string;\n configJson: Record<string, unknown>;\n }>;\n changed: Array<{\n id: string;\n nodeType: string;\n typeChanged: boolean;\n beforeType?: string;\n afterType?: string;\n fieldChanges: Array<{ path: string; before: unknown; after: unknown }>;\n }>;\n };\n edges: {\n added: Array<{\n sourceNodeId: string;\n targetNodeId: string;\n edgeType: string | null;\n }>;\n removed: Array<{\n sourceNodeId: string;\n targetNodeId: string;\n edgeType: string | null;\n }>;\n };\n}\n\nfunction buildDiffPayload(\n proposal: ProposalDetail,\n proposedSnap: ReturnType<typeof fromApiSnapshot>,\n diff: SnapshotDiff,\n): DiffPayload {\n return {\n proposal: {\n id: proposal.id,\n title: proposal.title,\n source: proposal.source,\n status: proposal.status,\n stale: proposal.status === 'stale',\n createdAt: proposal.createdAt,\n decidedAt: proposal.decidedAt,\n },\n summary: {\n addedNodes: diff.addedNodes.length,\n removedNodes: diff.removedNodes.length,\n changedNodes: diff.changedNodes.length,\n addedEdges: diff.addedEdges.length,\n removedEdges: diff.removedEdges.length,\n touchedCount: diff.touchedCount,\n isEmpty: diff.isEmpty,\n },\n nodes: {\n added: diff.addedNodes.map((n) => ({\n id: n.id,\n nodeType: n.nodeType,\n configJson: n.configJson,\n })),\n removed: diff.removedNodes.map((n) => ({\n id: n.id,\n nodeType: n.nodeType,\n configJson: n.configJson,\n })),\n changed: diff.changedNodes.map((c) => ({\n id: c.id,\n nodeType: c.nodeType,\n typeChanged: c.typeChanged,\n beforeType: c.beforeType,\n afterType: c.afterType,\n fieldChanges: c.fieldChanges,\n })),\n },\n edges: {\n added: diff.addedEdges.map((e) => ({\n sourceNodeId: e.sourceNodeId,\n targetNodeId: e.targetNodeId,\n edgeType: e.edgeType ?? null,\n })),\n removed: diff.removedEdges.map((e) => ({\n sourceNodeId: e.sourceNodeId,\n targetNodeId: e.targetNodeId,\n edgeType: e.edgeType ?? null,\n })),\n },\n };\n}\n","/**\n * Pretty-text renderers for `canary workflow proposals list | diff`.\n * Pure — no fetching, easy to test.\n */\n\nimport { getNodeDisplayTitle } from '@chatsdet/workflow-diff';\nimport type { ProposalSummary, DiffPayload } from './workflow-proposals.js';\n\nconst STATUS_DOTS: Record<string, string> = {\n pending: '●',\n accepted: '✓',\n rejected: '✗',\n stale: '⚠',\n};\n\nexport function renderProposalList(proposals: ProposalSummary[]): string {\n if (proposals.length === 0) return 'No proposals.';\n const rows = proposals.map((p) => {\n const dot = STATUS_DOTS[p.status] ?? '•';\n return `${dot} ${pad(p.status, 10)} ${pad(p.source, 8)} ${p.id.slice(0, 8)}… ${p.title}`;\n });\n return [\n `${proposals.length} proposal${proposals.length === 1 ? '' : 's'}`,\n '',\n ...rows,\n ].join('\\n');\n}\n\nexport function renderProposalDiff(\n payload: DiffPayload,\n opts: { includeUnchanged?: boolean } = {},\n): string {\n const { proposal, summary, nodes, edges } = payload;\n const staleNote = proposal.stale ? ' ⚠ STALE' : '';\n const header = [\n `Proposal: ${proposal.title}`,\n `Source: ${proposal.source} Status: ${proposal.status}${staleNote}`,\n `Created: ${proposal.createdAt}`,\n '',\n `Summary: ${summary.addedNodes} added · ${summary.removedNodes} removed · ${summary.changedNodes} changed · ${summary.touchedCount} touched`,\n ];\n\n if (summary.isEmpty) {\n return [...header, '', 'No changes — proposal matches the current draft.'].join('\\n');\n }\n\n const blocks: string[] = [];\n\n for (const n of nodes.added) {\n blocks.push(\n `+ ${pad(n.nodeType.toUpperCase(), 14)} ${getNodeDisplayTitle(n.nodeType, n.configJson)} (${n.id})`,\n );\n }\n for (const n of nodes.removed) {\n blocks.push(\n `- ${pad(n.nodeType.toUpperCase(), 14)} ${getNodeDisplayTitle(n.nodeType, n.configJson)} (${n.id})`,\n );\n }\n for (const c of nodes.changed) {\n const lines = [\n `~ ${pad(c.nodeType.toUpperCase(), 14)} ${c.id}`,\n ];\n if (c.typeChanged) {\n lines.push(` nodeType: ${c.beforeType} → ${c.afterType}`);\n }\n for (const fc of c.fieldChanges) {\n lines.push(` ${fc.path}: ${fmt(fc.before)} → ${fmt(fc.after)}`);\n }\n blocks.push(lines.join('\\n'));\n }\n\n const edgeLine = `Edges: +${summary.addedEdges} -${summary.removedEdges}`;\n if (edges.added.length === 0 && edges.removed.length === 0) {\n return [...header, '', ...blocks, '', edgeLine].join('\\n');\n }\n const edgeLines = [\n ...edges.added.map(\n (e) => ` + ${e.sourceNodeId} → ${e.targetNodeId}${e.edgeType ? ` [${e.edgeType}]` : ''}`,\n ),\n ...edges.removed.map(\n (e) => ` - ${e.sourceNodeId} → ${e.targetNodeId}${e.edgeType ? ` [${e.edgeType}]` : ''}`,\n ),\n ];\n\n const out = [...header, '', ...blocks, '', edgeLine, ...edgeLines];\n\n // --include-unchanged is a passthrough hook for a future expansion; today\n // the diff engine doesn't surface unchanged nodes, so we just note that.\n if (opts.includeUnchanged) {\n out.push('', '(--include-unchanged has no additional output in v1)');\n }\n\n return out.join('\\n');\n}\n\nfunction pad(s: string, n: number): string {\n return s.length >= n ? s : s + ' '.repeat(n - s.length);\n}\n\nfunction fmt(v: unknown): string {\n if (v === undefined) return '(none)';\n if (v === null) return 'null';\n if (typeof v === 'string') return JSON.stringify(v);\n if (typeof v === 'number' || typeof v === 'boolean') return String(v);\n try {\n return JSON.stringify(v);\n } catch {\n return String(v);\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli-helpers.ts"],"sourcesContent":["/**\n * Shared CLI helpers for superadmin management commands (knobs, feature-flags).\n */\n\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { getCanaryTmpDir } from '@chatsdet/tmp';\nimport { VALID_MACRO_NAMES } from '@chatsdet/types';\nimport { getArgValue } from './auth.js';\nimport { apiFetch, exitOnFailure, isTerminalFailure } from './api-fetch.js';\n\nexport type LifecycleStage = 'active' | 'deprecated' | 'ready_for_cleanup';\n\nexport function toLifecycleLabel(stage: LifecycleStage): string {\n switch (stage) {\n case 'deprecated':\n return 'deprecated';\n case 'ready_for_cleanup':\n return 'ready_for_cleanup';\n default:\n return 'active';\n }\n}\n\nexport function parseLifecycleStage(argv: string[]): LifecycleStage {\n const stage = getArgValue(argv, '--stage');\n if (!stage || !['active', 'deprecated', 'ready_for_cleanup'].includes(stage)) {\n console.error(\n 'Error: --stage is required and must be one of: active, deprecated, ready_for_cleanup'\n );\n process.exit(1);\n }\n return stage as LifecycleStage;\n}\n\nexport async function apiRequest<T extends { ok: boolean; error?: string }>(\n apiUrl: string,\n token: string,\n method: string,\n path: string,\n body?: Record<string, unknown>,\n options?: { timeoutMs?: number }\n): Promise<T> {\n const result = await apiFetch(`${apiUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n token,\n ...(options?.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),\n ...(body ? { body: JSON.stringify(body) } : {}),\n });\n\n if (!result.ok) {\n const { failure } = result;\n // Terminal kinds (auth/proxy/TLS) surface the full diagnostic and exit;\n // http-error falls through so the caller can pretty-print structured\n // user errors (unresolved vars, invalid macros, etc.).\n if (isTerminalFailure(failure)) exitOnFailure(failure);\n const text = failure.body ?? '';\n let errorMessage = failure.message;\n let parsed: Record<string, unknown> | null = null;\n try {\n const data = JSON.parse(text);\n if (data && typeof data === 'object') {\n parsed = data as Record<string, unknown>;\n if (typeof parsed.error === 'string') errorMessage = parsed.error;\n }\n } catch {\n /* keep failure.message */\n }\n return { ...parsed, ok: false, error: errorMessage } as T;\n }\n\n try {\n return (await result.response.json()) as T;\n } catch {\n return { ok: false, error: `Invalid JSON response (${result.response.status})` } as T;\n }\n}\n\ntype UnresolvedRef = {\n nodeId?: string;\n nodeType?: string;\n field?: string;\n variable: string;\n};\n\n/**\n * Render a structured `userError` response from the workflow API into a\n * multi-line, actionable message. Recognizes `WORKFLOW_UNRESOLVED_VARIABLES`\n * and falls back to `✖ {code}: {message}` for other codes. Returns `null` if\n * the response body isn't a recognized structured error.\n */\nexport function renderWorkflowUserError(result: Record<string, unknown>): string | null {\n const code = typeof result.code === 'string' ? result.code : null;\n const message = typeof result.error === 'string' ? result.error : null;\n if (!code) return null;\n\n if (code === 'WORKFLOW_VALIDATION_FAILED') {\n type ValidationIssue = {\n nodeId?: string | null;\n nodeType?: string | null;\n field?: string;\n message?: string;\n severity?: 'error' | 'warning';\n };\n const issues = Array.isArray(result.issues) ? (result.issues as ValidationIssue[]) : [];\n const errors = issues.filter((i) => (i.severity ?? 'error') === 'error');\n const warnings = issues.filter((i) => i.severity === 'warning');\n\n const lines: string[] = [\n `✖ Validation failed (${errors.length} error${errors.length === 1 ? '' : 's'}` +\n (warnings.length > 0\n ? `, ${warnings.length} warning${warnings.length === 1 ? '' : 's'}`\n : '') +\n ')',\n ];\n if (message) lines.push(` ${message}`);\n\n // Group by nodeId (null = flow-level).\n const byNode = new Map<string, ValidationIssue[]>();\n for (const issue of issues) {\n const key = issue.nodeId ?? '__flow__';\n const arr = byNode.get(key) ?? [];\n arr.push(issue);\n byNode.set(key, arr);\n }\n for (const [nodeKey, nodeIssues] of byNode) {\n const heading =\n nodeKey === '__flow__'\n ? 'Flow'\n : `Node ${nodeKey}${nodeIssues[0]?.nodeType ? ` (${nodeIssues[0].nodeType})` : ''}`;\n lines.push(` ${heading}:`);\n for (const issue of nodeIssues) {\n const sev = issue.severity === 'warning' ? '⚠' : '•';\n const field = issue.field ? `${issue.field} — ` : '';\n lines.push(` ${sev} ${field}${issue.message ?? ''}`);\n }\n }\n return lines.join('\\n');\n }\n\n if (code === 'WORKFLOW_UNRESOLVED_VARIABLES') {\n const lines: string[] = [`✖ ${code}`];\n if (message) lines.push(` ${message}`);\n const refs = Array.isArray(result.refs) ? (result.refs as UnresolvedRef[]) : [];\n const variables = Array.isArray(result.variables)\n ? (result.variables as string[])\n : refs.map((r) => r.variable);\n\n if (refs.length > 0) {\n lines.push(' Unresolved references:');\n for (const ref of refs) {\n const loc = ref.field && ref.nodeId ? ` (node ${ref.nodeId}, ${ref.field})` : '';\n lines.push(` • $var.${ref.variable}${loc}`);\n }\n } else if (variables.length > 0) {\n lines.push(' Unresolved:');\n for (const v of variables) lines.push(` • $var.${v}`);\n }\n\n const macroHints = variables.filter((v) => VALID_MACRO_NAMES.has(v.toUpperCase()));\n if (macroHints.length > 0) {\n lines.push(' Hint: these look like macro names, not variables:');\n for (const v of macroHints) {\n lines.push(` $var.${v} → $${v.toUpperCase()}()`);\n }\n }\n return lines.join('\\n');\n }\n\n if (code === 'WORKFLOW_INVALID_INPUT_VALUES') {\n const lines: string[] = [`✖ ${code}`];\n if (message) lines.push(` ${message}`);\n const issues = Array.isArray(result.issues)\n ? (result.issues as Array<{\n key?: string;\n value?: string;\n reason?: string;\n variables?: string[];\n }>)\n : [];\n for (const issue of issues) {\n const key = issue.key ?? '?';\n const value = issue.value ?? '';\n if (issue.reason === 'self_referential') {\n lines.push(` • ${key}: self-referential → ${value}`);\n lines.push(` Use a literal or point at a different upstream variable.`);\n } else if (issue.reason === 'macro_name_used_as_var') {\n lines.push(` • ${key}: macro name used as $var → ${value}`);\n for (const v of issue.variables ?? []) {\n lines.push(` $var.${v} → $${v.toUpperCase()}()`);\n }\n } else {\n lines.push(` • ${key}: ${issue.reason ?? 'invalid'} → ${value}`);\n }\n }\n return lines.join('\\n');\n }\n\n if (code === 'WORKFLOW_INVALID_MACRO') {\n const lines: string[] = [`✖ ${code}`];\n if (message) lines.push(` ${message}`);\n const invalid = Array.isArray(result.invalid) ? (result.invalid as string[]) : [];\n const valid = Array.isArray(result.valid) ? (result.valid as string[]) : [];\n if (invalid.length > 0) {\n lines.push(` Invalid macro(s): ${invalid.map((n) => `$${n}()`).join(', ')}`);\n }\n if (valid.length > 0) {\n lines.push(` Valid macros: ${valid.map((n) => `$${n}()`).join(', ')}`);\n }\n return lines.join('\\n');\n }\n\n return `✖ ${code}${message ? `: ${message}` : ''}`;\n}\n\nexport async function downloadStorageState(opts: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n prefix?: string;\n}): Promise<string | undefined> {\n const tmpFile = path.join(getCanaryTmpDir(), `${opts.prefix ?? 'canary-ss'}-${Date.now()}.json`);\n try {\n const res = await fetch(\n `${opts.apiUrl}/org/properties/${opts.propertyId}/credentials/${opts.credentialId}/storage-state/download`,\n {\n headers: { Authorization: `Bearer ${opts.token}` },\n redirect: 'follow',\n }\n );\n if (res.ok) {\n const body = await res.text();\n await fs.writeFile(tmpFile, body, 'utf-8');\n return tmpFile;\n }\n } catch {\n // Caller handles missing storage state\n }\n return undefined;\n}\n\n/* ── Credential selection ─────────────────────────────────────────────── */\n\nexport interface CredentialListItem {\n id: string;\n name: string;\n propertyId: string;\n propertyName?: string;\n propertyBaseUrl?: string;\n environmentId?: string | null;\n environmentName?: string | null;\n storageStateS3Key?: string | null;\n isDefault?: boolean;\n isEphemeral?: boolean;\n}\n\n/**\n * Fetch org credentials and let the user pick one interactively.\n *\n * @param credentialArg - Credential name or ID to auto-select, or undefined for interactive\n * @returns The selected credential, or null if none found / invalid selection\n */\nexport async function selectCredential(\n apiUrl: string,\n token: string,\n credentialArg?: string\n): Promise<CredentialListItem | null> {\n const credentials = await fetchList<CredentialListItem>(\n apiUrl,\n token,\n '/org/credentials',\n 'items'\n );\n\n if (credentials.length === 0) {\n console.error('No credentials found. Create one first in the web app.');\n return null;\n }\n\n if (credentialArg) {\n const match = credentials.find(\n (c) => c.id === credentialArg || c.name.toLowerCase() === credentialArg.toLowerCase()\n );\n if (!match) {\n console.error(`Credential \"${credentialArg}\" not found.`);\n console.error('Available credentials:');\n for (const c of credentials) {\n const env = c.environmentName ? ` — ${c.environmentName}` : '';\n const baseUrl = c.propertyBaseUrl ? ` — ${c.propertyBaseUrl}` : '';\n console.error(` - ${c.name} [${c.propertyName ?? c.propertyId}${env}${baseUrl}]`);\n }\n return null;\n }\n return match;\n }\n\n // Interactive selection\n console.log('\\nSelect a credential:\\n');\n const labels = credentials.map((c) => {\n const property = c.propertyName ?? c.propertyId;\n const env = c.environmentName ? ` — ${c.environmentName}` : '';\n const baseUrl = c.propertyBaseUrl ? ` — ${c.propertyBaseUrl}` : '';\n return `${c.name} [${property}${env}${baseUrl}]`;\n });\n\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n for (let i = 0; i < labels.length; i++) {\n console.log(` ${i + 1}. ${labels[i]}`);\n }\n rl.question('\\nEnter number: ', (ans) => {\n rl.close();\n resolve(ans.trim());\n });\n });\n\n const idx = parseInt(answer, 10) - 1;\n if (isNaN(idx) || idx < 0 || idx >= credentials.length) {\n console.error('Invalid selection.');\n return null;\n }\n\n return credentials[idx];\n}\n\n/* ── Property selection ──────────────────────────────────────────────── */\n\ninterface PropertyListItem {\n id: string;\n name: string;\n baseUrl: string;\n}\n\nexport async function fetchProperties(apiUrl: string, token: string): Promise<PropertyListItem[]> {\n return fetchList<PropertyListItem>(apiUrl, token, '/org/properties', 'items');\n}\n\n/**\n * Read the application/property selector flag. `--application` is the user-facing\n * name; `--property` is kept as a backwards-compat alias (read second). Internally\n * this is still a \"property\" — the rename is cosmetic.\n */\nexport function getApplicationArg(argv: string[]): string | undefined {\n return getArgValue(argv, '--application') ?? getArgValue(argv, '--property');\n}\n\n/**\n * Read the application/property UUID flag. `--application-id` is the user-facing\n * name; `--property-id` is kept as a backwards-compat alias.\n */\nexport function getApplicationIdArg(argv: string[]): string | undefined {\n return getArgValue(argv, '--application-id') ?? getArgValue(argv, '--property-id');\n}\n\nexport async function selectProperty(\n apiUrl: string,\n token: string,\n hint?: string\n): Promise<PropertyListItem | null> {\n const properties = await fetchProperties(apiUrl, token);\n\n if (properties.length === 0) {\n console.error('No applications found. Create one first in the web app.');\n return null;\n }\n\n if (hint) {\n const match = properties.find(\n (p) => p.id === hint || p.name.toLowerCase() === hint.toLowerCase()\n );\n if (!match) {\n console.error(`Application \"${hint}\" not found.`);\n console.error('Available applications:');\n for (const p of properties) {\n console.error(` - ${p.name} (${p.baseUrl})`);\n }\n return null;\n }\n return match;\n }\n\n if (properties.length === 1) {\n console.log(`Auto-selected application: ${properties[0].name}`);\n return properties[0];\n }\n\n return promptChoice(\n 'Select an application:',\n properties.map((p) => ({ label: `${p.name} — ${p.baseUrl}`, value: p }))\n );\n}\n\n/* ── Interactive prompt helpers ──────────────────────────────────────── */\n\nexport async function promptInput(question: string, defaultValue?: string): Promise<string> {\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;\n const answer = await new Promise<string>((resolve) => {\n rl.question(prompt, (ans) => {\n rl.close();\n resolve(ans.trim());\n });\n });\n return answer || defaultValue || '';\n}\n\nexport async function promptChoice<T>(\n question: string,\n options: Array<{ label: string; value: T }>\n): Promise<T | null> {\n console.log(`\\n${question}\\n`);\n for (let i = 0; i < options.length; i++) {\n console.log(` ${i + 1}. ${options[i].label}`);\n }\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n rl.question('\\nEnter number: ', (ans) => {\n rl.close();\n resolve(ans.trim());\n });\n });\n\n const idx = parseInt(answer, 10) - 1;\n if (isNaN(idx) || idx < 0 || idx >= options.length) {\n console.error('Invalid selection.');\n return null;\n }\n return options[idx].value;\n}\n\nexport async function uploadStorageState(opts: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n storageState: unknown;\n}): Promise<{ ok: boolean; s3Key?: string; error?: string }> {\n const result = await apiFetch(\n `${opts.apiUrl}/org/properties/${opts.propertyId}/credentials/${opts.credentialId}/storage-state/upload`,\n {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${opts.token}`,\n 'Content-Type': 'application/json',\n },\n token: opts.token,\n body: JSON.stringify({ storageState: opts.storageState }),\n }\n );\n\n if (!result.ok) exitOnFailure(result.failure);\n\n return (await result.response.json()) as { ok: boolean; s3Key?: string; error?: string };\n}\n\nexport async function fetchList<T>(\n apiUrl: string,\n token: string,\n path: string,\n listKey: string\n): Promise<T[]> {\n const result = await apiFetch(`${apiUrl}${path}`, {\n headers: { Authorization: `Bearer ${token}` },\n token,\n });\n\n if (!result.ok) exitOnFailure(result.failure);\n\n const json = (await result.response.json()) as Record<string, unknown>;\n\n if (!json.ok) {\n console.error(`Error: ${json.error}`);\n process.exit(1);\n }\n\n return (json[listKey] as T[]) ?? [];\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/remote-test.ts"],"sourcesContent":["/**\n * Remote Test Command\n *\n * Triggers workflow tests on the Canary platform and streams results via SSE.\n * Designed for CI/CD pipelines - exits with code 0 on success, 1 on failure.\n *\n * Usage:\n * canary test-suite run [options]\n *\n * Options:\n * --token <key> API key (or set CANARY_API_TOKEN env var)\n * --api-url <url> API URL (default: https://api.trycanary.ai)\n * --tag <tag> Filter workflows by tag\n * --name-pattern <pat> Filter workflows by name pattern\n * --verbose, -v Show all events (not just results)\n */\n\nimport process from \"node:process\";\nimport { createParser, type EventSourceMessage } from \"eventsource-parser\";\nimport { resolveConfig } from \"./auth\";\nimport { isTriageEnabledForExecution } from \"./triage.js\";\n\ntype WorkflowTestStatus = \"queued\" | \"running\" | \"waiting\" | \"success\" | \"failed\";\n\ntype WorkflowTestEvent = {\n type: \"workflow-test\";\n suiteId: string;\n workflowId: string;\n testRunId: string;\n workflowRunId: string | null;\n status: WorkflowTestStatus;\n startedAt: string | null;\n finishedAt: string | null;\n durationMs: number | null;\n errorMessage?: string | null;\n linkedIssueId?: string | null;\n message?: string;\n resumeAt?: string | null;\n segmentIndex?: number | null;\n totalSegments?: number | null;\n};\n\ntype WorkflowTestSuiteEvent = {\n type: \"workflow-test-suite\";\n suiteId: string;\n status: \"running\" | \"completed\";\n startedAt: string;\n finishedAt: string | null;\n durationMs: number | null;\n totalWorkflows: number;\n completedWorkflows: number;\n failedWorkflows: number;\n successfulWorkflows: number;\n errorMessage?: string | null;\n message?: string;\n};\n\ntype TriggerResponse = {\n ok: boolean;\n jobId?: string;\n suiteId?: string;\n startedAt?: string;\n appUrl?: string;\n error?: string;\n};\n\nfunction getArgValue(argv: string[], key: string): string | undefined {\n const index = argv.indexOf(key);\n if (index === -1 || index >= argv.length - 1) return undefined;\n return argv[index + 1];\n}\n\nfunction hasFlag(argv: string[], ...flags: string[]): boolean {\n return flags.some((flag) => argv.includes(flag));\n}\n\nfunction buildQueryParams(tag?: string, namePattern?: string): string {\n const params = new URLSearchParams();\n if (tag) params.set(\"tag\", tag);\n if (namePattern) params.set(\"namePattern\", namePattern);\n return params.toString();\n}\n\nfunction extractWorkflowName(message: string | undefined, workflowId: string): string {\n if (!message) return workflowId;\n const match = message.match(/^Flow \"(.+?)\" /);\n return match ? match[1] : workflowId;\n}\n\ntype FailedTest = { name: string; testRunId: string };\n\nfunction formatFailedTests(\n failedTests: FailedTest[],\n appUrl: string | undefined,\n): string | null {\n if (failedTests.length === 0 || !appUrl) return null;\n\n const lines = [\"\", \"Failed tests:\"];\n for (const t of failedTests) {\n lines.push(` \\u2717 ${t.name}`);\n lines.push(` ${appUrl}/runs/tests/${t.testRunId}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatSummary(stats: {\n totalWorkflows: number;\n successfulWorkflows: number;\n failedWorkflows: number;\n completedWorkflows: number;\n}): { message: string; exitCode: number } {\n const { totalWorkflows, successfulWorkflows, failedWorkflows, completedWorkflows } = stats;\n\n if (totalWorkflows === 0) {\n return { message: \"No workflows found matching the filter criteria.\", exitCode: 0 };\n }\n\n const passRate = Math.round((successfulWorkflows / totalWorkflows) * 100);\n const waitingWorkflows = totalWorkflows - completedWorkflows;\n\n let message: string;\n let exitCode: number;\n\n if (failedWorkflows > 0) {\n message = `FAILED: ${failedWorkflows} of ${totalWorkflows} workflows failed (${passRate}% pass rate)`;\n exitCode = 1;\n } else {\n message = `PASSED: ${successfulWorkflows} of ${totalWorkflows} workflows passed`;\n exitCode = 0;\n }\n\n if (waitingWorkflows > 0) {\n message += `\\nNote: ${waitingWorkflows} workflow(s) are still waiting (scheduled for later)`;\n }\n\n return { message, exitCode };\n}\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\ntype TestConfigProperty = {\n id: string;\n name: string;\n baseUrl: string;\n environments: Array<{ id: string; name: string; url: string; isDefault: boolean }>;\n};\n\ntype TestConfigResponse = {\n ok: boolean;\n properties: TestConfigProperty[];\n error?: string;\n};\n\ntype ResolvedConfig = {\n propertyId?: string;\n environmentId?: string;\n};\n\nasync function resolveTestConfig(\n apiUrl: string,\n token: string,\n propertyArg?: string,\n environmentArg?: string,\n): Promise<ResolvedConfig> {\n if (!propertyArg && !environmentArg) return {};\n\n const res = await fetch(`${apiUrl}/workflows/test-config`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Failed to fetch test config: ${res.status} ${text}`);\n }\n\n const data = (await res.json()) as TestConfigResponse;\n if (!data.ok || !data.properties) {\n throw new Error(`Failed to fetch test config: ${data.error ?? \"Unknown error\"}`);\n }\n\n const { properties } = data;\n let property: TestConfigProperty | undefined;\n\n if (propertyArg) {\n if (UUID_RE.test(propertyArg)) {\n property = properties.find((p) => p.id === propertyArg);\n } else {\n property = properties.find(\n (p) => p.name.toLowerCase() === propertyArg.toLowerCase()\n );\n }\n if (!property) {\n const available = properties.map((p) => ` - ${p.name} (${p.id})`).join(\"\\n\");\n throw new Error(\n `Application \"${propertyArg}\" not found.\\nAvailable applications:\\n${available}`\n );\n }\n } else if (environmentArg) {\n // --environment without --application: auto-resolve if single application\n if (properties.length === 0) {\n throw new Error(\"No applications found in your organization.\");\n }\n if (properties.length > 1) {\n const available = properties.map((p) => ` - ${p.name} (${p.id})`).join(\"\\n\");\n throw new Error(\n `--environment requires --application when multiple applications exist.\\nAvailable applications:\\n${available}`\n );\n }\n property = properties[0];\n }\n\n const result: ResolvedConfig = {};\n if (property) {\n result.propertyId = property.id;\n\n if (environmentArg) {\n let env: TestConfigProperty[\"environments\"][number] | undefined;\n if (UUID_RE.test(environmentArg)) {\n env = property.environments.find((e) => e.id === environmentArg);\n } else {\n env = property.environments.find(\n (e) => e.name.toLowerCase() === environmentArg.toLowerCase()\n );\n }\n if (!env) {\n const available = property.environments\n .map((e) => ` - ${e.name}${e.isDefault ? \" (default)\" : \"\"} (${e.id})`)\n .join(\"\\n\");\n throw new Error(\n `Environment \"${environmentArg}\" not found for application \"${property.name}\".\\nAvailable environments:\\n${available}`\n );\n }\n result.environmentId = env.id;\n }\n }\n\n return result;\n}\n\n// Export internals for testing\nexport const __internals = {\n getArgValue,\n hasFlag,\n buildQueryParams,\n extractWorkflowName,\n formatSummary,\n formatFailedTests,\n resolveTestConfig,\n UUID_RE,\n};\n\ntype SuiteListItem = { id: string; name: string };\n\n/**\n * Resolve a `--suite <name|id>` argument to a suite id and trigger a layered\n * run via POST /test-suites/:id/run. Returns the execution id (used as the SSE\n * stream key) and the orchestrator job id.\n */\nasync function triggerNamedSuiteRun(\n apiUrl: string,\n token: string,\n suiteArg: string,\n environmentId: string | undefined,\n verbose: boolean\n): Promise<{ executionId: string; jobId: string }> {\n const authHeaders = {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n };\n\n // Resolve name → id (exact id is accepted as-is; otherwise match by name).\n const listRes = await fetch(`${apiUrl}/test-suites`, { headers: authHeaders });\n if (!listRes.ok) {\n console.error(`Failed to list test suites: ${listRes.status}`);\n process.exit(1);\n }\n const listJson = (await listRes.json()) as { ok: boolean; data?: SuiteListItem[] };\n const suites = listJson.data ?? [];\n const match =\n suites.find((s) => s.id === suiteArg) ??\n suites.find((s) => s.name.toLowerCase() === suiteArg.toLowerCase());\n if (!match) {\n console.error(`Suite not found: \"${suiteArg}\"`);\n if (suites.length > 0) {\n console.error(\"Available suites:\");\n for (const s of suites) console.error(` - ${s.name} (${s.id})`);\n }\n process.exit(1);\n }\n\n console.log(`Starting test suite: ${match.name}`);\n if (environmentId) console.log(` Environment: ${environmentId}`);\n console.log(\"\");\n\n const runRes = await fetch(`${apiUrl}/test-suites/${match.id}/run`, {\n method: \"POST\",\n headers: authHeaders,\n body: JSON.stringify(environmentId ? { environmentId } : {}),\n });\n if (!runRes.ok) {\n console.error(`Failed to start suite: ${runRes.status}`);\n console.error(await runRes.text());\n process.exit(1);\n }\n const runJson = (await runRes.json()) as {\n ok: boolean;\n data?: { executionId: string; jobId: string };\n error?: string;\n };\n if (!runJson.ok || !runJson.data) {\n console.error(`Failed to start suite: ${runJson.error ?? \"Unknown error\"}`);\n process.exit(1);\n }\n if (verbose) {\n console.log(`Execution ID: ${runJson.data.executionId}`);\n console.log(`Job ID: ${runJson.data.jobId}`);\n console.log(\"\");\n }\n return runJson.data;\n}\n\nexport async function runRemoteTest(argv: string[]): Promise<void> {\n const { apiUrl, token } = await resolveConfig(argv);\n\n const tag = getArgValue(argv, \"--tag\");\n const namePattern = getArgValue(argv, \"--name-pattern\");\n // \"--application\" is the user-facing flag; \"--property\" stays as a backwards-compat alias.\n const propertyArg = getArgValue(argv, \"--application\") ?? getArgValue(argv, \"--property\");\n const environmentArg = getArgValue(argv, \"--environment\");\n const suiteArg = getArgValue(argv, \"--suite\");\n const verbose = hasFlag(argv, \"--verbose\", \"-v\");\n\n // 0. Resolve property/environment if specified\n let resolvedConfig: ResolvedConfig = {};\n if (propertyArg || environmentArg) {\n try {\n resolvedConfig = await resolveTestConfig(apiUrl, token, propertyArg, environmentArg);\n } catch (err) {\n console.error(`${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n }\n\n console.log(\"Starting remote workflow tests...\");\n if (resolvedConfig.propertyId) console.log(` Application: ${propertyArg}`);\n if (resolvedConfig.environmentId) console.log(` Environment: ${environmentArg}`);\n if (tag) console.log(` Filtering by tag: ${tag}`);\n if (namePattern) console.log(` Filtering by name pattern: ${namePattern}`);\n console.log(\"\");\n\n let suiteId: string;\n let jobId: string | undefined;\n let appUrl: string | undefined;\n\n if (suiteArg) {\n // Named, layered suite run. Resolve name→id, then POST /test-suites/:id/run.\n const triggered = await triggerNamedSuiteRun(\n apiUrl,\n token,\n suiteArg,\n resolvedConfig.environmentId,\n verbose\n );\n suiteId = triggered.executionId;\n jobId = triggered.jobId;\n } else {\n console.log(\"Starting remote workflow tests...\");\n if (resolvedConfig.propertyId) console.log(` Property: ${propertyArg}`);\n if (resolvedConfig.environmentId) console.log(` Environment: ${environmentArg}`);\n if (tag) console.log(` Filtering by tag: ${tag}`);\n if (namePattern) console.log(` Filtering by name pattern: ${namePattern}`);\n console.log(\"\");\n\n // 1. Trigger test run\n const queryParams = new URLSearchParams();\n if (tag) queryParams.set(\"tag\", tag);\n if (namePattern) queryParams.set(\"namePattern\", namePattern);\n\n const triggerUrl = `${apiUrl}/workflows/test-runs${queryParams.toString() ? `?${queryParams}` : \"\"}`;\n\n const body: Record<string, string> = {};\n if (resolvedConfig.propertyId) body.propertyId = resolvedConfig.propertyId;\n if (resolvedConfig.environmentId) body.environmentId = resolvedConfig.environmentId;\n\n let triggerRes: Response;\n try {\n triggerRes = await fetch(triggerUrl, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n } catch (err) {\n console.error(`Failed to connect to API: ${err}`);\n process.exit(1);\n }\n\n if (!triggerRes.ok) {\n const errorText = await triggerRes.text();\n console.error(`Failed to start tests: ${triggerRes.status}`);\n console.error(errorText);\n process.exit(1);\n }\n\n const triggerData = (await triggerRes.json()) as TriggerResponse;\n if (!triggerData.ok || !triggerData.suiteId) {\n console.error(`Failed to start tests: ${triggerData.error ?? \"Unknown error\"}`);\n process.exit(1);\n }\n suiteId = triggerData.suiteId;\n jobId = triggerData.jobId;\n appUrl = triggerData.appUrl;\n }\n\n if (verbose) {\n console.log(`Suite ID: ${suiteId}`);\n console.log(`Job ID: ${jobId}`);\n console.log(\"\");\n }\n\n // 2. Subscribe to SSE stream\n const streamUrl = `${apiUrl}/workflows/test-runs/stream?suiteId=${suiteId}`;\n\n let streamRes: Response;\n try {\n streamRes = await fetch(streamUrl, {\n headers: {\n Authorization: `Bearer ${token}`,\n Accept: \"text/event-stream\",\n },\n });\n } catch (err) {\n console.error(`Failed to connect to event stream: ${err}`);\n process.exit(1);\n }\n\n if (!streamRes.ok || !streamRes.body) {\n console.error(`Failed to connect to event stream: ${streamRes.status}`);\n process.exit(1);\n }\n\n // Track state\n let exitCode = 0;\n let hasCompleted = false;\n const workflowNames = new Map<string, string>();\n const failedTests: FailedTest[] = [];\n let totalWorkflows = 0;\n let completedWorkflows = 0;\n let failedWorkflows = 0;\n let successfulWorkflows = 0;\n\n // 3. Parse SSE events\n const parser = createParser({\n onEvent: (event: EventSourceMessage) => {\n if (!event.data) return;\n\n try {\n const data = JSON.parse(event.data) as\n | WorkflowTestEvent\n | WorkflowTestSuiteEvent\n | { error?: string };\n\n if (verbose) {\n console.log(`[${event.event}] ${JSON.stringify(data)}`);\n }\n\n if (event.event === \"workflow-test\") {\n const testEvent = data as WorkflowTestEvent;\n const { status, workflowId, message, errorMessage } = testEvent;\n const name = workflowNames.get(workflowId) || message?.replace(/^Flow \"(.+)\" .*$/, \"$1\") || workflowId;\n\n if (message?.startsWith('Flow \"')) {\n const match = message.match(/^Flow \"(.+?)\" /);\n if (match) workflowNames.set(workflowId, match[1]);\n }\n\n if (!verbose) {\n if (status === \"success\") {\n console.log(` \\u2713 ${name}`);\n } else if (status === \"failed\") {\n console.log(` \\u2717 ${name}`);\n if (errorMessage) {\n console.log(` Error: ${errorMessage.slice(0, 200)}`);\n }\n failedTests.push({ name, testRunId: testEvent.testRunId });\n exitCode = 1;\n } else if (status === \"running\") {\n // Don't log running status in non-verbose mode\n } else if (status === \"waiting\") {\n console.log(` \\u23F3 ${name} (waiting for scheduled time)`);\n }\n }\n }\n\n if (event.event === \"workflow-test-suite\") {\n const suiteEvent = data as WorkflowTestSuiteEvent;\n totalWorkflows = suiteEvent.totalWorkflows;\n completedWorkflows = suiteEvent.completedWorkflows;\n failedWorkflows = suiteEvent.failedWorkflows;\n successfulWorkflows = suiteEvent.successfulWorkflows;\n\n if (suiteEvent.status === \"completed\") {\n hasCompleted = true;\n }\n }\n\n if (event.event === \"error\") {\n const errorData = data as { error?: string };\n console.error(`Stream error: ${errorData.error ?? \"Unknown error\"}`);\n exitCode = 1;\n }\n } catch {\n // Ignore parse errors for keepalive, etc.\n }\n },\n });\n\n const reader = streamRes.body.getReader();\n const decoder = new TextDecoder();\n\n try {\n while (!hasCompleted) {\n const { done, value } = await reader.read();\n if (done) break;\n parser.feed(decoder.decode(value, { stream: true }));\n }\n } finally {\n reader.releaseLock();\n }\n\n // 4. Print summary\n console.log(\"\");\n console.log(\"─\".repeat(50));\n\n if (totalWorkflows === 0) {\n console.log(\"No workflows found matching the filter criteria.\");\n process.exit(0);\n }\n\n const passRate = totalWorkflows > 0 ? Math.round((successfulWorkflows / totalWorkflows) * 100) : 0;\n\n if (failedWorkflows > 0) {\n console.log(`FAILED: ${failedWorkflows} of ${totalWorkflows} workflows failed (${passRate}% pass rate)`);\n exitCode = 1;\n } else {\n console.log(`PASSED: ${successfulWorkflows} of ${totalWorkflows} workflows passed`);\n }\n\n const waitingWorkflows = totalWorkflows - completedWorkflows;\n if (waitingWorkflows > 0) {\n console.log(`Note: ${waitingWorkflows} workflow(s) are still waiting (scheduled for later)`);\n }\n\n const failedSection = formatFailedTests(failedTests, appUrl);\n if (failedSection) {\n console.log(failedSection);\n }\n\n if (failedWorkflows > 0) {\n const triageEnabled = await isTriageEnabledForExecution(apiUrl, token, suiteId);\n if (triageEnabled) {\n console.log(\"\");\n console.log(`Triage: canary triage wait ${suiteId}`);\n }\n }\n\n process.exit(exitCode);\n}\n"],"mappings":"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","names":[]}
|