@runcofactor/cli 0.10.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/account-22LMP5PX.js +255 -0
  2. package/dist/account-22LMP5PX.js.map +1 -0
  3. package/dist/{api-catalog-GFGCLVS4.js → api-catalog-WTFQNLK6.js} +5 -4
  4. package/dist/{api-catalog-GFGCLVS4.js.map → api-catalog-WTFQNLK6.js.map} +1 -1
  5. package/dist/{attachment-SJC7D7FY.js → attachment-U3NKVPEY.js} +5 -4
  6. package/dist/{attachment-SJC7D7FY.js.map → attachment-U3NKVPEY.js.map} +1 -1
  7. package/dist/augmentor-5GMNAX4M.js +198 -0
  8. package/dist/augmentor-5GMNAX4M.js.map +1 -0
  9. package/dist/{auth-EN6NQCJY.js → auth-VQG2CDUD.js} +3 -2
  10. package/dist/{chunk-A4OFTUVV.js → chunk-3X3NW7QA.js} +7 -4
  11. package/dist/chunk-3X3NW7QA.js.map +1 -0
  12. package/dist/{chunk-N7HFALX3.js → chunk-46IUJXSD.js} +2 -2
  13. package/dist/{chunk-IMPZAX6L.js → chunk-5GD47G2D.js} +37 -1
  14. package/dist/{chunk-IMPZAX6L.js.map → chunk-5GD47G2D.js.map} +1 -1
  15. package/dist/{chunk-B2VISN2V.js → chunk-7VMO2WOZ.js} +238 -68
  16. package/dist/chunk-7VMO2WOZ.js.map +1 -0
  17. package/dist/{chunk-QFDOWABX.js → chunk-CMGI7UZD.js} +6 -3
  18. package/dist/chunk-CMGI7UZD.js.map +1 -0
  19. package/dist/{chunk-XQXVG7RA.js → chunk-FNPMWDUQ.js} +3 -3
  20. package/dist/chunk-G4UYGRZR.js +2 -0
  21. package/dist/{chunk-I4QLI3JO.js → chunk-HDFYUFBI.js} +2 -2
  22. package/dist/chunk-JMJVGMXI.js +92 -0
  23. package/dist/chunk-JMJVGMXI.js.map +1 -0
  24. package/dist/{chunk-SJJW77WN.js → chunk-JYGNMKZ5.js} +129 -38
  25. package/dist/chunk-JYGNMKZ5.js.map +1 -0
  26. package/dist/{chunk-52IO7ACJ.js → chunk-KCHKFYVX.js} +68 -10
  27. package/dist/{chunk-52IO7ACJ.js.map → chunk-KCHKFYVX.js.map} +1 -1
  28. package/dist/{chunk-ZD3KHESI.js → chunk-KRWRUU6R.js} +27 -7
  29. package/dist/chunk-KRWRUU6R.js.map +1 -0
  30. package/dist/{chunk-CLAWT7BJ.js → chunk-NHTEKEYE.js} +3 -3
  31. package/dist/{chunk-WOHL4FTB.js → chunk-PRBRSIZP.js} +16 -10
  32. package/dist/chunk-PRBRSIZP.js.map +1 -0
  33. package/dist/{chunk-GKY2KXO5.js → chunk-UETBLPKM.js} +154 -37
  34. package/dist/chunk-UETBLPKM.js.map +1 -0
  35. package/dist/{chunk-4PNOV7OV.js → chunk-VGYN2KU2.js} +9284 -1421
  36. package/dist/chunk-VGYN2KU2.js.map +1 -0
  37. package/dist/{chunk-Q4BO4Z5V.js → chunk-XJ5YYYGC.js} +4 -4
  38. package/dist/{credential-COLTBV6D.js → credential-E6KUHRGU.js} +24 -20
  39. package/dist/credential-E6KUHRGU.js.map +1 -0
  40. package/dist/{credential-template-EEPYFG7R.js → credential-template-4GPOPBGD.js} +30 -28
  41. package/dist/credential-template-4GPOPBGD.js.map +1 -0
  42. package/dist/{debug-workflow-KOVH5GOP.js → debug-workflow-XCLCY6S7.js} +5 -4
  43. package/dist/{debug-workflow-KOVH5GOP.js.map → debug-workflow-XCLCY6S7.js.map} +1 -1
  44. package/dist/{docs-3SSORHB5.js → docs-COCZYMW6.js} +95 -10
  45. package/dist/docs-COCZYMW6.js.map +1 -0
  46. package/dist/{doctor-OTSIWV6G.js → doctor-ERIVTCQS.js} +9 -5
  47. package/dist/doctor-ERIVTCQS.js.map +1 -0
  48. package/dist/environment-7Y4BV6XY.js +221 -0
  49. package/dist/environment-7Y4BV6XY.js.map +1 -0
  50. package/dist/{feature-flag-T2LRZME3.js → feature-flag-MHONEX6T.js} +164 -16
  51. package/dist/feature-flag-MHONEX6T.js.map +1 -0
  52. package/dist/index.js +123 -58
  53. package/dist/index.js.map +1 -1
  54. package/dist/{init-TGWRECT2.js → init-OROOM4HF.js} +5 -4
  55. package/dist/{init-TGWRECT2.js.map → init-OROOM4HF.js.map} +1 -1
  56. package/dist/{install-DXSNWZKO.js → install-OJFXHY6U.js} +7 -7
  57. package/dist/{issues-XIZOPX6T.js → issues-32GONR6C.js} +5 -4
  58. package/dist/{issues-XIZOPX6T.js.map → issues-32GONR6C.js.map} +1 -1
  59. package/dist/{knobs-NBINZIUB.js → knobs-UQGGY3CP.js} +7 -5
  60. package/dist/knobs-UQGGY3CP.js.map +1 -0
  61. package/dist/{list-3TDHK637.js → list-ZMIKEC5P.js} +5 -4
  62. package/dist/{list-3TDHK637.js.map → list-ZMIKEC5P.js.map} +1 -1
  63. package/dist/{local-HICVD6PU.js → local-PUD24GGQ.js} +7 -6
  64. package/dist/{local-HICVD6PU.js.map → local-PUD24GGQ.js.map} +1 -1
  65. package/dist/{login-UOIUXVUK.js → login-BSO7YX2D.js} +5 -4
  66. package/dist/{login-UOIUXVUK.js.map → login-BSO7YX2D.js.map} +1 -1
  67. package/dist/{mcp-54IJEOUA.js → mcp-4LS7OJUT.js} +24 -25
  68. package/dist/mcp-4LS7OJUT.js.map +1 -0
  69. package/dist/{pdf-extract-ABWV3L5X.js → pdf-extract-YHE54XU4.js} +2 -2
  70. package/dist/product-3JKSJCBC.js +346 -0
  71. package/dist/product-3JKSJCBC.js.map +1 -0
  72. package/dist/{property-UXLOLPTD.js → property-K5DBL4UE.js} +76 -4
  73. package/dist/property-K5DBL4UE.js.map +1 -0
  74. package/dist/{psql-BYUUNLGG.js → psql-PQFUFTSE.js} +3 -2
  75. package/dist/{psql-BYUUNLGG.js.map → psql-PQFUFTSE.js.map} +1 -1
  76. package/dist/{record-4TR2UIIS.js → record-EIIYLFJ4.js} +16 -17
  77. package/dist/record-EIIYLFJ4.js.map +1 -0
  78. package/dist/{redis-35VBUYW7.js → redis-BU36EZZI.js} +3 -2
  79. package/dist/redis-BU36EZZI.js.map +1 -0
  80. package/dist/{release-OOLTUBUT.js → release-LYC2P7DZ.js} +5 -4
  81. package/dist/{release-OOLTUBUT.js.map → release-LYC2P7DZ.js.map} +1 -1
  82. package/dist/{sandbox-XGSUU6G7.js → sandbox-CKHXXZHU.js} +55 -10
  83. package/dist/sandbox-CKHXXZHU.js.map +1 -0
  84. package/dist/{scenarios-GWLJEGHA.js → scenarios-2XJ2G3KR.js} +5 -4
  85. package/dist/{scenarios-GWLJEGHA.js.map → scenarios-2XJ2G3KR.js.map} +1 -1
  86. package/dist/{session-MYFNZPRP.js → session-UTOD5ZYH.js} +77 -10
  87. package/dist/session-UTOD5ZYH.js.map +1 -0
  88. package/dist/{skill-KM34LDMO.js → skill-GMAERMQL.js} +220 -70
  89. package/dist/skill-GMAERMQL.js.map +1 -0
  90. package/dist/skills/debug-run/SKILL.md +40 -23
  91. package/dist/skills/debug-run/history/1.2.0.md +262 -0
  92. package/dist/skills/debug-run/history/1.3.0.md +273 -0
  93. package/dist/skills/debug-run/history/1.3.1.md +279 -0
  94. package/dist/skills/debug-run/version.json +1 -1
  95. package/dist/skills/optimize-cache/SKILL.md +233 -0
  96. package/dist/{spec-RA3CFEKG.js → spec-2NP36U3Y.js} +54 -25
  97. package/dist/spec-2NP36U3Y.js.map +1 -0
  98. package/dist/{src-LB4HBTJQ.js → src-4T6GHXVO.js} +19 -11
  99. package/dist/src-4T6GHXVO.js.map +1 -0
  100. package/dist/{src-N3TPKGTY.js → src-CG52HEE7.js} +10 -7
  101. package/dist/{src-UVDX5UP6.js → src-PK5OZXCM.js} +4 -2
  102. package/dist/src-UEOOC425.js +5941 -0
  103. package/dist/src-UEOOC425.js.map +1 -0
  104. package/dist/{start-PSEQSQA3.js → start-3C7EEFW2.js} +5 -4
  105. package/dist/{start-PSEQSQA3.js.map → start-3C7EEFW2.js.map} +1 -1
  106. package/dist/{tag-YY6YAABQ.js → tag-JSHOMLBR.js} +6 -5
  107. package/dist/{task-IQC3YR5K.js → task-YGWVYTBJ.js} +5 -4
  108. package/dist/{task-IQC3YR5K.js.map → task-YGWVYTBJ.js.map} +1 -1
  109. package/dist/{test-suite-DZNJFXDW.js → test-suite-LI7ZH367.js} +12 -7
  110. package/dist/{test-suite-DZNJFXDW.js.map → test-suite-LI7ZH367.js.map} +1 -1
  111. package/dist/trace-UMLOSIIR.js +16 -0
  112. package/dist/{triage-ORG45R5W.js → triage-ZWJG4NBJ.js} +6 -5
  113. package/dist/triage-ZWJG4NBJ.js.map +1 -0
  114. package/dist/{upgrade-L2VYMP2V.js → upgrade-S7CGEK6H.js} +3 -3
  115. package/dist/{workflow-XYFH5LTP.js → workflow-T4HSAOGW.js} +316 -241
  116. package/dist/workflow-T4HSAOGW.js.map +1 -0
  117. package/dist/{workflow-cache-NQJQFWMV.js → workflow-cache-XVEZ36KF.js} +140 -7
  118. package/dist/workflow-cache-XVEZ36KF.js.map +1 -0
  119. package/dist/{workflow-debug-BGD4UIXU.js → workflow-debug-T2BULXZ7.js} +9 -8
  120. package/dist/{workflow-debug-BGD4UIXU.js.map → workflow-debug-T2BULXZ7.js.map} +1 -1
  121. package/dist/{workflow-proposals-MTUDX46O.js → workflow-proposals-XXEZICN2.js} +5 -6
  122. package/dist/workflow-proposals-XXEZICN2.js.map +1 -0
  123. package/package.json +2 -1
  124. package/dist/chunk-4PNOV7OV.js.map +0 -1
  125. package/dist/chunk-A4OFTUVV.js.map +0 -1
  126. package/dist/chunk-B2VISN2V.js.map +0 -1
  127. package/dist/chunk-GKY2KXO5.js.map +0 -1
  128. package/dist/chunk-JICSYFRJ.js +0 -46
  129. package/dist/chunk-JICSYFRJ.js.map +0 -1
  130. package/dist/chunk-QFDOWABX.js.map +0 -1
  131. package/dist/chunk-SJJW77WN.js.map +0 -1
  132. package/dist/chunk-WOHL4FTB.js.map +0 -1
  133. package/dist/chunk-ZD3KHESI.js.map +0 -1
  134. package/dist/credential-COLTBV6D.js.map +0 -1
  135. package/dist/credential-template-EEPYFG7R.js.map +0 -1
  136. package/dist/docs-3SSORHB5.js.map +0 -1
  137. package/dist/doctor-OTSIWV6G.js.map +0 -1
  138. package/dist/feature-flag-T2LRZME3.js.map +0 -1
  139. package/dist/knobs-NBINZIUB.js.map +0 -1
  140. package/dist/mcp-54IJEOUA.js.map +0 -1
  141. package/dist/property-UXLOLPTD.js.map +0 -1
  142. package/dist/record-4TR2UIIS.js.map +0 -1
  143. package/dist/redis-35VBUYW7.js.map +0 -1
  144. package/dist/sandbox-XGSUU6G7.js.map +0 -1
  145. package/dist/session-MYFNZPRP.js.map +0 -1
  146. package/dist/skill-KM34LDMO.js.map +0 -1
  147. package/dist/spec-RA3CFEKG.js.map +0 -1
  148. package/dist/src-LB4HBTJQ.js.map +0 -1
  149. package/dist/trace-HXIW7U2D.js +0 -14
  150. package/dist/workflow-XYFH5LTP.js.map +0 -1
  151. package/dist/workflow-cache-NQJQFWMV.js.map +0 -1
  152. package/dist/workflow-proposals-MTUDX46O.js.map +0 -1
  153. /package/dist/{auth-EN6NQCJY.js.map → auth-VQG2CDUD.js.map} +0 -0
  154. /package/dist/{chunk-N7HFALX3.js.map → chunk-46IUJXSD.js.map} +0 -0
  155. /package/dist/{chunk-XQXVG7RA.js.map → chunk-FNPMWDUQ.js.map} +0 -0
  156. /package/dist/{pdf-extract-ABWV3L5X.js.map → chunk-G4UYGRZR.js.map} +0 -0
  157. /package/dist/{chunk-I4QLI3JO.js.map → chunk-HDFYUFBI.js.map} +0 -0
  158. /package/dist/{chunk-CLAWT7BJ.js.map → chunk-NHTEKEYE.js.map} +0 -0
  159. /package/dist/{chunk-Q4BO4Z5V.js.map → chunk-XJ5YYYGC.js.map} +0 -0
  160. /package/dist/{install-DXSNWZKO.js.map → install-OJFXHY6U.js.map} +0 -0
  161. /package/dist/{src-N3TPKGTY.js.map → pdf-extract-YHE54XU4.js.map} +0 -0
  162. /package/dist/{src-UVDX5UP6.js.map → src-CG52HEE7.js.map} +0 -0
  163. /package/dist/{tag-YY6YAABQ.js.map → src-PK5OZXCM.js.map} +0 -0
  164. /package/dist/{trace-HXIW7U2D.js.map → tag-JSHOMLBR.js.map} +0 -0
  165. /package/dist/{triage-ORG45R5W.js.map → trace-UMLOSIIR.js.map} +0 -0
  166. /package/dist/{upgrade-L2VYMP2V.js.map → upgrade-S7CGEK6H.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/login.ts"],"sourcesContent":["import process from \"node:process\";\nimport readline from \"node:readline\";\nimport { spawn } from \"node:child_process\";\nimport { saveAuth, ENV_URLS, envToProfile, getArgValue } from \"./auth\";\nimport { readBrandEnv } from \"./brand.js\";\n\nexport type StartResponse = {\n ok: boolean;\n deviceCode?: string;\n userCode?: string;\n verificationUrl?: string;\n expiresAt?: string;\n intervalSeconds?: number;\n error?: string;\n};\n\nexport type PollResponse = {\n ok: boolean;\n status?: \"pending\" | \"approved\" | \"rejected\" | \"expired\";\n accessToken?: string;\n orgId?: string;\n error?: string;\n};\n\nexport type OrgsResponse = {\n ok: boolean;\n currentOrgId?: string;\n organizations?: Array<{ id: string; name: string; role: string }>;\n error?: string;\n};\n\nexport type SwitchOrgResponse = {\n ok: boolean;\n accessToken?: string;\n orgId?: string;\n orgName?: string;\n role?: string;\n error?: string;\n};\n\nfunction shouldOpenBrowser(argv: string[]): boolean {\n return !argv.includes(\"--no-open\");\n}\n\nexport function openUrl(url: string) {\n const platform = process.platform;\n if (platform === \"darwin\") {\n spawn(\"open\", [url], { stdio: \"ignore\" });\n return;\n }\n if (platform === \"win32\") {\n spawn(\"cmd\", [\"/c\", \"start\", \"\", url], { stdio: \"ignore\" });\n return;\n }\n spawn(\"xdg-open\", [url], { stdio: \"ignore\" });\n}\n\nfunction promptChoice(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport async function fetchOrgs(apiUrl: string, token: string): Promise<OrgsResponse | null> {\n try {\n const res = await fetch(`${apiUrl}/cli-login/orgs`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n if (!res.ok) return null;\n return (await res.json()) as OrgsResponse;\n } catch {\n return null;\n }\n}\n\nexport async function switchOrg(apiUrl: string, token: string, orgId: string): Promise<SwitchOrgResponse> {\n const res = await fetch(`${apiUrl}/cli-login/switch-org`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ orgId }),\n });\n return (await res.json()) as SwitchOrgResponse;\n}\n\nexport async function runLogin(argv: string[]) {\n const env = getArgValue(argv, \"--env\");\n const envUrls = env ? ENV_URLS[env] : undefined;\n\n if (env && !envUrls) {\n console.error(`Unknown environment: ${env}`);\n console.error(\"Valid environments: prod, dev, local\");\n process.exit(1);\n }\n\n const apiUrl =\n getArgValue(argv, \"--api-url\") ??\n envUrls?.api ??\n readBrandEnv(\"CANARY_API_URL\") ??\n \"https://api.trycanary.ai\";\n const appUrl =\n getArgValue(argv, \"--app-url\") ??\n envUrls?.app ??\n process.env.CANARY_APP_URL ??\n \"https://app.trycanary.ai\";\n\n const orgFlag = getArgValue(argv, \"--org\");\n\n const startRes = await fetch(`${apiUrl}/cli-login/start`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ appUrl }),\n });\n\n const startJson = (await startRes.json()) as StartResponse;\n if (!startRes.ok || !startJson.ok || !startJson.deviceCode || !startJson.userCode) {\n console.error(\"Login start failed\", startJson.error ?? startRes.statusText);\n process.exit(1);\n }\n\n console.log(\"Login required.\");\n console.log(`User code: ${startJson.userCode}`);\n if (startJson.verificationUrl) {\n console.log(`Open: ${startJson.verificationUrl}`);\n if (shouldOpenBrowser(argv)) {\n try {\n openUrl(startJson.verificationUrl);\n } catch {\n console.log(\"Unable to open browser automatically. Please open the URL manually.\");\n }\n }\n }\n\n const intervalMs = (startJson.intervalSeconds ?? 3) * 1000;\n const expiresAt = startJson.expiresAt ? new Date(startJson.expiresAt).getTime() : null;\n\n let token: string | undefined;\n let initialOrgId: string | undefined;\n\n while (true) {\n if (expiresAt && Date.now() > expiresAt) {\n console.error(\"Login code expired.\");\n process.exit(1);\n }\n\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n\n const pollRes = await fetch(`${apiUrl}/cli-login/poll`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ deviceCode: startJson.deviceCode }),\n });\n\n const pollJson = (await pollRes.json()) as PollResponse;\n if (!pollRes.ok || !pollJson.ok) {\n console.error(\"Login poll failed\", pollJson.error ?? pollRes.statusText);\n process.exit(1);\n }\n\n if (pollJson.status === \"approved\" && pollJson.accessToken) {\n token = pollJson.accessToken;\n initialOrgId = pollJson.orgId;\n break;\n }\n\n if (pollJson.status === \"rejected\") {\n console.error(\"Login rejected.\");\n process.exit(1);\n }\n\n if (pollJson.status === \"expired\") {\n console.error(\"Login expired.\");\n process.exit(1);\n }\n }\n\n // Fetch user's organizations (gracefully skip if endpoint not available)\n const orgsData = await fetchOrgs(apiUrl, token);\n const orgs = orgsData?.organizations ?? [];\n\n let finalToken = token;\n let finalOrgId = initialOrgId;\n let finalOrgName: string | undefined;\n\n if (orgs.length <= 1) {\n // Single org (or none) — use as-is\n finalOrgName = orgs[0]?.name;\n } else {\n // Multiple orgs — determine which one to use\n let selectedOrg: (typeof orgs)[number] | undefined;\n\n if (orgFlag) {\n // Match --org flag by name (case-insensitive) or ID\n selectedOrg = orgs.find(\n (o) => o.name.toLowerCase() === orgFlag.toLowerCase() || o.id === orgFlag\n );\n if (!selectedOrg) {\n console.error(`Organization \"${orgFlag}\" not found. Available orgs:`);\n for (const o of orgs) {\n console.error(` - ${o.name} (${o.id})`);\n }\n process.exit(1);\n }\n } else if (process.stdin.isTTY) {\n // Interactive prompt\n console.log(\"\\nYou belong to multiple organizations. Select one:\");\n for (let i = 0; i < orgs.length; i++) {\n const marker = orgs[i].id === initialOrgId ? \" (current)\" : \"\";\n console.log(` ${i + 1}. ${orgs[i].name}${marker}`);\n }\n\n const answer = await promptChoice(`\\nChoice [1-${orgs.length}]: `);\n const idx = parseInt(answer, 10) - 1;\n if (isNaN(idx) || idx < 0 || idx >= orgs.length) {\n console.error(\"Invalid selection.\");\n process.exit(1);\n }\n selectedOrg = orgs[idx];\n } else {\n // Non-interactive — use default from JWT\n const defaultOrg = orgs.find((o) => o.id === initialOrgId);\n console.log(\n `Warning: Multiple organizations available but running non-interactively. Using \"${defaultOrg?.name ?? initialOrgId}\".`\n );\n console.log('Tip: Use --org <name> to select a specific organization.');\n selectedOrg = defaultOrg;\n }\n\n if (selectedOrg && selectedOrg.id !== initialOrgId) {\n // Switch to selected org\n const switchRes = await switchOrg(apiUrl, token, selectedOrg.id);\n if (!switchRes.ok || !switchRes.accessToken) {\n console.error(\"Failed to switch organization:\", switchRes.error ?? \"Unknown error\");\n process.exit(1);\n }\n finalToken = switchRes.accessToken;\n finalOrgId = switchRes.orgId;\n finalOrgName = switchRes.orgName;\n } else if (selectedOrg) {\n finalOrgName = selectedOrg.name;\n }\n }\n\n const profileName = env ? envToProfile(env) : undefined;\n const filePath = await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: finalOrgName }, profileName);\n const displayName = finalOrgName ? ` to ${finalOrgName}` : \"\";\n const profileLabel = profileName ? ` (profile: ${profileName})` : \"\";\n console.log(`Login successful${displayName}${profileLabel}. Token saved to ${filePath}`);\n console.log(\"Set CANARY_API_TOKEN to use the CLI without re-login.\");\n}\n"],"mappings":"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","names":[]}
