@runcofactor/cli 0.10.0 → 0.13.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.
Files changed (148) hide show
  1. package/dist/{api-catalog-GFGCLVS4.js → api-catalog-7HLEN7C2.js} +5 -4
  2. package/dist/{api-catalog-GFGCLVS4.js.map → api-catalog-7HLEN7C2.js.map} +1 -1
  3. package/dist/{attachment-SJC7D7FY.js → attachment-OVNQD6Z2.js} +5 -4
  4. package/dist/{attachment-SJC7D7FY.js.map → attachment-OVNQD6Z2.js.map} +1 -1
  5. package/dist/{auth-EN6NQCJY.js → auth-VUHL74FH.js} +3 -2
  6. package/dist/{chunk-IMPZAX6L.js → chunk-5GD47G2D.js} +37 -1
  7. package/dist/{chunk-IMPZAX6L.js.map → chunk-5GD47G2D.js.map} +1 -1
  8. package/dist/{chunk-WOHL4FTB.js → chunk-CQE46HSM.js} +5 -5
  9. package/dist/chunk-CQE46HSM.js.map +1 -0
  10. package/dist/{chunk-52IO7ACJ.js → chunk-CRHPDPRS.js} +39 -3
  11. package/dist/{chunk-52IO7ACJ.js.map → chunk-CRHPDPRS.js.map} +1 -1
  12. package/dist/{chunk-XQXVG7RA.js → chunk-EEN2TZUQ.js} +3 -3
  13. package/dist/{chunk-I4QLI3JO.js → chunk-EJ4U242G.js} +2 -2
  14. package/dist/{chunk-CLAWT7BJ.js → chunk-ENDHMYEJ.js} +3 -3
  15. package/dist/chunk-G4UYGRZR.js +2 -0
  16. package/dist/chunk-JZMJUPZP.js +92 -0
  17. package/dist/chunk-JZMJUPZP.js.map +1 -0
  18. package/dist/{chunk-GKY2KXO5.js → chunk-NL7CVG56.js} +105 -35
  19. package/dist/chunk-NL7CVG56.js.map +1 -0
  20. package/dist/{chunk-A4OFTUVV.js → chunk-PZ4LCN6K.js} +7 -4
  21. package/dist/chunk-PZ4LCN6K.js.map +1 -0
  22. package/dist/{chunk-SJJW77WN.js → chunk-QGI4UCJX.js} +69 -5
  23. package/dist/chunk-QGI4UCJX.js.map +1 -0
  24. package/dist/{chunk-4PNOV7OV.js → chunk-QQVWGWPI.js} +1023 -150
  25. package/dist/chunk-QQVWGWPI.js.map +1 -0
  26. package/dist/{chunk-N7HFALX3.js → chunk-VGTKUOYS.js} +2 -2
  27. package/dist/{chunk-B2VISN2V.js → chunk-YN763NWQ.js} +230 -66
  28. package/dist/chunk-YN763NWQ.js.map +1 -0
  29. package/dist/{chunk-QFDOWABX.js → chunk-Z5LUTUDN.js} +6 -3
  30. package/dist/chunk-Z5LUTUDN.js.map +1 -0
  31. package/dist/{chunk-Q4BO4Z5V.js → chunk-ZTOE3ND3.js} +4 -4
  32. package/dist/{credential-COLTBV6D.js → credential-LO2SEEHU.js} +24 -20
  33. package/dist/credential-LO2SEEHU.js.map +1 -0
  34. package/dist/{credential-template-EEPYFG7R.js → credential-template-ZN7W7734.js} +30 -28
  35. package/dist/credential-template-ZN7W7734.js.map +1 -0
  36. package/dist/{debug-workflow-KOVH5GOP.js → debug-workflow-R3RYYAXK.js} +5 -4
  37. package/dist/{debug-workflow-KOVH5GOP.js.map → debug-workflow-R3RYYAXK.js.map} +1 -1
  38. package/dist/{docs-3SSORHB5.js → docs-DIAFBDXQ.js} +5 -4
  39. package/dist/{docs-3SSORHB5.js.map → docs-DIAFBDXQ.js.map} +1 -1
  40. package/dist/{doctor-OTSIWV6G.js → doctor-NZPUSCRE.js} +9 -5
  41. package/dist/doctor-NZPUSCRE.js.map +1 -0
  42. package/dist/environment-RQVU4P5M.js +221 -0
  43. package/dist/environment-RQVU4P5M.js.map +1 -0
  44. package/dist/{feature-flag-T2LRZME3.js → feature-flag-XG26RURR.js} +72 -10
  45. package/dist/feature-flag-XG26RURR.js.map +1 -0
  46. package/dist/index.js +57 -48
  47. package/dist/index.js.map +1 -1
  48. package/dist/{init-TGWRECT2.js → init-EDNLKGPT.js} +5 -4
  49. package/dist/{init-TGWRECT2.js.map → init-EDNLKGPT.js.map} +1 -1
  50. package/dist/{install-DXSNWZKO.js → install-FYZ3HNZK.js} +7 -7
  51. package/dist/{issues-XIZOPX6T.js → issues-NNRVTJ4L.js} +5 -4
  52. package/dist/{issues-XIZOPX6T.js.map → issues-NNRVTJ4L.js.map} +1 -1
  53. package/dist/{knobs-NBINZIUB.js → knobs-A2BOBH22.js} +5 -4
  54. package/dist/{knobs-NBINZIUB.js.map → knobs-A2BOBH22.js.map} +1 -1
  55. package/dist/{list-3TDHK637.js → list-F33VZ4BJ.js} +5 -4
  56. package/dist/{list-3TDHK637.js.map → list-F33VZ4BJ.js.map} +1 -1
  57. package/dist/{local-HICVD6PU.js → local-DQDTM3XA.js} +7 -6
  58. package/dist/{local-HICVD6PU.js.map → local-DQDTM3XA.js.map} +1 -1
  59. package/dist/{login-UOIUXVUK.js → login-BUMVIB36.js} +5 -4
  60. package/dist/{login-UOIUXVUK.js.map → login-BUMVIB36.js.map} +1 -1
  61. package/dist/{mcp-54IJEOUA.js → mcp-B5Y5CDMQ.js} +23 -24
  62. package/dist/mcp-B5Y5CDMQ.js.map +1 -0
  63. package/dist/{property-UXLOLPTD.js → property-NJ4SRXQG.js} +76 -4
  64. package/dist/property-NJ4SRXQG.js.map +1 -0
  65. package/dist/{psql-BYUUNLGG.js → psql-VBZFCMNR.js} +3 -2
  66. package/dist/{psql-BYUUNLGG.js.map → psql-VBZFCMNR.js.map} +1 -1
  67. package/dist/{record-4TR2UIIS.js → record-WAO36O7G.js} +16 -17
  68. package/dist/record-WAO36O7G.js.map +1 -0
  69. package/dist/{redis-35VBUYW7.js → redis-DHZXHL4S.js} +3 -2
  70. package/dist/{redis-35VBUYW7.js.map → redis-DHZXHL4S.js.map} +1 -1
  71. package/dist/{release-OOLTUBUT.js → release-STJKUKTE.js} +5 -4
  72. package/dist/{release-OOLTUBUT.js.map → release-STJKUKTE.js.map} +1 -1
  73. package/dist/{sandbox-XGSUU6G7.js → sandbox-DWSGLY7B.js} +9 -8
  74. package/dist/{sandbox-XGSUU6G7.js.map → sandbox-DWSGLY7B.js.map} +1 -1
  75. package/dist/{scenarios-GWLJEGHA.js → scenarios-HCIDY725.js} +5 -4
  76. package/dist/{scenarios-GWLJEGHA.js.map → scenarios-HCIDY725.js.map} +1 -1
  77. package/dist/{session-MYFNZPRP.js → session-Y5RHU54D.js} +76 -8
  78. package/dist/session-Y5RHU54D.js.map +1 -0
  79. package/dist/{skill-KM34LDMO.js → skill-23WAHUOB.js} +217 -67
  80. package/dist/skill-23WAHUOB.js.map +1 -0
  81. package/dist/skills/debug-run/SKILL.md +33 -22
  82. package/dist/skills/debug-run/history/1.2.0.md +262 -0
  83. package/dist/skills/debug-run/history/1.3.0.md +273 -0
  84. package/dist/skills/debug-run/version.json +1 -1
  85. package/dist/skills/optimize-cache/SKILL.md +206 -0
  86. package/dist/{spec-RA3CFEKG.js → spec-LM5XHOQ5.js} +54 -25
  87. package/dist/spec-LM5XHOQ5.js.map +1 -0
  88. package/dist/{src-LB4HBTJQ.js → src-22RI5VP2.js} +19 -11
  89. package/dist/src-22RI5VP2.js.map +1 -0
  90. package/dist/src-BGDRMOKC.js +5748 -0
  91. package/dist/src-BGDRMOKC.js.map +1 -0
  92. package/dist/{src-N3TPKGTY.js → src-NCJPUAE6.js} +3 -2
  93. package/dist/{src-UVDX5UP6.js → src-Y3K7UJEF.js} +4 -2
  94. package/dist/{start-PSEQSQA3.js → start-SWY55CZX.js} +5 -4
  95. package/dist/{start-PSEQSQA3.js.map → start-SWY55CZX.js.map} +1 -1
  96. package/dist/{tag-YY6YAABQ.js → tag-YSU2XXPI.js} +6 -5
  97. package/dist/{task-IQC3YR5K.js → task-NLBKLD7D.js} +5 -4
  98. package/dist/{task-IQC3YR5K.js.map → task-NLBKLD7D.js.map} +1 -1
  99. package/dist/{test-suite-DZNJFXDW.js → test-suite-QCPWZ2LS.js} +9 -6
  100. package/dist/{test-suite-DZNJFXDW.js.map → test-suite-QCPWZ2LS.js.map} +1 -1
  101. package/dist/{trace-HXIW7U2D.js → trace-A3ZY6K26.js} +6 -4
  102. package/dist/{triage-ORG45R5W.js → triage-TT4BMDBU.js} +6 -5
  103. package/dist/triage-TT4BMDBU.js.map +1 -0
  104. package/dist/{upgrade-L2VYMP2V.js → upgrade-6ZUFETKX.js} +3 -3
  105. package/dist/{workflow-XYFH5LTP.js → workflow-2CX3ZNOQ.js} +241 -237
  106. package/dist/workflow-2CX3ZNOQ.js.map +1 -0
  107. package/dist/{workflow-cache-NQJQFWMV.js → workflow-cache-GXNE6SU2.js} +140 -7
  108. package/dist/workflow-cache-GXNE6SU2.js.map +1 -0
  109. package/dist/{workflow-debug-BGD4UIXU.js → workflow-debug-PRX3DWGD.js} +8 -7
  110. package/dist/{workflow-debug-BGD4UIXU.js.map → workflow-debug-PRX3DWGD.js.map} +1 -1
  111. package/dist/{workflow-proposals-MTUDX46O.js → workflow-proposals-BW327WGL.js} +5 -4
  112. package/dist/{workflow-proposals-MTUDX46O.js.map → workflow-proposals-BW327WGL.js.map} +1 -1
  113. package/package.json +2 -1
  114. package/dist/chunk-4PNOV7OV.js.map +0 -1
  115. package/dist/chunk-A4OFTUVV.js.map +0 -1
  116. package/dist/chunk-B2VISN2V.js.map +0 -1
  117. package/dist/chunk-GKY2KXO5.js.map +0 -1
  118. package/dist/chunk-JICSYFRJ.js +0 -46
  119. package/dist/chunk-JICSYFRJ.js.map +0 -1
  120. package/dist/chunk-QFDOWABX.js.map +0 -1
  121. package/dist/chunk-SJJW77WN.js.map +0 -1
  122. package/dist/chunk-WOHL4FTB.js.map +0 -1
  123. package/dist/credential-COLTBV6D.js.map +0 -1
  124. package/dist/credential-template-EEPYFG7R.js.map +0 -1
  125. package/dist/doctor-OTSIWV6G.js.map +0 -1
  126. package/dist/feature-flag-T2LRZME3.js.map +0 -1
  127. package/dist/mcp-54IJEOUA.js.map +0 -1
  128. package/dist/property-UXLOLPTD.js.map +0 -1
  129. package/dist/record-4TR2UIIS.js.map +0 -1
  130. package/dist/session-MYFNZPRP.js.map +0 -1
  131. package/dist/skill-KM34LDMO.js.map +0 -1
  132. package/dist/spec-RA3CFEKG.js.map +0 -1
  133. package/dist/src-LB4HBTJQ.js.map +0 -1
  134. package/dist/workflow-XYFH5LTP.js.map +0 -1
  135. package/dist/workflow-cache-NQJQFWMV.js.map +0 -1
  136. /package/dist/{auth-EN6NQCJY.js.map → auth-VUHL74FH.js.map} +0 -0
  137. /package/dist/{chunk-XQXVG7RA.js.map → chunk-EEN2TZUQ.js.map} +0 -0
  138. /package/dist/{chunk-I4QLI3JO.js.map → chunk-EJ4U242G.js.map} +0 -0
  139. /package/dist/{chunk-CLAWT7BJ.js.map → chunk-ENDHMYEJ.js.map} +0 -0
  140. /package/dist/{src-N3TPKGTY.js.map → chunk-G4UYGRZR.js.map} +0 -0
  141. /package/dist/{chunk-N7HFALX3.js.map → chunk-VGTKUOYS.js.map} +0 -0
  142. /package/dist/{chunk-Q4BO4Z5V.js.map → chunk-ZTOE3ND3.js.map} +0 -0
  143. /package/dist/{install-DXSNWZKO.js.map → install-FYZ3HNZK.js.map} +0 -0
  144. /package/dist/{src-UVDX5UP6.js.map → src-NCJPUAE6.js.map} +0 -0
  145. /package/dist/{tag-YY6YAABQ.js.map → src-Y3K7UJEF.js.map} +0 -0
  146. /package/dist/{trace-HXIW7U2D.js.map → tag-YSU2XXPI.js.map} +0 -0
  147. /package/dist/{triage-ORG45R5W.js.map → trace-A3ZY6K26.js.map} +0 -0
  148. /package/dist/{upgrade-L2VYMP2V.js.map → upgrade-6ZUFETKX.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/login.ts"],"sourcesContent":["import process from \"node:process\";\nimport readline from \"node:readline\";\nimport { spawn } from \"node:child_process\";\nimport { saveAuth, ENV_URLS, envToProfile, getArgValue } from \"./auth\";\nimport { readBrandEnv } from \"./brand.js\";\n\nexport type StartResponse = {\n ok: boolean;\n deviceCode?: string;\n userCode?: string;\n verificationUrl?: string;\n expiresAt?: string;\n intervalSeconds?: number;\n error?: string;\n};\n\nexport type PollResponse = {\n ok: boolean;\n status?: \"pending\" | \"approved\" | \"rejected\" | \"expired\";\n accessToken?: string;\n orgId?: string;\n error?: string;\n};\n\nexport type OrgsResponse = {\n ok: boolean;\n currentOrgId?: string;\n organizations?: Array<{ id: string; name: string; role: string }>;\n error?: string;\n};\n\nexport type SwitchOrgResponse = {\n ok: boolean;\n accessToken?: string;\n orgId?: string;\n orgName?: string;\n role?: string;\n error?: string;\n};\n\nfunction shouldOpenBrowser(argv: string[]): boolean {\n return !argv.includes(\"--no-open\");\n}\n\nexport function openUrl(url: string) {\n const platform = process.platform;\n if (platform === \"darwin\") {\n spawn(\"open\", [url], { stdio: \"ignore\" });\n return;\n }\n if (platform === \"win32\") {\n spawn(\"cmd\", [\"/c\", \"start\", \"\", url], { stdio: \"ignore\" });\n return;\n }\n spawn(\"xdg-open\", [url], { stdio: \"ignore\" });\n}\n\nfunction promptChoice(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport async function fetchOrgs(apiUrl: string, token: string): Promise<OrgsResponse | null> {\n try {\n const res = await fetch(`${apiUrl}/cli-login/orgs`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n if (!res.ok) return null;\n return (await res.json()) as OrgsResponse;\n } catch {\n return null;\n }\n}\n\nexport async function switchOrg(apiUrl: string, token: string, orgId: string): Promise<SwitchOrgResponse> {\n const res = await fetch(`${apiUrl}/cli-login/switch-org`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ orgId }),\n });\n return (await res.json()) as SwitchOrgResponse;\n}\n\nexport async function runLogin(argv: string[]) {\n const env = getArgValue(argv, \"--env\");\n const envUrls = env ? ENV_URLS[env] : undefined;\n\n if (env && !envUrls) {\n console.error(`Unknown environment: ${env}`);\n console.error(\"Valid environments: prod, dev, local\");\n process.exit(1);\n }\n\n const apiUrl =\n getArgValue(argv, \"--api-url\") ??\n envUrls?.api ??\n readBrandEnv(\"CANARY_API_URL\") ??\n \"https://api.trycanary.ai\";\n const appUrl =\n getArgValue(argv, \"--app-url\") ??\n envUrls?.app ??\n process.env.CANARY_APP_URL ??\n \"https://app.trycanary.ai\";\n\n const orgFlag = getArgValue(argv, \"--org\");\n\n const startRes = await fetch(`${apiUrl}/cli-login/start`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ appUrl }),\n });\n\n const startJson = (await startRes.json()) as StartResponse;\n if (!startRes.ok || !startJson.ok || !startJson.deviceCode || !startJson.userCode) {\n console.error(\"Login start failed\", startJson.error ?? startRes.statusText);\n process.exit(1);\n }\n\n console.log(\"Login required.\");\n console.log(`User code: ${startJson.userCode}`);\n if (startJson.verificationUrl) {\n console.log(`Open: ${startJson.verificationUrl}`);\n if (shouldOpenBrowser(argv)) {\n try {\n openUrl(startJson.verificationUrl);\n } catch {\n console.log(\"Unable to open browser automatically. Please open the URL manually.\");\n }\n }\n }\n\n const intervalMs = (startJson.intervalSeconds ?? 3) * 1000;\n const expiresAt = startJson.expiresAt ? new Date(startJson.expiresAt).getTime() : null;\n\n let token: string | undefined;\n let initialOrgId: string | undefined;\n\n while (true) {\n if (expiresAt && Date.now() > expiresAt) {\n console.error(\"Login code expired.\");\n process.exit(1);\n }\n\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n\n const pollRes = await fetch(`${apiUrl}/cli-login/poll`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ deviceCode: startJson.deviceCode }),\n });\n\n const pollJson = (await pollRes.json()) as PollResponse;\n if (!pollRes.ok || !pollJson.ok) {\n console.error(\"Login poll failed\", pollJson.error ?? pollRes.statusText);\n process.exit(1);\n }\n\n if (pollJson.status === \"approved\" && pollJson.accessToken) {\n token = pollJson.accessToken;\n initialOrgId = pollJson.orgId;\n break;\n }\n\n if (pollJson.status === \"rejected\") {\n console.error(\"Login rejected.\");\n process.exit(1);\n }\n\n if (pollJson.status === \"expired\") {\n console.error(\"Login expired.\");\n process.exit(1);\n }\n }\n\n // Fetch user's organizations (gracefully skip if endpoint not available)\n const orgsData = await fetchOrgs(apiUrl, token);\n const orgs = orgsData?.organizations ?? [];\n\n let finalToken = token;\n let finalOrgId = initialOrgId;\n let finalOrgName: string | undefined;\n\n if (orgs.length <= 1) {\n // Single org (or none) — use as-is\n finalOrgName = orgs[0]?.name;\n } else {\n // Multiple orgs — determine which one to use\n let selectedOrg: (typeof orgs)[number] | undefined;\n\n if (orgFlag) {\n // Match --org flag by name (case-insensitive) or ID\n selectedOrg = orgs.find(\n (o) => o.name.toLowerCase() === orgFlag.toLowerCase() || o.id === orgFlag\n );\n if (!selectedOrg) {\n console.error(`Organization \"${orgFlag}\" not found. Available orgs:`);\n for (const o of orgs) {\n console.error(` - ${o.name} (${o.id})`);\n }\n process.exit(1);\n }\n } else if (process.stdin.isTTY) {\n // Interactive prompt\n console.log(\"\\nYou belong to multiple organizations. Select one:\");\n for (let i = 0; i < orgs.length; i++) {\n const marker = orgs[i].id === initialOrgId ? \" (current)\" : \"\";\n console.log(` ${i + 1}. ${orgs[i].name}${marker}`);\n }\n\n const answer = await promptChoice(`\\nChoice [1-${orgs.length}]: `);\n const idx = parseInt(answer, 10) - 1;\n if (isNaN(idx) || idx < 0 || idx >= orgs.length) {\n console.error(\"Invalid selection.\");\n process.exit(1);\n }\n selectedOrg = orgs[idx];\n } else {\n // Non-interactive — use default from JWT\n const defaultOrg = orgs.find((o) => o.id === initialOrgId);\n console.log(\n `Warning: Multiple organizations available but running non-interactively. Using \"${defaultOrg?.name ?? initialOrgId}\".`\n );\n console.log('Tip: Use --org <name> to select a specific organization.');\n selectedOrg = defaultOrg;\n }\n\n if (selectedOrg && selectedOrg.id !== initialOrgId) {\n // Switch to selected org\n const switchRes = await switchOrg(apiUrl, token, selectedOrg.id);\n if (!switchRes.ok || !switchRes.accessToken) {\n console.error(\"Failed to switch organization:\", switchRes.error ?? \"Unknown error\");\n process.exit(1);\n }\n finalToken = switchRes.accessToken;\n finalOrgId = switchRes.orgId;\n finalOrgName = switchRes.orgName;\n } else if (selectedOrg) {\n finalOrgName = selectedOrg.name;\n }\n }\n\n const profileName = env ? envToProfile(env) : undefined;\n const filePath = await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: finalOrgName }, profileName);\n const displayName = finalOrgName ? ` to ${finalOrgName}` : \"\";\n const profileLabel = profileName ? ` (profile: ${profileName})` : \"\";\n console.log(`Login successful${displayName}${profileLabel}. Token saved to ${filePath}`);\n console.log(\"Set CANARY_API_TOKEN to use the CLI without re-login.\");\n}\n"],"mappings":"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","names":[]}
