@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
@@ -1,14 +1,15 @@
1
1
  import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
2
  import {
3
3
  apiRequest
4
- } from "./chunk-WOHL4FTB.js";
5
- import "./chunk-SJJW77WN.js";
4
+ } from "./chunk-CQE46HSM.js";
6
5
  import "./chunk-3CZU7XCS.js";
7
6
  import {
8
7
  getArgValue,
9
8
  hasFlag
10
- } from "./chunk-A4OFTUVV.js";
9
+ } from "./chunk-PZ4LCN6K.js";
10
+ import "./chunk-JZMJUPZP.js";
11
11
  import "./chunk-JWHYXEA2.js";
12
+ import "./chunk-QGI4UCJX.js";
12
13
  import "./chunk-VKVL7WBN.js";
13
14
 
14
15
  // src/api-catalog.ts
@@ -398,4 +399,4 @@ function exitErr(msg) {
398
399
  export {
399
400
  runApiCatalog
400
401
  };
401
- //# sourceMappingURL=api-catalog-GFGCLVS4.js.map
402
+ //# sourceMappingURL=api-catalog-7HLEN7C2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api-catalog.ts"],"sourcesContent":["/**\n * `canary api-catalog <sources|endpoints> <verb>` — CRUD for API catalog\n * sources (OpenAPI/Postman imports) and endpoints (aka api_requests).\n *\n * Lets a coding agent seed a catalog from scratch, search for endpoints to\n * wire into API sequences, and curate existing entries.\n *\n * @module ApiCatalogCLI\n */\n\nimport fs from 'node:fs/promises';\nimport process from 'node:process';\nimport { getArgValue, hasFlag } from './auth.js';\nimport { apiRequest } from './cli-helpers.js';\n\n/* ── Arg helpers ───────────────────────────────────────────────────────── */\n\nfunction getArg(argv: string[], key: string): string | undefined {\n const prefix = `${key}=`;\n const eq = argv.find((a) => a.startsWith(prefix));\n if (eq) return eq.slice(prefix.length);\n return getArgValue(argv, key);\n}\n\nfunction wantsJson(argv: string[]): boolean {\n if (hasFlag(argv, '--json')) return true;\n if (hasFlag(argv, '--text')) return false;\n return !process.stdout.isTTY;\n}\n\nfunction emit(argv: string[], textFallback: string, json: unknown): void {\n if (wantsJson(argv)) {\n console.log(JSON.stringify(json, null, 2));\n } else {\n console.log(textFallback);\n }\n}\n\nasync function readJsonInput(argv: string[]): Promise<unknown> {\n const fromFile = getArg(argv, '--from-file');\n let raw: string;\n if (fromFile) {\n raw = await fs.readFile(fromFile, 'utf-8');\n } else if (hasFlag(argv, '--from-stdin') || !process.stdin.isTTY) {\n raw = await readStdin();\n } else {\n throw new Error('Provide --from-file <path> or pipe JSON on stdin.');\n }\n try {\n return JSON.parse(raw);\n } catch {\n throw new Error('Invalid JSON input.');\n }\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n process.stdin.on('data', (chunk) => {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);\n });\n process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n process.stdin.on('error', reject);\n });\n}\n\nfunction positional(argv: string[]): string[] {\n return argv.filter((a) => !a.startsWith('-'));\n}\n\n/* ── Types ─────────────────────────────────────────────────────────────── */\n\ninterface GenericResponse<T = unknown> {\n ok: boolean;\n error?: string;\n data?: T;\n pagination?: unknown;\n filters?: unknown;\n meta?: unknown;\n}\n\n/* ── Entry point ───────────────────────────────────────────────────────── */\n\nexport async function runApiCatalog(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n const [group, ...rest] = argv;\n\n if (!group || group === 'help' || hasFlag(argv, '--help', '-h')) {\n printHelp();\n return;\n }\n\n switch (group) {\n case 'sources':\n await runSources(rest, apiUrl, token);\n break;\n case 'endpoints':\n await runEndpoints(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown group: ${group}`);\n printHelp();\n process.exit(1);\n }\n}\n\nfunction printHelp() {\n console.error(\n [\n 'Usage: canary api-catalog <sources|endpoints> <verb> [options]',\n '',\n 'Sources (OpenAPI / Postman imports):',\n ' sources list list catalog sources',\n ' sources get <id> fetch a source',\n ' sources create --from-file <f> create source + run initial import',\n ' sources patch <id> --from-file <f> update source metadata',\n ' sources refresh <id> re-sync a source',\n ' sources delete <id> delete a source',\n '',\n 'Endpoints (individual requests):',\n ' endpoints list [--search <q>] [--application <id>] [--method <m>] [--page <n>]',\n ' list/search endpoints',\n ' endpoints get <id> fetch one endpoint',\n ' endpoints create --from-file <f> create a manual endpoint',\n ' body: { method, url, propertyId, name? }',\n ' endpoints patch <id> --from-file <f> update endpoint fields (name, schemas)',\n ' endpoints delete <id> delete one endpoint',\n ' endpoints delete-many --ids a,b,c delete many endpoints',\n ' endpoints test <id> run the endpoint against its application',\n ' endpoints domains list distinct domains',\n '',\n 'Global options:',\n ' --json force JSON output',\n ' --text force pretty-text output',\n '',\n 'Input for create/patch: JSON via --from-file or stdin. Field shapes match the API route',\n 'schemas (see apps/api/src/api-catalog/*.ts for the authoritative definitions).',\n ].join('\\n'),\n );\n}\n\n/* ── Sources ───────────────────────────────────────────────────────────── */\n\nasync function runSources(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [verb, ...rest] = argv;\n switch (verb) {\n case 'list':\n await sourcesList(rest, apiUrl, token);\n break;\n case 'get':\n await sourcesGet(rest, apiUrl, token);\n break;\n case 'create':\n await sourcesCreate(rest, apiUrl, token);\n break;\n case 'patch':\n await sourcesPatch(rest, apiUrl, token);\n break;\n case 'refresh':\n await sourcesRefresh(rest, apiUrl, token);\n break;\n case 'delete':\n await sourcesDelete(rest, apiUrl, token);\n break;\n default:\n printHelp();\n process.exit(verb ? 1 : 0);\n }\n}\n\nasync function sourcesList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const result = await apiRequest<GenericResponse<unknown[]>>(\n apiUrl,\n token,\n 'GET',\n '/api-catalog-sources',\n );\n if (!result.ok) exitErr(result.error);\n const sources = (result.data ?? []) as Array<Record<string, unknown>>;\n const text =\n sources.length === 0\n ? 'No sources.'\n : sources\n .map((s) => {\n const id = String(s.id ?? '?');\n const name = String(s.name ?? '(unnamed)');\n const format = String(s.format ?? '?');\n const count = s.lastEndpointCount ?? '-';\n const status = String(s.lastSyncStatus ?? '?');\n return `${id} ${name.padEnd(30)} ${format.padEnd(10)} ${count} endpoints (${status})`;\n })\n .join('\\n');\n emit(argv, text, result);\n}\n\nasync function sourcesGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing source ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'GET',\n `/api-catalog-sources/${id}`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, JSON.stringify(result.data, null, 2), result);\n}\n\nasync function sourcesCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n let body: unknown;\n try {\n body = await readJsonInput(argv);\n } catch (err) {\n exitErr(err instanceof Error ? err.message : String(err));\n }\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'POST',\n '/api-catalog-sources',\n body as Record<string, unknown>,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, 'Source created.', result);\n}\n\nasync function sourcesPatch(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing source ID.');\n let body: unknown;\n try {\n body = await readJsonInput(argv);\n } catch (err) {\n exitErr(err instanceof Error ? err.message : String(err));\n }\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/api-catalog-sources/${id}`,\n body as Record<string, unknown>,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Source ${id} patched.`, result);\n}\n\nasync function sourcesRefresh(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing source ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'POST',\n `/api-catalog-sources/${id}/refresh`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Source ${id} refreshed.`, result);\n}\n\nasync function sourcesDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing source ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'DELETE',\n `/api-catalog-sources/${id}`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Source ${id} deleted.`, result);\n}\n\n/* ── Endpoints ─────────────────────────────────────────────────────────── */\n\nasync function runEndpoints(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [verb, ...rest] = argv;\n switch (verb) {\n case 'list':\n await endpointsList(rest, apiUrl, token);\n break;\n case 'get':\n await endpointsGet(rest, apiUrl, token);\n break;\n case 'create':\n await endpointsCreate(rest, apiUrl, token);\n break;\n case 'patch':\n await endpointsPatch(rest, apiUrl, token);\n break;\n case 'delete':\n await endpointsDelete(rest, apiUrl, token);\n break;\n case 'delete-many':\n await endpointsDeleteMany(rest, apiUrl, token);\n break;\n case 'test':\n await endpointsTest(rest, apiUrl, token);\n break;\n case 'domains':\n await endpointsDomains(rest, apiUrl, token);\n break;\n default:\n printHelp();\n process.exit(verb ? 1 : 0);\n }\n}\n\nasync function endpointsList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const params = new URLSearchParams();\n const search = getArg(argv, '--search');\n const propertyId = getArg(argv, '--application') ?? getArg(argv, '--property');\n const method = getArg(argv, '--method');\n const page = getArg(argv, '--page');\n const pageSize = getArg(argv, '--page-size');\n if (search) params.set('search', search);\n if (propertyId) params.set('propertyId', propertyId);\n if (method) params.set('method', method);\n if (page) params.set('page', page);\n if (pageSize) params.set('pageSize', pageSize);\n\n const qs = params.toString();\n const result = await apiRequest<GenericResponse<Array<Record<string, unknown>>>>(\n apiUrl,\n token,\n 'GET',\n `/api-requests${qs ? `?${qs}` : ''}`,\n );\n if (!result.ok) exitErr(result.error);\n\n const items = (result.data ?? []) as Array<Record<string, unknown>>;\n const text =\n items.length === 0\n ? 'No endpoints.'\n : items\n .map((ep) => {\n const id = String(ep.id ?? '?');\n const method = String(ep.method ?? '?').toUpperCase().padEnd(6);\n const url = String(ep.url ?? ep.path ?? '');\n const name = ep.name ? ` — ${String(ep.name)}` : '';\n return `${id} ${method} ${url}${name}`;\n })\n .join('\\n');\n emit(argv, text, result);\n}\n\nasync function endpointsGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing endpoint ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'GET',\n `/api-requests/${id}`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, JSON.stringify(result.data, null, 2), result);\n}\n\nasync function endpointsCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n let body: unknown;\n try {\n body = await readJsonInput(argv);\n } catch (err) {\n exitErr(err instanceof Error ? err.message : String(err));\n }\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'POST',\n '/api-requests',\n body as Record<string, unknown>,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, 'Endpoint created.', result);\n}\n\nasync function endpointsPatch(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing endpoint ID.');\n let body: unknown;\n try {\n body = await readJsonInput(argv);\n } catch (err) {\n exitErr(err instanceof Error ? err.message : String(err));\n }\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/api-requests/${id}`,\n body as Record<string, unknown>,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Endpoint ${id} patched.`, result);\n}\n\nasync function endpointsDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing endpoint ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'DELETE',\n '/api-requests/bulk',\n { ids: [id] },\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Endpoint ${id} deleted.`, result);\n}\n\nasync function endpointsDeleteMany(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n const idsArg = getArg(argv, '--ids');\n if (!idsArg) exitErr('Missing --ids <a,b,c>.');\n const ids = idsArg\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n if (ids.length === 0) exitErr('No IDs provided.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'DELETE',\n '/api-requests/bulk',\n { ids },\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Deleted ${ids.length} endpoint(s).`, result);\n}\n\nasync function endpointsTest(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing endpoint ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'POST',\n `/api-requests/${id}/test`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, JSON.stringify(result.data, null, 2), result);\n}\n\nasync function endpointsDomains(argv: string[], apiUrl: string, token: string): Promise<void> {\n const result = await apiRequest<GenericResponse<unknown>>(\n apiUrl,\n token,\n 'GET',\n '/api-requests/domains',\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, JSON.stringify(result.data, null, 2), result);\n}\n\n/* ── Error helper ──────────────────────────────────────────────────────── */\n\nfunction exitErr(msg: string | undefined): never {\n console.error(`Error: ${msg ?? 'Unknown error'}`);\n process.exit(1);\n}\n"],"mappings":"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","names":["method"]}
1
+ {"version":3,"sources":["../src/api-catalog.ts"],"sourcesContent":["/**\n * `canary api-catalog <sources|endpoints> <verb>` — CRUD for API catalog\n * sources (OpenAPI/Postman imports) and endpoints (aka api_requests).\n *\n * Lets a coding agent seed a catalog from scratch, search for endpoints to\n * wire into API sequences, and curate existing entries.\n *\n * @module ApiCatalogCLI\n */\n\nimport fs from 'node:fs/promises';\nimport process from 'node:process';\nimport { getArgValue, hasFlag } from './auth.js';\nimport { apiRequest } from './cli-helpers.js';\n\n/* ── Arg helpers ───────────────────────────────────────────────────────── */\n\nfunction getArg(argv: string[], key: string): string | undefined {\n const prefix = `${key}=`;\n const eq = argv.find((a) => a.startsWith(prefix));\n if (eq) return eq.slice(prefix.length);\n return getArgValue(argv, key);\n}\n\nfunction wantsJson(argv: string[]): boolean {\n if (hasFlag(argv, '--json')) return true;\n if (hasFlag(argv, '--text')) return false;\n return !process.stdout.isTTY;\n}\n\nfunction emit(argv: string[], textFallback: string, json: unknown): void {\n if (wantsJson(argv)) {\n console.log(JSON.stringify(json, null, 2));\n } else {\n console.log(textFallback);\n }\n}\n\nasync function readJsonInput(argv: string[]): Promise<unknown> {\n const fromFile = getArg(argv, '--from-file');\n let raw: string;\n if (fromFile) {\n raw = await fs.readFile(fromFile, 'utf-8');\n } else if (hasFlag(argv, '--from-stdin') || !process.stdin.isTTY) {\n raw = await readStdin();\n } else {\n throw new Error('Provide --from-file <path> or pipe JSON on stdin.');\n }\n try {\n return JSON.parse(raw);\n } catch {\n throw new Error('Invalid JSON input.');\n }\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n process.stdin.on('data', (chunk) => {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);\n });\n process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n process.stdin.on('error', reject);\n });\n}\n\nfunction positional(argv: string[]): string[] {\n return argv.filter((a) => !a.startsWith('-'));\n}\n\n/* ── Types ─────────────────────────────────────────────────────────────── */\n\ninterface GenericResponse<T = unknown> {\n ok: boolean;\n error?: string;\n data?: T;\n pagination?: unknown;\n filters?: unknown;\n meta?: unknown;\n}\n\n/* ── Entry point ───────────────────────────────────────────────────────── */\n\nexport async function runApiCatalog(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n const [group, ...rest] = argv;\n\n if (!group || group === 'help' || hasFlag(argv, '--help', '-h')) {\n printHelp();\n return;\n }\n\n switch (group) {\n case 'sources':\n await runSources(rest, apiUrl, token);\n break;\n case 'endpoints':\n await runEndpoints(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown group: ${group}`);\n printHelp();\n process.exit(1);\n }\n}\n\nfunction printHelp() {\n console.error(\n [\n 'Usage: canary api-catalog <sources|endpoints> <verb> [options]',\n '',\n 'Sources (OpenAPI / Postman imports):',\n ' sources list list catalog sources',\n ' sources get <id> fetch a source',\n ' sources create --from-file <f> create source + run initial import',\n ' sources patch <id> --from-file <f> update source metadata',\n ' sources refresh <id> re-sync a source',\n ' sources delete <id> delete a source',\n '',\n 'Endpoints (individual requests):',\n ' endpoints list [--search <q>] [--application <id>] [--method <m>] [--page <n>]',\n ' list/search endpoints',\n ' endpoints get <id> fetch one endpoint',\n ' endpoints create --from-file <f> create a manual endpoint',\n ' body: { method, url, propertyId, name? }',\n ' endpoints patch <id> --from-file <f> update endpoint fields (name, schemas)',\n ' endpoints delete <id> delete one endpoint',\n ' endpoints delete-many --ids a,b,c delete many endpoints',\n ' endpoints test <id> run the endpoint against its application',\n ' endpoints domains list distinct domains',\n '',\n 'Global options:',\n ' --json force JSON output',\n ' --text force pretty-text output',\n '',\n 'Input for create/patch: JSON via --from-file or stdin. Field shapes match the API route',\n 'schemas (see apps/api/src/api-catalog/*.ts for the authoritative definitions).',\n ].join('\\n'),\n );\n}\n\n/* ── Sources ───────────────────────────────────────────────────────────── */\n\nasync function runSources(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [verb, ...rest] = argv;\n switch (verb) {\n case 'list':\n await sourcesList(rest, apiUrl, token);\n break;\n case 'get':\n await sourcesGet(rest, apiUrl, token);\n break;\n case 'create':\n await sourcesCreate(rest, apiUrl, token);\n break;\n case 'patch':\n await sourcesPatch(rest, apiUrl, token);\n break;\n case 'refresh':\n await sourcesRefresh(rest, apiUrl, token);\n break;\n case 'delete':\n await sourcesDelete(rest, apiUrl, token);\n break;\n default:\n printHelp();\n process.exit(verb ? 1 : 0);\n }\n}\n\nasync function sourcesList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const result = await apiRequest<GenericResponse<unknown[]>>(\n apiUrl,\n token,\n 'GET',\n '/api-catalog-sources',\n );\n if (!result.ok) exitErr(result.error);\n const sources = (result.data ?? []) as Array<Record<string, unknown>>;\n const text =\n sources.length === 0\n ? 'No sources.'\n : sources\n .map((s) => {\n const id = String(s.id ?? '?');\n const name = String(s.name ?? '(unnamed)');\n const format = String(s.format ?? '?');\n const count = s.lastEndpointCount ?? '-';\n const status = String(s.lastSyncStatus ?? '?');\n return `${id} ${name.padEnd(30)} ${format.padEnd(10)} ${count} endpoints (${status})`;\n })\n .join('\\n');\n emit(argv, text, result);\n}\n\nasync function sourcesGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing source ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'GET',\n `/api-catalog-sources/${id}`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, JSON.stringify(result.data, null, 2), result);\n}\n\nasync function sourcesCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n let body: unknown;\n try {\n body = await readJsonInput(argv);\n } catch (err) {\n exitErr(err instanceof Error ? err.message : String(err));\n }\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'POST',\n '/api-catalog-sources',\n body as Record<string, unknown>,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, 'Source created.', result);\n}\n\nasync function sourcesPatch(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing source ID.');\n let body: unknown;\n try {\n body = await readJsonInput(argv);\n } catch (err) {\n exitErr(err instanceof Error ? err.message : String(err));\n }\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/api-catalog-sources/${id}`,\n body as Record<string, unknown>,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Source ${id} patched.`, result);\n}\n\nasync function sourcesRefresh(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing source ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'POST',\n `/api-catalog-sources/${id}/refresh`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Source ${id} refreshed.`, result);\n}\n\nasync function sourcesDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing source ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'DELETE',\n `/api-catalog-sources/${id}`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Source ${id} deleted.`, result);\n}\n\n/* ── Endpoints ─────────────────────────────────────────────────────────── */\n\nasync function runEndpoints(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [verb, ...rest] = argv;\n switch (verb) {\n case 'list':\n await endpointsList(rest, apiUrl, token);\n break;\n case 'get':\n await endpointsGet(rest, apiUrl, token);\n break;\n case 'create':\n await endpointsCreate(rest, apiUrl, token);\n break;\n case 'patch':\n await endpointsPatch(rest, apiUrl, token);\n break;\n case 'delete':\n await endpointsDelete(rest, apiUrl, token);\n break;\n case 'delete-many':\n await endpointsDeleteMany(rest, apiUrl, token);\n break;\n case 'test':\n await endpointsTest(rest, apiUrl, token);\n break;\n case 'domains':\n await endpointsDomains(rest, apiUrl, token);\n break;\n default:\n printHelp();\n process.exit(verb ? 1 : 0);\n }\n}\n\nasync function endpointsList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const params = new URLSearchParams();\n const search = getArg(argv, '--search');\n const propertyId = getArg(argv, '--application') ?? getArg(argv, '--property');\n const method = getArg(argv, '--method');\n const page = getArg(argv, '--page');\n const pageSize = getArg(argv, '--page-size');\n if (search) params.set('search', search);\n if (propertyId) params.set('propertyId', propertyId);\n if (method) params.set('method', method);\n if (page) params.set('page', page);\n if (pageSize) params.set('pageSize', pageSize);\n\n const qs = params.toString();\n const result = await apiRequest<GenericResponse<Array<Record<string, unknown>>>>(\n apiUrl,\n token,\n 'GET',\n `/api-requests${qs ? `?${qs}` : ''}`,\n );\n if (!result.ok) exitErr(result.error);\n\n const items = (result.data ?? []) as Array<Record<string, unknown>>;\n const text =\n items.length === 0\n ? 'No endpoints.'\n : items\n .map((ep) => {\n const id = String(ep.id ?? '?');\n const method = String(ep.method ?? '?').toUpperCase().padEnd(6);\n const url = String(ep.url ?? ep.path ?? '');\n const name = ep.name ? ` — ${String(ep.name)}` : '';\n return `${id} ${method} ${url}${name}`;\n })\n .join('\\n');\n emit(argv, text, result);\n}\n\nasync function endpointsGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing endpoint ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'GET',\n `/api-requests/${id}`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, JSON.stringify(result.data, null, 2), result);\n}\n\nasync function endpointsCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n let body: unknown;\n try {\n body = await readJsonInput(argv);\n } catch (err) {\n exitErr(err instanceof Error ? err.message : String(err));\n }\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'POST',\n '/api-requests',\n body as Record<string, unknown>,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, 'Endpoint created.', result);\n}\n\nasync function endpointsPatch(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing endpoint ID.');\n let body: unknown;\n try {\n body = await readJsonInput(argv);\n } catch (err) {\n exitErr(err instanceof Error ? err.message : String(err));\n }\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/api-requests/${id}`,\n body as Record<string, unknown>,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Endpoint ${id} patched.`, result);\n}\n\nasync function endpointsDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing endpoint ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'DELETE',\n '/api-requests/bulk',\n { ids: [id] },\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Endpoint ${id} deleted.`, result);\n}\n\nasync function endpointsDeleteMany(\n argv: string[],\n apiUrl: string,\n token: string,\n): Promise<void> {\n const idsArg = getArg(argv, '--ids');\n if (!idsArg) exitErr('Missing --ids <a,b,c>.');\n const ids = idsArg\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n if (ids.length === 0) exitErr('No IDs provided.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'DELETE',\n '/api-requests/bulk',\n { ids },\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, `Deleted ${ids.length} endpoint(s).`, result);\n}\n\nasync function endpointsTest(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = positional(argv);\n if (!id) exitErr('Missing endpoint ID.');\n const result = await apiRequest<GenericResponse>(\n apiUrl,\n token,\n 'POST',\n `/api-requests/${id}/test`,\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, JSON.stringify(result.data, null, 2), result);\n}\n\nasync function endpointsDomains(argv: string[], apiUrl: string, token: string): Promise<void> {\n const result = await apiRequest<GenericResponse<unknown>>(\n apiUrl,\n token,\n 'GET',\n '/api-requests/domains',\n );\n if (!result.ok) exitErr(result.error);\n emit(argv, JSON.stringify(result.data, null, 2), result);\n}\n\n/* ── Error helper ──────────────────────────────────────────────────────── */\n\nfunction exitErr(msg: string | undefined): never {\n console.error(`Error: ${msg ?? 'Unknown error'}`);\n process.exit(1);\n}\n"],"mappings":"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","names":["method"]}
@@ -1,15 +1,16 @@
1
1
  import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
2
  import {
3
3
  apiRequest
4
- } from "./chunk-WOHL4FTB.js";
5
- import "./chunk-SJJW77WN.js";
4
+ } from "./chunk-CQE46HSM.js";
6
5
  import "./chunk-3CZU7XCS.js";