@@ -1,12 +1,12 @@
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";
4
+ } from "./chunk-PRBRSIZP.js";
5
5
  import {
6
6
  getArgValue,
7
7
  hasFlag,
8
8
  resolveConfig
9
- } from "./chunk-A4OFTUVV.js";
9
+ } from "./chunk-3X3NW7QA.js";
10
10
 
11
11
  // src/tag.ts
12
12
  import process from "process";
@@ -423,4 +423,4 @@ export {
423
423
  applyWorkflowTagFlags,
424
424
  runTag
425
425
  };
426
- //# sourceMappingURL=chunk-XQXVG7RA.js.map
426
+ //# sourceMappingURL=chunk-FNPMWDUQ.js.map
@@ -0,0 +1,2 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+ //# sourceMappingURL=chunk-G4UYGRZR.js.map
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
2
  import {
3
3
  PlaywrightClient
4
- } from "./chunk-4PNOV7OV.js";
4
+ } from "./chunk-VGYN2KU2.js";
5
5
 
6
6
  // src/local-browser/host.ts
7
7
  var HEARTBEAT_INTERVAL_MS = 3e4;
@@ -410,4 +410,4 @@ export {
410
410
  LocalBrowserHost,
411
411
  USER_PAUSED_ERROR
412
412
  };