@@ -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-A4OFTUVV.js";
4
+ } from "./chunk-PZ4LCN6K.js";
5
5
  import {
6
6
  formatSemanticSnapshot
7
- } from "./chunk-4PNOV7OV.js";
7
+ } from "./chunk-QQVWGWPI.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-UVDX5UP6.js");
58
+ const { reconstructSnapshots, downloadTrace, cleanupTrace } = await import("./src-Y3K7UJEF.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-Q4BO4Z5V.js.map
178
+ //# sourceMappingURL=chunk-ZTOE3ND3.js.map
@@ -3,8 +3,7 @@ import {
3
3
  apiRequest,
4
4
  fetchProperties,
5
5
  getApplicationArg
6
- } from "./chunk-WOHL4FTB.js";
7
- import "./chunk-SJJW77WN.js";
6
+ } from "./chunk-CQE46HSM.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-A4OFTUVV.js";
15
+ } from "./chunk-PZ4LCN6K.js";
16
+ import "./chunk-JZMJUPZP.js";
17
17
  import "./chunk-JWHYXEA2.js";
18
+ import "./chunk-QGI4UCJX.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> --login-url <url> [--name <name>] [--role <role>]");
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 (!loginUrl && !name && !role && !loginInstructions) {
129
+ if (!name && !role && !loginInstructions) {
125
130
  console.error(
126
- "Error: No fields to update. Provide at least one of: --login-url, --name, --role, --login-instructions"
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
- const loginUrl = getArgValue(argv, "--login-url");
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-COLTBV6D.js.map
454
+ //# sourceMappingURL=credential-LO2SEEHU.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-WOHL4FTB.js";
7
- import "./chunk-SJJW77WN.js";
6
+ } from "./chunk-CQE46HSM.js";
8
7
  import "./chunk-3CZU7XCS.js";
9
8
  import {
10
9
  getArgValue,
11
10
  hasFlag,
12
11
  resolveConfig
13
- } from "./chunk-A4OFTUVV.js";
12
+ } from "./chunk-PZ4LCN6K.js";
13
+ import "./chunk-JZMJUPZP.js";
14
14
  import "./chunk-JWHYXEA2.js";
15
+ import "./chunk-QGI4UCJX.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 credential-template <sub-command> [options]",
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 templates on an application",
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> <templateId> Show template + its bindings",
28
- " rename --application <name|id> <templateId> --name <new-name>",
29
- " delete --application <name|id> <templateId>",
30
- " link --application <name|id> <templateId> --credential <credId>",
31
- " unlink --application <name|id> <templateId> --credential <credId>",
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 templates"}`);
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 credential templates on application "${property.name}".`);
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 template"}`);
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 template "${result.template.name}" (${result.template.id})`);
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 <templateId> are required.");
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 template"}`);
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, <templateId>, and --name are required.");
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 template"}`);
187
+ console.error(`Error: ${result.error ?? "Failed to rename persona"}`);
186
188
  process.exit(1);