7
6
  import {
8
7
  getArgValue,
9
8
  hasFlag,
10
9
  resolveConfig
11
- } from "./chunk-A4OFTUVV.js";
10
+ } from "./chunk-PZ4LCN6K.js";
11
+ import "./chunk-JZMJUPZP.js";
12
12
  import "./chunk-JWHYXEA2.js";
13
+ import "./chunk-QGI4UCJX.js";
13
14
  import "./chunk-VKVL7WBN.js";
14
15
 
15
16
  // src/attachment.ts
@@ -273,4 +274,4 @@ async function runAttachment(argv) {
273
274
  export {
274
275
  runAttachment
275
276
  };
276
- //# sourceMappingURL=attachment-SJC7D7FY.js.map
277
+ //# sourceMappingURL=attachment-OVNQD6Z2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/attachment.ts"],"sourcesContent":["/**\n * CLI Attachment Commands\n *\n * List, upload, fetch, and delete org-scoped attachments used by action\n * and notification nodes (config.attachmentIds).\n *\n * @module attachment\n */\n\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest } from './cli-helpers.js';\n\ntype AttachmentListItem = {\n id: string;\n filename: string;\n contentType: string;\n sizeBytes: number;\n createdAt: string;\n createdBy: string | null;\n};\n\ntype ListResponse = {\n ok: boolean;\n error?: string;\n data: AttachmentListItem[];\n pagination: { page: number; pageSize: number; totalItems: number; totalPages: number };\n};\n\ntype UploadResponse = {\n ok: boolean;\n error?: string;\n data?: AttachmentListItem[];\n};\n\ntype UrlResponse = { ok: boolean; error?: string; url?: string };\n\nconst VALID_KINDS = ['all', 'image', 'pdf', 'spreadsheet', 'data'] as const;\n\nfunction printAttachmentHelp(): void {\n console.log(\n [\n 'Usage: canary attachment <sub-command> [options]',\n '',\n 'Sub-commands:',\n ' list [options] List uploaded attachments',\n ' upload <file> [options] Upload a local file; prints the new ID',\n ' get <id> [--url] Print attachment metadata (or signed URL)',\n ' delete <id> Soft-delete an attachment',\n '',\n 'List options:',\n ' --kind <kind> Filter: all, image, pdf, spreadsheet, data (default: all)',\n ' --search <query> Search by filename',\n ' --page <n> Page number (default: 1)',\n ' --page-size <n> Page size (default: 25)',\n ' --json Output raw JSON',\n '',\n 'Upload options:',\n ' --filename <name> Override filename (default: basename of file)',\n ' --json Output raw JSON',\n '',\n 'Get options:',\n ' --url Print short-lived signed download URL',\n ' --json Output raw JSON',\n '',\n 'Tip: use the returned ID in a node\\'s `configJson.attachmentIds` array',\n 'for action or notification nodes when creating/patching workflows.',\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\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length <= max ? s : s.slice(0, max - 1) + '…';\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const kind = getArgValue(argv, '--kind');\n const search = getArgValue(argv, '--search');\n const page = getArgValue(argv, '--page');\n const pageSize = getArgValue(argv, '--page-size');\n const jsonOutput = hasFlag(argv, '--json');\n\n if (kind && !VALID_KINDS.includes(kind as (typeof VALID_KINDS)[number])) {\n console.error(`Error: invalid --kind \"${kind}\". Must be one of: ${VALID_KINDS.join(', ')}`);\n process.exit(1);\n }\n\n const params = new URLSearchParams();\n if (kind) params.set('kind', kind);\n if (search) params.set('search', search);\n if (page) params.set('page', page);\n if (pageSize) params.set('pageSize', pageSize);\n\n const qs = params.toString();\n const route = `/org/attachments${qs ? `?${qs}` : ''}`;\n const result = await apiRequest<ListResponse>(apiUrl, token, 'GET', route);\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify({ data: result.data, pagination: result.pagination }, null, 2));\n return;\n }\n\n const { data, pagination } = result;\n console.log(\n `Attachments: ${pagination.totalItems} total (page ${pagination.page}/${pagination.totalPages})\\n`\n );\n\n if (data.length === 0) {\n console.log('No attachments found.');\n return;\n }\n\n const idW = 36;\n const nameW = 40;\n const typeW = 24;\n const sizeW = 10;\n\n console.log(\n ['ID'.padEnd(idW), 'Filename'.padEnd(nameW), 'Type'.padEnd(typeW), 'Size'.padEnd(sizeW)].join(\n ' '\n )\n );\n for (const a of data) {\n console.log(\n [\n a.id.padEnd(idW),\n truncate(a.filename, nameW).padEnd(nameW),\n truncate(a.contentType, typeW).padEnd(typeW),\n formatSize(a.sizeBytes).padEnd(sizeW),\n ].join(' ')\n );\n }\n}\n\nasync function handleUpload(argv: string[], apiUrl: string, token: string): Promise<void> {\n const filePath = argv.find((a) => !a.startsWith('-'));\n if (!filePath) {\n console.error('Error: missing file path.');\n console.error('Usage: canary attachment upload <file> [--filename <name>]');\n process.exit(1);\n }\n\n const overrideName = getArgValue(argv, '--filename');\n const jsonOutput = hasFlag(argv, '--json');\n\n let buf: Buffer;\n try {\n buf = await fs.readFile(filePath);\n } catch (err) {\n console.error(`Error: failed to read ${filePath}: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n const filename = overrideName ?? path.basename(filePath);\n const form = new FormData();\n form.append('files', new Blob([new Uint8Array(buf)]), filename);\n\n const res = await fetch(`${apiUrl}/org/attachments`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}` },\n body: form,\n });\n\n if (res.status === 401) {\n console.error('Error: Unauthorized. Run: canary login');\n process.exit(1);\n }\n\n let body: UploadResponse;\n try {\n body = (await res.json()) as UploadResponse;\n } catch {\n console.error(`Error: invalid JSON response (${res.status})`);\n process.exit(1);\n }\n\n if (!body.ok || !body.data || body.data.length === 0) {\n console.error(`Error: ${body.error ?? `upload failed (${res.status})`}`);\n process.exit(1);\n }\n\n const [created] = body.data;\n\n if (jsonOutput) {\n console.log(JSON.stringify(created, null, 2));\n return;\n }\n\n console.log(`\\u2713 Uploaded ${created.filename}`);\n console.log(` ID: ${created.id}`);\n console.log(` Type: ${created.contentType}`);\n console.log(` Size: ${formatSize(created.sizeBytes)}`);\n console.log('');\n console.log('Reference in a workflow node:');\n console.log(` configJson.attachmentIds = [\"${created.id}\"]`);\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const id = argv.find((a) => !a.startsWith('-'));\n if (!id) {\n console.error('Error: missing attachment ID.');\n console.error('Usage: canary attachment get <id> [--url]');\n process.exit(1);\n }\n\n const wantUrl = hasFlag(argv, '--url');\n const jsonOutput = hasFlag(argv, '--json');\n\n if (wantUrl) {\n const result = await apiRequest<UrlResponse>(\n apiUrl,\n token,\n 'GET',\n `/org/attachments/${id}/url`\n );\n if (!result.ok || !result.url) {\n console.error(`Error: ${result.error ?? 'failed to fetch signed URL'}`);\n process.exit(1);\n }\n if (jsonOutput) {\n console.log(JSON.stringify({ id, url: result.url }, null, 2));\n } else {\n console.log(result.url);\n }\n return;\n }\n\n // No dedicated GET by id metadata endpoint; use bulk resolve as the read path.\n const res = await fetch(`${apiUrl}/org/attachments/resolve`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ ids: [id] }),\n });\n if (res.status === 401) {\n console.error('Error: Unauthorized. Run: canary login');\n process.exit(1);\n }\n const body = (await res.json()) as { ok: boolean; error?: string; data?: AttachmentListItem[] };\n if (!body.ok || !body.data || body.data.length === 0) {\n console.error(`Error: ${body.error ?? 'attachment not found'}`);\n process.exit(1);\n }\n const [att] = body.data;\n if (jsonOutput) {\n console.log(JSON.stringify(att, null, 2));\n return;\n }\n console.log(`${att.filename}`);\n console.log(` ID: ${att.id}`);\n console.log(` Type: ${att.contentType}`);\n console.log(` Size: ${formatSize(att.sizeBytes)}`);\n console.log(` Created: ${att.createdAt}`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const id = argv.find((a) => !a.startsWith('-'));\n if (!id) {\n console.error('Error: missing attachment ID.');\n console.error('Usage: canary attachment delete <id>');\n process.exit(1);\n }\n const jsonOutput = hasFlag(argv, '--json');\n\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'DELETE',\n `/org/attachments/${id}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'delete failed'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: true, id }, null, 2));\n return;\n }\n console.log(`\\u2713 Deleted attachment ${id}`);\n}\n\nexport async function runAttachment(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printAttachmentHelp();\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 'upload':\n await handleUpload(rest, apiUrl, token);\n return;\n case 'get':\n await handleGet(rest, apiUrl, token);\n return;\n case 'delete':\n await handleDelete(rest, apiUrl, token);\n return;\n default:\n console.error(`Unknown attachment sub-command: ${subCommand}`);\n printAttachmentHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/attachment.ts"],"sourcesContent":["/**\n * CLI Attachment Commands\n *\n * List, upload, fetch, and delete org-scoped attachments used by action\n * and notification nodes (config.attachmentIds).\n *\n * @module attachment\n */\n\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest } from './cli-helpers.js';\n\ntype AttachmentListItem = {\n id: string;\n filename: string;\n contentType: string;\n sizeBytes: number;\n createdAt: string;\n createdBy: string | null;\n};\n\ntype ListResponse = {\n ok: boolean;\n error?: string;\n data: AttachmentListItem[];\n pagination: { page: number; pageSize: number; totalItems: number; totalPages: number };\n};\n\ntype UploadResponse = {\n ok: boolean;\n error?: string;\n data?: AttachmentListItem[];\n};\n\ntype UrlResponse = { ok: boolean; error?: string; url?: string };\n\nconst VALID_KINDS = ['all', 'image', 'pdf', 'spreadsheet', 'data'] as const;\n\nfunction printAttachmentHelp(): void {\n console.log(\n [\n 'Usage: canary attachment <sub-command> [options]',\n '',\n 'Sub-commands:',\n ' list [options] List uploaded attachments',\n ' upload <file> [options] Upload a local file; prints the new ID',\n ' get <id> [--url] Print attachment metadata (or signed URL)',\n ' delete <id> Soft-delete an attachment',\n '',\n 'List options:',\n ' --kind <kind> Filter: all, image, pdf, spreadsheet, data (default: all)',\n ' --search <query> Search by filename',\n ' --page <n> Page number (default: 1)',\n ' --page-size <n> Page size (default: 25)',\n ' --json Output raw JSON',\n '',\n 'Upload options:',\n ' --filename <name> Override filename (default: basename of file)',\n ' --json Output raw JSON',\n '',\n 'Get options:',\n ' --url Print short-lived signed download URL',\n ' --json Output raw JSON',\n '',\n 'Tip: use the returned ID in a node\\'s `configJson.attachmentIds` array',\n 'for action or notification nodes when creating/patching workflows.',\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\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length <= max ? s : s.slice(0, max - 1) + '…';\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const kind = getArgValue(argv, '--kind');\n const search = getArgValue(argv, '--search');\n const page = getArgValue(argv, '--page');\n const pageSize = getArgValue(argv, '--page-size');\n const jsonOutput = hasFlag(argv, '--json');\n\n if (kind && !VALID_KINDS.includes(kind as (typeof VALID_KINDS)[number])) {\n console.error(`Error: invalid --kind \"${kind}\". Must be one of: ${VALID_KINDS.join(', ')}`);\n process.exit(1);\n }\n\n const params = new URLSearchParams();\n if (kind) params.set('kind', kind);\n if (search) params.set('search', search);\n if (page) params.set('page', page);\n if (pageSize) params.set('pageSize', pageSize);\n\n const qs = params.toString();\n const route = `/org/attachments${qs ? `?${qs}` : ''}`;\n const result = await apiRequest<ListResponse>(apiUrl, token, 'GET', route);\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify({ data: result.data, pagination: result.pagination }, null, 2));\n return;\n }\n\n const { data, pagination } = result;\n console.log(\n `Attachments: ${pagination.totalItems} total (page ${pagination.page}/${pagination.totalPages})\\n`\n );\n\n if (data.length === 0) {\n console.log('No attachments found.');\n return;\n }\n\n const idW = 36;\n const nameW = 40;\n const typeW = 24;\n const sizeW = 10;\n\n console.log(\n ['ID'.padEnd(idW), 'Filename'.padEnd(nameW), 'Type'.padEnd(typeW), 'Size'.padEnd(sizeW)].join(\n ' '\n )\n );\n for (const a of data) {\n console.log(\n [\n a.id.padEnd(idW),\n truncate(a.filename, nameW).padEnd(nameW),\n truncate(a.contentType, typeW).padEnd(typeW),\n formatSize(a.sizeBytes).padEnd(sizeW),\n ].join(' ')\n );\n }\n}\n\nasync function handleUpload(argv: string[], apiUrl: string, token: string): Promise<void> {\n const filePath = argv.find((a) => !a.startsWith('-'));\n if (!filePath) {\n console.error('Error: missing file path.');\n console.error('Usage: canary attachment upload <file> [--filename <name>]');\n process.exit(1);\n }\n\n const overrideName = getArgValue(argv, '--filename');\n const jsonOutput = hasFlag(argv, '--json');\n\n let buf: Buffer;\n try {\n buf = await fs.readFile(filePath);\n } catch (err) {\n console.error(`Error: failed to read ${filePath}: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n const filename = overrideName ?? path.basename(filePath);\n const form = new FormData();\n form.append('files', new Blob([new Uint8Array(buf)]), filename);\n\n const res = await fetch(`${apiUrl}/org/attachments`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}` },\n body: form,\n });\n\n if (res.status === 401) {\n console.error('Error: Unauthorized. Run: canary login');\n process.exit(1);\n }\n\n let body: UploadResponse;\n try {\n body = (await res.json()) as UploadResponse;\n } catch {\n console.error(`Error: invalid JSON response (${res.status})`);\n process.exit(1);\n }\n\n if (!body.ok || !body.data || body.data.length === 0) {\n console.error(`Error: ${body.error ?? `upload failed (${res.status})`}`);\n process.exit(1);\n }\n\n const [created] = body.data;\n\n if (jsonOutput) {\n console.log(JSON.stringify(created, null, 2));\n return;\n }\n\n console.log(`\\u2713 Uploaded ${created.filename}`);\n console.log(` ID: ${created.id}`);\n console.log(` Type: ${created.contentType}`);\n console.log(` Size: ${formatSize(created.sizeBytes)}`);\n console.log('');\n console.log('Reference in a workflow node:');\n console.log(` configJson.attachmentIds = [\"${created.id}\"]`);\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const id = argv.find((a) => !a.startsWith('-'));\n if (!id) {\n console.error('Error: missing attachment ID.');\n console.error('Usage: canary attachment get <id> [--url]');\n process.exit(1);\n }\n\n const wantUrl = hasFlag(argv, '--url');\n const jsonOutput = hasFlag(argv, '--json');\n\n if (wantUrl) {\n const result = await apiRequest<UrlResponse>(\n apiUrl,\n token,\n 'GET',\n `/org/attachments/${id}/url`\n );\n if (!result.ok || !result.url) {\n console.error(`Error: ${result.error ?? 'failed to fetch signed URL'}`);\n process.exit(1);\n }\n if (jsonOutput) {\n console.log(JSON.stringify({ id, url: result.url }, null, 2));\n } else {\n console.log(result.url);\n }\n return;\n }\n\n // No dedicated GET by id metadata endpoint; use bulk resolve as the read path.\n const res = await fetch(`${apiUrl}/org/attachments/resolve`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ ids: [id] }),\n });\n if (res.status === 401) {\n console.error('Error: Unauthorized. Run: canary login');\n process.exit(1);\n }\n const body = (await res.json()) as { ok: boolean; error?: string; data?: AttachmentListItem[] };\n if (!body.ok || !body.data || body.data.length === 0) {\n console.error(`Error: ${body.error ?? 'attachment not found'}`);\n process.exit(1);\n }\n const [att] = body.data;\n if (jsonOutput) {\n console.log(JSON.stringify(att, null, 2));\n return;\n }\n console.log(`${att.filename}`);\n console.log(` ID: ${att.id}`);\n console.log(` Type: ${att.contentType}`);\n console.log(` Size: ${formatSize(att.sizeBytes)}`);\n console.log(` Created: ${att.createdAt}`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const id = argv.find((a) => !a.startsWith('-'));\n if (!id) {\n console.error('Error: missing attachment ID.');\n console.error('Usage: canary attachment delete <id>');\n process.exit(1);\n }\n const jsonOutput = hasFlag(argv, '--json');\n\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'DELETE',\n `/org/attachments/${id}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'delete failed'}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: true, id }, null, 2));\n return;\n }\n console.log(`\\u2713 Deleted attachment ${id}`);\n}\n\nexport async function runAttachment(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printAttachmentHelp();\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 'upload':\n await handleUpload(rest, apiUrl, token);\n return;\n case 'get':\n await handleGet(rest, apiUrl, token);\n return;\n case 'delete':\n await handleDelete(rest, apiUrl, token);\n return;\n default:\n console.error(`Unknown attachment sub-command: ${subCommand}`);\n printAttachmentHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
@@ -12,7 +12,8 @@ import {
12
12
  resolveConfig,
13
13
  resolveOptionalConfig,
14
14
  saveAuth
15
- } from "./chunk-A4OFTUVV.js";
15
+ } from "./chunk-PZ4LCN6K.js";
16
+ import "./chunk-JZMJUPZP.js";
16
17
  import "./chunk-VKVL7WBN.js";