413
- //# sourceMappingURL=chunk-I4QLI3JO.js.map
413
+ //# sourceMappingURL=chunk-HDFYUFBI.js.map
@@ -0,0 +1,92 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+
3
+ // src/brand.ts
4
+ import { createRequire } from "module";
5
+ import path from "path";
6
+ import process from "process";
7
+ var require2 = createRequire(import.meta.url);
8
+ var pkg = require2("../package.json");
9
+ function resolveBrandFromArgv(argv1) {
10
+ if (argv1) {
11
+ const base = path.basename(argv1).replace(/\.[^./\\]+$/, "").toLowerCase();
12
+ if (base.includes("cofactor")) return "cofactor";
13
+ }
14
+ return "canary";
15
+ }
16
+ var command = resolveBrandFromArgv(process.argv[1]);
17
+ var packageName = pkg.name;
18
+ var version = pkg.version;
19
+ var INVOCATION_RE = /(^|[^\w-])canary(?= [a-z])/g;
20
+ var PROSE_RE = /\bCanary\b/g;
21
+ function brandTextFor(text, brand) {
22
+ if (brand === "canary") return text;
23
+ const display = brand === "cofactor" ? "Cofactor" : "Canary";
24
+ return text.replace(INVOCATION_RE, (_m, prefix) => `${prefix}${brand}`).replace(PROSE_RE, display);
25
+ }
26
+ function brandText(text) {
27
+ return brandTextFor(text, command);
28
+ }
29
+ function brandSkillContentFor(content, brand) {
30
+ const base = brandTextFor(content, brand);
31
+ if (brand !== "cofactor") return base;
32
+ return base.replace(/`canary`/g, "`cofactor`").replace(/@canaryai\/cli/g, "@runcofactor/cli").replace(/\bCANARY_/g, "COFACTOR_").replace(/trycanary\.ai/g, "runcofactor.com");
33
+ }
34
+ function readBrandEnvFor(canaryName, brand, env = process.env) {
35
+ const cofactorName = canaryName.replace(/^CANARY_/, "COFACTOR_");
36
+ const order = brand === "cofactor" ? [cofactorName, canaryName] : [canaryName, cofactorName];
37
+ for (const name of order) {
38
+ const value = env[name];
39
+ if (value !== null && value !== void 0 && value !== "") return value;
40
+ }
41
+ return void 0;
42
+ }
43
+ function readBrandEnv(canaryName, env = process.env) {
44
+ return readBrandEnvFor(canaryName, command, env);
45
+ }
46
+ var SPEC_EXTENSIONS = [".cofactor.md", ".canary.md"];
47
+ var SPEC_DIRS = ["cofactor", "canary"];
48
+ function specExtensionFor(brand) {
49
+ return brand === "cofactor" ? ".cofactor.md" : ".canary.md";
50
+ }
51
+ function specDirFor(brand) {
52
+ return path.join(brand === "cofactor" ? "cofactor" : "canary", "specs");
53
+ }
54
+ var specExtension = specExtensionFor(command);
55
+ var specDir = specDirFor(command);
56
+ function readableSpecDirs() {
57
+ return SPEC_DIRS.map((root) => path.join(root, "specs"));
58
+ }
59
+ function isSpecFile(name) {
60
+ return SPEC_EXTENSIONS.some((ext) => name.endsWith(ext));
61
+ }
62
+ function splitSpecExtension(name) {
63
+ for (const ext of SPEC_EXTENSIONS) {
64
+ if (name.endsWith(ext)) return { base: name.slice(0, -ext.length), ext };
65
+ }
66
+ return null;
67
+ }
68
+ function installConsoleBranding() {
69
+ if (command === "canary") return;
70
+ const methods = ["log", "error", "warn", "info"];
71
+ for (const method of methods) {
72
+ const original = console[method].bind(console);
73
+ console[method] = (...args) => {
74
+ original(...args.map((arg) => typeof arg === "string" ? brandText(arg) : arg));
75
+ };
76
+ }
77
+ }
78
+
79
+ export {
80
+ command,
81
+ packageName,
82
+ version,
83
+ brandSkillContentFor,
84
+ readBrandEnv,
85
+ specExtension,
86
+ specDir,
87
+ readableSpecDirs,
88
+ isSpecFile,
89
+ splitSpecExtension,
90
+ installConsoleBranding
91
+ };
92
+ //# sourceMappingURL=chunk-JMJVGMXI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/brand.ts"],"sourcesContent":["/**\n * Brand resolution for the dual-published CLI.\n *\n * We ship a single build to two npm packages:\n * - `@canaryai/cli` → binary `canary` (legacy brand)\n * - `@runcofactor/cli` → binary `cofactor` (new brand)\n *\n * Both packages contain the identical artifact; they differ only in their\n * `name` and `bin` map (rewritten at publish time — see\n * `.github/workflows/publish-canary-cli.yml`). Everything brand-specific is\n * therefore derived at runtime:\n *\n * - `command` comes from the invoked binary name (`basename(process.argv[1])`),\n * so output reflects how the user called it (`brandText` rewrites legacy\n * `canary` display strings to the active brand).\n * - `packageName` comes from the installed package's own `package.json`, so\n * self-upgrade and the update check target whatever package was installed.\n *\n * The legacy `canary` brand is the default for every non-`cofactor` invocation\n * (`node dist/index.js`, dev scripts, tests), which keeps existing behaviour\n * byte-for-byte unchanged.\n *\n * @module\n */\n\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport process from 'node:process';\n\nconst require = createRequire(import.meta.url);\nconst pkg = require('../package.json') as { name: string; version: string };\n\nexport type Brand = 'canary' | 'cofactor';\n\n/**\n * Resolve the brand from the invoked binary path (`process.argv[1]`). The\n * global-install shim is named `canary` or `cofactor` (npm/bun/pnpm bin link),\n * so the basename is the brand. Everything else (`node dist/index.js`, dev\n * scripts, tests) defaults to the legacy `canary` brand. Pure for testing.\n */\nexport function resolveBrandFromArgv(argv1: string | undefined): Brand {\n if (argv1) {\n const base = path.basename(argv1).replace(/\\.[^./\\\\]+$/, '').toLowerCase();\n if (base.includes('cofactor')) return 'cofactor';\n }\n return 'canary';\n}\n\n/** The invoked command / binary name, e.g. `canary` or `cofactor`. */\nexport const command: Brand = resolveBrandFromArgv(process.argv[1]);\n\n/** npm package name of the installed CLI, read from its own package.json. */\nexport const packageName: string = pkg.name;\n\n/** CLI version, read from package.json. */\nexport const version: string = pkg.version;\n\n/**\n * Rewrite display strings authored against the legacy `canary` brand to the\n * active brand. Identity for the `canary` brand (so legacy output never\n * changes). Two precise, word-anchored rules:\n *\n * 1. The invocation token `canary ` followed by a lowercase letter (i.e. a\n * sub-command or `canary v1.2.3`). Anchored on a non-word, non-hyphen\n * boundary so it never touches `trycanary.ai`, `x-canary-request-id`,\n * `canary-cli`, or `CANARY_API_TOKEN`.\n * 2. The prose noun `Canary` (capitalized, standalone word) → display name.\n */\nconst INVOCATION_RE = /(^|[^\\w-])canary(?= [a-z])/g;\nconst PROSE_RE = /\\bCanary\\b/g;\n\n/** Pure brand rewrite for a given target brand. Identity for `canary`. */\nexport function brandTextFor(text: string, brand: Brand): string {\n if (brand === 'canary') return text;\n const display = brand === 'cofactor' ? 'Cofactor' : 'Canary';\n return text\n .replace(INVOCATION_RE, (_m, prefix: string) => `${prefix}${brand}`)\n .replace(PROSE_RE, display);\n}\n\nfunction brandText(text: string): string {\n return brandTextFor(text, command);\n}\n\n/**\n * Rewrite a bundled skill template's content to the target brand for the\n * `canary skill install` / `canary skill <name>` output. Builds on\n * {@link brandTextFor} (invocation tokens + the prose noun) and additionally\n * maps the brand-specific identifiers that {@link brandTextFor} deliberately\n * leaves intact for console output — but which a distributed skill file must\n * carry per brand:\n *\n * - inline binary: `` `canary` `` → `` `cofactor` `` (a backtick-wrapped bare\n * binary reference, e.g. \"the `canary` CLI\" — `brandTextFor` only rewrites\n * `canary <subcommand>` invocations, not the standalone binary name)\n * - npm package: `@canaryai/cli` → `@runcofactor/cli`\n * - env prefix: `CANARY_*` → `COFACTOR_*`\n * - domains: `*.trycanary.ai` → `*.runcofactor.com`\n *\n * Identity for the `canary` brand, so legacy skill text installs byte-for-byte\n * unchanged. The skill's frontmatter `name:` is never an invocation/prose/token\n * match (it's `canary-basic`, hyphenated), so the install directory key is\n * preserved. Trigger keywords in prose (e.g. \"mentions canary, canary CLI\")\n * intentionally keep the legacy term so the skill still activates for users who\n * say \"canary\". Pure (brand injectable).\n */\nexport function brandSkillContentFor(content: string, brand: Brand): string {\n const base = brandTextFor(content, brand);\n if (brand !== 'cofactor') return base;\n return base\n .replace(/`canary`/g, '`cofactor`')\n .replace(/@canaryai\\/cli/g, '@runcofactor/cli')\n .replace(/\\bCANARY_/g, 'COFACTOR_')\n .replace(/trycanary\\.ai/g, 'runcofactor.com');\n}\n\n/**\n * Read a brand-prefixed environment variable, accepting EITHER brand's prefix.\n *\n * The two published brands historically diverged: the binary only ever read the\n * legacy `CANARY_*` names, but the cofactor docs tell users to set `COFACTOR_*`\n * (e.g. `COFACTOR_API_TOKEN`). This bridges that gap — a value set under either\n * prefix is honoured regardless of which binary (`canary` / `cofactor`) was\n * invoked. When both are set, the active brand's prefix wins.\n *\n * `canaryName` is the legacy `CANARY_`-prefixed name; the `COFACTOR_` variant is\n * derived from it. Empty strings are treated as unset so a blank value can't\n * shadow a real one set under the other prefix. Pure (brand + env injectable).\n */\nexport function readBrandEnvFor(\n canaryName: string,\n brand: Brand,\n env: NodeJS.ProcessEnv = process.env,\n): string | undefined {\n const cofactorName = canaryName.replace(/^CANARY_/, 'COFACTOR_');\n const order = brand === 'cofactor' ? [cofactorName, canaryName] : [canaryName, cofactorName];\n for (const name of order) {\n const value = env[name];\n if (value !== null && value !== undefined && value !== '') return value;\n }\n return undefined;\n}\n\n/** Read a brand-prefixed env var for the active brand. See {@link readBrandEnvFor}. */\nexport function readBrandEnv(\n canaryName: string,\n env: NodeJS.ProcessEnv = process.env,\n): string | undefined {\n return readBrandEnvFor(canaryName, command, env);\n}\n\n/**\n * Workflow spec file convention — brand-aware, backwards compatible.\n *\n * The spec extension and default directory follow the active brand: the\n * `cofactor` binary writes `.cofactor.md` into `cofactor/specs`, the legacy\n * `canary` binary writes `.canary.md` into `canary/specs` (byte-for-byte\n * unchanged). Reading/discovery always accepts BOTH — {@link SPEC_EXTENSIONS}\n * and {@link SPEC_DIRS} list every recognized variant (newest brand first), so\n * an existing `.canary.md` repo keeps working under either binary.\n */\nexport const SPEC_EXTENSIONS = ['.cofactor.md', '.canary.md'] as const;\n\n/**\n * Default spec-directory roots, newest brand first. Each is used as\n * `<root>/specs`. The ordering is a precedence contract: consumers that merge\n * across roots (e.g. `pull --all`) must treat earlier entries as higher\n * priority, so the active/new brand's copy wins over a legacy one.\n */\nexport const SPEC_DIRS = ['cofactor', 'canary'] as const;\n\n/** Spec-file extension to WRITE for a given brand. See {@link SPEC_EXTENSIONS}. */\nexport function specExtensionFor(brand: Brand): string {\n return brand === 'cofactor' ? '.cofactor.md' : '.canary.md';\n}\n\n/** Default spec directory (`<root>/specs`) to WRITE into for a given brand. */\nexport function specDirFor(brand: Brand): string {\n return path.join(brand === 'cofactor' ? 'cofactor' : 'canary', 'specs');\n}\n\n/** Spec-file extension to WRITE for the active brand. See {@link specExtensionFor}. */\nexport const specExtension: string = specExtensionFor(command);\n\n/** Default spec directory to WRITE into for the active brand. See {@link specDirFor}. */\nexport const specDir: string = specDirFor(command);\n\n/**\n * Every spec directory to READ from, highest precedence first — `<root>/specs`\n * for each {@link SPEC_DIRS} root. This is the single source of the spec-dir\n * convention for discovery; consumers merge across these in order (first-seen\n * wins) so the active brand's copy beats a legacy one. Brand-independent: a\n * `cofactor` run still discovers an existing `canary/specs` repo, and vice\n * versa.\n */\nexport function readableSpecDirs(): string[] {\n return SPEC_DIRS.map((root) => path.join(root, 'specs'));\n}\n\n/** True if `name` ends with any recognized spec extension (either brand). */\nexport function isSpecFile(name: string): boolean {\n return SPEC_EXTENSIONS.some((ext) => name.endsWith(ext));\n}\n\n/**\n * Split a recognized spec extension off `name`, returning `{ base, ext }` for\n * the first matching {@link SPEC_EXTENSIONS} entry, or `null` if none match.\n * Lets callers derive sibling names (e.g. `.stamped`) without assuming a brand.\n */\nexport function splitSpecExtension(name: string): { base: string; ext: string } | null {\n for (const ext of SPEC_EXTENSIONS) {\n if (name.endsWith(ext)) return { base: name.slice(0, -ext.length), ext };\n }\n return null;\n}\n\n/**\n * Install brand rewriting over the `console` methods used for human-readable\n * output. No-op for the `canary` brand. Skipped by the caller for machine\n * output (`--json`/`--format`) and the `mcp` JSON-RPC transport, where rewriting\n * could corrupt structured payloads — display branding only.\n */\nexport function installConsoleBranding(): void {\n if (command === 'canary') return;\n const methods = ['log', 'error', 'warn', 'info'] as const;\n for (const method of methods) {\n const original = console[method].bind(console);\n console[method] = (...args: unknown[]) => {\n original(...args.map((arg) => (typeof arg === 'string' ? brandText(arg) : arg)));\n };\n }\n}\n"],"mappings":";;;AAyBA,SAAS,qBAAqB;AAC9B,OAAO,UAAU;AACjB,OAAO,aAAa;AAEpB,IAAMA,WAAU,cAAc,YAAY,GAAG;AAC7C,IAAM,MAAMA,SAAQ,iBAAiB;AAU9B,SAAS,qBAAqB,OAAkC;AACrE,MAAI,OAAO;AACT,UAAM,OAAO,KAAK,SAAS,KAAK,EAAE,QAAQ,eAAe,EAAE,EAAE,YAAY;AACzE,QAAI,KAAK,SAAS,UAAU,EAAG,QAAO;AAAA,EACxC;AACA,SAAO;AACT;AAGO,IAAM,UAAiB,qBAAqB,QAAQ,KAAK,CAAC,CAAC;AAG3D,IAAM,cAAsB,IAAI;AAGhC,IAAM,UAAkB,IAAI;AAanC,IAAM,gBAAgB;AACtB,IAAM,WAAW;AAGV,SAAS,aAAa,MAAc,OAAsB;AAC/D,MAAI,UAAU,SAAU,QAAO;AAC/B,QAAM,UAAU,UAAU,aAAa,aAAa;AACpD,SAAO,KACJ,QAAQ,eAAe,CAAC,IAAI,WAAmB,GAAG,MAAM,GAAG,KAAK,EAAE,EAClE,QAAQ,UAAU,OAAO;AAC9B;AAEA,SAAS,UAAU,MAAsB;AACvC,SAAO,aAAa,MAAM,OAAO;AACnC;AAwBO,SAAS,qBAAqB,SAAiB,OAAsB;AAC1E,QAAM,OAAO,aAAa,SAAS,KAAK;AACxC,MAAI,UAAU,WAAY,QAAO;AACjC,SAAO,KACJ,QAAQ,aAAa,YAAY,EACjC,QAAQ,mBAAmB,kBAAkB,EAC7C,QAAQ,cAAc,WAAW,EACjC,QAAQ,kBAAkB,iBAAiB;AAChD;AAeO,SAAS,gBACd,YACA,OACA,MAAyB,QAAQ,KACb;AACpB,QAAM,eAAe,WAAW,QAAQ,YAAY,WAAW;AAC/D,QAAM,QAAQ,UAAU,aAAa,CAAC,cAAc,UAAU,IAAI,CAAC,YAAY,YAAY;AAC3F,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,IAAI,IAAI;AACtB,QAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,GAAI,QAAO;AAAA,EACpE;AACA,SAAO;AACT;AAGO,SAAS,aACd,YACA,MAAyB,QAAQ,KACb;AACpB,SAAO,gBAAgB,YAAY,SAAS,GAAG;AACjD;AAYO,IAAM,kBAAkB,CAAC,gBAAgB,YAAY;AAQrD,IAAM,YAAY,CAAC,YAAY,QAAQ;AAGvC,SAAS,iBAAiB,OAAsB;AACrD,SAAO,UAAU,aAAa,iBAAiB;AACjD;AAGO,SAAS,WAAW,OAAsB;AAC/C,SAAO,KAAK,KAAK,UAAU,aAAa,aAAa,UAAU,OAAO;AACxE;AAGO,IAAM,gBAAwB,iBAAiB,OAAO;AAGtD,IAAM,UAAkB,WAAW,OAAO;AAU1C,SAAS,mBAA6B;AAC3C,SAAO,UAAU,IAAI,CAAC,SAAS,KAAK,KAAK,MAAM,OAAO,CAAC;AACzD;AAGO,SAAS,WAAW,MAAuB;AAChD,SAAO,gBAAgB,KAAK,CAAC,QAAQ,KAAK,SAAS,GAAG,CAAC;AACzD;AAOO,SAAS,mBAAmB,MAAoD;AACrF,aAAW,OAAO,iBAAiB;AACjC,QAAI,KAAK,SAAS,GAAG,EAAG,QAAO,EAAE,MAAM,KAAK,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,IAAI;AAAA,EACzE;AACA,SAAO;AACT;AAQO,SAAS,yBAA+B;AAC7C,MAAI,YAAY,SAAU;AAC1B,QAAM,UAAU,CAAC,OAAO,SAAS,QAAQ,MAAM;AAC/C,aAAW,UAAU,SAAS;AAC5B,UAAM,WAAW,QAAQ,MAAM,EAAE,KAAK,OAAO;AAC7C,YAAQ,MAAM,IAAI,IAAI,SAAoB;AACxC,eAAS,GAAG,KAAK,IAAI,CAAC,QAAS,OAAO,QAAQ,WAAW,UAAU,GAAG,IAAI,GAAI,CAAC;AAAA,IACjF;AAAA,EACF;AACF;","names":["require"]}
@@ -3,7 +3,7 @@ import { createRequire as __cr } from "module"; const require = __cr(import.meta
3
3
  // ../types/src/workflows.ts
4
4
  var USER_SETTABLE_WORKFLOW_STATUSES = [
5
5
  "draft",
6
- "published"
6
+ "approved"
7
7
  ];
8
8
 
9
9
  // ../types/src/sandbox-instance-size.ts
@@ -86,6 +86,7 @@ var NODE_TYPE_LABEL = {
86
86
  notification: "Notification",
87
87
  audio: "Audio input",
88
88
  "audio-assertion": "Audio assertion",
89
+ sandbox_action: "Sandbox action",
89
90
  end: "End"
90
91
  };
91
92
  function normalizeNodeType(input) {
@@ -94,7 +95,7 @@ function normalizeNodeType(input) {
94
95
  }
95
96
 
96
97
  // ../types/src/index.ts
97
- import { z as z5 } from "zod";
98
+ import { z as z6 } from "zod";
98
99
 
99
100
  // ../types/src/credentials.ts
100
101
  import { z } from "zod";
@@ -171,11 +172,6 @@ var TLDR_LIMIT = 512;
171
172
  var URL_LIMIT = 2048;
172
173
  var STORAGE_KEY_LIMIT = 1024;
173
174
  var DIAGNOSTIC_LIMIT = 4e3;
174
- var NarrationTranscriptSegmentSchema = z2.object({
175
- startMs: z2.number().int().min(0),
176
- endMs: z2.number().int().min(1),
177
- text: z2.string().min(1)
178
- });
179
175
  var RecordIssueOccurrencePayloadSchema = z2.object({
180
176
  orgId: UUID,
181
177
  propertyId: UUID,
@@ -205,8 +201,6 @@ var RecordIssueOccurrencePayloadSchema = z2.object({
205
201
  videoStorageKey: optionalLimitedString(STORAGE_KEY_LIMIT),
206
202
  /** Action timeline for video overlay synchronization */
207
203
  videoTimelineJson: z2.unknown().optional().nullable(),
208
- /** Timed narration transcript for video overlay */
209
- narrationTranscriptJson: z2.array(NarrationTranscriptSegmentSchema).optional().nullable(),
210
204
  consoleLogExcerpt: optionalLimitedString(DIAGNOSTIC_LIMIT),
211
205
  networkFailureUrl: optionalLimitedString(URL_LIMIT),
212
206
  networkFailureStatus: z2.number().int().optional().nullable().transform((value) => value ?? null),
@@ -231,6 +225,21 @@ var benchmarkWorkflowSuiteConfigSchema = z3.object({
231
225
  sendSlackSummary: z3.boolean().optional()
232
226
  });
233
227
 
228
+ // ../types/src/api-sequence.ts
229
+ import { z as z4 } from "zod";
230
+ var ValidationOperatorSchema = z4.enum([
231
+ "equals",
232
+ "not_equals",
233
+ "gt",
234
+ "lt",
235
+ "gte",
236
+ "lte",
237
+ "contains",
238
+ "not_contains",
239
+ "is_set",
240
+ "is_not_set"
241
+ ]);
242
+
234
243
  // ../types/src/sandbox-tasks.ts
235
244
  var CHECKLIST_ITEMS = [
236
245
  {
@@ -439,13 +448,14 @@ var MACRO_CATALOG = [
439
448
  ];
440
449
  var VALID_MACRO_NAMES = new Set(MACRO_CATALOG.map((m) => m.name));
441
450
  var MACRO_ARG_COUNTS = new Map(MACRO_CATALOG.map((m) => [m.name, m.args.length]));
451
+ var MACRO_PATTERN = /(?<!\\)\$([A-Z_]+)\(([^)]*)\)/g;
442
452
 
443
453
  // ../types/src/workflow-node-schemas.ts
444
- import { z as z4 } from "zod";
445
- var FormFieldSchema = z4.object({
446
- name: z4.string().describe('Unique field identifier (snake_case, e.g., "search_query", "recipient_email")'),
447
- label: z4.string().describe('Human-friendly label (e.g., "Search Query", "Recipient Email")'),
448
- type: z4.enum([
454
+ import { z as z5 } from "zod";
455
+ var FormFieldSchema = z5.object({
456
+ name: z5.string().describe('Unique field identifier (snake_case, e.g., "search_query", "recipient_email")'),
457
+ label: z5.string().describe('Human-friendly label (e.g., "Search Query", "Recipient Email")'),
458
+ type: z5.enum([
449
459
  "text",
450
460
  "email",
451
461
  "password",
@@ -456,16 +466,38 @@ var FormFieldSchema = z4.object({
456
466
  "multiselect",
457
467
  "file"
458
468
  ]).optional().describe('Input type, defaults to "text"'),
459
- required: z4.boolean().optional().describe("Whether this field is required"),
460
- value: z4.string().describe("The value to use for this field"),
461
- options: z4.array(z4.object({ value: z4.string(), label: z4.string() })).optional().describe("If type is select/multiselect, provide allowed options here")
469
+ required: z5.boolean().optional().describe("Whether this field is required"),
470
+ value: z5.string().describe("The value to use for this field"),
471
+ options: z5.array(z5.object({ value: z5.string(), label: z5.string() })).optional().describe("If type is select/multiselect, provide allowed options here")
472
+ });
473
+ var AssertionSeverityEnum = z5.enum(["warn", "fail", "fatal"]);
474
+ var InlineAssertionSchema = z5.object({
475
+ condition: z5.string().describe("What to verify after the action"),
476
+ severity: AssertionSeverityEnum.describe(
477
+ "fatal = stop the test immediately on failure, fail = mark the run failed but keep going, warn = log a warning and continue (run still passes)"
478
+ ),
479
+ agentic: z5.boolean().optional().describe("true if requires visual/complex evaluation that cannot be cached")
462
480
  });
463
- var InlineAssertionSchema = z4.object({
464
- condition: z4.string().describe("What to verify after the action"),
465
- severity: z4.enum(["warn", "fail"]).describe("warn = log and continue on failure, fail = stop the test"),
466
- agentic: z4.boolean().optional().describe("true if requires visual/complex evaluation that cannot be cached")
481
+ var ConditionSubjectSchema = z5.discriminatedUnion("kind", [
482
+ z5.object({
483
+ kind: z5.literal("variable"),
484
+ name: z5.string().describe('Input/variable name, e.g. "count" for $var.count')
485
+ }),
486
+ z5.object({
487
+ kind: z5.literal("acting_as")
488
+ })
489
+ ]);
490
+ var ConditionPredicateSchema = z5.object({
491
+ subject: ConditionSubjectSchema,
492
+ operator: ValidationOperatorSchema,
493
+ /**
494
+ * Right-hand operand. For a `variable` subject this is a literal (or `$var`
495
+ * reference); for `acting_as` it is a credential template id. Omitted for the
496
+ * unary operators `is_set` / `is_not_set`.
497
+ */
498
+ value: z5.string().optional()
467
499
  });
468
- var NodeTypeEnum = z4.enum([
500
+ var NodeTypeEnum = z5.enum([
469
501
  "login",
470
502
  "navigate",
471
503
  "action",
@@ -478,7 +510,8 @@ var NodeTypeEnum = z4.enum([
478
510
  "end",
479
511
  "notification",
480
512
  "audio",
481
- "audio-assertion"
513
+ "audio-assertion",
514
+ "sandbox_action"
482
515
  ]);
483
516
 
484
517
  // ../types/src/browser-viewport.ts
@@ -493,6 +526,60 @@ var BROWSER_VIEWPORT_PRESET_KEYS = Object.keys(
493
526
  BROWSER_VIEWPORT_PRESETS
494
527
  );
495
528
 
529
+ // ../types/src/identifier-stability.ts
530
+ var FRAMEWORK_PREFIX_RE = /^(?::r[0-9a-z]+:?$|radix-|headlessui-|mantine-|react-aria-|react-select-|rc-|menu-v-\d)/i;
531
+ var BARE_HASH_RE = /^[a-f0-9]{8,}$/i;
532
+ var PREFIX_HASH_RE = /^[a-z]+-[0-9a-f]{6,}$/i;
533
+ var UUID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
534
+ var ULID_RE = /\b[0-9A-HJKMNP-TV-Z]{26}\b/i;
535
+ var DIGIT_RUN_RE = /(?:^|[^0-9A-Za-z])(\d{6,})(?![0-9A-Za-z])/;
536
+ var TRAILING_COUNTER_RE = /[-_](\d{3,})$/;
537
+ var MIN_PREFIX_LEN = 3;
538
+ function usablePrefix(prefix) {
539
+ return prefix.length >= MIN_PREFIX_LEN && /[a-z]/i.test(prefix);
540
+ }
541
+ function earliestVolatileTokenIndex(value) {
542
+ let best = null;
543
+ const consider = (idx) => {
544
+ if (idx !== void 0 && idx >= 0 && (best === null || idx < best)) best = idx;
545
+ };
546
+ consider(UUID_RE.exec(value)?.index);
547
+ consider(ULID_RE.exec(value)?.index);
548
+ const digit = DIGIT_RUN_RE.exec(value);
549
+ if (digit) consider(digit.index + (digit[0].length - digit[1].length));
550
+ const counter = TRAILING_COUNTER_RE.exec(value);
551
+ if (counter) consider(counter.index + 1);
552
+ return best;
553
+ }
554
+ function classifyIdentifier(value) {
555
+ if (!value) return { kind: "volatile" };
556
+ if (FRAMEWORK_PREFIX_RE.test(value) || BARE_HASH_RE.test(value) || PREFIX_HASH_RE.test(value)) {
557
+ return { kind: "volatile" };
558
+ }
559
+ const tokenIdx = earliestVolatileTokenIndex(value);
560
+ if (tokenIdx !== null) {
561
+ const prefix = value.slice(0, tokenIdx);
562
+ return usablePrefix(prefix) ? { kind: "stable-prefix", prefix } : { kind: "volatile" };
563
+ }
564
+ return { kind: "stable" };
565
+ }
566
+ function isVolatileIdentifier(value) {
567
+ return classifyIdentifier(value).kind !== "stable";
568
+ }
569
+ function stableIdentifierPrefix(value) {
570
+ const c = classifyIdentifier(value);
571
+ return c.kind === "stable-prefix" ? c.prefix : null;
572
+ }
573
+ function escapeCssAttrValue(value) {
574
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
575
+ }
576
+ function stableAttrSelector(attr, value) {
577
+ const c = classifyIdentifier(value);
578
+ if (c.kind === "stable") return `[${attr}="${escapeCssAttrValue(value)}"]`;
579
+ if (c.kind === "stable-prefix") return `[${attr}^="${escapeCssAttrValue(c.prefix)}"]`;
580
+ return null;
581
+ }
582
+
496
583
  // ../types/src/index.ts
497
584
  var PLAYBOOK_STEP_ACTIONS = [
498
585
  "click",
@@ -520,24 +607,24 @@ function isPositiveIntegerString(value) {
520
607
  if (!value || !/^\d+$/.test(value)) return false;
521
608
  return Number(value) > 0;
522
609
  }
523
- var playbookStepAgentSchema = z5.object({
524
- order: z5.number().describe("Step number (1-based)."),
525
- action: z5.enum(PLAYBOOK_STEP_ACTIONS).describe(
610
+ var playbookStepAgentSchema = z6.object({
611
+ order: z6.number().describe("Step number (1-based)."),
612
+ action: z6.enum(PLAYBOOK_STEP_ACTIONS).describe(
526
613
  'The type of browser interaction. PREFER DETERMINISTIC VERBS even when verbose \u2014 three deterministic steps beat one agentic step, because deterministic steps replay via Playwright with no agent dispatch. Each replayable playbook step must be 1:1 with an exposed browser tool you actually used and must correspond to zero or one recorded actionRef. If you cannot accomplish the intent with the browser tools you have, do not add a playbook step for it; report the limitation outside playbookSteps. Do not summarize several recorded actions into one "other" step; report the same 1:1 browser primitives you actually used. The only multi-field exception is one fill_form step for one browser_fill_form action. Use "verify" for assertion checks \u2014 both inline assertions and completion assertions proving the action succeeded. Use "verify" for inspection language such as "inspect whether", "confirm", "observe", or "check" when the result is visible in the DOM. Use "capture" instead only when the observed value is needed by later steps. Use "fill" for single-field inputs. Use "fill_form" when browser_fill_form was called to fill multiple fields at once \u2014 one fill_form step per call. Use "click" for checkboxes, switches, toggle buttons, and click-to-focus interactions. There is no separate "toggle" or "focus" action. Use "upload" for file upload actions, including generated CSV/file, attach file, choose file, import file, and document/image attachment intents (browser_action action="upload"). Set params.path to the staged attachment handle, generated file variable, or filename reference used by the upload tool (e.g. {path: "$var.csv_file"}), and include actionRefs pointing to the recorded file_upload action. Do NOT use "other" for file attachment/upload/import intents. Use "scroll" only when scrolling is the user-visible action being tested; routine browser_scroll calls for visibility, inspection, or video framing are observation steps and should usually be omitted from playbookSteps. Use "press_key" for keyboard actions (Enter, Escape, Tab, arrows). Use "press_key" with params.key="Escape" to dismiss a popover, dropdown, panel, or modal when Escape was the recorded action; use "click" if the recorded action clicked a close button or outside target. There is no separate "dismiss" action. Use "drag" for drag-and-drop interactions. Use "resize" when browser_resize was used to resize the viewport. Set params.width and params.height to positive integer pixel values and include the actionRef pointing to the recorded resize action. Use "capture" to extract app-generated values (IDs, codes, URLs) for later steps via $var.name, but only from a visible DOM target or the current URL. Do not capture from performance/network timing, storage, hidden DOM, or app-global state. Use "screenshot" only when browser_screenshot itself is the requested evidence capture. Set params.label when a label was used, optionally params.fullPage="true". Do not use screenshot for routine visual checks after actions; use verify when a browser_assert proves visible state. Use "extract_table" when browser_extract_table was used to extract tabular data from the page. Use "python_execute" when python_execute was used with cache_label to run a data validation script. Use "verify_download" when browser_download(action="list") / browser_list_downloads proves that a file matching some pattern was downloaded. Set params.pattern to a glob (supports *, ?) or substring; optionally params.timeoutMs. This is currently agent-only at replay, so do not set actionRefs. Use "verify_download_content" when browser_download(action="read") / browser_read_download content proves CSV headers, PDF text, exported rows, or similar downloaded-file content. Set params.contains or params.pattern to the expected content predicate. This is currently agent-only at replay, so do not set actionRefs. Use "agent_loop" ONLY when the action set is genuinely unknown until runtime \u2014 variable count of items (e.g. "toggle row checkboxes until 3 selected"), conditional retry that depends on UI state, or a runtime predicate over non-DOM state. Set params.goal to a one-sentence checkable predicate (e.g. params.goal = "3 grid row checkboxes are selected"). DO NOT use agent_loop for: known-N iteration (write N deterministic steps), single click that might double-fire (use "click"), retry-on-flake (the runtime handles that). agent_loop steps replay via a Playwright override authored after first run; they are non-deterministic on first run, so the bar is high. Network/devtools/API inspections and unsupported browser environment mutations are diagnostic-only unless there is an exposed browser tool for the action. If visible page state proves the condition, record that as "verify"; otherwise omit the diagnostic observation from playbookSteps. Do not use "other". If no concrete browser-tool-backed action above fits, omit the observation from playbookSteps and report the limitation outside the playbook.'
527
614
  ),
528
- target: z5.string().describe(
615
+ target: z6.string().describe(
529
616
  `Human-readable element description using visible labels, placeholders, or aria-labels. Examples: "'Submit' button", "'Email' input field", "'Status' dropdown". For upload actions, describe the file input and include the attachment name (e.g. "CSV file input for 'testing-checklist.csv'"). Never use coordinates, ref IDs, or internal identifiers.`
530
617
  ),
531
- params: z5.record(z5.string(), z5.string()).optional().describe(
618
+ params: z6.record(z6.string(), z6.string()).optional().describe(
532
619
  'Data values using $var.name references and $MACRO() expressions \u2014 NEVER hard-coded literals. Common keys: value (for fill: {value: "$EMAIL()"}), option (for select: {option: "Admin"} \u2014 fixed app constants like dropdown options are allowed as literals), url (for navigate: {url: "$var.target_url"}), path (for upload: {path: "$var.file_path"}), key (for press_key: {key: "Enter"}, {key: "Escape"}), width and height (for resize: {width: "390", height: "844"}), label and fullPage (for screenshot: {label: "seats-table", fullPage: "true"}), pattern or contains (for download verification: {pattern: "report-*.csv"} or {contains: "Expected Header"}), expression + saveAs (for capture: prefer a visible DOM ref expression or "() => window.location.href"; do not use performance.getEntries() or other network/storage/global state; e.g. {saveAs: "order_confirmation_id"}). For fill_form: keys are field names from the fill_form call, values are $var.name or $MACRO() (e.g. {company: "$var.company", email: "$EMAIL()"}). Available macros: $UUID(), $EMAIL(), $FIRST_NAME(), $LAST_NAME(), $PHONE(), $RANDOM_STRING(n), $RANDOM_INT(min,max), $TODAY(), $DATE(days), $NOW(), $TIMESTAMP(), $SEQUENCE("name").'
533
620
  ),
534
- note: z5.string().optional().describe(
621
+ note: z6.string().optional().describe(
535
622
  'Timing or quirk notes ONLY (e.g. "Wait 1s for modal animation", "Scroll into view first"). Do NOT put data values, optional markers, or verification notes here.'
536
623
  ),
537
- actionRefs: z5.array(z5.number()).max(1).optional().describe(
624
+ actionRefs: z6.array(z6.number()).max(1).optional().describe(
538
625
  'Zero or one recorded browser action index that corresponds to this playbook step. Interaction tools, browser_resize, capture evaluates (browser_evaluate with saveAs), and browser_assert produce [Action #N] tags \u2014 collect those indices here. Read-only browser_snapshot and plain browser_evaluate without saveAs do NOT produce action indices. browser_scroll and browser_screenshot may produce action indices when they are the primary requested tool call; omit actionRefs when no action tag was emitted. If you took multiple cacheable UI actions, report multiple 1:1 playbook steps instead of putting multiple refs on one step or summarizing them as "other". A fill_form call is a single action \u2014 use one fill_form playbook step with one actionRef. For a click that triggers a native dialog, keep one click actionRef on the click step and set expectedDialogs rather than adding a separate dialog actionRef. Actions not referenced by any playbook step are considered exploratory and will be discarded by the cache compiler.'
539
626
  ),
540
- expectedDialogs: z5.enum(["accept", "dismiss"]).optional().describe(
627
+ expectedDialogs: z6.enum(["accept", "dismiss"]).optional().describe(
541
628
  'Set when this step is known to fire a native browser dialog (alert/confirm/prompt) \u2014 e.g. clicking a "Delete" button that prompts "Are you sure?". On replay the runtime pre-arms the dialog handler with this action automatically. In free-form runs, you should call the dialog tool (browser_dialog for consolidated tools, browser_handle_dialog for legacy tools) with this action immediately before the step. Do not add a separate dialog step \u2014 keeping the pre-arm on the triggering step keeps the pre-arm and the triggering action in one place.'
542
629
  )
543
630
  }).superRefine((step, ctx) => {
@@ -545,7 +632,7 @@ var playbookStepAgentSchema = z5.object({
545
632
  const goal = step.params?.goal;
546
633
  if (!goal || goal.trim().length === 0) {
547
634
  ctx.addIssue({
548
- code: z5.ZodIssueCode.custom,
635
+ code: z6.ZodIssueCode.custom,
549
636
  path: ["params", "goal"],
550
637
  message: 'agent_loop steps must set params.goal to a one-sentence checkable predicate (e.g. "3 grid row checkboxes are selected").'
551
638
  });
@@ -555,7 +642,7 @@ var playbookStepAgentSchema = z5.object({
555
642
  const pattern = step.params?.pattern;
556
643
  if (!pattern || pattern.trim().length === 0) {
557
644
  ctx.addIssue({
558
- code: z5.ZodIssueCode.custom,
645
+ code: z6.ZodIssueCode.custom,
559
646
  path: ["params", "pattern"],
560
647
  message: "verify_download steps must set params.pattern to a glob (supports *, ?) or substring matching the expected filename."
561
648
  });
@@ -566,7 +653,7 @@ var playbookStepAgentSchema = z5.object({
566
653
  const contains = step.params?.contains;
567
654
  if ((!pattern || pattern.trim().length === 0) && (!contains || contains.trim().length === 0)) {
568
655
  ctx.addIssue({
569
- code: z5.ZodIssueCode.custom,
656
+ code: z6.ZodIssueCode.custom,
570
657
  path: ["params"],
571
658
  message: "verify_download_content steps must set params.contains or params.pattern for the expected downloaded content."
572
659
  });
@@ -577,14 +664,14 @@ var playbookStepAgentSchema = z5.object({
577
664
  const height = step.params?.height;
578
665
  if (!isPositiveIntegerString(width)) {
579
666
  ctx.addIssue({
580
- code: z5.ZodIssueCode.custom,
667
+ code: z6.ZodIssueCode.custom,
581
668
  path: ["params", "width"],
582
669
  message: "resize steps must set params.width to a positive integer pixel value."
583
670
  });
584
671
  }
585
672
  if (!isPositiveIntegerString(height)) {
586
673
  ctx.addIssue({
587
- code: z5.ZodIssueCode.custom,
674
+ code: z6.ZodIssueCode.custom,
588
675
  path: ["params", "height"],
589
676
  message: "resize steps must set params.height to a positive integer pixel value."
590
677
  });
@@ -598,8 +685,12 @@ export {
598
685
  INSTANCE_SIZE_SPEC,
599
686
  parseInstanceSize,
600
687
  VALID_MACRO_NAMES,
688
+ MACRO_PATTERN,
601
689
  InlineAssertionSchema,
602
690
  NODE_TYPE_LABEL,
603
- normalizeNodeType
691
+ normalizeNodeType,
692
+ isVolatileIdentifier,
693
+ stableIdentifierPrefix,
694
+ stableAttrSelector
604
695
  };
605
- //# sourceMappingURL=chunk-SJJW77WN.js.map
696
+ //# sourceMappingURL=chunk-JYGNMKZ5.js.map