@runcofactor/cli 0.10.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-GFGCLVS4.js → api-catalog-WTFQNLK6.js} +5 -4
- package/dist/{api-catalog-GFGCLVS4.js.map → api-catalog-WTFQNLK6.js.map} +1 -1
- package/dist/{attachment-SJC7D7FY.js → attachment-U3NKVPEY.js} +5 -4
- package/dist/{attachment-SJC7D7FY.js.map → attachment-U3NKVPEY.js.map} +1 -1
- package/dist/augmentor-5GMNAX4M.js +198 -0
- package/dist/augmentor-5GMNAX4M.js.map +1 -0
- package/dist/{auth-EN6NQCJY.js → auth-VQG2CDUD.js} +3 -2
- package/dist/{chunk-A4OFTUVV.js → chunk-3X3NW7QA.js} +7 -4
- package/dist/chunk-3X3NW7QA.js.map +1 -0
- package/dist/{chunk-N7HFALX3.js → chunk-46IUJXSD.js} +2 -2
- package/dist/{chunk-IMPZAX6L.js → chunk-5GD47G2D.js} +37 -1
- package/dist/{chunk-IMPZAX6L.js.map → chunk-5GD47G2D.js.map} +1 -1
- package/dist/{chunk-B2VISN2V.js → chunk-7VMO2WOZ.js} +238 -68
- package/dist/chunk-7VMO2WOZ.js.map +1 -0
- package/dist/{chunk-QFDOWABX.js → chunk-CMGI7UZD.js} +6 -3
- package/dist/chunk-CMGI7UZD.js.map +1 -0
- package/dist/{chunk-XQXVG7RA.js → chunk-FNPMWDUQ.js} +3 -3
- package/dist/chunk-G4UYGRZR.js +2 -0
- package/dist/{chunk-I4QLI3JO.js → chunk-HDFYUFBI.js} +2 -2
- package/dist/chunk-JMJVGMXI.js +92 -0
- package/dist/chunk-JMJVGMXI.js.map +1 -0
- package/dist/{chunk-SJJW77WN.js → chunk-JYGNMKZ5.js} +129 -38
- package/dist/chunk-JYGNMKZ5.js.map +1 -0
- package/dist/{chunk-52IO7ACJ.js → chunk-KCHKFYVX.js} +68 -10
- package/dist/{chunk-52IO7ACJ.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-CLAWT7BJ.js → chunk-NHTEKEYE.js} +3 -3
- package/dist/{chunk-WOHL4FTB.js → chunk-PRBRSIZP.js} +16 -10
- package/dist/chunk-PRBRSIZP.js.map +1 -0
- package/dist/{chunk-GKY2KXO5.js → chunk-UETBLPKM.js} +154 -37
- package/dist/chunk-UETBLPKM.js.map +1 -0
- package/dist/{chunk-4PNOV7OV.js → chunk-VGYN2KU2.js} +9284 -1421
- package/dist/chunk-VGYN2KU2.js.map +1 -0
- package/dist/{chunk-Q4BO4Z5V.js → chunk-XJ5YYYGC.js} +4 -4
- package/dist/{credential-COLTBV6D.js → credential-E6KUHRGU.js} +24 -20
- package/dist/credential-E6KUHRGU.js.map +1 -0
- package/dist/{credential-template-EEPYFG7R.js → credential-template-4GPOPBGD.js} +30 -28
- package/dist/credential-template-4GPOPBGD.js.map +1 -0
- package/dist/{debug-workflow-KOVH5GOP.js → debug-workflow-XCLCY6S7.js} +5 -4
- package/dist/{debug-workflow-KOVH5GOP.js.map → debug-workflow-XCLCY6S7.js.map} +1 -1
- package/dist/{docs-3SSORHB5.js → docs-COCZYMW6.js} +95 -10
- package/dist/docs-COCZYMW6.js.map +1 -0
- package/dist/{doctor-OTSIWV6G.js → doctor-ERIVTCQS.js} +9 -5
- package/dist/doctor-ERIVTCQS.js.map +1 -0
- package/dist/environment-7Y4BV6XY.js +221 -0
- package/dist/environment-7Y4BV6XY.js.map +1 -0
- package/dist/{feature-flag-T2LRZME3.js → feature-flag-MHONEX6T.js} +164 -16
- package/dist/feature-flag-MHONEX6T.js.map +1 -0
- package/dist/index.js +123 -58
- package/dist/index.js.map +1 -1
- package/dist/{init-TGWRECT2.js → init-OROOM4HF.js} +5 -4
- package/dist/{init-TGWRECT2.js.map → init-OROOM4HF.js.map} +1 -1
- package/dist/{install-DXSNWZKO.js → install-OJFXHY6U.js} +7 -7
- package/dist/{issues-XIZOPX6T.js → issues-32GONR6C.js} +5 -4
- package/dist/{issues-XIZOPX6T.js.map → issues-32GONR6C.js.map} +1 -1
- package/dist/{knobs-NBINZIUB.js → knobs-UQGGY3CP.js} +7 -5
- package/dist/knobs-UQGGY3CP.js.map +1 -0
- package/dist/{list-3TDHK637.js → list-ZMIKEC5P.js} +5 -4
- package/dist/{list-3TDHK637.js.map → list-ZMIKEC5P.js.map} +1 -1
- package/dist/{local-HICVD6PU.js → local-PUD24GGQ.js} +7 -6
- package/dist/{local-HICVD6PU.js.map → local-PUD24GGQ.js.map} +1 -1
- package/dist/{login-UOIUXVUK.js → login-BSO7YX2D.js} +5 -4
- package/dist/{login-UOIUXVUK.js.map → login-BSO7YX2D.js.map} +1 -1
- package/dist/{mcp-54IJEOUA.js → mcp-4LS7OJUT.js} +24 -25
- package/dist/mcp-4LS7OJUT.js.map +1 -0
- 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-UXLOLPTD.js → property-K5DBL4UE.js} +76 -4
- package/dist/property-K5DBL4UE.js.map +1 -0
- package/dist/{psql-BYUUNLGG.js → psql-PQFUFTSE.js} +3 -2
- package/dist/{psql-BYUUNLGG.js.map → psql-PQFUFTSE.js.map} +1 -1
- package/dist/{record-4TR2UIIS.js → record-EIIYLFJ4.js} +16 -17
- package/dist/record-EIIYLFJ4.js.map +1 -0
- package/dist/{redis-35VBUYW7.js → redis-BU36EZZI.js} +3 -2
- package/dist/redis-BU36EZZI.js.map +1 -0
- package/dist/{release-OOLTUBUT.js → release-LYC2P7DZ.js} +5 -4
- package/dist/{release-OOLTUBUT.js.map → release-LYC2P7DZ.js.map} +1 -1
- package/dist/{sandbox-XGSUU6G7.js → sandbox-CKHXXZHU.js} +55 -10
- package/dist/sandbox-CKHXXZHU.js.map +1 -0
- package/dist/{scenarios-GWLJEGHA.js → scenarios-2XJ2G3KR.js} +5 -4
- package/dist/{scenarios-GWLJEGHA.js.map → scenarios-2XJ2G3KR.js.map} +1 -1
- package/dist/{session-MYFNZPRP.js → session-UTOD5ZYH.js} +77 -10
- package/dist/session-UTOD5ZYH.js.map +1 -0
- package/dist/{skill-KM34LDMO.js → skill-GMAERMQL.js} +220 -70
- package/dist/skill-GMAERMQL.js.map +1 -0
- package/dist/skills/debug-run/SKILL.md +40 -23
- package/dist/skills/debug-run/history/1.2.0.md +262 -0
- package/dist/skills/debug-run/history/1.3.0.md +273 -0
- 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 +233 -0
- package/dist/{spec-RA3CFEKG.js → spec-2NP36U3Y.js} +54 -25
- package/dist/spec-2NP36U3Y.js.map +1 -0
- package/dist/{src-LB4HBTJQ.js → src-4T6GHXVO.js} +19 -11
- package/dist/src-4T6GHXVO.js.map +1 -0
- package/dist/{src-N3TPKGTY.js → src-CG52HEE7.js} +10 -7
- package/dist/{src-UVDX5UP6.js → src-PK5OZXCM.js} +4 -2
- package/dist/src-UEOOC425.js +5941 -0
- package/dist/src-UEOOC425.js.map +1 -0
- package/dist/{start-PSEQSQA3.js → start-3C7EEFW2.js} +5 -4
- package/dist/{start-PSEQSQA3.js.map → start-3C7EEFW2.js.map} +1 -1
- package/dist/{tag-YY6YAABQ.js → tag-JSHOMLBR.js} +6 -5
- package/dist/{task-IQC3YR5K.js → task-YGWVYTBJ.js} +5 -4
- package/dist/{task-IQC3YR5K.js.map → task-YGWVYTBJ.js.map} +1 -1
- package/dist/{test-suite-DZNJFXDW.js → test-suite-LI7ZH367.js} +12 -7
- package/dist/{test-suite-DZNJFXDW.js.map → test-suite-LI7ZH367.js.map} +1 -1
- package/dist/trace-UMLOSIIR.js +16 -0
- package/dist/{triage-ORG45R5W.js → triage-ZWJG4NBJ.js} +6 -5
- package/dist/triage-ZWJG4NBJ.js.map +1 -0
- package/dist/{upgrade-L2VYMP2V.js → upgrade-S7CGEK6H.js} +3 -3
- package/dist/{workflow-XYFH5LTP.js → workflow-T4HSAOGW.js} +316 -241
- package/dist/workflow-T4HSAOGW.js.map +1 -0
- package/dist/{workflow-cache-NQJQFWMV.js → workflow-cache-XVEZ36KF.js} +140 -7
- package/dist/workflow-cache-XVEZ36KF.js.map +1 -0
- package/dist/{workflow-debug-BGD4UIXU.js → workflow-debug-T2BULXZ7.js} +9 -8
- package/dist/{workflow-debug-BGD4UIXU.js.map → workflow-debug-T2BULXZ7.js.map} +1 -1
- package/dist/{workflow-proposals-MTUDX46O.js → workflow-proposals-XXEZICN2.js} +5 -6
- package/dist/workflow-proposals-XXEZICN2.js.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-4PNOV7OV.js.map +0 -1
- package/dist/chunk-A4OFTUVV.js.map +0 -1
- package/dist/chunk-B2VISN2V.js.map +0 -1
- package/dist/chunk-GKY2KXO5.js.map +0 -1
- package/dist/chunk-JICSYFRJ.js +0 -46
- package/dist/chunk-JICSYFRJ.js.map +0 -1
- package/dist/chunk-QFDOWABX.js.map +0 -1
- package/dist/chunk-SJJW77WN.js.map +0 -1
- package/dist/chunk-WOHL4FTB.js.map +0 -1
- package/dist/chunk-ZD3KHESI.js.map +0 -1
- package/dist/credential-COLTBV6D.js.map +0 -1
- package/dist/credential-template-EEPYFG7R.js.map +0 -1
- package/dist/docs-3SSORHB5.js.map +0 -1
- package/dist/doctor-OTSIWV6G.js.map +0 -1
- package/dist/feature-flag-T2LRZME3.js.map +0 -1
- package/dist/knobs-NBINZIUB.js.map +0 -1
- package/dist/mcp-54IJEOUA.js.map +0 -1
- package/dist/property-UXLOLPTD.js.map +0 -1
- package/dist/record-4TR2UIIS.js.map +0 -1
- package/dist/redis-35VBUYW7.js.map +0 -1
- package/dist/sandbox-XGSUU6G7.js.map +0 -1
- package/dist/session-MYFNZPRP.js.map +0 -1
- package/dist/skill-KM34LDMO.js.map +0 -1
- package/dist/spec-RA3CFEKG.js.map +0 -1
- package/dist/src-LB4HBTJQ.js.map +0 -1
- package/dist/trace-HXIW7U2D.js +0 -14
- package/dist/workflow-XYFH5LTP.js.map +0 -1
- package/dist/workflow-cache-NQJQFWMV.js.map +0 -1
- package/dist/workflow-proposals-MTUDX46O.js.map +0 -1
- /package/dist/{auth-EN6NQCJY.js.map → auth-VQG2CDUD.js.map} +0 -0
- /package/dist/{chunk-N7HFALX3.js.map → chunk-46IUJXSD.js.map} +0 -0
- /package/dist/{chunk-XQXVG7RA.js.map → chunk-FNPMWDUQ.js.map} +0 -0
- /package/dist/{pdf-extract-ABWV3L5X.js.map → chunk-G4UYGRZR.js.map} +0 -0
- /package/dist/{chunk-I4QLI3JO.js.map → chunk-HDFYUFBI.js.map} +0 -0
- /package/dist/{chunk-CLAWT7BJ.js.map → chunk-NHTEKEYE.js.map} +0 -0
- /package/dist/{chunk-Q4BO4Z5V.js.map → chunk-XJ5YYYGC.js.map} +0 -0
- /package/dist/{install-DXSNWZKO.js.map → install-OJFXHY6U.js.map} +0 -0
- /package/dist/{src-N3TPKGTY.js.map → pdf-extract-YHE54XU4.js.map} +0 -0
- /package/dist/{src-UVDX5UP6.js.map → src-CG52HEE7.js.map} +0 -0
- /package/dist/{tag-YY6YAABQ.js.map → src-PK5OZXCM.js.map} +0 -0
- /package/dist/{trace-HXIW7U2D.js.map → tag-JSHOMLBR.js.map} +0 -0
- /package/dist/{triage-ORG45R5W.js.map → trace-UMLOSIIR.js.map} +0 -0
- /package/dist/{upgrade-L2VYMP2V.js.map → upgrade-S7CGEK6H.js.map} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getArgValue
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3X3NW7QA.js";
|
|
5
5
|
import {
|
|
6
6
|
formatSemanticSnapshot
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VGYN2KU2.js";
|
|
8
8
|
|
|
9
9
|
// src/trace.ts
|
|
10
10
|
import fs from "fs";
|
|
@@ -55,7 +55,7 @@ async function runTraceSnapshot(argv) {
|
|
|
55
55
|
process.exit(1);
|
|
56
56
|
}
|
|
57
57
|
const filter = filterArg;
|
|
58
|
-
const { reconstructSnapshots, downloadTrace, cleanupTrace } = await import("./src-
|
|
58
|
+
const { reconstructSnapshots, downloadTrace, cleanupTrace } = await import("./src-PK5OZXCM.js");
|
|
59
59
|
let localPath = tracePath;
|
|
60
60
|
let isTemp = false;
|
|
61
61
|
if (tracePath.startsWith("http://") || tracePath.startsWith("https://")) {
|
|
@@ -175,4 +175,4 @@ function slugify(text) {
|
|
|
175
175
|
export {
|
|
176
176
|
runTrace
|
|
177
177
|
};
|
|
178
|
-
//# sourceMappingURL=chunk-
|
|
178
|
+
//# sourceMappingURL=chunk-XJ5YYYGC.js.map
|
|
@@ -3,8 +3,7 @@ import {
|
|
|
3
3
|
apiRequest,
|
|
4
4
|
fetchProperties,
|
|
5
5
|
getApplicationArg
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-SJJW77WN.js";
|
|
6
|
+
} from "./chunk-PRBRSIZP.js";
|
|
8
7
|
import {
|
|
9
8
|
apiFetch,
|
|
10
9
|
exitOnFailure
|
|
@@ -13,8 +12,10 @@ import {
|
|
|
13
12
|
getArgValue,
|
|
14
13
|
hasFlag,
|
|
15
14
|
resolveConfig
|
|
16
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-3X3NW7QA.js";
|
|
16
|
+
import "./chunk-JMJVGMXI.js";
|
|
17
17
|
import "./chunk-JWHYXEA2.js";
|
|
18
|
+
import "./chunk-JYGNMKZ5.js";
|
|
18
19
|
import "./chunk-VKVL7WBN.js";
|
|
19
20
|
|
|
20
21
|
// src/credential.ts
|
|
@@ -48,7 +49,6 @@ function printCredentialHelp() {
|
|
|
48
49
|
"Create options:",
|
|
49
50
|
" --application <name|id> Application to attach to (required; alias: --property)",
|
|
50
51
|
" --name <name> Credential name (required)",
|
|
51
|
-
" --login-url <url> Login URL",
|
|
52
52
|
" --login-instructions <text> Login instructions",
|
|
53
53
|
" --username <user> Username (stored encrypted)",
|
|
54
54
|
" --password <pw> Password (or set CANARY_CRED_PASSWORD)",
|
|
@@ -57,12 +57,15 @@ function printCredentialHelp() {
|
|
|
57
57
|
" --json Output raw JSON",
|
|
58
58
|
"",
|
|
59
59
|
"Update options:",
|
|
60
|
-
" --login-url <url> Set the login URL",
|
|
61
60
|
" --name <name> Set the credential name",
|
|
62
61
|
" --role <role> Set the role (admin, user, viewer, custom)",
|
|
63
62
|
" --login-instructions <text> Set login instructions",
|
|
64
63
|
" --json Output raw JSON",
|
|
65
64
|
"",
|
|
65
|
+
"Note: the login URL is no longer set per credential. Configure the relative",
|
|
66
|
+
"login path on the application (canary application update --login-path /login)",
|
|
67
|
+
"or per environment; it is appended to the environment URL at run time.",
|
|
68
|
+
"",
|
|
66
69
|
"Test options:",
|
|
67
70
|
" --application <name|id> Disambiguate when <credId> is a name (alias: --property)",
|
|
68
71
|
" --json Stream raw SSE events as JSON",
|
|
@@ -100,12 +103,9 @@ Credentials (${items.length}):
|
|
|
100
103
|
const property = c.propertyName ?? c.propertyId;
|
|
101
104
|
const env = c.environmentName ? ` | ${c.environmentName}` : "";
|
|
102
105
|
const baseUrl = c.propertyBaseUrl ? ` | ${c.propertyBaseUrl}` : "";
|
|
103
|
-
const loginUrl = c.loginUrl ? ` Login URL: ${c.loginUrl}
|
|
104
|
-
` : "";
|
|
105
106
|
console.log(` ${c.name}`);
|
|
106
107
|
console.log(` ID: ${c.id}`);
|
|
107
108
|
console.log(` Application: ${property}${env}${baseUrl}`);
|
|
108
|
-
if (loginUrl) process.stdout.write(loginUrl);
|
|
109
109
|
console.log("");
|
|
110
110
|
}
|
|
111
111
|
}
|
|
@@ -113,17 +113,22 @@ async function handleUpdate(argv, apiUrl, token) {
|
|
|
113
113
|
const credId = argv.find((a) => !a.startsWith("-"));
|
|
114
114
|
if (!credId) {
|
|
115
115
|
console.error("Error: Missing credential ID.");
|
|
116
|
-
console.error("Usage: canary credential update <credId> --
|
|
116
|
+
console.error("Usage: canary credential update <credId> [--name <name>] [--role <role>] [--login-instructions <text>]");
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
if (getArgValue(argv, "--login-url") !== void 0) {
|
|
120
|
+
console.error(
|
|
121
|
+
"Error: --login-url has been removed. The login URL now derives from the application:\n canary application update <app> --login-path /login"
|
|
122
|
+
);
|
|
117
123
|
process.exit(1);
|
|
118
124
|
}
|
|
119
|
-
const loginUrl = getArgValue(argv, "--login-url");
|
|
120
125
|
const name = getArgValue(argv, "--name");
|
|
121
126
|
const role = getArgValue(argv, "--role");
|
|
122
127
|
const loginInstructions = getArgValue(argv, "--login-instructions");
|
|
123
128
|
const jsonOutput = hasFlag(argv, "--json");
|
|
124
|
-
if (!
|
|
129
|
+
if (!name && !role && !loginInstructions) {
|
|
125
130
|
console.error(
|
|
126
|
-
"Error: No fields to update. Provide at least one of: --
|
|
131
|
+
"Error: No fields to update. Provide at least one of: --name, --role, --login-instructions"
|
|
127
132
|
);
|
|
128
133
|
process.exit(1);
|
|
129
134
|
}
|
|
@@ -145,7 +150,6 @@ async function handleUpdate(argv, apiUrl, token) {
|
|
|
145
150
|
process.exit(1);
|
|
146
151
|
}
|
|
147
152
|
const body = {};
|
|
148
|
-
if (loginUrl !== void 0) body.loginUrl = loginUrl;
|
|
149
153
|
if (name !== void 0) body.name = name;
|
|
150
154
|
if (role !== void 0) body.role = role;
|
|
151
155
|
if (loginInstructions !== void 0) body.loginInstructions = loginInstructions;
|
|
@@ -169,9 +173,6 @@ async function handleUpdate(argv, apiUrl, token) {
|
|
|
169
173
|
return;
|
|
170
174
|
}
|
|
171
175
|
console.log(`Updated "${credential.name}" (${credId}):`);
|
|
172
|
-
if (loginUrl !== void 0) {
|
|
173
|
-
console.log(` loginUrl: ${credential.loginUrl ?? "(none)"} -> ${loginUrl}`);
|
|
174
|
-
}
|
|
175
176
|
if (name !== void 0) {
|
|
176
177
|
console.log(` name: ${credential.name} -> ${name}`);
|
|
177
178
|
}
|
|
@@ -186,7 +187,12 @@ async function handleCreate(argv, apiUrl, token) {
|
|
|
186
187
|
const jsonOutput = hasFlag(argv, "--json");
|
|
187
188
|
const propertyArg = getApplicationArg(argv);
|
|
188
189
|
const name = getArgValue(argv, "--name");
|
|
189
|
-
|
|
190
|
+
if (getArgValue(argv, "--login-url") !== void 0) {
|
|
191
|
+
console.error(
|
|
192
|
+
"Error: --login-url has been removed. The login URL now derives from the application:\n canary application update <app> --login-path /login"
|
|
193
|
+
);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
190
196
|
const loginInstructions = getArgValue(argv, "--login-instructions");
|
|
191
197
|
const username = getArgValue(argv, "--username");
|
|
192
198
|
const password = getArgValue(argv, "--password") ?? process.env.CANARY_CRED_PASSWORD;
|
|
@@ -215,7 +221,6 @@ async function handleCreate(argv, apiUrl, token) {
|
|
|
215
221
|
if (apiKey !== void 0) data.apiKey = apiKey;
|
|
216
222
|
if (mfaSecret !== void 0) data.mfaSecret = mfaSecret;
|
|
217
223
|
const body = { name, data };
|
|
218
|
-
if (loginUrl !== void 0) body.loginUrl = loginUrl;
|
|
219
224
|
if (loginInstructions !== void 0) body.loginInstructions = loginInstructions;
|
|
220
225
|
const result = await apiRequest(apiUrl, token, "POST", `/org/properties/${property.id}/credentials`, body);
|
|
221
226
|
if (!result.ok) {
|
|
@@ -293,7 +298,6 @@ async function handleGet(argv, apiUrl, token) {
|
|
|
293
298
|
console.log(` Application: ${credSummary.propertyName ?? credSummary.propertyId}`);
|
|
294
299
|
console.log(` Auth provider: ${detail.authProvider ?? "(unknown)"}`);
|
|
295
300
|
console.log(` Login URL: ${detail.loginUrl ?? "(not set)"}`);
|
|
296
|
-
console.log(` Post-login URL: ${detail.postLoginStartUrl ?? "(not set)"}`);
|
|
297
301
|
if (username) console.log(` Username: ${username}`);
|
|
298
302
|
if (data.password) console.log(` Password: ${data.password}`);
|
|
299
303
|
if (data.mfaSecret) console.log(` MFA secret: ${data.mfaSecret}`);
|
|
@@ -447,4 +451,4 @@ async function runCredential(argv) {
|
|
|
447
451
|
export {
|
|
448
452
|
runCredential
|
|
449
453
|
};
|
|
450
|
-
//# sourceMappingURL=credential-
|
|
454
|
+
//# sourceMappingURL=credential-E6KUHRGU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/credential.ts"],"sourcesContent":["/**\n * CLI Credential Commands\n *\n * List, inspect, and update credentials for workflow authoring.\n *\n * @module credential\n */\n\nimport process from 'node:process';\nimport { createParser, type EventSourceMessage } from 'eventsource-parser';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest, fetchProperties, getApplicationArg, type CredentialListItem } from './cli-helpers.js';\nimport { apiFetch, exitOnFailure } from './api-fetch.js';\n\nasync function fetchCredentials(apiUrl: string, token: string): Promise<CredentialListItem[]> {\n const result = await apiFetch(`${apiUrl}/org/credentials`, {\n headers: { Authorization: `Bearer ${token}` },\n token,\n });\n\n if (!result.ok) exitOnFailure(result.failure);\n\n const data = (await result.response.json()) as { ok: boolean; items: CredentialListItem[] };\n return data.items ?? [];\n}\n\nfunction printCredentialHelp(): void {\n console.log(\n [\n 'Usage: canary credential <sub-command> [options]',\n '',\n 'Sub-commands:',\n ' list [options] List credentials with environment info',\n ' get <credId|name> [options] Print credential login bundle (URL + instructions + username/password)',\n ' create [options] Create a new credential',\n ' update <credId> [options] Update credential fields',\n ' test <credId> [options] Run the browser login test for a credential',\n '',\n 'List options:',\n ' --application <name> Filter by application name (alias: --property)',\n ' --json Output raw JSON',\n '',\n 'Create options:',\n ' --application <name|id> Application to attach to (required; alias: --property)',\n ' --name <name> Credential name (required)',\n ' --login-instructions <text> Login instructions',\n ' --username <user> Username (stored encrypted)',\n ' --password <pw> Password (or set CANARY_CRED_PASSWORD)',\n ' --api-key <key> API key (or set CANARY_CRED_API_KEY)',\n ' --mfa-secret <secret> MFA seed (or set CANARY_CRED_MFA_SECRET)',\n ' --json Output raw JSON',\n '',\n 'Update options:',\n ' --name <name> Set the credential name',\n ' --role <role> Set the role (admin, user, viewer, custom)',\n ' --login-instructions <text> Set login instructions',\n ' --json Output raw JSON',\n '',\n 'Note: the login URL is no longer set per credential. Configure the relative',\n 'login path on the application (canary application update --login-path /login)',\n 'or per environment; it is appended to the environment URL at run time.',\n '',\n 'Test options:',\n ' --application <name|id> Disambiguate when <credId> is a name (alias: --property)',\n ' --json Stream raw SSE events as JSON',\n '',\n 'Common options:',\n ' --env <env> Target environment (prod, dev, local)',\n ' --api-url <url> API URL override',\n ' --token <key> API token override',\n ].join('\\n')\n );\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonFlag = hasFlag(argv, '--json');\n const propertyFilter = getApplicationArg(argv);\n\n let items = await fetchCredentials(apiUrl, token);\n\n if (propertyFilter) {\n const lower = propertyFilter.toLowerCase();\n items = items.filter(\n (c) =>\n c.propertyId === propertyFilter ||\n (c.propertyName && c.propertyName.toLowerCase().includes(lower))\n );\n }\n\n // Filter out ephemeral credentials for cleaner output\n items = items.filter((c) => !(c as unknown as { isEphemeral?: boolean }).isEphemeral);\n\n if (jsonFlag) {\n console.log(JSON.stringify(items, null, 2));\n return;\n }\n\n if (items.length === 0) {\n console.log('No credentials found.');\n return;\n }\n\n console.log(`\\nCredentials (${items.length}):\\n`);\n for (const c of items) {\n const property = c.propertyName ?? c.propertyId;\n const env = c.environmentName ? ` | ${c.environmentName}` : '';\n const baseUrl = c.propertyBaseUrl ? ` | ${c.propertyBaseUrl}` : '';\n console.log(` ${c.name}`);\n console.log(` ID: ${c.id}`);\n console.log(` Application: ${property}${env}${baseUrl}`);\n console.log('');\n }\n}\n\nasync function handleUpdate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const credId = argv.find((a) => !a.startsWith('-'));\n if (!credId) {\n console.error('Error: Missing credential ID.');\n console.error('Usage: canary credential update <credId> [--name <name>] [--role <role>] [--login-instructions <text>]');\n process.exit(1);\n }\n\n if (getArgValue(argv, '--login-url') !== undefined) {\n console.error(\n 'Error: --login-url has been removed. The login URL now derives from the application:\\n' +\n ' canary application update <app> --login-path /login'\n );\n process.exit(1);\n }\n\n const name = getArgValue(argv, '--name');\n const role = getArgValue(argv, '--role');\n const loginInstructions = getArgValue(argv, '--login-instructions');\n const jsonOutput = hasFlag(argv, '--json');\n\n if (!name && !role && !loginInstructions) {\n console.error(\n 'Error: No fields to update. Provide at least one of: --name, --role, --login-instructions'\n );\n process.exit(1);\n }\n\n const validRoles = ['admin', 'user', 'viewer', 'custom'];\n if (role && !validRoles.includes(role)) {\n console.error(`Error: Invalid role \"${role}\". Must be one of: ${validRoles.join(', ')}`);\n process.exit(1);\n }\n\n // Auto-resolve propertyId from credential list\n const credentials = await fetchCredentials(apiUrl, token);\n const credential = credentials.find((c) => c.id === credId);\n if (!credential) {\n console.error(`Error: Credential ${credId} not found.`);\n if (credentials.length > 0) {\n console.error('\\nAvailable credentials:');\n for (const c of credentials.slice(0, 10)) {\n console.error(` ${c.id} ${c.name} (${c.propertyName ?? c.propertyId})`);\n }\n }\n process.exit(1);\n }\n\n const body: Record<string, unknown> = {};\n if (name !== undefined) body.name = name;\n if (role !== undefined) body.role = role;\n if (loginInstructions !== undefined) body.loginInstructions = loginInstructions;\n\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'PUT',\n `/org/properties/${credential.propertyId}/credentials/${credId}`,\n body\n );\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: false, error: result.error ?? 'Unknown error' }, null, 2));\n } else {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: true, credentialId: credId, updated: body }, null, 2));\n return;\n }\n\n console.log(`Updated \"${credential.name}\" (${credId}):`);\n if (name !== undefined) {\n console.log(` name: ${credential.name} -> ${name}`);\n }\n if (role !== undefined) {\n console.log(` role: -> ${role}`);\n }\n if (loginInstructions !== undefined) {\n console.log(` loginInstructions: updated`);\n }\n}\n\nasync function handleCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n const propertyArg = getApplicationArg(argv);\n const name = getArgValue(argv, '--name');\n if (getArgValue(argv, '--login-url') !== undefined) {\n console.error(\n 'Error: --login-url has been removed. The login URL now derives from the application:\\n' +\n ' canary application update <app> --login-path /login'\n );\n process.exit(1);\n }\n const loginInstructions = getArgValue(argv, '--login-instructions');\n const username = getArgValue(argv, '--username');\n const password = getArgValue(argv, '--password') ?? process.env.CANARY_CRED_PASSWORD;\n const apiKey = getArgValue(argv, '--api-key') ?? process.env.CANARY_CRED_API_KEY;\n const mfaSecret = getArgValue(argv, '--mfa-secret') ?? process.env.CANARY_CRED_MFA_SECRET;\n\n if (!propertyArg || !name) {\n console.error('Error: --application and --name are required (alias: --property).');\n console.error('Usage: canary credential create --application <name|id> --name <name> [options]');\n process.exit(1);\n }\n\n const properties = await fetchProperties(apiUrl, token);\n const property = properties.find(\n (p) => p.id === propertyArg || p.name.toLowerCase() === propertyArg.toLowerCase()\n );\n if (!property) {\n console.error(`Error: Application \"${propertyArg}\" not found.`);\n if (properties.length > 0) {\n console.error('Available applications:');\n for (const p of properties) console.error(` - ${p.name} (${p.id})`);\n }\n process.exit(1);\n }\n\n const data: Record<string, unknown> = {};\n if (username !== undefined) data.username = username;\n if (password !== undefined) data.password = password;\n if (apiKey !== undefined) data.apiKey = apiKey;\n if (mfaSecret !== undefined) data.mfaSecret = mfaSecret;\n\n const body: Record<string, unknown> = { name, data };\n if (loginInstructions !== undefined) body.loginInstructions = loginInstructions;\n\n const result = await apiRequest<{\n ok: boolean;\n id?: string;\n credential?: { id: string };\n error?: string;\n }>(apiUrl, token, 'POST', `/org/properties/${property.id}/credentials`, body);\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(`Created credential \"${name}\" (${result.id}) on application \"${property.name}\"`);\n}\n\ntype CredentialDetail = {\n id: string;\n name: string;\n authProvider?: string;\n /** Resolved login start URL (environment URL + relative login path) */\n loginUrl?: string | null;\n loginInstructions?: string | null;\n data?: {\n username?: string;\n password?: string;\n email?: string;\n user?: string;\n mfaSecret?: string;\n apiKey?: string;\n customHeaders?: Record<string, string>;\n [key: string]: unknown;\n } | null;\n};\n\nasync function fetchCredentialDetail(\n apiUrl: string,\n token: string,\n propertyId: string,\n credId: string\n): Promise<CredentialDetail | null> {\n const result = await apiRequest<{ ok: boolean; credential?: CredentialDetail; error?: string }>(\n apiUrl,\n token,\n 'GET',\n `/org/properties/${propertyId}/credentials/${credId}`\n );\n if (!result.ok || !result.credential) return null;\n return result.credential;\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n const propertyArg = getApplicationArg(argv);\n const credArg = argv.find((a) => !a.startsWith('-'));\n\n if (!credArg) {\n console.error('Error: Missing credential ID or name.');\n console.error('Usage: canary credential get <credId|name> [--application <name|id>] [--json]');\n process.exit(1);\n }\n\n const credentials = await fetchCredentials(apiUrl, token);\n const candidates = credentials.filter(\n (c) => c.id === credArg || c.name.toLowerCase() === credArg.toLowerCase()\n );\n\n let credSummary: CredentialListItem | undefined;\n if (candidates.length === 0) {\n console.error(`Error: Credential \"${credArg}\" not found.`);\n process.exit(1);\n } else if (candidates.length === 1) {\n credSummary = candidates[0];\n } else {\n if (!propertyArg) {\n console.error(`Error: Multiple credentials match \"${credArg}\". Pass --application to disambiguate.`);\n for (const c of candidates) {\n console.error(` - ${c.id} (${c.propertyName ?? c.propertyId})`);\n }\n process.exit(1);\n }\n const lower = propertyArg.toLowerCase();\n credSummary = candidates.find(\n (c) => c.propertyId === propertyArg || (c.propertyName && c.propertyName.toLowerCase() === lower)\n );\n if (!credSummary) {\n console.error(`Error: No credential named \"${credArg}\" on application \"${propertyArg}\".`);\n process.exit(1);\n }\n }\n\n const detail = await fetchCredentialDetail(apiUrl, token, credSummary.propertyId, credSummary.id);\n if (!detail) {\n console.error(`Error: Failed to load credential ${credSummary.id}.`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(detail, null, 2));\n return;\n }\n\n const data = detail.data ?? {};\n const username = data.username ?? data.email ?? data.user ?? '';\n console.log(`Credential: ${detail.name} (${detail.id})`);\n console.log(` Application: ${credSummary.propertyName ?? credSummary.propertyId}`);\n console.log(` Auth provider: ${detail.authProvider ?? '(unknown)'}`);\n console.log(` Login URL: ${detail.loginUrl ?? '(not set)'}`);\n if (username) console.log(` Username: ${username}`);\n if (data.password) console.log(` Password: ${data.password}`);\n if (data.mfaSecret) console.log(` MFA secret: ${data.mfaSecret}`);\n console.log('');\n console.log(' Login instructions:');\n if (detail.loginInstructions) {\n for (const line of detail.loginInstructions.split('\\n')) {\n console.log(` ${line}`);\n }\n } else {\n console.log(' (none)');\n }\n}\n\nasync function handleTest(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n const propertyArg = getApplicationArg(argv);\n const credArg = argv.find((a) => !a.startsWith('-'));\n\n if (!credArg) {\n console.error('Error: Missing credential ID or name.');\n console.error('Usage: canary credential test <credId> [--application <name|id>]');\n process.exit(1);\n }\n\n const credentials = await fetchCredentials(apiUrl, token);\n const candidates = credentials.filter(\n (c) => c.id === credArg || c.name.toLowerCase() === credArg.toLowerCase()\n );\n let credSummary: CredentialListItem | undefined;\n if (candidates.length === 0) {\n console.error(`Error: Credential \"${credArg}\" not found.`);\n process.exit(1);\n } else if (candidates.length === 1) {\n credSummary = candidates[0];\n } else {\n if (!propertyArg) {\n console.error(`Error: Multiple credentials match \"${credArg}\". Pass --application to disambiguate.`);\n for (const c of candidates) {\n console.error(` - ${c.id} (${c.propertyName ?? c.propertyId})`);\n }\n process.exit(1);\n }\n const lower = propertyArg.toLowerCase();\n credSummary = candidates.find(\n (c) => c.propertyId === propertyArg || (c.propertyName && c.propertyName.toLowerCase() === lower)\n );\n if (!credSummary) {\n console.error(`Error: No credential named \"${credArg}\" on application \"${propertyArg}\".`);\n process.exit(1);\n }\n }\n\n const detail = await fetchCredentialDetail(apiUrl, token, credSummary.propertyId, credSummary.id);\n if (!detail) {\n console.error(`Error: Failed to load credential ${credSummary.id}.`);\n process.exit(1);\n }\n\n if (detail.authProvider === 'api_key') {\n console.error(\n `Error: Credential \"${detail.name}\" uses the api_key auth provider. The browser login test is only valid for browser credentials.`\n );\n process.exit(1);\n }\n\n const startRes = await apiRequest<{ ok: boolean; streamId?: string; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/org/properties/${credSummary.propertyId}/credentials/${credSummary.id}/mcp-test/browser-stream`\n );\n\n if (!startRes.ok || !startRes.streamId) {\n console.error(`Error: ${startRes.error ?? 'Failed to start browser login test'}`);\n process.exit(1);\n }\n\n const { streamId } = startRes;\n if (!jsonOutput) {\n console.log(`Starting browser login test for \"${detail.name}\" (stream ${streamId})...`);\n }\n\n const streamRes = await fetch(`${apiUrl}/browser-stream/${streamId}/stream`, {\n headers: { Authorization: `Bearer ${token}`, Accept: 'text/event-stream' },\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 let exitCode = 0;\n let done = false;\n\n const parser = createParser({\n onEvent: (event: EventSourceMessage) => {\n if (!event.data) return;\n let data: unknown;\n try {\n data = JSON.parse(event.data);\n } catch {\n return;\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify({ event: event.event, data }));\n } else if (event.event === 'browser.action') {\n const action = data as { type?: string; description?: string };\n console.log(` → ${action.type ?? 'action'}${action.description ? `: ${action.description}` : ''}`);\n } else if (event.event === 'browser.status') {\n const status = data as { status?: string; message?: string };\n if (status.status) {\n console.log(`[${status.status}]${status.message ? ` ${status.message}` : ''}`);\n }\n }\n\n if (event.event === 'browser.status') {\n const status = data as { status?: string };\n if (status.status === 'disconnected' || status.status === 'error') {\n done = true;\n if (status.status === 'error') exitCode = 1;\n }\n }\n },\n });\n\n const reader = streamRes.body.getReader();\n const decoder = new TextDecoder();\n while (!done) {\n const { value, done: streamDone } = await reader.read();\n if (streamDone) break;\n parser.feed(decoder.decode(value, { stream: true }));\n }\n\n process.exit(exitCode);\n}\n\nexport async function runCredential(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printCredentialHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(rest);\n\n switch (subCommand) {\n case 'list':\n await handleList(rest, apiUrl, token);\n return;\n case 'get':\n await handleGet(rest, apiUrl, token);\n return;\n case 'create':\n await handleCreate(rest, apiUrl, token);\n return;\n case 'update':\n await handleUpdate(rest, apiUrl, token);\n return;\n case 'test':\n await handleTest(rest, apiUrl, token);\n return;\n default:\n console.error(`Unknown credential sub-command: ${subCommand}`);\n printCredentialHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,15 +3,16 @@ import {
|
|
|
3
3
|
apiRequest,
|
|
4
4
|
fetchProperties,
|
|
5
5
|
getApplicationArg
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-SJJW77WN.js";
|
|
6
|
+
} from "./chunk-PRBRSIZP.js";
|
|
8
7
|
import "./chunk-3CZU7XCS.js";
|
|
9
8
|
import {
|
|
10
9
|
getArgValue,
|
|
11
10
|
hasFlag,
|
|
12
11
|
resolveConfig
|
|
13
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3X3NW7QA.js";
|
|
13
|
+
import "./chunk-JMJVGMXI.js";
|
|
14
14
|
import "./chunk-JWHYXEA2.js";
|
|
15
|
+
import "./chunk-JYGNMKZ5.js";
|
|
15
16
|
import "./chunk-VKVL7WBN.js";
|
|
16
17
|
|
|
17
18
|
// src/credential-template.ts
|
|
@@ -19,16 +20,17 @@ import process from "process";
|
|
|
19
20
|
function printHelp() {
|
|
20
21
|
console.log(
|
|
21
22
|
[
|
|
22
|
-
"Usage: canary
|
|
23
|
+
"Usage: canary persona <sub-command> [options]",
|
|
24
|
+
" (alias: canary credential-template \u2014 kept for backwards compatibility)",
|
|
23
25
|
"",
|
|
24
26
|
"Sub-commands: (--application accepted as --app; --property is a backwards-compat alias)",
|
|
25
|
-
" list --application <name|id> List
|
|
27
|
+
" list --application <name|id> List personas on an application",
|
|
26
28
|
" create --application <name|id> --name <name> [--description <text>]",
|
|
27
|
-
" show --application <name|id> <
|
|
28
|
-
" rename --application <name|id> <
|
|
29
|
-
" delete --application <name|id> <
|
|
30
|
-
" link --application <name|id> <
|
|
31
|
-
" unlink --application <name|id> <
|
|
29
|
+
" show --application <name|id> <personaId> Show persona + its bindings",
|
|
30
|
+
" rename --application <name|id> <personaId> --name <new-name>",
|
|
31
|
+
" delete --application <name|id> <personaId>",
|
|
32
|
+
" link --application <name|id> <personaId> --credential <credId>",
|
|
33
|
+
" unlink --application <name|id> <personaId> --credential <credId>",
|
|
32
34
|
"",
|
|
33
35
|
"Common options:",
|
|
34
36
|
" --json Output raw JSON",
|
|
@@ -89,7 +91,7 @@ async function handleList(argv, apiUrl, token) {
|
|
|
89
91
|
`/org/properties/${property.id}/credential-templates`
|
|
90
92
|
);
|
|
91
93
|
if (!result.ok) {
|
|
92
|
-
console.error(`Error: ${result.error ?? "Failed to list
|
|
94
|
+
console.error(`Error: ${result.error ?? "Failed to list personas"}`);
|
|
93
95
|
process.exit(1);
|
|
94
96
|
}
|
|
95
97
|
const items = result.items ?? [];
|
|
@@ -98,7 +100,7 @@ async function handleList(argv, apiUrl, token) {
|
|
|
98
100
|
return;
|
|
99
101
|
}
|
|
100
102
|
if (items.length === 0) {
|
|
101
|
-
console.log(`No
|
|
103
|
+
console.log(`No personas on application "${property.name}".`);
|
|
102
104
|
return;
|
|
103
105
|
}
|
|
104
106
|
for (const t of items) {
|
|
@@ -123,21 +125,21 @@ async function handleCreate(argv, apiUrl, token) {
|
|
|
123
125
|
{ name, description: description ?? null }
|
|
124
126
|
);
|
|
125
127
|
if (!result.ok || !result.template) {
|
|
126
|
-
console.error(`Error: ${result.error ?? "Failed to create
|
|
128
|
+
console.error(`Error: ${result.error ?? "Failed to create persona"}`);
|
|
127
129
|
process.exit(1);
|
|
128
130
|
}
|
|
129
131
|
if (jsonFlag) {
|
|
130
132
|
console.log(JSON.stringify(result.template, null, 2));
|
|
131
133
|
return;
|
|
132
134
|
}
|
|
133
|
-
console.log(`Created
|
|
135
|
+
console.log(`Created persona "${result.template.name}" (${result.template.id})`);
|
|
134
136
|
}
|
|
135
137
|
async function handleShow(argv, apiUrl, token) {
|
|
136
138
|
const propertyArg = getApplicationArg(argv);
|
|
137
139
|
const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);
|
|
138
140
|
const jsonFlag = hasFlag(argv, "--json");
|
|
139
141
|
if (!propertyArg || !templateId) {
|
|
140
|
-
console.error("Error: --application and <
|
|
142
|
+
console.error("Error: --application and <personaId> are required.");
|
|
141
143
|
process.exit(1);
|
|
142
144
|
}
|
|
143
145
|
const property = await resolveProperty(apiUrl, token, propertyArg);
|
|
@@ -148,7 +150,7 @@ async function handleShow(argv, apiUrl, token) {
|
|
|
148
150
|
`/org/properties/${property.id}/credential-templates/${templateId}`
|
|
149
151
|
);
|
|
150
152
|
if (!result.ok || !result.template) {
|
|
151
|
-
console.error(`Error: ${result.error ?? "Failed to fetch
|
|
153
|
+
console.error(`Error: ${result.error ?? "Failed to fetch persona"}`);
|
|
152
154
|
process.exit(1);
|
|
153
155
|
}
|
|
154
156
|
if (jsonFlag) {
|
|
@@ -170,7 +172,7 @@ async function handleRename(argv, apiUrl, token) {
|
|
|
170
172
|
const newName = getArgValue(argv, "--name");
|
|
171
173
|
const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);
|
|
172
174
|
if (!propertyArg || !templateId || !newName) {
|
|
173
|
-
console.error("Error: --application, <
|
|
175
|
+
console.error("Error: --application, <personaId>, and --name are required.");
|
|
174
176
|
process.exit(1);
|
|
175
177
|
}
|
|
176
178
|
const property = await resolveProperty(apiUrl, token, propertyArg);
|
|
@@ -182,16 +184,16 @@ async function handleRename(argv, apiUrl, token) {
|
|
|
182
184
|
{ name: newName }
|
|
183
185
|
);
|
|
184
186
|
if (!result.ok) {
|
|
185
|
-
console.error(`Error: ${result.error ?? "Failed to rename
|
|
187
|
+
console.error(`Error: ${result.error ?? "Failed to rename persona"}`);
|
|
186
188
|
process.exit(1);
|
|
187
189
|
}
|
|
188
|
-
console.log(`Renamed
|
|
190
|
+
console.log(`Renamed persona ${templateId} \u2192 "${newName}"`);
|
|
189
191
|
}
|
|
190
192
|
async function handleDelete(argv, apiUrl, token) {
|
|
191
193
|
const propertyArg = getApplicationArg(argv);
|
|
192
194
|
const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);
|
|
193
195
|
if (!propertyArg || !templateId) {
|
|
194
|
-
console.error("Error: --application and <
|
|
196
|
+
console.error("Error: --application and <personaId> are required.");
|
|
195
197
|
process.exit(1);
|
|
196
198
|
}
|
|
197
199
|
const property = await resolveProperty(apiUrl, token, propertyArg);
|
|
@@ -202,17 +204,17 @@ async function handleDelete(argv, apiUrl, token) {
|
|
|
202
204
|
`/org/properties/${property.id}/credential-templates/${templateId}`
|
|
203
205
|
);
|
|
204
206
|
if (!result.ok) {
|
|
205
|
-
console.error(`Error: ${result.error ?? "Failed to delete
|
|
207
|
+
console.error(`Error: ${result.error ?? "Failed to delete persona"}`);
|
|
206
208
|
process.exit(1);
|
|
207
209
|
}
|
|
208
|
-
console.log(`Deleted
|
|
210
|
+
console.log(`Deleted persona ${templateId}`);
|
|
209
211
|
}
|
|
210
212
|
async function handleLink(argv, apiUrl, token) {
|
|
211
213
|
const propertyArg = getApplicationArg(argv);
|
|
212
214
|
const credentialId = getArgValue(argv, "--credential");
|
|
213
215
|
const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);
|
|
214
216
|
if (!propertyArg || !templateId || !credentialId) {
|
|
215
|
-
console.error("Error: --application, <
|
|
217
|
+
console.error("Error: --application, <personaId>, and --credential are required.");
|
|
216
218
|
process.exit(1);
|
|
217
219
|
}
|
|
218
220
|
const property = await resolveProperty(apiUrl, token, propertyArg);
|
|
@@ -227,14 +229,14 @@ async function handleLink(argv, apiUrl, token) {
|
|
|
227
229
|
console.error(`Error: ${result.error ?? "Failed to link credential"}`);
|
|
228
230
|
process.exit(1);
|
|
229
231
|
}
|
|
230
|
-
console.log(`Linked credential ${credentialId} to
|
|
232
|
+
console.log(`Linked credential ${credentialId} to persona ${templateId}`);
|
|
231
233
|
}
|
|
232
234
|
async function handleUnlink(argv, apiUrl, token) {
|
|
233
235
|
const propertyArg = getApplicationArg(argv);
|
|
234
236
|
const credentialId = getArgValue(argv, "--credential");
|
|
235
237
|
const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);
|
|
236
238
|
if (!propertyArg || !templateId || !credentialId) {
|
|
237
|
-
console.error("Error: --application, <
|
|
239
|
+
console.error("Error: --application, <personaId>, and --credential are required.");
|
|
238
240
|
process.exit(1);
|
|
239
241
|
}
|
|
240
242
|
const property = await resolveProperty(apiUrl, token, propertyArg);
|
|
@@ -248,7 +250,7 @@ async function handleUnlink(argv, apiUrl, token) {
|
|
|
248
250
|
console.error(`Error: ${result.error ?? "Failed to unlink credential"}`);
|
|
249
251
|
process.exit(1);
|
|
250
252
|
}
|
|
251
|
-
console.log(`Unlinked credential ${credentialId} from
|
|
253
|
+
console.log(`Unlinked credential ${credentialId} from persona ${templateId}`);
|
|
252
254
|
}
|
|
253
255
|
async function runCredentialTemplate(argv) {
|
|
254
256
|
const [subCommand, ...rest] = argv;
|
|
@@ -280,7 +282,7 @@ async function runCredentialTemplate(argv) {
|
|
|
280
282
|
await handleUnlink(rest, apiUrl, token);
|
|
281
283
|
return;
|
|
282
284
|
default:
|
|
283
|
-
console.error(`Unknown
|
|
285
|
+
console.error(`Unknown persona sub-command: ${subCommand}`);
|
|
284
286
|
printHelp();
|
|
285
287
|
process.exit(1);
|
|
286
288
|
}
|
|
@@ -288,4 +290,4 @@ async function runCredentialTemplate(argv) {
|
|
|
288
290
|
export {
|
|
289
291
|
runCredentialTemplate
|
|
290
292
|
};
|
|
291
|
-
//# sourceMappingURL=credential-template-
|
|
293
|
+
//# sourceMappingURL=credential-template-4GPOPBGD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/credential-template.ts"],"sourcesContent":["/**\n * CLI Credential Template Commands\n *\n * Manage property-scoped credential templates (logical credential identities\n * that group per-environment concrete credential bindings).\n *\n * @module credential-template\n */\n\nimport process from 'node:process';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest, fetchProperties, getApplicationArg } from './cli-helpers.js';\n\ntype Template = {\n id: string;\n propertyId: string;\n name: string;\n description: string | null;\n createdAt: string;\n updatedAt: string;\n};\n\ntype Binding = {\n id: string;\n name: string;\n environmentId: string | null;\n isEphemeral: boolean;\n templateId: string | null;\n};\n\nfunction printHelp(): void {\n console.log(\n [\n 'Usage: canary persona <sub-command> [options]',\n ' (alias: canary credential-template — kept for backwards compatibility)',\n '',\n 'Sub-commands: (--application accepted as --app; --property is a backwards-compat alias)',\n ' list --application <name|id> List personas on an application',\n ' create --application <name|id> --name <name> [--description <text>]',\n ' show --application <name|id> <personaId> Show persona + its bindings',\n ' rename --application <name|id> <personaId> --name <new-name>',\n ' delete --application <name|id> <personaId>',\n ' link --application <name|id> <personaId> --credential <credId>',\n ' unlink --application <name|id> <personaId> --credential <credId>',\n '',\n 'Common options:',\n ' --json Output raw JSON',\n ' --env <env> Target environment (prod, dev, local)',\n ' --api-url <url> API URL override',\n ' --token <key> API token override',\n ].join('\\n')\n );\n}\n\n/**\n * Return the first positional argument, excluding values consumed by the given\n * `--flag value` pairs. Prior implementation used `argv.find(a => !a.startsWith('-'))`\n * which incorrectly returned the value of `--property` (the first flag value) as\n * the templateId.\n */\nfunction getPositionalArg(argv: string[], flagsWithValues: string[]): string | undefined {\n const skip = new Set<number>();\n for (let i = 0; i < argv.length; i++) {\n if (flagsWithValues.includes(argv[i]!) && i + 1 < argv.length) {\n skip.add(i);\n skip.add(i + 1);\n }\n }\n for (let i = 0; i < argv.length; i++) {\n if (skip.has(i)) continue;\n const a = argv[i]!;\n if (!a.startsWith('-')) return a;\n }\n return undefined;\n}\n\nconst TEMPLATE_FLAGS = [\n '--application',\n '--property',\n '--credential',\n '--name',\n '--description',\n '--env',\n '--api-url',\n '--token',\n];\n\nasync function resolveProperty(\n apiUrl: string,\n token: string,\n arg: string\n): Promise<{ id: string; name: string }> {\n const properties = await fetchProperties(apiUrl, token);\n const property = properties.find(\n (p) => p.id === arg || p.name.toLowerCase() === arg.toLowerCase()\n );\n if (!property) {\n console.error(`Error: Application \"${arg}\" not found.`);\n process.exit(1);\n }\n return property;\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const propertyArg = getApplicationArg(argv);\n const jsonFlag = hasFlag(argv, '--json');\n if (!propertyArg) {\n console.error('Error: --application is required (alias: --property).');\n process.exit(1);\n }\n const property = await resolveProperty(apiUrl, token, propertyArg);\n const result = await apiRequest<{ ok: boolean; items?: Template[]; error?: string }>(\n apiUrl,\n token,\n 'GET',\n `/org/properties/${property.id}/credential-templates`\n );\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Failed to list personas'}`);\n process.exit(1);\n }\n const items = result.items ?? [];\n if (jsonFlag) {\n console.log(JSON.stringify(items, null, 2));\n return;\n }\n if (items.length === 0) {\n console.log(`No personas on application \"${property.name}\".`);\n return;\n }\n for (const t of items) {\n console.log(`${t.id} ${t.name}${t.description ? ` — ${t.description}` : ''}`);\n }\n}\n\nasync function handleCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const propertyArg = getApplicationArg(argv);\n const name = getArgValue(argv, '--name');\n const description = getArgValue(argv, '--description');\n const jsonFlag = hasFlag(argv, '--json');\n\n if (!propertyArg || !name) {\n console.error('Error: --application and --name are required.');\n process.exit(1);\n }\n const property = await resolveProperty(apiUrl, token, propertyArg);\n const result = await apiRequest<{ ok: boolean; template?: Template; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/org/properties/${property.id}/credential-templates`,\n { name, description: description ?? null }\n );\n if (!result.ok || !result.template) {\n console.error(`Error: ${result.error ?? 'Failed to create persona'}`);\n process.exit(1);\n }\n if (jsonFlag) {\n console.log(JSON.stringify(result.template, null, 2));\n return;\n }\n console.log(`Created persona \"${result.template.name}\" (${result.template.id})`);\n}\n\nasync function handleShow(argv: string[], apiUrl: string, token: string): Promise<void> {\n const propertyArg = getApplicationArg(argv);\n const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);\n const jsonFlag = hasFlag(argv, '--json');\n\n if (!propertyArg || !templateId) {\n console.error('Error: --application and <personaId> are required.');\n process.exit(1);\n }\n const property = await resolveProperty(apiUrl, token, propertyArg);\n const result = await apiRequest<{\n ok: boolean;\n template?: Template;\n bindings?: Binding[];\n error?: string;\n }>(\n apiUrl,\n token,\n 'GET',\n `/org/properties/${property.id}/credential-templates/${templateId}`\n );\n if (!result.ok || !result.template) {\n console.error(`Error: ${result.error ?? 'Failed to fetch persona'}`);\n process.exit(1);\n }\n if (jsonFlag) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n const t = result.template;\n console.log(`${t.name} (${t.id})`);\n if (t.description) console.log(` ${t.description}`);\n console.log(`Bindings (${result.bindings?.length ?? 0}):`);\n for (const b of result.bindings ?? []) {\n const env = b.environmentId ?? '(no env)';\n const eph = b.isEphemeral ? ' [ephemeral]' : '';\n console.log(` ${b.id} env=${env} ${b.name}${eph}`);\n }\n}\n\nasync function handleRename(argv: string[], apiUrl: string, token: string): Promise<void> {\n const propertyArg = getApplicationArg(argv);\n const newName = getArgValue(argv, '--name');\n const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);\n if (!propertyArg || !templateId || !newName) {\n console.error('Error: --application, <personaId>, and --name are required.');\n process.exit(1);\n }\n const property = await resolveProperty(apiUrl, token, propertyArg);\n const result = await apiRequest<{ ok: boolean; template?: Template; error?: string }>(\n apiUrl,\n token,\n 'PATCH',\n `/org/properties/${property.id}/credential-templates/${templateId}`,\n { name: newName }\n );\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Failed to rename persona'}`);\n process.exit(1);\n }\n console.log(`Renamed persona ${templateId} → \"${newName}\"`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const propertyArg = getApplicationArg(argv);\n const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);\n if (!propertyArg || !templateId) {\n console.error('Error: --application and <personaId> are required.');\n process.exit(1);\n }\n const property = await resolveProperty(apiUrl, token, propertyArg);\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'DELETE',\n `/org/properties/${property.id}/credential-templates/${templateId}`\n );\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Failed to delete persona'}`);\n process.exit(1);\n }\n console.log(`Deleted persona ${templateId}`);\n}\n\nasync function handleLink(argv: string[], apiUrl: string, token: string): Promise<void> {\n const propertyArg = getApplicationArg(argv);\n const credentialId = getArgValue(argv, '--credential');\n const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);\n if (!propertyArg || !templateId || !credentialId) {\n console.error('Error: --application, <personaId>, and --credential are required.');\n process.exit(1);\n }\n const property = await resolveProperty(apiUrl, token, propertyArg);\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/org/properties/${property.id}/credential-templates/${templateId}/bindings`,\n { credentialId }\n );\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Failed to link credential'}`);\n process.exit(1);\n }\n console.log(`Linked credential ${credentialId} to persona ${templateId}`);\n}\n\nasync function handleUnlink(argv: string[], apiUrl: string, token: string): Promise<void> {\n const propertyArg = getApplicationArg(argv);\n const credentialId = getArgValue(argv, '--credential');\n const templateId = getPositionalArg(argv, TEMPLATE_FLAGS);\n if (!propertyArg || !templateId || !credentialId) {\n console.error('Error: --application, <personaId>, and --credential are required.');\n process.exit(1);\n }\n const property = await resolveProperty(apiUrl, token, propertyArg);\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'DELETE',\n `/org/properties/${property.id}/credential-templates/${templateId}/bindings/${credentialId}`\n );\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Failed to unlink credential'}`);\n process.exit(1);\n }\n console.log(`Unlinked credential ${credentialId} from persona ${templateId}`);\n}\n\nexport async function runCredentialTemplate(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(rest);\n\n switch (subCommand) {\n case 'list':\n await handleList(rest, apiUrl, token);\n return;\n case 'create':\n await handleCreate(rest, apiUrl, token);\n return;\n case 'show':\n await handleShow(rest, apiUrl, token);\n return;\n case 'rename':\n await handleRename(rest, apiUrl, token);\n return;\n case 'delete':\n await handleDelete(rest, apiUrl, token);\n return;\n case 'link':\n await handleLink(rest, apiUrl, token);\n return;\n case 'unlink':\n await handleUnlink(rest, apiUrl, token);\n return;\n default:\n console.error(`Unknown persona sub-command: ${subCommand}`);\n printHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -7,15 +7,16 @@ import {
|
|
|
7
7
|
} from "./chunk-J6SH7GQT.js";
|
|
8
8
|
import {
|
|
9
9
|
downloadStorageState
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-SJJW77WN.js";
|
|
10
|
+
} from "./chunk-PRBRSIZP.js";
|
|
12
11
|
import "./chunk-3CZU7XCS.js";
|
|
13
12
|
import {
|
|
14
13
|
getArgValue,
|
|
15
14
|
hasFlag,
|
|
16
15
|
resolveConfig
|
|
17
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3X3NW7QA.js";
|
|
17
|
+
import "./chunk-JMJVGMXI.js";
|
|
18
18
|
import "./chunk-JWHYXEA2.js";
|
|
19
|
+
import "./chunk-JYGNMKZ5.js";
|
|
19
20
|
import "./chunk-VKVL7WBN.js";
|
|
20
21
|
|
|
21
22
|
// src/debug-workflow.ts
|
|
@@ -256,4 +257,4 @@ async function runDebugWorkflow(argv) {
|
|
|
256
257
|
export {
|
|
257
258
|
runDebugWorkflow
|
|
258
259
|
};
|
|
259
|
-
//# sourceMappingURL=debug-workflow-
|
|
260
|
+
//# sourceMappingURL=debug-workflow-XCLCY6S7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/debug-workflow.ts"],"sourcesContent":["/**\n * Debug Workflow Command\n *\n * Runs a workflow in a local headed browser for debugging. Replays cached\n * actions where possible and falls back to the agent for uncached steps.\n * The browser stays open after execution so the user can inspect page state.\n *\n * Uses the session daemon for browser lifecycle and cloud relay for\n * server-driven step execution.\n *\n * Usage:\n * canary debug <workflowId> [--to-step N] [--api-url URL] [--env local|dev|prod]\n *\n * @module debug-workflow\n */\n\nimport fs from 'node:fs/promises';\nimport process from 'node:process';\nimport { createParser, type EventSourceMessage } from 'eventsource-parser';\nimport { resolveConfig, getArgValue, hasFlag } from './auth';\nimport { downloadStorageState } from './cli-helpers.js';\nimport {\n createSessionWithRelay,\n deleteSession,\n acquireCloudLock,\n releaseCloudLock,\n} from './session/daemon-client.js';\n\ninterface DebugSessionResponse {\n ok: boolean;\n sessionId?: string;\n workflowName?: string;\n nodes?: Array<{\n index: number;\n id: string;\n name: string;\n type: string;\n }>;\n isAuthenticated?: boolean;\n credential?: { credentialId: string; propertyId: string } | null;\n error?: string;\n}\n\ninterface StepStartedEvent {\n type: 'step-started';\n stepIndex: number;\n totalSteps: number;\n stepName: string;\n nodeType: string;\n nodeId: string;\n}\n\ninterface NodeCompletedEvent {\n type: 'completed';\n stepIndex?: number;\n result: { success: boolean; errorMessage?: string; source?: string };\n}\n\ninterface RunCompleteEvent {\n type: 'run-complete';\n stepsExecuted: number;\n totalSteps: number;\n stoppedEarly: boolean;\n reason?: string;\n}\n\ntype DebugEvent =\n | StepStartedEvent\n | NodeCompletedEvent\n | RunCompleteEvent\n | { type: string; [key: string]: unknown };\n\nexport async function runDebugWorkflow(argv: string[]): Promise<void> {\n const workflowId = argv.find((arg) => !arg.startsWith('-'));\n\n if (!workflowId) {\n console.error('Usage: canary debug <workflowId> [--to-step N] [--env local|dev|prod]');\n process.exit(1);\n }\n\n const toStepStr = getArgValue(argv, '--to-step');\n const toStep = toStepStr ? parseInt(toStepStr, 10) : undefined;\n const verbose = hasFlag(argv, '--verbose', '-v');\n\n if (toStep !== undefined && (isNaN(toStep) || toStep < 1)) {\n console.error('Error: --to-step must be a positive integer');\n process.exit(1);\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n // 1. Create debug session (before browser launch so we can download storage state)\n console.log('Loading workflow...');\n\n let debugSession: DebugSessionResponse;\n try {\n const res = await fetch(`${apiUrl}/cli/debug/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ workflowId }),\n });\n\n if (!res.ok) {\n const text = await res.text();\n console.error(`Failed to create debug session: ${res.status} ${text}`);\n process.exit(1);\n }\n\n debugSession = (await res.json()) as DebugSessionResponse;\n if (!debugSession.ok || !debugSession.sessionId) {\n console.error(`Failed to create debug session: ${debugSession.error}`);\n process.exit(1);\n }\n } catch (err) {\n console.error(`Failed to create debug session: ${err}`);\n process.exit(1);\n }\n\n const debugSessionId: string = debugSession.sessionId!;\n\n // 2. Download storage state if the workflow has valid credentials\n let storageStatePath: string | undefined;\n if (debugSession.isAuthenticated && debugSession.credential) {\n console.log('Downloading storage state...');\n storageStatePath = await downloadStorageState({\n apiUrl,\n token,\n propertyId: debugSession.credential.propertyId,\n credentialId: debugSession.credential.credentialId,\n prefix: 'canary-debug-ss',\n });\n if (storageStatePath) {\n console.log('Storage state loaded.');\n } else {\n console.warn('Could not download storage state, continuing without it.');\n }\n }\n\n // 3. Create a daemon session with cloud relay\n console.log('Launching headed browser...');\n\n let daemonSessionId: string;\n let localBrowserSessionId: string | undefined;\n try {\n const result = await createSessionWithRelay({\n headless: false,\n storageStatePath,\n name: `debug-${workflowId.slice(0, 8)}`,\n cloudRelay: { apiUrl, token },\n });\n\n if (!result.ok || !result.data) {\n console.error(`Failed to create browser session: ${result.error}`);\n process.exit(1);\n }\n\n daemonSessionId = result.data.id;\n localBrowserSessionId = result.data.cloudRelay?.localBrowserSessionId;\n\n if (!localBrowserSessionId) {\n console.error('Cloud relay not established. Cannot run debug workflow.');\n await deleteSession(daemonSessionId);\n process.exit(1);\n }\n } catch (err) {\n console.error(`Failed to start browser: ${err}`);\n process.exit(1);\n }\n\n // 4. Link the debug session to the cloud browser session\n try {\n const res = await fetch(`${apiUrl}/cli/debug/sessions/${debugSessionId}/link`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ localBrowserSessionId }),\n });\n\n if (!res.ok) {\n const text = await res.text();\n console.error(`Failed to link debug session to browser: ${res.status} ${text}`);\n await deleteSession(daemonSessionId);\n process.exit(1);\n }\n } catch (err) {\n console.error(`Failed to link debug session: ${err}`);\n await deleteSession(daemonSessionId);\n process.exit(1);\n }\n\n console.log('Browser connected.');\n console.log();\n\n // Set up cleanup\n const cleanup = async () => {\n console.log('\\nShutting down...');\n\n try {\n await fetch(`${apiUrl}/cli/debug/sessions/${debugSessionId}`, {\n method: 'DELETE',\n headers: { Authorization: `Bearer ${token}` },\n });\n } catch {\n // Ignore cleanup errors\n }\n\n if (storageStatePath) {\n await fs.unlink(storageStatePath).catch(() => {});\n }\n\n await deleteSession(daemonSessionId);\n process.exit(0);\n };\n\n process.on('SIGINT', () => void cleanup());\n process.on('SIGTERM', () => void cleanup());\n\n const nodes = debugSession.nodes ?? [];\n const totalSteps = nodes.length;\n const effectiveToStep = toStep ? Math.min(toStep, totalSteps) : totalSteps;\n\n console.log(`Debugging: \"${debugSession.workflowName}\" (${totalSteps} steps)`);\n if (toStep) {\n console.log(`Running steps 1-${effectiveToStep} of ${totalSteps}`);\n }\n console.log();\n\n // 5. Acquire cloud lock so the server can control the browser\n await acquireCloudLock(daemonSessionId);\n\n // 6. Run steps via SSE\n let runRes: Response;\n try {\n runRes = await fetch(`${apiUrl}/cli/debug/sessions/${debugSessionId}/run`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n Accept: 'text/event-stream',\n },\n body: JSON.stringify({ toStep: effectiveToStep }),\n });\n } catch (err) {\n console.error(`Failed to start execution: ${err}`);\n await cleanup();\n return;\n }\n\n if (!runRes.ok || !runRes.body) {\n console.error(`Failed to start execution: ${runRes.status}`);\n await cleanup();\n return;\n }\n\n // Track execution state\n let currentStep = 0;\n let _hasError = false;\n const stepResults = new Map<number, { name: string; success: boolean; source?: string }>();\n\n const parser = createParser({\n onEvent: (event: EventSourceMessage) => {\n if (!event.data) return;\n\n try {\n const data = JSON.parse(event.data) as DebugEvent;\n\n if (verbose) {\n console.log(`[SSE] ${JSON.stringify(data)}`);\n }\n\n if (data.type === 'step-started') {\n const e = data as StepStartedEvent;\n currentStep = e.stepIndex;\n process.stdout.write(`[${e.stepIndex}/${e.totalSteps}] ${e.stepName} `);\n }\n\n if (data.type === 'completed') {\n const e = data as NodeCompletedEvent;\n const stepIndex = e.stepIndex ?? currentStep;\n const success = e.result.success;\n const source = e.result.source;\n\n if (success) {\n const sourceLabel =\n source === 'cache' ? '(cache)' : source === 'agent' ? '(agent)' : '';\n console.log(`\\u2713 ${sourceLabel}`);\n } else {\n console.log('\\u2717');\n if (e.result.errorMessage) {\n console.log(` Error: ${e.result.errorMessage.slice(0, 200)}`);\n }\n _hasError = true;\n }\n\n stepResults.set(stepIndex, {\n name: `Step ${stepIndex}`,\n success,\n source,\n });\n }\n\n if (data.type === 'run-complete') {\n const e = data as RunCompleteEvent;\n console.log();\n if (e.stoppedEarly) {\n console.log(\n `Stopped at step ${e.stepsExecuted} of ${e.totalSteps}. ${e.reason === 'step-failed' ? 'Step failed.' : 'Error occurred.'}`\n );\n } else {\n console.log(`All ${e.stepsExecuted} step(s) completed.`);\n }\n }\n\n if (data.type === 'run-error') {\n const errorData = data as { error?: string };\n console.log(`\\u2717`);\n if (errorData.error) {\n console.log(` Error: ${String(errorData.error).slice(0, 200)}`);\n }\n _hasError = true;\n }\n } catch {\n // Ignore parse errors\n }\n },\n });\n\n const reader = runRes.body.getReader();\n const decoder = new TextDecoder();\n\n try {\n while (true) {\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 // 7. Release cloud lock — hand control back to CLI for inspection\n await releaseCloudLock(daemonSessionId);\n\n // 8. Keep browser open for inspection\n console.log();\n console.log('Browser is open for inspection.');\n console.log(' Take control: canary session take-control');\n console.log(' Resume cloud: canary session resume-cloud');\n console.log('Press Ctrl+C to close.');\n\n // Keep the process running until Ctrl+C\n await new Promise(() => {});\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/debug-workflow.ts"],"sourcesContent":["/**\n * Debug Workflow Command\n *\n * Runs a workflow in a local headed browser for debugging. Replays cached\n * actions where possible and falls back to the agent for uncached steps.\n * The browser stays open after execution so the user can inspect page state.\n *\n * Uses the session daemon for browser lifecycle and cloud relay for\n * server-driven step execution.\n *\n * Usage:\n * canary debug <workflowId> [--to-step N] [--api-url URL] [--env local|dev|prod]\n *\n * @module debug-workflow\n */\n\nimport fs from 'node:fs/promises';\nimport process from 'node:process';\nimport { createParser, type EventSourceMessage } from 'eventsource-parser';\nimport { resolveConfig, getArgValue, hasFlag } from './auth';\nimport { downloadStorageState } from './cli-helpers.js';\nimport {\n createSessionWithRelay,\n deleteSession,\n acquireCloudLock,\n releaseCloudLock,\n} from './session/daemon-client.js';\n\ninterface DebugSessionResponse {\n ok: boolean;\n sessionId?: string;\n workflowName?: string;\n nodes?: Array<{\n index: number;\n id: string;\n name: string;\n type: string;\n }>;\n isAuthenticated?: boolean;\n credential?: { credentialId: string; propertyId: string } | null;\n error?: string;\n}\n\ninterface StepStartedEvent {\n type: 'step-started';\n stepIndex: number;\n totalSteps: number;\n stepName: string;\n nodeType: string;\n nodeId: string;\n}\n\ninterface NodeCompletedEvent {\n type: 'completed';\n stepIndex?: number;\n result: { success: boolean; errorMessage?: string; source?: string };\n}\n\ninterface RunCompleteEvent {\n type: 'run-complete';\n stepsExecuted: number;\n totalSteps: number;\n stoppedEarly: boolean;\n reason?: string;\n}\n\ntype DebugEvent =\n | StepStartedEvent\n | NodeCompletedEvent\n | RunCompleteEvent\n | { type: string; [key: string]: unknown };\n\nexport async function runDebugWorkflow(argv: string[]): Promise<void> {\n const workflowId = argv.find((arg) => !arg.startsWith('-'));\n\n if (!workflowId) {\n console.error('Usage: canary debug <workflowId> [--to-step N] [--env local|dev|prod]');\n process.exit(1);\n }\n\n const toStepStr = getArgValue(argv, '--to-step');\n const toStep = toStepStr ? parseInt(toStepStr, 10) : undefined;\n const verbose = hasFlag(argv, '--verbose', '-v');\n\n if (toStep !== undefined && (isNaN(toStep) || toStep < 1)) {\n console.error('Error: --to-step must be a positive integer');\n process.exit(1);\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n // 1. Create debug session (before browser launch so we can download storage state)\n console.log('Loading workflow...');\n\n let debugSession: DebugSessionResponse;\n try {\n const res = await fetch(`${apiUrl}/cli/debug/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ workflowId }),\n });\n\n if (!res.ok) {\n const text = await res.text();\n console.error(`Failed to create debug session: ${res.status} ${text}`);\n process.exit(1);\n }\n\n debugSession = (await res.json()) as DebugSessionResponse;\n if (!debugSession.ok || !debugSession.sessionId) {\n console.error(`Failed to create debug session: ${debugSession.error}`);\n process.exit(1);\n }\n } catch (err) {\n console.error(`Failed to create debug session: ${err}`);\n process.exit(1);\n }\n\n const debugSessionId: string = debugSession.sessionId!;\n\n // 2. Download storage state if the workflow has valid credentials\n let storageStatePath: string | undefined;\n if (debugSession.isAuthenticated && debugSession.credential) {\n console.log('Downloading storage state...');\n storageStatePath = await downloadStorageState({\n apiUrl,\n token,\n propertyId: debugSession.credential.propertyId,\n credentialId: debugSession.credential.credentialId,\n prefix: 'canary-debug-ss',\n });\n if (storageStatePath) {\n console.log('Storage state loaded.');\n } else {\n console.warn('Could not download storage state, continuing without it.');\n }\n }\n\n // 3. Create a daemon session with cloud relay\n console.log('Launching headed browser...');\n\n let daemonSessionId: string;\n let localBrowserSessionId: string | undefined;\n try {\n const result = await createSessionWithRelay({\n headless: false,\n storageStatePath,\n name: `debug-${workflowId.slice(0, 8)}`,\n cloudRelay: { apiUrl, token },\n });\n\n if (!result.ok || !result.data) {\n console.error(`Failed to create browser session: ${result.error}`);\n process.exit(1);\n }\n\n daemonSessionId = result.data.id;\n localBrowserSessionId = result.data.cloudRelay?.localBrowserSessionId;\n\n if (!localBrowserSessionId) {\n console.error('Cloud relay not established. Cannot run debug workflow.');\n await deleteSession(daemonSessionId);\n process.exit(1);\n }\n } catch (err) {\n console.error(`Failed to start browser: ${err}`);\n process.exit(1);\n }\n\n // 4. Link the debug session to the cloud browser session\n try {\n const res = await fetch(`${apiUrl}/cli/debug/sessions/${debugSessionId}/link`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ localBrowserSessionId }),\n });\n\n if (!res.ok) {\n const text = await res.text();\n console.error(`Failed to link debug session to browser: ${res.status} ${text}`);\n await deleteSession(daemonSessionId);\n process.exit(1);\n }\n } catch (err) {\n console.error(`Failed to link debug session: ${err}`);\n await deleteSession(daemonSessionId);\n process.exit(1);\n }\n\n console.log('Browser connected.');\n console.log();\n\n // Set up cleanup\n const cleanup = async () => {\n console.log('\\nShutting down...');\n\n try {\n await fetch(`${apiUrl}/cli/debug/sessions/${debugSessionId}`, {\n method: 'DELETE',\n headers: { Authorization: `Bearer ${token}` },\n });\n } catch {\n // Ignore cleanup errors\n }\n\n if (storageStatePath) {\n await fs.unlink(storageStatePath).catch(() => {});\n }\n\n await deleteSession(daemonSessionId);\n process.exit(0);\n };\n\n process.on('SIGINT', () => void cleanup());\n process.on('SIGTERM', () => void cleanup());\n\n const nodes = debugSession.nodes ?? [];\n const totalSteps = nodes.length;\n const effectiveToStep = toStep ? Math.min(toStep, totalSteps) : totalSteps;\n\n console.log(`Debugging: \"${debugSession.workflowName}\" (${totalSteps} steps)`);\n if (toStep) {\n console.log(`Running steps 1-${effectiveToStep} of ${totalSteps}`);\n }\n console.log();\n\n // 5. Acquire cloud lock so the server can control the browser\n await acquireCloudLock(daemonSessionId);\n\n // 6. Run steps via SSE\n let runRes: Response;\n try {\n runRes = await fetch(`${apiUrl}/cli/debug/sessions/${debugSessionId}/run`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n Accept: 'text/event-stream',\n },\n body: JSON.stringify({ toStep: effectiveToStep }),\n });\n } catch (err) {\n console.error(`Failed to start execution: ${err}`);\n await cleanup();\n return;\n }\n\n if (!runRes.ok || !runRes.body) {\n console.error(`Failed to start execution: ${runRes.status}`);\n await cleanup();\n return;\n }\n\n // Track execution state\n let currentStep = 0;\n let _hasError = false;\n const stepResults = new Map<number, { name: string; success: boolean; source?: string }>();\n\n const parser = createParser({\n onEvent: (event: EventSourceMessage) => {\n if (!event.data) return;\n\n try {\n const data = JSON.parse(event.data) as DebugEvent;\n\n if (verbose) {\n console.log(`[SSE] ${JSON.stringify(data)}`);\n }\n\n if (data.type === 'step-started') {\n const e = data as StepStartedEvent;\n currentStep = e.stepIndex;\n process.stdout.write(`[${e.stepIndex}/${e.totalSteps}] ${e.stepName} `);\n }\n\n if (data.type === 'completed') {\n const e = data as NodeCompletedEvent;\n const stepIndex = e.stepIndex ?? currentStep;\n const success = e.result.success;\n const source = e.result.source;\n\n if (success) {\n const sourceLabel =\n source === 'cache' ? '(cache)' : source === 'agent' ? '(agent)' : '';\n console.log(`\\u2713 ${sourceLabel}`);\n } else {\n console.log('\\u2717');\n if (e.result.errorMessage) {\n console.log(` Error: ${e.result.errorMessage.slice(0, 200)}`);\n }\n _hasError = true;\n }\n\n stepResults.set(stepIndex, {\n name: `Step ${stepIndex}`,\n success,\n source,\n });\n }\n\n if (data.type === 'run-complete') {\n const e = data as RunCompleteEvent;\n console.log();\n if (e.stoppedEarly) {\n console.log(\n `Stopped at step ${e.stepsExecuted} of ${e.totalSteps}. ${e.reason === 'step-failed' ? 'Step failed.' : 'Error occurred.'}`\n );\n } else {\n console.log(`All ${e.stepsExecuted} step(s) completed.`);\n }\n }\n\n if (data.type === 'run-error') {\n const errorData = data as { error?: string };\n console.log(`\\u2717`);\n if (errorData.error) {\n console.log(` Error: ${String(errorData.error).slice(0, 200)}`);\n }\n _hasError = true;\n }\n } catch {\n // Ignore parse errors\n }\n },\n });\n\n const reader = runRes.body.getReader();\n const decoder = new TextDecoder();\n\n try {\n while (true) {\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 // 7. Release cloud lock — hand control back to CLI for inspection\n await releaseCloudLock(daemonSessionId);\n\n // 8. Keep browser open for inspection\n console.log();\n console.log('Browser is open for inspection.');\n console.log(' Take control: canary session take-control');\n console.log(' Resume cloud: canary session resume-cloud');\n console.log('Press Ctrl+C to close.');\n\n // Keep the process running until Ctrl+C\n await new Promise(() => {});\n}\n"],"mappings":"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","names":[]}
|