17
18
  export {
18
19
  ENV_URLS,
@@ -28,4 +29,4 @@ export {
28
29
  resolveOptionalConfig,
29
30
  saveAuth
30
31
  };
31
- //# sourceMappingURL=auth-EN6NQCJY.js.map
32
+ //# sourceMappingURL=auth-VUHL74FH.js.map
@@ -1,5 +1,40 @@
1
1
  import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
2
 
3
+ // ../recording/src/locator-string.ts
4
+ function buildLocatorString(selectors) {
5
+ const parts = [];
6
+ if (selectors.testId) {
7
+ parts.push(`getByTestId(${JSON.stringify(selectors.testId)})`);
8
+ }
9
+ if (selectors.role) {
10
+ const { role, name, exact } = selectors.role;
11
+ if (name) {
12
+ const options = exact ? `{ name: ${JSON.stringify(name)}, exact: true }` : `{ name: ${JSON.stringify(name)} }`;
13
+ parts.push(`getByRole('${role}', ${options})`);
14
+ } else {
15
+ parts.push(`getByRole('${role}')`);
16
+ }
17
+ }
18
+ if (selectors.ariaLabel) {
19
+ parts.push(`getByLabel(${JSON.stringify(selectors.ariaLabel)})`);
20
+ }
21
+ if (selectors.placeholder) {
22
+ parts.push(`getByPlaceholder(${JSON.stringify(selectors.placeholder)})`);
23
+ }
24
+ if (selectors.text) {
25
+ const { text, exact } = selectors.text;
26
+ if (exact) {
27
+ parts.push(`getByText(${JSON.stringify(text)}, { exact: true })`);
28
+ } else {
29
+ parts.push(`getByText(${JSON.stringify(text)})`);
30
+ }
31
+ }
32
+ if (selectors.css) {
33
+ parts.push(`locator(${JSON.stringify(selectors.css)})`);
34
+ }
35
+ return parts.length > 0 ? parts[0] : 'locator("*")';
36
+ }
37
+
3
38
  // ../recording/src/capture-script.ts
4
39
  var INTERACTION_CAPTURE_SCRIPT = `
5
40
  (function() {
@@ -175,6 +210,7 @@ var INTERACTION_CAPTURE_SCRIPT = `
175
210
  `;
176
211
 
177
212
  export {
213
+ buildLocatorString,
178
214
  INTERACTION_CAPTURE_SCRIPT
179
215
  };
180
- //# sourceMappingURL=chunk-IMPZAX6L.js.map
216
+ //# sourceMappingURL=chunk-5GD47G2D.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../recording/src/capture-script.ts"],"sourcesContent":["/**\n * In-page interaction capture script injected via addInitScript.\n * Captures user interactions to window.__canaryRecordedEvents.\n *\n * @module record-interaction-script\n */\n\nexport const INTERACTION_CAPTURE_SCRIPT = `\n(function() {\n if (window.__canaryRecordedEvents) return;\n window.__canaryRecordedEvents = [];\n\n function push(event) {\n window.__canaryRecordedEvents.push(event);\n }\n\n // --- Input debouncing ---\n // Accumulate input per element, flush after 500ms idle as a single event\n var inputTimers = new Map();\n var inputState = new Map();\n\n function getElementKey(el) {\n return (el.id || '') + '|' + (el.getAttribute('aria-label') || '') + '|' + (el.tagName || '') + '|' + (el.getAttribute('name') || '');\n }\n\n function flushInput(key) {\n var state = inputState.get(key);\n if (!state) return;\n inputTimers.delete(key);\n inputState.delete(key);\n push({\n type: 'input',\n ts: state.ts,\n tagName: state.tagName,\n id: state.id || undefined,\n inputType: state.inputType || undefined,\n ariaLabel: state.ariaLabel || undefined,\n value: state.value,\n isFinal: true,\n });\n }\n\n function flushAllInputs() {\n inputTimers.forEach(function(timer) { clearTimeout(timer); });\n inputState.forEach(function(_, key) { flushInput(key); });\n }\n\n document.addEventListener('click', function(e) {\n var el = e.target;\n push({\n type: 'click',\n ts: Date.now(),\n x: e.clientX,\n y: e.clientY,\n tagName: el.tagName || '',\n id: el.id || undefined,\n testId: el.getAttribute('data-testid') || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n role: el.getAttribute('role') || undefined,\n textContent: (el.textContent || '').slice(0, 200).trim() || undefined,\n className: el.className && typeof el.className === 'string' ? el.className.slice(0, 200) : undefined,\n });\n }, true);\n\n document.addEventListener('input', function(e) {\n var el = e.target;\n var isPassword = el.type === 'password';\n var key = getElementKey(el);\n\n // Clear previous timer for this element\n var prevTimer = inputTimers.get(key);\n if (prevTimer) clearTimeout(prevTimer);\n\n // Update accumulated state\n inputState.set(key, {\n ts: Date.now(),\n tagName: el.tagName || '',\n id: el.id || undefined,\n inputType: el.type || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n value: isPassword ? '***' : (el.value || ''),\n });\n\n // Schedule flush after 500ms idle\n inputTimers.set(key, setTimeout(function() { flushInput(key); }, 500));\n }, true);\n\n // --- Change events for selects, checkboxes, radios ---\n document.addEventListener('change', function(e) {\n var el = e.target;\n var tagName = el.tagName || '';\n var inputType = (el.type || '').toLowerCase();\n\n // Only capture selects, checkboxes, and radios (text inputs are handled by input debouncing)\n var isSelect = tagName === 'SELECT';\n var isCheckOrRadio = inputType === 'checkbox' || inputType === 'radio';\n if (!isSelect && !isCheckOrRadio) return;\n\n var value;\n if (isCheckOrRadio) {\n value = el.checked ? 'checked' : 'unchecked';\n } else {\n value = el.value || '';\n }\n\n push({\n type: 'change',\n ts: Date.now(),\n tagName: tagName,\n id: el.id || undefined,\n inputType: inputType || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n value: value,\n });\n }, true);\n\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Enter' || e.key === 'Tab' || e.key === 'Escape') {\n push({\n type: 'keydown',\n ts: Date.now(),\n key: e.key,\n });\n }\n }, true);\n\n // --- SPA navigation: patch pushState/replaceState ---\n var origPushState = history.pushState;\n var origReplaceState = history.replaceState;\n\n history.pushState = function() {\n origPushState.apply(this, arguments);\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'pushState',\n });\n };\n\n history.replaceState = function() {\n origReplaceState.apply(this, arguments);\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'replaceState',\n });\n };\n\n window.addEventListener('popstate', function() {\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'popstate',\n });\n });\n\n window.addEventListener('beforeunload', function() {\n flushAllInputs();\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'beforeunload',\n });\n });\n\n // Exposed for discardCapturedEvents — cancels pending debounce timers\n // without flushing their events, then clears the array.\n window.__canaryFlushAndDiscard = function() {\n inputTimers.forEach(function(timer) { clearTimeout(timer); });\n inputTimers.clear();\n inputState.clear();\n window.__canaryRecordedEvents = [];\n };\n})();\n`;\n"],"mappings":";;;AAOO,IAAM,6BAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
1
+ {"version":3,"sources":["../../recording/src/locator-string.ts","../../recording/src/capture-script.ts"],"sourcesContent":["import type { SelectorStrategy } from '@chatsdet/types';\n\n/**\n * Build a Playwright locator string from a selector strategy.\n *\n * Returns the locator string in priority order (testId, role, label, placeholder, text, css).\n * Used during replay to find elements and during recording to pre-render the locator each\n * captured event would produce.\n *\n * @param selectors - Selector strategy from a cached action or captured recording event.\n * @returns Playwright locator chain as a string, e.g. `getByRole('button', { name: 'Sign in' })`.\n */\nexport function buildLocatorString(selectors: SelectorStrategy): string {\n const parts: string[] = [];\n\n if (selectors.testId) {\n parts.push(`getByTestId(${JSON.stringify(selectors.testId)})`);\n }\n\n if (selectors.role) {\n const { role, name, exact } = selectors.role;\n if (name) {\n const options = exact\n ? `{ name: ${JSON.stringify(name)}, exact: true }`\n : `{ name: ${JSON.stringify(name)} }`;\n parts.push(`getByRole('${role}', ${options})`);\n } else {\n parts.push(`getByRole('${role}')`);\n }\n }\n\n if (selectors.ariaLabel) {\n parts.push(`getByLabel(${JSON.stringify(selectors.ariaLabel)})`);\n }\n\n if (selectors.placeholder) {\n parts.push(`getByPlaceholder(${JSON.stringify(selectors.placeholder)})`);\n }\n\n if (selectors.text) {\n const { text, exact } = selectors.text;\n if (exact) {\n parts.push(`getByText(${JSON.stringify(text)}, { exact: true })`);\n } else {\n parts.push(`getByText(${JSON.stringify(text)})`);\n }\n }\n\n if (selectors.css) {\n parts.push(`locator(${JSON.stringify(selectors.css)})`);\n }\n\n return parts.length > 0 ? parts[0] : 'locator(\"*\")';\n}\n","/**\n * In-page interaction capture script injected via addInitScript.\n * Captures user interactions to window.__canaryRecordedEvents.\n *\n * @module record-interaction-script\n */\n\nexport const INTERACTION_CAPTURE_SCRIPT = `\n(function() {\n if (window.__canaryRecordedEvents) return;\n window.__canaryRecordedEvents = [];\n\n function push(event) {\n window.__canaryRecordedEvents.push(event);\n }\n\n // --- Input debouncing ---\n // Accumulate input per element, flush after 500ms idle as a single event\n var inputTimers = new Map();\n var inputState = new Map();\n\n function getElementKey(el) {\n return (el.id || '') + '|' + (el.getAttribute('aria-label') || '') + '|' + (el.tagName || '') + '|' + (el.getAttribute('name') || '');\n }\n\n function flushInput(key) {\n var state = inputState.get(key);\n if (!state) return;\n inputTimers.delete(key);\n inputState.delete(key);\n push({\n type: 'input',\n ts: state.ts,\n tagName: state.tagName,\n id: state.id || undefined,\n inputType: state.inputType || undefined,\n ariaLabel: state.ariaLabel || undefined,\n value: state.value,\n isFinal: true,\n });\n }\n\n function flushAllInputs() {\n inputTimers.forEach(function(timer) { clearTimeout(timer); });\n inputState.forEach(function(_, key) { flushInput(key); });\n }\n\n document.addEventListener('click', function(e) {\n var el = e.target;\n push({\n type: 'click',\n ts: Date.now(),\n x: e.clientX,\n y: e.clientY,\n tagName: el.tagName || '',\n id: el.id || undefined,\n testId: el.getAttribute('data-testid') || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n role: el.getAttribute('role') || undefined,\n textContent: (el.textContent || '').slice(0, 200).trim() || undefined,\n className: el.className && typeof el.className === 'string' ? el.className.slice(0, 200) : undefined,\n });\n }, true);\n\n document.addEventListener('input', function(e) {\n var el = e.target;\n var isPassword = el.type === 'password';\n var key = getElementKey(el);\n\n // Clear previous timer for this element\n var prevTimer = inputTimers.get(key);\n if (prevTimer) clearTimeout(prevTimer);\n\n // Update accumulated state\n inputState.set(key, {\n ts: Date.now(),\n tagName: el.tagName || '',\n id: el.id || undefined,\n inputType: el.type || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n value: isPassword ? '***' : (el.value || ''),\n });\n\n // Schedule flush after 500ms idle\n inputTimers.set(key, setTimeout(function() { flushInput(key); }, 500));\n }, true);\n\n // --- Change events for selects, checkboxes, radios ---\n document.addEventListener('change', function(e) {\n var el = e.target;\n var tagName = el.tagName || '';\n var inputType = (el.type || '').toLowerCase();\n\n // Only capture selects, checkboxes, and radios (text inputs are handled by input debouncing)\n var isSelect = tagName === 'SELECT';\n var isCheckOrRadio = inputType === 'checkbox' || inputType === 'radio';\n if (!isSelect && !isCheckOrRadio) return;\n\n var value;\n if (isCheckOrRadio) {\n value = el.checked ? 'checked' : 'unchecked';\n } else {\n value = el.value || '';\n }\n\n push({\n type: 'change',\n ts: Date.now(),\n tagName: tagName,\n id: el.id || undefined,\n inputType: inputType || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n value: value,\n });\n }, true);\n\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Enter' || e.key === 'Tab' || e.key === 'Escape') {\n push({\n type: 'keydown',\n ts: Date.now(),\n key: e.key,\n });\n }\n }, true);\n\n // --- SPA navigation: patch pushState/replaceState ---\n var origPushState = history.pushState;\n var origReplaceState = history.replaceState;\n\n history.pushState = function() {\n origPushState.apply(this, arguments);\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'pushState',\n });\n };\n\n history.replaceState = function() {\n origReplaceState.apply(this, arguments);\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'replaceState',\n });\n };\n\n window.addEventListener('popstate', function() {\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'popstate',\n });\n });\n\n window.addEventListener('beforeunload', function() {\n flushAllInputs();\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'beforeunload',\n });\n });\n\n // Exposed for discardCapturedEvents — cancels pending debounce timers\n // without flushing their events, then clears the array.\n window.__canaryFlushAndDiscard = function() {\n inputTimers.forEach(function(timer) { clearTimeout(timer); });\n inputTimers.clear();\n inputState.clear();\n window.__canaryRecordedEvents = [];\n };\n})();\n`;\n"],"mappings":";;;AAYO,SAAS,mBAAmB,WAAqC;AACtE,QAAM,QAAkB,CAAC;AAEzB,MAAI,UAAU,QAAQ;AACpB,UAAM,KAAK,eAAe,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG;AAAA,EAC/D;AAEA,MAAI,UAAU,MAAM;AAClB,UAAM,EAAE,MAAM,MAAM,MAAM,IAAI,UAAU;AACxC,QAAI,MAAM;AACR,YAAM,UAAU,QACZ,WAAW,KAAK,UAAU,IAAI,CAAC,oBAC/B,WAAW,KAAK,UAAU,IAAI,CAAC;AACnC,YAAM,KAAK,cAAc,IAAI,MAAM,OAAO,GAAG;AAAA,IAC/C,OAAO;AACL,YAAM,KAAK,cAAc,IAAI,IAAI;AAAA,IACnC;AAAA,EACF;AAEA,MAAI,UAAU,WAAW;AACvB,UAAM,KAAK,cAAc,KAAK,UAAU,UAAU,SAAS,CAAC,GAAG;AAAA,EACjE;AAEA,MAAI,UAAU,aAAa;AACzB,UAAM,KAAK,oBAAoB,KAAK,UAAU,UAAU,WAAW,CAAC,GAAG;AAAA,EACzE;AAEA,MAAI,UAAU,MAAM;AAClB,UAAM,EAAE,MAAM,MAAM,IAAI,UAAU;AAClC,QAAI,OAAO;AACT,YAAM,KAAK,aAAa,KAAK,UAAU,IAAI,CAAC,oBAAoB;AAAA,IAClE,OAAO;AACL,YAAM,KAAK,aAAa,KAAK,UAAU,IAAI,CAAC,GAAG;AAAA,IACjD;AAAA,EACF;AAEA,MAAI,UAAU,KAAK;AACjB,UAAM,KAAK,WAAW,KAAK,UAAU,UAAU,GAAG,CAAC,GAAG;AAAA,EACxD;AAEA,SAAO,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI;AACvC;;;AC9CO,IAAM,6BAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
@@ -1,7 +1,4 @@
1
1
  import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
- import {
3
- VALID_MACRO_NAMES
4
- } from "./chunk-SJJW77WN.js";
5
2
  import {
6
3
  apiFetch,
7
4
  exitOnFailure,
@@ -9,10 +6,13 @@ import {
9
6
  } from "./chunk-3CZU7XCS.js";
10
7
  import {
11
8
  getArgValue
12
- } from "./chunk-A4OFTUVV.js";
9
+ } from "./chunk-PZ4LCN6K.js";
13
10
  import {
14
11
  getCanaryTmpDir
15
12
  } from "./chunk-JWHYXEA2.js";
13
+ import {
14
+ VALID_MACRO_NAMES
15
+ } from "./chunk-QGI4UCJX.js";
16
16
 
17
17
  // src/cli-helpers.ts
18
18
  import fs from "fs/promises";
@@ -350,4 +350,4 @@ export {
350
350
  uploadStorageState,
351
351
  fetchList
352
352
  };
353
- //# sourceMappingURL=chunk-WOHL4FTB.js.map
353
+ //# sourceMappingURL=chunk-CQE46HSM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-helpers.ts"],"sourcesContent":["/**\n * Shared CLI helpers for superadmin management commands (knobs, feature-flags).\n */\n\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { getCanaryTmpDir } from '@chatsdet/tmp';\nimport { VALID_MACRO_NAMES } from '@chatsdet/types';\nimport { getArgValue } from './auth.js';\nimport { apiFetch, exitOnFailure, isTerminalFailure } from './api-fetch.js';\n\nexport type LifecycleStage = 'active' | 'deprecated' | 'ready_for_cleanup';\n\nexport function toLifecycleLabel(stage: LifecycleStage): string {\n switch (stage) {\n case 'deprecated':\n return 'deprecated';\n case 'ready_for_cleanup':\n return 'ready_for_cleanup';\n default:\n return 'active';\n }\n}\n\nexport function parseLifecycleStage(argv: string[]): LifecycleStage {\n const stage = getArgValue(argv, '--stage');\n if (!stage || !['active', 'deprecated', 'ready_for_cleanup'].includes(stage)) {\n console.error(\n 'Error: --stage is required and must be one of: active, deprecated, ready_for_cleanup'\n );\n process.exit(1);\n }\n return stage as LifecycleStage;\n}\n\nexport async function apiRequest<T extends { ok: boolean; error?: string }>(\n apiUrl: string,\n token: string,\n method: string,\n path: string,\n body?: Record<string, unknown>,\n options?: { timeoutMs?: number }\n): Promise<T> {\n const result = await apiFetch(`${apiUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n token,\n ...(options?.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),\n ...(body ? { body: JSON.stringify(body) } : {}),\n });\n\n if (!result.ok) {\n const { failure } = result;\n // Terminal kinds (auth/proxy/TLS) surface the full diagnostic and exit;\n // http-error falls through so the caller can pretty-print structured\n // user errors (unresolved vars, invalid macros, etc.).\n if (isTerminalFailure(failure)) exitOnFailure(failure);\n const text = failure.body ?? '';\n let errorMessage = failure.message;\n let parsed: Record<string, unknown> | null = null;\n try {\n const data = JSON.parse(text);\n if (data && typeof data === 'object') {\n parsed = data as Record<string, unknown>;\n if (typeof parsed.error === 'string') errorMessage = parsed.error;\n }\n } catch {\n /* keep failure.message */\n }\n return { ...parsed, ok: false, error: errorMessage } as T;\n }\n\n try {\n return (await result.response.json()) as T;\n } catch {\n return { ok: false, error: `Invalid JSON response (${result.response.status})` } as T;\n }\n}\n\ntype UnresolvedRef = {\n nodeId?: string;\n nodeType?: string;\n field?: string;\n variable: string;\n};\n\n/**\n * Render a structured `userError` response from the workflow API into a\n * multi-line, actionable message. Recognizes `WORKFLOW_UNRESOLVED_VARIABLES`\n * and falls back to `✖ {code}: {message}` for other codes. Returns `null` if\n * the response body isn't a recognized structured error.\n */\nexport function renderWorkflowUserError(result: Record<string, unknown>): string | null {\n const code = typeof result.code === 'string' ? result.code : null;\n const message = typeof result.error === 'string' ? result.error : null;\n if (!code) return null;\n\n if (code === 'WORKFLOW_VALIDATION_FAILED') {\n type ValidationIssue = {\n nodeId?: string | null;\n nodeType?: string | null;\n field?: string;\n message?: string;\n severity?: 'error' | 'warning';\n };\n const issues = Array.isArray(result.issues) ? (result.issues as ValidationIssue[]) : [];\n const errors = issues.filter((i) => (i.severity ?? 'error') === 'error');\n const warnings = issues.filter((i) => i.severity === 'warning');\n\n const lines: string[] = [\n `✖ Validation failed (${errors.length} error${errors.length === 1 ? '' : 's'}` +\n (warnings.length > 0\n ? `, ${warnings.length} warning${warnings.length === 1 ? '' : 's'}`\n : '') +\n ')',\n ];\n if (message) lines.push(` ${message}`);\n\n // Group by nodeId (null = flow-level).\n const byNode = new Map<string, ValidationIssue[]>();\n for (const issue of issues) {\n const key = issue.nodeId ?? '__flow__';\n const arr = byNode.get(key) ?? [];\n arr.push(issue);\n byNode.set(key, arr);\n }\n for (const [nodeKey, nodeIssues] of byNode) {\n const heading =\n nodeKey === '__flow__'\n ? 'Flow'\n : `Node ${nodeKey}${nodeIssues[0]?.nodeType ? ` (${nodeIssues[0].nodeType})` : ''}`;\n lines.push(` ${heading}:`);\n for (const issue of nodeIssues) {\n const sev = issue.severity === 'warning' ? '⚠' : '•';\n const field = issue.field ? `${issue.field} — ` : '';\n lines.push(` ${sev} ${field}${issue.message ?? ''}`);\n }\n }\n return lines.join('\\n');\n }\n\n if (code === 'WORKFLOW_UNRESOLVED_VARIABLES') {\n const lines: string[] = [`✖ ${code}`];\n if (message) lines.push(` ${message}`);\n const refs = Array.isArray(result.refs) ? (result.refs as UnresolvedRef[]) : [];\n const variables = Array.isArray(result.variables)\n ? (result.variables as string[])\n : refs.map((r) => r.variable);\n\n if (refs.length > 0) {\n lines.push(' Unresolved references:');\n for (const ref of refs) {\n const loc = ref.field && ref.nodeId ? ` (node ${ref.nodeId}, ${ref.field})` : '';\n lines.push(` • $var.${ref.variable}${loc}`);\n }\n } else if (variables.length > 0) {\n lines.push(' Unresolved:');\n for (const v of variables) lines.push(` • $var.${v}`);\n }\n\n const macroHints = variables.filter((v) => VALID_MACRO_NAMES.has(v.toUpperCase()));\n if (macroHints.length > 0) {\n lines.push(' Hint: these look like macro names, not variables:');\n for (const v of macroHints) {\n lines.push(` $var.${v} → $${v.toUpperCase()}()`);\n }\n }\n return lines.join('\\n');\n }\n\n if (code === 'WORKFLOW_INVALID_INPUT_VALUES') {\n const lines: string[] = [`✖ ${code}`];\n if (message) lines.push(` ${message}`);\n const issues = Array.isArray(result.issues)\n ? (result.issues as Array<{\n key?: string;\n value?: string;\n reason?: string;\n variables?: string[];\n }>)\n : [];\n for (const issue of issues) {\n const key = issue.key ?? '?';\n const value = issue.value ?? '';\n if (issue.reason === 'self_referential') {\n lines.push(` • ${key}: self-referential → ${value}`);\n lines.push(` Use a literal or point at a different upstream variable.`);\n } else if (issue.reason === 'macro_name_used_as_var') {\n lines.push(` • ${key}: macro name used as $var → ${value}`);\n for (const v of issue.variables ?? []) {\n lines.push(` $var.${v} → $${v.toUpperCase()}()`);\n }\n } else {\n lines.push(` • ${key}: ${issue.reason ?? 'invalid'} → ${value}`);\n }\n }\n return lines.join('\\n');\n }\n\n if (code === 'WORKFLOW_INVALID_MACRO') {\n const lines: string[] = [`✖ ${code}`];\n if (message) lines.push(` ${message}`);\n const invalid = Array.isArray(result.invalid) ? (result.invalid as string[]) : [];\n const valid = Array.isArray(result.valid) ? (result.valid as string[]) : [];\n if (invalid.length > 0) {\n lines.push(` Invalid macro(s): ${invalid.map((n) => `$${n}()`).join(', ')}`);\n }\n if (valid.length > 0) {\n lines.push(` Valid macros: ${valid.map((n) => `$${n}()`).join(', ')}`);\n }\n return lines.join('\\n');\n }\n\n return `✖ ${code}${message ? `: ${message}` : ''}`;\n}\n\nexport async function downloadStorageState(opts: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n prefix?: string;\n}): Promise<string | undefined> {\n const tmpFile = path.join(getCanaryTmpDir(), `${opts.prefix ?? 'canary-ss'}-${Date.now()}.json`);\n try {\n const res = await fetch(\n `${opts.apiUrl}/org/properties/${opts.propertyId}/credentials/${opts.credentialId}/storage-state/download`,\n {\n headers: { Authorization: `Bearer ${opts.token}` },\n redirect: 'follow',\n }\n );\n if (res.ok) {\n const body = await res.text();\n await fs.writeFile(tmpFile, body, 'utf-8');\n return tmpFile;\n }\n } catch {\n // Caller handles missing storage state\n }\n return undefined;\n}\n\n/* ── Credential selection ─────────────────────────────────────────────── */\n\nexport interface CredentialListItem {\n id: string;\n name: string;\n propertyId: string;\n propertyName?: string;\n propertyBaseUrl?: string;\n environmentId?: string | null;\n environmentName?: string | null;\n storageStateS3Key?: string | null;\n isDefault?: boolean;\n isEphemeral?: boolean;\n}\n\n/**\n * Fetch org credentials and let the user pick one interactively.\n *\n * @param credentialArg - Credential name or ID to auto-select, or undefined for interactive\n * @returns The selected credential, or null if none found / invalid selection\n */\nexport async function selectCredential(\n apiUrl: string,\n token: string,\n credentialArg?: string\n): Promise<CredentialListItem | null> {\n const credentials = await fetchList<CredentialListItem>(\n apiUrl,\n token,\n '/org/credentials',\n 'items'\n );\n\n if (credentials.length === 0) {\n console.error('No credentials found. Create one first in the web app.');\n return null;\n }\n\n if (credentialArg) {\n const match = credentials.find(\n (c) => c.id === credentialArg || c.name.toLowerCase() === credentialArg.toLowerCase()\n );\n if (!match) {\n console.error(`Credential \"${credentialArg}\" not found.`);\n console.error('Available credentials:');\n for (const c of credentials) {\n const env = c.environmentName ? ` — ${c.environmentName}` : '';\n const baseUrl = c.propertyBaseUrl ? ` — ${c.propertyBaseUrl}` : '';\n console.error(` - ${c.name} [${c.propertyName ?? c.propertyId}${env}${baseUrl}]`);\n }\n return null;\n }\n return match;\n }\n\n // Interactive selection\n console.log('\\nSelect a credential:\\n');\n const labels = credentials.map((c) => {\n const property = c.propertyName ?? c.propertyId;\n const env = c.environmentName ? ` — ${c.environmentName}` : '';\n const baseUrl = c.propertyBaseUrl ? ` — ${c.propertyBaseUrl}` : '';\n return `${c.name} [${property}${env}${baseUrl}]`;\n });\n\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n for (let i = 0; i < labels.length; i++) {\n console.log(` ${i + 1}. ${labels[i]}`);\n }\n rl.question('\\nEnter number: ', (ans) => {\n rl.close();\n resolve(ans.trim());\n });\n });\n\n const idx = parseInt(answer, 10) - 1;\n if (isNaN(idx) || idx < 0 || idx >= credentials.length) {\n console.error('Invalid selection.');\n return null;\n }\n\n return credentials[idx];\n}\n\n/* ── Property selection ──────────────────────────────────────────────── */\n\ninterface PropertyListItem {\n id: string;\n name: string;\n baseUrl: string;\n}\n\nexport async function fetchProperties(apiUrl: string, token: string): Promise<PropertyListItem[]> {\n return fetchList<PropertyListItem>(apiUrl, token, '/org/properties', 'items');\n}\n\n/**\n * Read the application/property selector flag. `--application` is the user-facing\n * name; `--property` is kept as a backwards-compat alias (read second). Internally\n * this is still a \"property\" — the rename is cosmetic.\n */\nexport function getApplicationArg(argv: string[]): string | undefined {\n return getArgValue(argv, '--application') ?? getArgValue(argv, '--property');\n}\n\n/**\n * Read the application/property UUID flag. `--application-id` is the user-facing\n * name; `--property-id` is kept as a backwards-compat alias.\n */\nexport function getApplicationIdArg(argv: string[]): string | undefined {\n return getArgValue(argv, '--application-id') ?? getArgValue(argv, '--property-id');\n}\n\nexport async function selectProperty(\n apiUrl: string,\n token: string,\n hint?: string\n): Promise<PropertyListItem | null> {\n const properties = await fetchProperties(apiUrl, token);\n\n if (properties.length === 0) {\n console.error('No applications found. Create one first in the web app.');\n return null;\n }\n\n if (hint) {\n const match = properties.find(\n (p) => p.id === hint || p.name.toLowerCase() === hint.toLowerCase()\n );\n if (!match) {\n console.error(`Application \"${hint}\" not found.`);\n console.error('Available applications:');\n for (const p of properties) {\n console.error(` - ${p.name} (${p.baseUrl})`);\n }\n return null;\n }\n return match;\n }\n\n if (properties.length === 1) {\n console.log(`Auto-selected application: ${properties[0].name}`);\n return properties[0];\n }\n\n return promptChoice(\n 'Select an application:',\n properties.map((p) => ({ label: `${p.name} — ${p.baseUrl}`, value: p }))\n );\n}\n\n/* ── Interactive prompt helpers ──────────────────────────────────────── */\n\nexport async function promptInput(question: string, defaultValue?: string): Promise<string> {\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;\n const answer = await new Promise<string>((resolve) => {\n rl.question(prompt, (ans) => {\n rl.close();\n resolve(ans.trim());\n });\n });\n return answer || defaultValue || '';\n}\n\nexport async function promptChoice<T>(\n question: string,\n options: Array<{ label: string; value: T }>\n): Promise<T | null> {\n console.log(`\\n${question}\\n`);\n for (let i = 0; i < options.length; i++) {\n console.log(` ${i + 1}. ${options[i].label}`);\n }\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n rl.question('\\nEnter number: ', (ans) => {\n rl.close();\n resolve(ans.trim());\n });\n });\n\n const idx = parseInt(answer, 10) - 1;\n if (isNaN(idx) || idx < 0 || idx >= options.length) {\n console.error('Invalid selection.');\n return null;\n }\n return options[idx].value;\n}\n\nexport async function uploadStorageState(opts: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n storageState: unknown;\n}): Promise<{ ok: boolean; s3Key?: string; error?: string }> {\n const result = await apiFetch(\n `${opts.apiUrl}/org/properties/${opts.propertyId}/credentials/${opts.credentialId}/storage-state/upload`,\n {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${opts.token}`,\n 'Content-Type': 'application/json',\n },\n token: opts.token,\n body: JSON.stringify({ storageState: opts.storageState }),\n }\n );\n\n if (!result.ok) exitOnFailure(result.failure);\n\n return (await result.response.json()) as { ok: boolean; s3Key?: string; error?: string };\n}\n\nexport async function fetchList<T>(\n apiUrl: string,\n token: string,\n path: string,\n listKey: string\n): Promise<T[]> {\n const result = await apiFetch(`${apiUrl}${path}`, {\n headers: { Authorization: `Bearer ${token}` },\n token,\n });\n\n if (!result.ok) exitOnFailure(result.failure);\n\n const json = (await result.response.json()) as Record<string, unknown>;\n\n if (!json.ok) {\n console.error(`Error: ${json.error}`);\n process.exit(1);\n }\n\n return (json[listKey] as T[]) ?? [];\n}\n"],"mappings":"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","names":["path"]}
@@ -2736,7 +2736,8 @@ function parseTraceActions(traceZipPath) {
2736
2736
  params: event.params,
2737
2737
  beforeSnapshot: event.beforeSnapshot,
2738
2738
  pageId: event.pageId ?? "",
2739
- point: event.point
2739
+ point: event.point,
2740
+ parentId: event.parentId
2740
2741
  });
2741
2742
  break;
2742
2743
  }
@@ -2770,7 +2771,8 @@ function parseTraceActions(traceZipPath) {
2770
2771
  inputSnapshot: event.inputSnapshot,
2771
2772
  pageId: event.pageId ?? "",
2772
2773
  error: event.error,
2773
- point: event.point
2774
+ point: event.point,
2775
+ parentId: event.parentId
2774
2776
  });
2775
2777
  break;
2776
2778
  }
