@runcofactor/cli 0.15.2 → 0.17.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 (141) hide show
  1. package/dist/{account-62I7FG5G.js → account-ZSM2Q3RB.js} +6 -6
  2. package/dist/account-ZSM2Q3RB.js.map +1 -0
  3. package/dist/{api-catalog-CAJUASVC.js → api-catalog-MMPFWS52.js} +5 -5
  4. package/dist/{attachment-RL4AZUJE.js → attachment-NSYL5X3S.js} +5 -5
  5. package/dist/{augmentor-GAF3MFY6.js → augmentor-LSJLMJYP.js} +5 -5
  6. package/dist/{auth-DURHUZDW.js → auth-OYF5A4BY.js} +4 -2
  7. package/dist/{chunk-26U3DGUM.js → chunk-7YJTQCPX.js} +3 -5
  8. package/dist/chunk-7YJTQCPX.js.map +1 -0
  9. package/dist/{chunk-PXFDH6YL.js → chunk-A4ISG3VX.js} +55 -15
  10. package/dist/{chunk-PXFDH6YL.js.map → chunk-A4ISG3VX.js.map} +1 -1
  11. package/dist/{chunk-4NRDONSC.js → chunk-FGB6PS2T.js} +4 -4
  12. package/dist/chunk-FGB6PS2T.js.map +1 -0
  13. package/dist/{chunk-VKBTI5EF.js → chunk-GFP4UEUT.js} +3 -3
  14. package/dist/{chunk-IWKJQZJQ.js → chunk-GZVCNYR4.js} +55 -55
  15. package/dist/chunk-GZVCNYR4.js.map +1 -0
  16. package/dist/{chunk-G5SXUXSU.js → chunk-H7ZML5QL.js} +2 -2
  17. package/dist/{chunk-HKQ5XQAQ.js → chunk-HGPZ2QWV.js} +4 -4
  18. package/dist/{chunk-CJEKEW7R.js → chunk-IHCPMYKU.js} +3 -3
  19. package/dist/{chunk-UZ2ZA5A6.js → chunk-JZWJFG4M.js} +2 -2
  20. package/dist/{chunk-5R4HMSNX.js → chunk-MO5G5TP5.js} +17141 -16812
  21. package/dist/chunk-MO5G5TP5.js.map +1 -0
  22. package/dist/{chunk-CFJXYPTF.js → chunk-PVWG3V62.js} +13 -5
  23. package/dist/chunk-PVWG3V62.js.map +1 -0
  24. package/dist/{chunk-3CZU7XCS.js → chunk-PWZ4ULCB.js} +20 -14
  25. package/dist/chunk-PWZ4ULCB.js.map +1 -0
  26. package/dist/{chunk-ZXRVFFCY.js → chunk-VHVOTGBQ.js} +3 -3
  27. package/dist/{chunk-IGHDIWZU.js → chunk-VYTIJ6HJ.js} +17 -2
  28. package/dist/{chunk-IGHDIWZU.js.map → chunk-VYTIJ6HJ.js.map} +1 -1
  29. package/dist/{credential-JGVSEGVH.js → credential-WOATCWOU.js} +5 -5
  30. package/dist/{credential-template-CWWMOKB2.js → credential-template-Q3DQE2AH.js} +5 -5
  31. package/dist/{debug-workflow-BXRU72YZ.js → debug-workflow-ZNP5XZQF.js} +7 -7
  32. package/dist/{src-CV57ZD6I.js → dist-WW2S733L.js} +7 -9
  33. package/dist/{docs-PVBXPTGR.js → docs-XVU4LA7G.js} +5 -5
  34. package/dist/{doctor-RHMKD4W5.js → doctor-PGNHD3TI.js} +3 -3
  35. package/dist/{environment-WZKIO3R3.js → environment-MRDNWU47.js} +5 -5
  36. package/dist/{feature-flag-K5REGGDY.js → feature-flag-D3DQZ6DX.js} +11 -10
  37. package/dist/feature-flag-D3DQZ6DX.js.map +1 -0
  38. package/dist/index.js +144 -56
  39. package/dist/index.js.map +1 -1
  40. package/dist/{init-FFUZO5D7.js → init-DHWKUYIR.js} +10 -10
  41. package/dist/{install-XRKEQAFZ.js → install-DMEFGQHD.js} +5 -5
  42. package/dist/{issues-I3V6GEXU.js → issues-E4YQ4DVC.js} +5 -5
  43. package/dist/{knobs-6WLJMB44.js → knobs-NA6SPLHX.js} +5 -5
  44. package/dist/{list-PHC7VYNS.js → list-GJNGFQMC.js} +5 -5
  45. package/dist/{local-VGYRSW22.js → local-NSKOZHHA.js} +6 -6
  46. package/dist/{login-QPU2BKG2.js → login-AMSRVPXG.js} +10 -10
  47. package/dist/{mcp-LA452TOA.js → mcp-V4GKEL2J.js} +7 -8
  48. package/dist/{mcp-LA452TOA.js.map → mcp-V4GKEL2J.js.map} +1 -1
  49. package/dist/metrics-DM4YQQZN.js +367 -0
  50. package/dist/metrics-DM4YQQZN.js.map +1 -0
  51. package/dist/{product-RSZV5HMB.js → product-WGOLTBRI.js} +6 -5
  52. package/dist/product-WGOLTBRI.js.map +1 -0
  53. package/dist/{property-YP4GHQAR.js → property-B7QMGLVW.js} +5 -5
  54. package/dist/{psql-XGLBI6T7.js → psql-4JHPJ2CO.js} +3 -3
  55. package/dist/{record-KWKHP2ZY.js → record-LDNKS42Y.js} +6 -6
  56. package/dist/{record-KWKHP2ZY.js.map → record-LDNKS42Y.js.map} +1 -1
  57. package/dist/{redis-VJGCUJPV.js → redis-N44ZZ6VB.js} +3 -3
  58. package/dist/{release-NDRHPW6V.js → release-R7GKLEAI.js} +5 -5
  59. package/dist/{sandbox-OOCANWOG.js → sandbox-PLYUNOFX.js} +6 -6
  60. package/dist/{scenarios-2HRLCGFY.js → scenarios-WUUUKP2S.js} +5 -5
  61. package/dist/{session-M4ULYDYP.js → session-Y6RO7GFC.js} +15 -17
  62. package/dist/{session-M4ULYDYP.js.map → session-Y6RO7GFC.js.map} +1 -1
  63. package/dist/{skill-4DGPRDUC.js → skill-3SP7MAA4.js} +176 -15
  64. package/dist/skill-3SP7MAA4.js.map +1 -0
  65. package/dist/{spec-XZ2TKUFZ.js → spec-ESPA3H26.js} +5 -5
  66. package/dist/{src-HL7HEJIW.js → src-ECFPDE5X.js} +18 -2
  67. package/dist/src-ECFPDE5X.js.map +1 -0
  68. package/dist/{src-7LAXXTVG.js → src-OWPS5DCK.js} +63 -27
  69. package/dist/{src-7LAXXTVG.js.map → src-OWPS5DCK.js.map} +1 -1
  70. package/dist/{src-OU7544PM.js → src-PDYXACRP.js} +2 -2
  71. package/dist/{start-IYKF3C3X.js → start-KDDRLUFN.js} +8 -8
  72. package/dist/{tag-T45MMSCH.js → tag-DAGHQZAR.js} +6 -6
  73. package/dist/{task-MCUHAVTD.js → task-PRR75HI4.js} +5 -5
  74. package/dist/{test-suite-BICBRSBP.js → test-suite-O3UY7EER.js} +7 -7
  75. package/dist/{trace-2BAPMYAS.js → trace-BCSP7PCX.js} +5 -6
  76. package/dist/{triage-M3RZ2ASB.js → triage-2BKUBMMX.js} +6 -6
  77. package/dist/utilities-O3OO64T5.js +441 -0
  78. package/dist/utilities-O3OO64T5.js.map +1 -0
  79. package/dist/{workflow-ZGJU4QCV.js → workflow-76EKT3DS.js} +16 -21
  80. package/dist/workflow-76EKT3DS.js.map +1 -0
  81. package/dist/{workflow-cache-M4N325UT.js → workflow-cache-UDTTNIHT.js} +8 -8
  82. package/dist/{workflow-cache-M4N325UT.js.map → workflow-cache-UDTTNIHT.js.map} +1 -1
  83. package/dist/{workflow-debug-W4USZH35.js → workflow-debug-WO7D32EI.js} +8 -9
  84. package/dist/{workflow-debug-W4USZH35.js.map → workflow-debug-WO7D32EI.js.map} +1 -1
  85. package/dist/{workflow-proposals-5E3DTYZB.js → workflow-proposals-PGURJ6ZI.js} +7 -7
  86. package/package.json +3 -3
  87. package/dist/account-62I7FG5G.js.map +0 -1
  88. package/dist/chunk-26U3DGUM.js.map +0 -1
  89. package/dist/chunk-3CZU7XCS.js.map +0 -1
  90. package/dist/chunk-4NRDONSC.js.map +0 -1
  91. package/dist/chunk-5R4HMSNX.js.map +0 -1
  92. package/dist/chunk-CFJXYPTF.js.map +0 -1
  93. package/dist/chunk-IWKJQZJQ.js.map +0 -1
  94. package/dist/chunk-KRWRUU6R.js +0 -114
  95. package/dist/chunk-KRWRUU6R.js.map +0 -1
  96. package/dist/feature-flag-K5REGGDY.js.map +0 -1
  97. package/dist/pdf-extract-YHE54XU4.js +0 -13
  98. package/dist/product-RSZV5HMB.js.map +0 -1
  99. package/dist/skill-4DGPRDUC.js.map +0 -1
  100. package/dist/src-HL7HEJIW.js.map +0 -1
  101. package/dist/triage-M3RZ2ASB.js.map +0 -1
  102. package/dist/workflow-ZGJU4QCV.js.map +0 -1
  103. /package/dist/{api-catalog-CAJUASVC.js.map → api-catalog-MMPFWS52.js.map} +0 -0
  104. /package/dist/{attachment-RL4AZUJE.js.map → attachment-NSYL5X3S.js.map} +0 -0
  105. /package/dist/{augmentor-GAF3MFY6.js.map → augmentor-LSJLMJYP.js.map} +0 -0
  106. /package/dist/{auth-DURHUZDW.js.map → auth-OYF5A4BY.js.map} +0 -0
  107. /package/dist/{chunk-VKBTI5EF.js.map → chunk-GFP4UEUT.js.map} +0 -0
  108. /package/dist/{chunk-G5SXUXSU.js.map → chunk-H7ZML5QL.js.map} +0 -0
  109. /package/dist/{chunk-HKQ5XQAQ.js.map → chunk-HGPZ2QWV.js.map} +0 -0
  110. /package/dist/{chunk-CJEKEW7R.js.map → chunk-IHCPMYKU.js.map} +0 -0
  111. /package/dist/{chunk-UZ2ZA5A6.js.map → chunk-JZWJFG4M.js.map} +0 -0
  112. /package/dist/{chunk-ZXRVFFCY.js.map → chunk-VHVOTGBQ.js.map} +0 -0
  113. /package/dist/{credential-JGVSEGVH.js.map → credential-WOATCWOU.js.map} +0 -0
  114. /package/dist/{credential-template-CWWMOKB2.js.map → credential-template-Q3DQE2AH.js.map} +0 -0
  115. /package/dist/{debug-workflow-BXRU72YZ.js.map → debug-workflow-ZNP5XZQF.js.map} +0 -0
  116. /package/dist/{pdf-extract-YHE54XU4.js.map → dist-WW2S733L.js.map} +0 -0
  117. /package/dist/{docs-PVBXPTGR.js.map → docs-XVU4LA7G.js.map} +0 -0
  118. /package/dist/{doctor-RHMKD4W5.js.map → doctor-PGNHD3TI.js.map} +0 -0
  119. /package/dist/{environment-WZKIO3R3.js.map → environment-MRDNWU47.js.map} +0 -0
  120. /package/dist/{init-FFUZO5D7.js.map → init-DHWKUYIR.js.map} +0 -0
  121. /package/dist/{install-XRKEQAFZ.js.map → install-DMEFGQHD.js.map} +0 -0
  122. /package/dist/{issues-I3V6GEXU.js.map → issues-E4YQ4DVC.js.map} +0 -0
  123. /package/dist/{knobs-6WLJMB44.js.map → knobs-NA6SPLHX.js.map} +0 -0
  124. /package/dist/{list-PHC7VYNS.js.map → list-GJNGFQMC.js.map} +0 -0
  125. /package/dist/{local-VGYRSW22.js.map → local-NSKOZHHA.js.map} +0 -0
  126. /package/dist/{login-QPU2BKG2.js.map → login-AMSRVPXG.js.map} +0 -0
  127. /package/dist/{property-YP4GHQAR.js.map → property-B7QMGLVW.js.map} +0 -0
  128. /package/dist/{psql-XGLBI6T7.js.map → psql-4JHPJ2CO.js.map} +0 -0
  129. /package/dist/{redis-VJGCUJPV.js.map → redis-N44ZZ6VB.js.map} +0 -0
  130. /package/dist/{release-NDRHPW6V.js.map → release-R7GKLEAI.js.map} +0 -0
  131. /package/dist/{sandbox-OOCANWOG.js.map → sandbox-PLYUNOFX.js.map} +0 -0
  132. /package/dist/{scenarios-2HRLCGFY.js.map → scenarios-WUUUKP2S.js.map} +0 -0
  133. /package/dist/{spec-XZ2TKUFZ.js.map → spec-ESPA3H26.js.map} +0 -0
  134. /package/dist/{src-CV57ZD6I.js.map → src-PDYXACRP.js.map} +0 -0
  135. /package/dist/{start-IYKF3C3X.js.map → start-KDDRLUFN.js.map} +0 -0
  136. /package/dist/{src-OU7544PM.js.map → tag-DAGHQZAR.js.map} +0 -0
  137. /package/dist/{task-MCUHAVTD.js.map → task-PRR75HI4.js.map} +0 -0
  138. /package/dist/{test-suite-BICBRSBP.js.map → test-suite-O3UY7EER.js.map} +0 -0
  139. /package/dist/{tag-T45MMSCH.js.map → trace-BCSP7PCX.js.map} +0 -0
  140. /package/dist/{trace-2BAPMYAS.js.map → triage-2BKUBMMX.js.map} +0 -0
  141. /package/dist/{workflow-proposals-5E3DTYZB.js.map → workflow-proposals-PGURJ6ZI.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mcp/index.ts","../../mcp-tools/src/context.ts","../../mcp-tools/src/api-client.ts","../../mcp-tools/src/tool-helpers.ts","../../mcp-tools/src/registry.ts","../../mcp-tools/src/groups/workflows.ts","../../mcp-tools/src/groups/workflow-proposals.ts","../../mcp-tools/src/groups/workflow-runs.ts","../../mcp-tools/src/groups/test-suites.ts","../../mcp-tools/src/groups/credentials.ts","../../mcp-tools/src/groups/issues.ts","../../mcp-tools/src/groups/index.ts","../src/mcp/api-url.ts","../src/mcp/tool-helpers.ts","../src/mcp/session-tools.ts","../src/mcp/browser-tools.ts","../src/mcp/login-tool.ts","../src/mcp/upgrade-tool.ts","../src/mcp/instructions.ts"],"sourcesContent":["/**\n * MCP Server for Canary CLI.\n *\n * Combines:\n * - HTTP-only shared tools from @chatsdet/mcp-tools (workflows, runs, suites,\n * credentials, issues, proposals)\n * - CLI-local tools (login, upgrade, browser daemon, cloud-relay sessions)\n * that depend on local state and can't be hosted remotely.\n *\n * @module\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { buildRegistry, sharedGroups } from '@chatsdet/mcp-tools';\nimport { readStoredToken } from '../auth';\nimport { readBrandEnv } from '../brand.js';\nimport { resolveApiUrl } from './api-url';\nimport { toolText } from './tool-helpers';\nimport { getSessionToolDefinitions, handleSessionTool } from './session-tools';\nimport { getBrowserMCPToolDefinitions, handleBrowserTool } from './browser-tools';\nimport { getLoginToolDefinitions, handleLoginTool } from './login-tool';\nimport { getUpgradeToolDefinitions, handleUpgradeTool } from './upgrade-tool';\nimport { CANARY_MCP_INSTRUCTIONS } from './instructions';\n\nasync function resolveCtx() {\n const apiToken = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken());\n if (!apiToken) {\n throw new Error('Missing token. Call the canary_login tool or set CANARY_API_TOKEN.');\n }\n return { apiUrl: resolveApiUrl(), apiToken };\n}\n\nexport async function runMcp(_argv: string[]) {\n const registry = buildRegistry(sharedGroups);\n\n const server = new Server(\n { name: 'canary-cli', version: '0.1.0' },\n {\n capabilities: { tools: {} },\n instructions: CANARY_MCP_INSTRUCTIONS,\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n ...getLoginToolDefinitions(),\n ...getUpgradeToolDefinitions(),\n ...getSessionToolDefinitions(),\n ...getBrowserMCPToolDefinitions(),\n ...registry.list(),\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = req.params.name;\n const args = (req.params.arguments ?? {}) as Record<string, unknown>;\n\n // CLI-local groups try first; each returns null if the tool is not theirs.\n const loginResult = await handleLoginTool(tool, args);\n if (loginResult) return loginResult;\n\n const upgradeResult = await handleUpgradeTool(tool, args);\n if (upgradeResult) return upgradeResult;\n\n const browserResult = await handleBrowserTool(tool, args);\n if (browserResult) return browserResult;\n\n const sessionResult = await handleSessionTool(tool, args);\n if (sessionResult) return sessionResult;\n\n // Shared HTTP-only tools — provide ctx for this call.\n try {\n const ctx = await resolveCtx();\n return await registry.call(tool, args, ctx);\n } catch (err) {\n return toolText(err instanceof Error ? err.message : String(err));\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n return new Promise<void>(() => undefined);\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * Per-request context for MCP tool handlers. Threaded via AsyncLocalStorage so\n * handler bodies don't have to take ctx as a parameter — `mcpApiRequest()`\n * pulls it from `currentToolCtx()`.\n */\nexport type ToolCtx = {\n apiUrl: string;\n apiToken: string;\n};\n\nconst storage = new AsyncLocalStorage<ToolCtx>();\n\nexport function withToolCtx<T>(ctx: ToolCtx, fn: () => Promise<T>): Promise<T> {\n return storage.run(ctx, fn);\n}\n\nexport function currentToolCtx(): ToolCtx | undefined {\n return storage.getStore();\n}\n","import { currentToolCtx } from './context';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/**\n * Authenticated API request. Pulls `{ apiUrl, apiToken }` from the\n * AsyncLocalStorage-backed ToolCtx — every tool handler runs inside a\n * `withToolCtx()` frame set up by the registry dispatcher.\n *\n * Throws on non-2xx with a prefixed message MCP clients can pattern-match\n * (`[unauthorized]`, `[timeout]`, `[http-N]`).\n */\nexport async function mcpApiRequest<T>(\n method: string,\n path: string,\n body?: Record<string, unknown>\n): Promise<T> {\n const ctx = currentToolCtx();\n if (!ctx) {\n throw new Error('[no-context] mcpApiRequest called outside of withToolCtx()');\n }\n\n const url = `${ctx.apiUrl}${path}`;\n let res: Response;\n try {\n res = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${ctx.apiToken}`,\n 'Content-Type': 'application/json',\n },\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n ...(body ? { body: JSON.stringify(body) } : {}),\n });\n } catch (err) {\n if (err instanceof Error && err.name === 'TimeoutError') {\n throw new Error(`[timeout] upstream API did not respond within ${DEFAULT_TIMEOUT_MS}ms`);\n }\n throw new Error(`[network] ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (!res.ok) {\n if (res.status === 401) {\n throw new Error('[unauthorized] Your session may have expired.');\n }\n const text = await res.text().catch(() => '');\n throw new Error(`[http-${res.status}] ${text || res.statusText}`);\n }\n\n return (await res.json()) as T;\n}\n","export function toolText(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nexport function toolJson(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n","import type { ToolCallResult, ToolDefinition, ToolGroup } from './types';\nimport { type ToolCtx, withToolCtx } from './context';\nimport { toolText } from './tool-helpers';\n\nexport type Registry = {\n list(): ToolDefinition[];\n call(tool: string, args: Record<string, unknown>, ctx: ToolCtx): Promise<ToolCallResult>;\n};\n\n/**\n * Bundle a set of ToolGroups into a Registry. The Registry runs each tool call\n * inside an `AsyncLocalStorage` frame so handler bodies can call\n * `mcpApiRequest()` without taking ctx as a parameter.\n */\nexport function buildRegistry(groups: ToolGroup[]): Registry {\n return {\n list() {\n return groups.flatMap((g) => g.definitions());\n },\n\n async call(tool, args, ctx) {\n return withToolCtx(ctx, async () => {\n for (const group of groups) {\n const result = await group.handle(tool, args);\n if (result) return result;\n }\n return toolText(`Unknown tool: ${tool}`);\n });\n },\n };\n}\n","/**\n * MCP tools for workflow management.\n *\n * Mirrors `canary workflow list` and `canary workflow get`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getWorkflowToolDefinitions() {\n return [\n {\n name: 'canary_workflow_list',\n description:\n 'List workflows in the current organization. Supports filtering by name, type, and status with pagination.',\n inputSchema: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description: 'Search workflows by name',\n },\n flowType: {\n type: 'string',\n enum: ['standard', 'setup', 'seed', 'teardown'],\n description: 'Filter by flow type',\n },\n status: {\n type: 'string',\n enum: ['draft', 'approved'],\n description:\n \"Filter by approval status. 'draft' = not yet approved; 'approved' = a human verified the test checks the right thing. Suite inclusion is the separate `promotion` axis (promoted/paused, managed via `canary workflow promote|pause`), and reliability (passing/flaky/degraded) is the separate `health` dimension.\",\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n pageSize: {\n type: 'number',\n description: 'Page size (default: 25)',\n },\n },\n },\n },\n {\n name: 'canary_workflow_get',\n description:\n 'Get a workflow definition with its steps, nodes, and configuration details.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_patch',\n description:\n 'Update workflow properties using merge-patch. Only provided fields are updated; omitted fields are left unchanged.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n name: {\n type: 'string',\n description: 'New workflow name',\n },\n description: {\n type: 'string',\n description: 'New description',\n },\n status: {\n type: 'string',\n enum: ['draft', 'approved'],\n description:\n \"New approval status. 'approved' asserts a HUMAN verified this test checks the right thing — only set it when the user has personally confirmed. Approval does NOT put the test into suites; suite inclusion is the separate promote/pause axis (use `canary workflow promote|pause`). Reliability is tracked automatically by the `health` dimension.\",\n },\n flowType: {\n type: 'string',\n enum: ['standard', 'setup', 'seed', 'teardown'],\n description: 'New flow type',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_run',\n description:\n 'Trigger a workflow execution. Returns the run ID for tracking status via canary_workflow_runs_get.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID to execute',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_sync',\n description:\n 'Atomically replace all nodes and edges in a workflow. Automatically creates a draft snapshot of the current state before overwriting so changes can be reverted. Use canary_workflow_get to read the current DAG first, modify nodes/edges, then sync back. When using propose=true on an existing workflow, REUSE each existing node\\'s `id` for steps you keep (omit `id` only for genuinely new steps). Without ID reuse the proposal will diff as a full rewrite — every step shown as Removed+Added in the review UI even when only configs changed.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n nodes: {\n type: 'array',\n description: 'Array of node objects with id, nodeType, orderIndex, configJson',\n items: { type: 'object' },\n },\n edges: {\n type: 'array',\n description: 'Array of edge objects with id, sourceNodeId, targetNodeId, edgeType',\n items: { type: 'object' },\n },\n createSnapshot: {\n type: 'boolean',\n description: 'Create a draft snapshot before syncing (default: true)',\n default: true,\n },\n propose: {\n type: 'boolean',\n description: 'Create a proposal instead of applying directly. The proposal can be reviewed and accepted/rejected via the UI. IMPORTANT: when proposing on an existing workflow, reuse each existing node\\'s `id` for steps you intend to keep — only omit `id` for genuinely new steps. Otherwise the diff will show every step as Removed+Added.',\n default: false,\n },\n proposalTitle: {\n type: 'string',\n description: 'Title for the proposal (used with propose: true)',\n },\n proposalDescription: {\n type: 'string',\n description: 'Description/rationale for the proposal (used with propose: true)',\n },\n },\n required: ['workflowId', 'nodes', 'edges'],\n },\n },\n ];\n}\n\nexport async function handleWorkflowTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_workflow_list') {\n try {\n const params = new URLSearchParams();\n if (args.search) params.set('search', String(args.search));\n if (args.flowType) params.set('flowType', String(args.flowType));\n if (args.status) params.set('status', String(args.status));\n if (args.page) params.set('page', String(args.page));\n if (args.pageSize) params.set('pageSize', String(args.pageSize));\n\n const qs = params.toString();\n const path = `/workflows${qs ? `?${qs}` : ''}`;\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown[];\n pagination: unknown;\n }>('GET', path);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data, pagination: result.pagination });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_get') {\n try {\n const workflowId = args.workflowId as string;\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n workflow?: unknown;\n targetOrgId?: string;\n targetOrgName?: string;\n }>('GET', `/workflows/${workflowId}`);\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({ ok: true, workflow: result.workflow });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_patch') {\n try {\n const workflowId = args.workflowId as string;\n const body: Record<string, unknown> = {};\n if (args.name) body.name = String(args.name);\n if (args.description) body.description = String(args.description);\n if (args.status) body.status = String(args.status);\n if (args.flowType) body.flowType = String(args.flowType);\n\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n workflow?: unknown;\n }>('PUT', `/workflows/${workflowId}`, body);\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({ ok: true, workflow: result.workflow });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_run') {\n try {\n const workflowId = args.workflowId as string;\n\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n runId?: string;\n streamId?: string;\n }>('POST', `/workflows/${workflowId}/execute`);\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({ ok: true, runId: result.runId, streamId: result.streamId });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_sync') {\n try {\n const workflowId = args.workflowId as string;\n const nodes = args.nodes as unknown[];\n const edges = args.edges as unknown[];\n\n // --propose: create a proposal instead of applying directly\n if (args.propose) {\n const title = (args.proposalTitle as string) ?? `Sync proposal (${nodes.length} nodes)`;\n const description = (args.proposalDescription as string) ?? null;\n\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n data?: { id: string; title: string; status: string };\n }>('POST', `/workflows/${workflowId}/proposals`, {\n title,\n description,\n snapshotJson: { nodes, edges },\n source: 'api',\n });\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({\n ok: true,\n proposalId: result.data?.id,\n title: result.data?.title,\n status: result.data?.status,\n });\n }\n\n const createSnapshot = args.createSnapshot !== false;\n\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n snapshotVersion?: string;\n }>('PUT', `/workflows/${workflowId}/draft-state`, {\n nodes,\n edges,\n createSnapshot,\n });\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({\n ok: true,\n ...(result.snapshotVersion ? { snapshotVersion: result.snapshotVersion } : {}),\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","/**\n * MCP tools for workflow proposals: list / get / diff / accept / reject /\n * revert. Mirrors `canary workflow proposals <verb>` with the same JSON\n * output shape so agents get identical responses whether they shell-out or\n * call MCP directly.\n *\n * @module\n */\n\nimport {\n diffSnapshots,\n fromApiSnapshot,\n type SnapshotDiff,\n} from '@chatsdet/workflow-diff';\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\n// Types duplicated here to avoid the MCP server importing from the CLI's\n// `workflow-proposals.ts` which would pull in TTY-detection + process.exit\n// paths that don't belong in MCP land.\ninterface ProposalSummary {\n id: string;\n workflowId: string;\n title: string;\n description: string | null;\n source: string;\n status: string;\n createdByUserId: string | null;\n decidedByUserId: string | null;\n decidedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface ProposalDetail extends ProposalSummary {\n snapshotJson: {\n nodes?: Array<{ id: string; nodeType: string; orderIndex?: number; configJson?: Record<string, unknown> }>;\n edges?: Array<{ id: string; sourceNodeId: string; targetNodeId: string; edgeType?: string | null }>;\n };\n sourceMetadata: Record<string, unknown> | null;\n}\n\ninterface WorkflowDetail {\n id: string;\n nodes: Array<{ id: string; nodeType: string; orderIndex?: number; configJson?: Record<string, unknown> }>;\n edges: Array<{ id: string; sourceNodeId: string; targetNodeId: string; edgeType?: string | null }>;\n}\n\nexport function getWorkflowProposalsToolDefinitions() {\n return [\n {\n name: 'canary_workflow_proposals_list',\n description:\n 'List workflow proposals. By default returns pending proposals; pass status=\"all\" for every status.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string', description: 'Workflow UUID' },\n status: {\n type: 'string',\n enum: ['pending', 'accepted', 'rejected', 'stale', 'all'],\n description: 'Filter by status (default: pending)',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_proposals_get',\n description: 'Fetch a proposal including its full snapshot JSON.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n {\n name: 'canary_workflow_proposals_diff',\n description:\n 'Compute a per-node diff between a proposal and the current workflow draft. Returns summary counts plus per-field changes for changed nodes.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n {\n name: 'canary_workflow_proposals_accept',\n description:\n 'Apply a proposal to the workflow draft. Omit acceptedNodeIds for atomic (all-or-nothing) accept; provide it to cherry-pick a subset.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n acceptedNodeIds: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Optional: node ids from the diff to include. Omit for atomic accept of every change.',\n },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n {\n name: 'canary_workflow_proposals_reject',\n description: 'Reject a pending proposal. Does not change the workflow draft.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n {\n name: 'canary_workflow_proposals_revert',\n description:\n 'Revert a previously-accepted proposal back to pending. Only the user who accepted it may revert.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n ];\n}\n\nexport async function handleWorkflowProposalsTool(\n tool: string,\n args: Record<string, unknown>,\n) {\n if (!tool.startsWith('canary_workflow_proposals_')) return null;\n\n try {\n switch (tool) {\n case 'canary_workflow_proposals_list':\n return await listProposals(args);\n case 'canary_workflow_proposals_get':\n return await getProposal(args);\n case 'canary_workflow_proposals_diff':\n return await diffProposal(args);\n case 'canary_workflow_proposals_accept':\n return await acceptProposal(args);\n case 'canary_workflow_proposals_reject':\n return await rejectProposal(args);\n case 'canary_workflow_proposals_revert':\n return await revertProposal(args);\n default:\n return null;\n }\n } catch (err) {\n return toolJson({\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n}\n\n// ── Tool implementations ─────────────────────────────────────────────────\n\nasync function listProposals(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const status = typeof args.status === 'string' ? args.status : 'pending';\n const query = status === 'all' ? '' : `?status=${encodeURIComponent(status)}`;\n const res = await mcpApiRequest<{\n ok: boolean;\n data?: ProposalSummary[];\n error?: string;\n }>('GET', `/workflows/${workflowId}/proposals${query}`);\n return toolJson({\n ok: res.ok,\n workflowId,\n count: res.data?.length ?? 0,\n proposals: res.data ?? [],\n error: res.error,\n });\n}\n\nasync function getProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const res = await mcpApiRequest<{\n ok: boolean;\n data?: ProposalDetail;\n error?: string;\n }>('GET', `/workflows/${workflowId}/proposals/${proposalId}`);\n return toolJson(res);\n}\n\nasync function diffProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const [propRes, wfRes] = await Promise.all([\n mcpApiRequest<{ ok: boolean; data?: ProposalDetail; error?: string }>(\n 'GET',\n `/workflows/${workflowId}/proposals/${proposalId}`,\n ),\n mcpApiRequest<{ ok: boolean; workflow?: WorkflowDetail; error?: string }>(\n 'GET',\n `/workflows/${workflowId}`,\n ),\n ]);\n if (!propRes.ok || !propRes.data) {\n return toolJson({ ok: false, error: propRes.error ?? 'proposal not found' });\n }\n if (!wfRes.workflow) {\n return toolJson({ ok: false, error: wfRes.error ?? 'workflow not found' });\n }\n const current = fromApiSnapshot({\n nodes: wfRes.workflow.nodes,\n edges: wfRes.workflow.edges,\n });\n const proposed = fromApiSnapshot(propRes.data.snapshotJson);\n const diff = diffSnapshots(current, proposed);\n return toolJson(buildDiffPayload(propRes.data, diff));\n}\n\nasync function acceptProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const acceptedNodeIds = Array.isArray(args.acceptedNodeIds)\n ? (args.acceptedNodeIds as string[]).filter((s) => typeof s === 'string')\n : null;\n const body = acceptedNodeIds\n ? { selection: { acceptedNodeIds } }\n : undefined;\n const res = await mcpApiRequest<{ ok: boolean; error?: string }>(\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/accept`,\n body,\n );\n return toolJson({\n ...res,\n workflowId,\n proposalId,\n partial: acceptedNodeIds !== null,\n });\n}\n\nasync function rejectProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const res = await mcpApiRequest<{ ok: boolean; error?: string }>(\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/reject`,\n );\n return toolJson({ ...res, workflowId, proposalId });\n}\n\nasync function revertProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const res = await mcpApiRequest<{ ok: boolean; error?: string }>(\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/revert`,\n );\n return toolJson({ ...res, workflowId, proposalId });\n}\n\n// ── Diff payload shaper (shared shape with the CLI) ──────────────────────\n\nfunction buildDiffPayload(proposal: ProposalDetail, diff: SnapshotDiff) {\n return {\n proposal: {\n id: proposal.id,\n title: proposal.title,\n source: proposal.source,\n status: proposal.status,\n stale: proposal.status === 'stale',\n createdAt: proposal.createdAt,\n decidedAt: proposal.decidedAt,\n },\n summary: {\n addedNodes: diff.addedNodes.length,\n removedNodes: diff.removedNodes.length,\n changedNodes: diff.changedNodes.length,\n addedEdges: diff.addedEdges.length,\n removedEdges: diff.removedEdges.length,\n touchedCount: diff.touchedCount,\n isEmpty: diff.isEmpty,\n },\n nodes: {\n added: diff.addedNodes.map((n) => ({\n id: n.id,\n nodeType: n.nodeType,\n configJson: n.configJson,\n })),\n removed: diff.removedNodes.map((n) => ({\n id: n.id,\n nodeType: n.nodeType,\n configJson: n.configJson,\n })),\n changed: diff.changedNodes.map((c) => ({\n id: c.id,\n nodeType: c.nodeType,\n typeChanged: c.typeChanged,\n beforeType: c.beforeType,\n afterType: c.afterType,\n fieldChanges: c.fieldChanges,\n })),\n },\n edges: {\n added: diff.addedEdges.map((e) => ({\n sourceNodeId: e.sourceNodeId,\n targetNodeId: e.targetNodeId,\n edgeType: e.edgeType ?? null,\n })),\n removed: diff.removedEdges.map((e) => ({\n sourceNodeId: e.sourceNodeId,\n targetNodeId: e.targetNodeId,\n edgeType: e.edgeType ?? null,\n })),\n },\n };\n}\n","/**\n * MCP tools for workflow run results.\n *\n * Mirrors `canary workflow runs list`, `get`, and `diagnostics`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getWorkflowRunsToolDefinitions() {\n return [\n {\n name: 'canary_workflow_runs_list',\n description:\n 'List runs for a specific workflow with status, duration, and pagination.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n pageSize: {\n type: 'number',\n description: 'Page size (default: 10)',\n },\n mode: {\n type: 'string',\n enum: ['browser', 'api'],\n description: 'Filter by run mode',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_runs_get',\n description:\n 'Get workflow run detail including steps, status, duration, and error messages. Also serves as a status check for in-progress runs.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n runId: {\n type: 'string',\n description: 'The workflow run UUID',\n },\n },\n required: ['workflowId', 'runId'],\n },\n },\n {\n name: 'canary_workflow_runs_diagnostics',\n description:\n 'Get failure diagnostic for a workflow run. Returns AI-generated analysis if available, otherwise falls back to console logs and network requests.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n runId: {\n type: 'string',\n description: 'The workflow run UUID',\n },\n },\n required: ['workflowId', 'runId'],\n },\n },\n ];\n}\n\nexport async function handleWorkflowRunsTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_workflow_runs_list') {\n try {\n const workflowId = args.workflowId as string;\n const params = new URLSearchParams();\n params.set('page', String(args.page ?? 1));\n params.set('pageSize', String(args.pageSize ?? 10));\n if (args.mode) params.set('mode', String(args.mode));\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: { runs: unknown[] };\n pagination: unknown;\n }>('GET', `/workflows/${workflowId}/runs?${params}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, runs: result.data.runs, pagination: result.pagination });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_runs_get') {\n try {\n const workflowId = args.workflowId as string;\n const runId = args.runId as string;\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown;\n }>('GET', `/workflows/${workflowId}/runs/${runId}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_runs_diagnostics') {\n try {\n const workflowId = args.workflowId as string;\n const runId = args.runId as string;\n\n // Try AI failure diagnostic first\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown;\n }>('GET', `/workflows/${workflowId}/runs/${runId}/failure-diagnostic`);\n\n if (result.ok && result.data) {\n return toolJson({ ok: true, data: result.data });\n }\n\n // Fall back to raw diagnostics\n const rawResult = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n consoleLogs: unknown[];\n networkRequests: unknown[];\n }>('GET', `/workflows/${workflowId}/runs/${runId}/diagnostics`);\n\n if (!rawResult.ok) {\n return toolJson({ ok: true, data: null, message: 'No diagnostic available' });\n }\n\n return toolJson({\n ok: true,\n consoleLogs: rawResult.consoleLogs,\n networkRequests: rawResult.networkRequests,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","/**\n * MCP tools for test suite (workflow test execution) results and triggering.\n *\n * Mirrors `canary test-suite run`, `list`, `get`, `diagnostics`, and `steps`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getTestSuiteToolDefinitions() {\n return [\n {\n name: 'canary_test_suite_run',\n description:\n 'Trigger a test suite execution. Returns the suite ID and job ID. Use canary_test_suite_get to check results after triggering.',\n inputSchema: {\n type: 'object',\n properties: {\n tag: {\n type: 'string',\n description: 'Filter workflows by tag',\n },\n namePattern: {\n type: 'string',\n description: 'Filter workflows by name pattern (regex)',\n },\n propertyId: {\n type: 'string',\n description: 'Target a specific property by UUID',\n },\n environmentId: {\n type: 'string',\n description: 'Target a specific environment by UUID',\n },\n },\n },\n },\n {\n name: 'canary_test_suite_list',\n description:\n 'List recent test suite executions with pass/fail counts, ordered by most recent first.',\n inputSchema: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n pageSize: {\n type: 'number',\n description: 'Page size (default: 20)',\n },\n },\n },\n },\n {\n name: 'canary_test_suite_get',\n description:\n 'Get test suite detail including all individual test runs and their results.',\n inputSchema: {\n type: 'object',\n properties: {\n executionId: {\n type: 'string',\n description: 'The test execution UUID',\n },\n },\n required: ['executionId'],\n },\n },\n {\n name: 'canary_test_suite_diagnostics',\n description:\n 'Get AI-generated failure diagnostic for a specific workflow run, including root cause analysis and recommendations.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n runId: {\n type: 'string',\n description: 'The workflow run UUID',\n },\n },\n required: ['workflowId', 'runId'],\n },\n },\n {\n name: 'canary_test_suite_steps',\n description:\n 'Get the individual steps of a workflow run with their status, duration, and error messages.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n runId: {\n type: 'string',\n description: 'The workflow run UUID',\n },\n },\n required: ['workflowId', 'runId'],\n },\n },\n ];\n}\n\nexport async function handleTestSuiteTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_test_suite_run') {\n try {\n const params = new URLSearchParams();\n if (args.tag) params.set('tag', String(args.tag));\n if (args.namePattern) params.set('namePattern', String(args.namePattern));\n\n const queryStr = params.toString();\n const path = `/workflows/test-runs${queryStr ? `?${queryStr}` : ''}`;\n\n const body: Record<string, string> = {};\n if (args.propertyId) body.propertyId = String(args.propertyId);\n if (args.environmentId) body.environmentId = String(args.environmentId);\n\n const data = await mcpApiRequest<{\n ok: boolean;\n suiteId?: string;\n jobId?: string;\n appUrl?: string;\n error?: string;\n }>('POST', path, body);\n\n if (!data.ok) {\n return toolJson({ ok: false, error: data.error ?? 'Unknown error' });\n }\n\n return toolJson({\n ok: true,\n suiteId: data.suiteId,\n jobId: data.jobId,\n appUrl: data.appUrl,\n message: `Test suite triggered. Use canary_test_suite_get or canary_test_suite_list to check results.`,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_test_suite_list') {\n try {\n const params = new URLSearchParams();\n params.set('page', String(args.page ?? 1));\n params.set('pageSize', String(args.pageSize ?? 20));\n params.set('sortBy', 'createdAt');\n params.set('sortOrder', 'desc');\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown[];\n pagination: unknown;\n }>('GET', `/workflows/test-executions?${params}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data, pagination: result.pagination });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_test_suite_get') {\n try {\n const executionId = args.executionId as string;\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n execution: unknown;\n testRuns: unknown[];\n }>('GET', `/workflows/test-executions/${executionId}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, execution: result.execution, testRuns: result.testRuns });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_test_suite_diagnostics') {\n try {\n const workflowId = args.workflowId as string;\n const runId = args.runId as string;\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown;\n }>('GET', `/workflows/${workflowId}/runs/${runId}/failure-diagnostic`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_test_suite_steps') {\n try {\n const workflowId = args.workflowId as string;\n const runId = args.runId as string;\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown;\n }>('GET', `/workflows/${workflowId}/runs/${runId}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","/**\n * MCP tools for credential management.\n *\n * Mirrors `canary credential list`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getCredentialToolDefinitions() {\n return [\n {\n name: 'canary_credential_list',\n description:\n 'List credentials in the current organization with their property and environment info.',\n inputSchema: {\n type: 'object',\n properties: {\n property: {\n type: 'string',\n description: 'Filter by property name or ID',\n },\n },\n },\n },\n ];\n}\n\nexport async function handleCredentialTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_credential_list') {\n try {\n const result = await mcpApiRequest<{\n ok: boolean;\n items: Array<{\n id: string;\n name: string;\n propertyId: string;\n propertyName?: string;\n propertyBaseUrl?: string;\n environmentId?: string | null;\n environmentName?: string | null;\n isEphemeral?: boolean;\n }>;\n }>('GET', '/org/credentials');\n\n let items = result.items ?? [];\n\n // Filter out ephemeral credentials\n items = items.filter((c) => !c.isEphemeral);\n\n // Apply property filter if provided\n if (args.property) {\n const filter = String(args.property).toLowerCase();\n items = items.filter(\n (c) =>\n c.propertyId === args.property ||\n (c.propertyName && c.propertyName.toLowerCase().includes(filter))\n );\n }\n\n return toolJson({ ok: true, credentials: items });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","/**\n * MCP tools for issue management.\n *\n * Mirrors `canary issues list` and `canary issues get`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getIssueToolDefinitions() {\n return [\n {\n name: 'canary_issues_list',\n description:\n 'List and search issues in the current organization. Supports full-text search, severity/status filtering, and pagination.',\n inputSchema: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description: 'Full-text search query',\n },\n severity: {\n type: 'string',\n enum: ['low', 'medium', 'high', 'unknown'],\n description: 'Filter by severity level',\n },\n statuses: {\n type: 'string',\n description: 'Comma-separated status filter: open, closed, not_a_bug',\n },\n propertyId: {\n type: 'string',\n description: 'Filter by property UUID',\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n pageSize: {\n type: 'number',\n description: 'Page size (default: 25)',\n },\n },\n },\n },\n {\n name: 'canary_issues_get',\n description:\n 'Get issue detail with diagnostics, including console errors and network failures from the latest occurrence.',\n inputSchema: {\n type: 'object',\n properties: {\n issueId: {\n type: 'string',\n description: 'The issue UUID',\n },\n },\n required: ['issueId'],\n },\n },\n ];\n}\n\nexport async function handleIssueTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_issues_list') {\n try {\n const params = new URLSearchParams();\n if (args.search) params.set('search', String(args.search));\n if (args.severity) params.set('severity', String(args.severity));\n if (args.statuses) params.set('statuses', String(args.statuses));\n if (args.propertyId) params.set('propertyId', String(args.propertyId));\n if (args.page) params.set('page', String(args.page));\n if (args.pageSize) params.set('pageSize', String(args.pageSize));\n\n const qs = params.toString();\n const path = `/v2/issues${qs ? `?${qs}` : ''}`;\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown[];\n pagination: unknown;\n }>('GET', path);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data, pagination: result.pagination });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_issues_get') {\n try {\n const issueId = args.issueId as string;\n\n const detailResult = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: {\n issue: { id: string; latestOccurrence?: { id: string } | null };\n occurrences: unknown[];\n commentCount: number;\n };\n }>('GET', `/v2/issues/${issueId}`);\n\n if (!detailResult.ok) {\n return toolJson({ ok: false, error: detailResult.error ?? 'Unknown error' });\n }\n\n const { issue } = detailResult.data;\n const occ = issue.latestOccurrence;\n\n let consoleErrors: unknown[] = [];\n let networkErrors: unknown[] = [];\n\n if (occ) {\n try {\n const [consoleRes, networkRes] = await Promise.all([\n mcpApiRequest<{ ok: boolean; data: unknown[] }>(\n 'GET',\n `/v2/issues/${issueId}/occurrences/${occ.id}/console-logs`\n ),\n mcpApiRequest<{ ok: boolean; data: unknown[] }>(\n 'GET',\n `/v2/issues/${issueId}/occurrences/${occ.id}/network-requests`\n ),\n ]);\n\n if (consoleRes.ok && Array.isArray(consoleRes.data)) {\n consoleErrors = (consoleRes.data as Array<{ type: string }>).filter(\n (e) => e.type === 'error'\n );\n }\n\n if (networkRes.ok && Array.isArray(networkRes.data)) {\n networkErrors = (networkRes.data as Array<{ status: number | null }>).filter(\n (e) => e.status === null || e.status === 0 || (e.status !== null && e.status >= 400)\n );\n }\n } catch {\n // Diagnostics are best-effort\n }\n }\n\n return toolJson({\n ok: true,\n ...detailResult.data,\n consoleErrors,\n networkErrors,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","import type { ToolGroup } from '../types';\nimport { getWorkflowToolDefinitions, handleWorkflowTool } from './workflows';\nimport {\n getWorkflowProposalsToolDefinitions,\n handleWorkflowProposalsTool,\n} from './workflow-proposals';\nimport { getWorkflowRunsToolDefinitions, handleWorkflowRunsTool } from './workflow-runs';\nimport { getTestSuiteToolDefinitions, handleTestSuiteTool } from './test-suites';\nimport { getCredentialToolDefinitions, handleCredentialTool } from './credentials';\nimport { getIssueToolDefinitions, handleIssueTool } from './issues';\n\nexport const workflowsGroup: ToolGroup = {\n id: 'workflows',\n definitions: getWorkflowToolDefinitions,\n handle: (tool, args) => handleWorkflowTool(tool, args),\n};\n\nexport const workflowProposalsGroup: ToolGroup = {\n id: 'workflow-proposals',\n definitions: getWorkflowProposalsToolDefinitions,\n handle: (tool, args) => handleWorkflowProposalsTool(tool, args),\n};\n\nexport const workflowRunsGroup: ToolGroup = {\n id: 'workflow-runs',\n definitions: getWorkflowRunsToolDefinitions,\n handle: (tool, args) => handleWorkflowRunsTool(tool, args),\n};\n\nexport const testSuitesGroup: ToolGroup = {\n id: 'test-suites',\n definitions: getTestSuiteToolDefinitions,\n handle: (tool, args) => handleTestSuiteTool(tool, args),\n};\n\nexport const credentialsGroup: ToolGroup = {\n id: 'credentials',\n definitions: getCredentialToolDefinitions,\n handle: (tool, args) => handleCredentialTool(tool, args),\n};\n\nexport const issuesGroup: ToolGroup = {\n id: 'issues',\n definitions: getIssueToolDefinitions,\n handle: (tool, args) => handleIssueTool(tool, args),\n};\n\n/**\n * All HTTP-only groups (no daemon, no CLI auth state). Safe to use from any\n * MCP host that has an `apiToken` for the canary API.\n */\nexport const sharedGroups: ToolGroup[] = [\n workflowsGroup,\n workflowProposalsGroup,\n workflowRunsGroup,\n testSuitesGroup,\n credentialsGroup,\n issuesGroup,\n];\n","import { readBrandEnv } from '../brand.js';\n\nexport const DEFAULT_API_URL = 'https://api.trycanary.ai';\n\nexport function resolveApiUrl(): string {\n return readBrandEnv('CANARY_API_URL') ?? DEFAULT_API_URL;\n}\n","/**\n * MCP tool response helpers.\n *\n * @module\n */\n\nimport type { ToolResult } from '@chatsdet/browser-core';\n\nexport function toolText(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nexport function toolJson(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n\n/**\n * Convert a BrowserToolExecutor result to MCP SDK content blocks.\n */\nexport function formatMCPContent(result: ToolResult) {\n if (typeof result === 'string') {\n return { content: [{ type: 'text' as const, text: result }] };\n }\n\n // MCPContentResult with text and optional images\n const content: Array<{ type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string }> = [];\n\n if (result.text) {\n content.push({ type: 'text', text: result.text });\n }\n\n for (const img of result.images ?? []) {\n content.push({ type: 'image', data: img.data, mimeType: img.mimeType });\n }\n\n return { content };\n}\n","/**\n * Cloud-relay session tools for the MCP server.\n *\n * These tools proxy browser control through the cloud API via WebSocket.\n *\n * @module\n */\n\nimport { readStoredToken } from '../auth';\nimport { readBrandEnv } from '../brand.js';\nimport { LocalBrowserHost } from '../local-browser/host';\nimport type { LocalBrowserMode } from '../local-browser/protocol';\nimport { toolJson } from './tool-helpers';\n\ntype LocalBrowserStartInput = {\n mode?: LocalBrowserMode;\n cdpUrl?: string;\n headless?: boolean;\n storageStatePath?: string;\n instructions?: string;\n};\n\ntype LocalBrowserStopInput = {\n sessionId: string;\n};\n\ntype LocalBrowserStatusInput = {\n sessionId: string;\n};\n\ninterface BrowserSession {\n sessionId: string;\n host: LocalBrowserHost;\n startedAt: number;\n mode: LocalBrowserMode;\n}\n\n// Global browser sessions managed by MCP\nconst browserSessions = new Map<string, BrowserSession>();\n\nconst DEFAULT_API_URL = 'https://api.trycanary.ai';\n\nfunction resolveApiUrl(input?: string): string {\n return input ?? readBrandEnv('CANARY_API_URL') ?? DEFAULT_API_URL;\n}\n\nasync function resolveToken(): Promise<string> {\n const token = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken());\n if (!token) {\n throw new Error('Missing token. Run `canary login` first or set CANARY_API_TOKEN.');\n }\n return token;\n}\n\nexport function getSessionToolDefinitions() {\n return [\n {\n name: 'local_browser_start',\n description:\n 'Start a local browser session that connects to the cloud agent. The cloud agent can then control this browser to test local applications. Returns sessionId for tracking.',\n inputSchema: {\n type: 'object',\n properties: {\n mode: {\n type: 'string',\n enum: ['playwright', 'cdp'],\n description:\n \"Browser mode: 'playwright' for fresh browser, 'cdp' to connect to existing Chrome\",\n },\n cdpUrl: {\n type: 'string',\n description: \"CDP endpoint URL when mode is 'cdp' (e.g. http://localhost:9222)\",\n },\n headless: {\n type: 'boolean',\n description: 'Run browser headless (default: true for playwright mode)',\n },\n storageStatePath: {\n type: 'string',\n description: 'Path to Playwright storage state JSON for pre-authenticated sessions',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n },\n },\n },\n {\n name: 'local_browser_status',\n description: 'Check the status of a local browser session.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_stop',\n description: 'Stop a local browser session and close the browser.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_list',\n description: 'List all active local browser sessions.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'local_browser_run',\n description:\n 'Start a test run on an active local browser session. The cloud agent will control the local browser according to the instructions.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID from local_browser_start',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n startUrl: {\n type: 'string',\n description: 'Optional URL to navigate to before starting',\n },\n },\n required: ['sessionId', 'instructions'],\n },\n },\n ];\n}\n\nexport async function handleSessionTool(tool: string, args: Record<string, unknown>) {\n const token = await resolveToken();\n\n if (tool === 'local_browser_start') {\n const input = args as unknown as LocalBrowserStartInput;\n const apiUrl = resolveApiUrl();\n const mode = input.mode ?? 'playwright';\n\n const sessionResponse = await fetch(`${apiUrl}/local-browser/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n browserMode: mode,\n instructions: input.instructions ?? null,\n }),\n });\n\n if (!sessionResponse.ok) {\n const text = await sessionResponse.text();\n return toolJson({ ok: false, error: `Failed to create session: ${text}` });\n }\n\n const session = (await sessionResponse.json()) as {\n ok: boolean;\n sessionId: string;\n wsToken: string;\n expiresAt: string;\n };\n\n const host = new LocalBrowserHost({\n apiUrl,\n wsToken: session.wsToken,\n sessionId: session.sessionId,\n browserMode: mode,\n cdpUrl: input.cdpUrl,\n headless: input.headless ?? true,\n storageStatePath: input.storageStatePath,\n onLog: (level, message) => {\n if (level === 'error') {\n console.error(`[LocalBrowser] ${message}`);\n }\n },\n });\n\n host.start().catch((err) => {\n console.error('Failed to start local browser:', err);\n browserSessions.delete(session.sessionId);\n });\n\n browserSessions.set(session.sessionId, {\n sessionId: session.sessionId,\n host,\n startedAt: Date.now(),\n mode,\n });\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode,\n expiresAt: session.expiresAt,\n note: 'Browser session started. The cloud agent can now control this browser. Use local_browser_stop to end the session.',\n });\n }\n\n if (tool === 'local_browser_status') {\n const input = args as unknown as LocalBrowserStatusInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode: session.mode,\n startedAt: new Date(session.startedAt).toISOString(),\n uptimeMs: Date.now() - session.startedAt,\n });\n }\n\n if (tool === 'local_browser_stop') {\n const input = args as unknown as LocalBrowserStopInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n await session.host.stop();\n browserSessions.delete(input.sessionId);\n\n return toolJson({\n ok: true,\n sessionId: input.sessionId,\n note: 'Browser session stopped and browser closed.',\n });\n }\n\n if (tool === 'local_browser_list') {\n const sessions = Array.from(browserSessions.values()).map((s) => ({\n sessionId: s.sessionId,\n mode: s.mode,\n startedAt: new Date(s.startedAt).toISOString(),\n uptimeMs: Date.now() - s.startedAt,\n }));\n\n return toolJson({\n ok: true,\n count: sessions.length,\n sessions,\n });\n }\n\n if (tool === 'local_browser_run') {\n const input = args as unknown as {\n sessionId: string;\n instructions: string;\n startUrl?: string;\n };\n const apiUrl = resolveApiUrl();\n\n const session = browserSessions.get(input.sessionId);\n if (!session) {\n return toolJson({\n ok: false,\n error: 'Session not found locally. Make sure you started it with local_browser_start.',\n sessionId: input.sessionId,\n });\n }\n\n const response = await fetch(`${apiUrl}/local-browser/sessions/${input.sessionId}/run`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n instructions: input.instructions,\n startUrl: input.startUrl ?? null,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n return toolJson({ ok: false, error: `Failed to start run: ${text}` });\n }\n\n const result = (await response.json()) as { ok: boolean; jobId: string; sessionId: string };\n\n return toolJson({\n ok: true,\n jobId: result.jobId,\n sessionId: result.sessionId,\n note: 'Test run started. The cloud agent is now controlling your local browser. You can watch the browser to see the test in action.',\n });\n }\n\n return null; // Not handled\n}\n","/**\n * Browser MCP tool registration — daemon adapter.\n *\n * Thin layer that maps MCP tool calls to the session daemon,\n * ensuring the CLI gets the SAME semantic diff, snapshot formatting,\n * click validation, and recovery notices as the cloud agent.\n *\n * The daemon owns all browser sessions. MCP is just a protocol adapter.\n *\n * @module\n */\n\nimport { getBrowserToolDefinitionsWithLifecycle } from '@chatsdet/browser-core';\nimport {\n createSession,\n deleteSession,\n deleteAllSessions,\n callTool,\n resolveTargetSession,\n} from '../session/daemon-client.js';\nimport { formatMCPContent, toolJson, toolText } from './tool-helpers';\nimport { USER_PAUSED_ERROR } from '../session/types.js';\nimport type { ToolResult } from '@chatsdet/browser-core';\n\n/** Track the active session ID within this MCP server instance */\nlet activeSessionId: string | null = null;\n\n/**\n * Get tool definitions for browser MCP tools (including lifecycle).\n */\nexport function getBrowserMCPToolDefinitions() {\n return getBrowserToolDefinitionsWithLifecycle();\n}\n\n/**\n * Handle a browser tool call.\n * Returns null if the tool name is not a browser tool.\n */\nexport async function handleBrowserTool(name: string, args: Record<string, unknown>) {\n // Lifecycle tools\n if (name === 'browser_start') {\n try {\n const result = await createSession({\n headless: (args.headless as boolean) ?? false,\n storageStatePath: args.storageStatePath as string | undefined,\n });\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error });\n }\n\n activeSessionId = result.data!.id;\n return toolJson({\n ok: true,\n sessionId: activeSessionId,\n note: 'Browser started. You can now use browser_navigate, browser_click, and other browser tools.',\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (name === 'browser_stop') {\n try {\n if (activeSessionId) {\n await deleteSession(activeSessionId);\n activeSessionId = null;\n } else {\n // Stop all sessions if no specific one tracked\n await deleteAllSessions();\n }\n return toolJson({ ok: true, note: 'Browser stopped and cleaned up.' });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n // All other browser_* tools require an active session\n if (!name.startsWith('browser_')) return null;\n\n try {\n // Resolve target session: prefer tracked MCP session, then auto-resolve\n let sessionId = activeSessionId;\n if (!sessionId) {\n try {\n const target = await resolveTargetSession();\n sessionId = target.id;\n activeSessionId = sessionId;\n } catch {\n return toolJson({\n ok: false,\n error: 'No active browser session. Start one with browser_start first.',\n });\n }\n }\n\n // Strip 'browser_' prefix for the daemon tool name\n const toolName = name.replace(/^browser_/, '');\n const result = await callTool(sessionId, toolName, args);\n\n if (!result.ok) {\n // If session not found, clear tracking and report error\n if (result.error?.includes('not found')) {\n activeSessionId = null;\n }\n // User has taken control via the in-browser badge — return as\n // informational text rather than an error so Claude waits instead of retrying\n if (result.errorCode === USER_PAUSED_ERROR) {\n return toolText(result.error ?? 'User has taken control of the browser.');\n }\n return toolJson({ ok: false, error: result.error, tool: name });\n }\n\n // Convert daemon response back to ToolResult format for MCP formatting\n const toolResult: ToolResult = result.images?.length\n ? { text: result.text ?? '', images: result.images }\n : (result.text ?? '');\n\n return formatMCPContent(toolResult);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return toolJson({ ok: false, error: message, tool: name });\n }\n}\n","/**\n * MCP tool for device code OAuth login.\n *\n * Allows AI coding tools to trigger authentication without\n * requiring the user to run `canary login` in a separate terminal.\n *\n * @module\n */\n\nimport { ENV_URLS, envToProfile, resolveAppUrl, saveAuth } from '../auth';\nimport { openUrl, fetchOrgs, switchOrg } from '../login';\nimport type { StartResponse, PollResponse } from '../login';\nimport { resolveApiUrl } from './api-url';\nimport { toolJson } from './tool-helpers';\n\nexport function getLoginToolDefinitions() {\n return [\n {\n name: 'canary_login',\n description:\n 'Authenticate with Canary using the device code OAuth flow. Opens a browser window for the user to approve. ' +\n 'May take 30-120 seconds while waiting for the user to complete login. ' +\n 'Returns the verification URL and user code in case the browser does not open automatically.',\n inputSchema: {\n type: 'object',\n properties: {\n env: {\n type: 'string',\n enum: ['prod', 'dev', 'local'],\n description: 'Target environment (default: prod)',\n },\n org: {\n type: 'string',\n description:\n 'Organization name or ID to select if the user belongs to multiple orgs. If omitted, uses the default org.',\n },\n },\n },\n },\n ];\n}\n\nexport async function handleLoginTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool !== 'canary_login') return null;\n\n try {\n const env = args.env as string | undefined;\n const orgFlag = args.org as string | undefined;\n const envUrls = env ? ENV_URLS[env] : undefined;\n\n if (env && !envUrls) {\n return toolJson({ ok: false, error: `Unknown environment: ${env}. Valid: prod, dev, local` });\n }\n\n const apiUrl = envUrls?.api ?? resolveApiUrl();\n const appUrl = envUrls?.app ?? resolveAppUrl(apiUrl);\n\n // Step 1: Start device code flow\n const startRes = await fetch(`${apiUrl}/cli-login/start`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ appUrl }),\n });\n\n const startJson = (await startRes.json()) as StartResponse;\n if (!startRes.ok || !startJson.ok || !startJson.deviceCode || !startJson.userCode) {\n return toolJson({\n ok: false,\n error: `Login start failed: ${startJson.error ?? startRes.statusText}`,\n });\n }\n\n // Step 2: Open browser (non-fatal if it fails)\n if (startJson.verificationUrl) {\n try {\n openUrl(startJson.verificationUrl);\n } catch {\n // Browser open failed — user will need to open the URL manually\n }\n }\n\n // Step 3: Poll until approved/rejected/expired\n const intervalMs = (startJson.intervalSeconds ?? 3) * 1000;\n const expiresAt = startJson.expiresAt ? new Date(startJson.expiresAt).getTime() : null;\n\n let token: string | undefined;\n let initialOrgId: string | undefined;\n\n while (true) {\n if (expiresAt && Date.now() > expiresAt) {\n return toolJson({\n ok: false,\n error: 'Login code expired. Please try again.',\n userCode: startJson.userCode,\n verificationUrl: startJson.verificationUrl,\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n\n const pollRes = await fetch(`${apiUrl}/cli-login/poll`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ deviceCode: startJson.deviceCode }),\n });\n\n const pollJson = (await pollRes.json()) as PollResponse;\n if (!pollRes.ok || !pollJson.ok) {\n return toolJson({\n ok: false,\n error: `Login poll failed: ${pollJson.error ?? pollRes.statusText}`,\n });\n }\n\n if (pollJson.status === 'approved' && pollJson.accessToken) {\n token = pollJson.accessToken;\n initialOrgId = pollJson.orgId;\n break;\n }\n\n if (pollJson.status === 'rejected') {\n return toolJson({ ok: false, error: 'Login rejected by user.' });\n }\n\n if (pollJson.status === 'expired') {\n return toolJson({ ok: false, error: 'Login expired. Please try again.' });\n }\n }\n\n // Step 4: Handle org selection\n const orgsData = await fetchOrgs(apiUrl, token);\n const orgs = orgsData?.organizations ?? [];\n\n let finalToken = token;\n let finalOrgId = initialOrgId;\n let finalOrgName: string | undefined;\n\n if (orgs.length <= 1) {\n finalOrgName = orgs[0]?.name;\n } else if (orgFlag) {\n // Match by name (case-insensitive) or ID\n const selectedOrg = orgs.find(\n (o) => o.name.toLowerCase() === orgFlag.toLowerCase() || o.id === orgFlag\n );\n if (!selectedOrg) {\n // Save the default token so they're at least logged in\n const profileName = env ? envToProfile(env) : undefined;\n await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: orgs.find((o) => o.id === initialOrgId)?.name }, profileName);\n\n return toolJson({\n ok: false,\n error: `Organization \"${orgFlag}\" not found.`,\n loggedIn: true,\n currentOrg: orgs.find((o) => o.id === initialOrgId)?.name,\n availableOrgs: orgs.map((o) => ({ id: o.id, name: o.name, role: o.role })),\n });\n }\n\n if (selectedOrg.id !== initialOrgId) {\n const switchRes = await switchOrg(apiUrl, token, selectedOrg.id);\n if (!switchRes.ok || !switchRes.accessToken) {\n return toolJson({\n ok: false,\n error: `Failed to switch organization: ${switchRes.error ?? 'Unknown error'}`,\n });\n }\n finalToken = switchRes.accessToken;\n finalOrgId = switchRes.orgId;\n finalOrgName = switchRes.orgName;\n } else {\n finalOrgName = selectedOrg.name;\n }\n } else {\n // Multiple orgs, no flag — use default\n const defaultOrg = orgs.find((o) => o.id === initialOrgId);\n finalOrgName = defaultOrg?.name;\n }\n\n // Step 5: Save auth\n const profileName = env ? envToProfile(env) : undefined;\n await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: finalOrgName }, profileName);\n\n return toolJson({\n ok: true,\n message: 'Login successful. Token saved.',\n orgName: finalOrgName,\n orgId: finalOrgId,\n ...(orgs.length > 1\n ? { availableOrgs: orgs.map((o) => ({ id: o.id, name: o.name, role: o.role })) }\n : {}),\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","/**\n * MCP tool for upgrading the Canary CLI to the latest version.\n *\n * Adapts the `canary upgrade` command for MCP context where\n * stdio is the transport and process.exit() must be avoided.\n *\n * @module\n */\n\nimport fs from 'node:fs';\nimport { spawnSync } from 'node:child_process';\nimport process from 'node:process';\nimport { packageName } from '../brand.js';\nimport { clearUpdateCache } from '../update-check.js';\nimport { toolJson } from './tool-helpers';\n\ntype PackageManager = 'bun' | 'pnpm' | 'npm';\n\nfunction detectPackageManager(): PackageManager {\n try {\n const binPath = fs.realpathSync(process.argv[1]).replace(/\\\\/g, '/');\n if (binPath.includes('.bun/') || binPath.includes('/bun/')) return 'bun';\n if (binPath.includes('.pnpm/') || binPath.includes('/pnpm/')) return 'pnpm';\n } catch {\n // realpathSync can fail if symlink is broken\n }\n return 'npm';\n}\n\nconst UPGRADE_COMMANDS: Record<PackageManager, string[]> = {\n bun: ['bun', 'add', '-g', `${packageName}@latest`],\n pnpm: ['pnpm', 'add', '-g', `${packageName}@latest`],\n npm: ['npm', 'install', '-g', `${packageName}@latest`],\n};\n\nexport function getUpgradeToolDefinitions() {\n return [\n {\n name: 'canary_upgrade',\n description:\n 'Upgrade the Canary CLI to the latest version. ' +\n 'Detects the package manager (npm, bun, pnpm) and runs the appropriate global install command.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n ];\n}\n\nexport async function handleUpgradeTool(\n tool: string,\n _args: Record<string, unknown>\n) {\n if (tool !== 'canary_upgrade') return null;\n\n try {\n const pm = detectPackageManager();\n const cmd = UPGRADE_COMMANDS[pm];\n\n const result = spawnSync(cmd[0], cmd.slice(1), {\n stdio: ['pipe', 'pipe', 'pipe'],\n cwd: process.cwd(),\n timeout: 120_000,\n shell: process.platform === 'win32',\n windowsHide: true,\n });\n\n if (result.error) {\n return toolJson({\n ok: false,\n error: `Failed to run ${pm}: ${result.error.message}`,\n });\n }\n\n const stdout = result.stdout?.toString().trim() ?? '';\n const stderr = result.stderr?.toString().trim() ?? '';\n\n if (result.status !== 0) {\n return toolJson({\n ok: false,\n error: `Upgrade failed (exit code ${result.status}).`,\n output: stderr || stdout,\n });\n }\n\n await clearUpdateCache();\n\n return toolJson({\n ok: true,\n message: `Successfully upgraded ${packageName} to the latest version.`,\n packageManager: pm,\n output: stdout || undefined,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","/**\n * MCP server instructions for Claude Cowork.\n *\n * These instructions are returned in the InitializeResult and injected\n * into the agent's system prompt before any tools or user messages.\n * They teach Cowork how to use the canary toolset effectively.\n *\n * @module\n */\n\nexport const CANARY_MCP_INSTRUCTIONS = `\n# Canary — AI-Powered QA Platform\n\nYou have access to the Canary MCP tools for testing web applications, managing test workflows, and investigating issues. This guide teaches you how to use them effectively.\n\n## Authentication & Defaults\n\n- **Always use env: \"prod\"** when calling canary_login unless the user explicitly asks for dev or local.\n- After login, if multiple organizations are available, ask the user which one to use. Pass the org name via the \\`org\\` parameter.\n- To switch orgs later, call canary_login again with the \\`org\\` parameter — no need to re-authenticate.\n\n## Browser Sessions — Exploring Apps\n\nUse browser tools to interactively explore and test web applications. The workflow is:\n\n### Starting a Session\n\n1. **List credentials first:** Call \\`canary_credential_list\\` to see available credentials with their property names and base URLs.\n2. **Pick the right credential:**\n - Prefer the **default credential** (\\`isDefault: true\\`)\n - **Never** use a credential with \"local\" or \"manual\" in the name — these are for local development and won't work in deployed environments\n - If multiple non-local credentials exist and you're unsure, ask the user\n3. **Start the browser with a credential:** Use \\`browser_start\\` to launch a headed browser, then load the credential's storage state. Or use the session tools (\\`local_browser_start\\`) for cloud-relay sessions.\n\n### The Core Interaction Loop\n\n**snapshot → read → act → snapshot → verify**\n\nThis is the fundamental pattern. Never skip the verification snapshot.\n\n1. **Snapshot the page** with \\`browser_snapshot\\` to see what's on screen. The accessibility tree shows elements with refs like \\`[ref=e15]\\`.\n2. **Find elements efficiently** using the \\`search\\` parameter: \\`browser_snapshot\\` with \\`search: \"Submit\"\\` or \\`search: \"Email|Password\"\\` (OR-matched, case-insensitive).\n3. **Interact using refs** from the snapshot — click, type, fill, select. Always use refs, not coordinates. Fall back to coordinate-based clicking only when refs fail (overlays, canvas elements).\n4. **Snapshot again** after every action to verify it succeeded. Never assume an action worked.\n5. **Check for errors** after form submissions or navigation — look at the page content for error messages, and use console/network tools if available.\n\n### Tips\n\n- Use \\`search\\` to locate elements quickly rather than scanning the full accessibility tree.\n- Use \\`browser_snapshot\\` with \\`mode: \"screenshot\"\\` for visual verification when you need to see the actual rendering.\n- Wait for async operations (API calls, animations) before snapshotting — look for loading indicators.\n- Group related observations: take one snapshot and read the full tree rather than searching for every element individually.\n\n## Building Tests — Workflow Authoring\n\nAfter exploring an app via browser session, you can persist what you discovered as a reusable test workflow. The flow is: **explore → author → create**.\n\n### Step 1: Gather Credential Info\n\nCall \\`canary_credential_list\\` to get the credential UUID. You'll need it for the login node.\n- Always use \\`credentialId\\` (UUID) — never just the credential name\n- Set both \\`credentialId\\` and \\`credentialName\\` in the login node\n\n### Step 2: Design the Workflow\n\nA workflow is a directed graph of **nodes** connected by **edges**.\n\n#### Node Types\n\n| Type | Purpose | Required configJson |\n|------|---------|-------------------|\n| \\`login\\` | Authenticate with a credential | \\`credentialId\\`, \\`credentialName\\` |\n| \\`navigate\\` | Go to a URL | \\`pageUrl\\`, \\`pageTitle\\` |\n| \\`action\\` | Interact with elements | \\`customActionTitle\\`, \\`playbookSteps\\`, optionally \\`inlineAssertions\\` |\n| \\`assertion\\` | Standalone page verification | \\`condition\\` text |\n| \\`end\\` | Terminal node | (none) |\n\n#### Action Node Guidelines\n\n- Every action node **must** have a \\`customActionTitle\\` — a short (3-8 word) human-readable title describing the step (e.g., \"Create a new invoice\", \"Fill registration form\")\n- **Group related actions** into a single action node (one node per logical step, not per click)\n- **Prefer inline assertions** on action nodes over separate assertion nodes. Add \\`inlineAssertions\\` to verify outcomes right after the action. **Do not author an \\`id\\` field** — the server stamps a UUID on persist:\n \\`\\`\\`json\n {\n \"inlineAssertions\": [\n {\n \"condition\": \"Success message 'Invoice created' is visible\",\n \"severity\": \"fail\"\n }\n ]\n }\n \\`\\`\\`\n- Use separate \\`assertion\\` nodes only for standalone page-level verifications (e.g., initial page state before any action)\n\n#### Playbook Steps (inside action nodes)\n\nPlaybook steps describe what to do within an action node. Each step has:\n- \\`order\\`: sequence number (1, 2, 3...)\n- \\`action\\`: what to do — \\`click\\`, \\`fill\\`, \\`fill_form\\`, \\`select\\`, \\`navigate\\`, \\`wait\\`, \\`scroll\\`, \\`hover\\`, \\`upload\\`, \\`verify\\`, \\`press_key\\`, \\`drag\\`, \\`resize\\`, \\`capture\\`, \\`extract_table\\`, \\`python_execute\\`, \\`verify_download\\`, \\`verify_download_content\\`, \\`screenshot\\`, \\`agent_loop\\`\n- \\`target\\`: **semantic description** from the accessibility tree — button text, field labels, placeholder text. Describe as a human would: \"Submit button\", \"Email input field\", \"Status dropdown\". **Never use refs, CSS selectors, or XPaths.**\n- \\`params\\`: for \\`fill\\` actions, include \\`{ \"value\": \"...\" }\\`\n\nEach playbook step maps to at most one recorded browser tool call. If the user intent took multiple clicks, fills, key presses, or assertions, write multiple playbook steps instead of bundling them. Do not use \\`other\\`; if no concrete browser-tool-backed action fits, omit that diagnostic observation from \\`playbookSteps\\`. Use \\`click\\` for switches, checkboxes, and click-to-focus behavior. Use \\`press_key\\` with \\`{ \"key\": \"Escape\" }\\` or an explicit \\`click\\` to close popovers and panels; there is no \\`dismiss\\`, \\`toggle\\`, \\`focus\\`, or \\`handle_native_dialog\\` action.\n\n### Macros — Always Prefer Over Hardcoded Data\n\nMacros generate fresh values each run, preventing flaky tests from stale or colliding data. **Never hardcode emails, names, phone numbers, or dates when a macro exists.**\n\n| Macro | Output | Example |\n|-------|--------|---------|\n| \\`$EMAIL()\\` | Unique test email | \\`test-xk9mq2@example-test.com\\` |\n| \\`$FIRST_NAME()\\` | Random first name | \\`Jordan\\` |\n| \\`$LAST_NAME()\\` | Random last name | \\`Chen\\` |\n| \\`$PHONE()\\` | US phone (555 prefix) | \\`+1-555-382-7491\\` |\n| \\`$UUID()\\` | Random UUID v4 | \\`a1b2c3d4-...\\` |\n| \\`$RANDOM_INT(min, max)\\` | Random integer | \\`$RANDOM_INT(100,999)\\` → \\`427\\` |\n| \\`$RANDOM_STRING(length)\\` | Alphanumeric string | \\`$RANDOM_STRING(8)\\` → \\`xK9mQ3bR\\` |\n| \\`$TODAY()\\` | Current date (YYYY-MM-DD) | \\`2026-04-06\\` |\n| \\`$DATE(days)\\` | Date offset from today | \\`$DATE(-7)\\` → last week |\n| \\`$NOW()\\` | ISO 8601 timestamp | \\`2026-04-06T14:30:00.000Z\\` |\n| \\`$TIMESTAMP()\\` | Unix milliseconds | \\`1771520400000\\` |\n| \\`$SEQUENCE(\"name\")\\` | Auto-incrementing per run | \\`1\\`, \\`2\\`, \\`3\\`... |\n\nMacros combine inline: \\`\"QA Test $FIRST_NAME() $LAST_NAME()\"\\`, \\`\"order-$RANDOM_STRING(6)\"\\`\n\n**Prefix test data with \"QA Test\"** for identifiability.\n\n### Step 3: Create the Workflow\n\nUse \\`canary_workflow_sync\\` for existing workflows or construct the full workflow JSON and create via the API. Then verify with \\`canary_workflow_get\\`.\n\n### Example Workflow JSON\n\n\\`\\`\\`json\n{\n \"name\": \"Verify user can create an invoice\",\n \"description\": \"Tests the invoice creation flow end-to-end\",\n \"nodes\": [\n {\n \"nodeType\": \"login\",\n \"configJson\": {\n \"credentialId\": \"4f6db838-16be-49e8-8887-8d0be1c83a87\",\n \"credentialName\": \"QA User\"\n }\n },\n {\n \"nodeType\": \"navigate\",\n \"configJson\": { \"pageUrl\": \"/invoices\", \"pageTitle\": \"Invoices\" }\n },\n {\n \"nodeType\": \"action\",\n \"configJson\": {\n \"customActionTitle\": \"Create a new invoice\",\n \"actionDescription\": \"Fill out the new invoice form and save\",\n \"playbookSteps\": [\n { \"order\": 1, \"action\": \"click\", \"target\": \"New Invoice button\" },\n { \"order\": 2, \"action\": \"fill\", \"target\": \"Client name field\", \"params\": { \"value\": \"QA Test $FIRST_NAME()\" } },\n { \"order\": 3, \"action\": \"fill\", \"target\": \"Amount field\", \"params\": { \"value\": \"$RANDOM_INT(100,999)\" } },\n { \"order\": 4, \"action\": \"click\", \"target\": \"Save button\" }\n ],\n \"inlineAssertions\": [\n {\n \"condition\": \"Success message 'Invoice created' is visible and the new invoice appears in the list\",\n \"severity\": \"fail\"\n }\n ]\n }\n }\n ]\n}\n\\`\\`\\`\n\n## Managing Workflows\n\n- **canary_workflow_list** — Browse existing tests. Filter by \\`status\\` (draft = editable, published = active in regression runs), \\`flowType\\` (standard/setup/seed/teardown), or \\`search\\` by name. Reliability is tracked separately by the workflow's \\`health\\`.\n- **canary_workflow_get** — Inspect a test's full definition: nodes, edges, playbook steps, assertions.\n- **canary_workflow_patch** — Update name, description, status, or flow type. Only provided fields change.\n- **canary_workflow_run** — Trigger execution. Returns a \\`runId\\` — use it to track progress.\n- **canary_workflow_sync** — Atomically replace all nodes and edges. Automatically snapshots current state first so changes are reversible. Read the current DAG with \\`canary_workflow_get\\` before syncing.\n\n## Monitoring Runs & Debugging Failures\n\nAfter triggering a workflow run, monitor and debug with:\n\n- **canary_workflow_runs_list** — Recent runs for a workflow with status and duration.\n- **canary_workflow_runs_get** — Detailed run view: step-by-step status, duration, errors. Also works for in-progress runs to check status.\n- **canary_workflow_runs_diagnostics** — AI-generated failure analysis. Returns root cause and recommendations. Falls back to raw console logs and network requests if no AI analysis is available.\n\n### Regression Suite\n\n- **canary_test_suite_run** — Trigger a regression suite execution. Returns suiteId for tracking. Use canary_test_suite_list or canary_test_suite_get to check results.\n- **canary_test_suite_list** — Recent regression suite executions with pass/fail counts.\n- **canary_test_suite_get** — Individual test results within a suite execution.\n- **canary_test_suite_diagnostics** — Failure diagnostics for a specific test in a suite run.\n- **canary_test_suite_steps** — Step-by-step breakdown of a test run within a suite.\n\n## Investigating Issues\n\nIssues are bugs discovered by Canary during test runs.\n\n- **canary_issues_list** — Search and filter issues by severity (\\`low\\`/\\`medium\\`/\\`high\\`), status (\\`open\\`/\\`closed\\`/\\`not_a_bug\\`), or property. Supports full-text search.\n- **canary_issues_get** — Full issue detail including console errors and network failures from the latest occurrence. Use this to understand what went wrong.\n\n## API Sequences (API-only workflows)\n\nFor APIs that need deterministic, browser-free smoke testing — composed of ordered HTTP calls that chain outputs into inputs.\n\n- **Create** with the same command as any workflow, with \\`--api-only\\`:\n \\`canary workflow create --api-only --name \"<n>\" --sequence-from-file seq.json\\`\n Returns \\`{ workflowId, apiSequenceId, nodeId }\\`. No \\`--property\\` — api-sequences are org-scoped.\n- **Inspect runs** with the same command as any runs, with \\`--side api\\` (or \\`--side all\\` for both):\n \\`canary workflow runs list <wf> --side api\\`\n \\`canary workflow runs get <wf> <runId>\\`\n- **Edit the sequence itself** via \\`canary workflow api-sequence <verb>\\`:\n - \\`get <wf>\\` — dump config + steps\n - \\`update <wf> --from-file seq.json\\` — replace config\n - \\`execute <wf>\\` — run it\n - \\`generate <wf> [--prompt \"...\"]\\` — AI-draft a config, then refine with \\`update\\`\n- **Discover endpoints** before composing steps:\n \\`canary api-catalog sources list\\`\n \\`canary api-catalog endpoints list --search <q>\\`\n \\`canary api-catalog endpoints create --from-file ep.json\\` (add a one-off)\n- **Read the reference first** for the config/step shape and template syntax:\n \\`canary workflow guide api-sequences\\`\n\nTemplates in step fields use \\`{{stepId.response.path}}\\` to reference prior-step outputs and \\`$MACRO()\\` for dynamic test data (same macros as browser workflows).\n\n## Common Workflows\n\n### \"Let's explore the app\"\n1. \\`canary_login\\` (env: prod) → switch to the right org\n2. \\`canary_credential_list\\` → find the right credential\n3. \\`browser_start\\` → launch browser\n4. Load credential and navigate to the app\n5. Snapshot, interact, explore\n\n### \"Write a test for this feature\"\n1. Explore the feature via browser (above workflow)\n2. \\`canary_credential_list\\` → get credentialId\n3. Construct workflow JSON with nodes, edges, playbook steps, macros\n4. Create or sync the workflow\n5. \\`canary_workflow_run\\` → execute it\n6. \\`canary_workflow_runs_get\\` → verify it passes\n\n### \"Why did this test fail?\"\n1. \\`canary_workflow_runs_list\\` → find the failed run\n2. \\`canary_workflow_runs_get\\` → see which step failed\n3. \\`canary_workflow_runs_diagnostics\\` → AI analysis of the failure\n4. If needed, open a browser session to reproduce and investigate\n\n### \"What issues have been found?\"\n1. \\`canary_issues_list\\` → browse open issues\n2. \\`canary_issues_get\\` → deep dive with console/network errors\n`.trim();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC,SAAS,uBAAuB,8BAA8B;;;ACd9D,SAAS,yBAAyB;AAYlC,IAAM,UAAU,IAAI,kBAA2B;AAExC,SAAS,YAAe,KAAc,IAAkC;AAC7E,SAAO,QAAQ,IAAI,KAAK,EAAE;AAC5B;AAEO,SAAS,iBAAsC;AACpD,SAAO,QAAQ,SAAS;AAC1B;;;AClBA,IAAM,qBAAqB;AAU3B,eAAsB,cACpB,QACA,MACA,MACY;AACZ,QAAM,MAAM,eAAe;AAC3B,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,4DAA4D;AAAA,EAC9E;AAEA,QAAM,MAAM,GAAG,IAAI,MAAM,GAAG,IAAI;AAChC,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA,SAAS;AAAA,QACP,eAAe,UAAU,IAAI,QAAQ;AAAA,QACrC,gBAAgB;AAAA,MAClB;AAAA,MACA,QAAQ,YAAY,QAAQ,kBAAkB;AAAA,MAC9C,GAAI,OAAO,EAAE,MAAM,KAAK,UAAU,IAAI,EAAE,IAAI,CAAC;AAAA,IAC/C,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,QAAI,eAAe,SAAS,IAAI,SAAS,gBAAgB;AACvD,YAAM,IAAI,MAAM,iDAAiD,kBAAkB,IAAI;AAAA,IACzF;AACA,UAAM,IAAI,MAAM,aAAa,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EACjF;AAEA,MAAI,CAAC,IAAI,IAAI;AACX,QAAI,IAAI,WAAW,KAAK;AACtB,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AACA,UAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,UAAM,IAAI,MAAM,SAAS,IAAI,MAAM,KAAK,QAAQ,IAAI,UAAU,EAAE;AAAA,EAClE;AAEA,SAAQ,MAAM,IAAI,KAAK;AACzB;;;AClDO,SAAS,SAAS,MAAc;AACrC,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,KAAK,CAAC,EAAE;AACtD;AAEO,SAAS,SAAS,MAAe;AACtC,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,EAAE,CAAC,EAAE;AACrF;;;ACQO,SAAS,cAAc,QAA+B;AAC3D,SAAO;AAAA,IACL,OAAO;AACL,aAAO,OAAO,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;AAAA,IAC9C;AAAA,IAEA,MAAM,KAAK,MAAM,MAAM,KAAK;AAC1B,aAAO,YAAY,KAAK,YAAY;AAClC,mBAAW,SAAS,QAAQ;AAC1B,gBAAM,SAAS,MAAM,MAAM,OAAO,MAAM,IAAI;AAC5C,cAAI,OAAQ,QAAO;AAAA,QACrB;AACA,eAAO,SAAS,iBAAiB,IAAI,EAAE;AAAA,MACzC,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ACnBO,SAAS,6BAA6B;AAC3C,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,MAAM,CAAC,YAAY,SAAS,QAAQ,UAAU;AAAA,YAC9C,aAAa;AAAA,UACf;AAAA,UACA,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM,CAAC,SAAS,UAAU;AAAA,YAC1B,aACE;AAAA,UACJ;AAAA,UACA,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,YAAY;AAAA,MACzB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,aAAa;AAAA,YACX,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM,CAAC,SAAS,UAAU;AAAA,YAC1B,aACE;AAAA,UACJ;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,MAAM,CAAC,YAAY,SAAS,QAAQ,UAAU;AAAA,YAC9C,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,YAAY;AAAA,MACzB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,YAAY;AAAA,MACzB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,OAAO;AAAA,YACL,MAAM;AAAA,YACN,aAAa;AAAA,YACb,OAAO,EAAE,MAAM,SAAS;AAAA,UAC1B;AAAA,UACA,OAAO;AAAA,YACL,MAAM;AAAA,YACN,aAAa;AAAA,YACb,OAAO,EAAE,MAAM,SAAS;AAAA,UAC1B;AAAA,UACA,gBAAgB;AAAA,YACd,MAAM;AAAA,YACN,aAAa;AAAA,YACb,SAAS;AAAA,UACX;AAAA,UACA,SAAS;AAAA,YACP,MAAM;AAAA,YACN,aAAa;AAAA,YACb,SAAS;AAAA,UACX;AAAA,UACA,eAAe;AAAA,YACb,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,qBAAqB;AAAA,YACnB,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,cAAc,SAAS,OAAO;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,mBACpB,MACA,MACA;AACA,MAAI,SAAS,wBAAwB;AACnC,QAAI;AACF,YAAM,SAAS,IAAI,gBAAgB;AACnC,UAAI,KAAK,OAAQ,QAAO,IAAI,UAAU,OAAO,KAAK,MAAM,CAAC;AACzD,UAAI,KAAK,SAAU,QAAO,IAAI,YAAY,OAAO,KAAK,QAAQ,CAAC;AAC/D,UAAI,KAAK,OAAQ,QAAO,IAAI,UAAU,OAAO,KAAK,MAAM,CAAC;AACzD,UAAI,KAAK,KAAM,QAAO,IAAI,QAAQ,OAAO,KAAK,IAAI,CAAC;AACnD,UAAI,KAAK,SAAU,QAAO,IAAI,YAAY,OAAO,KAAK,QAAQ,CAAC;AAE/D,YAAM,KAAK,OAAO,SAAS;AAC3B,YAAM,OAAO,aAAa,KAAK,IAAI,EAAE,KAAK,EAAE;AAC5C,YAAM,SAAS,MAAM,cAKlB,OAAO,IAAI;AAEd,UAAI,CAAC,OAAO,IAAI;AACd,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,SAAS,gBAAgB,CAAC;AAAA,MACvE;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,MAAM,OAAO,MAAM,YAAY,OAAO,WAAW,CAAC;AAAA,IAChF,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,uBAAuB;AAClC,QAAI;AACF,YAAM,aAAa,KAAK;AACxB,YAAM,SAAS,MAAM,cAMlB,OAAO,cAAc,UAAU,EAAE;AAEpC,UAAI,OAAO,OAAO;AAChB,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,MAAM,CAAC;AAAA,MACpD;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,UAAU,OAAO,SAAS,CAAC;AAAA,IACzD,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,yBAAyB;AACpC,QAAI;AACF,YAAM,aAAa,KAAK;AACxB,YAAM,OAAgC,CAAC;AACvC,UAAI,KAAK,KAAM,MAAK,OAAO,OAAO,KAAK,IAAI;AAC3C,UAAI,KAAK,YAAa,MAAK,cAAc,OAAO,KAAK,WAAW;AAChE,UAAI,KAAK,OAAQ,MAAK,SAAS,OAAO,KAAK,MAAM;AACjD,UAAI,KAAK,SAAU,MAAK,WAAW,OAAO,KAAK,QAAQ;AAEvD,YAAM,SAAS,MAAM,cAIlB,OAAO,cAAc,UAAU,IAAI,IAAI;AAE1C,UAAI,OAAO,OAAO;AAChB,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,MAAM,CAAC;AAAA,MACpD;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,UAAU,OAAO,SAAS,CAAC;AAAA,IACzD,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,uBAAuB;AAClC,QAAI;AACF,YAAM,aAAa,KAAK;AAExB,YAAM,SAAS,MAAM,cAKlB,QAAQ,cAAc,UAAU,UAAU;AAE7C,UAAI,OAAO,OAAO;AAChB,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,MAAM,CAAC;AAAA,MACpD;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,OAAO,OAAO,OAAO,UAAU,OAAO,SAAS,CAAC;AAAA,IAC9E,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,wBAAwB;AACnC,QAAI;AACF,YAAM,aAAa,KAAK;AACxB,YAAM,QAAQ,KAAK;AACnB,YAAM,QAAQ,KAAK;AAGnB,UAAI,KAAK,SAAS;AAChB,cAAM,QAAS,KAAK,iBAA4B,kBAAkB,MAAM,MAAM;AAC9E,cAAM,cAAe,KAAK,uBAAkC;AAE5D,cAAMA,UAAS,MAAM,cAIlB,QAAQ,cAAc,UAAU,cAAc;AAAA,UAC/C;AAAA,UACA;AAAA,UACA,cAAc,EAAE,OAAO,MAAM;AAAA,UAC7B,QAAQ;AAAA,QACV,CAAC;AAED,YAAIA,QAAO,OAAO;AAChB,iBAAO,SAAS,EAAE,IAAI,OAAO,OAAOA,QAAO,MAAM,CAAC;AAAA,QACpD;AAEA,eAAO,SAAS;AAAA,UACd,IAAI;AAAA,UACJ,YAAYA,QAAO,MAAM;AAAA,UACzB,OAAOA,QAAO,MAAM;AAAA,UACpB,QAAQA,QAAO,MAAM;AAAA,QACvB,CAAC;AAAA,MACH;AAEA,YAAM,iBAAiB,KAAK,mBAAmB;AAE/C,YAAM,SAAS,MAAM,cAIlB,OAAO,cAAc,UAAU,gBAAgB;AAAA,QAChD;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,UAAI,OAAO,OAAO;AAChB,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,MAAM,CAAC;AAAA,MACpD;AAEA,aAAO,SAAS;AAAA,QACd,IAAI;AAAA,QACJ,GAAI,OAAO,kBAAkB,EAAE,iBAAiB,OAAO,gBAAgB,IAAI,CAAC;AAAA,MAC9E,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,SAAO;AACT;;;AC3QO,SAAS,sCAAsC;AACpD,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY,EAAE,MAAM,UAAU,aAAa,gBAAgB;AAAA,UAC3D,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM,CAAC,WAAW,YAAY,YAAY,SAAS,KAAK;AAAA,YACxD,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,YAAY;AAAA,MACzB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY,EAAE,MAAM,SAAS;AAAA,UAC7B,YAAY,EAAE,MAAM,SAAS;AAAA,QAC/B;AAAA,QACA,UAAU,CAAC,cAAc,YAAY;AAAA,MACvC;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY,EAAE,MAAM,SAAS;AAAA,UAC7B,YAAY,EAAE,MAAM,SAAS;AAAA,QAC/B;AAAA,QACA,UAAU,CAAC,cAAc,YAAY;AAAA,MACvC;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY,EAAE,MAAM,SAAS;AAAA,UAC7B,YAAY,EAAE,MAAM,SAAS;AAAA,UAC7B,iBAAiB;AAAA,YACf,MAAM;AAAA,YACN,OAAO,EAAE,MAAM,SAAS;AAAA,YACxB,aACE;AAAA,UACJ;AAAA,QACF;AAAA,QACA,UAAU,CAAC,cAAc,YAAY;AAAA,MACvC;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY,EAAE,MAAM,SAAS;AAAA,UAC7B,YAAY,EAAE,MAAM,SAAS;AAAA,QAC/B;AAAA,QACA,UAAU,CAAC,cAAc,YAAY;AAAA,MACvC;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY,EAAE,MAAM,SAAS;AAAA,UAC7B,YAAY,EAAE,MAAM,SAAS;AAAA,QAC/B;AAAA,QACA,UAAU,CAAC,cAAc,YAAY;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,4BACpB,MACA,MACA;AACA,MAAI,CAAC,KAAK,WAAW,4BAA4B,EAAG,QAAO;AAE3D,MAAI;AACF,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,MAAM,cAAc,IAAI;AAAA,MACjC,KAAK;AACH,eAAO,MAAM,YAAY,IAAI;AAAA,MAC/B,KAAK;AACH,eAAO,MAAM,aAAa,IAAI;AAAA,MAChC,KAAK;AACH,eAAO,MAAM,eAAe,IAAI;AAAA,MAClC,KAAK;AACH,eAAO,MAAM,eAAe,IAAI;AAAA,MAClC,KAAK;AACH,eAAO,MAAM,eAAe,IAAI;AAAA,MAClC;AACE,eAAO;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,SAAS;AAAA,MACd,IAAI;AAAA,MACJ,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD,CAAC;AAAA,EACH;AACF;AAIA,eAAe,cAAc,MAA+B;AAC1D,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,SAAS,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;AAC/D,QAAM,QAAQ,WAAW,QAAQ,KAAK,WAAW,mBAAmB,MAAM,CAAC;AAC3E,QAAM,MAAM,MAAM,cAIf,OAAO,cAAc,UAAU,aAAa,KAAK,EAAE;AACtD,SAAO,SAAS;AAAA,IACd,IAAI,IAAI;AAAA,IACR;AAAA,IACA,OAAO,IAAI,MAAM,UAAU;AAAA,IAC3B,WAAW,IAAI,QAAQ,CAAC;AAAA,IACxB,OAAO,IAAI;AAAA,EACb,CAAC;AACH;AAEA,eAAe,YAAY,MAA+B;AACxD,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,MAAM,MAAM,cAIf,OAAO,cAAc,UAAU,cAAc,UAAU,EAAE;AAC5D,SAAO,SAAS,GAAG;AACrB;AAEA,eAAe,aAAa,MAA+B;AACzD,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,CAAC,SAAS,KAAK,IAAI,MAAM,QAAQ,IAAI;AAAA,IACzC;AAAA,MACE;AAAA,MACA,cAAc,UAAU,cAAc,UAAU;AAAA,IAClD;AAAA,IACA;AAAA,MACE;AAAA,MACA,cAAc,UAAU;AAAA,IAC1B;AAAA,EACF,CAAC;AACD,MAAI,CAAC,QAAQ,MAAM,CAAC,QAAQ,MAAM;AAChC,WAAO,SAAS,EAAE,IAAI,OAAO,OAAO,QAAQ,SAAS,qBAAqB,CAAC;AAAA,EAC7E;AACA,MAAI,CAAC,MAAM,UAAU;AACnB,WAAO,SAAS,EAAE,IAAI,OAAO,OAAO,MAAM,SAAS,qBAAqB,CAAC;AAAA,EAC3E;AACA,QAAM,UAAU,gBAAgB;AAAA,IAC9B,OAAO,MAAM,SAAS;AAAA,IACtB,OAAO,MAAM,SAAS;AAAA,EACxB,CAAC;AACD,QAAM,WAAW,gBAAgB,QAAQ,KAAK,YAAY;AAC1D,QAAM,OAAO,cAAc,SAAS,QAAQ;AAC5C,SAAO,SAAS,iBAAiB,QAAQ,MAAM,IAAI,CAAC;AACtD;AAEA,eAAe,eAAe,MAA+B;AAC3D,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,kBAAkB,MAAM,QAAQ,KAAK,eAAe,IACrD,KAAK,gBAA6B,OAAO,CAAC,MAAM,OAAO,MAAM,QAAQ,IACtE;AACJ,QAAM,OAAO,kBACT,EAAE,WAAW,EAAE,gBAAgB,EAAE,IACjC;AACJ,QAAM,MAAM,MAAM;AAAA,IAChB;AAAA,IACA,cAAc,UAAU,cAAc,UAAU;AAAA,IAChD;AAAA,EACF;AACA,SAAO,SAAS;AAAA,IACd,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA,SAAS,oBAAoB;AAAA,EAC/B,CAAC;AACH;AAEA,eAAe,eAAe,MAA+B;AAC3D,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,MAAM,MAAM;AAAA,IAChB;AAAA,IACA,cAAc,UAAU,cAAc,UAAU;AAAA,EAClD;AACA,SAAO,SAAS,EAAE,GAAG,KAAK,YAAY,WAAW,CAAC;AACpD;AAEA,eAAe,eAAe,MAA+B;AAC3D,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,aAAa,OAAO,KAAK,UAAU;AACzC,QAAM,MAAM,MAAM;AAAA,IAChB;AAAA,IACA,cAAc,UAAU,cAAc,UAAU;AAAA,EAClD;AACA,SAAO,SAAS,EAAE,GAAG,KAAK,YAAY,WAAW,CAAC;AACpD;AAIA,SAAS,iBAAiB,UAA0B,MAAoB;AACtE,SAAO;AAAA,IACL,UAAU;AAAA,MACR,IAAI,SAAS;AAAA,MACb,OAAO,SAAS;AAAA,MAChB,QAAQ,SAAS;AAAA,MACjB,QAAQ,SAAS;AAAA,MACjB,OAAO,SAAS,WAAW;AAAA,MAC3B,WAAW,SAAS;AAAA,MACpB,WAAW,SAAS;AAAA,IACtB;AAAA,IACA,SAAS;AAAA,MACP,YAAY,KAAK,WAAW;AAAA,MAC5B,cAAc,KAAK,aAAa;AAAA,MAChC,cAAc,KAAK,aAAa;AAAA,MAChC,YAAY,KAAK,WAAW;AAAA,MAC5B,cAAc,KAAK,aAAa;AAAA,MAChC,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,IAChB;AAAA,IACA,OAAO;AAAA,MACL,OAAO,KAAK,WAAW,IAAI,CAAC,OAAO;AAAA,QACjC,IAAI,EAAE;AAAA,QACN,UAAU,EAAE;AAAA,QACZ,YAAY,EAAE;AAAA,MAChB,EAAE;AAAA,MACF,SAAS,KAAK,aAAa,IAAI,CAAC,OAAO;AAAA,QACrC,IAAI,EAAE;AAAA,QACN,UAAU,EAAE;AAAA,QACZ,YAAY,EAAE;AAAA,MAChB,EAAE;AAAA,MACF,SAAS,KAAK,aAAa,IAAI,CAAC,OAAO;AAAA,QACrC,IAAI,EAAE;AAAA,QACN,UAAU,EAAE;AAAA,QACZ,aAAa,EAAE;AAAA,QACf,YAAY,EAAE;AAAA,QACd,WAAW,EAAE;AAAA,QACb,cAAc,EAAE;AAAA,MAClB,EAAE;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,MACL,OAAO,KAAK,WAAW,IAAI,CAAC,OAAO;AAAA,QACjC,cAAc,EAAE;AAAA,QAChB,cAAc,EAAE;AAAA,QAChB,UAAU,EAAE,YAAY;AAAA,MAC1B,EAAE;AAAA,MACF,SAAS,KAAK,aAAa,IAAI,CAAC,OAAO;AAAA,QACrC,cAAc,EAAE;AAAA,QAChB,cAAc,EAAE;AAAA,QAChB,UAAU,EAAE,YAAY;AAAA,MAC1B,EAAE;AAAA,IACJ;AAAA,EACF;AACF;;;AC3TO,SAAS,iCAAiC;AAC/C,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,MAAM,CAAC,WAAW,KAAK;AAAA,YACvB,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,YAAY;AAAA,MACzB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,OAAO;AAAA,YACL,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,cAAc,OAAO;AAAA,MAClC;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,OAAO;AAAA,YACL,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,cAAc,OAAO;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,uBACpB,MACA,MACA;AACA,MAAI,SAAS,6BAA6B;AACxC,QAAI;AACF,YAAM,aAAa,KAAK;AACxB,YAAM,SAAS,IAAI,gBAAgB;AACnC,aAAO,IAAI,QAAQ,OAAO,KAAK,QAAQ,CAAC,CAAC;AACzC,aAAO,IAAI,YAAY,OAAO,KAAK,YAAY,EAAE,CAAC;AAClD,UAAI,KAAK,KAAM,QAAO,IAAI,QAAQ,OAAO,KAAK,IAAI,CAAC;AAEnD,YAAM,SAAS,MAAM,cAKlB,OAAO,cAAc,UAAU,SAAS,MAAM,EAAE;AAEnD,UAAI,CAAC,OAAO,IAAI;AACd,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,SAAS,gBAAgB,CAAC;AAAA,MACvE;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK,MAAM,YAAY,OAAO,WAAW,CAAC;AAAA,IACrF,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,4BAA4B;AACvC,QAAI;AACF,YAAM,aAAa,KAAK;AACxB,YAAM,QAAQ,KAAK;AAEnB,YAAM,SAAS,MAAM,cAIlB,OAAO,cAAc,UAAU,SAAS,KAAK,EAAE;AAElD,UAAI,CAAC,OAAO,IAAI;AACd,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,SAAS,gBAAgB,CAAC;AAAA,MACvE;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK,CAAC;AAAA,IACjD,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,oCAAoC;AAC/C,QAAI;AACF,YAAM,aAAa,KAAK;AACxB,YAAM,QAAQ,KAAK;AAGnB,YAAM,SAAS,MAAM,cAIlB,OAAO,cAAc,UAAU,SAAS,KAAK,qBAAqB;AAErE,UAAI,OAAO,MAAM,OAAO,MAAM;AAC5B,eAAO,SAAS,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK,CAAC;AAAA,MACjD;AAGA,YAAM,YAAY,MAAM,cAKrB,OAAO,cAAc,UAAU,SAAS,KAAK,cAAc;AAE9D,UAAI,CAAC,UAAU,IAAI;AACjB,eAAO,SAAS,EAAE,IAAI,MAAM,MAAM,MAAM,SAAS,0BAA0B,CAAC;AAAA,MAC9E;AAEA,aAAO,SAAS;AAAA,QACd,IAAI;AAAA,QACJ,aAAa,UAAU;AAAA,QACvB,iBAAiB,UAAU;AAAA,MAC7B,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,SAAO;AACT;;;AChKO,SAAS,8BAA8B;AAC5C,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,KAAK;AAAA,YACH,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,aAAa;AAAA,YACX,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,eAAe;AAAA,YACb,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,aAAa;AAAA,YACX,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,aAAa;AAAA,MAC1B;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,OAAO;AAAA,YACL,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,cAAc,OAAO;AAAA,MAClC;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,OAAO;AAAA,YACL,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,cAAc,OAAO;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,oBACpB,MACA,MACA;AACA,MAAI,SAAS,yBAAyB;AACpC,QAAI;AACF,YAAM,SAAS,IAAI,gBAAgB;AACnC,UAAI,KAAK,IAAK,QAAO,IAAI,OAAO,OAAO,KAAK,GAAG,CAAC;AAChD,UAAI,KAAK,YAAa,QAAO,IAAI,eAAe,OAAO,KAAK,WAAW,CAAC;AAExE,YAAM,WAAW,OAAO,SAAS;AACjC,YAAM,OAAO,uBAAuB,WAAW,IAAI,QAAQ,KAAK,EAAE;AAElE,YAAM,OAA+B,CAAC;AACtC,UAAI,KAAK,WAAY,MAAK,aAAa,OAAO,KAAK,UAAU;AAC7D,UAAI,KAAK,cAAe,MAAK,gBAAgB,OAAO,KAAK,aAAa;AAEtE,YAAM,OAAO,MAAM,cAMhB,QAAQ,MAAM,IAAI;AAErB,UAAI,CAAC,KAAK,IAAI;AACZ,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,KAAK,SAAS,gBAAgB,CAAC;AAAA,MACrE;AAEA,aAAO,SAAS;AAAA,QACd,IAAI;AAAA,QACJ,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,QACb,SAAS;AAAA,MACX,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,0BAA0B;AACrC,QAAI;AACF,YAAM,SAAS,IAAI,gBAAgB;AACnC,aAAO,IAAI,QAAQ,OAAO,KAAK,QAAQ,CAAC,CAAC;AACzC,aAAO,IAAI,YAAY,OAAO,KAAK,YAAY,EAAE,CAAC;AAClD,aAAO,IAAI,UAAU,WAAW;AAChC,aAAO,IAAI,aAAa,MAAM;AAE9B,YAAM,SAAS,MAAM,cAKlB,OAAO,8BAA8B,MAAM,EAAE;AAEhD,UAAI,CAAC,OAAO,IAAI;AACd,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,SAAS,gBAAgB,CAAC;AAAA,MACvE;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,MAAM,OAAO,MAAM,YAAY,OAAO,WAAW,CAAC;AAAA,IAChF,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,yBAAyB;AACpC,QAAI;AACF,YAAM,cAAc,KAAK;AACzB,YAAM,SAAS,MAAM,cAKlB,OAAO,8BAA8B,WAAW,EAAE;AAErD,UAAI,CAAC,OAAO,IAAI;AACd,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,SAAS,gBAAgB,CAAC;AAAA,MACvE;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,WAAW,OAAO,WAAW,UAAU,OAAO,SAAS,CAAC;AAAA,IACtF,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,iCAAiC;AAC5C,QAAI;AACF,YAAM,aAAa,KAAK;AACxB,YAAM,QAAQ,KAAK;AAEnB,YAAM,SAAS,MAAM,cAIlB,OAAO,cAAc,UAAU,SAAS,KAAK,qBAAqB;AAErE,UAAI,CAAC,OAAO,IAAI;AACd,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,SAAS,gBAAgB,CAAC;AAAA,MACvE;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK,CAAC;AAAA,IACjD,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,2BAA2B;AACtC,QAAI;AACF,YAAM,aAAa,KAAK;AACxB,YAAM,QAAQ,KAAK;AAEnB,YAAM,SAAS,MAAM,cAIlB,OAAO,cAAc,UAAU,SAAS,KAAK,EAAE;AAElD,UAAI,CAAC,OAAO,IAAI;AACd,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,SAAS,gBAAgB,CAAC;AAAA,MACvE;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK,CAAC;AAAA,IACjD,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,SAAO;AACT;;;ACvOO,SAAS,+BAA+B;AAC7C,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,UAAU;AAAA,YACR,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,qBACpB,MACA,MACA;AACA,MAAI,SAAS,0BAA0B;AACrC,QAAI;AACF,YAAM,SAAS,MAAM,cAYlB,OAAO,kBAAkB;AAE5B,UAAI,QAAQ,OAAO,SAAS,CAAC;AAG7B,cAAQ,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW;AAG1C,UAAI,KAAK,UAAU;AACjB,cAAM,SAAS,OAAO,KAAK,QAAQ,EAAE,YAAY;AACjD,gBAAQ,MAAM;AAAA,UACZ,CAAC,MACC,EAAE,eAAe,KAAK,YACrB,EAAE,gBAAgB,EAAE,aAAa,YAAY,EAAE,SAAS,MAAM;AAAA,QACnE;AAAA,MACF;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,aAAa,MAAM,CAAC;AAAA,IAClD,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,SAAO;AACT;;;AC7DO,SAAS,0BAA0B;AACxC,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,MAAM,CAAC,OAAO,UAAU,QAAQ,SAAS;AAAA,YACzC,aAAa;AAAA,UACf;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,YAAY;AAAA,YACV,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS;AAAA,YACP,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,SAAS;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,gBACpB,MACA,MACA;AACA,MAAI,SAAS,sBAAsB;AACjC,QAAI;AACF,YAAM,SAAS,IAAI,gBAAgB;AACnC,UAAI,KAAK,OAAQ,QAAO,IAAI,UAAU,OAAO,KAAK,MAAM,CAAC;AACzD,UAAI,KAAK,SAAU,QAAO,IAAI,YAAY,OAAO,KAAK,QAAQ,CAAC;AAC/D,UAAI,KAAK,SAAU,QAAO,IAAI,YAAY,OAAO,KAAK,QAAQ,CAAC;AAC/D,UAAI,KAAK,WAAY,QAAO,IAAI,cAAc,OAAO,KAAK,UAAU,CAAC;AACrE,UAAI,KAAK,KAAM,QAAO,IAAI,QAAQ,OAAO,KAAK,IAAI,CAAC;AACnD,UAAI,KAAK,SAAU,QAAO,IAAI,YAAY,OAAO,KAAK,QAAQ,CAAC;AAE/D,YAAM,KAAK,OAAO,SAAS;AAC3B,YAAM,OAAO,aAAa,KAAK,IAAI,EAAE,KAAK,EAAE;AAC5C,YAAM,SAAS,MAAM,cAKlB,OAAO,IAAI;AAEd,UAAI,CAAC,OAAO,IAAI;AACd,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,OAAO,SAAS,gBAAgB,CAAC;AAAA,MACvE;AAEA,aAAO,SAAS,EAAE,IAAI,MAAM,MAAM,OAAO,MAAM,YAAY,OAAO,WAAW,CAAC;AAAA,IAChF,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,qBAAqB;AAChC,QAAI;AACF,YAAM,UAAU,KAAK;AAErB,YAAM,eAAe,MAAM,cAQxB,OAAO,cAAc,OAAO,EAAE;AAEjC,UAAI,CAAC,aAAa,IAAI;AACpB,eAAO,SAAS,EAAE,IAAI,OAAO,OAAO,aAAa,SAAS,gBAAgB,CAAC;AAAA,MAC7E;AAEA,YAAM,EAAE,MAAM,IAAI,aAAa;AAC/B,YAAM,MAAM,MAAM;AAElB,UAAI,gBAA2B,CAAC;AAChC,UAAI,gBAA2B,CAAC;AAEhC,UAAI,KAAK;AACP,YAAI;AACF,gBAAM,CAAC,YAAY,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,YACjD;AAAA,cACE;AAAA,cACA,cAAc,OAAO,gBAAgB,IAAI,EAAE;AAAA,YAC7C;AAAA,YACA;AAAA,cACE;AAAA,cACA,cAAc,OAAO,gBAAgB,IAAI,EAAE;AAAA,YAC7C;AAAA,UACF,CAAC;AAED,cAAI,WAAW,MAAM,MAAM,QAAQ,WAAW,IAAI,GAAG;AACnD,4BAAiB,WAAW,KAAiC;AAAA,cAC3D,CAAC,MAAM,EAAE,SAAS;AAAA,YACpB;AAAA,UACF;AAEA,cAAI,WAAW,MAAM,MAAM,QAAQ,WAAW,IAAI,GAAG;AACnD,4BAAiB,WAAW,KAA0C;AAAA,cACpE,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE,WAAW,KAAM,EAAE,WAAW,QAAQ,EAAE,UAAU;AAAA,YAClF;AAAA,UACF;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,aAAO,SAAS;AAAA,QACd,IAAI;AAAA,QACJ,GAAG,aAAa;AAAA,QAChB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,SAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,SAAO;AACT;;;ACzJO,IAAM,iBAA4B;AAAA,EACvC,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,QAAQ,CAAC,MAAM,SAAS,mBAAmB,MAAM,IAAI;AACvD;AAEO,IAAM,yBAAoC;AAAA,EAC/C,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,QAAQ,CAAC,MAAM,SAAS,4BAA4B,MAAM,IAAI;AAChE;AAEO,IAAM,oBAA+B;AAAA,EAC1C,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,QAAQ,CAAC,MAAM,SAAS,uBAAuB,MAAM,IAAI;AAC3D;AAEO,IAAM,kBAA6B;AAAA,EACxC,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,QAAQ,CAAC,MAAM,SAAS,oBAAoB,MAAM,IAAI;AACxD;AAEO,IAAM,mBAA8B;AAAA,EACzC,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,QAAQ,CAAC,MAAM,SAAS,qBAAqB,MAAM,IAAI;AACzD;AAEO,IAAM,cAAyB;AAAA,EACpC,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,QAAQ,CAAC,MAAM,SAAS,gBAAgB,MAAM,IAAI;AACpD;AAMO,IAAM,eAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACxDO,IAAM,kBAAkB;AAExB,SAAS,gBAAwB;AACtC,SAAO,aAAa,gBAAgB,KAAK;AAC3C;;;ACEO,SAASC,UAAS,MAAc;AACrC,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,KAAK,CAAC,EAAE;AACtD;AAEO,SAASC,UAAS,MAAe;AACtC,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,EAAE,CAAC,EAAE;AACrF;AAKO,SAAS,iBAAiB,QAAoB;AACnD,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,OAAO,CAAC,EAAE;AAAA,EAC9D;AAGA,QAAM,UAAqG,CAAC;AAE5G,MAAI,OAAO,MAAM;AACf,YAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,OAAO,KAAK,CAAC;AAAA,EAClD;AAEA,aAAW,OAAO,OAAO,UAAU,CAAC,GAAG;AACrC,YAAQ,KAAK,EAAE,MAAM,SAAS,MAAM,IAAI,MAAM,UAAU,IAAI,SAAS,CAAC;AAAA,EACxE;AAEA,SAAO,EAAE,QAAQ;AACnB;;;ACEA,IAAM,kBAAkB,oBAAI,IAA4B;AAExD,IAAMC,mBAAkB;AAExB,SAASC,eAAc,OAAwB;AAC7C,SAAO,SAAS,aAAa,gBAAgB,KAAKD;AACpD;AAEA,eAAe,eAAgC;AAC7C,QAAM,QAAQ,aAAa,kBAAkB,KAAM,MAAM,gBAAgB;AACzE,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,kEAAkE;AAAA,EACpF;AACA,SAAO;AACT;AAEO,SAAS,4BAA4B;AAC1C,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,MAAM,CAAC,cAAc,KAAK;AAAA,YAC1B,aACE;AAAA,UACJ;AAAA,UACA,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,kBAAkB;AAAA,YAChB,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,cAAc;AAAA,YACZ,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,WAAW,EAAE,MAAM,SAAS;AAAA,QAC9B;AAAA,QACA,UAAU,CAAC,WAAW;AAAA,MACxB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,WAAW,EAAE,MAAM,SAAS;AAAA,QAC9B;AAAA,QACA,UAAU,CAAC,WAAW;AAAA,MACxB;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY,CAAC;AAAA,MACf;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,WAAW;AAAA,YACT,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,cAAc;AAAA,YACZ,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,UACA,UAAU;AAAA,YACR,MAAM;AAAA,YACN,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,UAAU,CAAC,aAAa,cAAc;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,kBAAkB,MAAc,MAA+B;AACnF,QAAM,QAAQ,MAAM,aAAa;AAEjC,MAAI,SAAS,uBAAuB;AAClC,UAAM,QAAQ;AACd,UAAM,SAASC,eAAc;AAC7B,UAAM,OAAO,MAAM,QAAQ;AAE3B,UAAM,kBAAkB,MAAM,MAAM,GAAG,MAAM,2BAA2B;AAAA,MACtE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,KAAK;AAAA,MAChC;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,aAAa;AAAA,QACb,cAAc,MAAM,gBAAgB;AAAA,MACtC,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,gBAAgB,IAAI;AACvB,YAAM,OAAO,MAAM,gBAAgB,KAAK;AACxC,aAAOC,UAAS,EAAE,IAAI,OAAO,OAAO,6BAA6B,IAAI,GAAG,CAAC;AAAA,IAC3E;AAEA,UAAM,UAAW,MAAM,gBAAgB,KAAK;AAO5C,UAAM,OAAO,IAAI,iBAAiB;AAAA,MAChC;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ;AAAA,MACnB,aAAa;AAAA,MACb,QAAQ,MAAM;AAAA,MACd,UAAU,MAAM,YAAY;AAAA,MAC5B,kBAAkB,MAAM;AAAA,MACxB,OAAO,CAAC,OAAO,YAAY;AACzB,YAAI,UAAU,SAAS;AACrB,kBAAQ,MAAM,kBAAkB,OAAO,EAAE;AAAA,QAC3C;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,MAAM,EAAE,MAAM,CAAC,QAAQ;AAC1B,cAAQ,MAAM,kCAAkC,GAAG;AACnD,sBAAgB,OAAO,QAAQ,SAAS;AAAA,IAC1C,CAAC;AAED,oBAAgB,IAAI,QAAQ,WAAW;AAAA,MACrC,WAAW,QAAQ;AAAA,MACnB;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB;AAAA,IACF,CAAC;AAED,WAAOA,UAAS;AAAA,MACd,IAAI;AAAA,MACJ,WAAW,QAAQ;AAAA,MACnB;AAAA,MACA,WAAW,QAAQ;AAAA,MACnB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,wBAAwB;AACnC,UAAM,QAAQ;AACd,UAAM,UAAU,gBAAgB,IAAI,MAAM,SAAS;AAEnD,QAAI,CAAC,SAAS;AACZ,aAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,qBAAqB,WAAW,MAAM,UAAU,CAAC;AAAA,IACvF;AAEA,WAAOA,UAAS;AAAA,MACd,IAAI;AAAA,MACJ,WAAW,QAAQ;AAAA,MACnB,MAAM,QAAQ;AAAA,MACd,WAAW,IAAI,KAAK,QAAQ,SAAS,EAAE,YAAY;AAAA,MACnD,UAAU,KAAK,IAAI,IAAI,QAAQ;AAAA,IACjC,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,sBAAsB;AACjC,UAAM,QAAQ;AACd,UAAM,UAAU,gBAAgB,IAAI,MAAM,SAAS;AAEnD,QAAI,CAAC,SAAS;AACZ,aAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,qBAAqB,WAAW,MAAM,UAAU,CAAC;AAAA,IACvF;AAEA,UAAM,QAAQ,KAAK,KAAK;AACxB,oBAAgB,OAAO,MAAM,SAAS;AAEtC,WAAOA,UAAS;AAAA,MACd,IAAI;AAAA,MACJ,WAAW,MAAM;AAAA,MACjB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,sBAAsB;AACjC,UAAM,WAAW,MAAM,KAAK,gBAAgB,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO;AAAA,MAChE,WAAW,EAAE;AAAA,MACb,MAAM,EAAE;AAAA,MACR,WAAW,IAAI,KAAK,EAAE,SAAS,EAAE,YAAY;AAAA,MAC7C,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,IAC3B,EAAE;AAEF,WAAOA,UAAS;AAAA,MACd,IAAI;AAAA,MACJ,OAAO,SAAS;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,qBAAqB;AAChC,UAAM,QAAQ;AAKd,UAAM,SAASD,eAAc;AAE7B,UAAM,UAAU,gBAAgB,IAAI,MAAM,SAAS;AACnD,QAAI,CAAC,SAAS;AACZ,aAAOC,UAAS;AAAA,QACd,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,WAAW,MAAM;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,MAAM,MAAM,GAAG,MAAM,2BAA2B,MAAM,SAAS,QAAQ;AAAA,MACtF,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,KAAK;AAAA,MAChC;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,cAAc,MAAM;AAAA,QACpB,UAAU,MAAM,YAAY;AAAA,MAC9B,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,wBAAwB,IAAI,GAAG,CAAC;AAAA,IACtE;AAEA,UAAM,SAAU,MAAM,SAAS,KAAK;AAEpC,WAAOA,UAAS;AAAA,MACd,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,WAAW,OAAO;AAAA,MAClB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AC1RA,IAAI,kBAAiC;AAK9B,SAAS,+BAA+B;AAC7C,SAAO,uCAAuC;AAChD;AAMA,eAAsB,kBAAkB,MAAc,MAA+B;AAEnF,MAAI,SAAS,iBAAiB;AAC5B,QAAI;AACF,YAAM,SAAS,MAAM,cAAc;AAAA,QACjC,UAAW,KAAK,YAAwB;AAAA,QACxC,kBAAkB,KAAK;AAAA,MACzB,CAAC;AAED,UAAI,CAAC,OAAO,IAAI;AACd,eAAOC,UAAS,EAAE,IAAI,OAAO,OAAO,OAAO,MAAM,CAAC;AAAA,MACpD;AAEA,wBAAkB,OAAO,KAAM;AAC/B,aAAOA,UAAS;AAAA,QACd,IAAI;AAAA,QACJ,WAAW;AAAA,QACX,MAAM;AAAA,MACR,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS,gBAAgB;AAC3B,QAAI;AACF,UAAI,iBAAiB;AACnB,cAAM,cAAc,eAAe;AACnC,0BAAkB;AAAA,MACpB,OAAO;AAEL,cAAM,kBAAkB;AAAA,MAC1B;AACA,aAAOA,UAAS,EAAE,IAAI,MAAM,MAAM,kCAAkC,CAAC;AAAA,IACvE,SAAS,KAAK;AACZ,aAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACxF;AAAA,EACF;AAGA,MAAI,CAAC,KAAK,WAAW,UAAU,EAAG,QAAO;AAEzC,MAAI;AAEF,QAAI,YAAY;AAChB,QAAI,CAAC,WAAW;AACd,UAAI;AACF,cAAM,SAAS,MAAM,qBAAqB;AAC1C,oBAAY,OAAO;AACnB,0BAAkB;AAAA,MACpB,QAAQ;AACN,eAAOA,UAAS;AAAA,UACd,IAAI;AAAA,UACJ,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,QAAQ,aAAa,EAAE;AAC7C,UAAM,SAAS,MAAM,SAAS,WAAW,UAAU,IAAI;AAEvD,QAAI,CAAC,OAAO,IAAI;AAEd,UAAI,OAAO,OAAO,SAAS,WAAW,GAAG;AACvC,0BAAkB;AAAA,MACpB;AAGA,UAAI,OAAO,cAAc,mBAAmB;AAC1C,eAAOC,UAAS,OAAO,SAAS,wCAAwC;AAAA,MAC1E;AACA,aAAOD,UAAS,EAAE,IAAI,OAAO,OAAO,OAAO,OAAO,MAAM,KAAK,CAAC;AAAA,IAChE;AAGA,UAAM,aAAyB,OAAO,QAAQ,SAC1C,EAAE,MAAM,OAAO,QAAQ,IAAI,QAAQ,OAAO,OAAO,IAChD,OAAO,QAAQ;AAEpB,WAAO,iBAAiB,UAAU;AAAA,EACpC,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,SAAS,MAAM,KAAK,CAAC;AAAA,EAC3D;AACF;;;AC5GO,SAAS,0BAA0B;AACxC,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAGF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,KAAK;AAAA,YACH,MAAM;AAAA,YACN,MAAM,CAAC,QAAQ,OAAO,OAAO;AAAA,YAC7B,aAAa;AAAA,UACf;AAAA,UACA,KAAK;AAAA,YACH,MAAM;AAAA,YACN,aACE;AAAA,UACJ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,gBACpB,MACA,MACA;AACA,MAAI,SAAS,eAAgB,QAAO;AAEpC,MAAI;AACF,UAAM,MAAM,KAAK;AACjB,UAAM,UAAU,KAAK;AACrB,UAAM,UAAU,MAAM,SAAS,GAAG,IAAI;AAEtC,QAAI,OAAO,CAAC,SAAS;AACnB,aAAOE,UAAS,EAAE,IAAI,OAAO,OAAO,wBAAwB,GAAG,4BAA4B,CAAC;AAAA,IAC9F;AAEA,UAAM,SAAS,SAAS,OAAO,cAAc;AAC7C,UAAM,SAAS,SAAS,OAAO,cAAc,MAAM;AAGnD,UAAM,WAAW,MAAM,MAAM,GAAG,MAAM,oBAAoB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,OAAO,CAAC;AAAA,IACjC,CAAC;AAED,UAAM,YAAa,MAAM,SAAS,KAAK;AACvC,QAAI,CAAC,SAAS,MAAM,CAAC,UAAU,MAAM,CAAC,UAAU,cAAc,CAAC,UAAU,UAAU;AACjF,aAAOA,UAAS;AAAA,QACd,IAAI;AAAA,QACJ,OAAO,uBAAuB,UAAU,SAAS,SAAS,UAAU;AAAA,MACtE,CAAC;AAAA,IACH;AAGA,QAAI,UAAU,iBAAiB;AAC7B,UAAI;AACF,gBAAQ,UAAU,eAAe;AAAA,MACnC,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,UAAM,cAAc,UAAU,mBAAmB,KAAK;AACtD,UAAM,YAAY,UAAU,YAAY,IAAI,KAAK,UAAU,SAAS,EAAE,QAAQ,IAAI;AAElF,QAAI;AACJ,QAAI;AAEJ,WAAO,MAAM;AACX,UAAI,aAAa,KAAK,IAAI,IAAI,WAAW;AACvC,eAAOA,UAAS;AAAA,UACd,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,UAAU,UAAU;AAAA,UACpB,iBAAiB,UAAU;AAAA,QAC7B,CAAC;AAAA,MACH;AAEA,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,UAAU,CAAC;AAE9D,YAAM,UAAU,MAAM,MAAM,GAAG,MAAM,mBAAmB;AAAA,QACtD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,YAAY,UAAU,WAAW,CAAC;AAAA,MAC3D,CAAC;AAED,YAAM,WAAY,MAAM,QAAQ,KAAK;AACrC,UAAI,CAAC,QAAQ,MAAM,CAAC,SAAS,IAAI;AAC/B,eAAOA,UAAS;AAAA,UACd,IAAI;AAAA,UACJ,OAAO,sBAAsB,SAAS,SAAS,QAAQ,UAAU;AAAA,QACnE,CAAC;AAAA,MACH;AAEA,UAAI,SAAS,WAAW,cAAc,SAAS,aAAa;AAC1D,gBAAQ,SAAS;AACjB,uBAAe,SAAS;AACxB;AAAA,MACF;AAEA,UAAI,SAAS,WAAW,YAAY;AAClC,eAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,0BAA0B,CAAC;AAAA,MACjE;AAEA,UAAI,SAAS,WAAW,WAAW;AACjC,eAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,mCAAmC,CAAC;AAAA,MAC1E;AAAA,IACF;AAGA,UAAM,WAAW,MAAM,UAAU,QAAQ,KAAK;AAC9C,UAAM,OAAO,UAAU,iBAAiB,CAAC;AAEzC,QAAI,aAAa;AACjB,QAAI,aAAa;AACjB,QAAI;AAEJ,QAAI,KAAK,UAAU,GAAG;AACpB,qBAAe,KAAK,CAAC,GAAG;AAAA,IAC1B,WAAW,SAAS;AAElB,YAAM,cAAc,KAAK;AAAA,QACvB,CAAC,MAAM,EAAE,KAAK,YAAY,MAAM,QAAQ,YAAY,KAAK,EAAE,OAAO;AAAA,MACpE;AACA,UAAI,CAAC,aAAa;AAEhB,cAAMC,eAAc,MAAM,aAAa,GAAG,IAAI;AAC9C,cAAM,SAAS,EAAE,OAAO,YAAY,QAAQ,OAAO,YAAY,SAAS,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY,GAAG,KAAK,GAAGA,YAAW;AAEpI,eAAOD,UAAS;AAAA,UACd,IAAI;AAAA,UACJ,OAAO,iBAAiB,OAAO;AAAA,UAC/B,UAAU;AAAA,UACV,YAAY,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY,GAAG;AAAA,UACrD,eAAe,KAAK,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,EAAE,KAAK,EAAE;AAAA,QAC3E,CAAC;AAAA,MACH;AAEA,UAAI,YAAY,OAAO,cAAc;AACnC,cAAM,YAAY,MAAM,UAAU,QAAQ,OAAO,YAAY,EAAE;AAC/D,YAAI,CAAC,UAAU,MAAM,CAAC,UAAU,aAAa;AAC3C,iBAAOA,UAAS;AAAA,YACd,IAAI;AAAA,YACJ,OAAO,kCAAkC,UAAU,SAAS,eAAe;AAAA,UAC7E,CAAC;AAAA,QACH;AACA,qBAAa,UAAU;AACvB,qBAAa,UAAU;AACvB,uBAAe,UAAU;AAAA,MAC3B,OAAO;AACL,uBAAe,YAAY;AAAA,MAC7B;AAAA,IACF,OAAO;AAEL,YAAM,aAAa,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY;AACzD,qBAAe,YAAY;AAAA,IAC7B;AAGA,UAAM,cAAc,MAAM,aAAa,GAAG,IAAI;AAC9C,UAAM,SAAS,EAAE,OAAO,YAAY,QAAQ,OAAO,YAAY,SAAS,aAAa,GAAG,WAAW;AAEnG,WAAOA,UAAS;AAAA,MACd,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,MACP,GAAI,KAAK,SAAS,IACd,EAAE,eAAe,KAAK,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,EAAE,KAAK,EAAE,EAAE,IAC7E,CAAC;AAAA,IACP,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,EACxF;AACF;;;AC5LA,OAAO,QAAQ;AACf,SAAS,iBAAiB;AAC1B,OAAO,aAAa;AAOpB,SAAS,uBAAuC;AAC9C,MAAI;AACF,UAAM,UAAU,GAAG,aAAa,QAAQ,KAAK,CAAC,CAAC,EAAE,QAAQ,OAAO,GAAG;AACnE,QAAI,QAAQ,SAAS,OAAO,KAAK,QAAQ,SAAS,OAAO,EAAG,QAAO;AACnE,QAAI,QAAQ,SAAS,QAAQ,KAAK,QAAQ,SAAS,QAAQ,EAAG,QAAO;AAAA,EACvE,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEA,IAAM,mBAAqD;AAAA,EACzD,KAAK,CAAC,OAAO,OAAO,MAAM,GAAG,WAAW,SAAS;AAAA,EACjD,MAAM,CAAC,QAAQ,OAAO,MAAM,GAAG,WAAW,SAAS;AAAA,EACnD,KAAK,CAAC,OAAO,WAAW,MAAM,GAAG,WAAW,SAAS;AACvD;AAEO,SAAS,4BAA4B;AAC1C,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY,CAAC;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,kBACpB,MACA,OACA;AACA,MAAI,SAAS,iBAAkB,QAAO;AAEtC,MAAI;AACF,UAAM,KAAK,qBAAqB;AAChC,UAAM,MAAM,iBAAiB,EAAE;AAE/B,UAAM,SAAS,UAAU,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG;AAAA,MAC7C,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,MAC9B,KAAK,QAAQ,IAAI;AAAA,MACjB,SAAS;AAAA,MACT,OAAO,QAAQ,aAAa;AAAA,MAC5B,aAAa;AAAA,IACf,CAAC;AAED,QAAI,OAAO,OAAO;AAChB,aAAOE,UAAS;AAAA,QACd,IAAI;AAAA,QACJ,OAAO,iBAAiB,EAAE,KAAK,OAAO,MAAM,OAAO;AAAA,MACrD,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,OAAO,QAAQ,SAAS,EAAE,KAAK,KAAK;AACnD,UAAM,SAAS,OAAO,QAAQ,SAAS,EAAE,KAAK,KAAK;AAEnD,QAAI,OAAO,WAAW,GAAG;AACvB,aAAOA,UAAS;AAAA,QACd,IAAI;AAAA,QACJ,OAAO,6BAA6B,OAAO,MAAM;AAAA,QACjD,QAAQ,UAAU;AAAA,MACpB,CAAC;AAAA,IACH;AAEA,UAAM,iBAAiB;AAEvB,WAAOA,UAAS;AAAA,MACd,IAAI;AAAA,MACJ,SAAS,yBAAyB,WAAW;AAAA,MAC7C,gBAAgB;AAAA,MAChB,QAAQ,UAAU;AAAA,IACpB,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAOA,UAAS,EAAE,IAAI,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,EACxF;AACF;;;ACvFO,IAAM,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmPrC,KAAK;;;AlBnOP,eAAe,aAAa;AAC1B,QAAM,WAAW,aAAa,kBAAkB,KAAM,MAAM,gBAAgB;AAC5E,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,oEAAoE;AAAA,EACtF;AACA,SAAO,EAAE,QAAQ,cAAc,GAAG,SAAS;AAC7C;AAEA,eAAsB,OAAO,OAAiB;AAC5C,QAAM,WAAW,cAAc,YAAY;AAE3C,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,cAAc,SAAS,QAAQ;AAAA,IACvC;AAAA,MACE,cAAc,EAAE,OAAO,CAAC,EAAE;AAAA,MAC1B,cAAc;AAAA,IAChB;AAAA,EACF;AAEA,SAAO,kBAAkB,wBAAwB,aAAa;AAAA,IAC5D,OAAO;AAAA,MACL,GAAG,wBAAwB;AAAA,MAC3B,GAAG,0BAA0B;AAAA,MAC7B,GAAG,0BAA0B;AAAA,MAC7B,GAAG,6BAA6B;AAAA,MAChC,GAAG,SAAS,KAAK;AAAA,IACnB;AAAA,EACF,EAAE;AAEF,SAAO,kBAAkB,uBAAuB,OAAO,QAAQ;AAC7D,UAAM,OAAO,IAAI,OAAO;AACxB,UAAM,OAAQ,IAAI,OAAO,aAAa,CAAC;AAGvC,UAAM,cAAc,MAAM,gBAAgB,MAAM,IAAI;AACpD,QAAI,YAAa,QAAO;AAExB,UAAM,gBAAgB,MAAM,kBAAkB,MAAM,IAAI;AACxD,QAAI,cAAe,QAAO;AAE1B,UAAM,gBAAgB,MAAM,kBAAkB,MAAM,IAAI;AACxD,QAAI,cAAe,QAAO;AAE1B,UAAM,gBAAgB,MAAM,kBAAkB,MAAM,IAAI;AACxD,QAAI,cAAe,QAAO;AAG1B,QAAI;AACF,YAAM,MAAM,MAAM,WAAW;AAC7B,aAAO,MAAM,SAAS,KAAK,MAAM,MAAM,GAAG;AAAA,IAC5C,SAAS,KAAK;AACZ,aAAOC,UAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAClE;AAAA,EACF,CAAC;AAED,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAC9B,SAAO,IAAI,QAAc,MAAM,MAAS;AAC1C;","names":["result","toolText","toolJson","DEFAULT_API_URL","resolveApiUrl","toolJson","toolJson","toolText","toolJson","profileName","toolJson","toolText"]}
1
+ {"version":3,"sources":["../src/mcp/index.ts","../../mcp-tools/src/context.ts","../../mcp-tools/src/api-client.ts","../../mcp-tools/src/tool-helpers.ts","../../mcp-tools/src/registry.ts","../../mcp-tools/src/groups/workflows.ts","../../mcp-tools/src/groups/workflow-proposals.ts","../../mcp-tools/src/groups/workflow-runs.ts","../../mcp-tools/src/groups/test-suites.ts","../../mcp-tools/src/groups/credentials.ts","../../mcp-tools/src/groups/issues.ts","../../mcp-tools/src/groups/index.ts","../src/mcp/api-url.ts","../src/mcp/tool-helpers.ts","../src/mcp/session-tools.ts","../src/mcp/browser-tools.ts","../src/mcp/login-tool.ts","../src/mcp/upgrade-tool.ts","../src/mcp/instructions.ts"],"sourcesContent":["/**\n * MCP Server for Canary CLI.\n *\n * Combines:\n * - HTTP-only shared tools from @chatsdet/mcp-tools (workflows, runs, suites,\n * credentials, issues, proposals)\n * - CLI-local tools (login, upgrade, browser daemon, cloud-relay sessions)\n * that depend on local state and can't be hosted remotely.\n *\n * @module\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { buildRegistry, sharedGroups } from '@chatsdet/mcp-tools';\nimport { readStoredToken } from '../auth';\nimport { readBrandEnv } from '../brand.js';\nimport { resolveApiUrl } from './api-url';\nimport { toolText } from './tool-helpers';\nimport { getSessionToolDefinitions, handleSessionTool } from './session-tools';\nimport { getBrowserMCPToolDefinitions, handleBrowserTool } from './browser-tools';\nimport { getLoginToolDefinitions, handleLoginTool } from './login-tool';\nimport { getUpgradeToolDefinitions, handleUpgradeTool } from './upgrade-tool';\nimport { CANARY_MCP_INSTRUCTIONS } from './instructions';\n\nasync function resolveCtx() {\n const apiToken = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken());\n if (!apiToken) {\n throw new Error('Missing token. Call the canary_login tool or set CANARY_API_TOKEN.');\n }\n return { apiUrl: resolveApiUrl(), apiToken };\n}\n\nexport async function runMcp(_argv: string[]) {\n const registry = buildRegistry(sharedGroups);\n\n const server = new Server(\n { name: 'canary-cli', version: '0.1.0' },\n {\n capabilities: { tools: {} },\n instructions: CANARY_MCP_INSTRUCTIONS,\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n ...getLoginToolDefinitions(),\n ...getUpgradeToolDefinitions(),\n ...getSessionToolDefinitions(),\n ...getBrowserMCPToolDefinitions(),\n ...registry.list(),\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = req.params.name;\n const args = (req.params.arguments ?? {}) as Record<string, unknown>;\n\n // CLI-local groups try first; each returns null if the tool is not theirs.\n const loginResult = await handleLoginTool(tool, args);\n if (loginResult) return loginResult;\n\n const upgradeResult = await handleUpgradeTool(tool, args);\n if (upgradeResult) return upgradeResult;\n\n const browserResult = await handleBrowserTool(tool, args);\n if (browserResult) return browserResult;\n\n const sessionResult = await handleSessionTool(tool, args);\n if (sessionResult) return sessionResult;\n\n // Shared HTTP-only tools — provide ctx for this call.\n try {\n const ctx = await resolveCtx();\n return await registry.call(tool, args, ctx);\n } catch (err) {\n return toolText(err instanceof Error ? err.message : String(err));\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n return new Promise<void>(() => undefined);\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * Per-request context for MCP tool handlers. Threaded via AsyncLocalStorage so\n * handler bodies don't have to take ctx as a parameter — `mcpApiRequest()`\n * pulls it from `currentToolCtx()`.\n */\nexport type ToolCtx = {\n apiUrl: string;\n apiToken: string;\n};\n\nconst storage = new AsyncLocalStorage<ToolCtx>();\n\nexport function withToolCtx<T>(ctx: ToolCtx, fn: () => Promise<T>): Promise<T> {\n return storage.run(ctx, fn);\n}\n\nexport function currentToolCtx(): ToolCtx | undefined {\n return storage.getStore();\n}\n","import { currentToolCtx } from './context';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/**\n * Authenticated API request. Pulls `{ apiUrl, apiToken }` from the\n * AsyncLocalStorage-backed ToolCtx — every tool handler runs inside a\n * `withToolCtx()` frame set up by the registry dispatcher.\n *\n * Throws on non-2xx with a prefixed message MCP clients can pattern-match\n * (`[unauthorized]`, `[timeout]`, `[http-N]`).\n */\nexport async function mcpApiRequest<T>(\n method: string,\n path: string,\n body?: Record<string, unknown>\n): Promise<T> {\n const ctx = currentToolCtx();\n if (!ctx) {\n throw new Error('[no-context] mcpApiRequest called outside of withToolCtx()');\n }\n\n const url = `${ctx.apiUrl}${path}`;\n let res: Response;\n try {\n res = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${ctx.apiToken}`,\n 'Content-Type': 'application/json',\n },\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n ...(body ? { body: JSON.stringify(body) } : {}),\n });\n } catch (err) {\n if (err instanceof Error && err.name === 'TimeoutError') {\n throw new Error(`[timeout] upstream API did not respond within ${DEFAULT_TIMEOUT_MS}ms`);\n }\n throw new Error(`[network] ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (!res.ok) {\n if (res.status === 401) {\n throw new Error('[unauthorized] Your session may have expired.');\n }\n const text = await res.text().catch(() => '');\n throw new Error(`[http-${res.status}] ${text || res.statusText}`);\n }\n\n return (await res.json()) as T;\n}\n","export function toolText(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nexport function toolJson(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n","import type { ToolCallResult, ToolDefinition, ToolGroup } from './types';\nimport { type ToolCtx, withToolCtx } from './context';\nimport { toolText } from './tool-helpers';\n\nexport type Registry = {\n list(): ToolDefinition[];\n call(tool: string, args: Record<string, unknown>, ctx: ToolCtx): Promise<ToolCallResult>;\n};\n\n/**\n * Bundle a set of ToolGroups into a Registry. The Registry runs each tool call\n * inside an `AsyncLocalStorage` frame so handler bodies can call\n * `mcpApiRequest()` without taking ctx as a parameter.\n */\nexport function buildRegistry(groups: ToolGroup[]): Registry {\n return {\n list() {\n return groups.flatMap((g) => g.definitions());\n },\n\n async call(tool, args, ctx) {\n return withToolCtx(ctx, async () => {\n for (const group of groups) {\n const result = await group.handle(tool, args);\n if (result) return result;\n }\n return toolText(`Unknown tool: ${tool}`);\n });\n },\n };\n}\n","/**\n * MCP tools for workflow management.\n *\n * Mirrors `canary workflow list` and `canary workflow get`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getWorkflowToolDefinitions() {\n return [\n {\n name: 'canary_workflow_list',\n description:\n 'List workflows in the current organization. Supports filtering by name, type, and status with pagination.',\n inputSchema: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description: 'Search workflows by name',\n },\n flowType: {\n type: 'string',\n enum: ['standard', 'setup', 'seed', 'teardown'],\n description: 'Filter by flow type',\n },\n status: {\n type: 'string',\n enum: ['draft', 'approved'],\n description:\n \"Filter by approval status. 'draft' = not yet approved; 'approved' = a human verified the test checks the right thing. Suite inclusion is the separate `promotion` axis (promoted/paused, managed via `canary workflow promote|pause`), and reliability (passing/flaky/degraded) is the separate `health` dimension.\",\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n pageSize: {\n type: 'number',\n description: 'Page size (default: 25)',\n },\n },\n },\n },\n {\n name: 'canary_workflow_get',\n description:\n 'Get a workflow definition with its steps, nodes, and configuration details.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_patch',\n description:\n 'Update workflow properties using merge-patch. Only provided fields are updated; omitted fields are left unchanged.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n name: {\n type: 'string',\n description: 'New workflow name',\n },\n description: {\n type: 'string',\n description: 'New description',\n },\n status: {\n type: 'string',\n enum: ['draft', 'approved'],\n description:\n \"New approval status. 'approved' asserts a HUMAN verified this test checks the right thing — only set it when the user has personally confirmed. Approval does NOT put the test into suites; suite inclusion is the separate promote/pause axis (use `canary workflow promote|pause`). Reliability is tracked automatically by the `health` dimension.\",\n },\n flowType: {\n type: 'string',\n enum: ['standard', 'setup', 'seed', 'teardown'],\n description: 'New flow type',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_run',\n description:\n 'Trigger a workflow execution. Returns the run ID for tracking status via canary_workflow_runs_get.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID to execute',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_sync',\n description:\n 'Atomically replace all nodes and edges in a workflow. Automatically creates a draft snapshot of the current state before overwriting so changes can be reverted. Use canary_workflow_get to read the current DAG first, modify nodes/edges, then sync back. When using propose=true on an existing workflow, REUSE each existing node\\'s `id` for steps you keep (omit `id` only for genuinely new steps). Without ID reuse the proposal will diff as a full rewrite — every step shown as Removed+Added in the review UI even when only configs changed.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n nodes: {\n type: 'array',\n description: 'Array of node objects with id, nodeType, orderIndex, configJson',\n items: { type: 'object' },\n },\n edges: {\n type: 'array',\n description: 'Array of edge objects with id, sourceNodeId, targetNodeId, edgeType',\n items: { type: 'object' },\n },\n createSnapshot: {\n type: 'boolean',\n description: 'Create a draft snapshot before syncing (default: true)',\n default: true,\n },\n propose: {\n type: 'boolean',\n description: 'Create a proposal instead of applying directly. The proposal can be reviewed and accepted/rejected via the UI. IMPORTANT: when proposing on an existing workflow, reuse each existing node\\'s `id` for steps you intend to keep — only omit `id` for genuinely new steps. Otherwise the diff will show every step as Removed+Added.',\n default: false,\n },\n proposalTitle: {\n type: 'string',\n description: 'Title for the proposal (used with propose: true)',\n },\n proposalDescription: {\n type: 'string',\n description: 'Description/rationale for the proposal (used with propose: true)',\n },\n },\n required: ['workflowId', 'nodes', 'edges'],\n },\n },\n ];\n}\n\nexport async function handleWorkflowTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_workflow_list') {\n try {\n const params = new URLSearchParams();\n if (args.search) params.set('search', String(args.search));\n if (args.flowType) params.set('flowType', String(args.flowType));\n if (args.status) params.set('status', String(args.status));\n if (args.page) params.set('page', String(args.page));\n if (args.pageSize) params.set('pageSize', String(args.pageSize));\n\n const qs = params.toString();\n const path = `/workflows${qs ? `?${qs}` : ''}`;\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown[];\n pagination: unknown;\n }>('GET', path);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data, pagination: result.pagination });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_get') {\n try {\n const workflowId = args.workflowId as string;\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n workflow?: unknown;\n targetOrgId?: string;\n targetOrgName?: string;\n }>('GET', `/workflows/${workflowId}`);\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({ ok: true, workflow: result.workflow });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_patch') {\n try {\n const workflowId = args.workflowId as string;\n const body: Record<string, unknown> = {};\n if (args.name) body.name = String(args.name);\n if (args.description) body.description = String(args.description);\n if (args.status) body.status = String(args.status);\n if (args.flowType) body.flowType = String(args.flowType);\n\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n workflow?: unknown;\n }>('PUT', `/workflows/${workflowId}`, body);\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({ ok: true, workflow: result.workflow });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_run') {\n try {\n const workflowId = args.workflowId as string;\n\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n runId?: string;\n streamId?: string;\n }>('POST', `/workflows/${workflowId}/execute`);\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({ ok: true, runId: result.runId, streamId: result.streamId });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_sync') {\n try {\n const workflowId = args.workflowId as string;\n const nodes = args.nodes as unknown[];\n const edges = args.edges as unknown[];\n\n // --propose: create a proposal instead of applying directly\n if (args.propose) {\n const title = (args.proposalTitle as string) ?? `Sync proposal (${nodes.length} nodes)`;\n const description = (args.proposalDescription as string) ?? null;\n\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n data?: { id: string; title: string; status: string };\n }>('POST', `/workflows/${workflowId}/proposals`, {\n title,\n description,\n snapshotJson: { nodes, edges },\n source: 'api',\n });\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({\n ok: true,\n proposalId: result.data?.id,\n title: result.data?.title,\n status: result.data?.status,\n });\n }\n\n const createSnapshot = args.createSnapshot !== false;\n\n const result = await mcpApiRequest<{\n ok?: boolean;\n error?: string;\n snapshotVersion?: string;\n }>('PUT', `/workflows/${workflowId}/draft-state`, {\n nodes,\n edges,\n createSnapshot,\n });\n\n if (result.error) {\n return toolJson({ ok: false, error: result.error });\n }\n\n return toolJson({\n ok: true,\n ...(result.snapshotVersion ? { snapshotVersion: result.snapshotVersion } : {}),\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","/**\n * MCP tools for workflow proposals: list / get / diff / accept / reject /\n * revert. Mirrors `canary workflow proposals <verb>` with the same JSON\n * output shape so agents get identical responses whether they shell-out or\n * call MCP directly.\n *\n * @module\n */\n\nimport {\n diffSnapshots,\n fromApiSnapshot,\n type SnapshotDiff,\n} from '@chatsdet/workflow-diff';\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\n// Types duplicated here to avoid the MCP server importing from the CLI's\n// `workflow-proposals.ts` which would pull in TTY-detection + process.exit\n// paths that don't belong in MCP land.\ninterface ProposalSummary {\n id: string;\n workflowId: string;\n title: string;\n description: string | null;\n source: string;\n status: string;\n createdByUserId: string | null;\n decidedByUserId: string | null;\n decidedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface ProposalDetail extends ProposalSummary {\n snapshotJson: {\n nodes?: Array<{ id: string; nodeType: string; orderIndex?: number; configJson?: Record<string, unknown> }>;\n edges?: Array<{ id: string; sourceNodeId: string; targetNodeId: string; edgeType?: string | null }>;\n };\n sourceMetadata: Record<string, unknown> | null;\n}\n\ninterface WorkflowDetail {\n id: string;\n nodes: Array<{ id: string; nodeType: string; orderIndex?: number; configJson?: Record<string, unknown> }>;\n edges: Array<{ id: string; sourceNodeId: string; targetNodeId: string; edgeType?: string | null }>;\n}\n\nexport function getWorkflowProposalsToolDefinitions() {\n return [\n {\n name: 'canary_workflow_proposals_list',\n description:\n 'List workflow proposals. By default returns pending proposals; pass status=\"all\" for every status.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string', description: 'Workflow UUID' },\n status: {\n type: 'string',\n enum: ['pending', 'accepted', 'rejected', 'stale', 'all'],\n description: 'Filter by status (default: pending)',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_proposals_get',\n description: 'Fetch a proposal including its full snapshot JSON.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n {\n name: 'canary_workflow_proposals_diff',\n description:\n 'Compute a per-node diff between a proposal and the current workflow draft. Returns summary counts plus per-field changes for changed nodes.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n {\n name: 'canary_workflow_proposals_accept',\n description:\n 'Apply a proposal to the workflow draft. Omit acceptedNodeIds for atomic (all-or-nothing) accept; provide it to cherry-pick a subset.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n acceptedNodeIds: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Optional: node ids from the diff to include. Omit for atomic accept of every change.',\n },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n {\n name: 'canary_workflow_proposals_reject',\n description: 'Reject a pending proposal. Does not change the workflow draft.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n {\n name: 'canary_workflow_proposals_revert',\n description:\n 'Revert a previously-accepted proposal back to pending. Only the user who accepted it may revert.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: { type: 'string' },\n proposalId: { type: 'string' },\n },\n required: ['workflowId', 'proposalId'],\n },\n },\n ];\n}\n\nexport async function handleWorkflowProposalsTool(\n tool: string,\n args: Record<string, unknown>,\n) {\n if (!tool.startsWith('canary_workflow_proposals_')) return null;\n\n try {\n switch (tool) {\n case 'canary_workflow_proposals_list':\n return await listProposals(args);\n case 'canary_workflow_proposals_get':\n return await getProposal(args);\n case 'canary_workflow_proposals_diff':\n return await diffProposal(args);\n case 'canary_workflow_proposals_accept':\n return await acceptProposal(args);\n case 'canary_workflow_proposals_reject':\n return await rejectProposal(args);\n case 'canary_workflow_proposals_revert':\n return await revertProposal(args);\n default:\n return null;\n }\n } catch (err) {\n return toolJson({\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n}\n\n// ── Tool implementations ─────────────────────────────────────────────────\n\nasync function listProposals(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const status = typeof args.status === 'string' ? args.status : 'pending';\n const query = status === 'all' ? '' : `?status=${encodeURIComponent(status)}`;\n const res = await mcpApiRequest<{\n ok: boolean;\n data?: ProposalSummary[];\n error?: string;\n }>('GET', `/workflows/${workflowId}/proposals${query}`);\n return toolJson({\n ok: res.ok,\n workflowId,\n count: res.data?.length ?? 0,\n proposals: res.data ?? [],\n error: res.error,\n });\n}\n\nasync function getProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const res = await mcpApiRequest<{\n ok: boolean;\n data?: ProposalDetail;\n error?: string;\n }>('GET', `/workflows/${workflowId}/proposals/${proposalId}`);\n return toolJson(res);\n}\n\nasync function diffProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const [propRes, wfRes] = await Promise.all([\n mcpApiRequest<{ ok: boolean; data?: ProposalDetail; error?: string }>(\n 'GET',\n `/workflows/${workflowId}/proposals/${proposalId}`,\n ),\n mcpApiRequest<{ ok: boolean; workflow?: WorkflowDetail; error?: string }>(\n 'GET',\n `/workflows/${workflowId}`,\n ),\n ]);\n if (!propRes.ok || !propRes.data) {\n return toolJson({ ok: false, error: propRes.error ?? 'proposal not found' });\n }\n if (!wfRes.workflow) {\n return toolJson({ ok: false, error: wfRes.error ?? 'workflow not found' });\n }\n const current = fromApiSnapshot({\n nodes: wfRes.workflow.nodes,\n edges: wfRes.workflow.edges,\n });\n const proposed = fromApiSnapshot(propRes.data.snapshotJson);\n const diff = diffSnapshots(current, proposed);\n return toolJson(buildDiffPayload(propRes.data, diff));\n}\n\nasync function acceptProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const acceptedNodeIds = Array.isArray(args.acceptedNodeIds)\n ? (args.acceptedNodeIds as string[]).filter((s) => typeof s === 'string')\n : null;\n const body = acceptedNodeIds\n ? { selection: { acceptedNodeIds } }\n : undefined;\n const res = await mcpApiRequest<{ ok: boolean; error?: string }>(\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/accept`,\n body,\n );\n return toolJson({\n ...res,\n workflowId,\n proposalId,\n partial: acceptedNodeIds !== null,\n });\n}\n\nasync function rejectProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const res = await mcpApiRequest<{ ok: boolean; error?: string }>(\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/reject`,\n );\n return toolJson({ ...res, workflowId, proposalId });\n}\n\nasync function revertProposal(args: Record<string, unknown>) {\n const workflowId = String(args.workflowId);\n const proposalId = String(args.proposalId);\n const res = await mcpApiRequest<{ ok: boolean; error?: string }>(\n 'POST',\n `/workflows/${workflowId}/proposals/${proposalId}/revert`,\n );\n return toolJson({ ...res, workflowId, proposalId });\n}\n\n// ── Diff payload shaper (shared shape with the CLI) ──────────────────────\n\nfunction buildDiffPayload(proposal: ProposalDetail, diff: SnapshotDiff) {\n return {\n proposal: {\n id: proposal.id,\n title: proposal.title,\n source: proposal.source,\n status: proposal.status,\n stale: proposal.status === 'stale',\n createdAt: proposal.createdAt,\n decidedAt: proposal.decidedAt,\n },\n summary: {\n addedNodes: diff.addedNodes.length,\n removedNodes: diff.removedNodes.length,\n changedNodes: diff.changedNodes.length,\n addedEdges: diff.addedEdges.length,\n removedEdges: diff.removedEdges.length,\n touchedCount: diff.touchedCount,\n isEmpty: diff.isEmpty,\n },\n nodes: {\n added: diff.addedNodes.map((n) => ({\n id: n.id,\n nodeType: n.nodeType,\n configJson: n.configJson,\n })),\n removed: diff.removedNodes.map((n) => ({\n id: n.id,\n nodeType: n.nodeType,\n configJson: n.configJson,\n })),\n changed: diff.changedNodes.map((c) => ({\n id: c.id,\n nodeType: c.nodeType,\n typeChanged: c.typeChanged,\n beforeType: c.beforeType,\n afterType: c.afterType,\n fieldChanges: c.fieldChanges,\n })),\n },\n edges: {\n added: diff.addedEdges.map((e) => ({\n sourceNodeId: e.sourceNodeId,\n targetNodeId: e.targetNodeId,\n edgeType: e.edgeType ?? null,\n })),\n removed: diff.removedEdges.map((e) => ({\n sourceNodeId: e.sourceNodeId,\n targetNodeId: e.targetNodeId,\n edgeType: e.edgeType ?? null,\n })),\n },\n };\n}\n","/**\n * MCP tools for workflow run results.\n *\n * Mirrors `canary workflow runs list`, `get`, and `diagnostics`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getWorkflowRunsToolDefinitions() {\n return [\n {\n name: 'canary_workflow_runs_list',\n description:\n 'List runs for a specific workflow with status, duration, and pagination.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n pageSize: {\n type: 'number',\n description: 'Page size (default: 10)',\n },\n mode: {\n type: 'string',\n enum: ['browser', 'api'],\n description: 'Filter by run mode',\n },\n },\n required: ['workflowId'],\n },\n },\n {\n name: 'canary_workflow_runs_get',\n description:\n 'Get workflow run detail including steps, status, duration, and error messages. Also serves as a status check for in-progress runs.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n runId: {\n type: 'string',\n description: 'The workflow run UUID',\n },\n },\n required: ['workflowId', 'runId'],\n },\n },\n {\n name: 'canary_workflow_runs_diagnostics',\n description:\n 'Get failure diagnostic for a workflow run. Returns AI-generated analysis if available, otherwise falls back to console logs and network requests.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n runId: {\n type: 'string',\n description: 'The workflow run UUID',\n },\n },\n required: ['workflowId', 'runId'],\n },\n },\n ];\n}\n\nexport async function handleWorkflowRunsTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_workflow_runs_list') {\n try {\n const workflowId = args.workflowId as string;\n const params = new URLSearchParams();\n params.set('page', String(args.page ?? 1));\n params.set('pageSize', String(args.pageSize ?? 10));\n if (args.mode) params.set('mode', String(args.mode));\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: { runs: unknown[] };\n pagination: unknown;\n }>('GET', `/workflows/${workflowId}/runs?${params}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, runs: result.data.runs, pagination: result.pagination });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_runs_get') {\n try {\n const workflowId = args.workflowId as string;\n const runId = args.runId as string;\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown;\n }>('GET', `/workflows/${workflowId}/runs/${runId}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_workflow_runs_diagnostics') {\n try {\n const workflowId = args.workflowId as string;\n const runId = args.runId as string;\n\n // Try AI failure diagnostic first\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown;\n }>('GET', `/workflows/${workflowId}/runs/${runId}/failure-diagnostic`);\n\n if (result.ok && result.data) {\n return toolJson({ ok: true, data: result.data });\n }\n\n // Fall back to raw diagnostics\n const rawResult = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n consoleLogs: unknown[];\n networkRequests: unknown[];\n }>('GET', `/workflows/${workflowId}/runs/${runId}/diagnostics`);\n\n if (!rawResult.ok) {\n return toolJson({ ok: true, data: null, message: 'No diagnostic available' });\n }\n\n return toolJson({\n ok: true,\n consoleLogs: rawResult.consoleLogs,\n networkRequests: rawResult.networkRequests,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","/**\n * MCP tools for test suite (workflow test execution) results and triggering.\n *\n * Mirrors `canary test-suite run`, `list`, `get`, `diagnostics`, and `steps`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getTestSuiteToolDefinitions() {\n return [\n {\n name: 'canary_test_suite_run',\n description:\n 'Trigger a test suite execution. Returns the suite ID and job ID. Use canary_test_suite_get to check results after triggering.',\n inputSchema: {\n type: 'object',\n properties: {\n tag: {\n type: 'string',\n description: 'Filter workflows by tag',\n },\n namePattern: {\n type: 'string',\n description: 'Filter workflows by name pattern (regex)',\n },\n propertyId: {\n type: 'string',\n description: 'Target a specific property by UUID',\n },\n environmentId: {\n type: 'string',\n description: 'Target a specific environment by UUID',\n },\n },\n },\n },\n {\n name: 'canary_test_suite_list',\n description:\n 'List recent test suite executions with pass/fail counts, ordered by most recent first.',\n inputSchema: {\n type: 'object',\n properties: {\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n pageSize: {\n type: 'number',\n description: 'Page size (default: 20)',\n },\n },\n },\n },\n {\n name: 'canary_test_suite_get',\n description:\n 'Get test suite detail including all individual test runs and their results.',\n inputSchema: {\n type: 'object',\n properties: {\n executionId: {\n type: 'string',\n description: 'The test execution UUID',\n },\n },\n required: ['executionId'],\n },\n },\n {\n name: 'canary_test_suite_diagnostics',\n description:\n 'Get AI-generated failure diagnostic for a specific workflow run, including root cause analysis and recommendations.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n runId: {\n type: 'string',\n description: 'The workflow run UUID',\n },\n },\n required: ['workflowId', 'runId'],\n },\n },\n {\n name: 'canary_test_suite_steps',\n description:\n 'Get the individual steps of a workflow run with their status, duration, and error messages.',\n inputSchema: {\n type: 'object',\n properties: {\n workflowId: {\n type: 'string',\n description: 'The workflow UUID',\n },\n runId: {\n type: 'string',\n description: 'The workflow run UUID',\n },\n },\n required: ['workflowId', 'runId'],\n },\n },\n ];\n}\n\nexport async function handleTestSuiteTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_test_suite_run') {\n try {\n const params = new URLSearchParams();\n if (args.tag) params.set('tag', String(args.tag));\n if (args.namePattern) params.set('namePattern', String(args.namePattern));\n\n const queryStr = params.toString();\n const path = `/workflows/test-runs${queryStr ? `?${queryStr}` : ''}`;\n\n const body: Record<string, string> = {};\n if (args.propertyId) body.propertyId = String(args.propertyId);\n if (args.environmentId) body.environmentId = String(args.environmentId);\n\n const data = await mcpApiRequest<{\n ok: boolean;\n suiteId?: string;\n jobId?: string;\n appUrl?: string;\n error?: string;\n }>('POST', path, body);\n\n if (!data.ok) {\n return toolJson({ ok: false, error: data.error ?? 'Unknown error' });\n }\n\n return toolJson({\n ok: true,\n suiteId: data.suiteId,\n jobId: data.jobId,\n appUrl: data.appUrl,\n message: `Test suite triggered. Use canary_test_suite_get or canary_test_suite_list to check results.`,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_test_suite_list') {\n try {\n const params = new URLSearchParams();\n params.set('page', String(args.page ?? 1));\n params.set('pageSize', String(args.pageSize ?? 20));\n params.set('sortBy', 'createdAt');\n params.set('sortOrder', 'desc');\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown[];\n pagination: unknown;\n }>('GET', `/workflows/test-executions?${params}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data, pagination: result.pagination });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_test_suite_get') {\n try {\n const executionId = args.executionId as string;\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n execution: unknown;\n testRuns: unknown[];\n }>('GET', `/workflows/test-executions/${executionId}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, execution: result.execution, testRuns: result.testRuns });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_test_suite_diagnostics') {\n try {\n const workflowId = args.workflowId as string;\n const runId = args.runId as string;\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown;\n }>('GET', `/workflows/${workflowId}/runs/${runId}/failure-diagnostic`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_test_suite_steps') {\n try {\n const workflowId = args.workflowId as string;\n const runId = args.runId as string;\n\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown;\n }>('GET', `/workflows/${workflowId}/runs/${runId}`);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","/**\n * MCP tools for credential management.\n *\n * Mirrors `canary credential list`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getCredentialToolDefinitions() {\n return [\n {\n name: 'canary_credential_list',\n description:\n 'List credentials in the current organization with their property and environment info.',\n inputSchema: {\n type: 'object',\n properties: {\n property: {\n type: 'string',\n description: 'Filter by property name or ID',\n },\n },\n },\n },\n ];\n}\n\nexport async function handleCredentialTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_credential_list') {\n try {\n const result = await mcpApiRequest<{\n ok: boolean;\n items: Array<{\n id: string;\n name: string;\n propertyId: string;\n propertyName?: string;\n propertyBaseUrl?: string;\n environmentId?: string | null;\n environmentName?: string | null;\n isEphemeral?: boolean;\n }>;\n }>('GET', '/org/credentials');\n\n let items = result.items ?? [];\n\n // Filter out ephemeral credentials\n items = items.filter((c) => !c.isEphemeral);\n\n // Apply property filter if provided\n if (args.property) {\n const filter = String(args.property).toLowerCase();\n items = items.filter(\n (c) =>\n c.propertyId === args.property ||\n (c.propertyName && c.propertyName.toLowerCase().includes(filter))\n );\n }\n\n return toolJson({ ok: true, credentials: items });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","/**\n * MCP tools for issue management.\n *\n * Mirrors `canary issues list` and `canary issues get`.\n *\n * @module\n */\n\nimport { mcpApiRequest } from '../api-client';\nimport { toolJson } from '../tool-helpers';\n\nexport function getIssueToolDefinitions() {\n return [\n {\n name: 'canary_issues_list',\n description:\n 'List and search issues in the current organization. Supports full-text search, severity/status filtering, and pagination.',\n inputSchema: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description: 'Full-text search query',\n },\n severity: {\n type: 'string',\n enum: ['low', 'medium', 'high', 'unknown'],\n description: 'Filter by severity level',\n },\n statuses: {\n type: 'string',\n description: 'Comma-separated status filter: open, closed, not_a_bug',\n },\n propertyId: {\n type: 'string',\n description: 'Filter by property UUID',\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n pageSize: {\n type: 'number',\n description: 'Page size (default: 25)',\n },\n },\n },\n },\n {\n name: 'canary_issues_get',\n description:\n 'Get issue detail with diagnostics, including console errors and network failures from the latest occurrence.',\n inputSchema: {\n type: 'object',\n properties: {\n issueId: {\n type: 'string',\n description: 'The issue UUID',\n },\n },\n required: ['issueId'],\n },\n },\n ];\n}\n\nexport async function handleIssueTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool === 'canary_issues_list') {\n try {\n const params = new URLSearchParams();\n if (args.search) params.set('search', String(args.search));\n if (args.severity) params.set('severity', String(args.severity));\n if (args.statuses) params.set('statuses', String(args.statuses));\n if (args.propertyId) params.set('propertyId', String(args.propertyId));\n if (args.page) params.set('page', String(args.page));\n if (args.pageSize) params.set('pageSize', String(args.pageSize));\n\n const qs = params.toString();\n const path = `/v2/issues${qs ? `?${qs}` : ''}`;\n const result = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: unknown[];\n pagination: unknown;\n }>('GET', path);\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error ?? 'Unknown error' });\n }\n\n return toolJson({ ok: true, data: result.data, pagination: result.pagination });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (tool === 'canary_issues_get') {\n try {\n const issueId = args.issueId as string;\n\n const detailResult = await mcpApiRequest<{\n ok: boolean;\n error?: string;\n data: {\n issue: { id: string; latestOccurrence?: { id: string } | null };\n occurrences: unknown[];\n commentCount: number;\n };\n }>('GET', `/v2/issues/${issueId}`);\n\n if (!detailResult.ok) {\n return toolJson({ ok: false, error: detailResult.error ?? 'Unknown error' });\n }\n\n const { issue } = detailResult.data;\n const occ = issue.latestOccurrence;\n\n let consoleErrors: unknown[] = [];\n let networkErrors: unknown[] = [];\n\n if (occ) {\n try {\n const [consoleRes, networkRes] = await Promise.all([\n mcpApiRequest<{ ok: boolean; data: unknown[] }>(\n 'GET',\n `/v2/issues/${issueId}/occurrences/${occ.id}/console-logs`\n ),\n mcpApiRequest<{ ok: boolean; data: unknown[] }>(\n 'GET',\n `/v2/issues/${issueId}/occurrences/${occ.id}/network-requests`\n ),\n ]);\n\n if (consoleRes.ok && Array.isArray(consoleRes.data)) {\n consoleErrors = (consoleRes.data as Array<{ type: string }>).filter(\n (e) => e.type === 'error'\n );\n }\n\n if (networkRes.ok && Array.isArray(networkRes.data)) {\n networkErrors = (networkRes.data as Array<{ status: number | null }>).filter(\n (e) => e.status === null || e.status === 0 || (e.status !== null && e.status >= 400)\n );\n }\n } catch {\n // Diagnostics are best-effort\n }\n }\n\n return toolJson({\n ok: true,\n ...detailResult.data,\n consoleErrors,\n networkErrors,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n return null;\n}\n","import type { ToolGroup } from '../types';\nimport { getWorkflowToolDefinitions, handleWorkflowTool } from './workflows';\nimport {\n getWorkflowProposalsToolDefinitions,\n handleWorkflowProposalsTool,\n} from './workflow-proposals';\nimport { getWorkflowRunsToolDefinitions, handleWorkflowRunsTool } from './workflow-runs';\nimport { getTestSuiteToolDefinitions, handleTestSuiteTool } from './test-suites';\nimport { getCredentialToolDefinitions, handleCredentialTool } from './credentials';\nimport { getIssueToolDefinitions, handleIssueTool } from './issues';\n\nexport const workflowsGroup: ToolGroup = {\n id: 'workflows',\n definitions: getWorkflowToolDefinitions,\n handle: (tool, args) => handleWorkflowTool(tool, args),\n};\n\nexport const workflowProposalsGroup: ToolGroup = {\n id: 'workflow-proposals',\n definitions: getWorkflowProposalsToolDefinitions,\n handle: (tool, args) => handleWorkflowProposalsTool(tool, args),\n};\n\nexport const workflowRunsGroup: ToolGroup = {\n id: 'workflow-runs',\n definitions: getWorkflowRunsToolDefinitions,\n handle: (tool, args) => handleWorkflowRunsTool(tool, args),\n};\n\nexport const testSuitesGroup: ToolGroup = {\n id: 'test-suites',\n definitions: getTestSuiteToolDefinitions,\n handle: (tool, args) => handleTestSuiteTool(tool, args),\n};\n\nexport const credentialsGroup: ToolGroup = {\n id: 'credentials',\n definitions: getCredentialToolDefinitions,\n handle: (tool, args) => handleCredentialTool(tool, args),\n};\n\nexport const issuesGroup: ToolGroup = {\n id: 'issues',\n definitions: getIssueToolDefinitions,\n handle: (tool, args) => handleIssueTool(tool, args),\n};\n\n/**\n * All HTTP-only groups (no daemon, no CLI auth state). Safe to use from any\n * MCP host that has an `apiToken` for the canary API.\n */\nexport const sharedGroups: ToolGroup[] = [\n workflowsGroup,\n workflowProposalsGroup,\n workflowRunsGroup,\n testSuitesGroup,\n credentialsGroup,\n issuesGroup,\n];\n","import { readBrandEnv } from '../brand.js';\n\nexport const DEFAULT_API_URL = 'https://api.trycanary.ai';\n\nexport function resolveApiUrl(): string {\n return readBrandEnv('CANARY_API_URL') ?? DEFAULT_API_URL;\n}\n","/**\n * MCP tool response helpers.\n *\n * @module\n */\n\nimport type { ToolResult } from '@chatsdet/browser-core';\n\nexport function toolText(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nexport function toolJson(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n\n/**\n * Convert a BrowserToolExecutor result to MCP SDK content blocks.\n */\nexport function formatMCPContent(result: ToolResult) {\n if (typeof result === 'string') {\n return { content: [{ type: 'text' as const, text: result }] };\n }\n\n // MCPContentResult with text and optional images\n const content: Array<{ type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string }> = [];\n\n if (result.text) {\n content.push({ type: 'text', text: result.text });\n }\n\n for (const img of result.images ?? []) {\n content.push({ type: 'image', data: img.data, mimeType: img.mimeType });\n }\n\n return { content };\n}\n","/**\n * Cloud-relay session tools for the MCP server.\n *\n * These tools proxy browser control through the cloud API via WebSocket.\n *\n * @module\n */\n\nimport { readStoredToken } from '../auth';\nimport { readBrandEnv } from '../brand.js';\nimport { LocalBrowserHost } from '../local-browser/host';\nimport type { LocalBrowserMode } from '../local-browser/protocol';\nimport { toolJson } from './tool-helpers';\n\ntype LocalBrowserStartInput = {\n mode?: LocalBrowserMode;\n cdpUrl?: string;\n headless?: boolean;\n storageStatePath?: string;\n instructions?: string;\n};\n\ntype LocalBrowserStopInput = {\n sessionId: string;\n};\n\ntype LocalBrowserStatusInput = {\n sessionId: string;\n};\n\ninterface BrowserSession {\n sessionId: string;\n host: LocalBrowserHost;\n startedAt: number;\n mode: LocalBrowserMode;\n}\n\n// Global browser sessions managed by MCP\nconst browserSessions = new Map<string, BrowserSession>();\n\nconst DEFAULT_API_URL = 'https://api.trycanary.ai';\n\nfunction resolveApiUrl(input?: string): string {\n return input ?? readBrandEnv('CANARY_API_URL') ?? DEFAULT_API_URL;\n}\n\nasync function resolveToken(): Promise<string> {\n const token = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken());\n if (!token) {\n throw new Error('Missing token. Run `canary login` first or set CANARY_API_TOKEN.');\n }\n return token;\n}\n\nexport function getSessionToolDefinitions() {\n return [\n {\n name: 'local_browser_start',\n description:\n 'Start a local browser session that connects to the cloud agent. The cloud agent can then control this browser to test local applications. Returns sessionId for tracking.',\n inputSchema: {\n type: 'object',\n properties: {\n mode: {\n type: 'string',\n enum: ['playwright', 'cdp'],\n description:\n \"Browser mode: 'playwright' for fresh browser, 'cdp' to connect to existing Chrome\",\n },\n cdpUrl: {\n type: 'string',\n description: \"CDP endpoint URL when mode is 'cdp' (e.g. http://localhost:9222)\",\n },\n headless: {\n type: 'boolean',\n description: 'Run browser headless (default: true for playwright mode)',\n },\n storageStatePath: {\n type: 'string',\n description: 'Path to Playwright storage state JSON for pre-authenticated sessions',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n },\n },\n },\n {\n name: 'local_browser_status',\n description: 'Check the status of a local browser session.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_stop',\n description: 'Stop a local browser session and close the browser.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_list',\n description: 'List all active local browser sessions.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'local_browser_run',\n description:\n 'Start a test run on an active local browser session. The cloud agent will control the local browser according to the instructions.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID from local_browser_start',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n startUrl: {\n type: 'string',\n description: 'Optional URL to navigate to before starting',\n },\n },\n required: ['sessionId', 'instructions'],\n },\n },\n ];\n}\n\nexport async function handleSessionTool(tool: string, args: Record<string, unknown>) {\n const token = await resolveToken();\n\n if (tool === 'local_browser_start') {\n const input = args as unknown as LocalBrowserStartInput;\n const apiUrl = resolveApiUrl();\n const mode = input.mode ?? 'playwright';\n\n const sessionResponse = await fetch(`${apiUrl}/local-browser/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n browserMode: mode,\n instructions: input.instructions ?? null,\n }),\n });\n\n if (!sessionResponse.ok) {\n const text = await sessionResponse.text();\n return toolJson({ ok: false, error: `Failed to create session: ${text}` });\n }\n\n const session = (await sessionResponse.json()) as {\n ok: boolean;\n sessionId: string;\n wsToken: string;\n expiresAt: string;\n };\n\n const host = new LocalBrowserHost({\n apiUrl,\n wsToken: session.wsToken,\n sessionId: session.sessionId,\n browserMode: mode,\n cdpUrl: input.cdpUrl,\n headless: input.headless ?? true,\n storageStatePath: input.storageStatePath,\n onLog: (level, message) => {\n if (level === 'error') {\n console.error(`[LocalBrowser] ${message}`);\n }\n },\n });\n\n host.start().catch((err) => {\n console.error('Failed to start local browser:', err);\n browserSessions.delete(session.sessionId);\n });\n\n browserSessions.set(session.sessionId, {\n sessionId: session.sessionId,\n host,\n startedAt: Date.now(),\n mode,\n });\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode,\n expiresAt: session.expiresAt,\n note: 'Browser session started. The cloud agent can now control this browser. Use local_browser_stop to end the session.',\n });\n }\n\n if (tool === 'local_browser_status') {\n const input = args as unknown as LocalBrowserStatusInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode: session.mode,\n startedAt: new Date(session.startedAt).toISOString(),\n uptimeMs: Date.now() - session.startedAt,\n });\n }\n\n if (tool === 'local_browser_stop') {\n const input = args as unknown as LocalBrowserStopInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n await session.host.stop();\n browserSessions.delete(input.sessionId);\n\n return toolJson({\n ok: true,\n sessionId: input.sessionId,\n note: 'Browser session stopped and browser closed.',\n });\n }\n\n if (tool === 'local_browser_list') {\n const sessions = Array.from(browserSessions.values()).map((s) => ({\n sessionId: s.sessionId,\n mode: s.mode,\n startedAt: new Date(s.startedAt).toISOString(),\n uptimeMs: Date.now() - s.startedAt,\n }));\n\n return toolJson({\n ok: true,\n count: sessions.length,\n sessions,\n });\n }\n\n if (tool === 'local_browser_run') {\n const input = args as unknown as {\n sessionId: string;\n instructions: string;\n startUrl?: string;\n };\n const apiUrl = resolveApiUrl();\n\n const session = browserSessions.get(input.sessionId);\n if (!session) {\n return toolJson({\n ok: false,\n error: 'Session not found locally. Make sure you started it with local_browser_start.',\n sessionId: input.sessionId,\n });\n }\n\n const response = await fetch(`${apiUrl}/local-browser/sessions/${input.sessionId}/run`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n instructions: input.instructions,\n startUrl: input.startUrl ?? null,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n return toolJson({ ok: false, error: `Failed to start run: ${text}` });\n }\n\n const result = (await response.json()) as { ok: boolean; jobId: string; sessionId: string };\n\n return toolJson({\n ok: true,\n jobId: result.jobId,\n sessionId: result.sessionId,\n note: 'Test run started. The cloud agent is now controlling your local browser. You can watch the browser to see the test in action.',\n });\n }\n\n return null; // Not handled\n}\n","/**\n * Browser MCP tool registration — daemon adapter.\n *\n * Thin layer that maps MCP tool calls to the session daemon,\n * ensuring the CLI gets the SAME semantic diff, snapshot formatting,\n * click validation, and recovery notices as the cloud agent.\n *\n * The daemon owns all browser sessions. MCP is just a protocol adapter.\n *\n * @module\n */\n\nimport { getBrowserToolDefinitionsWithLifecycle } from '@chatsdet/browser-core';\nimport {\n createSession,\n deleteSession,\n deleteAllSessions,\n callTool,\n resolveTargetSession,\n} from '../session/daemon-client.js';\nimport { formatMCPContent, toolJson, toolText } from './tool-helpers';\nimport { USER_PAUSED_ERROR } from '../session/types.js';\nimport type { ToolResult } from '@chatsdet/browser-core';\n\n/** Track the active session ID within this MCP server instance */\nlet activeSessionId: string | null = null;\n\n/**\n * Get tool definitions for browser MCP tools (including lifecycle).\n */\nexport function getBrowserMCPToolDefinitions() {\n return getBrowserToolDefinitionsWithLifecycle();\n}\n\n/**\n * Handle a browser tool call.\n * Returns null if the tool name is not a browser tool.\n */\nexport async function handleBrowserTool(name: string, args: Record<string, unknown>) {\n // Lifecycle tools\n if (name === 'browser_start') {\n try {\n const result = await createSession({\n headless: (args.headless as boolean) ?? false,\n storageStatePath: args.storageStatePath as string | undefined,\n });\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error });\n }\n\n activeSessionId = result.data!.id;\n return toolJson({\n ok: true,\n sessionId: activeSessionId,\n note: 'Browser started. You can now use browser_navigate, browser_click, and other browser tools.',\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (name === 'browser_stop') {\n try {\n if (activeSessionId) {\n await deleteSession(activeSessionId);\n activeSessionId = null;\n } else {\n // Stop all sessions if no specific one tracked\n await deleteAllSessions();\n }\n return toolJson({ ok: true, note: 'Browser stopped and cleaned up.' });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n // All other browser_* tools require an active session\n if (!name.startsWith('browser_')) return null;\n\n try {\n // Resolve target session: prefer tracked MCP session, then auto-resolve\n let sessionId = activeSessionId;\n if (!sessionId) {\n try {\n const target = await resolveTargetSession();\n sessionId = target.id;\n activeSessionId = sessionId;\n } catch {\n return toolJson({\n ok: false,\n error: 'No active browser session. Start one with browser_start first.',\n });\n }\n }\n\n // Strip 'browser_' prefix for the daemon tool name\n const toolName = name.replace(/^browser_/, '');\n const result = await callTool(sessionId, toolName, args);\n\n if (!result.ok) {\n // If session not found, clear tracking and report error\n if (result.error?.includes('not found')) {\n activeSessionId = null;\n }\n // User has taken control via the in-browser badge — return as\n // informational text rather than an error so Claude waits instead of retrying\n if (result.errorCode === USER_PAUSED_ERROR) {\n return toolText(result.error ?? 'User has taken control of the browser.');\n }\n return toolJson({ ok: false, error: result.error, tool: name });\n }\n\n // Convert daemon response back to ToolResult format for MCP formatting\n const toolResult: ToolResult = result.images?.length\n ? { text: result.text ?? '', images: result.images }\n : (result.text ?? '');\n\n return formatMCPContent(toolResult);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return toolJson({ ok: false, error: message, tool: name });\n }\n}\n","/**\n * MCP tool for device code OAuth login.\n *\n * Allows AI coding tools to trigger authentication without\n * requiring the user to run `canary login` in a separate terminal.\n *\n * @module\n */\n\nimport { ENV_URLS, envToProfile, resolveAppUrl, saveAuth } from '../auth';\nimport { openUrl, fetchOrgs, switchOrg } from '../login';\nimport type { StartResponse, PollResponse } from '../login';\nimport { resolveApiUrl } from './api-url';\nimport { toolJson } from './tool-helpers';\n\nexport function getLoginToolDefinitions() {\n return [\n {\n name: 'canary_login',\n description:\n 'Authenticate with Canary using the device code OAuth flow. Opens a browser window for the user to approve. ' +\n 'May take 30-120 seconds while waiting for the user to complete login. ' +\n 'Returns the verification URL and user code in case the browser does not open automatically.',\n inputSchema: {\n type: 'object',\n properties: {\n env: {\n type: 'string',\n enum: ['prod', 'dev', 'local'],\n description: 'Target environment (default: prod)',\n },\n org: {\n type: 'string',\n description:\n 'Organization name or ID to select if the user belongs to multiple orgs. If omitted, uses the default org.',\n },\n },\n },\n },\n ];\n}\n\nexport async function handleLoginTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool !== 'canary_login') return null;\n\n try {\n const env = args.env as string | undefined;\n const orgFlag = args.org as string | undefined;\n const envUrls = env ? ENV_URLS[env] : undefined;\n\n if (env && !envUrls) {\n return toolJson({ ok: false, error: `Unknown environment: ${env}. Valid: prod, dev, local` });\n }\n\n const apiUrl = envUrls?.api ?? resolveApiUrl();\n const appUrl = envUrls?.app ?? resolveAppUrl(apiUrl);\n\n // Step 1: Start device code flow\n const startRes = await fetch(`${apiUrl}/cli-login/start`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ appUrl }),\n });\n\n const startJson = (await startRes.json()) as StartResponse;\n if (!startRes.ok || !startJson.ok || !startJson.deviceCode || !startJson.userCode) {\n return toolJson({\n ok: false,\n error: `Login start failed: ${startJson.error ?? startRes.statusText}`,\n });\n }\n\n // Step 2: Open browser (non-fatal if it fails)\n if (startJson.verificationUrl) {\n try {\n openUrl(startJson.verificationUrl);\n } catch {\n // Browser open failed — user will need to open the URL manually\n }\n }\n\n // Step 3: Poll until approved/rejected/expired\n const intervalMs = (startJson.intervalSeconds ?? 3) * 1000;\n const expiresAt = startJson.expiresAt ? new Date(startJson.expiresAt).getTime() : null;\n\n let token: string | undefined;\n let initialOrgId: string | undefined;\n\n while (true) {\n if (expiresAt && Date.now() > expiresAt) {\n return toolJson({\n ok: false,\n error: 'Login code expired. Please try again.',\n userCode: startJson.userCode,\n verificationUrl: startJson.verificationUrl,\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n\n const pollRes = await fetch(`${apiUrl}/cli-login/poll`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ deviceCode: startJson.deviceCode }),\n });\n\n const pollJson = (await pollRes.json()) as PollResponse;\n if (!pollRes.ok || !pollJson.ok) {\n return toolJson({\n ok: false,\n error: `Login poll failed: ${pollJson.error ?? pollRes.statusText}`,\n });\n }\n\n if (pollJson.status === 'approved' && pollJson.accessToken) {\n token = pollJson.accessToken;\n initialOrgId = pollJson.orgId;\n break;\n }\n\n if (pollJson.status === 'rejected') {\n return toolJson({ ok: false, error: 'Login rejected by user.' });\n }\n\n if (pollJson.status === 'expired') {\n return toolJson({ ok: false, error: 'Login expired. Please try again.' });\n }\n }\n\n // Step 4: Handle org selection\n const orgsData = await fetchOrgs(apiUrl, token);\n const orgs = orgsData?.organizations ?? [];\n\n let finalToken = token;\n let finalOrgId = initialOrgId;\n let finalOrgName: string | undefined;\n\n if (orgs.length <= 1) {\n finalOrgName = orgs[0]?.name;\n } else if (orgFlag) {\n // Match by name (case-insensitive) or ID\n const selectedOrg = orgs.find(\n (o) => o.name.toLowerCase() === orgFlag.toLowerCase() || o.id === orgFlag\n );\n if (!selectedOrg) {\n // Save the default token so they're at least logged in\n const profileName = env ? envToProfile(env) : undefined;\n await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: orgs.find((o) => o.id === initialOrgId)?.name }, profileName);\n\n return toolJson({\n ok: false,\n error: `Organization \"${orgFlag}\" not found.`,\n loggedIn: true,\n currentOrg: orgs.find((o) => o.id === initialOrgId)?.name,\n availableOrgs: orgs.map((o) => ({ id: o.id, name: o.name, role: o.role })),\n });\n }\n\n if (selectedOrg.id !== initialOrgId) {\n const switchRes = await switchOrg(apiUrl, token, selectedOrg.id);\n if (!switchRes.ok || !switchRes.accessToken) {\n return toolJson({\n ok: false,\n error: `Failed to switch organization: ${switchRes.error ?? 'Unknown error'}`,\n });\n }\n finalToken = switchRes.accessToken;\n finalOrgId = switchRes.orgId;\n finalOrgName = switchRes.orgName;\n } else {\n finalOrgName = selectedOrg.name;\n }\n } else {\n // Multiple orgs, no flag — use default\n const defaultOrg = orgs.find((o) => o.id === initialOrgId);\n finalOrgName = defaultOrg?.name;\n }\n\n // Step 5: Save auth\n const profileName = env ? envToProfile(env) : undefined;\n await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: finalOrgName }, profileName);\n\n return toolJson({\n ok: true,\n message: 'Login successful. Token saved.',\n orgName: finalOrgName,\n orgId: finalOrgId,\n ...(orgs.length > 1\n ? { availableOrgs: orgs.map((o) => ({ id: o.id, name: o.name, role: o.role })) }\n : {}),\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","/**\n * MCP tool for upgrading the Canary CLI to the latest version.\n *\n * Adapts the `canary upgrade` command for MCP context where\n * stdio is the transport and process.exit() must be avoided.\n *\n * @module\n */\n\nimport fs from 'node:fs';\nimport { spawnSync } from 'node:child_process';\nimport process from 'node:process';\nimport { packageName } from '../brand.js';\nimport { clearUpdateCache } from '../update-check.js';\nimport { toolJson } from './tool-helpers';\n\ntype PackageManager = 'bun' | 'pnpm' | 'npm';\n\nfunction detectPackageManager(): PackageManager {\n try {\n const binPath = fs.realpathSync(process.argv[1]).replace(/\\\\/g, '/');\n if (binPath.includes('.bun/') || binPath.includes('/bun/')) return 'bun';\n if (binPath.includes('.pnpm/') || binPath.includes('/pnpm/')) return 'pnpm';\n } catch {\n // realpathSync can fail if symlink is broken\n }\n return 'npm';\n}\n\nconst UPGRADE_COMMANDS: Record<PackageManager, string[]> = {\n bun: ['bun', 'add', '-g', `${packageName}@latest`],\n pnpm: ['pnpm', 'add', '-g', `${packageName}@latest`],\n npm: ['npm', 'install', '-g', `${packageName}@latest`],\n};\n\nexport function getUpgradeToolDefinitions() {\n return [\n {\n name: 'canary_upgrade',\n description:\n 'Upgrade the Canary CLI to the latest version. ' +\n 'Detects the package manager (npm, bun, pnpm) and runs the appropriate global install command.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n ];\n}\n\nexport async function handleUpgradeTool(\n tool: string,\n _args: Record<string, unknown>\n) {\n if (tool !== 'canary_upgrade') return null;\n\n try {\n const pm = detectPackageManager();\n const cmd = UPGRADE_COMMANDS[pm];\n\n const result = spawnSync(cmd[0], cmd.slice(1), {\n stdio: ['pipe', 'pipe', 'pipe'],\n cwd: process.cwd(),\n timeout: 120_000,\n shell: process.platform === 'win32',\n windowsHide: true,\n });\n\n if (result.error) {\n return toolJson({\n ok: false,\n error: `Failed to run ${pm}: ${result.error.message}`,\n });\n }\n\n const stdout = result.stdout?.toString().trim() ?? '';\n const stderr = result.stderr?.toString().trim() ?? '';\n\n if (result.status !== 0) {\n return toolJson({\n ok: false,\n error: `Upgrade failed (exit code ${result.status}).`,\n output: stderr || stdout,\n });\n }\n\n await clearUpdateCache();\n\n return toolJson({\n ok: true,\n message: `Successfully upgraded ${packageName} to the latest version.`,\n packageManager: pm,\n output: stdout || undefined,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","/**\n * MCP server instructions for Claude Cowork.\n *\n * These instructions are returned in the InitializeResult and injected\n * into the agent's system prompt before any tools or user messages.\n * They teach Cowork how to use the canary toolset effectively.\n *\n * @module\n */\n\nexport const CANARY_MCP_INSTRUCTIONS = `\n# Canary — AI-Powered QA Platform\n\nYou have access to the Canary MCP tools for testing web applications, managing test workflows, and investigating issues. This guide teaches you how to use them effectively.\n\n## Authentication & Defaults\n\n- **Always use env: \"prod\"** when calling canary_login unless the user explicitly asks for dev or local.\n- After login, if multiple organizations are available, ask the user which one to use. Pass the org name via the \\`org\\` parameter.\n- To switch orgs later, call canary_login again with the \\`org\\` parameter — no need to re-authenticate.\n\n## Browser Sessions — Exploring Apps\n\nUse browser tools to interactively explore and test web applications. The workflow is:\n\n### Starting a Session\n\n1. **List credentials first:** Call \\`canary_credential_list\\` to see available credentials with their property names and base URLs.\n2. **Pick the right credential:**\n - Prefer the **default credential** (\\`isDefault: true\\`)\n - **Never** use a credential with \"local\" or \"manual\" in the name — these are for local development and won't work in deployed environments\n - If multiple non-local credentials exist and you're unsure, ask the user\n3. **Start the browser with a credential:** Use \\`browser_start\\` to launch a headed browser, then load the credential's storage state. Or use the session tools (\\`local_browser_start\\`) for cloud-relay sessions.\n\n### The Core Interaction Loop\n\n**snapshot → read → act → snapshot → verify**\n\nThis is the fundamental pattern. Never skip the verification snapshot.\n\n1. **Snapshot the page** with \\`browser_snapshot\\` to see what's on screen. The accessibility tree shows elements with refs like \\`[ref=e15]\\`.\n2. **Find elements efficiently** using the \\`search\\` parameter: \\`browser_snapshot\\` with \\`search: \"Submit\"\\` or \\`search: \"Email|Password\"\\` (OR-matched, case-insensitive).\n3. **Interact using refs** from the snapshot — click, type, fill, select. Always use refs, not coordinates. Fall back to coordinate-based clicking only when refs fail (overlays, canvas elements).\n4. **Snapshot again** after every action to verify it succeeded. Never assume an action worked.\n5. **Check for errors** after form submissions or navigation — look at the page content for error messages, and use console/network tools if available.\n\n### Tips\n\n- Use \\`search\\` to locate elements quickly rather than scanning the full accessibility tree.\n- Use \\`browser_snapshot\\` with \\`mode: \"screenshot\"\\` for visual verification when you need to see the actual rendering.\n- Wait for async operations (API calls, animations) before snapshotting — look for loading indicators.\n- Group related observations: take one snapshot and read the full tree rather than searching for every element individually.\n\n## Building Tests — Workflow Authoring\n\nAfter exploring an app via browser session, you can persist what you discovered as a reusable test workflow. The flow is: **explore → author → create**.\n\n### Step 1: Gather Credential Info\n\nCall \\`canary_credential_list\\` to get the credential UUID. You'll need it for the login node.\n- Always use \\`credentialId\\` (UUID) — never just the credential name\n- Set both \\`credentialId\\` and \\`credentialName\\` in the login node\n\n### Step 2: Design the Workflow\n\nA workflow is a directed graph of **nodes** connected by **edges**.\n\n#### Node Types\n\n| Type | Purpose | Required configJson |\n|------|---------|-------------------|\n| \\`login\\` | Authenticate with a credential | \\`credentialId\\`, \\`credentialName\\` |\n| \\`navigate\\` | Go to a URL | \\`pageUrl\\`, \\`pageTitle\\` |\n| \\`action\\` | Interact with elements | \\`customActionTitle\\`, \\`playbookSteps\\`, optionally \\`inlineAssertions\\` |\n| \\`assertion\\` | Standalone page verification | \\`condition\\` text |\n| \\`end\\` | Terminal node | (none) |\n\n#### Action Node Guidelines\n\n- Every action node **must** have a \\`customActionTitle\\` — a short (3-8 word) human-readable title describing the step (e.g., \"Create a new invoice\", \"Fill registration form\")\n- **Group related actions** into a single action node (one node per logical step, not per click)\n- **Prefer inline assertions** on action nodes over separate assertion nodes. Add \\`inlineAssertions\\` to verify outcomes right after the action. **Do not author an \\`id\\` field** — the server stamps a UUID on persist:\n \\`\\`\\`json\n {\n \"inlineAssertions\": [\n {\n \"condition\": \"Success message 'Invoice created' is visible\",\n \"severity\": \"fail\"\n }\n ]\n }\n \\`\\`\\`\n- Use separate \\`assertion\\` nodes only for standalone page-level verifications (e.g., initial page state before any action)\n\n#### Playbook Steps (inside action nodes)\n\nPlaybook steps describe what to do within an action node. Each step has:\n- \\`order\\`: sequence number (1, 2, 3...)\n- \\`action\\`: what to do — \\`click\\`, \\`fill\\`, \\`fill_form\\`, \\`select\\`, \\`navigate\\`, \\`wait\\`, \\`scroll\\`, \\`hover\\`, \\`upload\\`, \\`verify\\`, \\`press_key\\`, \\`drag\\`, \\`resize\\`, \\`capture\\`, \\`extract_table\\`, \\`python_execute\\`, \\`verify_download\\`, \\`verify_download_content\\`, \\`screenshot\\`, \\`agent_loop\\`\n- \\`target\\`: **semantic description** from the accessibility tree — button text, field labels, placeholder text. Describe as a human would: \"Submit button\", \"Email input field\", \"Status dropdown\". **Never use refs, CSS selectors, or XPaths.**\n- \\`params\\`: for \\`fill\\` actions, include \\`{ \"value\": \"...\" }\\`\n\nEach playbook step maps to at most one recorded browser tool call. If the user intent took multiple clicks, fills, key presses, or assertions, write multiple playbook steps instead of bundling them. Do not use \\`other\\`; if no concrete browser-tool-backed action fits, omit that diagnostic observation from \\`playbookSteps\\`. Use \\`click\\` for switches, checkboxes, and click-to-focus behavior. Use \\`press_key\\` with \\`{ \"key\": \"Escape\" }\\` or an explicit \\`click\\` to close popovers and panels; there is no \\`dismiss\\`, \\`toggle\\`, \\`focus\\`, or \\`handle_native_dialog\\` action.\n\n### Macros — Always Prefer Over Hardcoded Data\n\nMacros generate fresh values each run, preventing flaky tests from stale or colliding data. **Never hardcode emails, names, phone numbers, or dates when a macro exists.**\n\n| Macro | Output | Example |\n|-------|--------|---------|\n| \\`$EMAIL()\\` | Unique test email | \\`test-xk9mq2@example-test.com\\` |\n| \\`$FIRST_NAME()\\` | Random first name | \\`Jordan\\` |\n| \\`$LAST_NAME()\\` | Random last name | \\`Chen\\` |\n| \\`$PHONE()\\` | US phone (555 prefix) | \\`+1-555-382-7491\\` |\n| \\`$UUID()\\` | Random UUID v4 | \\`a1b2c3d4-...\\` |\n| \\`$RANDOM_INT(min, max)\\` | Random integer | \\`$RANDOM_INT(100,999)\\` → \\`427\\` |\n| \\`$RANDOM_STRING(length)\\` | Alphanumeric string | \\`$RANDOM_STRING(8)\\` → \\`xK9mQ3bR\\` |\n| \\`$TODAY()\\` | Current date (YYYY-MM-DD) | \\`2026-04-06\\` |\n| \\`$DATE(days)\\` | Date offset from today | \\`$DATE(-7)\\` → last week |\n| \\`$NOW()\\` | ISO 8601 timestamp | \\`2026-04-06T14:30:00.000Z\\` |\n| \\`$TIMESTAMP()\\` | Unix milliseconds | \\`1771520400000\\` |\n| \\`$SEQUENCE(\"name\")\\` | Auto-incrementing per run | \\`1\\`, \\`2\\`, \\`3\\`... |\n\nMacros combine inline: \\`\"QA Test $FIRST_NAME() $LAST_NAME()\"\\`, \\`\"order-$RANDOM_STRING(6)\"\\`\n\n**Prefix test data with \"QA Test\"** for identifiability.\n\n### Step 3: Create the Workflow\n\nUse \\`canary_workflow_sync\\` for existing workflows or construct the full workflow JSON and create via the API. Then verify with \\`canary_workflow_get\\`.\n\n### Example Workflow JSON\n\n\\`\\`\\`json\n{\n \"name\": \"Verify user can create an invoice\",\n \"description\": \"Tests the invoice creation flow end-to-end\",\n \"nodes\": [\n {\n \"nodeType\": \"login\",\n \"configJson\": {\n \"credentialId\": \"4f6db838-16be-49e8-8887-8d0be1c83a87\",\n \"credentialName\": \"QA User\"\n }\n },\n {\n \"nodeType\": \"navigate\",\n \"configJson\": { \"pageUrl\": \"/invoices\", \"pageTitle\": \"Invoices\" }\n },\n {\n \"nodeType\": \"action\",\n \"configJson\": {\n \"customActionTitle\": \"Create a new invoice\",\n \"actionDescription\": \"Fill out the new invoice form and save\",\n \"playbookSteps\": [\n { \"order\": 1, \"action\": \"click\", \"target\": \"New Invoice button\" },\n { \"order\": 2, \"action\": \"fill\", \"target\": \"Client name field\", \"params\": { \"value\": \"QA Test $FIRST_NAME()\" } },\n { \"order\": 3, \"action\": \"fill\", \"target\": \"Amount field\", \"params\": { \"value\": \"$RANDOM_INT(100,999)\" } },\n { \"order\": 4, \"action\": \"click\", \"target\": \"Save button\" }\n ],\n \"inlineAssertions\": [\n {\n \"condition\": \"Success message 'Invoice created' is visible and the new invoice appears in the list\",\n \"severity\": \"fail\"\n }\n ]\n }\n }\n ]\n}\n\\`\\`\\`\n\n## Managing Workflows\n\n- **canary_workflow_list** — Browse existing tests. Filter by \\`status\\` (draft = editable, approved = human-verified), \\`flowType\\` (standard/setup/seed/teardown), or \\`search\\` by name. Suite inclusion is the separate promotion axis (promote/pause); reliability is tracked separately by the workflow's \\`health\\`.\n- **canary_workflow_get** — Inspect a test's full definition: nodes, edges, playbook steps, assertions.\n- **canary_workflow_patch** — Update name, description, status, or flow type. Only provided fields change.\n- **canary_workflow_run** — Trigger execution. Returns a \\`runId\\` — use it to track progress.\n- **canary_workflow_sync** — Atomically replace all nodes and edges. Automatically snapshots current state first so changes are reversible. Read the current DAG with \\`canary_workflow_get\\` before syncing.\n\n## Monitoring Runs & Debugging Failures\n\nAfter triggering a workflow run, monitor and debug with:\n\n- **canary_workflow_runs_list** — Recent runs for a workflow with status and duration.\n- **canary_workflow_runs_get** — Detailed run view: step-by-step status, duration, errors. Also works for in-progress runs to check status.\n- **canary_workflow_runs_diagnostics** — AI-generated failure analysis. Returns root cause and recommendations. Falls back to raw console logs and network requests if no AI analysis is available.\n\n### Regression Suite\n\n- **canary_test_suite_run** — Trigger a regression suite execution. Returns suiteId for tracking. Use canary_test_suite_list or canary_test_suite_get to check results.\n- **canary_test_suite_list** — Recent regression suite executions with pass/fail counts.\n- **canary_test_suite_get** — Individual test results within a suite execution.\n- **canary_test_suite_diagnostics** — Failure diagnostics for a specific test in a suite run.\n- **canary_test_suite_steps** — Step-by-step breakdown of a test run within a suite.\n\n## Investigating Issues\n\nIssues are bugs discovered by Canary during test runs.\n\n- **canary_issues_list** — Search and filter issues by severity (\\`low\\`/\\`medium\\`/\\`high\\`), status (\\`open\\`/\\`closed\\`/\\`not_a_bug\\`), or property. Supports full-text search.\n- **canary_issues_get** — Full issue detail including console errors and network failures from the latest occurrence. Use this to understand what went wrong.\n\n## API Sequences (API-only workflows)\n\nFor APIs that need deterministic, browser-free smoke testing — composed of ordered HTTP calls that chain outputs into inputs.\n\n- **Create** with the same command as any workflow, with \\`--api-only\\`:\n \\`canary workflow create --api-only --name \"<n>\" --sequence-from-file seq.json\\`\n Returns \\`{ workflowId, apiSequenceId, nodeId }\\`. No \\`--property\\` — api-sequences are org-scoped.\n- **Inspect runs** with the same command as any runs, with \\`--side api\\` (or \\`--side all\\` for both):\n \\`canary workflow runs list <wf> --side api\\`\n \\`canary workflow runs get <wf> <runId>\\`\n- **Edit the sequence itself** via \\`canary workflow api-sequence <verb>\\`:\n - \\`get <wf>\\` — dump config + steps\n - \\`update <wf> --from-file seq.json\\` — replace config\n - \\`execute <wf>\\` — run it\n - \\`generate <wf> [--prompt \"...\"]\\` — AI-draft a config, then refine with \\`update\\`\n- **Discover endpoints** before composing steps:\n \\`canary api-catalog sources list\\`\n \\`canary api-catalog endpoints list --search <q>\\`\n \\`canary api-catalog endpoints create --from-file ep.json\\` (add a one-off)\n- **Read the reference first** for the config/step shape and template syntax:\n \\`canary workflow guide api-sequences\\`\n\nTemplates in step fields use \\`{{stepId.response.path}}\\` to reference prior-step outputs and \\`$MACRO()\\` for dynamic test data (same macros as browser workflows).\n\n## Common Workflows\n\n### \"Let's explore the app\"\n1. \\`canary_login\\` (env: prod) → switch to the right org\n2. \\`canary_credential_list\\` → find the right credential\n3. \\`browser_start\\` → launch browser\n4. Load credential and navigate to the app\n5. Snapshot, interact, explore\n\n### \"Write a test for this feature\"\n1. Explore the feature via browser (above workflow)\n2. \\`canary_credential_list\\` → get credentialId\n3. Construct workflow JSON with nodes, edges, playbook steps, macros\n4. Create or sync the workflow\n5. \\`canary_workflow_run\\` → execute it\n6. \\`canary_workflow_runs_get\\` → verify it passes\n\n### \"Why did this test fail?\"\n1. \\`canary_workflow_runs_list\\` → find the failed run\n2. \\`canary_workflow_runs_get\\` → see which step failed\n3. \\`canary_workflow_runs_diagnostics\\` → AI analysis of the failure\n4. If needed, open a browser session to reproduce and investigate\n\n### \"What issues have been found?\"\n1. \\`canary_issues_list\\` → browse open issues\n2. \\`canary_issues_get\\` → deep dive with console/network errors\n`.trim();\n"],"mappings":"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","names":["result","toolText","toolJson","DEFAULT_API_URL","resolveApiUrl","toolJson","toolJson","toolText","toolJson","profileName","toolJson","toolText"]}