187
189
  }
188
- console.log(`Renamed template ${templateId} \u2192 "${newName}"`);
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 <templateId> are required.");
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 template"}`);
207
+ console.error(`Error: ${result.error ?? "Failed to delete persona"}`);
206
208
  process.exit(1);
207
209
  }
208
- console.log(`Deleted template ${templateId}`);
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, <templateId>, and --credential are required.");
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 template ${templateId}`);
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, <templateId>, and --credential are required.");
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 template ${templateId}`);
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 credential-template sub-command: ${subCommand}`);
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-EEPYFG7R.js.map
293
+ //# sourceMappingURL=credential-template-ZN7W7734.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-WOHL4FTB.js";
11
- import "./chunk-SJJW77WN.js";
10
+ } from "./chunk-CQE46HSM.js";
12
11
  import "./chunk-3CZU7XCS.js";
13
12
  import {
14
13
  getArgValue,
15
14
  hasFlag,
16
15
  resolveConfig
17
- } from "./chunk-A4OFTUVV.js";
16
+ } from "./chunk-PZ4LCN6K.js";
17
+ import "./chunk-JZMJUPZP.js";
18
18
  import "./chunk-JWHYXEA2.js";
19
+ import "./chunk-QGI4UCJX.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-KOVH5GOP.js.map
260
+ //# sourceMappingURL=debug-workflow-R3RYYAXK.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":[]}