@@ -2790,6 +2792,39 @@ function filterMutationActions(actions) {
2790
2792
  return !OBSERVATION_METHODS.has(method);
2791
2793
  });
2792
2794
  }
2795
+ function parseTraceGroups(traceZipPath) {
2796
+ const zip = new import_adm_zip.default(traceZipPath);
2797
+ const traceEntries = zip.getEntries().filter((e) => e.entryName.endsWith(".trace") && !e.entryName.endsWith(".network"));
2798
+ if (traceEntries.length === 0) {
2799
+ throw new Error("No .trace entries found in the zip archive");
2800
+ }
2801
+ const groups = /* @__PURE__ */ new Map();
2802
+ for (const entry of traceEntries) {
2803
+ const content = entry.getData().toString("utf-8");
2804
+ for (const line of content.split("\n")) {
2805
+ if (!line.trim()) continue;
2806
+ let event;
2807
+ try {
2808
+ event = JSON.parse(line);
2809
+ } catch {
2810
+ continue;
2811
+ }
2812
+ if (!event.callId) continue;
2813
+ if (event.type === "before" && event.method === "tracingGroup") {
2814
+ groups.set(event.callId, {
2815
+ callId: event.callId,
2816
+ name: event.title ?? "",
2817
+ startTime: event.startTime ?? 0,
2818
+ parentId: event.parentId
2819
+ });
2820
+ } else if (event.type === "after") {
2821
+ const group = groups.get(event.callId);
2822
+ if (group) group.endTime = event.endTime;
2823
+ }
2824
+ }
2825
+ }
2826
+ return [...groups.values()].sort((a, b) => a.startTime - b.startTime);
2827
+ }
2793
2828
 
2794
2829
  // ../trace-tools/src/snapshot-reconstructor.ts
2795
2830
  import { chromium } from "playwright";
@@ -2934,8 +2969,9 @@ async function loadTraceViewer() {
2934
2969
  export {
2935
2970
  parseTraceActions,
2936
2971
  filterMutationActions,
2972
+ parseTraceGroups,
2937
2973
  reconstructSnapshots,
2938
2974
  downloadTrace,
2939
2975
  cleanupTrace
2940
2976
  };
2941
- //# sourceMappingURL=chunk-52IO7ACJ.js.map
2977
+ //# sourceMappingURL=chunk-CRHPDPRS.js.map