@runcofactor/cli 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/dist/account-22LMP5PX.js +255 -0
  2. package/dist/account-22LMP5PX.js.map +1 -0
  3. package/dist/{api-catalog-7HLEN7C2.js → api-catalog-WTFQNLK6.js} +5 -5
  4. package/dist/{attachment-OVNQD6Z2.js → attachment-U3NKVPEY.js} +5 -5
  5. package/dist/augmentor-5GMNAX4M.js +198 -0
  6. package/dist/augmentor-5GMNAX4M.js.map +1 -0
  7. package/dist/{auth-VUHL74FH.js → auth-VQG2CDUD.js} +3 -3
  8. package/dist/{chunk-PZ4LCN6K.js → chunk-3X3NW7QA.js} +2 -2
  9. package/dist/{chunk-VGTKUOYS.js → chunk-46IUJXSD.js} +2 -2
  10. package/dist/{chunk-YN763NWQ.js → chunk-7VMO2WOZ.js} +10 -4
  11. package/dist/chunk-7VMO2WOZ.js.map +1 -0
  12. package/dist/{chunk-Z5LUTUDN.js → chunk-CMGI7UZD.js} +3 -3
  13. package/dist/{chunk-EEN2TZUQ.js → chunk-FNPMWDUQ.js} +3 -3
  14. package/dist/{chunk-EJ4U242G.js → chunk-HDFYUFBI.js} +2 -2
  15. package/dist/{chunk-JZMJUPZP.js → chunk-JMJVGMXI.js} +2 -2
  16. package/dist/{chunk-JZMJUPZP.js.map → chunk-JMJVGMXI.js.map} +1 -1
  17. package/dist/{chunk-QGI4UCJX.js → chunk-JYGNMKZ5.js} +62 -35
  18. package/dist/chunk-JYGNMKZ5.js.map +1 -0
  19. package/dist/{chunk-CRHPDPRS.js → chunk-KCHKFYVX.js} +30 -8
  20. package/dist/{chunk-CRHPDPRS.js.map → chunk-KCHKFYVX.js.map} +1 -1
  21. package/dist/{chunk-ZD3KHESI.js → chunk-KRWRUU6R.js} +27 -7
  22. package/dist/chunk-KRWRUU6R.js.map +1 -0
  23. package/dist/{chunk-ENDHMYEJ.js → chunk-NHTEKEYE.js} +3 -3
  24. package/dist/{chunk-CQE46HSM.js → chunk-PRBRSIZP.js} +14 -8
  25. package/dist/chunk-PRBRSIZP.js.map +1 -0
  26. package/dist/{chunk-NL7CVG56.js → chunk-UETBLPKM.js} +57 -10
  27. package/dist/chunk-UETBLPKM.js.map +1 -0
  28. package/dist/{chunk-QQVWGWPI.js → chunk-VGYN2KU2.js} +8494 -1504
  29. package/dist/chunk-VGYN2KU2.js.map +1 -0
  30. package/dist/{chunk-ZTOE3ND3.js → chunk-XJ5YYYGC.js} +4 -4
  31. package/dist/{credential-LO2SEEHU.js → credential-E6KUHRGU.js} +5 -5
  32. package/dist/{credential-template-ZN7W7734.js → credential-template-4GPOPBGD.js} +5 -5
  33. package/dist/{debug-workflow-R3RYYAXK.js → debug-workflow-XCLCY6S7.js} +5 -5
  34. package/dist/{docs-DIAFBDXQ.js → docs-COCZYMW6.js} +95 -11
  35. package/dist/docs-COCZYMW6.js.map +1 -0
  36. package/dist/{doctor-NZPUSCRE.js → doctor-ERIVTCQS.js} +3 -3
  37. package/dist/{environment-RQVU4P5M.js → environment-7Y4BV6XY.js} +5 -5
  38. package/dist/{feature-flag-XG26RURR.js → feature-flag-MHONEX6T.js} +98 -12
  39. package/dist/feature-flag-MHONEX6T.js.map +1 -0
  40. package/dist/index.js +107 -51
  41. package/dist/index.js.map +1 -1
  42. package/dist/{init-EDNLKGPT.js → init-OROOM4HF.js} +5 -5
  43. package/dist/{install-FYZ3HNZK.js → install-OJFXHY6U.js} +5 -5
  44. package/dist/{issues-NNRVTJ4L.js → issues-32GONR6C.js} +5 -5
  45. package/dist/{knobs-A2BOBH22.js → knobs-UQGGY3CP.js} +7 -6
  46. package/dist/knobs-UQGGY3CP.js.map +1 -0
  47. package/dist/{list-F33VZ4BJ.js → list-ZMIKEC5P.js} +5 -5
  48. package/dist/{local-DQDTM3XA.js → local-PUD24GGQ.js} +7 -7
  49. package/dist/{login-BUMVIB36.js → login-BSO7YX2D.js} +5 -5
  50. package/dist/{mcp-B5Y5CDMQ.js → mcp-4LS7OJUT.js} +9 -9
  51. package/dist/{mcp-B5Y5CDMQ.js.map → mcp-4LS7OJUT.js.map} +1 -1
  52. package/dist/{pdf-extract-ABWV3L5X.js → pdf-extract-YHE54XU4.js} +2 -2
  53. package/dist/product-3JKSJCBC.js +346 -0
  54. package/dist/product-3JKSJCBC.js.map +1 -0
  55. package/dist/{property-NJ4SRXQG.js → property-K5DBL4UE.js} +5 -5
  56. package/dist/{psql-VBZFCMNR.js → psql-PQFUFTSE.js} +3 -3
  57. package/dist/{record-WAO36O7G.js → record-EIIYLFJ4.js} +6 -6
  58. package/dist/{redis-DHZXHL4S.js → redis-BU36EZZI.js} +3 -3
  59. package/dist/redis-BU36EZZI.js.map +1 -0
  60. package/dist/{release-STJKUKTE.js → release-LYC2P7DZ.js} +5 -5
  61. package/dist/{sandbox-DWSGLY7B.js → sandbox-CKHXXZHU.js} +51 -7
  62. package/dist/sandbox-CKHXXZHU.js.map +1 -0
  63. package/dist/{scenarios-HCIDY725.js → scenarios-2XJ2G3KR.js} +5 -5
  64. package/dist/{session-Y5RHU54D.js → session-UTOD5ZYH.js} +8 -9
  65. package/dist/session-UTOD5ZYH.js.map +1 -0
  66. package/dist/{skill-23WAHUOB.js → skill-GMAERMQL.js} +10 -10
  67. package/dist/{skill-23WAHUOB.js.map → skill-GMAERMQL.js.map} +1 -1
  68. package/dist/skills/debug-run/SKILL.md +7 -1
  69. package/dist/skills/debug-run/history/1.3.1.md +279 -0
  70. package/dist/skills/debug-run/version.json +1 -1
  71. package/dist/skills/optimize-cache/SKILL.md +29 -2
  72. package/dist/{spec-LM5XHOQ5.js → spec-2NP36U3Y.js} +5 -5
  73. package/dist/{src-22RI5VP2.js → src-4T6GHXVO.js} +2 -2
  74. package/dist/{src-NCJPUAE6.js → src-CG52HEE7.js} +10 -8
  75. package/dist/{src-Y3K7UJEF.js → src-PK5OZXCM.js} +2 -2
  76. package/dist/{src-BGDRMOKC.js → src-UEOOC425.js} +295 -102
  77. package/dist/src-UEOOC425.js.map +1 -0
  78. package/dist/{start-SWY55CZX.js → start-3C7EEFW2.js} +5 -5
  79. package/dist/{tag-YSU2XXPI.js → tag-JSHOMLBR.js} +6 -6
  80. package/dist/{task-NLBKLD7D.js → task-YGWVYTBJ.js} +5 -5
  81. package/dist/{test-suite-QCPWZ2LS.js → test-suite-LI7ZH367.js} +10 -8
  82. package/dist/{test-suite-QCPWZ2LS.js.map → test-suite-LI7ZH367.js.map} +1 -1
  83. package/dist/trace-UMLOSIIR.js +16 -0
  84. package/dist/{triage-TT4BMDBU.js → triage-ZWJG4NBJ.js} +6 -6
  85. package/dist/{upgrade-6ZUFETKX.js → upgrade-S7CGEK6H.js} +3 -3
  86. package/dist/{workflow-2CX3ZNOQ.js → workflow-T4HSAOGW.js} +86 -15
  87. package/dist/workflow-T4HSAOGW.js.map +1 -0
  88. package/dist/{workflow-cache-GXNE6SU2.js → workflow-cache-XVEZ36KF.js} +8 -8
  89. package/dist/{workflow-debug-PRX3DWGD.js → workflow-debug-T2BULXZ7.js} +9 -9
  90. package/dist/{workflow-proposals-BW327WGL.js → workflow-proposals-XXEZICN2.js} +5 -7
  91. package/dist/workflow-proposals-XXEZICN2.js.map +1 -0
  92. package/package.json +1 -1
  93. package/dist/chunk-CQE46HSM.js.map +0 -1
  94. package/dist/chunk-NL7CVG56.js.map +0 -1
  95. package/dist/chunk-QGI4UCJX.js.map +0 -1
  96. package/dist/chunk-QQVWGWPI.js.map +0 -1
  97. package/dist/chunk-YN763NWQ.js.map +0 -1
  98. package/dist/chunk-ZD3KHESI.js.map +0 -1
  99. package/dist/docs-DIAFBDXQ.js.map +0 -1
  100. package/dist/feature-flag-XG26RURR.js.map +0 -1
  101. package/dist/knobs-A2BOBH22.js.map +0 -1
  102. package/dist/redis-DHZXHL4S.js.map +0 -1
  103. package/dist/sandbox-DWSGLY7B.js.map +0 -1
  104. package/dist/session-Y5RHU54D.js.map +0 -1
  105. package/dist/src-BGDRMOKC.js.map +0 -1
  106. package/dist/trace-A3ZY6K26.js +0 -16
  107. package/dist/workflow-2CX3ZNOQ.js.map +0 -1
  108. package/dist/workflow-proposals-BW327WGL.js.map +0 -1
  109. /package/dist/{api-catalog-7HLEN7C2.js.map → api-catalog-WTFQNLK6.js.map} +0 -0
  110. /package/dist/{attachment-OVNQD6Z2.js.map → attachment-U3NKVPEY.js.map} +0 -0
  111. /package/dist/{auth-VUHL74FH.js.map → auth-VQG2CDUD.js.map} +0 -0
  112. /package/dist/{chunk-PZ4LCN6K.js.map → chunk-3X3NW7QA.js.map} +0 -0
  113. /package/dist/{chunk-VGTKUOYS.js.map → chunk-46IUJXSD.js.map} +0 -0
  114. /package/dist/{chunk-Z5LUTUDN.js.map → chunk-CMGI7UZD.js.map} +0 -0
  115. /package/dist/{chunk-EEN2TZUQ.js.map → chunk-FNPMWDUQ.js.map} +0 -0
  116. /package/dist/{chunk-EJ4U242G.js.map → chunk-HDFYUFBI.js.map} +0 -0
  117. /package/dist/{chunk-ENDHMYEJ.js.map → chunk-NHTEKEYE.js.map} +0 -0
  118. /package/dist/{chunk-ZTOE3ND3.js.map → chunk-XJ5YYYGC.js.map} +0 -0
  119. /package/dist/{credential-LO2SEEHU.js.map → credential-E6KUHRGU.js.map} +0 -0
  120. /package/dist/{credential-template-ZN7W7734.js.map → credential-template-4GPOPBGD.js.map} +0 -0
  121. /package/dist/{debug-workflow-R3RYYAXK.js.map → debug-workflow-XCLCY6S7.js.map} +0 -0
  122. /package/dist/{doctor-NZPUSCRE.js.map → doctor-ERIVTCQS.js.map} +0 -0
  123. /package/dist/{environment-RQVU4P5M.js.map → environment-7Y4BV6XY.js.map} +0 -0
  124. /package/dist/{init-EDNLKGPT.js.map → init-OROOM4HF.js.map} +0 -0
  125. /package/dist/{install-FYZ3HNZK.js.map → install-OJFXHY6U.js.map} +0 -0
  126. /package/dist/{issues-NNRVTJ4L.js.map → issues-32GONR6C.js.map} +0 -0
  127. /package/dist/{list-F33VZ4BJ.js.map → list-ZMIKEC5P.js.map} +0 -0
  128. /package/dist/{local-DQDTM3XA.js.map → local-PUD24GGQ.js.map} +0 -0
  129. /package/dist/{login-BUMVIB36.js.map → login-BSO7YX2D.js.map} +0 -0
  130. /package/dist/{pdf-extract-ABWV3L5X.js.map → pdf-extract-YHE54XU4.js.map} +0 -0
  131. /package/dist/{property-NJ4SRXQG.js.map → property-K5DBL4UE.js.map} +0 -0
  132. /package/dist/{psql-VBZFCMNR.js.map → psql-PQFUFTSE.js.map} +0 -0
  133. /package/dist/{record-WAO36O7G.js.map → record-EIIYLFJ4.js.map} +0 -0
  134. /package/dist/{release-STJKUKTE.js.map → release-LYC2P7DZ.js.map} +0 -0
  135. /package/dist/{scenarios-HCIDY725.js.map → scenarios-2XJ2G3KR.js.map} +0 -0
  136. /package/dist/{spec-LM5XHOQ5.js.map → spec-2NP36U3Y.js.map} +0 -0
  137. /package/dist/{src-22RI5VP2.js.map → src-4T6GHXVO.js.map} +0 -0
  138. /package/dist/{src-NCJPUAE6.js.map → src-CG52HEE7.js.map} +0 -0
  139. /package/dist/{src-Y3K7UJEF.js.map → src-PK5OZXCM.js.map} +0 -0
  140. /package/dist/{start-SWY55CZX.js.map → start-3C7EEFW2.js.map} +0 -0
  141. /package/dist/{tag-YSU2XXPI.js.map → tag-JSHOMLBR.js.map} +0 -0
  142. /package/dist/{task-NLBKLD7D.js.map → task-YGWVYTBJ.js.map} +0 -0
  143. /package/dist/{trace-A3ZY6K26.js.map → trace-UMLOSIIR.js.map} +0 -0
  144. /package/dist/{triage-TT4BMDBU.js.map → triage-ZWJG4NBJ.js.map} +0 -0
  145. /package/dist/{upgrade-6ZUFETKX.js.map → upgrade-S7CGEK6H.js.map} +0 -0
  146. /package/dist/{workflow-cache-GXNE6SU2.js.map → workflow-cache-XVEZ36KF.js.map} +0 -0
  147. /package/dist/{workflow-debug-PRX3DWGD.js.map → workflow-debug-T2BULXZ7.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/docs.ts"],"sourcesContent":["/**\n * CLI Documentation Management\n *\n * Allows agents and superadmins to list, pull, edit, and push documentation pages.\n * Supports both global (public/superadmin) and org-scoped (--org) modes.\n */\n\nimport { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport { getSubDir } from '@chatsdet/tmp';\nimport process from 'node:process';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest } from './cli-helpers.js';\n\ntype DocsPageListItem = {\n slug: string;\n title: string;\n description: string | null;\n updatedAt: string;\n publishedBy: string | null;\n};\n\ntype DocsVersionItem = {\n version: number;\n title: string;\n checksum: string;\n message: string | null;\n createdBy: string;\n createdAt: string;\n};\n\ntype DocsApiResponse = {\n ok: boolean;\n error?: string;\n data?: {\n slug?: string;\n title?: string;\n pages?: DocsPageListItem[];\n content?: string;\n versions?: DocsVersionItem[];\n };\n};\n\nconst DEFAULT_PULL_DIR = getSubDir('docs');\n\n/**\n * Parse the optional data-driven sidebar-placement flags. Only present flags\n * are included, so `push`/`create` without them leaves existing values intact.\n */\nfunction parseNavFields(argv: string[]): {\n navSection?: string;\n navGroup?: string;\n navOrder?: number;\n} {\n const out: { navSection?: string; navGroup?: string; navOrder?: number } = {};\n const section = getArgValue(argv, '--section');\n const group = getArgValue(argv, '--group');\n const order = getArgValue(argv, '--order');\n if (section != null) out.navSection = section;\n if (group != null) out.navGroup = group;\n if (order != null) {\n const n = Number.parseInt(order, 10);\n if (Number.isNaN(n)) {\n console.error('Error: --order must be an integer.');\n process.exit(1);\n }\n out.navOrder = n;\n }\n return out;\n}\n\n/** Return the base path prefix for read endpoints based on --org flag */\nfunction readPrefix(orgMode: boolean): string {\n return orgMode ? '/docs' : '/public/docs';\n}\n\n/** Return the base path prefix for write endpoints based on --org flag */\nfunction writePrefix(orgMode: boolean): string {\n return orgMode ? '/docs' : '/superadmin/docs';\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string, orgMode: boolean): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n const result = await apiRequest<DocsApiResponse>(apiUrl, token, 'GET', `${readPrefix(orgMode)}/pages`);\n const pages: DocsPageListItem[] = result.data?.pages ?? [];\n\n if (jsonOutput) {\n console.log(JSON.stringify(pages, null, 2));\n return;\n }\n\n if (pages.length === 0) {\n console.log('No documentation pages found.');\n return;\n }\n\n // Default: markdown table for easy consumption by agents and humans\n const slugWidth = Math.max(4, ...pages.map((p) => p.slug.length));\n const titleWidth = Math.max(5, ...pages.map((p) => p.title.length));\n const header = `| ${'Slug'.padEnd(slugWidth)} | ${'Title'.padEnd(titleWidth)} | Updated | Published By |`;\n const sep = `| ${'-'.repeat(slugWidth)} | ${'-'.repeat(titleWidth)} | ---------- | ------------ |`;\n console.log(header);\n console.log(sep);\n for (const page of pages) {\n const date = new Date(page.updatedAt).toISOString().slice(0, 10);\n const by = page.publishedBy ?? '';\n console.log(`| ${page.slug.padEnd(slugWidth)} | ${page.title.padEnd(titleWidth)} | ${date} | ${by.padEnd(12)} |`);\n }\n}\n\nasync function fetchDocContent(slug: string, apiUrl: string, token: string, orgMode: boolean): Promise<string> {\n if (orgMode) {\n const result = await apiRequest<DocsApiResponse>(\n apiUrl,\n token,\n 'GET',\n `/docs/pages/content?slug=${encodeURIComponent(slug)}`\n );\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n return result.data?.content ?? '';\n }\n\n const res = await fetch(`${apiUrl}/public/docs/pages/raw?slug=${encodeURIComponent(slug)}`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (res.status === 404) {\n console.error(`Error: Page not found: ${slug}`);\n process.exit(1);\n }\n\n if (!res.ok) {\n console.error(`Error: ${res.statusText}`);\n process.exit(1);\n }\n\n return res.text();\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string, orgMode: boolean): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith('--')) {\n console.error('Error: Missing slug.');\n console.error('Usage: canary docs get <slug>');\n process.exit(1);\n }\n\n const content = await fetchDocContent(slug, apiUrl, token, orgMode);\n console.log(content);\n}\n\nasync function handlePull(argv: string[], apiUrl: string, token: string, orgMode: boolean): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith('--')) {\n console.error('Error: Missing slug.');\n console.error('Usage: canary docs pull <slug> [--output <path>]');\n process.exit(1);\n }\n\n const outputPath = getArgValue(argv, '--output') ?? path.join(DEFAULT_PULL_DIR, `${slug}.md`);\n const content = await fetchDocContent(slug, apiUrl, token, orgMode);\n\n await mkdir(path.dirname(outputPath), { recursive: true });\n await writeFile(outputPath, content, 'utf8');\n console.log(`Pulled ${slug} → ${outputPath}`);\n}\n\nasync function handlePush(argv: string[], apiUrl: string, token: string, orgMode: boolean): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith('--')) {\n console.error('Error: Missing slug.');\n console.error('Usage: canary docs push <slug> --file <path> [--message <text>]');\n process.exit(1);\n }\n\n const filePath = getArgValue(argv, '--file');\n if (!filePath) {\n console.error('Error: Missing --file <path>.');\n process.exit(1);\n }\n\n const message = getArgValue(argv, '--message') ?? undefined;\n const createdBy = getArgValue(argv, '--created-by') ?? undefined;\n\n let content: string;\n try {\n content = await readFile(filePath, 'utf8');\n } catch {\n console.error(`Error: Could not read file: ${filePath}`);\n process.exit(1);\n }\n\n // Strip `export const meta = { ... };` block so raw JS isn't stored as doc content\n content = content.replace(/^\\s*export\\s+const\\s+meta\\s*=\\s*\\{[^}]*\\};\\s*/, '');\n\n const result = await apiRequest<DocsApiResponse>(\n apiUrl,\n token,\n 'PUT',\n `${writePrefix(orgMode)}/pages?slug=${encodeURIComponent(slug)}`,\n { content, message, createdBy, ...parseNavFields(argv) }\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Published new version of ${slug}`);\n}\n\nasync function handleHistory(argv: string[], apiUrl: string, token: string, orgMode: boolean): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith('--')) {\n console.error('Error: Missing slug.');\n console.error('Usage: canary docs history <slug>');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n\n const res = await fetch(`${apiUrl}${readPrefix(orgMode)}/pages/versions?slug=${encodeURIComponent(slug)}`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: res.statusText }));\n console.error(`Error: ${(body as { error?: string }).error ?? res.statusText}`);\n process.exit(1);\n }\n\n const body = (await res.json()) as DocsApiResponse;\n const versions = body.data?.versions ?? [];\n\n if (jsonOutput) {\n console.log(JSON.stringify(versions, null, 2));\n return;\n }\n\n if (versions.length === 0) {\n console.log(`No versions found for ${slug}.`);\n return;\n }\n\n for (const v of versions) {\n const date = new Date(v.createdAt).toISOString().slice(0, 19).replace('T', ' ');\n const msg = v.message ? ` — ${v.message}` : '';\n console.log(` v${v.version} ${date} ${v.createdBy}${msg}`);\n }\n}\n\nasync function handleCreate(argv: string[], apiUrl: string, token: string, orgMode: boolean): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith('--')) {\n console.error('Error: Missing slug.');\n console.error('Usage: canary docs create <slug> --file <path> --title <text>');\n process.exit(1);\n }\n\n const filePath = getArgValue(argv, '--file');\n const title = getArgValue(argv, '--title');\n\n if (!filePath) {\n console.error('Error: Missing --file <path>.');\n process.exit(1);\n }\n if (!title) {\n console.error('Error: Missing --title <text>.');\n process.exit(1);\n }\n\n const description = getArgValue(argv, '--description') ?? undefined;\n const message = getArgValue(argv, '--message') ?? undefined;\n\n let content: string;\n try {\n content = await readFile(filePath, 'utf8');\n } catch {\n console.error(`Error: Could not read file: ${filePath}`);\n process.exit(1);\n }\n\n // Strip `export const meta = { ... };` block so raw JS isn't stored as doc content\n content = content.replace(/^\\s*export\\s+const\\s+meta\\s*=\\s*\\{[^}]*\\};\\s*/, '');\n\n const result = await apiRequest<DocsApiResponse>(\n apiUrl,\n token,\n 'POST',\n `${writePrefix(orgMode)}/pages`,\n {\n slug,\n title,\n description,\n content,\n message,\n ...parseNavFields(argv),\n }\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Created page: ${slug}`);\n}\n\ntype DocsSearchResult = {\n path: string;\n title: string;\n description: string | null;\n excerpt: string;\n};\n\ntype DocsSearchResponse = {\n ok: boolean;\n error?: string;\n data?: { results: DocsSearchResult[] };\n};\n\nasync function handleSearch(argv: string[], apiUrl: string, token: string, orgMode: boolean): Promise<void> {\n const query = argv.filter((a) => !a.startsWith('--')).join(' ').trim();\n if (!query) {\n console.error('Error: Missing search query.');\n console.error('Usage: canary docs search <query> [--limit <n>] [--json]');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n const limitArg = getArgValue(argv, '--limit');\n const params = new URLSearchParams({ q: query });\n if (limitArg) params.set('limit', limitArg);\n\n const searchPath = orgMode ? '/docs/search' : '/public/docs/search';\n const res = await fetch(`${apiUrl}${searchPath}?${params.toString()}`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: res.statusText }));\n console.error(`Error: ${(body as { error?: string }).error ?? res.statusText}`);\n process.exit(1);\n }\n\n const body = (await res.json()) as DocsSearchResponse;\n const results = body.data?.results ?? [];\n\n if (jsonOutput) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log('No results found.');\n return;\n }\n\n for (const r of results) {\n const desc = r.description ? ` ${r.description}` : '';\n const excerpt = r.excerpt\n ? ` ${r.excerpt.replace(/<\\/?mark>/g, '').replace(/\\n/g, ' ').slice(0, 120)}`\n : '';\n console.log(` ${r.path ?? r.title}`);\n if (r.title) console.log(` ${r.title}${desc}`);\n if (excerpt) console.log(` ${excerpt}`);\n console.log();\n }\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string, orgMode: boolean): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith('--')) {\n console.error('Error: Missing slug.');\n console.error('Usage: canary docs delete <slug>');\n process.exit(1);\n }\n\n const result = await apiRequest<DocsApiResponse>(\n apiUrl,\n token,\n 'DELETE',\n `${writePrefix(orgMode)}/pages?slug=${encodeURIComponent(slug)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Deleted page: ${slug}`);\n}\n\nfunction printDocsHelp(): void {\n console.log(\n [\n 'Usage: canary docs <sub-command> [options]',\n '',\n 'Sub-commands:',\n ' list List all doc pages',\n ' get <slug> Print content to stdout',\n ' search <query> Full-text search docs',\n ' pull <slug> [--output <path>] Download to local file',\n ' push <slug> --file <path> [--message] Publish new version',\n ' history <slug> Show version history',\n ' create <slug> --file <path> --title ... Create new page',\n ' delete <slug> Soft-delete a page',\n '',\n 'Options:',\n ' --org Use org-scoped endpoints (requires auth)',\n ' --file <path> Path to markdown file',\n ' --title <text> Page title (create only)',\n ' --description <text> Page description (create only)',\n ' --section <text> Sidebar section (data-driven nav; create/push)',\n ' --group <text> Sidebar sub-group within the section (create/push)',\n ' --order <n> Sort order within the section/group (create/push)',\n ' --message <text> Version commit message',\n ' --limit <n> Max results for search (default: 8, max: 20)',\n ' --output <path> Output path for pull (default: <tmpdir>/canary/docs/<slug>.md)',\n ' --json Output as JSON (list, history, search)',\n ' --env <env> Target environment (prod, dev)',\n ' --api-url <url> API URL override',\n ' --token <key> API token override',\n ].join('\\n')\n );\n}\n\nexport async function runDocs(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printDocsHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n const orgMode = hasFlag(rest, '--org');\n\n switch (subCommand) {\n case 'list':\n await handleList(rest, apiUrl, token, orgMode);\n break;\n case 'get':\n await handleGet(rest, apiUrl, token, orgMode);\n break;\n case 'search':\n await handleSearch(rest, apiUrl, token, orgMode);\n break;\n case 'pull':\n await handlePull(rest, apiUrl, token, orgMode);\n break;\n case 'push':\n await handlePush(rest, apiUrl, token, orgMode);\n break;\n case 'history':\n await handleHistory(rest, apiUrl, token, orgMode);\n break;\n case 'create':\n await handleCreate(rest, apiUrl, token, orgMode);\n break;\n case 'delete':\n await handleDelete(rest, apiUrl, token, orgMode);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printDocsHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["body"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/feature-flag.ts"],"sourcesContent":["/**\n * CLI Feature Flag Management\n *\n * Allows superadmins to manage feature flags via the CLI.\n */\n\nimport process from \"node:process\";\nimport { resolveConfig, getArgValue, hasFlag } from \"./auth.js\";\nimport {\n type LifecycleStage,\n toLifecycleLabel,\n parseLifecycleStage,\n apiRequest,\n fetchList,\n} from \"./cli-helpers.js\";\n\ntype FeatureFlag = {\n id: string;\n name: string;\n description: string | null;\n lifecycleStage: LifecycleStage;\n finalValue: boolean | null;\n createdAt: string;\n lastToggledAt: string;\n isStale: boolean;\n productCardId: string | null;\n productTitle: string | null;\n organizations?: Array<{\n gateId: string;\n orgId: string;\n orgName: string;\n createdAt: string;\n }>;\n users?: Array<{\n gateId: string;\n userId: string;\n userEmail: string | null;\n createdAt: string;\n }>;\n};\n\ntype FlagApiResponse = {\n ok: boolean;\n error?: string;\n flag?: FeatureFlag;\n};\n\ntype ProductCard = {\n id: string;\n title: string;\n stage: string;\n orgId: string;\n orgName: string;\n};\n\nfunction fetchFlags(apiUrl: string, token: string): Promise<FeatureFlag[]> {\n return fetchList<FeatureFlag>(apiUrl, token, \"/superadmin/feature-flags\", \"flags\");\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, \"--json\");\n const flags = await fetchFlags(apiUrl, token);\n\n if (jsonOutput) {\n console.log(JSON.stringify(flags, null, 2));\n return;\n }\n\n if (flags.length === 0) {\n console.log(\"No feature flags found.\");\n return;\n }\n\n for (const flag of flags) {\n const orgCount = flag.organizations?.length ?? 0;\n const userCount = flag.users?.length ?? 0;\n const lifecycle = `lifecycle=${toLifecycleLabel(flag.lifecycleStage)}`;\n const finalValue =\n flag.lifecycleStage === \"active\" ? \"\" : ` final=${flag.finalValue === true ? \"true\" : \"false\"}`;\n const stale = flag.isStale ? \" [STALE]\" : \"\";\n const product = flag.productCardId\n ? ` product=${flag.productTitle ?? flag.productCardId}`\n : \"\";\n console.log(` ${flag.name} ${flag.description ?? \"\"} (${lifecycle}${finalValue}) [orgs=${orgCount}, users=${userCount}]${product}${stale}`);\n }\n}\n\nasync function handleCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag create <name> [--description <text>] [--product <productCardId>]\");\n process.exit(1);\n }\n\n const description = getArgValue(argv, \"--description\") ?? null;\n const productCardId = getArgValue(argv, \"--product\") ?? null;\n const result = await apiRequest<FlagApiResponse>(apiUrl, token, \"POST\", \"/superadmin/feature-flags\", {\n name,\n description,\n productCardId,\n });\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Created feature flag: ${name}${productCardId ? ` (product ${productCardId})` : \"\"}`);\n}\n\nasync function handleProduct(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n const productCardId = getArgValue(argv, \"--product\");\n const clear = hasFlag(argv, \"--clear\");\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag product <name> (--product <productCardId> | --clear)\");\n process.exit(1);\n }\n\n if ((productCardId && clear) || (!productCardId && !clear)) {\n console.error(\"Error: Provide either --product <productCardId> or --clear.\");\n process.exit(1);\n }\n\n const result = await apiRequest<FlagApiResponse & { flag?: { productTitle?: string | null } }>(\n apiUrl, token, \"POST\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/product`,\n { productCardId: clear ? null : productCardId }\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(\n clear\n ? `Cleared product link for ${name}`\n : `Linked ${name} to product ${result.flag?.productTitle ?? productCardId}`\n );\n}\n\nasync function handleProducts(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, \"--json\");\n const search = getArgValue(argv, \"--search\");\n const path = search\n ? `/superadmin/product-cards?search=${encodeURIComponent(search)}`\n : \"/superadmin/product-cards\";\n const products = await fetchList<ProductCard>(apiUrl, token, path, \"products\");\n\n if (jsonOutput) {\n console.log(JSON.stringify(products, null, 2));\n return;\n }\n\n if (products.length === 0) {\n console.log(\"No product cards found.\");\n return;\n }\n\n for (const product of products) {\n console.log(` ${product.id} ${product.title} (stage=${product.stage}, org=${product.orgName})`);\n }\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag delete <name>\");\n process.exit(1);\n }\n\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"DELETE\", `/superadmin/feature-flags/${encodeURIComponent(name)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Deleted feature flag: ${name}`);\n}\n\nasync function handleEnable(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n const orgId = getArgValue(argv, \"--org\");\n const userId = getArgValue(argv, \"--user\");\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag enable <name> (--org <orgId> | --user <userId>)\");\n process.exit(1);\n }\n\n if (orgId && userId) {\n console.error(\"Error: Provide either --org or --user, not both.\");\n process.exit(1);\n }\n\n if (!orgId && !userId) {\n console.error(\"Error: Provide either --org <orgId> or --user <userId>.\");\n console.error(\"Usage: canary feature-flag enable <name> (--org <orgId> | --user <userId>)\");\n process.exit(1);\n }\n\n if (orgId) {\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"POST\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Enabled ${name} for org ${orgId}`);\n } else {\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"POST\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/users/${encodeURIComponent(userId!)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Enabled ${name} for user ${userId}`);\n }\n}\n\nasync function handleDisable(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n const orgId = getArgValue(argv, \"--org\");\n const userId = getArgValue(argv, \"--user\");\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag disable <name> (--org <orgId> | --user <userId>)\");\n process.exit(1);\n }\n\n if (orgId && userId) {\n console.error(\"Error: Provide either --org or --user, not both.\");\n process.exit(1);\n }\n\n if (!orgId && !userId) {\n console.error(\"Error: Provide either --org <orgId> or --user <userId>.\");\n console.error(\"Usage: canary feature-flag disable <name> (--org <orgId> | --user <userId>)\");\n process.exit(1);\n }\n\n if (orgId) {\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"DELETE\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Disabled ${name} for org ${orgId}`);\n } else {\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"DELETE\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/users/${encodeURIComponent(userId!)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Disabled ${name} for user ${userId}`);\n }\n}\n\nasync function handleLifecycle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag lifecycle <name> --stage <active|deprecated|ready_for_cleanup> [--final-value true|false]\");\n process.exit(1);\n }\n\n const stage = parseLifecycleStage(argv);\n const rawFinalValue = getArgValue(argv, \"--final-value\");\n const clearFinalValue = hasFlag(argv, \"--clear-final-value\");\n\n if (rawFinalValue !== undefined && clearFinalValue) {\n console.error(\"Error: use either --final-value or --clear-final-value, not both.\");\n process.exit(1);\n }\n\n let finalValue: boolean | undefined = undefined;\n\n if (stage === \"active\") {\n if (rawFinalValue !== undefined) {\n console.error(\"Error: active stage does not accept --final-value.\");\n process.exit(1);\n }\n finalValue = undefined;\n } else {\n if (clearFinalValue) {\n console.error(\"Error: --clear-final-value can only be used with --stage active.\");\n process.exit(1);\n }\n if (!rawFinalValue) {\n console.error(\"Error: --final-value true|false is required for deprecated or ready_for_cleanup.\");\n process.exit(1);\n }\n if (rawFinalValue !== \"true\" && rawFinalValue !== \"false\") {\n console.error(\"Error: --final-value must be true or false.\");\n process.exit(1);\n }\n finalValue = rawFinalValue === \"true\";\n }\n\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"POST\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/lifecycle`,\n { stage, finalValue }\n );\n\n if (!result.ok || !result.flag) {\n console.error(`Error: ${result.error ?? \"Failed to update lifecycle\"}`);\n process.exit(1);\n }\n\n const final =\n result.flag.lifecycleStage === \"active\"\n ? \"(none)\"\n : result.flag.finalValue === true\n ? \"true\"\n : \"false\";\n console.log(`Updated lifecycle for ${name}: stage=${toLifecycleLabel(result.flag.lifecycleStage)}, final=${final}`);\n}\n\nfunction printFeatureFlagHelp(): void {\n console.log(\n [\n \"Usage: canary feature-flag <sub-command> [options]\",\n \"\",\n \"Sub-commands:\",\n \" list List all feature flags\",\n \" create <name> [--description <text>] [--product <productCardId>]\",\n \" Create a new flag (optionally linked to a product)\",\n \" delete <name> Delete a flag and all its gates\",\n \" enable <name> (--org <orgId> | --user <userId>)\",\n \" Enable a flag for an org or user\",\n \" disable <name> (--org <orgId> | --user <userId>)\",\n \" Disable a flag for an org or user (kept as 'was enabled' history)\",\n \" lifecycle <name> --stage <stage> [--final-value true|false]\",\n \" Mark lifecycle + final value\",\n \" product <name> (--product <productCardId> | --clear)\",\n \" Link/unlink a flag to a product board item\",\n \" products [--search <text>] List product board items (find product card ids)\",\n \"\",\n \"Stages: active, deprecated, ready_for_cleanup\",\n \"\",\n \"Options:\",\n \" --org <orgId> Target organization\",\n \" --user <userId> Target user\",\n \" --product <productCardId> Product board item (cards.id) to link\",\n \" --clear Clear the product link (product sub-command only)\",\n \" --search <text> Filter product cards by title (products sub-command only)\",\n \" --final-value <true|false> Final value for deprecated/ready_for_cleanup\",\n \" --clear-final-value Clear final value (only valid with --stage active)\",\n \" --env <env> Target environment (prod, dev, local)\",\n \" --json Output as JSON (list only)\",\n \" --api-url <url> API URL override (takes precedence over --env)\",\n \" --token <key> API token override\",\n ].join(\"\\n\")\n );\n}\n\nexport async function runFeatureFlag(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === \"help\" || hasFlag(argv, \"--help\", \"-h\")) {\n printFeatureFlagHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case \"list\":\n await handleList(rest, apiUrl, token);\n break;\n case \"create\":\n await handleCreate(rest, apiUrl, token);\n break;\n case \"delete\":\n await handleDelete(rest, apiUrl, token);\n break;\n case \"enable\":\n await handleEnable(rest, apiUrl, token);\n break;\n case \"disable\":\n await handleDisable(rest, apiUrl, token);\n break;\n case \"lifecycle\":\n await handleLifecycle(rest, apiUrl, token);\n break;\n case \"product\":\n await handleProduct(rest, apiUrl, token);\n break;\n case \"products\":\n await handleProducts(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printFeatureFlagHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/knobs.ts"],"sourcesContent":["/**\n * CLI Knobs Management\n *\n * Allows superadmins to manage knobs (global config) via the CLI.\n */\n\nimport process from \"node:process\";\nimport { resolveConfig, getArgValue, hasFlag } from \"./auth.js\";\nimport {\n type LifecycleStage,\n toLifecycleLabel,\n parseLifecycleStage,\n apiRequest,\n fetchList,\n} from \"./cli-helpers.js\";\n\ntype SerializedKnob = {\n key: string;\n description: string | null;\n valueType: \"boolean\" | \"string\" | \"number\" | \"json\";\n value: unknown;\n lifecycleStage: LifecycleStage;\n finalValue: unknown;\n updatedAt: string | null;\n updatedBy: string | null;\n createdAt: string | null;\n isStale: boolean;\n};\n\ntype KnobApiResponse = {\n ok: boolean;\n error?: string;\n knob?: SerializedKnob;\n};\n\nfunction formatValue(valueType: SerializedKnob[\"valueType\"], value: unknown): string {\n if (valueType === \"json\") return JSON.stringify(value);\n return String(value);\n}\n\nfunction formatFinalValue(knob: SerializedKnob): string {\n if (knob.lifecycleStage === \"active\") return \"(none)\";\n return formatValue(knob.valueType, knob.finalValue);\n}\n\nfunction parseTypedValue(raw: string, valueType: SerializedKnob[\"valueType\"]): unknown {\n switch (valueType) {\n case \"boolean\":\n if (raw !== \"true\" && raw !== \"false\") {\n console.error('Error: Boolean value must be \"true\" or \"false\".');\n process.exit(1);\n }\n return raw === \"true\";\n case \"string\":\n return raw;\n case \"number\": {\n const num = parseFloat(raw);\n if (Number.isNaN(num)) {\n console.error(`Error: Invalid number: ${raw}`);\n process.exit(1);\n }\n return num;\n }\n case \"json\":\n try {\n return JSON.parse(raw);\n } catch {\n console.error(`Error: Invalid JSON: ${raw}`);\n process.exit(1);\n }\n }\n}\n\nfunction fetchKnobs(apiUrl: string, token: string): Promise<SerializedKnob[]> {\n return fetchList<SerializedKnob>(apiUrl, token, \"/superadmin/knobs\", \"knobs\");\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, \"--json\");\n const knobs = await fetchKnobs(apiUrl, token);\n\n if (jsonOutput) {\n console.log(JSON.stringify(knobs, null, 2));\n return;\n }\n\n if (knobs.length === 0) {\n console.log(\"No knobs found.\");\n return;\n }\n\n for (const knob of knobs) {\n const desc = knob.description ? ` ${knob.description}` : \"\";\n const lifecycle = `lifecycle=${toLifecycleLabel(knob.lifecycleStage)}`;\n const finalValue =\n knob.lifecycleStage === \"active\" ? \"\" : ` final=${formatFinalValue(knob)}`;\n const stale = knob.isStale ? \" [STALE]\" : \"\";\n console.log(\n ` ${knob.key} [${knob.valueType}] = ${formatValue(knob.valueType, knob.value)} (${lifecycle}${finalValue})${desc}${stale}`\n );\n }\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs get <key>\");\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, \"--json\");\n const knobs = await fetchKnobs(apiUrl, token);\n const knob = knobs.find((k) => k.key === key);\n\n if (!knob) {\n console.error(`Knob not found: ${key}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(knob, null, 2));\n return;\n }\n\n console.log(` Key: ${knob.key}`);\n console.log(` Type: ${knob.valueType}`);\n console.log(` Value: ${formatValue(knob.valueType, knob.value)}`);\n console.log(` Lifecycle: ${toLifecycleLabel(knob.lifecycleStage)}`);\n console.log(` Final value: ${formatFinalValue(knob)}`);\n console.log(` Description: ${knob.description ?? \"(none)\"}`);\n console.log(` Updated: ${knob.updatedAt ?? \"(never)\"}`);\n if (knob.isStale) {\n console.log(` Status: STALE (no changes in 30+ days)`);\n }\n}\n\nasync function handleSet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs set <key> <value> --type <boolean|string|number|json> [--description <text>]\");\n process.exit(1);\n }\n\n const rawValue = argv[1];\n if (rawValue === undefined || rawValue.startsWith(\"--\")) {\n console.error(\"Error: Missing knob value.\");\n console.error(\"Usage: canary knobs set <key> <value> --type <boolean|string|number|json> [--description <text>]\");\n process.exit(1);\n }\n\n const valueType = getArgValue(argv, \"--type\") as SerializedKnob[\"valueType\"] | undefined;\n if (!valueType || ![\"boolean\", \"string\", \"number\", \"json\"].includes(valueType)) {\n console.error(\"Error: --type is required and must be one of: boolean, string, number, json\");\n process.exit(1);\n }\n\n const value = parseTypedValue(rawValue, valueType);\n const description = getArgValue(argv, \"--description\") ?? undefined;\n\n const result = await apiRequest<KnobApiResponse>(apiUrl, token, \"POST\", \"/superadmin/knobs\", {\n key,\n valueType,\n value,\n description,\n });\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Set knob: ${key} = ${formatValue(valueType, result.knob?.value)}`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs delete <key>\");\n process.exit(1);\n }\n\n const result = await apiRequest<KnobApiResponse>(\n apiUrl, token, \"DELETE\", `/superadmin/knobs/${encodeURIComponent(key)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Deleted knob: ${key}`);\n}\n\nasync function handleToggle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs toggle <key>\");\n process.exit(1);\n }\n\n const result = await apiRequest<KnobApiResponse>(\n apiUrl, token, \"POST\", `/superadmin/knobs/${encodeURIComponent(key)}/toggle`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n const knob = result.knob;\n console.log(`Toggled knob: ${key} -> ${formatValue(knob?.valueType ?? \"boolean\", knob?.value)}`);\n}\n\nasync function handleLifecycle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs lifecycle <key> --stage <active|deprecated|ready_for_cleanup> [--final-value <value>]\");\n process.exit(1);\n }\n\n const stage = parseLifecycleStage(argv);\n const rawFinalValue = getArgValue(argv, \"--final-value\");\n const clearFinalValue = hasFlag(argv, \"--clear-final-value\");\n\n if (rawFinalValue !== undefined && clearFinalValue) {\n console.error(\"Error: use either --final-value or --clear-final-value, not both.\");\n process.exit(1);\n }\n\n const knobs = await fetchKnobs(apiUrl, token);\n const knob = knobs.find((k) => k.key === key);\n\n if (!knob) {\n console.error(`Knob not found: ${key}`);\n process.exit(1);\n }\n\n let finalValue: unknown = undefined;\n\n if (stage === \"active\") {\n if (rawFinalValue !== undefined) {\n console.error(\"Error: active stage does not accept --final-value. Use --stage deprecated|ready_for_cleanup.\");\n process.exit(1);\n }\n finalValue = clearFinalValue ? undefined : undefined;\n } else {\n if (clearFinalValue) {\n console.error(\"Error: --clear-final-value can only be used with --stage active.\");\n process.exit(1);\n }\n if (rawFinalValue === undefined) {\n console.error(\"Error: --final-value is required when stage is deprecated or ready_for_cleanup.\");\n process.exit(1);\n }\n finalValue = parseTypedValue(rawFinalValue, knob.valueType);\n }\n\n const result = await apiRequest<KnobApiResponse>(\n apiUrl, token, \"POST\", `/superadmin/knobs/${encodeURIComponent(key)}/lifecycle`,\n { stage, finalValue }\n );\n\n if (!result.ok || !result.knob) {\n console.error(`Error: ${result.error ?? \"Failed to update lifecycle\"}`);\n process.exit(1);\n }\n\n console.log(\n `Updated lifecycle for ${key}: stage=${toLifecycleLabel(result.knob.lifecycleStage)}, final=${formatFinalValue(result.knob)}`\n );\n}\n\nfunction printKnobsHelp(): void {\n console.log(\n [\n \"Usage: canary knobs <sub-command> [options]\",\n \"\",\n \"Sub-commands:\",\n \" list List all knobs\",\n \" get <key> Get a knob value\",\n \" set <key> <value> --type <type> [--description <text>]\",\n \" Set a knob value\",\n \" delete <key> Delete a knob\",\n \" toggle <key> Toggle a boolean knob\",\n \" lifecycle <key> --stage <stage> [--final-value <value>]\",\n \" Mark knob lifecycle + final value\",\n \"\",\n \"Types: boolean, string, number, json\",\n \"Stages: active, deprecated, ready_for_cleanup\",\n \"\",\n \"Options:\",\n \" --final-value <value> Final value for deprecated/ready_for_cleanup\",\n \" --clear-final-value Clear final value (only valid with --stage active)\",\n \" --env <env> Target environment (prod, dev, local)\",\n \" --json Output as JSON (list/get only)\",\n \" --api-url <url> API URL override (takes precedence over --env)\",\n \" --token <key> API token override\",\n ].join(\"\\n\")\n );\n}\n\nexport async function runKnobs(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === \"help\" || hasFlag(argv, \"--help\", \"-h\")) {\n printKnobsHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case \"list\":\n await handleList(rest, apiUrl, token);\n break;\n case \"get\":\n await handleGet(rest, apiUrl, token);\n break;\n case \"set\":\n await handleSet(rest, apiUrl, token);\n break;\n case \"delete\":\n await handleDelete(rest, apiUrl, token);\n break;\n case \"toggle\":\n await handleToggle(rest, apiUrl, token);\n break;\n case \"lifecycle\":\n await handleLifecycle(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printKnobsHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/redis.ts"],"sourcesContent":["/**\n * CLI Redis Passthrough\n *\n * Allows superadmins to execute read-only Redis commands against the production cache.\n */\n\nimport process from \"node:process\";\nimport { resolveConfig } from \"./auth.js\";\nimport { fetchOrExit } from \"./api-fetch.js\";\n\nconst MAX_COMMAND_SIZE = 10_000; // 10KB - reasonable for interactive use\n\ntype RedisResponse = {\n ok: boolean;\n data?: unknown;\n durationMs?: number;\n error?: string;\n code?: \"DISABLED\" | \"BLOCKED\";\n};\n\nfunction getArgValue(argv: string[], key: string): string | undefined {\n const index = argv.indexOf(key);\n if (index === -1 || index >= argv.length - 1) return undefined;\n return argv[index + 1];\n}\n\nfunction hasFlag(argv: string[], ...flags: string[]): boolean {\n return flags.some((flag) => argv.includes(flag));\n}\n\n/**\n * Formats Redis response for display.\n */\nfunction formatOutput(data: unknown): string {\n if (data === null) {\n return \"(nil)\";\n }\n\n if (typeof data === \"string\") {\n return data;\n }\n\n if (typeof data === \"number\") {\n return `(integer) ${data}`;\n }\n\n if (Array.isArray(data)) {\n if (data.length === 0) {\n return \"(empty array)\";\n }\n return data\n .map((item, index) => `${index + 1}) ${formatOutput(item)}`)\n .join(\"\\n\");\n }\n\n if (typeof data === \"object\") {\n return JSON.stringify(data, null, 2);\n }\n\n return String(data);\n}\n\nexport async function runRedis(argv: string[]): Promise<void> {\n const { apiUrl, token } = await resolveConfig(argv);\n\n const jsonOutput = hasFlag(argv, \"--json\");\n\n // Get command: remaining args after filtering flags\n const flagsWithValues = [\"--api-url\", \"--token\", \"--env\"];\n const commandParts: string[] = [];\n for (let i = 0; i < argv.length; i++) {\n if (flagsWithValues.includes(argv[i])) {\n i++; // Skip flag value\n continue;\n }\n if (argv[i].startsWith(\"--\")) continue;\n commandParts.push(argv[i]);\n }\n const command = commandParts.join(\" \");\n\n if (!command) {\n console.error(\"Error: No command provided.\");\n console.error(\"\");\n console.error(\"Usage: canary redis <command> [--json]\");\n console.error(' canary redis KEYS \"job:*\"');\n console.error(\"\");\n console.error(\"Examples:\");\n console.error(\" canary redis PING\");\n console.error(\" canary redis INFO\");\n console.error(' canary redis KEYS \"job:*\"');\n console.error(' canary redis HGETALL \"job:123:status\"');\n console.error(' canary redis GET \"some:key\" --json');\n process.exit(1);\n }\n\n if (command.length > MAX_COMMAND_SIZE) {\n console.error(`Error: Command too large (${command.length} chars, max ${MAX_COMMAND_SIZE})`);\n process.exit(1);\n }\n\n try {\n const res = await fetchOrExit(`${apiUrl}/superadmin/redis`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n token,\n body: JSON.stringify({ command }),\n });\n\n // Handle HTTP errors before parsing JSON\n if (!res.ok) {\n const text = await res.text();\n\n if (res.status === 404) {\n console.error(\"Error: Endpoint not found. The redis feature may not be deployed to this environment.\");\n process.exit(1);\n }\n\n // Try to parse error as JSON, fallback to raw text\n try {\n const errorJson = JSON.parse(text) as { error?: string };\n console.error(`Error: ${errorJson.error ?? text}`);\n } catch {\n console.error(`Error (${res.status}): ${text || res.statusText}`);\n }\n process.exit(1);\n }\n\n const json_response = (await res.json()) as RedisResponse;\n\n if (!json_response.ok) {\n console.error(`Error: ${json_response.error}`);\n if (json_response.code === \"BLOCKED\") {\n console.error(\"The Redis debugging feature has been disabled due to this blocked command.\");\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(json_response.data, null, 2));\n } else {\n console.log(formatOutput(json_response.data));\n console.log(`\\nTime: ${json_response.durationMs}ms`);\n }\n } catch (err) {\n console.error(`Failed to execute command: ${err}`);\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sandbox.ts"],"sourcesContent":["/**\n * CLI Sandbox Management\n *\n * Create, provision, and manage sandbox templates and instances.\n * Drive template authoring through artifact uploads, command execution,\n * and diagnostics — designed for Claude Code to iterate on sandbox setup.\n */\n\nimport process from 'node:process';\nimport { readFileSync } from 'node:fs';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest, selectProperty } from './cli-helpers.js';\nimport { apiFetch, isTerminalFailure, exitOnFailure } from './api-fetch.js';\nimport { SANDBOX_GUIDE_SECTIONS, printGuide } from '@chatsdet/content';\nimport { INSTANCE_SIZES, INSTANCE_SIZE_SPEC, parseInstanceSize, type InstanceSize } from '@chatsdet/types';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Template = {\n id: string;\n name: string;\n propertyId: string | null;\n repositoryFullName: string;\n branch: string;\n subdirectory: string | null;\n status: string;\n checklistProfile: string | null;\n configSchema: Array<{ key: string; description?: string; required: boolean; sensitive: boolean }> | null;\n configDefaults: Record<string, string> | null;\n createdAt: string;\n updatedAt: string;\n};\n\ntype GitHubRepo = {\n id: string;\n repoFullName: string;\n repoName: string;\n defaultBranch: string;\n rootDir: string | null;\n agentHint: string | null;\n};\n\ntype Instance = {\n id: string;\n templateId: string;\n name: string;\n status: string;\n hostUrl: string | null;\n isPrivate: boolean;\n expiresAt: string | null;\n createdAt: string;\n};\n\ntype Artifact = {\n id: string;\n taskId: string;\n artifactType: string;\n filename: string;\n content?: string;\n createdAt: string;\n updatedAt: string;\n};\n\ntype ChecklistItem = {\n id: string;\n label: string;\n description: string;\n dependsOn: string[];\n producesArtifacts: string[];\n agentAutomatable: boolean;\n itemStatus: { status: string; startedAt?: string; completedAt?: string; summary?: string; error?: string };\n actionable: boolean;\n artifacts: Array<{ artifactType: string; filename: string }>;\n};\n\ntype CommandOrError = { stdout: string; stderr: string; exitCode: number } | { error: string };\n\ntype DiagnosticsResult = {\n instance: Record<string, unknown>;\n docker: CommandOrError;\n git: CommandOrError;\n disk: CommandOrError;\n agentHealth: CommandOrError;\n appHealth: CommandOrError;\n provision?: {\n phase: string;\n jobStatus: string;\n startedAt?: string;\n elapsedSeconds: number | null;\n lastError?: string;\n };\n};\n\ntype ServiceRoute = { service: string; route: string; port: string };\n\nasync function fetchInstanceRoutes(apiUrl: string, token: string, instanceId: string): Promise<ServiceRoute[]> {\n const res = await apiRequest<{ ok: boolean; error?: string; data: { routes: ServiceRoute[] } }>(\n apiUrl, token, 'GET', `/org/environments/instances/${instanceId}/routes`,\n undefined,\n { timeoutMs: 30_000 }\n );\n return res.ok ? res.data.routes : [];\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst STATUS_ICONS: Record<string, string> = {\n completed: '[done]',\n running: '[....]',\n pending: '[ ]',\n failed: '[FAIL]',\n skipped: '[skip]',\n};\n\nfunction formatDate(iso: string): string {\n return new Date(iso).toLocaleString();\n}\n\nfunction pad(s: string, n: number): string {\n return s.padEnd(n);\n}\n\nconst INSTANCE_SIZE_HELP_LINES = INSTANCE_SIZES.map((size) => {\n const spec = INSTANCE_SIZE_SPEC[size];\n return ` ${pad(size, 8)} ${spec.ec2InstanceType} · ${spec.vcpu} vCPU · ${spec.memoryMiB / 1024} GiB`;\n});\n\n// ---------------------------------------------------------------------------\n// Help\n// ---------------------------------------------------------------------------\n\nfunction printHelp(): void {\n console.log(\n [\n 'canary sandbox: Manage sandbox templates and instances',\n '',\n 'Sub-commands:',\n ' guide [section] Show sandbox authoring guide',\n ' list List templates and instances',\n ' template [id] Show template details',\n ' repo list --template <id> List repos linked to a template',\n ' repo add --template <id> --property-github-repo-id <uuid> [--role <r>] [--spec <r=owner/name@branch:subdir>]',\n ' repo update --template <id> --link-id <uuid> [--role <r>] [--branch <b>] [--subdirectory <s>] [--service-name <n>]',\n ' repo remove --template <id> --link-id <uuid>',\n ' checklist <template-id> Show checklist state',\n ' checklist skip <template-id> <item-id> Skip a checklist item',\n ' checklist complete <template-id> <item-id> [options] Mark item complete from CLI',\n ' artifacts <template-id> List artifacts',\n ' artifact get <template-id> <type> Get artifact content',\n ' artifact create <template-id> <type> <file> Upload artifact (use --path for file type)',\n ' create [property] [options] Create template from property (triggers provisioning)',\n ' provision <template-id> [options] Create instance from verified template',\n ' verify <template-id> Verify an authoring template (provision + probe + flip to verified)',\n ' set-size <template-id> <size> Set EC2 size for next provision (see \"Instance sizes\" below)',\n ' ami list <template-id> List per-template AMI history',\n ' ami rebake <template-id> [opts] Trigger a fresh AMI bake (--force, --wait)',\n ' ami use <template-id> <ami-row-id> Switch the template to a specific AMI (rollback)',\n ' build <instance-id> Build and start app services on sandbox',\n ' run-command <instance-id> <command...> Execute shell command on sandbox',\n ' --service <name> Run inside a Docker container instead of on the host VM',\n ' diagnostics <instance-id> Show sandbox diagnostics',\n ' logs <instance-id> [options] Show container logs',\n ' terminate <instance-id> Terminate an instance',\n ' config list <template-id> Show config schema and defaults',\n ' config set <template-id> <key> <value> Set a config default value',\n ' delete <template-id> Delete template and all instances',\n '',\n 'Create options:',\n ' --property <name|id> Property (prompted if omitted, auto-selected if only one)',\n ' --branch <branch> Branch (default: from linked repo)',\n ' --name <name> Template name (default: repo name)',\n ' --subdirectory <path> Subdirectory (default: from linked repo rootDir)',\n ' --size <size> EC2 size for first authoring sandbox (default: medium; see \"Instance sizes\" below)',\n '',\n 'Provision options:',\n ' --name <name> Instance name',\n ' --ttl <hours> Time to live in hours (default: 8)',\n ' --with-agent Start with sandbox agent',\n '',\n 'Artifact get options:',\n ' --output <file> Write to file instead of stdout',\n '',\n 'Logs options:',\n ' --service <name> Service name (default: all services)',\n ' --tail <n> Number of lines (default: 200)',\n '',\n 'Guide sections:',\n ' goal, research, artifacts, actions, verify, checklist',\n '',\n 'Instance sizes:',\n ...INSTANCE_SIZE_HELP_LINES,\n '',\n 'Action sub-commands:',\n ' action list <template-id> List actions for a template',\n ' action get <template-id> <slug> Show action definition + script',\n ' action create <template-id> <slug> [opts] Create or update an action',\n ' action delete <template-id> <slug> Delete an action',\n ' action execute <instance-id> <slug> [opts] Execute action on a running instance',\n ' action executions <instance-id> [opts] List execution history',\n '',\n 'Action create options:',\n ' --label <label> Display name (default: slug → Title Case)',\n ' --description <text> Description',\n ' --icon <icon> Phosphor icon name',\n ' --script <file> Path to script file (bash)',\n ' --input-schema <file> Path to JSON Schema file for input params',\n ' --output-schema <file> Path to JSON Schema file for output',\n ' --credential-output-config <file> JSON file with ActionCredentialOutputConfig (auto-creates a Canary credential from the action result)',\n ' --credential-template <id> Credential template this action provisions; login nodes using it auto-provision',\n ' --provisioning-mode <shared|unique> shared = provision once / reused (default); unique = one credential per run (script must accept a runId input param)',\n ' --timeout <ms> Timeout in ms (default: 55000)',\n ' --encrypt-script Encrypt script content at rest',\n '',\n 'Action execute options:',\n ' --param <key>=<value> Set parameter (repeatable)',\n ' --params-file <file> JSON file with all params',\n '',\n 'Global options:',\n ' --json Output raw JSON',\n ' --env <env> Environment (prod, dev, local)',\n ' -h, --help Show help',\n ].join('\\n')\n );\n}\n\n// ---------------------------------------------------------------------------\n// Sub-command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const json = hasFlag(argv, '--json');\n\n const [templatesRes, instancesRes] = await Promise.all([\n apiRequest<{ ok: boolean; error?: string; data: Template[] }>(\n apiUrl, token, 'GET', '/org/environments/templates'\n ),\n apiRequest<{ ok: boolean; error?: string; data: Instance[] }>(\n apiUrl, token, 'GET', '/org/environments/instances'\n ),\n ]);\n\n if (!templatesRes.ok) {\n console.error(`Error: ${templatesRes.error}`);\n process.exit(1);\n }\n if (!instancesRes.ok) {\n console.error(`Error loading instances: ${instancesRes.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify({ templates: templatesRes.data, instances: instancesRes.data }, null, 2));\n return;\n }\n\n const templates = templatesRes.data ?? [];\n const instances = instancesRes.data ?? [];\n\n console.log('Templates:');\n if (templates.length === 0) {\n console.log(' (none)');\n } else {\n console.log(` ${pad('ID', 38)} ${pad('Name', 24)} ${pad('Status', 14)} ${pad('Profile', 12)} Repository`);\n for (const t of templates) {\n console.log(` ${pad(t.id, 38)} ${pad(t.name, 24)} ${pad(t.status, 14)} ${pad(t.checklistProfile ?? '-', 12)} ${t.repositoryFullName}:${t.branch}`);\n }\n }\n\n console.log('');\n console.log('Instances:');\n if (instances.length === 0) {\n console.log(' (none)');\n } else {\n console.log(` ${pad('ID', 38)} ${pad('Status', 14)} ${pad('Access', 10)} ${pad('Template', 38)} Expires`);\n for (const i of instances) {\n const access = i.isPrivate ? 'private' : 'public';\n console.log(` ${pad(i.id, 38)} ${pad(i.status, 14)} ${pad(access, 10)} ${pad(i.templateId, 38)} ${i.expiresAt ? formatDate(i.expiresAt) : '-'}`);\n }\n }\n}\n\nasync function handleTemplate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [id] = argv.filter((a) => !a.startsWith('-'));\n const json = hasFlag(argv, '--json');\n\n if (!id) {\n await handleList(argv, apiUrl, token);\n return;\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: Template }>(\n apiUrl, token, 'GET', `/org/environments/templates/${id}`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n const t = res.data;\n console.log(`Template: ${t.name}`);\n console.log(` ID: ${t.id}`);\n console.log(` Repository: ${t.repositoryFullName}:${t.branch}`);\n if (t.subdirectory) console.log(` Subdir: ${t.subdirectory}`);\n console.log(` Status: ${t.status}`);\n console.log(` Profile: ${t.checklistProfile ?? 'full-stack (default)'}`);\n console.log(` Created: ${formatDate(t.createdAt)}`);\n console.log(` Updated: ${formatDate(t.updatedAt)}`);\n\n if (t.configSchema && t.configSchema.length > 0) {\n console.log('');\n console.log(' Config Schema:');\n for (const c of t.configSchema) {\n const flags = [c.required ? 'required' : 'optional', c.sensitive ? 'sensitive' : ''].filter(Boolean).join(', ');\n console.log(` ${c.key} (${flags})${c.description ? ` — ${c.description}` : ''}`);\n }\n }\n}\n\nasync function handleArtifacts(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [templateId] = argv.filter((a) => !a.startsWith('-'));\n const json = hasFlag(argv, '--json');\n\n if (!templateId) {\n console.error('Error: template ID required. Usage: canary sandbox artifacts <template-id>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: Artifact[] }>(\n apiUrl, token, 'GET', `/org/environments/templates/${templateId}/artifacts`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n const artifacts = res.data ?? [];\n if (artifacts.length === 0) {\n console.log('No artifacts found.');\n return;\n }\n\n console.log(`${pad('Type', 22)} ${pad('Filename', 30)} ${pad('Task', 24)} Created`);\n for (const a of artifacts) {\n console.log(`${pad(a.artifactType, 22)} ${pad(a.filename, 30)} ${pad(a.taskId, 24)} ${formatDate(a.createdAt)}`);\n }\n}\n\nasync function handleChecklist(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const json = hasFlag(argv, '--json');\n\n // Handle checklist sub-commands: skip, complete\n if (positional[0] === 'skip') {\n await handleChecklistSkip(argv.slice(1), apiUrl, token);\n return;\n }\n if (positional[0] === 'complete') {\n await handleChecklistComplete(argv.slice(1), apiUrl, token);\n return;\n }\n\n const templateId = positional[0];\n if (!templateId) {\n console.error('Error: template ID required. Usage: canary sandbox checklist <template-id>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: ChecklistItem[] }>(\n apiUrl, token, 'GET', `/org/environments/templates/${templateId}/checklist`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n const items = res.data ?? [];\n if (items.length === 0) {\n console.log('No checklist items.');\n return;\n }\n\n console.log('Checklist:');\n for (const item of items) {\n const icon = STATUS_ICONS[item.itemStatus.status] ?? '[????]';\n const actionable = item.actionable ? ' *' : '';\n console.log(` ${icon} ${item.label}${actionable}`);\n if (item.itemStatus.summary) {\n console.log(` ${item.itemStatus.summary}`);\n }\n if (item.itemStatus.error) {\n console.log(` ERROR: ${item.itemStatus.error}`);\n }\n if (item.artifacts.length > 0) {\n console.log(` Artifacts: ${item.artifacts.map((a) => a.artifactType).join(', ')}`);\n }\n }\n console.log('');\n console.log(' * = actionable (deps met, ready to run)');\n}\n\nasync function handleChecklistSkip(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const itemId = positional[1];\n\n if (!templateId || !itemId) {\n console.error('Error: both template ID and item ID required. Usage: canary sandbox checklist skip <template-id> <item-id>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl, token, 'POST', `/org/environments/templates/${templateId}/checklist/${itemId}/skip`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n console.log(`Skipped checklist item: ${itemId}`);\n}\n\nasync function handleChecklistComplete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const itemId = positional[1];\n\n const json = hasFlag(argv, '--json');\n\n if (!templateId || !itemId) {\n console.error('Error: both template ID and item ID required.');\n console.error('Usage: canary sandbox checklist complete <template-id> <item-id> [--status success|failed] [--summary \"...\"]');\n process.exit(1);\n }\n\n const status = getArgValue(argv, '--status') ?? 'success';\n const summary = getArgValue(argv, '--summary');\n const configSchemaArg = getArgValue(argv, '--config-schema');\n const healthCheckPath = getArgValue(argv, '--health-check-path');\n\n let configSchema: unknown;\n if (configSchemaArg) {\n // Accept inline JSON or a file path\n try {\n configSchema = JSON.parse(configSchemaArg);\n } catch {\n try {\n configSchema = JSON.parse(readFileSync(configSchemaArg, 'utf-8'));\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n console.error(`Error reading config schema from \"${configSchemaArg}\": ${msg}`);\n process.exit(1);\n }\n }\n }\n\n const body: Record<string, unknown> = {\n status: status === 'failed' ? 'failed' : 'completed',\n ...(summary ? { summary } : {}),\n ...(configSchema ? { configSchema } : {}),\n ...(healthCheckPath ? { healthCheckPath } : {}),\n };\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: { itemId: string; status: string } }>(\n apiUrl, token, 'POST', `/org/environments/templates/${templateId}/checklist/${itemId}/complete`, body\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n console.log(`Completed checklist item: ${itemId} (${res.data?.status})`);\n}\n\nasync function handleConfigList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const json = hasFlag(argv, '--json');\n\n if (!templateId) {\n console.error('Error: template ID required. Usage: canary sandbox config list <template-id>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: Template }>(\n apiUrl, token, 'GET', `/org/environments/templates/${templateId}`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n const t = res.data;\n const schema = t.configSchema ?? [];\n const defaults = t.configDefaults ?? {};\n\n if (json) {\n console.log(JSON.stringify({ configSchema: schema, configDefaults: defaults }, null, 2));\n return;\n }\n\n if (schema.length === 0) {\n console.log('No config schema defined for this template.');\n return;\n }\n\n console.log('Config Schema:');\n for (const item of schema) {\n const value = defaults[item.key];\n const display = item.sensitive && value ? '••••••••' : (value ?? '(not set)');\n const required = item.required ? ' (required)' : '';\n const sensitive = item.sensitive ? ' [sensitive]' : '';\n console.log(` ${item.key}${required}${sensitive}`);\n if (item.description) console.log(` ${item.description}`);\n console.log(` Value: ${display}`);\n }\n}\n\nasync function handleConfigSet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const fromStdin = hasFlag(argv, '--value-stdin');\n const templateId = positional[0];\n const key = positional[1];\n let value = positional[2];\n\n if (!templateId || !key) {\n console.error('Error: template ID and key required.');\n console.error('Usage: canary sandbox config set <template-id> <key> <value>');\n console.error(' For sensitive values: echo \"sk-ant-...\" | canary sandbox config set <template-id> <key> --value-stdin');\n process.exit(1);\n }\n\n if (fromStdin) {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(chunk as Buffer);\n value = Buffer.concat(chunks).toString('utf-8').trim();\n }\n\n if (value === undefined) {\n console.error('Error: value required. Pass as argument or use --value-stdin');\n process.exit(1);\n }\n\n // First get current defaults to merge\n const getRes = await apiRequest<{ ok: boolean; error?: string; data: Template }>(\n apiUrl, token, 'GET', `/org/environments/templates/${templateId}`\n );\n if (!getRes.ok) {\n console.error(`Error: ${getRes.error}`);\n process.exit(1);\n }\n\n const currentDefaults = getRes.data?.configDefaults ?? {};\n const updatedDefaults = { ...currentDefaults, [key]: value };\n\n // The server may take longer than 30s to acknowledge config writes\n // (encrypted columns, audit log). Even when it does the write succeeds —\n // bump the CLI ceiling so the user sees the success rather than a\n // misleading timeout.\n const res = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl, token, 'PATCH', `/org/environments/templates/${templateId}/config`, {\n configDefaults: updatedDefaults,\n },\n { timeoutMs: 90_000 }\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n console.log(`Config set: ${key}`);\n}\n\nasync function handleSetSize(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [templateId, sizeArg] = argv.filter((a) => !a.startsWith('-'));\n\n if (!templateId || !sizeArg) {\n console.error('Error: template ID and size required.');\n console.error(`Usage: canary sandbox set-size <template-id> <${INSTANCE_SIZES.join('|')}>`);\n process.exit(1);\n }\n\n const size = parseInstanceSize(sizeArg);\n if (!size) {\n console.error(`Error: invalid size '${sizeArg}'. Must be one of: ${INSTANCE_SIZES.join(', ')}`);\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; instanceSize?: InstanceSize }>(\n apiUrl,\n token,\n 'PATCH',\n `/org/environments/templates/${templateId}/instance-size`,\n { instanceSize: size }\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n console.log(`Instance size set to ${size}`);\n}\n\nasync function handleCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const json = hasFlag(argv, '--json');\n\n // Resolve property — positional arg or --property flag, prompted if omitted\n const propertyHint = positional[0] ?? getArgValue(argv, '--property');\n const property = await selectProperty(apiUrl, token, propertyHint ?? undefined);\n if (!property) process.exit(1);\n\n // Fetch linked repos for the property\n const reposRes = await apiRequest<{ ok: boolean; error?: string; items: GitHubRepo[] }>(\n apiUrl, token, 'GET', `/org/properties/${property.id}/github-repos`\n );\n if (!reposRes.ok || !reposRes.items?.length) {\n console.error(`No GitHub repos linked to property \"${property.name}\". Link one first in the web app.`);\n process.exit(1);\n }\n\n const linkedRepo = reposRes.items[0];\n const branch = getArgValue(argv, '--branch') ?? linkedRepo.defaultBranch ?? 'main';\n const name = getArgValue(argv, '--name') ?? linkedRepo.repoName ?? linkedRepo.repoFullName.split('/').pop() ?? property.name;\n const subdirectory = getArgValue(argv, '--subdirectory') ?? linkedRepo.rootDir ?? undefined;\n\n const sizeArg = getArgValue(argv, '--size');\n const instanceSize = sizeArg ? parseInstanceSize(sizeArg) : undefined;\n if (sizeArg && !instanceSize) {\n console.error(`Error: invalid --size '${sizeArg}'. Must be one of: ${INSTANCE_SIZES.join(', ')}`);\n process.exit(1);\n }\n\n const body: Record<string, unknown> = {\n name,\n propertyId: property.id,\n repositoryFullName: linkedRepo.repoFullName,\n branch,\n };\n if (subdirectory) body.subdirectory = subdirectory;\n if (linkedRepo.agentHint) body.hints = linkedRepo.agentHint;\n if (instanceSize) body.instanceSize = instanceSize;\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: Template }>(\n apiUrl, token, 'POST', '/org/environments/templates', body\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n console.log(`Template created: ${res.data.id}`);\n console.log(` Property: ${property.name}`);\n console.log(` Repository: ${res.data.repositoryFullName}:${res.data.branch}`);\n console.log(` Status: ${res.data.status}`);\n console.log('');\n console.log('Authoring job enqueued. Poll status with:');\n console.log(` canary sandbox template ${res.data.id}`);\n}\n\nasync function handleProvision(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const json = hasFlag(argv, '--json');\n\n if (!templateId) {\n console.error('Error: template ID required. Usage: canary sandbox provision <template-id> [--ttl 8]');\n process.exit(1);\n }\n\n const name = getArgValue(argv, '--name') ?? `instance-${Date.now()}`;\n const ttl = parseInt(getArgValue(argv, '--ttl') ?? '8', 10);\n const withAgent = hasFlag(argv, '--with-agent');\n const isPrivate = hasFlag(argv, '--private');\n\n const body: Record<string, unknown> = {\n templateId,\n name,\n expiresInHours: ttl,\n userConfig: {},\n withAgent,\n isPrivate,\n };\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: Instance }>(\n apiUrl, token, 'POST', '/org/environments/instances', body\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n console.log(`Instance created: ${res.data.id}`);\n console.log(` Status: ${res.data.status}`);\n if (isPrivate) console.log(` Access: private (no public URL)`);\n console.log(` Expires: ${res.data.expiresAt ? formatDate(res.data.expiresAt) : '-'}`);\n}\n\nexport interface ContainerLine {\n name: string;\n status: string;\n state: 'up-healthy' | 'up' | 'up-unhealthy' | 'restarting' | 'exited' | 'other';\n}\n\n/**\n * Parse `docker ps --format '{{.Names}}\\t{{.Status}}\\t{{.Ports}}'` output\n * into a structured list. State classification is coarse — the verify loop\n * only needs to know \"is this container healthy / exited / restart-looping\".\n */\nexport function parseDockerPs(stdout: string): ContainerLine[] {\n const lines = stdout.split('\\n').map((l) => l.trim()).filter(Boolean);\n return lines.map((line) => {\n const [name = '', status = ''] = line.split('\\t');\n const lower = status.toLowerCase();\n let state: ContainerLine['state'] = 'other';\n if (lower.startsWith('restarting')) state = 'restarting';\n else if (lower.startsWith('exited')) state = 'exited';\n else if (lower.startsWith('up') && lower.includes('unhealthy')) state = 'up-unhealthy';\n else if (lower.startsWith('up') && lower.includes('healthy')) state = 'up-healthy';\n else if (lower.startsWith('up')) state = 'up';\n return { name, status, state };\n });\n}\n\n/** Containers that aren't cleanly up. Used to decide what to dump logs for. */\nexport function isBrokenContainer(c: ContainerLine): boolean {\n return c.state === 'restarting' || c.state === 'exited' || c.state === 'up-unhealthy';\n}\n\n/**\n * Map a container name back to its compose service.\n *\n * docker-compose names containers `<project>-<service>-<replica>`. The\n * sandbox platform sets the project to `workspace` via\n * `--project-directory /workspace` (see `SANDBOX_COMPOSE_BASE` in\n * apps/api/.../sandbox-cli/service.ts), so the common case is\n * `workspace-<svc>-<n>`. Fall back to stripping the trailing replica\n * index only, so attribution still works if the project name ever\n * changes or someone uses an explicit `container_name:` override.\n */\nexport function containerNameToService(containerName: string): string {\n const withProject = containerName.match(/^workspace-(.+)-\\d+$/);\n if (withProject) return withProject[1]!;\n const withoutProject = containerName.match(/^(.+)-\\d+$/);\n if (withoutProject) return withoutProject[1]!;\n return containerName;\n}\n\nasync function fetchServiceLogs(\n apiUrl: string,\n token: string,\n instanceId: string,\n service: string,\n tail: number\n): Promise<string> {\n const res = await apiRequest<{ ok: boolean; error?: string; data: { logs: string } }>(\n apiUrl,\n token,\n 'POST',\n `/org/environments/instances/${instanceId}/docker/logs`,\n { service, tail }\n );\n if (!res.ok) return `(log fetch failed: ${res.error ?? 'unknown'})`;\n return res.data?.logs ?? '';\n}\n\nasync function handleVerify(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const json = hasFlag(argv, '--json');\n // --keep-instance is kept as a success-path alias (existing behavior).\n // On failure the probe is now preserved by default so the user can debug;\n // pass --auto-terminate-on-failure for CI where you want cleanup anyway.\n const keepInstance = hasFlag(argv, '--keep-instance');\n const autoTerminateOnFailure = hasFlag(argv, '--auto-terminate-on-failure');\n\n if (!templateId) {\n console.error('Error: template ID required. Usage: canary sandbox verify <template-id>');\n process.exit(1);\n }\n\n console.log(`Verifying template ${templateId}...`);\n\n // Kick off a verification instance — server bypasses the \"verified\" gate\n // via verificationMode but otherwise runs the full provisioning flow.\n const verifyRes = await apiRequest<{ ok: boolean; error?: string; data: { instanceId: string; expiresAt: string } }>(\n apiUrl, token, 'POST', `/org/environments/templates/${templateId}/verify`, {}\n );\n if (!verifyRes.ok) {\n console.error(`Error: ${verifyRes.error}`);\n process.exit(1);\n }\n const instanceId = verifyRes.data.instanceId;\n console.log(` Verification instance: ${instanceId}`);\n\n // Poll diagnostics until instance reaches 'running' or a terminal state.\n const POLL_INTERVAL_MS = 10_000;\n const TIMEOUT_MS = 600_000; // 10 minutes\n const DETAIL_DUMP_INTERVAL_MS = 30_000; // rate-limit noisy dumps\n const LOG_TAIL_LINES = 40;\n const startTime = Date.now();\n let finalStatus = '';\n let publicUrl: string | undefined;\n let lastDetailDumpAt = 0;\n let routes: ServiceRoute[] = [];\n let routesFetched = false;\n\n while (Date.now() - startTime < TIMEOUT_MS) {\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n\n const diag = await apiRequest<{ ok: boolean; error?: string; data: DiagnosticsResult }>(\n apiUrl, token, 'GET', `/org/environments/instances/${instanceId}/diagnostics`,\n undefined,\n { timeoutMs: 60_000 }\n );\n if (!diag.ok) continue;\n\n const now = Date.now();\n const elapsed = Math.round((now - startTime) / 1000);\n const remaining = Math.max(0, Math.round((TIMEOUT_MS - (now - startTime)) / 1000));\n const status = String((diag.data.instance as { status?: string; publicUrl?: string }).status ?? '');\n publicUrl = (diag.data.instance as { publicUrl?: string }).publicUrl;\n const appOutput = 'stdout' in diag.data.appHealth ? diag.data.appHealth.stdout : '';\n const appUp = appOutput.length > 0 && !appOutput.includes('UNREACHABLE');\n const dockerOutput = 'stdout' in diag.data.docker ? diag.data.docker.stdout : '';\n const containers = parseDockerPs(dockerOutput);\n const broken = containers.filter(isBrokenContainer);\n\n // Compact progress line (overwriting, like before) — adds remaining time.\n const ttl = remaining > 60 ? `${elapsed}s elapsed` : `${remaining}s remaining`;\n process.stdout.write(\n `\\r [${ttl}] status: ${status}, app: ${appUp ? 'up' : 'waiting'}, containers: ${containers.length}, unhealthy: ${broken.length} `\n );\n\n if (status === 'running' && appUp) {\n process.stdout.write('\\n');\n finalStatus = 'running';\n break;\n }\n if (status === 'failed' || status === 'terminated') {\n process.stdout.write('\\n');\n finalStatus = status;\n break;\n }\n\n // When the app is still down and at least one container is broken,\n // dump details + log tails once every DETAIL_DUMP_INTERVAL_MS so the\n // user actually sees what's failing instead of staring at a spinner.\n const shouldDump =\n !appUp &&\n broken.length > 0 &&\n now - lastDetailDumpAt >= DETAIL_DUMP_INTERVAL_MS;\n if (shouldDump) {\n lastDetailDumpAt = now;\n process.stdout.write('\\n');\n console.log('');\n console.log(` App unreachable after ${elapsed}s. Container state:`);\n for (const c of containers) {\n console.log(` ${c.name.padEnd(40)} ${c.status}`);\n }\n console.log('');\n // Per-broken-container log tails. Cap to MAX_LOG_CONTAINERS to avoid\n // SSM call amplification on pathological cases (a template with 6\n // restart-looping services would otherwise issue 6 sequential SSM\n // calls every 30s). Fetch in parallel — these are independent.\n const MAX_LOG_CONTAINERS = 3;\n const toFetch = broken.slice(0, MAX_LOG_CONTAINERS);\n const overflow = broken.length - toFetch.length;\n const fetched = await Promise.all(\n toFetch.map((c) =>\n fetchServiceLogs(apiUrl, token, instanceId, containerNameToService(c.name), LOG_TAIL_LINES)\n .then((logs) => ({ c, logs }))\n )\n );\n for (const { c, logs } of fetched) {\n const tail = logs.trim().split('\\n').slice(-LOG_TAIL_LINES).join('\\n ');\n console.log(` --- ${c.name} (${c.state}) ---`);\n console.log(` ${tail || '(no logs)'}`);\n console.log('');\n }\n if (overflow > 0) {\n console.log(\n ` (+${overflow} more broken container${overflow === 1 ? '' : 's'} — re-run with: canary sandbox logs ${instanceId} --service <name>)`\n );\n console.log('');\n }\n // Attribution: if nginx-proxy is looping because of a labeled upstream\n // that's exited, call that out so the user doesn't chase nginx's\n // \"host not found in upstream\" as the root cause.\n if (!routesFetched) {\n routes = await fetchInstanceRoutes(apiUrl, token, instanceId);\n routesFetched = true;\n }\n const nginxProxy = containers.find((c) => containerNameToService(c.name) === 'nginx-proxy');\n if (nginxProxy?.state === 'restarting' && routes.length > 0) {\n const failedUpstreams = routes\n .map((r) => ({\n route: r.route,\n service: r.service,\n container: broken.find((c) => containerNameToService(c.name) === r.service),\n }))\n .filter((x) => x.container);\n if (failedUpstreams.length > 0) {\n for (const fu of failedUpstreams) {\n console.log(\n ` >> nginx-proxy is restart-looping because upstream '${fu.service}' (route '${fu.route}') is ${fu.container!.state}. Read that service's logs above, not nginx's.`\n );\n }\n console.log('');\n }\n }\n }\n }\n\n if (finalStatus !== 'running') {\n console.error('');\n console.error(`Verification failed — instance ended in status '${finalStatus || 'timeout'}'.`);\n if (publicUrl) console.error(` Instance URL: ${publicUrl}`);\n console.error(` Instance ID: ${instanceId}`);\n console.error(` Debug with: canary sandbox diagnostics ${instanceId}`);\n console.error(` canary sandbox logs ${instanceId} --service <name>`);\n console.error(` canary sandbox run-command ${instanceId} 'docker ps -a'`);\n if (autoTerminateOnFailure) {\n await apiRequest(apiUrl, token, 'POST', `/org/environments/instances/${instanceId}/terminate`);\n console.error(` Terminated (--auto-terminate-on-failure).`);\n } else {\n // Default flip (was: auto-terminate). Call it out so CI users don't\n // silently accumulate orphan instances.\n console.error(` Instance preserved by default for debugging. Pass --auto-terminate-on-failure in CI.`);\n console.error(` Terminate manually with:`);\n console.error(` canary sandbox terminate ${instanceId}`);\n }\n process.exit(1);\n }\n\n // We just observed the instance reach status === 'running' && appUp.\n // That's the same observation that backs the server-running and\n // server-accessible checklist items, so flip them too — best-effort\n // (templates without those items in their checklist 404 silently).\n const evidenceSummary = `Verified via canary sandbox verify — fresh instance ${instanceId} came up healthy.`;\n for (const itemId of ['server-running', 'server-accessible']) {\n await apiRequest(\n apiUrl,\n token,\n 'POST',\n `/org/environments/templates/${templateId}/checklist/${itemId}/complete`,\n { status: 'completed', summary: evidenceSummary }\n ).catch(() => {\n // Item not present on this checklist profile — fine.\n });\n }\n\n // Mark the template-verified checklist item complete — this is what flips\n // template.status to 'verified' (via ChecklistService.completeChecklistItem).\n const completeRes = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/org/environments/templates/${templateId}/checklist/template-verified/complete`,\n {\n status: 'completed',\n summary: evidenceSummary,\n }\n );\n if (!completeRes.ok) {\n console.error(`Failed to record verification: ${completeRes.error}`);\n console.error(`Instance ${instanceId} left running for inspection.`);\n process.exit(1);\n }\n\n if (!keepInstance) {\n await apiRequest(apiUrl, token, 'POST', `/org/environments/instances/${instanceId}/terminate`);\n console.log(` Terminated verification instance.`);\n } else {\n console.log(` --keep-instance: instance ${instanceId} left running${publicUrl ? ` at ${publicUrl}` : ''}.`);\n }\n\n // Confirm the template actually flipped to verified. The status flip only\n // happens when every item in the checklist profile is terminal\n // (completed or skipped); if other items are still pending, the probe\n // succeeded but the template stays in its prior status.\n const templateAfter = await apiRequest<{ ok: boolean; data?: { status?: string } }>(\n apiUrl,\n token,\n 'GET',\n `/org/environments/templates/${templateId}`\n ).catch(() => ({ ok: false }) as { ok: boolean; data?: { status?: string } });\n const templateStatus = templateAfter.data?.status;\n const verified = templateStatus === 'verified';\n\n if (json) {\n console.log(JSON.stringify({ templateId, verified, status: templateStatus, instanceId, publicUrl }, null, 2));\n return;\n }\n\n if (verified) {\n console.log('Template verified.');\n return;\n }\n\n // Probe passed but status didn't flip — surface the pending items so the\n // user knows what to complete/skip before re-running verify.\n console.log(`Verification probe passed (instance ${instanceId} came up healthy),`);\n console.log(`but template status is still '${templateStatus ?? 'unknown'}'.`);\n type ChecklistItemSummary = { id: string; label: string; itemStatus?: { status?: string } };\n const checklistRes = await apiRequest<{ ok: boolean; data?: ChecklistItemSummary[] }>(\n apiUrl,\n token,\n 'GET',\n `/org/environments/templates/${templateId}/checklist`\n ).catch(() => ({ ok: false }) as { ok: boolean; data?: ChecklistItemSummary[] });\n const pending = (checklistRes.data ?? []).filter((it) => {\n const s = it.itemStatus?.status ?? 'pending';\n return s !== 'completed' && s !== 'skipped';\n });\n if (pending.length > 0) {\n console.log('Pending checklist items must be completed or skipped:');\n for (const item of pending) {\n console.log(` - ${item.label} (${item.id})`);\n }\n console.log('');\n console.log('Complete: canary sandbox checklist complete <template-id> <item-id> --status success --summary \"...\"');\n console.log('Skip: canary sandbox checklist skip <template-id> <item-id>');\n }\n process.exit(1);\n}\n\nasync function handleArtifactGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const type = positional[1];\n const outputFile = getArgValue(argv, '--output');\n\n if (!templateId || !type) {\n console.error('Error: template ID and artifact type required. Usage: canary sandbox artifact get <template-id> <type>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: Artifact }>(\n apiUrl, token, 'GET', `/org/environments/templates/${templateId}/artifacts/${type}`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (outputFile) {\n const { writeFileSync } = await import('node:fs');\n writeFileSync(outputFile, res.data.content ?? '', 'utf-8');\n console.log(`Written to ${outputFile}`);\n } else {\n process.stdout.write(res.data.content ?? '');\n }\n}\n\nasync function handleArtifactCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const type = positional[1];\n const filePath = positional[2];\n const json = hasFlag(argv, '--json');\n\n if (!templateId || !type || !filePath) {\n console.error('Error: all args required. Usage: canary sandbox artifact create <template-id> <type> <file>');\n process.exit(1);\n }\n\n // Keep in sync with WellKnownArtifactType in packages/types/src/sandbox-tasks.ts + 'file' (custom with --path)\n const WELL_KNOWN_TYPES = ['docker-compose', 'dockerfile', 'startup-script', 'setup-script', 'seed-script', 'environment-config', 'file'];\n if (!WELL_KNOWN_TYPES.includes(type)) {\n console.error(`Error: invalid artifact type \"${type}\". Valid types: ${WELL_KNOWN_TYPES.join(', ')}`);\n process.exit(1);\n }\n\n // File artifacts require --path <destination>\n const destinationPath = getArgValue(argv, '--path');\n if (type === 'file' && !destinationPath) {\n console.error('Error: file artifacts require --path <destination>. Example: --path /workspace/.canary/vite.sandbox.config.ts');\n process.exit(1);\n }\n if (destinationPath && !destinationPath.startsWith('/workspace/.canary/')) {\n const suggestedName = destinationPath.split('/').filter(Boolean).pop() ?? 'yourfile';\n console.error(\n 'Error: --path must be under /workspace/.canary/ (the repo tree is user-owned — sandbox files live in .canary/).\\n' +\n ` try: --path /workspace/.canary/${suggestedName}`\n );\n process.exit(1);\n }\n\n let content: string;\n try {\n content = readFileSync(filePath, 'utf-8');\n } catch (err) {\n console.error(`Error reading file: ${err}`);\n process.exit(1);\n }\n\n // Derive filename from path\n const filename = filePath.split('/').pop() ?? filePath;\n\n // Artifact upload writes through to the live authoring instance, which on\n // first push (or a large file) can outlast 30s easily. 90s lines up with\n // the slowest legitimate upload we've observed.\n const res = await apiRequest<{\n ok: boolean;\n error?: string;\n data?: { kind: 'created' | 'replaced'; previousPath?: string };\n }>(\n apiUrl, token, 'PUT', `/org/environments/templates/${templateId}/artifacts`, {\n artifactType: type,\n filename,\n content,\n ...(destinationPath ? { destinationPath } : {}),\n },\n { timeoutMs: 90_000 }\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n const kind = res.data?.kind;\n const marker = kind === 'replaced' ? ' (replaced)' : kind === 'created' ? ' (created)' : '';\n console.log(`Artifact uploaded: ${type} (${filename}, ${content.length} bytes)${marker}`);\n if (kind === 'replaced' && res.data?.previousPath) {\n console.log(` previous destination removed: ${res.data.previousPath}`);\n }\n}\n\nasync function handleBuild(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const json = hasFlag(argv, '--json');\n const noWait = hasFlag(argv, '--no-wait');\n const instanceId = positional[0];\n\n if (!instanceId) {\n console.error('Error: instance ID required. Usage: canary sandbox build <instance-id>');\n process.exit(1);\n }\n\n console.log('Building sandbox (this takes a few minutes)...');\n\n // The build is async by design: a single HTTP connection cannot reliably\n // span a multi-minute build (ALB caps, our own client timeouts, flaky\n // networks). Kick the build off with a short timeout — the server has\n // already started the work by the time it would otherwise reply — then\n // move to polling diagnostics for the truth.\n const KICKOFF_TIMEOUT_MS = 8_000;\n\n let buildCompleted = false;\n let buildResult: { stdout: string; stderr: string; exitCode: number } | null = null;\n\n const result = await apiFetch(`${apiUrl}/org/environments/instances/${instanceId}/build`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n token,\n timeoutMs: KICKOFF_TIMEOUT_MS,\n });\n\n if (result.ok) {\n // Fast path: server responded within the kickoff window (cached/no-op build).\n const data = (await result.response.json().catch(() => null)) as\n | { ok: boolean; error?: string; data?: { stdout: string; stderr: string; exitCode: number } }\n | null;\n if (data?.ok && data.data) {\n buildCompleted = true;\n buildResult = data.data;\n } else if (data && !data.ok) {\n console.error(`Error: ${data.error ?? 'build failed'}`);\n process.exit(1);\n }\n } else {\n const { failure } = result;\n // network = our kickoff timeout firing; 502/504 = gateway giving up while\n // the build runs on. Both mean \"watch via polling, not an error\".\n const isExpectedAsync =\n failure.kind === 'network' ||\n (failure.kind === 'http-error' && (failure.status === 502 || failure.status === 504));\n if (!isExpectedAsync) {\n if (isTerminalFailure(failure)) exitOnFailure(failure);\n console.error(`Error: ${failure.message}`);\n process.exit(1);\n }\n }\n\n // If build completed synchronously, print results and exit\n if (buildCompleted && buildResult) {\n if (json) {\n console.log(JSON.stringify(buildResult, null, 2));\n return;\n }\n\n if (buildResult.stdout) {\n process.stdout.write(buildResult.stdout);\n if (!buildResult.stdout.endsWith('\\n')) process.stdout.write('\\n');\n }\n if (buildResult.stderr) {\n process.stderr.write(`STDERR: ${buildResult.stderr}`);\n if (!buildResult.stderr.endsWith('\\n')) process.stderr.write('\\n');\n }\n\n if (buildResult.exitCode === 0) {\n console.log('Build complete.');\n } else {\n console.error(`Build failed with exit code ${buildResult.exitCode}`);\n process.exit(1);\n }\n return;\n }\n\n // Build is async — poll diagnostics until the app is reachable or timeout\n if (noWait) {\n console.log('Build started. Use diagnostics to monitor progress:');\n console.log(` canary sandbox diagnostics ${instanceId}`);\n return;\n }\n\n console.log('Build started, watching for services...');\n\n const BUILD_POLL_TIMEOUT_MS = 300_000; // 5 minutes\n const POLL_INTERVAL_MS = 10_000;\n const startTime = Date.now();\n\n while (Date.now() - startTime < BUILD_POLL_TIMEOUT_MS) {\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n\n const diag = await apiRequest<{ ok: boolean; error?: string; data: DiagnosticsResult }>(\n apiUrl, token, 'GET', `/org/environments/instances/${instanceId}/diagnostics`,\n undefined,\n { timeoutMs: 60_000 }\n );\n\n if (!diag.ok) continue;\n\n const elapsed = Math.round((Date.now() - startTime) / 1000);\n const dockerOutput = 'stdout' in diag.data.docker ? diag.data.docker.stdout : '';\n const appOutput = 'stdout' in diag.data.appHealth ? diag.data.appHealth.stdout : '';\n const appUp = appOutput.length > 0 && !appOutput.includes('UNREACHABLE');\n\n // Show a compact progress line\n const containerCount = (dockerOutput.match(/\\n/g) || []).length + (dockerOutput ? 1 : 0);\n const healthyCount = (dockerOutput.match(/\\(healthy\\)/g) || []).length;\n process.stdout.write(`\\r [${elapsed}s] containers: ${containerCount}, healthy: ${healthyCount}, app: ${appUp ? 'up' : 'waiting'} `);\n\n // Trust the HTTP probe: if nginx is serving the app on :3000 or :8000, we're done.\n // Compose healthchecks are optional and most user services don't declare them.\n if (appUp) {\n process.stdout.write('\\n');\n console.log('Build complete.');\n return;\n }\n }\n\n process.stdout.write('\\n');\n console.error('Build timed out waiting for the app to respond. Check diagnostics and logs:');\n console.error(` canary sandbox diagnostics ${instanceId}`);\n console.error(` canary sandbox logs ${instanceId} --service <name>`);\n process.exit(1);\n}\n\nasync function handleRunCommand(argv: string[], apiUrl: string, token: string): Promise<void> {\n const json = hasFlag(argv, '--json');\n const service = getArgValue(argv, '--service');\n const timeoutFlag = getArgValue(argv, '--timeout');\n\n // Strip our flags (--json, --service <value>, --timeout <value>) so they\n // don't leak into the remote command.\n const filtered = argv.filter((a, i, arr) => {\n if (a === '--json') return false;\n if (a === '--service' || a === '--timeout') return false;\n if (i > 0 && (arr[i - 1] === '--service' || arr[i - 1] === '--timeout')) return false;\n return true;\n });\n\n // First non-flag arg is the instance ID; everything after it is the command\n // (including flags like -la that belong to the remote command, not to us)\n const firstNonFlag = filtered.findIndex((a) => !a.startsWith('-'));\n const instanceId = firstNonFlag >= 0 ? filtered[firstNonFlag] : undefined;\n const command = firstNonFlag >= 0 ? filtered.slice(firstNonFlag + 1).join(' ') : '';\n\n if (!instanceId || !command) {\n console.error('Error: instance ID and command required. Usage: canary sandbox run-command <instance-id> [--service <name>] [--timeout <ms>] <command...>');\n process.exit(1);\n }\n\n // Server-side run-command caps at 55s (SANDBOX_COMMAND_TIMEOUT). Default\n // the CLI just past that so we surface the server's typed timeout rather\n // than an opaque client-side cancel. For longer ops (test suites,\n // playwright), pass a higher value or use first-class actions.\n const timeoutMs = timeoutFlag ? Math.max(parseInt(timeoutFlag, 10), 1000) : 60_000;\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: { stdout: string; stderr: string; exitCode: number } }>(\n apiUrl, token, 'POST', `/org/environments/instances/${instanceId}/run-command`,\n { command, ...(service ? { service } : {}) },\n { timeoutMs }\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n if (res.data.stdout) {\n process.stdout.write(res.data.stdout);\n if (!res.data.stdout.endsWith('\\n')) process.stdout.write('\\n');\n }\n if (res.data.stderr) {\n process.stderr.write(`STDERR: ${res.data.stderr}`);\n if (!res.data.stderr.endsWith('\\n')) process.stderr.write('\\n');\n }\n if (res.data.exitCode !== 0) {\n console.log(`Exit code: ${res.data.exitCode}`);\n }\n}\n\nasync function handleDiagnostics(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const instanceId = positional[0];\n const json = hasFlag(argv, '--json');\n\n if (!instanceId) {\n console.error('Error: instance ID required. Usage: canary sandbox diagnostics <instance-id>');\n process.exit(1);\n }\n\n // Server-side DIAGNOSTICS_TIMEOUT_MS is 30s; the client needs a bit more\n // headroom than that or we race the server and report a misleading client\n // timeout for a server-side timeout.\n const res = await apiRequest<{ ok: boolean; error?: string; data: DiagnosticsResult }>(\n apiUrl, token, 'GET', `/org/environments/instances/${instanceId}/diagnostics`,\n undefined,\n { timeoutMs: 60_000 }\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n const routes = await fetchInstanceRoutes(apiUrl, token, instanceId);\n const data = { ...res.data, routes };\n\n if (json) {\n console.log(JSON.stringify(data, null, 2));\n return;\n }\n\n const d = data;\n\n console.log('=== Instance ===');\n for (const [key, value] of Object.entries(d.instance)) {\n console.log(` ${key}: ${value}`);\n }\n\n if (d.provision) {\n console.log('');\n console.log('=== Provisioning ===');\n console.log(` phase: ${d.provision.phase}`);\n console.log(` jobStatus: ${d.provision.jobStatus}`);\n if (d.provision.startedAt) console.log(` startedAt: ${d.provision.startedAt}`);\n if (d.provision.elapsedSeconds !== null) console.log(` elapsed: ${d.provision.elapsedSeconds}s`);\n if (d.provision.lastError) console.log(` lastError: ${d.provision.lastError}`);\n }\n\n const sections: Array<[string, CommandOrError]> = [\n ['Docker Containers', d.docker],\n ['Git Status', d.git],\n ['Disk Usage', d.disk],\n ['Agent Health', d.agentHealth],\n ['App Health', d.appHealth],\n ];\n\n for (const [title, result] of sections) {\n console.log('');\n console.log(`=== ${title} ===`);\n if ('error' in result) {\n console.log(` Error: ${result.error}`);\n } else {\n if (result.stdout) console.log(result.stdout);\n if (result.stderr) console.log(` STDERR: ${result.stderr}`);\n }\n }\n}\n\nasync function handleLogs(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const instanceId = positional[0];\n const json = hasFlag(argv, '--json');\n\n if (!instanceId) {\n console.error('Error: instance ID required. Usage: canary sandbox logs <instance-id>');\n process.exit(1);\n }\n\n const service = getArgValue(argv, '--service');\n const tail = getArgValue(argv, '--tail') ?? '200';\n\n // Don't send `service: ''` — the server's regex validator rejects empty\n // strings even though the field is optional, and the route then returns\n // 500 instead of an all-services tail. Omit the field when absent.\n const res = await apiRequest<{ ok: boolean; error?: string; data: { logs: string } }>(\n apiUrl, token, 'POST', `/org/environments/instances/${instanceId}/docker/logs`, {\n ...(service ? { service } : {}),\n tail: parseInt(tail, 10),\n }\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n process.stdout.write(res.data.logs ?? '(no logs)');\n}\n\nasync function handleTerminate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const instanceId = positional[0];\n\n if (!instanceId) {\n console.error('Error: instance ID required. Usage: canary sandbox terminate <instance-id>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl, token, 'POST', `/org/environments/instances/${instanceId}/terminate`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n console.log(`Instance ${instanceId} termination initiated.`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n\n if (!templateId) {\n console.error('Error: template ID required. Usage: canary sandbox delete <template-id>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl, token, 'DELETE', `/org/environments/templates/${templateId}`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n console.log(`Template ${templateId} deleted.`);\n}\n\n// ---------------------------------------------------------------------------\n// Action handlers\n// ---------------------------------------------------------------------------\n\ntype ActionDef = {\n id: string;\n slug: string;\n label: string;\n description: string | null;\n icon: string | null;\n enabled: boolean;\n inputSchema: Record<string, unknown>;\n outputSchema: Record<string, unknown> | null;\n scriptContent: string;\n timeoutMs: number;\n createdAt: string;\n updatedAt: string;\n};\n\ntype ActionExecution = {\n id: string;\n actionId: string;\n instanceId: string;\n source: string;\n status: string;\n result: Record<string, unknown> | null;\n stdout: string | null;\n stderr: string | null;\n exitCode: number | null;\n durationMs: number | null;\n error: string | null;\n createdAt: string;\n};\n\nasync function handleActionList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const json = hasFlag(argv, '--json');\n\n if (!templateId) {\n console.error('Error: template ID required. Usage: canary sandbox action list <template-id>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: ActionDef[] }>(\n apiUrl, token, 'GET', `/org/environments/templates/${templateId}/actions`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n const actions = res.data ?? [];\n if (actions.length === 0) {\n console.log('No actions defined for this template.');\n return;\n }\n\n console.log(`Actions (${actions.length}):`);\n for (const a of actions) {\n const status = a.enabled ? '' : ' [disabled]';\n console.log(` ${pad(a.slug, 30)} ${pad(a.label, 25)}${status}`);\n }\n}\n\nasync function handleActionGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const slug = positional[1];\n const json = hasFlag(argv, '--json');\n\n if (!templateId || !slug) {\n console.error('Error: template ID and slug required. Usage: canary sandbox action get <template-id> <slug>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: ActionDef }>(\n apiUrl, token, 'GET', `/org/environments/templates/${templateId}/actions/${slug}`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n const a = res.data;\n console.log(`Action: ${a.slug}`);\n console.log(` Label: ${a.label}`);\n console.log(` Description: ${a.description ?? '(none)'}`);\n console.log(` Icon: ${a.icon ?? '(none)'}`);\n console.log(` Enabled: ${a.enabled}`);\n console.log(` Timeout: ${a.timeoutMs}ms`);\n console.log(` Input Schema:`);\n console.log(` ${JSON.stringify(a.inputSchema, null, 2).split('\\n').join('\\n ')}`);\n if (a.outputSchema) {\n console.log(` Output Schema:`);\n console.log(` ${JSON.stringify(a.outputSchema, null, 2).split('\\n').join('\\n ')}`);\n }\n console.log(` Script:`);\n console.log(` ${a.scriptContent.split('\\n').join('\\n ')}`);\n}\n\nasync function handleActionCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const slug = positional[1];\n const json = hasFlag(argv, '--json');\n\n if (!templateId || !slug) {\n console.error('Error: template ID and slug required. Usage: canary sandbox action create <template-id> <slug> [options]');\n process.exit(1);\n }\n\n const scriptPath = getArgValue(argv, '--script');\n const inputSchemaPath = getArgValue(argv, '--input-schema');\n const outputSchemaPath = getArgValue(argv, '--output-schema');\n const credentialOutputConfigPath = getArgValue(argv, '--credential-output-config');\n const label = getArgValue(argv, '--label') ?? slug.replace(/-/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase());\n const description = getArgValue(argv, '--description');\n const icon = getArgValue(argv, '--icon');\n const timeoutStr = getArgValue(argv, '--timeout');\n const encryptScript = hasFlag(argv, '--encrypt-script');\n const credentialTemplateId = getArgValue(argv, '--credential-template');\n const provisioningMode = getArgValue(argv, '--provisioning-mode');\n\n if (provisioningMode && provisioningMode !== 'shared' && provisioningMode !== 'unique') {\n console.error(\"Error: --provisioning-mode must be 'shared' or 'unique'\");\n process.exit(1);\n }\n\n if (!scriptPath) {\n console.error('Error: --script <file> is required');\n process.exit(1);\n }\n if (!inputSchemaPath) {\n console.error('Error: --input-schema <file> is required');\n process.exit(1);\n }\n\n let scriptContent: string;\n try {\n scriptContent = readFileSync(scriptPath, 'utf-8');\n } catch (err) {\n console.error(`Error reading script file: ${err}`);\n process.exit(1);\n }\n\n let inputSchema: Record<string, unknown>;\n try {\n inputSchema = JSON.parse(readFileSync(inputSchemaPath, 'utf-8'));\n } catch (err) {\n console.error(`Error reading input schema file: ${err}`);\n process.exit(1);\n }\n\n let outputSchema: Record<string, unknown> | undefined;\n if (outputSchemaPath) {\n try {\n outputSchema = JSON.parse(readFileSync(outputSchemaPath, 'utf-8'));\n } catch (err) {\n console.error(`Error reading output schema file: ${err}`);\n process.exit(1);\n }\n }\n\n let credentialOutputConfig: Record<string, unknown> | undefined;\n if (credentialOutputConfigPath) {\n try {\n credentialOutputConfig = JSON.parse(readFileSync(credentialOutputConfigPath, 'utf-8'));\n } catch (err) {\n console.error(`Error reading credential output config file: ${err}`);\n process.exit(1);\n }\n }\n\n const body: Record<string, unknown> = {\n label,\n scriptContent,\n inputSchema,\n ...(description ? { description } : {}),\n ...(icon ? { icon } : {}),\n ...(outputSchema ? { outputSchema } : {}),\n ...(credentialOutputConfig ? { credentialOutputConfig } : {}),\n ...(credentialTemplateId ? { credentialTemplateId } : {}),\n ...(provisioningMode ? { provisioningMode } : {}),\n ...(timeoutStr ? { timeoutMs: parseInt(timeoutStr, 10) } : {}),\n ...(encryptScript ? { scriptEncrypted: true } : {}),\n };\n\n const res = await apiRequest<{ ok: boolean; error?: string; data?: ActionDef }>(\n apiUrl, token, 'PUT', `/org/environments/templates/${templateId}/actions/${slug}`, body\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n console.log(`Action '${slug}' saved (${scriptContent.length} bytes script, label: \"${label}\")`);\n}\n\nasync function handleActionDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const slug = positional[1];\n\n if (!templateId || !slug) {\n console.error('Error: template ID and slug required. Usage: canary sandbox action delete <template-id> <slug>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl, token, 'DELETE', `/org/environments/templates/${templateId}/actions/${slug}`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n console.log(`Action '${slug}' deleted.`);\n}\n\nasync function handleActionExecute(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const instanceId = positional[0];\n const slug = positional[1];\n const json = hasFlag(argv, '--json');\n\n if (!instanceId || !slug) {\n console.error('Error: instance ID and slug required. Usage: canary sandbox action execute <instance-id> <slug> [options]');\n process.exit(1);\n }\n\n // Collect params from --param key=value flags\n let params: Record<string, unknown> = {};\n\n const paramsFile = getArgValue(argv, '--params-file');\n if (paramsFile) {\n try {\n params = JSON.parse(readFileSync(paramsFile, 'utf-8'));\n } catch (err) {\n console.error(`Error reading params file: ${err}`);\n process.exit(1);\n }\n }\n\n // --param flags override params-file\n for (let i = 0; i < argv.length; i++) {\n if (argv[i] === '--param' && argv[i + 1]) {\n const [key, ...valueParts] = argv[i + 1]!.split('=');\n if (key && valueParts.length > 0) {\n params[key] = valueParts.join('=');\n }\n i++; // skip value\n }\n }\n\n interface ActionExecuteResponse {\n executionId: string;\n status: string;\n result: unknown;\n stdout: string | null;\n stderr: string | null;\n exitCode: number | null;\n durationMs: number | null;\n error: string | null;\n credentialId?: string | null;\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; data?: ActionExecuteResponse }>(\n apiUrl, token, 'POST', `/org/environments/instances/${instanceId}/actions/${slug}/execute`, {\n params,\n source: 'cli',\n }\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n const exec = res.data!;\n const statusIcon = exec.status === 'completed' ? '[done]' : exec.status === 'failed' ? '[FAIL]' : `[${exec.status}]`;\n console.log(`${statusIcon} Action '${slug}' ${exec.status} (${exec.durationMs ?? 0}ms, exit ${exec.exitCode ?? '?'})`);\n if (exec.result) {\n console.log(`Result: ${JSON.stringify(exec.result, null, 2)}`);\n }\n if (exec.credentialId) {\n console.log(`Credential: ${exec.credentialId} (linked in property vault)`);\n }\n if (exec.status === 'failed' && exec.stderr) {\n // Cap by bytes first so a single multi-MB line doesn't blow up the terminal,\n // then by line count for readability.\n const tail = exec.stderr.slice(-10_000).trim().split('\\n').slice(-20).join('\\n');\n console.log(`Stderr (last 20 lines):\\n${tail}`);\n }\n if (exec.error) {\n console.log(`Error: ${exec.error}`);\n }\n}\n\nasync function handleActionExecutions(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const instanceId = positional[0];\n const json = hasFlag(argv, '--json');\n\n if (!instanceId) {\n console.error('Error: instance ID required. Usage: canary sandbox action executions <instance-id>');\n process.exit(1);\n }\n\n const res = await apiRequest<{ ok: boolean; error?: string; data: ActionExecution[] }>(\n apiUrl, token, 'GET', `/org/environments/instances/${instanceId}/actions/executions`\n );\n\n if (!res.ok) {\n console.error(`Error: ${res.error}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res.data, null, 2));\n return;\n }\n\n const execs = res.data ?? [];\n if (execs.length === 0) {\n console.log('No executions yet.');\n return;\n }\n\n console.log('Executions:');\n for (const e of execs) {\n const icon = STATUS_ICONS[e.status] ?? `[${e.status}]`;\n const dur = e.durationMs !== null && e.durationMs !== undefined ? `${e.durationMs}ms` : '?ms';\n console.log(` ${icon} ${pad(e.id.slice(0, 8), 10)} ${pad(e.source, 6)} ${pad(e.status, 12)} ${pad(dur, 8)} ${formatDate(e.createdAt)}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Multi-repo: manage repos linked to a sandbox template\n// ---------------------------------------------------------------------------\n\ntype TemplateRepoLink = {\n id: string;\n templateId: string;\n propertyGithubRepoId: string;\n role: string | null;\n branch: string;\n subdirectory: string | null;\n serviceName: string;\n};\n\n/**\n * Parse `role=owner/name@branch:subdir` (branch and subdir optional) into the\n * pieces the API expects. Used by `canary sandbox repo add --spec ...`.\n */\nfunction parseRepoSpec(spec: string): {\n role?: string;\n repoFullName: string;\n branch?: string;\n subdirectory?: string;\n} {\n let rest = spec;\n let role: string | undefined;\n const eq = rest.indexOf('=');\n if (eq > -1 && !rest.slice(0, eq).includes('/')) {\n role = rest.slice(0, eq);\n rest = rest.slice(eq + 1);\n }\n let subdirectory: string | undefined;\n const colon = rest.indexOf(':');\n if (colon > -1) {\n subdirectory = rest.slice(colon + 1);\n rest = rest.slice(0, colon);\n }\n let branch: string | undefined;\n const at = rest.indexOf('@');\n if (at > -1) {\n branch = rest.slice(at + 1);\n rest = rest.slice(0, at);\n }\n return { role, repoFullName: rest, branch, subdirectory };\n}\n\nasync function handleRepoList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const json = hasFlag(argv, '--json');\n const templateId = getArgValue(argv, '--template');\n if (!templateId) {\n console.error('Error: --template is required.');\n process.exit(1);\n }\n\n const result = await apiRequest<{ ok: boolean; items?: TemplateRepoLink[]; error?: string }>(\n apiUrl,\n token,\n 'GET',\n `/org/environments/templates/${templateId}/repos`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(result.items ?? [], null, 2));\n return;\n }\n\n const items = result.items ?? [];\n if (items.length === 0) {\n console.log('No repos linked to this template.');\n return;\n }\n for (const r of items) {\n const role = r.role ? ` [${r.role}]` : '';\n const subdir = r.subdirectory ? `:${r.subdirectory}` : '';\n console.log(` ${r.serviceName} → ${r.propertyGithubRepoId}@${r.branch}${subdir}${role} (link=${r.id})`);\n }\n}\n\nasync function handleRepoAdd(argv: string[], apiUrl: string, token: string): Promise<void> {\n const json = hasFlag(argv, '--json');\n const templateId = getArgValue(argv, '--template');\n const propertyGithubRepoId = getArgValue(argv, '--property-github-repo-id');\n const spec = getArgValue(argv, '--spec');\n const role = getArgValue(argv, '--role');\n const branch = getArgValue(argv, '--branch');\n const subdirectory = getArgValue(argv, '--subdirectory');\n const serviceName = getArgValue(argv, '--service-name');\n\n if (!templateId || !propertyGithubRepoId) {\n console.error('Error: --template and --property-github-repo-id are required.');\n console.error('Tip: link the repo to the property first via `canary property repo link`, then pass its id here.');\n process.exit(1);\n }\n\n const parsed: ReturnType<typeof parseRepoSpec> | { role?: undefined; branch?: undefined; subdirectory?: undefined } = spec ? parseRepoSpec(spec) : {};\n\n const body: Record<string, unknown> = { propertyGithubRepoId };\n const finalRole = role ?? parsed.role;\n const finalBranch = branch ?? parsed.branch;\n const finalSubdir = subdirectory ?? parsed.subdirectory;\n if (finalRole !== undefined) body.role = finalRole;\n if (finalBranch !== undefined) body.branch = finalBranch;\n if (finalSubdir !== undefined) body.subdirectory = finalSubdir;\n if (serviceName !== undefined) body.serviceName = serviceName;\n\n const result = await apiRequest<{ ok: boolean; data?: TemplateRepoLink; error?: string }>(\n apiUrl,\n token,\n 'POST',\n `/org/environments/templates/${templateId}/repos`,\n body\n );\n\n if (!result.ok) {\n if (json) console.log(JSON.stringify(result, null, 2));\n else console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n if (json) console.log(JSON.stringify(result.data, null, 2));\n else console.log(`Linked repo to template ${templateId} (link=${result.data?.id})`);\n}\n\nasync function handleRepoUpdate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const json = hasFlag(argv, '--json');\n const templateId = getArgValue(argv, '--template');\n const linkId = getArgValue(argv, '--link-id');\n const role = getArgValue(argv, '--role');\n const branch = getArgValue(argv, '--branch');\n const subdirectory = getArgValue(argv, '--subdirectory');\n const serviceName = getArgValue(argv, '--service-name');\n\n if (!templateId || !linkId) {\n console.error('Error: --template and --link-id are required.');\n process.exit(1);\n }\n\n const body: Record<string, unknown> = {};\n if (role !== undefined) body.role = role;\n if (branch !== undefined) body.branch = branch;\n if (subdirectory !== undefined) body.subdirectory = subdirectory;\n if (serviceName !== undefined) body.serviceName = serviceName;\n\n const result = await apiRequest<{ ok: boolean; data?: TemplateRepoLink; error?: string }>(\n apiUrl,\n token,\n 'PATCH',\n `/org/environments/templates/${templateId}/repos/${linkId}`,\n body\n );\n\n if (!result.ok) {\n if (json) console.log(JSON.stringify(result, null, 2));\n else console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n if (json) console.log(JSON.stringify(result.data, null, 2));\n else console.log(`Updated repo link ${linkId}`);\n}\n\nasync function handleRepoRemove(argv: string[], apiUrl: string, token: string): Promise<void> {\n const json = hasFlag(argv, '--json');\n const templateId = getArgValue(argv, '--template');\n const linkId = getArgValue(argv, '--link-id');\n if (!templateId || !linkId) {\n console.error('Error: --template and --link-id are required.');\n process.exit(1);\n }\n const result = await apiRequest<{ ok: boolean; error?: string }>(\n apiUrl,\n token,\n 'DELETE',\n `/org/environments/templates/${templateId}/repos/${linkId}`\n );\n if (!result.ok) {\n if (json) console.log(JSON.stringify(result, null, 2));\n else console.error(`Error: ${result.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n if (json) console.log(JSON.stringify(result, null, 2));\n else console.log(`Removed repo link ${linkId} from template ${templateId}`);\n}\n\nasync function handleRepo(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [action, ...rest] = argv;\n switch (action) {\n case 'list':\n await handleRepoList(rest, apiUrl, token);\n break;\n case 'add':\n await handleRepoAdd(rest, apiUrl, token);\n break;\n case 'update':\n await handleRepoUpdate(rest, apiUrl, token);\n break;\n case 'remove':\n case 'rm':\n await handleRepoRemove(rest, apiUrl, token);\n break;\n default:\n console.error(\n `Unknown repo action: ${action ?? '(none)'}. Use list/add/update/remove.\\n` +\n 'Examples:\\n' +\n ' canary sandbox repo list --template <template-id>\\n' +\n ' canary sandbox repo add --template <template-id> --property-github-repo-id <uuid> --role frontend\\n' +\n ' canary sandbox repo add --template <template-id> --property-github-repo-id <uuid> --spec frontend=owner/web@main:/apps/web'\n );\n process.exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// AMI lifecycle (per-template golden AMI). See\n// specs/sandbox-infrastructure-optimization.md §Phase 2 §Naming + rollback UX.\n// ---------------------------------------------------------------------------\n\ninterface AmiRow {\n id: string;\n amiId: string | null;\n amiName: string | null;\n status: 'building' | 'ready' | 'failed' | 'superseded' | 'deregistered';\n artifactHash: string;\n instanceSize: string;\n baseAmiId: string;\n builtAt: string | null;\n supersededAt: string | null;\n deregisteredAt: string | null;\n buildError: string | null;\n buildJobId: string | null;\n createdAt: string;\n isCurrent: boolean;\n}\n\ninterface AmiListResponse {\n ok: boolean;\n error?: string;\n templateId?: string;\n currentAmiId?: string | null;\n pendingAmiBakeHash?: string | null;\n amis?: AmiRow[];\n}\n\nconst AMI_TERMINAL_STATUSES = new Set(['ready', 'failed', 'superseded', 'deregistered']);\n\nconst formatHashShort = (hash: string): string => hash.slice(0, 8);\n\n// Single source of truth for column widths so the header and row formatters\n// can't drift apart. The marker is a 1-char prefix sitting outside the\n// padded columns, with a single space gap.\nconst AMI_COL = {\n status: 12,\n hash: 8,\n built: 20,\n size: 8,\n amiId: 22,\n} as const;\n\nfunction printAmiTable(rows: AmiRow[], currentAmiId: string | null | undefined): void {\n if (rows.length === 0) {\n console.log('No AMI history yet — trigger one with `canary sandbox ami rebake <template-id>`.');\n return;\n }\n\n const header = ` ${'STATUS'.padEnd(AMI_COL.status)} ${'HASH'.padEnd(AMI_COL.hash)} ${'BUILT'.padEnd(AMI_COL.built)} ${'SIZE'.padEnd(AMI_COL.size)} ${'AMI-ID'.padEnd(AMI_COL.amiId)} ROW-ID`;\n const lines: string[] = [header];\n const markerFor = (row: AmiRow): string => {\n if (currentAmiId && row.id === currentAmiId) return '*';\n if (row.status === 'ready' || row.status === 'superseded') return 'R';\n return ' ';\n };\n for (const row of rows) {\n const marker = markerFor(row);\n const built = row.builtAt ? new Date(row.builtAt).toISOString().slice(0, 19) + 'Z' : '—';\n lines.push(\n `${marker} ${row.status.padEnd(AMI_COL.status)} ${formatHashShort(row.artifactHash).padEnd(AMI_COL.hash)} ${built.padEnd(AMI_COL.built)} ${row.instanceSize.padEnd(AMI_COL.size)} ${(row.amiId ?? '—').padEnd(AMI_COL.amiId)} ${row.id}`\n );\n }\n console.log(lines.join('\\n'));\n console.log('');\n console.log(\" '*' = current 'R' = ready/superseded (eligible for `canary sandbox ami use`)\");\n}\n\nasync function handleAmiList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const json = hasFlag(argv, '--json');\n\n if (!templateId) {\n console.error('Error: template ID required. Usage: canary sandbox ami list <template-id>');\n process.exit(1);\n }\n\n const res = await apiRequest<AmiListResponse>(\n apiUrl,\n token,\n 'GET',\n `/org/environments/templates/${templateId}/amis`\n );\n\n if (!res.ok) {\n if (json) console.log(JSON.stringify(res, null, 2));\n else console.error(`Error: ${res.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res, null, 2));\n return;\n }\n\n console.log(`Template: ${res.templateId}`);\n console.log(`Current AMI row: ${res.currentAmiId ?? '— (using base AMI)'}`);\n if (res.pendingAmiBakeHash) {\n console.log(`Pending bake hash: ${formatHashShort(res.pendingAmiBakeHash)}`);\n }\n console.log('');\n printAmiTable(res.amis ?? [], res.currentAmiId);\n}\n\ninterface AmiRebakeResponse {\n ok: boolean;\n error?: string;\n reason?: 'enqueued' | 'already-baked' | 'coalesced';\n jobId?: string;\n amiRowId?: string;\n status?: AmiRow['status'];\n artifactHash?: string;\n}\n\n// Tolerate transient API errors during a long bake — a 502/504/ECONNRESET\n// shouldn't abort a 45-minute wait. Three consecutive failures still bails;\n// a single blip is logged and the next poll retries.\nconst POLL_TRANSIENT_FAILURE_LIMIT = 3;\n\nasync function pollAmiBuild(\n apiUrl: string,\n token: string,\n templateId: string,\n jobId: string,\n pollIntervalMs = 5000,\n timeoutMs = 45 * 60 * 1000\n): Promise<AmiRow | null> {\n const startedAt = Date.now();\n let lastSeenStatus: string | null = null;\n let consecutiveFailures = 0;\n while (Date.now() - startedAt < timeoutMs) {\n const res = await apiRequest<AmiListResponse>(\n apiUrl,\n token,\n 'GET',\n `/org/environments/templates/${templateId}/amis`\n );\n if (!res.ok) {\n consecutiveFailures += 1;\n if (consecutiveFailures >= POLL_TRANSIENT_FAILURE_LIMIT) {\n console.error(\n `Aborting wait after ${consecutiveFailures} consecutive poll failures: ${res.error ?? 'Unknown'}`\n );\n return null;\n }\n console.error(\n ` ↳ poll failure ${consecutiveFailures}/${POLL_TRANSIENT_FAILURE_LIMIT} — ${res.error ?? 'Unknown'}; retrying`\n );\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n continue;\n }\n consecutiveFailures = 0;\n // Match on build_job_id, not artifactHash — multiple historical rows can\n // share the same hash (prior failed bakes), so a hash-only match races\n // against the worker's `building` row insert and can latch onto a stale\n // terminal row before the new row appears.\n const matching = (res.amis ?? []).find((r) => r.buildJobId === jobId);\n if (matching && AMI_TERMINAL_STATUSES.has(matching.status)) {\n return matching;\n }\n if (matching && matching.status !== lastSeenStatus) {\n lastSeenStatus = matching.status;\n console.log(` ↳ ${new Date().toISOString()} — status: ${matching.status}`);\n }\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n }\n console.error(`Timed out after ${Math.round(timeoutMs / 1000)}s waiting for bake to finish.`);\n return null;\n}\n\nasync function handleAmiRebake(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const json = hasFlag(argv, '--json');\n const force = hasFlag(argv, '--force');\n const wait = hasFlag(argv, '--wait');\n\n if (!templateId) {\n console.error('Error: template ID required.');\n console.error('Usage: canary sandbox ami rebake <template-id> [--force] [--wait]');\n process.exit(1);\n }\n\n const res = await apiRequest<AmiRebakeResponse>(\n apiUrl,\n token,\n 'POST',\n `/org/environments/templates/${templateId}/amis/rebake`,\n { force }\n );\n\n if (!res.ok) {\n if (json) console.log(JSON.stringify(res, null, 2));\n else console.error(`Error: ${res.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res, null, 2));\n return;\n }\n\n if (res.reason === 'already-baked') {\n console.log(`AMI for hash ${formatHashShort(res.artifactHash ?? '')} already exists (${res.status}).`);\n console.log(` Row id: ${res.amiRowId}`);\n console.log(` Use \\`canary sandbox ami use ${templateId} ${res.amiRowId}\\` to switch to it,`);\n console.log(' or pass --force to bake a fresh copy anyway.');\n return;\n }\n\n if (res.reason === 'coalesced') {\n console.log('Another rebake was already queued for this template; nothing to do.');\n if (wait) {\n console.log(\n ' (--wait skipped: coalesced response has no job handle to follow. ' +\n 'Watch via `canary task list --status in_progress` or re-run rebake when the in-flight one finishes.)'\n );\n }\n return;\n }\n\n // res.reason === 'enqueued'\n console.log(`Bake job enqueued.`);\n console.log(` Job id: ${res.jobId}`);\n console.log(` Hash: ${formatHashShort(res.artifactHash ?? '')}`);\n\n if (wait) {\n if (!res.jobId) {\n console.error('Cannot --wait: API did not return a jobId for the enqueued bake.');\n process.exit(1);\n }\n console.log('');\n console.log('Polling for completion (Ctrl+C to detach; bake continues server-side)…');\n const final = await pollAmiBuild(apiUrl, token, templateId, res.jobId);\n if (final) {\n console.log('');\n if (final.status === 'ready') {\n console.log(`Bake complete: AMI ${final.amiId} (row ${final.id})`);\n } else {\n console.error(`Bake ended in status: ${final.status}`);\n if (final.buildError) console.error(` ${final.buildError}`);\n process.exit(1);\n }\n }\n }\n}\n\ninterface AmiUseResponse {\n ok: boolean;\n error?: string;\n templateId?: string;\n /** Row UUID (`environment_template_amis.id`) — what the request set as current. */\n currentAmiRowId?: string;\n /** AWS AMI handle (`ami-XXXXX`) of the row, when known. */\n currentAmiId?: string | null;\n alreadyCurrent?: boolean;\n promotedFromSuperseded?: boolean;\n demotedPriorAmiRowId?: string | null;\n priorDemoteSkipped?: boolean;\n}\n\nasync function handleAmiUse(argv: string[], apiUrl: string, token: string): Promise<void> {\n const positional = argv.filter((a) => !a.startsWith('-'));\n const templateId = positional[0];\n const amiRowId = positional[1];\n const json = hasFlag(argv, '--json');\n\n if (!templateId || !amiRowId) {\n console.error('Error: template ID and AMI row id required.');\n console.error('Usage: canary sandbox ami use <template-id> <ami-row-id>');\n console.error('Find row ids with `canary sandbox ami list <template-id>`.');\n process.exit(1);\n }\n\n const res = await apiRequest<AmiUseResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/org/environments/templates/${templateId}/current-ami`,\n { amiRowId }\n );\n\n if (!res.ok) {\n if (json) console.log(JSON.stringify(res, null, 2));\n else console.error(`Error: ${res.error ?? 'Unknown error'}`);\n process.exit(1);\n }\n\n if (json) {\n console.log(JSON.stringify(res, null, 2));\n return;\n }\n\n if (res.alreadyCurrent) {\n console.log(`Row ${amiRowId} is already the current AMI for template ${templateId}.`);\n return;\n }\n\n console.log(`Current AMI updated.`);\n console.log(` Template: ${res.templateId}`);\n console.log(` Row: ${res.currentAmiRowId}`);\n if (res.currentAmiId) {\n console.log(` AMI: ${res.currentAmiId}`);\n }\n if (res.promotedFromSuperseded) {\n console.log(' Note: chosen row was superseded; promoted back to ready.');\n }\n if (res.demotedPriorAmiRowId) {\n console.log(` Demoted: ${res.demotedPriorAmiRowId} (prior current → superseded)`);\n }\n if (res.priorDemoteSkipped) {\n console.log(\n ' Warning: prior current row was not in `ready` status — demote skipped (see server logs).'\n );\n }\n}\n\nasync function handleAmi(argv: string[], apiUrl: string, token: string): Promise<void> {\n const [action, ...rest] = argv;\n switch (action) {\n case 'list':\n await handleAmiList(rest, apiUrl, token);\n break;\n case 'rebake':\n await handleAmiRebake(rest, apiUrl, token);\n break;\n case 'use':\n await handleAmiUse(rest, apiUrl, token);\n break;\n default:\n console.error(\n `Unknown ami action: ${action ?? '(none)'}. Use list/rebake/use.\\n` +\n 'Examples:\\n' +\n ' canary sandbox ami list <template-id>\\n' +\n ' canary sandbox ami rebake <template-id> [--force] [--wait]\\n' +\n ' canary sandbox ami use <template-id> <ami-row-id>'\n );\n process.exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main dispatcher\n// ---------------------------------------------------------------------------\n\nexport async function runSandbox(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printHelp();\n return;\n }\n\n // Guide is purely local — no auth needed\n if (subCommand === 'guide') {\n const section = rest.find((a) => !a.startsWith('-'));\n const json = hasFlag(rest, '--json');\n printGuide(SANDBOX_GUIDE_SECTIONS, section, json);\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n // Strip global flags consumed by resolveConfig so handlers don't see them as positional args\n const globalFlags = new Set(['--env', '--api-url', '--token']);\n const args = rest.filter((arg, i) => {\n if (globalFlags.has(arg)) return false;\n if (i > 0 && globalFlags.has(rest[i - 1])) return false;\n return true;\n });\n\n switch (subCommand) {\n case 'list':\n await handleList(args, apiUrl, token);\n break;\n case 'template':\n await handleTemplate(args, apiUrl, token);\n break;\n case 'repo':\n await handleRepo(args, apiUrl, token);\n break;\n case 'artifacts':\n await handleArtifacts(args, apiUrl, token);\n break;\n case 'checklist':\n await handleChecklist(args, apiUrl, token);\n break;\n case 'create':\n await handleCreate(args, apiUrl, token);\n break;\n case 'provision':\n await handleProvision(args, apiUrl, token);\n break;\n case 'verify':\n await handleVerify(args, apiUrl, token);\n break;\n case 'set-size':\n await handleSetSize(args, apiUrl, token);\n break;\n case 'ami':\n await handleAmi(args, apiUrl, token);\n break;\n case 'artifact': {\n const [action, ...actionRest] = args;\n if (action === 'get') {\n await handleArtifactGet(actionRest, apiUrl, token);\n } else if (action === 'create') {\n await handleArtifactCreate(actionRest, apiUrl, token);\n } else {\n console.error(`Unknown artifact action: ${action}. Use \"get\" or \"create\".`);\n process.exit(1);\n }\n break;\n }\n case 'config': {\n const [configAction, ...configRest] = args;\n if (configAction === 'list') {\n await handleConfigList(configRest, apiUrl, token);\n } else if (configAction === 'set') {\n await handleConfigSet(configRest, apiUrl, token);\n } else {\n console.error(`Unknown config action: ${configAction}. Use \"list\" or \"set\".`);\n process.exit(1);\n }\n break;\n }\n case 'action': {\n const [actionSub, ...actionRest] = args;\n switch (actionSub) {\n case 'list':\n await handleActionList(actionRest, apiUrl, token);\n break;\n case 'get':\n await handleActionGet(actionRest, apiUrl, token);\n break;\n case 'create':\n await handleActionCreate(actionRest, apiUrl, token);\n break;\n case 'delete':\n await handleActionDelete(actionRest, apiUrl, token);\n break;\n case 'execute':\n await handleActionExecute(actionRest, apiUrl, token);\n break;\n case 'executions':\n await handleActionExecutions(actionRest, apiUrl, token);\n break;\n default:\n console.error(`Unknown action sub-command: ${actionSub}. Use \"list\", \"get\", \"create\", \"delete\", \"execute\", or \"executions\".`);\n process.exit(1);\n }\n break;\n }\n case 'build':\n await handleBuild(args, apiUrl, token);\n break;\n case 'run-command':\n await handleRunCommand(args, apiUrl, token);\n break;\n case 'diagnostics':\n await handleDiagnostics(args, apiUrl, token);\n break;\n case 'logs':\n await handleLogs(args, apiUrl, token);\n break;\n case 'terminate':\n await handleTerminate(args, apiUrl, token);\n break;\n case 'delete':\n await handleDelete(args, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["a"]}