@runcofactor/cli 0.10.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-22LMP5PX.js +255 -0
- package/dist/account-22LMP5PX.js.map +1 -0
- package/dist/{api-catalog-GFGCLVS4.js → api-catalog-WTFQNLK6.js} +5 -4
- package/dist/{api-catalog-GFGCLVS4.js.map → api-catalog-WTFQNLK6.js.map} +1 -1
- package/dist/{attachment-SJC7D7FY.js → attachment-U3NKVPEY.js} +5 -4
- package/dist/{attachment-SJC7D7FY.js.map → attachment-U3NKVPEY.js.map} +1 -1
- package/dist/augmentor-5GMNAX4M.js +198 -0
- package/dist/augmentor-5GMNAX4M.js.map +1 -0
- package/dist/{auth-EN6NQCJY.js → auth-VQG2CDUD.js} +3 -2
- package/dist/{chunk-A4OFTUVV.js → chunk-3X3NW7QA.js} +7 -4
- package/dist/chunk-3X3NW7QA.js.map +1 -0
- package/dist/{chunk-N7HFALX3.js → chunk-46IUJXSD.js} +2 -2
- package/dist/{chunk-IMPZAX6L.js → chunk-5GD47G2D.js} +37 -1
- package/dist/{chunk-IMPZAX6L.js.map → chunk-5GD47G2D.js.map} +1 -1
- package/dist/{chunk-B2VISN2V.js → chunk-7VMO2WOZ.js} +238 -68
- package/dist/chunk-7VMO2WOZ.js.map +1 -0
- package/dist/{chunk-QFDOWABX.js → chunk-CMGI7UZD.js} +6 -3
- package/dist/chunk-CMGI7UZD.js.map +1 -0
- package/dist/{chunk-XQXVG7RA.js → chunk-FNPMWDUQ.js} +3 -3
- package/dist/chunk-G4UYGRZR.js +2 -0
- package/dist/{chunk-I4QLI3JO.js → chunk-HDFYUFBI.js} +2 -2
- package/dist/chunk-JMJVGMXI.js +92 -0
- package/dist/chunk-JMJVGMXI.js.map +1 -0
- package/dist/{chunk-SJJW77WN.js → chunk-JYGNMKZ5.js} +129 -38
- package/dist/chunk-JYGNMKZ5.js.map +1 -0
- package/dist/{chunk-52IO7ACJ.js → chunk-KCHKFYVX.js} +68 -10
- package/dist/{chunk-52IO7ACJ.js.map → chunk-KCHKFYVX.js.map} +1 -1
- package/dist/{chunk-ZD3KHESI.js → chunk-KRWRUU6R.js} +27 -7
- package/dist/chunk-KRWRUU6R.js.map +1 -0
- package/dist/{chunk-CLAWT7BJ.js → chunk-NHTEKEYE.js} +3 -3
- package/dist/{chunk-WOHL4FTB.js → chunk-PRBRSIZP.js} +16 -10
- package/dist/chunk-PRBRSIZP.js.map +1 -0
- package/dist/{chunk-GKY2KXO5.js → chunk-UETBLPKM.js} +154 -37
- package/dist/chunk-UETBLPKM.js.map +1 -0
- package/dist/{chunk-4PNOV7OV.js → chunk-VGYN2KU2.js} +9284 -1421
- package/dist/chunk-VGYN2KU2.js.map +1 -0
- package/dist/{chunk-Q4BO4Z5V.js → chunk-XJ5YYYGC.js} +4 -4
- package/dist/{credential-COLTBV6D.js → credential-E6KUHRGU.js} +24 -20
- package/dist/credential-E6KUHRGU.js.map +1 -0
- package/dist/{credential-template-EEPYFG7R.js → credential-template-4GPOPBGD.js} +30 -28
- package/dist/credential-template-4GPOPBGD.js.map +1 -0
- package/dist/{debug-workflow-KOVH5GOP.js → debug-workflow-XCLCY6S7.js} +5 -4
- package/dist/{debug-workflow-KOVH5GOP.js.map → debug-workflow-XCLCY6S7.js.map} +1 -1
- package/dist/{docs-3SSORHB5.js → docs-COCZYMW6.js} +95 -10
- package/dist/docs-COCZYMW6.js.map +1 -0
- package/dist/{doctor-OTSIWV6G.js → doctor-ERIVTCQS.js} +9 -5
- package/dist/doctor-ERIVTCQS.js.map +1 -0
- package/dist/environment-7Y4BV6XY.js +221 -0
- package/dist/environment-7Y4BV6XY.js.map +1 -0
- package/dist/{feature-flag-T2LRZME3.js → feature-flag-MHONEX6T.js} +164 -16
- package/dist/feature-flag-MHONEX6T.js.map +1 -0
- package/dist/index.js +123 -58
- package/dist/index.js.map +1 -1
- package/dist/{init-TGWRECT2.js → init-OROOM4HF.js} +5 -4
- package/dist/{init-TGWRECT2.js.map → init-OROOM4HF.js.map} +1 -1
- package/dist/{install-DXSNWZKO.js → install-OJFXHY6U.js} +7 -7
- package/dist/{issues-XIZOPX6T.js → issues-32GONR6C.js} +5 -4
- package/dist/{issues-XIZOPX6T.js.map → issues-32GONR6C.js.map} +1 -1
- package/dist/{knobs-NBINZIUB.js → knobs-UQGGY3CP.js} +7 -5
- package/dist/knobs-UQGGY3CP.js.map +1 -0
- package/dist/{list-3TDHK637.js → list-ZMIKEC5P.js} +5 -4
- package/dist/{list-3TDHK637.js.map → list-ZMIKEC5P.js.map} +1 -1
- package/dist/{local-HICVD6PU.js → local-PUD24GGQ.js} +7 -6
- package/dist/{local-HICVD6PU.js.map → local-PUD24GGQ.js.map} +1 -1
- package/dist/{login-UOIUXVUK.js → login-BSO7YX2D.js} +5 -4
- package/dist/{login-UOIUXVUK.js.map → login-BSO7YX2D.js.map} +1 -1
- package/dist/{mcp-54IJEOUA.js → mcp-4LS7OJUT.js} +24 -25
- package/dist/mcp-4LS7OJUT.js.map +1 -0
- package/dist/{pdf-extract-ABWV3L5X.js → pdf-extract-YHE54XU4.js} +2 -2
- package/dist/product-3JKSJCBC.js +346 -0
- package/dist/product-3JKSJCBC.js.map +1 -0
- package/dist/{property-UXLOLPTD.js → property-K5DBL4UE.js} +76 -4
- package/dist/property-K5DBL4UE.js.map +1 -0
- package/dist/{psql-BYUUNLGG.js → psql-PQFUFTSE.js} +3 -2
- package/dist/{psql-BYUUNLGG.js.map → psql-PQFUFTSE.js.map} +1 -1
- package/dist/{record-4TR2UIIS.js → record-EIIYLFJ4.js} +16 -17
- package/dist/record-EIIYLFJ4.js.map +1 -0
- package/dist/{redis-35VBUYW7.js → redis-BU36EZZI.js} +3 -2
- package/dist/redis-BU36EZZI.js.map +1 -0
- package/dist/{release-OOLTUBUT.js → release-LYC2P7DZ.js} +5 -4
- package/dist/{release-OOLTUBUT.js.map → release-LYC2P7DZ.js.map} +1 -1
- package/dist/{sandbox-XGSUU6G7.js → sandbox-CKHXXZHU.js} +55 -10
- package/dist/sandbox-CKHXXZHU.js.map +1 -0
- package/dist/{scenarios-GWLJEGHA.js → scenarios-2XJ2G3KR.js} +5 -4
- package/dist/{scenarios-GWLJEGHA.js.map → scenarios-2XJ2G3KR.js.map} +1 -1
- package/dist/{session-MYFNZPRP.js → session-UTOD5ZYH.js} +77 -10
- package/dist/session-UTOD5ZYH.js.map +1 -0
- package/dist/{skill-KM34LDMO.js → skill-GMAERMQL.js} +220 -70
- package/dist/skill-GMAERMQL.js.map +1 -0
- package/dist/skills/debug-run/SKILL.md +40 -23
- package/dist/skills/debug-run/history/1.2.0.md +262 -0
- package/dist/skills/debug-run/history/1.3.0.md +273 -0
- package/dist/skills/debug-run/history/1.3.1.md +279 -0
- package/dist/skills/debug-run/version.json +1 -1
- package/dist/skills/optimize-cache/SKILL.md +233 -0
- package/dist/{spec-RA3CFEKG.js → spec-2NP36U3Y.js} +54 -25
- package/dist/spec-2NP36U3Y.js.map +1 -0
- package/dist/{src-LB4HBTJQ.js → src-4T6GHXVO.js} +19 -11
- package/dist/src-4T6GHXVO.js.map +1 -0
- package/dist/{src-N3TPKGTY.js → src-CG52HEE7.js} +10 -7
- package/dist/{src-UVDX5UP6.js → src-PK5OZXCM.js} +4 -2
- package/dist/src-UEOOC425.js +5941 -0
- package/dist/src-UEOOC425.js.map +1 -0
- package/dist/{start-PSEQSQA3.js → start-3C7EEFW2.js} +5 -4
- package/dist/{start-PSEQSQA3.js.map → start-3C7EEFW2.js.map} +1 -1
- package/dist/{tag-YY6YAABQ.js → tag-JSHOMLBR.js} +6 -5
- package/dist/{task-IQC3YR5K.js → task-YGWVYTBJ.js} +5 -4
- package/dist/{task-IQC3YR5K.js.map → task-YGWVYTBJ.js.map} +1 -1
- package/dist/{test-suite-DZNJFXDW.js → test-suite-LI7ZH367.js} +12 -7
- package/dist/{test-suite-DZNJFXDW.js.map → test-suite-LI7ZH367.js.map} +1 -1
- package/dist/trace-UMLOSIIR.js +16 -0
- package/dist/{triage-ORG45R5W.js → triage-ZWJG4NBJ.js} +6 -5
- package/dist/triage-ZWJG4NBJ.js.map +1 -0
- package/dist/{upgrade-L2VYMP2V.js → upgrade-S7CGEK6H.js} +3 -3
- package/dist/{workflow-XYFH5LTP.js → workflow-T4HSAOGW.js} +316 -241
- package/dist/workflow-T4HSAOGW.js.map +1 -0
- package/dist/{workflow-cache-NQJQFWMV.js → workflow-cache-XVEZ36KF.js} +140 -7
- package/dist/workflow-cache-XVEZ36KF.js.map +1 -0
- package/dist/{workflow-debug-BGD4UIXU.js → workflow-debug-T2BULXZ7.js} +9 -8
- package/dist/{workflow-debug-BGD4UIXU.js.map → workflow-debug-T2BULXZ7.js.map} +1 -1
- package/dist/{workflow-proposals-MTUDX46O.js → workflow-proposals-XXEZICN2.js} +5 -6
- package/dist/workflow-proposals-XXEZICN2.js.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-4PNOV7OV.js.map +0 -1
- package/dist/chunk-A4OFTUVV.js.map +0 -1
- package/dist/chunk-B2VISN2V.js.map +0 -1
- package/dist/chunk-GKY2KXO5.js.map +0 -1
- package/dist/chunk-JICSYFRJ.js +0 -46
- package/dist/chunk-JICSYFRJ.js.map +0 -1
- package/dist/chunk-QFDOWABX.js.map +0 -1
- package/dist/chunk-SJJW77WN.js.map +0 -1
- package/dist/chunk-WOHL4FTB.js.map +0 -1
- package/dist/chunk-ZD3KHESI.js.map +0 -1
- package/dist/credential-COLTBV6D.js.map +0 -1
- package/dist/credential-template-EEPYFG7R.js.map +0 -1
- package/dist/docs-3SSORHB5.js.map +0 -1
- package/dist/doctor-OTSIWV6G.js.map +0 -1
- package/dist/feature-flag-T2LRZME3.js.map +0 -1
- package/dist/knobs-NBINZIUB.js.map +0 -1
- package/dist/mcp-54IJEOUA.js.map +0 -1
- package/dist/property-UXLOLPTD.js.map +0 -1
- package/dist/record-4TR2UIIS.js.map +0 -1
- package/dist/redis-35VBUYW7.js.map +0 -1
- package/dist/sandbox-XGSUU6G7.js.map +0 -1
- package/dist/session-MYFNZPRP.js.map +0 -1
- package/dist/skill-KM34LDMO.js.map +0 -1
- package/dist/spec-RA3CFEKG.js.map +0 -1
- package/dist/src-LB4HBTJQ.js.map +0 -1
- package/dist/trace-HXIW7U2D.js +0 -14
- package/dist/workflow-XYFH5LTP.js.map +0 -1
- package/dist/workflow-cache-NQJQFWMV.js.map +0 -1
- package/dist/workflow-proposals-MTUDX46O.js.map +0 -1
- /package/dist/{auth-EN6NQCJY.js.map → auth-VQG2CDUD.js.map} +0 -0
- /package/dist/{chunk-N7HFALX3.js.map → chunk-46IUJXSD.js.map} +0 -0
- /package/dist/{chunk-XQXVG7RA.js.map → chunk-FNPMWDUQ.js.map} +0 -0
- /package/dist/{pdf-extract-ABWV3L5X.js.map → chunk-G4UYGRZR.js.map} +0 -0
- /package/dist/{chunk-I4QLI3JO.js.map → chunk-HDFYUFBI.js.map} +0 -0
- /package/dist/{chunk-CLAWT7BJ.js.map → chunk-NHTEKEYE.js.map} +0 -0
- /package/dist/{chunk-Q4BO4Z5V.js.map → chunk-XJ5YYYGC.js.map} +0 -0
- /package/dist/{install-DXSNWZKO.js.map → install-OJFXHY6U.js.map} +0 -0
- /package/dist/{src-N3TPKGTY.js.map → pdf-extract-YHE54XU4.js.map} +0 -0
- /package/dist/{src-UVDX5UP6.js.map → src-CG52HEE7.js.map} +0 -0
- /package/dist/{tag-YY6YAABQ.js.map → src-PK5OZXCM.js.map} +0 -0
- /package/dist/{trace-HXIW7U2D.js.map → tag-JSHOMLBR.js.map} +0 -0
- /package/dist/{triage-ORG45R5W.js.map → trace-UMLOSIIR.js.map} +0 -0
- /package/dist/{upgrade-L2VYMP2V.js.map → upgrade-S7CGEK6H.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/issues.ts"],"sourcesContent":["/**\n * CLI Issues Management\n *\n * Search, list, and view issues with full diagnostics from the terminal.\n */\n\nimport process from 'node:process';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest, getApplicationIdArg } from './cli-helpers.js';\n\n/* ── Types ────────────────────────────────────────────────────────────── */\n\ntype IssueCategorySummary = {\n id: string;\n key: string;\n label: string;\n description: string | null;\n instructions: string | null;\n};\n\ntype IssueAssignee = {\n id: string;\n displayName: string | null;\n primaryEmail: string | null;\n};\n\ntype FailureDiagnostic = {\n category: string;\n confidence: number;\n title: string;\n analysis: string;\n recommendation: string;\n smokingGun?: { description: string; detail?: string } | null;\n};\n\ntype WorkflowSourceInfo = { workflowId: string; workflowRunId: string };\n\ntype IssueOccurrence = {\n id: string;\n sourceKind?: string;\n sourceId?: string | null;\n primaryUrl: string;\n ticketUserFacingSummary: string | null;\n ticketReproSteps: string | null;\n diagnosticJson: FailureDiagnostic | null;\n consoleLogExcerpt: string | null;\n networkFailureUrl: string | null;\n networkFailureStatus: number | null;\n workflowSourceInfo?: WorkflowSourceInfo | null;\n};\n\ntype IssueSummary = {\n id: string;\n title: string;\n severity: 'low' | 'medium' | 'high' | 'unknown';\n status: 'open' | 'closed' | 'not_a_bug';\n category: IssueCategorySummary;\n firstSeenAt: string;\n lastSeenAt: string;\n occurrenceCount: number;\n assignedTo: IssueAssignee | null;\n latestOccurrence: (IssueOccurrence & { workflowSourceInfo?: WorkflowSourceInfo | null }) | null;\n};\n\ntype ConsoleLogEntry = {\n type: string;\n text: string;\n timestamp: number | null;\n location: string | null;\n};\n\ntype NetworkRequestEntry = {\n url: string;\n method: string;\n status: number | null;\n durationMs: number | null;\n};\n\ntype Pagination = {\n page: number;\n pageSize: number;\n totalItems: number;\n totalPages: number;\n};\n\ntype IssueListResponse = {\n ok: boolean;\n error?: string;\n data: IssueSummary[];\n pagination: Pagination;\n};\n\ntype IssueDetailResponse = {\n ok: boolean;\n error?: string;\n data: {\n issue: IssueSummary;\n occurrences: IssueOccurrence[];\n commentCount: number;\n };\n};\n\ntype DiagnosticsDataResponse = {\n ok: boolean;\n data: ConsoleLogEntry[] | NetworkRequestEntry[];\n};\n\n/* ── Formatting Helpers ───────────────────────────────────────────────── */\n\nconst SEVERITY_ICONS: Record<string, string> = {\n high: '!!!',\n medium: '!!',\n low: '!',\n unknown: '?',\n};\n\nconst DIAGNOSTIC_CATEGORY_LABELS: Record<string, string> = {\n software_bug: 'Software Bug',\n dependency_issue: 'Dependency Issue',\n agent_confusion: 'Agent Confusion',\n platform_error: 'Platform Error',\n};\n\nfunction formatStatusLabel(status: string): string {\n switch (status) {\n case 'open':\n return 'Open';\n case 'closed':\n return 'Closed';\n case 'not_a_bug':\n return 'Not a Bug';\n default:\n return status;\n }\n}\n\nfunction formatSeverity(severity: string): string {\n return severity.charAt(0).toUpperCase() + severity.slice(1);\n}\n\nfunction formatRelative(value: string | null): string {\n if (!value) return '—';\n try {\n const date = new Date(value);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n if (diffMins < 1) return 'just now';\n if (diffMins < 60) return `${diffMins}m ago`;\n const diffHours = Math.floor(diffMins / 60);\n if (diffHours < 24) return `${diffHours}h ago`;\n const diffDays = Math.floor(diffHours / 24);\n if (diffDays < 30) return `${diffDays}d ago`;\n return date.toISOString().slice(0, 10);\n } catch {\n return value;\n }\n}\n\nfunction truncate(text: string, max: number): string {\n if (text.length <= max) return text;\n return text.slice(0, max - 1) + '…';\n}\n\n/* ── Markdown Formatters ──────────────────────────────────────────────── */\n\nfunction formatIssueDetailMarkdown(\n issue: IssueSummary,\n consoleErrors: ConsoleLogEntry[],\n networkErrors: NetworkRequestEntry[]\n): string {\n const sections: string[] = [];\n const occ = issue.latestOccurrence;\n\n sections.push(`# ${issue.title}`);\n\n const meta: string[] = [];\n meta.push(`**Status:** ${formatStatusLabel(issue.status)}`);\n meta.push(`**Severity:** ${formatSeverity(issue.severity)}`);\n meta.push(`**Category:** ${issue.category.label}`);\n sections.push(meta.join(' | '));\n\n if (occ?.primaryUrl) {\n sections.push(`**URL:** ${occ.primaryUrl}`);\n }\n\n if (occ?.workflowSourceInfo) {\n sections.push(\n `**Workflow:** ${occ.workflowSourceInfo.workflowId} | **Workflow Run:** ${occ.workflowSourceInfo.workflowRunId}`\n );\n }\n\n const timeParts: string[] = [];\n timeParts.push(`**First seen:** ${formatRelative(issue.firstSeenAt)}`);\n timeParts.push(`**Last seen:** ${formatRelative(issue.lastSeenAt)}`);\n timeParts.push(`**Occurrences:** ${issue.occurrenceCount}`);\n sections.push(timeParts.join(' | '));\n\n const summary = occ?.ticketUserFacingSummary?.trim();\n if (summary) {\n sections.push(`## Summary\\n${summary}`);\n }\n\n const reproSteps = occ?.ticketReproSteps?.trim();\n if (reproSteps) {\n sections.push(`## Reproduction Steps\\n${reproSteps}`);\n }\n\n const diagnostic = occ?.diagnosticJson;\n if (diagnostic) {\n const diagParts: string[] = [];\n const categoryLabel = DIAGNOSTIC_CATEGORY_LABELS[diagnostic.category] ?? diagnostic.category;\n diagParts.push('## Diagnostic Analysis');\n diagParts.push(\n `**Category:** ${categoryLabel} (${Math.round(diagnostic.confidence)}% confidence)`\n );\n diagParts.push(`**${diagnostic.title}**`);\n diagParts.push(diagnostic.analysis);\n\n if (diagnostic.smokingGun) {\n const gun = diagnostic.smokingGun;\n const gunLines = [`> **Key Evidence:** ${gun.description}`];\n if (gun.detail) {\n gunLines.push(`> \\`${gun.detail}\\``);\n }\n diagParts.push(gunLines.join('\\n'));\n }\n\n diagParts.push(`**Recommendation:** ${diagnostic.recommendation}`);\n sections.push(diagParts.join('\\n\\n'));\n }\n\n if (consoleErrors.length > 0) {\n const logLines = consoleErrors.map((entry) => {\n const loc = entry.location ? ` (${entry.location})` : '';\n return `[${entry.type}] ${entry.text}${loc}`;\n });\n sections.push(`## Console Errors\\n\\`\\`\\`\\n${logLines.join('\\n')}\\n\\`\\`\\``);\n }\n\n if (networkErrors.length > 0) {\n const rows = networkErrors.map((entry) => {\n const status =\n entry.status === null || entry.status === 0 ? '0 (failed)' : String(entry.status);\n const duration =\n entry.durationMs !== null && entry.durationMs !== undefined ? `${entry.durationMs}ms` : '—';\n return `| ${entry.method} | ${entry.url} | ${status} | ${duration} |`;\n });\n sections.push(\n `## Network Errors\\n| Method | URL | Status | Duration |\\n|--------|-----|--------|----------|\\n${rows.join('\\n')}`\n );\n }\n\n return sections.join('\\n\\n');\n}\n\nfunction formatIssueListMarkdown(data: IssueSummary[], pagination: Pagination): string {\n const sections: string[] = [];\n sections.push(\n `# Issues (page ${pagination.page} of ${pagination.totalPages}, ${pagination.totalItems} total)`\n );\n\n if (data.length === 0) {\n sections.push('No issues found.');\n return sections.join('\\n\\n');\n }\n\n const header = '| Severity | Title | Status | Last Seen | Occurrences |';\n const divider = '|----------|-------|--------|-----------|-------------|';\n const rows = data.map(\n (issue) =>\n `| ${issue.severity} | ${truncate(issue.title, 60)} | ${issue.status} | ${formatRelative(issue.lastSeenAt)} | ${issue.occurrenceCount} |`\n );\n sections.push([header, divider, ...rows].join('\\n'));\n\n return sections.join('\\n\\n');\n}\n\n/* ── Diagnostics Fetching ─────────────────────────────────────────────── */\n\nasync function fetchDiagnostics(\n apiUrl: string,\n token: string,\n issue: IssueSummary\n): Promise<{ consoleErrors: ConsoleLogEntry[]; networkErrors: NetworkRequestEntry[] }> {\n const occ = issue.latestOccurrence;\n if (!occ) return { consoleErrors: [], networkErrors: [] };\n\n let consoleErrors: ConsoleLogEntry[] = [];\n let networkErrors: NetworkRequestEntry[] = [];\n\n try {\n const [consoleRes, networkRes] = await Promise.all([\n apiRequest<DiagnosticsDataResponse>(\n apiUrl,\n token,\n 'GET',\n `/v2/issues/${issue.id}/occurrences/${occ.id}/console-logs`\n ),\n apiRequest<DiagnosticsDataResponse>(\n apiUrl,\n token,\n 'GET',\n `/v2/issues/${issue.id}/occurrences/${occ.id}/network-requests`\n ),\n ]);\n\n if (consoleRes.ok && Array.isArray(consoleRes.data)) {\n consoleErrors = (consoleRes.data as ConsoleLogEntry[]).filter((e) => e.type === 'error');\n }\n\n if (networkRes.ok && Array.isArray(networkRes.data)) {\n networkErrors = (networkRes.data as NetworkRequestEntry[]).filter(\n (e) => e.status === null || e.status === 0 || e.status >= 400\n );\n }\n } catch {\n // Diagnostics are best-effort; continue without them\n }\n\n // Fallback to legacy fields\n if (consoleErrors.length === 0 && occ.consoleLogExcerpt?.trim()) {\n consoleErrors = [\n { type: 'error', text: occ.consoleLogExcerpt.trim(), timestamp: null, location: null },\n ];\n }\n\n if (networkErrors.length === 0 && occ.networkFailureUrl) {\n networkErrors = [\n {\n url: occ.networkFailureUrl,\n method: 'GET',\n status: occ.networkFailureStatus,\n durationMs: null,\n },\n ];\n }\n\n return { consoleErrors, networkErrors };\n}\n\n/* ── Sub-command Handlers ─────────────────────────────────────────────── */\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n const fullOutput = hasFlag(argv, '--full') || hasFlag(argv, '--raw');\n const markdownOutput = getArgValue(argv, '--format') === 'markdown';\n\n const params = new URLSearchParams();\n const search = getArgValue(argv, '--search');\n const severity = getArgValue(argv, '--severity');\n const status = getArgValue(argv, '--status');\n const propertyId = getApplicationIdArg(argv);\n const page = getArgValue(argv, '--page');\n const pageSize = getArgValue(argv, '--page-size');\n\n if (search) params.set('search', search);\n if (severity) params.set('severity', severity);\n if (status) params.set('statuses', status);\n if (propertyId) params.set('propertyId', propertyId);\n if (page) params.set('page', page);\n if (pageSize) params.set('pageSize', pageSize);\n\n const qs = params.toString();\n const path = `/v2/issues${qs ? `?${qs}` : ''}`;\n\n const result = await apiRequest<IssueListResponse>(apiUrl, token, 'GET', path);\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n if (fullOutput) {\n console.log(JSON.stringify({ data: result.data, pagination: result.pagination }, null, 2));\n } else {\n const compact = result.data.map((issue) => {\n const occ = issue.latestOccurrence;\n const source: Record<string, unknown> = {\n kind: occ?.sourceKind ?? null,\n id: occ?.sourceId ?? null,\n };\n if (occ?.workflowSourceInfo) source.workflow = occ.workflowSourceInfo;\n return {\n id: issue.id,\n title: issue.title,\n severity: issue.severity,\n status: issue.status,\n occurrenceCount: issue.occurrenceCount,\n lastSeenAt: issue.lastSeenAt,\n source,\n };\n });\n console.log(JSON.stringify({ data: compact, pagination: result.pagination }, null, 2));\n }\n return;\n }\n\n if (markdownOutput) {\n console.log(formatIssueListMarkdown(result.data, result.pagination));\n return;\n }\n\n // Default compact output\n const { data, pagination } = result;\n console.log(\n `Issues: ${pagination.totalItems} total (page ${pagination.page}/${pagination.totalPages})\\n`\n );\n\n if (data.length === 0) {\n console.log('No issues found.');\n return;\n }\n\n for (const issue of data) {\n const icon = SEVERITY_ICONS[issue.severity] ?? '?';\n const statusLabel = formatStatusLabel(issue.status);\n const lastSeen = formatRelative(issue.lastSeenAt);\n const occ = issue.latestOccurrence;\n const sourceTag = occ?.workflowSourceInfo\n ? ` [wf:${occ.workflowSourceInfo.workflowRunId.slice(0, 8)}]`\n : occ?.sourceKind && occ.sourceKind !== 'workflow_test'\n ? ` [${occ.sourceKind}]`\n : '';\n console.log(\n ` [${icon}] ${truncate(issue.title, 60)} ${statusLabel} ${lastSeen} (${issue.occurrenceCount}x)${sourceTag} ${issue.id}`\n );\n }\n}\n\nfunction parseIncludes(argv: string[]): Set<string> {\n const raw = getArgValue(argv, '--include');\n if (!raw) return new Set();\n return new Set(\n raw\n .split(',')\n .map((s) => s.trim().toLowerCase())\n .filter(Boolean)\n );\n}\n\nfunction buildCompactIssueGet(\n issue: IssueSummary,\n consoleErrors: ConsoleLogEntry[],\n networkErrors: NetworkRequestEntry[],\n includes: Set<string>\n): Record<string, unknown> {\n const occ = issue.latestOccurrence;\n const diag = occ?.diagnosticJson ?? null;\n\n const source: Record<string, unknown> = {\n kind: occ?.sourceKind ?? null,\n id: occ?.sourceId ?? null,\n };\n if (occ?.workflowSourceInfo) source.workflow = occ.workflowSourceInfo;\n\n const compact: Record<string, unknown> = {\n id: issue.id,\n title: issue.title,\n status: issue.status,\n severity: issue.severity,\n category: { key: issue.category.key, label: issue.category.label },\n occurrenceCount: issue.occurrenceCount,\n firstSeenAt: issue.firstSeenAt,\n lastSeenAt: issue.lastSeenAt,\n primaryUrl: occ?.primaryUrl ?? null,\n assignedTo: issue.assignedTo\n ? { id: issue.assignedTo.id, displayName: issue.assignedTo.displayName }\n : null,\n source,\n summary: occ?.ticketUserFacingSummary ?? null,\n diagnostic: diag\n ? {\n category: diag.category,\n confidence: diag.confidence,\n title: diag.title,\n recommendation: diag.recommendation,\n }\n : null,\n consoleErrorCount: consoleErrors.length,\n networkErrorCount: networkErrors.length,\n links: {\n occurrences: `/v2/issues/${issue.id}/occurrences`,\n consoleLogs: occ\n ? `/v2/issues/${issue.id}/occurrences/${occ.id}/console-logs`\n : null,\n networkRequests: occ\n ? `/v2/issues/${issue.id}/occurrences/${occ.id}/network-requests`\n : null,\n reproPrompt: `/v2/issues/${issue.id}/repro-prompt`,\n },\n };\n\n if (includes.has('console')) compact.consoleErrors = consoleErrors;\n if (includes.has('network')) compact.networkErrors = networkErrors;\n if (includes.has('repro')) compact.reproSteps = occ?.ticketReproSteps ?? null;\n if (includes.has('diagnostic-full')) compact.diagnosticFull = diag;\n\n return compact;\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const issueId = argv[0];\n if (!issueId || issueId.startsWith('--')) {\n console.error('Error: Missing issue ID.');\n console.error('Usage: canary issues get <issueId>');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n const fullOutput = hasFlag(argv, '--full') || hasFlag(argv, '--raw');\n const markdownOutput = getArgValue(argv, '--format') === 'markdown';\n const includes = parseIncludes(argv);\n\n const result = await apiRequest<IssueDetailResponse>(\n apiUrl,\n token,\n 'GET',\n `/v2/issues/${issueId}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n const { issue } = result.data;\n\n // Diagnostics are prefetched only when the user will see them (text/markdown\n // output, `--full`, or an explicit `--include console|network`). Compact JSON\n // without those flags returns occurrence counts only and leaves the heavy\n // arrays behind the linked endpoints.\n const needDiagnostics =\n !jsonOutput ||\n fullOutput ||\n includes.has('console') ||\n includes.has('network');\n const { consoleErrors, networkErrors } = needDiagnostics\n ? await fetchDiagnostics(apiUrl, token, issue)\n : { consoleErrors: [] as ConsoleLogEntry[], networkErrors: [] as NetworkRequestEntry[] };\n\n if (jsonOutput) {\n if (fullOutput) {\n console.log(JSON.stringify({ ...result.data, consoleErrors, networkErrors }, null, 2));\n } else {\n console.log(\n JSON.stringify(buildCompactIssueGet(issue, consoleErrors, networkErrors, includes), null, 2)\n );\n }\n return;\n }\n\n if (markdownOutput) {\n console.log(formatIssueDetailMarkdown(issue, consoleErrors, networkErrors));\n return;\n }\n\n // Default human-readable output\n const occ = issue.latestOccurrence;\n console.log(` Title: ${issue.title}`);\n console.log(` ID: ${issue.id}`);\n console.log(` Status: ${formatStatusLabel(issue.status)}`);\n console.log(` Severity: ${formatSeverity(issue.severity)}`);\n console.log(` Category: ${issue.category.label}`);\n console.log(` Occurrences: ${issue.occurrenceCount}`);\n console.log(` First seen: ${formatRelative(issue.firstSeenAt)}`);\n console.log(` Last seen: ${formatRelative(issue.lastSeenAt)}`);\n\n if (occ?.primaryUrl) {\n console.log(` URL: ${occ.primaryUrl}`);\n }\n\n if (occ?.workflowSourceInfo) {\n console.log(` Workflow: ${occ.workflowSourceInfo.workflowId}`);\n console.log(` Workflow Run: ${occ.workflowSourceInfo.workflowRunId}`);\n } else if (occ?.sourceKind) {\n console.log(` Source: ${occ.sourceKind}${occ.sourceId ? ` (${occ.sourceId})` : ''}`);\n }\n\n if (issue.assignedTo) {\n console.log(\n ` Assigned to: ${issue.assignedTo.displayName ?? issue.assignedTo.primaryEmail ?? issue.assignedTo.id}`\n );\n }\n\n const summary = occ?.ticketUserFacingSummary?.trim();\n if (summary) {\n console.log(`\\n Summary:\\n ${summary.split('\\n').join('\\n ')}`);\n }\n\n const diagnostic = occ?.diagnosticJson;\n if (diagnostic) {\n const categoryLabel = DIAGNOSTIC_CATEGORY_LABELS[diagnostic.category] ?? diagnostic.category;\n console.log(`\\n Diagnostic: ${categoryLabel} (${Math.round(diagnostic.confidence)}%)`);\n console.log(` ${diagnostic.title}`);\n console.log(` Recommendation: ${diagnostic.recommendation}`);\n }\n\n if (consoleErrors.length > 0) {\n console.log(`\\n Console Errors (${consoleErrors.length}):`);\n for (const entry of consoleErrors.slice(0, 5)) {\n const loc = entry.location ? ` (${entry.location})` : '';\n console.log(` [${entry.type}] ${truncate(entry.text, 100)}${loc}`);\n }\n if (consoleErrors.length > 5) {\n console.log(` ... and ${consoleErrors.length - 5} more`);\n }\n }\n\n if (networkErrors.length > 0) {\n console.log(`\\n Network Errors (${networkErrors.length}):`);\n for (const entry of networkErrors.slice(0, 5)) {\n const status = entry.status === null || entry.status === 0 ? 'failed' : String(entry.status);\n console.log(` ${entry.method} ${truncate(entry.url, 80)} -> ${status}`);\n }\n if (networkErrors.length > 5) {\n console.log(` ... and ${networkErrors.length - 5} more`);\n }\n }\n}\n\ntype IssueStatusUpdateResponse = {\n ok: boolean;\n error?: string;\n status?: 'open' | 'closed' | 'not_a_bug';\n statusUpdatedAt?: string;\n closedAt?: string | null;\n};\n\nasync function handleClose(argv: string[], apiUrl: string, token: string): Promise<void> {\n const issueId = argv[0];\n if (!issueId || issueId.startsWith('--')) {\n console.error('Error: Missing issue ID.');\n console.error('Usage: canary issues close <issueId> [--not-a-bug --reason <text>]');\n process.exit(1);\n }\n\n const notABug = hasFlag(argv, '--not-a-bug');\n const reason = getArgValue(argv, '--reason') ?? getArgValue(argv, '--feedback');\n const jsonOutput = hasFlag(argv, '--json');\n\n if (notABug && !reason?.trim()) {\n console.error('Error: --not-a-bug requires --reason <text>.');\n process.exit(1);\n }\n\n const status: 'closed' | 'not_a_bug' = notABug ? 'not_a_bug' : 'closed';\n const body: Record<string, unknown> = { status };\n if (reason?.trim()) body.feedback = reason.trim();\n\n const result = await apiRequest<IssueStatusUpdateResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/issues/${issueId}/status`,\n body\n );\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: false, error: result.error }, null, 2));\n } else {\n console.error(`Error: ${result.error}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(\n `Issue ${issueId} ${status === 'not_a_bug' ? 'marked not-a-bug' : 'closed'}.`\n );\n}\n\nasync function handleReopen(argv: string[], apiUrl: string, token: string): Promise<void> {\n const issueId = argv[0];\n if (!issueId || issueId.startsWith('--')) {\n console.error('Error: Missing issue ID.');\n console.error('Usage: canary issues reopen <issueId>');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n\n const result = await apiRequest<IssueStatusUpdateResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/issues/${issueId}/status`,\n { status: 'open' }\n );\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: false, error: result.error }, null, 2));\n } else {\n console.error(`Error: ${result.error}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(`Issue ${issueId} reopened.`);\n}\n\n/* ── Help & Entry Point ───────────────────────────────────────────────── */\n\nfunction printIssuesHelp(): void {\n console.log(\n [\n 'Usage: canary issues <sub-command> [options]',\n '',\n 'Sub-commands:',\n ' list [options] List and search issues',\n ' get <issueId> [options] Get issue detail with diagnostics',\n ' close <issueId> [options] Close an issue (or mark not-a-bug)',\n ' reopen <issueId> [--json] Reopen a closed issue',\n '',\n 'Close options:',\n ' --not-a-bug Mark as not-a-bug instead of closed (requires --reason)',\n ' --reason <text> Feedback/reason (required when --not-a-bug)',\n ' --json JSON output',\n '',\n 'List options:',\n ' --search <query> Full-text search',\n ' --severity <level> Filter: low, medium, high, unknown',\n ' --status <statuses> Filter: open, closed, not_a_bug (comma-separated)',\n ' --application-id <uuid> Filter by application (alias: --property-id)',\n ' --page <n> Page number (default: 1)',\n ' --page-size <n> Page size (default: 25)',\n '',\n 'Output options:',\n ' --json Compact JSON (workflow IDs + counts + links)',\n ' --full With --json, return the full unmodified response',\n ' --include <csv> With --json on `get`: console, network, repro, diagnostic-full',\n ' --format markdown Output as markdown',\n '',\n 'Common options:',\n ' --env <env> Target environment (prod, dev, local)',\n ' --api-url <url> API URL override (takes precedence over --env)',\n ' --token <key> API token override',\n ].join('\\n')\n );\n}\n\nexport async function runIssues(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printIssuesHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case 'list':\n await handleList(rest, apiUrl, token);\n break;\n case 'get':\n await handleGet(rest, apiUrl, token);\n break;\n case 'close':\n await handleClose(rest, apiUrl, token);\n break;\n case 'reopen':\n await handleReopen(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printIssuesHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/issues.ts"],"sourcesContent":["/**\n * CLI Issues Management\n *\n * Search, list, and view issues with full diagnostics from the terminal.\n */\n\nimport process from 'node:process';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest, getApplicationIdArg } from './cli-helpers.js';\n\n/* ── Types ────────────────────────────────────────────────────────────── */\n\ntype IssueCategorySummary = {\n id: string;\n key: string;\n label: string;\n description: string | null;\n instructions: string | null;\n};\n\ntype IssueAssignee = {\n id: string;\n displayName: string | null;\n primaryEmail: string | null;\n};\n\ntype FailureDiagnostic = {\n category: string;\n confidence: number;\n title: string;\n analysis: string;\n recommendation: string;\n smokingGun?: { description: string; detail?: string } | null;\n};\n\ntype WorkflowSourceInfo = { workflowId: string; workflowRunId: string };\n\ntype IssueOccurrence = {\n id: string;\n sourceKind?: string;\n sourceId?: string | null;\n primaryUrl: string;\n ticketUserFacingSummary: string | null;\n ticketReproSteps: string | null;\n diagnosticJson: FailureDiagnostic | null;\n consoleLogExcerpt: string | null;\n networkFailureUrl: string | null;\n networkFailureStatus: number | null;\n workflowSourceInfo?: WorkflowSourceInfo | null;\n};\n\ntype IssueSummary = {\n id: string;\n title: string;\n severity: 'low' | 'medium' | 'high' | 'unknown';\n status: 'open' | 'closed' | 'not_a_bug';\n category: IssueCategorySummary;\n firstSeenAt: string;\n lastSeenAt: string;\n occurrenceCount: number;\n assignedTo: IssueAssignee | null;\n latestOccurrence: (IssueOccurrence & { workflowSourceInfo?: WorkflowSourceInfo | null }) | null;\n};\n\ntype ConsoleLogEntry = {\n type: string;\n text: string;\n timestamp: number | null;\n location: string | null;\n};\n\ntype NetworkRequestEntry = {\n url: string;\n method: string;\n status: number | null;\n durationMs: number | null;\n};\n\ntype Pagination = {\n page: number;\n pageSize: number;\n totalItems: number;\n totalPages: number;\n};\n\ntype IssueListResponse = {\n ok: boolean;\n error?: string;\n data: IssueSummary[];\n pagination: Pagination;\n};\n\ntype IssueDetailResponse = {\n ok: boolean;\n error?: string;\n data: {\n issue: IssueSummary;\n occurrences: IssueOccurrence[];\n commentCount: number;\n };\n};\n\ntype DiagnosticsDataResponse = {\n ok: boolean;\n data: ConsoleLogEntry[] | NetworkRequestEntry[];\n};\n\n/* ── Formatting Helpers ───────────────────────────────────────────────── */\n\nconst SEVERITY_ICONS: Record<string, string> = {\n high: '!!!',\n medium: '!!',\n low: '!',\n unknown: '?',\n};\n\nconst DIAGNOSTIC_CATEGORY_LABELS: Record<string, string> = {\n software_bug: 'Software Bug',\n dependency_issue: 'Dependency Issue',\n agent_confusion: 'Agent Confusion',\n platform_error: 'Platform Error',\n};\n\nfunction formatStatusLabel(status: string): string {\n switch (status) {\n case 'open':\n return 'Open';\n case 'closed':\n return 'Closed';\n case 'not_a_bug':\n return 'Not a Bug';\n default:\n return status;\n }\n}\n\nfunction formatSeverity(severity: string): string {\n return severity.charAt(0).toUpperCase() + severity.slice(1);\n}\n\nfunction formatRelative(value: string | null): string {\n if (!value) return '—';\n try {\n const date = new Date(value);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n if (diffMins < 1) return 'just now';\n if (diffMins < 60) return `${diffMins}m ago`;\n const diffHours = Math.floor(diffMins / 60);\n if (diffHours < 24) return `${diffHours}h ago`;\n const diffDays = Math.floor(diffHours / 24);\n if (diffDays < 30) return `${diffDays}d ago`;\n return date.toISOString().slice(0, 10);\n } catch {\n return value;\n }\n}\n\nfunction truncate(text: string, max: number): string {\n if (text.length <= max) return text;\n return text.slice(0, max - 1) + '…';\n}\n\n/* ── Markdown Formatters ──────────────────────────────────────────────── */\n\nfunction formatIssueDetailMarkdown(\n issue: IssueSummary,\n consoleErrors: ConsoleLogEntry[],\n networkErrors: NetworkRequestEntry[]\n): string {\n const sections: string[] = [];\n const occ = issue.latestOccurrence;\n\n sections.push(`# ${issue.title}`);\n\n const meta: string[] = [];\n meta.push(`**Status:** ${formatStatusLabel(issue.status)}`);\n meta.push(`**Severity:** ${formatSeverity(issue.severity)}`);\n meta.push(`**Category:** ${issue.category.label}`);\n sections.push(meta.join(' | '));\n\n if (occ?.primaryUrl) {\n sections.push(`**URL:** ${occ.primaryUrl}`);\n }\n\n if (occ?.workflowSourceInfo) {\n sections.push(\n `**Workflow:** ${occ.workflowSourceInfo.workflowId} | **Workflow Run:** ${occ.workflowSourceInfo.workflowRunId}`\n );\n }\n\n const timeParts: string[] = [];\n timeParts.push(`**First seen:** ${formatRelative(issue.firstSeenAt)}`);\n timeParts.push(`**Last seen:** ${formatRelative(issue.lastSeenAt)}`);\n timeParts.push(`**Occurrences:** ${issue.occurrenceCount}`);\n sections.push(timeParts.join(' | '));\n\n const summary = occ?.ticketUserFacingSummary?.trim();\n if (summary) {\n sections.push(`## Summary\\n${summary}`);\n }\n\n const reproSteps = occ?.ticketReproSteps?.trim();\n if (reproSteps) {\n sections.push(`## Reproduction Steps\\n${reproSteps}`);\n }\n\n const diagnostic = occ?.diagnosticJson;\n if (diagnostic) {\n const diagParts: string[] = [];\n const categoryLabel = DIAGNOSTIC_CATEGORY_LABELS[diagnostic.category] ?? diagnostic.category;\n diagParts.push('## Diagnostic Analysis');\n diagParts.push(\n `**Category:** ${categoryLabel} (${Math.round(diagnostic.confidence)}% confidence)`\n );\n diagParts.push(`**${diagnostic.title}**`);\n diagParts.push(diagnostic.analysis);\n\n if (diagnostic.smokingGun) {\n const gun = diagnostic.smokingGun;\n const gunLines = [`> **Key Evidence:** ${gun.description}`];\n if (gun.detail) {\n gunLines.push(`> \\`${gun.detail}\\``);\n }\n diagParts.push(gunLines.join('\\n'));\n }\n\n diagParts.push(`**Recommendation:** ${diagnostic.recommendation}`);\n sections.push(diagParts.join('\\n\\n'));\n }\n\n if (consoleErrors.length > 0) {\n const logLines = consoleErrors.map((entry) => {\n const loc = entry.location ? ` (${entry.location})` : '';\n return `[${entry.type}] ${entry.text}${loc}`;\n });\n sections.push(`## Console Errors\\n\\`\\`\\`\\n${logLines.join('\\n')}\\n\\`\\`\\``);\n }\n\n if (networkErrors.length > 0) {\n const rows = networkErrors.map((entry) => {\n const status =\n entry.status === null || entry.status === 0 ? '0 (failed)' : String(entry.status);\n const duration =\n entry.durationMs !== null && entry.durationMs !== undefined ? `${entry.durationMs}ms` : '—';\n return `| ${entry.method} | ${entry.url} | ${status} | ${duration} |`;\n });\n sections.push(\n `## Network Errors\\n| Method | URL | Status | Duration |\\n|--------|-----|--------|----------|\\n${rows.join('\\n')}`\n );\n }\n\n return sections.join('\\n\\n');\n}\n\nfunction formatIssueListMarkdown(data: IssueSummary[], pagination: Pagination): string {\n const sections: string[] = [];\n sections.push(\n `# Issues (page ${pagination.page} of ${pagination.totalPages}, ${pagination.totalItems} total)`\n );\n\n if (data.length === 0) {\n sections.push('No issues found.');\n return sections.join('\\n\\n');\n }\n\n const header = '| Severity | Title | Status | Last Seen | Occurrences |';\n const divider = '|----------|-------|--------|-----------|-------------|';\n const rows = data.map(\n (issue) =>\n `| ${issue.severity} | ${truncate(issue.title, 60)} | ${issue.status} | ${formatRelative(issue.lastSeenAt)} | ${issue.occurrenceCount} |`\n );\n sections.push([header, divider, ...rows].join('\\n'));\n\n return sections.join('\\n\\n');\n}\n\n/* ── Diagnostics Fetching ─────────────────────────────────────────────── */\n\nasync function fetchDiagnostics(\n apiUrl: string,\n token: string,\n issue: IssueSummary\n): Promise<{ consoleErrors: ConsoleLogEntry[]; networkErrors: NetworkRequestEntry[] }> {\n const occ = issue.latestOccurrence;\n if (!occ) return { consoleErrors: [], networkErrors: [] };\n\n let consoleErrors: ConsoleLogEntry[] = [];\n let networkErrors: NetworkRequestEntry[] = [];\n\n try {\n const [consoleRes, networkRes] = await Promise.all([\n apiRequest<DiagnosticsDataResponse>(\n apiUrl,\n token,\n 'GET',\n `/v2/issues/${issue.id}/occurrences/${occ.id}/console-logs`\n ),\n apiRequest<DiagnosticsDataResponse>(\n apiUrl,\n token,\n 'GET',\n `/v2/issues/${issue.id}/occurrences/${occ.id}/network-requests`\n ),\n ]);\n\n if (consoleRes.ok && Array.isArray(consoleRes.data)) {\n consoleErrors = (consoleRes.data as ConsoleLogEntry[]).filter((e) => e.type === 'error');\n }\n\n if (networkRes.ok && Array.isArray(networkRes.data)) {\n networkErrors = (networkRes.data as NetworkRequestEntry[]).filter(\n (e) => e.status === null || e.status === 0 || e.status >= 400\n );\n }\n } catch {\n // Diagnostics are best-effort; continue without them\n }\n\n // Fallback to legacy fields\n if (consoleErrors.length === 0 && occ.consoleLogExcerpt?.trim()) {\n consoleErrors = [\n { type: 'error', text: occ.consoleLogExcerpt.trim(), timestamp: null, location: null },\n ];\n }\n\n if (networkErrors.length === 0 && occ.networkFailureUrl) {\n networkErrors = [\n {\n url: occ.networkFailureUrl,\n method: 'GET',\n status: occ.networkFailureStatus,\n durationMs: null,\n },\n ];\n }\n\n return { consoleErrors, networkErrors };\n}\n\n/* ── Sub-command Handlers ─────────────────────────────────────────────── */\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, '--json');\n const fullOutput = hasFlag(argv, '--full') || hasFlag(argv, '--raw');\n const markdownOutput = getArgValue(argv, '--format') === 'markdown';\n\n const params = new URLSearchParams();\n const search = getArgValue(argv, '--search');\n const severity = getArgValue(argv, '--severity');\n const status = getArgValue(argv, '--status');\n const propertyId = getApplicationIdArg(argv);\n const page = getArgValue(argv, '--page');\n const pageSize = getArgValue(argv, '--page-size');\n\n if (search) params.set('search', search);\n if (severity) params.set('severity', severity);\n if (status) params.set('statuses', status);\n if (propertyId) params.set('propertyId', propertyId);\n if (page) params.set('page', page);\n if (pageSize) params.set('pageSize', pageSize);\n\n const qs = params.toString();\n const path = `/v2/issues${qs ? `?${qs}` : ''}`;\n\n const result = await apiRequest<IssueListResponse>(apiUrl, token, 'GET', path);\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n if (fullOutput) {\n console.log(JSON.stringify({ data: result.data, pagination: result.pagination }, null, 2));\n } else {\n const compact = result.data.map((issue) => {\n const occ = issue.latestOccurrence;\n const source: Record<string, unknown> = {\n kind: occ?.sourceKind ?? null,\n id: occ?.sourceId ?? null,\n };\n if (occ?.workflowSourceInfo) source.workflow = occ.workflowSourceInfo;\n return {\n id: issue.id,\n title: issue.title,\n severity: issue.severity,\n status: issue.status,\n occurrenceCount: issue.occurrenceCount,\n lastSeenAt: issue.lastSeenAt,\n source,\n };\n });\n console.log(JSON.stringify({ data: compact, pagination: result.pagination }, null, 2));\n }\n return;\n }\n\n if (markdownOutput) {\n console.log(formatIssueListMarkdown(result.data, result.pagination));\n return;\n }\n\n // Default compact output\n const { data, pagination } = result;\n console.log(\n `Issues: ${pagination.totalItems} total (page ${pagination.page}/${pagination.totalPages})\\n`\n );\n\n if (data.length === 0) {\n console.log('No issues found.');\n return;\n }\n\n for (const issue of data) {\n const icon = SEVERITY_ICONS[issue.severity] ?? '?';\n const statusLabel = formatStatusLabel(issue.status);\n const lastSeen = formatRelative(issue.lastSeenAt);\n const occ = issue.latestOccurrence;\n const sourceTag = occ?.workflowSourceInfo\n ? ` [wf:${occ.workflowSourceInfo.workflowRunId.slice(0, 8)}]`\n : occ?.sourceKind && occ.sourceKind !== 'workflow_test'\n ? ` [${occ.sourceKind}]`\n : '';\n console.log(\n ` [${icon}] ${truncate(issue.title, 60)} ${statusLabel} ${lastSeen} (${issue.occurrenceCount}x)${sourceTag} ${issue.id}`\n );\n }\n}\n\nfunction parseIncludes(argv: string[]): Set<string> {\n const raw = getArgValue(argv, '--include');\n if (!raw) return new Set();\n return new Set(\n raw\n .split(',')\n .map((s) => s.trim().toLowerCase())\n .filter(Boolean)\n );\n}\n\nfunction buildCompactIssueGet(\n issue: IssueSummary,\n consoleErrors: ConsoleLogEntry[],\n networkErrors: NetworkRequestEntry[],\n includes: Set<string>\n): Record<string, unknown> {\n const occ = issue.latestOccurrence;\n const diag = occ?.diagnosticJson ?? null;\n\n const source: Record<string, unknown> = {\n kind: occ?.sourceKind ?? null,\n id: occ?.sourceId ?? null,\n };\n if (occ?.workflowSourceInfo) source.workflow = occ.workflowSourceInfo;\n\n const compact: Record<string, unknown> = {\n id: issue.id,\n title: issue.title,\n status: issue.status,\n severity: issue.severity,\n category: { key: issue.category.key, label: issue.category.label },\n occurrenceCount: issue.occurrenceCount,\n firstSeenAt: issue.firstSeenAt,\n lastSeenAt: issue.lastSeenAt,\n primaryUrl: occ?.primaryUrl ?? null,\n assignedTo: issue.assignedTo\n ? { id: issue.assignedTo.id, displayName: issue.assignedTo.displayName }\n : null,\n source,\n summary: occ?.ticketUserFacingSummary ?? null,\n diagnostic: diag\n ? {\n category: diag.category,\n confidence: diag.confidence,\n title: diag.title,\n recommendation: diag.recommendation,\n }\n : null,\n consoleErrorCount: consoleErrors.length,\n networkErrorCount: networkErrors.length,\n links: {\n occurrences: `/v2/issues/${issue.id}/occurrences`,\n consoleLogs: occ\n ? `/v2/issues/${issue.id}/occurrences/${occ.id}/console-logs`\n : null,\n networkRequests: occ\n ? `/v2/issues/${issue.id}/occurrences/${occ.id}/network-requests`\n : null,\n reproPrompt: `/v2/issues/${issue.id}/repro-prompt`,\n },\n };\n\n if (includes.has('console')) compact.consoleErrors = consoleErrors;\n if (includes.has('network')) compact.networkErrors = networkErrors;\n if (includes.has('repro')) compact.reproSteps = occ?.ticketReproSteps ?? null;\n if (includes.has('diagnostic-full')) compact.diagnosticFull = diag;\n\n return compact;\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const issueId = argv[0];\n if (!issueId || issueId.startsWith('--')) {\n console.error('Error: Missing issue ID.');\n console.error('Usage: canary issues get <issueId>');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n const fullOutput = hasFlag(argv, '--full') || hasFlag(argv, '--raw');\n const markdownOutput = getArgValue(argv, '--format') === 'markdown';\n const includes = parseIncludes(argv);\n\n const result = await apiRequest<IssueDetailResponse>(\n apiUrl,\n token,\n 'GET',\n `/v2/issues/${issueId}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n const { issue } = result.data;\n\n // Diagnostics are prefetched only when the user will see them (text/markdown\n // output, `--full`, or an explicit `--include console|network`). Compact JSON\n // without those flags returns occurrence counts only and leaves the heavy\n // arrays behind the linked endpoints.\n const needDiagnostics =\n !jsonOutput ||\n fullOutput ||\n includes.has('console') ||\n includes.has('network');\n const { consoleErrors, networkErrors } = needDiagnostics\n ? await fetchDiagnostics(apiUrl, token, issue)\n : { consoleErrors: [] as ConsoleLogEntry[], networkErrors: [] as NetworkRequestEntry[] };\n\n if (jsonOutput) {\n if (fullOutput) {\n console.log(JSON.stringify({ ...result.data, consoleErrors, networkErrors }, null, 2));\n } else {\n console.log(\n JSON.stringify(buildCompactIssueGet(issue, consoleErrors, networkErrors, includes), null, 2)\n );\n }\n return;\n }\n\n if (markdownOutput) {\n console.log(formatIssueDetailMarkdown(issue, consoleErrors, networkErrors));\n return;\n }\n\n // Default human-readable output\n const occ = issue.latestOccurrence;\n console.log(` Title: ${issue.title}`);\n console.log(` ID: ${issue.id}`);\n console.log(` Status: ${formatStatusLabel(issue.status)}`);\n console.log(` Severity: ${formatSeverity(issue.severity)}`);\n console.log(` Category: ${issue.category.label}`);\n console.log(` Occurrences: ${issue.occurrenceCount}`);\n console.log(` First seen: ${formatRelative(issue.firstSeenAt)}`);\n console.log(` Last seen: ${formatRelative(issue.lastSeenAt)}`);\n\n if (occ?.primaryUrl) {\n console.log(` URL: ${occ.primaryUrl}`);\n }\n\n if (occ?.workflowSourceInfo) {\n console.log(` Workflow: ${occ.workflowSourceInfo.workflowId}`);\n console.log(` Workflow Run: ${occ.workflowSourceInfo.workflowRunId}`);\n } else if (occ?.sourceKind) {\n console.log(` Source: ${occ.sourceKind}${occ.sourceId ? ` (${occ.sourceId})` : ''}`);\n }\n\n if (issue.assignedTo) {\n console.log(\n ` Assigned to: ${issue.assignedTo.displayName ?? issue.assignedTo.primaryEmail ?? issue.assignedTo.id}`\n );\n }\n\n const summary = occ?.ticketUserFacingSummary?.trim();\n if (summary) {\n console.log(`\\n Summary:\\n ${summary.split('\\n').join('\\n ')}`);\n }\n\n const diagnostic = occ?.diagnosticJson;\n if (diagnostic) {\n const categoryLabel = DIAGNOSTIC_CATEGORY_LABELS[diagnostic.category] ?? diagnostic.category;\n console.log(`\\n Diagnostic: ${categoryLabel} (${Math.round(diagnostic.confidence)}%)`);\n console.log(` ${diagnostic.title}`);\n console.log(` Recommendation: ${diagnostic.recommendation}`);\n }\n\n if (consoleErrors.length > 0) {\n console.log(`\\n Console Errors (${consoleErrors.length}):`);\n for (const entry of consoleErrors.slice(0, 5)) {\n const loc = entry.location ? ` (${entry.location})` : '';\n console.log(` [${entry.type}] ${truncate(entry.text, 100)}${loc}`);\n }\n if (consoleErrors.length > 5) {\n console.log(` ... and ${consoleErrors.length - 5} more`);\n }\n }\n\n if (networkErrors.length > 0) {\n console.log(`\\n Network Errors (${networkErrors.length}):`);\n for (const entry of networkErrors.slice(0, 5)) {\n const status = entry.status === null || entry.status === 0 ? 'failed' : String(entry.status);\n console.log(` ${entry.method} ${truncate(entry.url, 80)} -> ${status}`);\n }\n if (networkErrors.length > 5) {\n console.log(` ... and ${networkErrors.length - 5} more`);\n }\n }\n}\n\ntype IssueStatusUpdateResponse = {\n ok: boolean;\n error?: string;\n status?: 'open' | 'closed' | 'not_a_bug';\n statusUpdatedAt?: string;\n closedAt?: string | null;\n};\n\nasync function handleClose(argv: string[], apiUrl: string, token: string): Promise<void> {\n const issueId = argv[0];\n if (!issueId || issueId.startsWith('--')) {\n console.error('Error: Missing issue ID.');\n console.error('Usage: canary issues close <issueId> [--not-a-bug --reason <text>]');\n process.exit(1);\n }\n\n const notABug = hasFlag(argv, '--not-a-bug');\n const reason = getArgValue(argv, '--reason') ?? getArgValue(argv, '--feedback');\n const jsonOutput = hasFlag(argv, '--json');\n\n if (notABug && !reason?.trim()) {\n console.error('Error: --not-a-bug requires --reason <text>.');\n process.exit(1);\n }\n\n const status: 'closed' | 'not_a_bug' = notABug ? 'not_a_bug' : 'closed';\n const body: Record<string, unknown> = { status };\n if (reason?.trim()) body.feedback = reason.trim();\n\n const result = await apiRequest<IssueStatusUpdateResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/issues/${issueId}/status`,\n body\n );\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: false, error: result.error }, null, 2));\n } else {\n console.error(`Error: ${result.error}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(\n `Issue ${issueId} ${status === 'not_a_bug' ? 'marked not-a-bug' : 'closed'}.`\n );\n}\n\nasync function handleReopen(argv: string[], apiUrl: string, token: string): Promise<void> {\n const issueId = argv[0];\n if (!issueId || issueId.startsWith('--')) {\n console.error('Error: Missing issue ID.');\n console.error('Usage: canary issues reopen <issueId>');\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, '--json');\n\n const result = await apiRequest<IssueStatusUpdateResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/issues/${issueId}/status`,\n { status: 'open' }\n );\n\n if (!result.ok) {\n if (jsonOutput) {\n console.log(JSON.stringify({ ok: false, error: result.error }, null, 2));\n } else {\n console.error(`Error: ${result.error}`);\n }\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log(`Issue ${issueId} reopened.`);\n}\n\n/* ── Help & Entry Point ───────────────────────────────────────────────── */\n\nfunction printIssuesHelp(): void {\n console.log(\n [\n 'Usage: canary issues <sub-command> [options]',\n '',\n 'Sub-commands:',\n ' list [options] List and search issues',\n ' get <issueId> [options] Get issue detail with diagnostics',\n ' close <issueId> [options] Close an issue (or mark not-a-bug)',\n ' reopen <issueId> [--json] Reopen a closed issue',\n '',\n 'Close options:',\n ' --not-a-bug Mark as not-a-bug instead of closed (requires --reason)',\n ' --reason <text> Feedback/reason (required when --not-a-bug)',\n ' --json JSON output',\n '',\n 'List options:',\n ' --search <query> Full-text search',\n ' --severity <level> Filter: low, medium, high, unknown',\n ' --status <statuses> Filter: open, closed, not_a_bug (comma-separated)',\n ' --application-id <uuid> Filter by application (alias: --property-id)',\n ' --page <n> Page number (default: 1)',\n ' --page-size <n> Page size (default: 25)',\n '',\n 'Output options:',\n ' --json Compact JSON (workflow IDs + counts + links)',\n ' --full With --json, return the full unmodified response',\n ' --include <csv> With --json on `get`: console, network, repro, diagnostic-full',\n ' --format markdown Output as markdown',\n '',\n 'Common options:',\n ' --env <env> Target environment (prod, dev, local)',\n ' --api-url <url> API URL override (takes precedence over --env)',\n ' --token <key> API token override',\n ].join('\\n')\n );\n}\n\nexport async function runIssues(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printIssuesHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case 'list':\n await handleList(rest, apiUrl, token);\n break;\n case 'get':\n await handleGet(rest, apiUrl, token);\n break;\n case 'close':\n await handleClose(rest, apiUrl, token);\n break;\n case 'reopen':\n await handleReopen(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printIssuesHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
+
KNOB_LIFECYCLE_STAGES,
|
|
3
4
|
apiRequest,
|
|
4
5
|
fetchList,
|
|
5
6
|
parseLifecycleStage,
|
|
6
7
|
toLifecycleLabel
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-SJJW77WN.js";
|
|
8
|
+
} from "./chunk-PRBRSIZP.js";
|
|
9
9
|
import "./chunk-3CZU7XCS.js";
|
|
10
10
|
import {
|
|
11
11
|
getArgValue,
|
|
12
12
|
hasFlag,
|
|
13
13
|
resolveConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-3X3NW7QA.js";
|
|
15
|
+
import "./chunk-JMJVGMXI.js";
|
|
15
16
|
import "./chunk-JWHYXEA2.js";
|
|
17
|
+
import "./chunk-JYGNMKZ5.js";
|
|
16
18
|
import "./chunk-VKVL7WBN.js";
|
|
17
19
|
|
|
18
20
|
// src/knobs.ts
|
|
@@ -183,7 +185,7 @@ async function handleLifecycle(argv, apiUrl, token) {
|
|
|
183
185
|
console.error("Usage: canary knobs lifecycle <key> --stage <active|deprecated|ready_for_cleanup> [--final-value <value>]");
|
|
184
186
|
process.exit(1);
|
|
185
187
|
}
|
|
186
|
-
const stage = parseLifecycleStage(argv);
|
|
188
|
+
const stage = parseLifecycleStage(argv, KNOB_LIFECYCLE_STAGES);
|
|
187
189
|
const rawFinalValue = getArgValue(argv, "--final-value");
|
|
188
190
|
const clearFinalValue = hasFlag(argv, "--clear-final-value");
|
|
189
191
|
if (rawFinalValue !== void 0 && clearFinalValue) {
|
|
@@ -292,4 +294,4 @@ async function runKnobs(argv) {
|
|
|
292
294
|
export {
|
|
293
295
|
runKnobs
|
|
294
296
|
};
|
|
295
|
-
//# sourceMappingURL=knobs-
|
|
297
|
+
//# sourceMappingURL=knobs-UQGGY3CP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/knobs.ts"],"sourcesContent":["/**\n * CLI Knobs Management\n *\n * Allows superadmins to manage knobs (global config) via the CLI.\n */\n\nimport process from \"node:process\";\nimport { resolveConfig, getArgValue, hasFlag } from \"./auth.js\";\nimport {\n type LifecycleStage,\n toLifecycleLabel,\n parseLifecycleStage,\n KNOB_LIFECYCLE_STAGES,\n apiRequest,\n fetchList,\n} from \"./cli-helpers.js\";\n\ntype SerializedKnob = {\n key: string;\n description: string | null;\n valueType: \"boolean\" | \"string\" | \"number\" | \"json\";\n value: unknown;\n lifecycleStage: LifecycleStage;\n finalValue: unknown;\n updatedAt: string | null;\n updatedBy: string | null;\n createdAt: string | null;\n isStale: boolean;\n};\n\ntype KnobApiResponse = {\n ok: boolean;\n error?: string;\n knob?: SerializedKnob;\n};\n\nfunction formatValue(valueType: SerializedKnob[\"valueType\"], value: unknown): string {\n if (valueType === \"json\") return JSON.stringify(value);\n return String(value);\n}\n\nfunction formatFinalValue(knob: SerializedKnob): string {\n if (knob.lifecycleStage === \"active\") return \"(none)\";\n return formatValue(knob.valueType, knob.finalValue);\n}\n\nfunction parseTypedValue(raw: string, valueType: SerializedKnob[\"valueType\"]): unknown {\n switch (valueType) {\n case \"boolean\":\n if (raw !== \"true\" && raw !== \"false\") {\n console.error('Error: Boolean value must be \"true\" or \"false\".');\n process.exit(1);\n }\n return raw === \"true\";\n case \"string\":\n return raw;\n case \"number\": {\n const num = parseFloat(raw);\n if (Number.isNaN(num)) {\n console.error(`Error: Invalid number: ${raw}`);\n process.exit(1);\n }\n return num;\n }\n case \"json\":\n try {\n return JSON.parse(raw);\n } catch {\n console.error(`Error: Invalid JSON: ${raw}`);\n process.exit(1);\n }\n }\n}\n\nfunction fetchKnobs(apiUrl: string, token: string): Promise<SerializedKnob[]> {\n return fetchList<SerializedKnob>(apiUrl, token, \"/superadmin/knobs\", \"knobs\");\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, \"--json\");\n const knobs = await fetchKnobs(apiUrl, token);\n\n if (jsonOutput) {\n console.log(JSON.stringify(knobs, null, 2));\n return;\n }\n\n if (knobs.length === 0) {\n console.log(\"No knobs found.\");\n return;\n }\n\n for (const knob of knobs) {\n const desc = knob.description ? ` ${knob.description}` : \"\";\n const lifecycle = `lifecycle=${toLifecycleLabel(knob.lifecycleStage)}`;\n const finalValue =\n knob.lifecycleStage === \"active\" ? \"\" : ` final=${formatFinalValue(knob)}`;\n const stale = knob.isStale ? \" [STALE]\" : \"\";\n console.log(\n ` ${knob.key} [${knob.valueType}] = ${formatValue(knob.valueType, knob.value)} (${lifecycle}${finalValue})${desc}${stale}`\n );\n }\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs get <key>\");\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, \"--json\");\n const knobs = await fetchKnobs(apiUrl, token);\n const knob = knobs.find((k) => k.key === key);\n\n if (!knob) {\n console.error(`Knob not found: ${key}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(knob, null, 2));\n return;\n }\n\n console.log(` Key: ${knob.key}`);\n console.log(` Type: ${knob.valueType}`);\n console.log(` Value: ${formatValue(knob.valueType, knob.value)}`);\n console.log(` Lifecycle: ${toLifecycleLabel(knob.lifecycleStage)}`);\n console.log(` Final value: ${formatFinalValue(knob)}`);\n console.log(` Description: ${knob.description ?? \"(none)\"}`);\n console.log(` Updated: ${knob.updatedAt ?? \"(never)\"}`);\n if (knob.isStale) {\n console.log(` Status: STALE (no changes in 30+ days)`);\n }\n}\n\nasync function handleSet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs set <key> <value> --type <boolean|string|number|json> [--description <text>]\");\n process.exit(1);\n }\n\n const rawValue = argv[1];\n if (rawValue === undefined || rawValue.startsWith(\"--\")) {\n console.error(\"Error: Missing knob value.\");\n console.error(\"Usage: canary knobs set <key> <value> --type <boolean|string|number|json> [--description <text>]\");\n process.exit(1);\n }\n\n const valueType = getArgValue(argv, \"--type\") as SerializedKnob[\"valueType\"] | undefined;\n if (!valueType || ![\"boolean\", \"string\", \"number\", \"json\"].includes(valueType)) {\n console.error(\"Error: --type is required and must be one of: boolean, string, number, json\");\n process.exit(1);\n }\n\n const value = parseTypedValue(rawValue, valueType);\n const description = getArgValue(argv, \"--description\") ?? undefined;\n\n const result = await apiRequest<KnobApiResponse>(apiUrl, token, \"POST\", \"/superadmin/knobs\", {\n key,\n valueType,\n value,\n description,\n });\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Set knob: ${key} = ${formatValue(valueType, result.knob?.value)}`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs delete <key>\");\n process.exit(1);\n }\n\n const result = await apiRequest<KnobApiResponse>(\n apiUrl, token, \"DELETE\", `/superadmin/knobs/${encodeURIComponent(key)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Deleted knob: ${key}`);\n}\n\nasync function handleToggle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs toggle <key>\");\n process.exit(1);\n }\n\n const result = await apiRequest<KnobApiResponse>(\n apiUrl, token, \"POST\", `/superadmin/knobs/${encodeURIComponent(key)}/toggle`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n const knob = result.knob;\n console.log(`Toggled knob: ${key} -> ${formatValue(knob?.valueType ?? \"boolean\", knob?.value)}`);\n}\n\nasync function handleLifecycle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs lifecycle <key> --stage <active|deprecated|ready_for_cleanup> [--final-value <value>]\");\n process.exit(1);\n }\n\n const stage = parseLifecycleStage(argv, KNOB_LIFECYCLE_STAGES);\n const rawFinalValue = getArgValue(argv, \"--final-value\");\n const clearFinalValue = hasFlag(argv, \"--clear-final-value\");\n\n if (rawFinalValue !== undefined && clearFinalValue) {\n console.error(\"Error: use either --final-value or --clear-final-value, not both.\");\n process.exit(1);\n }\n\n const knobs = await fetchKnobs(apiUrl, token);\n const knob = knobs.find((k) => k.key === key);\n\n if (!knob) {\n console.error(`Knob not found: ${key}`);\n process.exit(1);\n }\n\n let finalValue: unknown = undefined;\n\n if (stage === \"active\") {\n if (rawFinalValue !== undefined) {\n console.error(\"Error: active stage does not accept --final-value. Use --stage deprecated|ready_for_cleanup.\");\n process.exit(1);\n }\n finalValue = clearFinalValue ? undefined : undefined;\n } else {\n if (clearFinalValue) {\n console.error(\"Error: --clear-final-value can only be used with --stage active.\");\n process.exit(1);\n }\n if (rawFinalValue === undefined) {\n console.error(\"Error: --final-value is required when stage is deprecated or ready_for_cleanup.\");\n process.exit(1);\n }\n finalValue = parseTypedValue(rawFinalValue, knob.valueType);\n }\n\n const result = await apiRequest<KnobApiResponse>(\n apiUrl, token, \"POST\", `/superadmin/knobs/${encodeURIComponent(key)}/lifecycle`,\n { stage, finalValue }\n );\n\n if (!result.ok || !result.knob) {\n console.error(`Error: ${result.error ?? \"Failed to update lifecycle\"}`);\n process.exit(1);\n }\n\n console.log(\n `Updated lifecycle for ${key}: stage=${toLifecycleLabel(result.knob.lifecycleStage)}, final=${formatFinalValue(result.knob)}`\n );\n}\n\nfunction printKnobsHelp(): void {\n console.log(\n [\n \"Usage: canary knobs <sub-command> [options]\",\n \"\",\n \"Sub-commands:\",\n \" list List all knobs\",\n \" get <key> Get a knob value\",\n \" set <key> <value> --type <type> [--description <text>]\",\n \" Set a knob value\",\n \" delete <key> Delete a knob\",\n \" toggle <key> Toggle a boolean knob\",\n \" lifecycle <key> --stage <stage> [--final-value <value>]\",\n \" Mark knob lifecycle + final value\",\n \"\",\n \"Types: boolean, string, number, json\",\n \"Stages: active, deprecated, ready_for_cleanup\",\n \"\",\n \"Options:\",\n \" --final-value <value> Final value for deprecated/ready_for_cleanup\",\n \" --clear-final-value Clear final value (only valid with --stage active)\",\n \" --env <env> Target environment (prod, dev, local)\",\n \" --json Output as JSON (list/get only)\",\n \" --api-url <url> API URL override (takes precedence over --env)\",\n \" --token <key> API token override\",\n ].join(\"\\n\")\n );\n}\n\nexport async function runKnobs(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === \"help\" || hasFlag(argv, \"--help\", \"-h\")) {\n printKnobsHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case \"list\":\n await handleList(rest, apiUrl, token);\n break;\n case \"get\":\n await handleGet(rest, apiUrl, token);\n break;\n case \"set\":\n await handleSet(rest, apiUrl, token);\n break;\n case \"delete\":\n await handleDelete(rest, apiUrl, token);\n break;\n case \"toggle\":\n await handleToggle(rest, apiUrl, token);\n break;\n case \"lifecycle\":\n await handleLifecycle(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printKnobsHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,13 +2,14 @@ import { createRequire as __cr } from "module"; const require = __cr(import.meta
|
|
|
2
2
|
import {
|
|
3
3
|
fetchList,
|
|
4
4
|
fetchProperties
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-SJJW77WN.js";
|
|
5
|
+
} from "./chunk-PRBRSIZP.js";
|
|
7
6
|
import "./chunk-3CZU7XCS.js";
|
|
8
7
|
import {
|
|
9
8
|
resolveConfig
|
|
10
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-3X3NW7QA.js";
|
|
10
|
+
import "./chunk-JMJVGMXI.js";
|
|
11
11
|
import "./chunk-JWHYXEA2.js";
|
|
12
|
+
import "./chunk-JYGNMKZ5.js";
|
|
12
13
|
import "./chunk-VKVL7WBN.js";
|
|
13
14
|
|
|
14
15
|
// src/local/list.ts
|
|
@@ -56,4 +57,4 @@ async function runLocalList(argv) {
|
|
|
56
57
|
export {
|
|
57
58
|
runLocalList
|
|
58
59
|
};
|
|
59
|
-
//# sourceMappingURL=list-
|
|
60
|
+
//# sourceMappingURL=list-ZMIKEC5P.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/local/list.ts"],"sourcesContent":["/**\n * `canary local list` — List all local environments for the current user.\n *\n * @module\n */\n\nimport { resolveConfig } from '../auth.js';\nimport { fetchProperties, fetchList } from '../cli-helpers.js';\n\ninterface LocalEnvironment {\n id: string;\n name: string;\n url: string;\n propertyId: string;\n}\n\nexport async function runLocalList(argv: string[]) {\n const config = await resolveConfig(argv);\n\n const properties = await fetchProperties(config.apiUrl, config.token);\n\n if (properties.length === 0) {\n console.log('No properties found.');\n return;\n }\n\n const rows: Array<{ envId: string; property: string; name: string; url: string }> = [];\n\n for (const property of properties) {\n const envs = await fetchList<LocalEnvironment>(\n config.apiUrl,\n config.token,\n `/org/properties/${property.id}/environments/local`,\n 'items'\n );\n\n for (const env of envs) {\n rows.push({\n envId: env.id,\n property: property.name,\n name: env.name,\n url: env.url,\n });\n }\n }\n\n if (rows.length === 0) {\n console.log('No local environments found. Run `canary local init` to create one.');\n return;\n }\n\n // Print table\n const headers = ['ENV ID', 'PROPERTY', 'NAME', 'URL'];\n const widths = headers.map((h, i) => {\n const col = [h, ...rows.map((r) => Object.values(r)[i])];\n return Math.max(...col.map((v) => v.length));\n });\n\n const sep = widths.map((w) => '-'.repeat(w)).join(' ');\n const formatRow = (vals: string[]) => vals.map((v, i) => v.padEnd(widths[i])).join(' ');\n\n console.log(formatRow(headers));\n console.log(sep);\n for (const row of rows) {\n console.log(formatRow([row.envId, row.property, row.name, row.url]));\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/local/list.ts"],"sourcesContent":["/**\n * `canary local list` — List all local environments for the current user.\n *\n * @module\n */\n\nimport { resolveConfig } from '../auth.js';\nimport { fetchProperties, fetchList } from '../cli-helpers.js';\n\ninterface LocalEnvironment {\n id: string;\n name: string;\n url: string;\n propertyId: string;\n}\n\nexport async function runLocalList(argv: string[]) {\n const config = await resolveConfig(argv);\n\n const properties = await fetchProperties(config.apiUrl, config.token);\n\n if (properties.length === 0) {\n console.log('No properties found.');\n return;\n }\n\n const rows: Array<{ envId: string; property: string; name: string; url: string }> = [];\n\n for (const property of properties) {\n const envs = await fetchList<LocalEnvironment>(\n config.apiUrl,\n config.token,\n `/org/properties/${property.id}/environments/local`,\n 'items'\n );\n\n for (const env of envs) {\n rows.push({\n envId: env.id,\n property: property.name,\n name: env.name,\n url: env.url,\n });\n }\n }\n\n if (rows.length === 0) {\n console.log('No local environments found. Run `canary local init` to create one.');\n return;\n }\n\n // Print table\n const headers = ['ENV ID', 'PROPERTY', 'NAME', 'URL'];\n const widths = headers.map((h, i) => {\n const col = [h, ...rows.map((r) => Object.values(r)[i])];\n return Math.max(...col.map((v) => v.length));\n });\n\n const sep = widths.map((w) => '-'.repeat(w)).join(' ');\n const formatRow = (vals: string[]) => vals.map((v, i) => v.padEnd(widths[i])).join(' ');\n\n console.log(formatRow(headers));\n console.log(sep);\n for (const row of rows) {\n console.log(formatRow([row.envId, row.property, row.name, row.url]));\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,eAAsB,aAAa,MAAgB;AACjD,QAAM,SAAS,MAAM,cAAc,IAAI;AAEvC,QAAM,aAAa,MAAM,gBAAgB,OAAO,QAAQ,OAAO,KAAK;AAEpE,MAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,IAAI,sBAAsB;AAClC;AAAA,EACF;AAEA,QAAM,OAA8E,CAAC;AAErF,aAAW,YAAY,YAAY;AACjC,UAAM,OAAO,MAAM;AAAA,MACjB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,mBAAmB,SAAS,EAAE;AAAA,MAC9B;AAAA,IACF;AAEA,eAAW,OAAO,MAAM;AACtB,WAAK,KAAK;AAAA,QACR,OAAO,IAAI;AAAA,QACX,UAAU,SAAS;AAAA,QACnB,MAAM,IAAI;AAAA,QACV,KAAK,IAAI;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,GAAG;AACrB,YAAQ,IAAI,qEAAqE;AACjF;AAAA,EACF;AAGA,QAAM,UAAU,CAAC,UAAU,YAAY,QAAQ,KAAK;AACpD,QAAM,SAAS,QAAQ,IAAI,CAAC,GAAG,MAAM;AACnC,UAAM,MAAM,CAAC,GAAG,GAAG,KAAK,IAAI,CAAC,MAAM,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACvD,WAAO,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAAA,EAC7C,CAAC;AAED,QAAM,MAAM,OAAO,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI;AACtD,QAAM,YAAY,CAAC,SAAmB,KAAK,IAAI,CAAC,GAAG,MAAM,EAAE,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI;AAEvF,UAAQ,IAAI,UAAU,OAAO,CAAC;AAC9B,UAAQ,IAAI,GAAG;AACf,aAAW,OAAO,MAAM;AACtB,YAAQ,IAAI,UAAU,CAAC,IAAI,OAAO,IAAI,UAAU,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC;AAAA,EACrE;AACF;","names":[]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
hasFlag
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3X3NW7QA.js";
|
|
5
|
+
import "./chunk-JMJVGMXI.js";
|
|
5
6
|
import "./chunk-VKVL7WBN.js";
|
|
6
7
|
|
|
7
8
|
// src/local/index.ts
|
|
@@ -69,22 +70,22 @@ async function runLocal(argv) {
|
|
|
69
70
|
}
|
|
70
71
|
switch (subcommand) {
|
|
71
72
|
case "init": {
|
|
72
|
-
const { runLocalInit } = await import("./init-
|
|
73
|
+
const { runLocalInit } = await import("./init-OROOM4HF.js");
|
|
73
74
|
await runLocalInit(rest);
|
|
74
75
|
break;
|
|
75
76
|
}
|
|
76
77
|
case "start": {
|
|
77
|
-
const { runLocalStart } = await import("./start-
|
|
78
|
+
const { runLocalStart } = await import("./start-3C7EEFW2.js");
|
|
78
79
|
await runLocalStart(rest);
|
|
79
80
|
break;
|
|
80
81
|
}
|
|
81
82
|
case "list": {
|
|
82
|
-
const { runLocalList } = await import("./list-
|
|
83
|
+
const { runLocalList } = await import("./list-ZMIKEC5P.js");
|
|
83
84
|
await runLocalList(rest);
|
|
84
85
|
break;
|
|
85
86
|
}
|
|
86
87
|
case "login": {
|
|
87
|
-
const { runLocalLogin } = await import("./login-
|
|
88
|
+
const { runLocalLogin } = await import("./login-BSO7YX2D.js");
|
|
88
89
|
await runLocalLogin(rest);
|
|
89
90
|
break;
|
|
90
91
|
}
|
|
@@ -97,4 +98,4 @@ async function runLocal(argv) {
|
|
|
97
98
|
export {
|
|
98
99
|
runLocal
|
|
99
100
|
};
|
|
100
|
-
//# sourceMappingURL=local-
|
|
101
|
+
//# sourceMappingURL=local-PUD24GGQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/local/index.ts"],"sourcesContent":["/**\n * CLI local command — `canary local <subcommand>`.\n *\n * @module\n */\n\nimport process from 'node:process';\nimport { hasFlag } from '../auth.js';\n\nfunction printHelp() {\n console.log(\n [\n 'canary local — Manage local testing environments',\n '',\n 'Sub-commands:',\n ' init Set up a new local testing environment',\n ' start Start a browser session for a local environment',\n ' list List local environments',\n ' login Re-login / refresh credentials',\n '',\n 'Options for init:',\n ' --property <name|id> Skip property selection prompt',\n ' --url <url> Local testing URL',\n ' --credentials enter|manual|skip Credential setup mode',\n ' --username <u> Username (enter mode)',\n ' --password <p> Password (enter mode)',\n ' --login-url <url> Login page URL (enter mode)',\n ' --login-instructions <text> Free-text login instructions the agent will follow',\n '',\n 'Options for start:',\n ' --property <name|id> Skip property selection prompt',\n ' --environment <name|id> Skip environment selection prompt',\n ' --credential <name|id> Skip credential selection prompt',\n '',\n 'Options for login:',\n ' --property <name|id> Skip property selection prompt',\n ' --environment <name|id> Skip environment selection prompt',\n ' --credential <name|id> Skip credential selection prompt',\n ' --mode agent|manual Agent re-login (no browser) or manual browser login',\n '',\n 'Two setup paths:',\n ' 1. enter — you give us username + password + a sentence describing the login flow.',\n ' The agent can log itself back in whenever a session expires.',\n ' 2. manual — you log in yourself in a browser (SSO, MFA, magic link, etc).',\n ' We store only the session snapshot. When it expires, re-run',\n ' `canary local login` and log in again by hand.',\n '',\n 'For agents helping a user set this up: ask the user for their username + password',\n \"for the app, then run `canary local init --credentials enter --username ... --password ...`\",\n 'so future expirations recover automatically.',\n '',\n 'Common options:',\n ' --env <env> Environment (local, dev, prod)',\n ' --api-url <url> API URL override',\n ' -h, --help Show this help',\n '',\n 'Non-interactive example:',\n ' canary local init --property \"My App\" --url http://localhost:3000 \\\\',\n ' --credentials enter --username user@example.com --password secret \\\\',\n ' --login-url http://localhost:3000/login \\\\',\n ' --login-instructions \"Fill email and password fields, click Continue.\"',\n ].join('\\n')\n );\n}\n\nexport async function runLocal(argv: string[]) {\n const [subcommand, ...rest] = argv;\n\n if (!subcommand || subcommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printHelp();\n return;\n }\n\n switch (subcommand) {\n case 'init': {\n const { runLocalInit } = await import('./init.js');\n await runLocalInit(rest);\n break;\n }\n case 'start': {\n const { runLocalStart } = await import('./start.js');\n await runLocalStart(rest);\n break;\n }\n case 'list': {\n const { runLocalList } = await import('./list.js');\n await runLocalList(rest);\n break;\n }\n case 'login': {\n const { runLocalLogin } = await import('./login.js');\n await runLocalLogin(rest);\n break;\n }\n default:\n console.error(`Unknown sub-command: ${subcommand}`);\n printHelp();\n process.exitCode = 1;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/local/index.ts"],"sourcesContent":["/**\n * CLI local command — `canary local <subcommand>`.\n *\n * @module\n */\n\nimport process from 'node:process';\nimport { hasFlag } from '../auth.js';\n\nfunction printHelp() {\n console.log(\n [\n 'canary local — Manage local testing environments',\n '',\n 'Sub-commands:',\n ' init Set up a new local testing environment',\n ' start Start a browser session for a local environment',\n ' list List local environments',\n ' login Re-login / refresh credentials',\n '',\n 'Options for init:',\n ' --property <name|id> Skip property selection prompt',\n ' --url <url> Local testing URL',\n ' --credentials enter|manual|skip Credential setup mode',\n ' --username <u> Username (enter mode)',\n ' --password <p> Password (enter mode)',\n ' --login-url <url> Login page URL (enter mode)',\n ' --login-instructions <text> Free-text login instructions the agent will follow',\n '',\n 'Options for start:',\n ' --property <name|id> Skip property selection prompt',\n ' --environment <name|id> Skip environment selection prompt',\n ' --credential <name|id> Skip credential selection prompt',\n '',\n 'Options for login:',\n ' --property <name|id> Skip property selection prompt',\n ' --environment <name|id> Skip environment selection prompt',\n ' --credential <name|id> Skip credential selection prompt',\n ' --mode agent|manual Agent re-login (no browser) or manual browser login',\n '',\n 'Two setup paths:',\n ' 1. enter — you give us username + password + a sentence describing the login flow.',\n ' The agent can log itself back in whenever a session expires.',\n ' 2. manual — you log in yourself in a browser (SSO, MFA, magic link, etc).',\n ' We store only the session snapshot. When it expires, re-run',\n ' `canary local login` and log in again by hand.',\n '',\n 'For agents helping a user set this up: ask the user for their username + password',\n \"for the app, then run `canary local init --credentials enter --username ... --password ...`\",\n 'so future expirations recover automatically.',\n '',\n 'Common options:',\n ' --env <env> Environment (local, dev, prod)',\n ' --api-url <url> API URL override',\n ' -h, --help Show this help',\n '',\n 'Non-interactive example:',\n ' canary local init --property \"My App\" --url http://localhost:3000 \\\\',\n ' --credentials enter --username user@example.com --password secret \\\\',\n ' --login-url http://localhost:3000/login \\\\',\n ' --login-instructions \"Fill email and password fields, click Continue.\"',\n ].join('\\n')\n );\n}\n\nexport async function runLocal(argv: string[]) {\n const [subcommand, ...rest] = argv;\n\n if (!subcommand || subcommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printHelp();\n return;\n }\n\n switch (subcommand) {\n case 'init': {\n const { runLocalInit } = await import('./init.js');\n await runLocalInit(rest);\n break;\n }\n case 'start': {\n const { runLocalStart } = await import('./start.js');\n await runLocalStart(rest);\n break;\n }\n case 'list': {\n const { runLocalList } = await import('./list.js');\n await runLocalList(rest);\n break;\n }\n case 'login': {\n const { runLocalLogin } = await import('./login.js');\n await runLocalLogin(rest);\n break;\n }\n default:\n console.error(`Unknown sub-command: ${subcommand}`);\n printHelp();\n process.exitCode = 1;\n }\n}\n"],"mappings":";;;;;;;;AAMA,OAAO,aAAa;AAGpB,SAAS,YAAY;AACnB,UAAQ;AAAA,IACN;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;AAEA,eAAsB,SAAS,MAAgB;AAC7C,QAAM,CAAC,YAAY,GAAG,IAAI,IAAI;AAE9B,MAAI,CAAC,cAAc,eAAe,UAAU,QAAQ,MAAM,UAAU,IAAI,GAAG;AACzE,cAAU;AACV;AAAA,EACF;AAEA,UAAQ,YAAY;AAAA,IAClB,KAAK,QAAQ;AACX,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,oBAAW;AACjD,YAAM,aAAa,IAAI;AACvB;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,YAAM,cAAc,IAAI;AACxB;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,oBAAW;AACjD,YAAM,aAAa,IAAI;AACvB;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,YAAM,cAAc,IAAI;AACxB;AAAA,IACF;AAAA,IACA;AACE,cAAQ,MAAM,wBAAwB,UAAU,EAAE;AAClD,gBAAU;AACV,cAAQ,WAAW;AAAA,EACvB;AACF;","names":[]}
|
|
@@ -10,14 +10,15 @@ import {
|
|
|
10
10
|
promptChoice,
|
|
11
11
|
selectProperty,
|
|
12
12
|
uploadStorageState
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-SJJW77WN.js";
|
|
13
|
+
} from "./chunk-PRBRSIZP.js";
|
|
15
14
|
import "./chunk-3CZU7XCS.js";
|
|
16
15
|
import {
|
|
17
16
|
getArgValue,
|
|
18
17
|
resolveConfig
|
|
19
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-3X3NW7QA.js";
|
|
19
|
+
import "./chunk-JMJVGMXI.js";
|
|
20
20
|
import "./chunk-JWHYXEA2.js";
|
|
21
|
+
import "./chunk-JYGNMKZ5.js";
|
|
21
22
|
import "./chunk-VKVL7WBN.js";
|
|
22
23
|
|
|
23
24
|
// src/local/login.ts
|
|
@@ -312,4 +313,4 @@ Opening browser at ${args.url}...`);
|
|
|
312
313
|
export {
|
|
313
314
|
runLocalLogin
|
|
314
315
|
};
|
|
315
|
-
//# sourceMappingURL=login-
|
|
316
|
+
//# sourceMappingURL=login-BSO7YX2D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/local/login.ts"],"sourcesContent":["/**\n * `canary local login` — Re-login / refresh credentials for a local environment.\n *\n * @module\n */\n\nimport process from 'node:process';\nimport { createParser, type EventSourceMessage } from 'eventsource-parser';\nimport { getArgValue, resolveConfig } from '../auth.js';\nimport {\n selectProperty,\n promptChoice,\n fetchList,\n uploadStorageState,\n apiRequest,\n} from '../cli-helpers.js';\nimport {\n createSession,\n deleteSession,\n getSessionStorageState,\n} from '../session/daemon-client.js';\nimport type { CredentialListItem } from '../cli-helpers.js';\n\ninterface LocalEnvironment {\n id: string;\n name: string;\n url: string;\n propertyId: string;\n}\n\nexport async function runLocalLogin(argv: string[]) {\n const config = await resolveConfig(argv);\n const propertyHint = getArgValue(argv, '--property');\n const envHint = getArgValue(argv, '--environment');\n const credentialHint = getArgValue(argv, '--credential');\n const modeFlag = getArgValue(argv, '--mode');\n\n if (modeFlag && modeFlag !== 'agent' && modeFlag !== 'manual') {\n console.error(`--mode must be one of: agent, manual (got \"${modeFlag}\")`);\n process.exitCode = 1;\n return;\n }\n\n // Select property\n const property = await selectProperty(config.apiUrl, config.token, propertyHint);\n if (!property) {\n process.exitCode = 1;\n return;\n }\n\n // Get local environments\n const envs = await fetchList<LocalEnvironment>(\n config.apiUrl,\n config.token,\n `/org/properties/${property.id}/environments/local`,\n 'items'\n );\n\n if (envs.length === 0) {\n console.error('No local environments found. Run `canary local init` first.');\n process.exitCode = 1;\n return;\n }\n\n let selectedEnv: LocalEnvironment;\n if (envHint) {\n const match = envs.find(\n (e) => e.id === envHint || e.name.toLowerCase() === envHint.toLowerCase()\n );\n if (!match) {\n console.error(`Environment \"${envHint}\" not found.`);\n console.error('Available environments:');\n for (const e of envs) {\n console.error(` - ${e.name} (${e.url})`);\n }\n process.exitCode = 1;\n return;\n }\n selectedEnv = match;\n } else if (envs.length === 1) {\n selectedEnv = envs[0];\n } else {\n const picked = await promptChoice(\n 'Select a local environment:',\n envs.map((e) => ({ label: `${e.name} — ${e.url}`, value: e }))\n );\n if (!picked) {\n process.exitCode = 1;\n return;\n }\n selectedEnv = picked;\n }\n\n // Find credentials for this property\n const allCredentials = await fetchList<CredentialListItem>(\n config.apiUrl,\n config.token,\n '/org/credentials',\n 'items'\n );\n\n const envCredentials = allCredentials.filter(\n (c) => c.propertyId === property.id\n );\n\n if (envCredentials.length === 0) {\n console.error('No credentials found for this property.');\n process.exitCode = 1;\n return;\n }\n\n let credential: CredentialListItem;\n if (credentialHint) {\n const match = envCredentials.find(\n (c) => c.id === credentialHint || c.name.toLowerCase() === credentialHint.toLowerCase()\n );\n if (!match) {\n console.error(`Credential \"${credentialHint}\" not found.`);\n console.error('Available credentials:');\n for (const c of envCredentials) {\n console.error(` - ${c.name}`);\n }\n process.exitCode = 1;\n return;\n }\n credential = match;\n } else if (envCredentials.length === 1) {\n credential = envCredentials[0];\n } else {\n const picked = await promptChoice(\n 'Select a credential to refresh:',\n envCredentials.map((c) => ({ label: c.name, value: c }))\n );\n if (!picked) {\n process.exitCode = 1;\n return;\n }\n credential = picked;\n }\n\n // If the credential has login instructions + stored creds, offer the no-browser path first.\n const detail = await fetchCredentialLoginInfo(\n config.apiUrl,\n config.token,\n property.id,\n credential.id\n );\n const canAgentLogin = Boolean(\n detail?.loginInstructions &&\n detail.data?.username &&\n detail.data?.password &&\n (detail.loginUrl || selectedEnv.url)\n );\n\n let mode: 'agent' | 'manual';\n if (modeFlag === 'agent' || modeFlag === 'manual') {\n if (modeFlag === 'agent' && !canAgentLogin) {\n console.error(\n 'Credential is missing login instructions or stored username/password; cannot run agent login.'\n );\n process.exitCode = 1;\n return;\n }\n mode = modeFlag;\n } else if (canAgentLogin) {\n const choice = await promptChoice<'agent' | 'manual'>('How would you like to log in?', [\n { label: 'Let the agent log in (no browser, fastest) — recommended', value: 'agent' },\n { label: \"Open a browser and I'll log in myself\", value: 'manual' },\n ]);\n if (!choice) {\n process.exitCode = 1;\n return;\n }\n mode = choice;\n } else {\n if (!detail?.loginInstructions) {\n console.log(\n '\\nTip: add login instructions to this credential so the agent can log in for you next time.'\n );\n }\n mode = 'manual';\n }\n\n if (mode === 'agent') {\n const ok = await runAgentLogin({\n apiUrl: config.apiUrl,\n token: config.token,\n propertyId: property.id,\n credentialId: credential.id,\n credentialName: credential.name,\n });\n if (!ok) {\n console.log('\\nFalling back to manual browser login.');\n await runManualLogin({\n apiUrl: config.apiUrl,\n token: config.token,\n propertyId: property.id,\n credentialId: credential.id,\n url: selectedEnv.url,\n });\n }\n return;\n }\n\n await runManualLogin({\n apiUrl: config.apiUrl,\n token: config.token,\n propertyId: property.id,\n credentialId: credential.id,\n url: selectedEnv.url,\n });\n}\n\ntype CredentialLoginInfo = {\n id: string;\n name: string;\n authProvider?: string;\n loginUrl?: string | null;\n loginInstructions?: string | null;\n data?: { username?: string; password?: string } | null;\n};\n\nasync function fetchCredentialLoginInfo(\n apiUrl: string,\n token: string,\n propertyId: string,\n credentialId: string\n): Promise<CredentialLoginInfo | null> {\n const result = await apiRequest<{\n ok: boolean;\n credential?: CredentialLoginInfo;\n error?: string;\n }>(apiUrl, token, 'GET', `/org/properties/${propertyId}/credentials/${credentialId}`);\n if (!result.ok || !result.credential) return null;\n return result.credential;\n}\n\nasync function runAgentLogin(args: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n credentialName: string;\n}): Promise<boolean> {\n console.log(`\\nAsking the agent to log in as \"${args.credentialName}\"...`);\n\n const res = await fetch(\n `${args.apiUrl}/org/properties/${args.propertyId}/credentials/${args.credentialId}/mcp-test/stream`,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${args.token}`,\n Accept: 'text/event-stream',\n },\n }\n );\n\n if (!res.ok || !res.body) {\n console.error(`Agent login could not start (HTTP ${res.status}).`);\n return false;\n }\n\n let success: boolean | null = null;\n let errorMessage: string | null = null;\n\n const parser = createParser({\n onEvent: (event: EventSourceMessage) => {\n if (!event.data) return;\n let data: unknown;\n try {\n data = JSON.parse(event.data);\n } catch {\n return;\n }\n\n switch (event.event) {\n case 'status': {\n const { message } = data as { message?: string };\n if (message) console.log(` ${message}`);\n break;\n }\n case 'log': {\n const { level, message } = data as { level?: string; message?: string };\n if (message && level !== 'debug') {\n console.log(` ${message}`);\n }\n break;\n }\n case 'complete': {\n const summary = data as { ok?: boolean; message?: string | null };\n success = summary.ok === true;\n if (!success && summary.message) errorMessage = summary.message;\n break;\n }\n case 'error': {\n const { message } = data as { message?: string };\n errorMessage = message ?? 'Agent login failed';\n success = false;\n break;\n }\n }\n },\n });\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n parser.feed(decoder.decode(value, { stream: true }));\n if (success !== null && !success && errorMessage) break;\n }\n\n if (success) {\n console.log('\\nLogin state refreshed by agent. Run `canary local start` to begin.');\n return true;\n }\n\n console.error(`\\nAgent login failed: ${errorMessage ?? 'unknown error'}`);\n return false;\n}\n\nasync function runManualLogin(args: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n url: string;\n}): Promise<void> {\n console.log(`\\nOpening browser at ${args.url}...`);\n const sessionResult = await createSession({\n name: 'local-login',\n url: args.url,\n });\n\n if (!sessionResult.ok || !sessionResult.data) {\n console.error(`Failed to start browser: ${sessionResult.error ?? 'Unknown error'}`);\n process.exitCode = 1;\n return;\n }\n\n const sessionId = sessionResult.data.id;\n\n console.log('Log in, then press Enter when done.');\n\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n await new Promise<void>((resolve) => {\n rl.question('', () => {\n rl.close();\n resolve();\n });\n });\n\n console.log('Extracting login state...');\n const storageResult = await getSessionStorageState(sessionId);\n\n if (!storageResult.ok || !storageResult.data) {\n console.error(`Failed to extract storage state: ${storageResult.error ?? 'Unknown error'}`);\n await deleteSession(sessionId);\n process.exitCode = 1;\n return;\n }\n\n console.log('Saving login state...');\n const uploadResult = await uploadStorageState({\n apiUrl: args.apiUrl,\n token: args.token,\n propertyId: args.propertyId,\n credentialId: args.credentialId,\n storageState: storageResult.data,\n });\n\n if (!uploadResult.ok) {\n console.error(`Failed to save login state: ${uploadResult.error ?? 'Unknown error'}`);\n await deleteSession(sessionId);\n process.exitCode = 1;\n return;\n }\n\n await deleteSession(sessionId);\n console.log('\\nLogin state refreshed! Run `canary local start` to begin.');\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/local/login.ts"],"sourcesContent":["/**\n * `canary local login` — Re-login / refresh credentials for a local environment.\n *\n * @module\n */\n\nimport process from 'node:process';\nimport { createParser, type EventSourceMessage } from 'eventsource-parser';\nimport { getArgValue, resolveConfig } from '../auth.js';\nimport {\n selectProperty,\n promptChoice,\n fetchList,\n uploadStorageState,\n apiRequest,\n} from '../cli-helpers.js';\nimport {\n createSession,\n deleteSession,\n getSessionStorageState,\n} from '../session/daemon-client.js';\nimport type { CredentialListItem } from '../cli-helpers.js';\n\ninterface LocalEnvironment {\n id: string;\n name: string;\n url: string;\n propertyId: string;\n}\n\nexport async function runLocalLogin(argv: string[]) {\n const config = await resolveConfig(argv);\n const propertyHint = getArgValue(argv, '--property');\n const envHint = getArgValue(argv, '--environment');\n const credentialHint = getArgValue(argv, '--credential');\n const modeFlag = getArgValue(argv, '--mode');\n\n if (modeFlag && modeFlag !== 'agent' && modeFlag !== 'manual') {\n console.error(`--mode must be one of: agent, manual (got \"${modeFlag}\")`);\n process.exitCode = 1;\n return;\n }\n\n // Select property\n const property = await selectProperty(config.apiUrl, config.token, propertyHint);\n if (!property) {\n process.exitCode = 1;\n return;\n }\n\n // Get local environments\n const envs = await fetchList<LocalEnvironment>(\n config.apiUrl,\n config.token,\n `/org/properties/${property.id}/environments/local`,\n 'items'\n );\n\n if (envs.length === 0) {\n console.error('No local environments found. Run `canary local init` first.');\n process.exitCode = 1;\n return;\n }\n\n let selectedEnv: LocalEnvironment;\n if (envHint) {\n const match = envs.find(\n (e) => e.id === envHint || e.name.toLowerCase() === envHint.toLowerCase()\n );\n if (!match) {\n console.error(`Environment \"${envHint}\" not found.`);\n console.error('Available environments:');\n for (const e of envs) {\n console.error(` - ${e.name} (${e.url})`);\n }\n process.exitCode = 1;\n return;\n }\n selectedEnv = match;\n } else if (envs.length === 1) {\n selectedEnv = envs[0];\n } else {\n const picked = await promptChoice(\n 'Select a local environment:',\n envs.map((e) => ({ label: `${e.name} — ${e.url}`, value: e }))\n );\n if (!picked) {\n process.exitCode = 1;\n return;\n }\n selectedEnv = picked;\n }\n\n // Find credentials for this property\n const allCredentials = await fetchList<CredentialListItem>(\n config.apiUrl,\n config.token,\n '/org/credentials',\n 'items'\n );\n\n const envCredentials = allCredentials.filter(\n (c) => c.propertyId === property.id\n );\n\n if (envCredentials.length === 0) {\n console.error('No credentials found for this property.');\n process.exitCode = 1;\n return;\n }\n\n let credential: CredentialListItem;\n if (credentialHint) {\n const match = envCredentials.find(\n (c) => c.id === credentialHint || c.name.toLowerCase() === credentialHint.toLowerCase()\n );\n if (!match) {\n console.error(`Credential \"${credentialHint}\" not found.`);\n console.error('Available credentials:');\n for (const c of envCredentials) {\n console.error(` - ${c.name}`);\n }\n process.exitCode = 1;\n return;\n }\n credential = match;\n } else if (envCredentials.length === 1) {\n credential = envCredentials[0];\n } else {\n const picked = await promptChoice(\n 'Select a credential to refresh:',\n envCredentials.map((c) => ({ label: c.name, value: c }))\n );\n if (!picked) {\n process.exitCode = 1;\n return;\n }\n credential = picked;\n }\n\n // If the credential has login instructions + stored creds, offer the no-browser path first.\n const detail = await fetchCredentialLoginInfo(\n config.apiUrl,\n config.token,\n property.id,\n credential.id\n );\n const canAgentLogin = Boolean(\n detail?.loginInstructions &&\n detail.data?.username &&\n detail.data?.password &&\n (detail.loginUrl || selectedEnv.url)\n );\n\n let mode: 'agent' | 'manual';\n if (modeFlag === 'agent' || modeFlag === 'manual') {\n if (modeFlag === 'agent' && !canAgentLogin) {\n console.error(\n 'Credential is missing login instructions or stored username/password; cannot run agent login.'\n );\n process.exitCode = 1;\n return;\n }\n mode = modeFlag;\n } else if (canAgentLogin) {\n const choice = await promptChoice<'agent' | 'manual'>('How would you like to log in?', [\n { label: 'Let the agent log in (no browser, fastest) — recommended', value: 'agent' },\n { label: \"Open a browser and I'll log in myself\", value: 'manual' },\n ]);\n if (!choice) {\n process.exitCode = 1;\n return;\n }\n mode = choice;\n } else {\n if (!detail?.loginInstructions) {\n console.log(\n '\\nTip: add login instructions to this credential so the agent can log in for you next time.'\n );\n }\n mode = 'manual';\n }\n\n if (mode === 'agent') {\n const ok = await runAgentLogin({\n apiUrl: config.apiUrl,\n token: config.token,\n propertyId: property.id,\n credentialId: credential.id,\n credentialName: credential.name,\n });\n if (!ok) {\n console.log('\\nFalling back to manual browser login.');\n await runManualLogin({\n apiUrl: config.apiUrl,\n token: config.token,\n propertyId: property.id,\n credentialId: credential.id,\n url: selectedEnv.url,\n });\n }\n return;\n }\n\n await runManualLogin({\n apiUrl: config.apiUrl,\n token: config.token,\n propertyId: property.id,\n credentialId: credential.id,\n url: selectedEnv.url,\n });\n}\n\ntype CredentialLoginInfo = {\n id: string;\n name: string;\n authProvider?: string;\n loginUrl?: string | null;\n loginInstructions?: string | null;\n data?: { username?: string; password?: string } | null;\n};\n\nasync function fetchCredentialLoginInfo(\n apiUrl: string,\n token: string,\n propertyId: string,\n credentialId: string\n): Promise<CredentialLoginInfo | null> {\n const result = await apiRequest<{\n ok: boolean;\n credential?: CredentialLoginInfo;\n error?: string;\n }>(apiUrl, token, 'GET', `/org/properties/${propertyId}/credentials/${credentialId}`);\n if (!result.ok || !result.credential) return null;\n return result.credential;\n}\n\nasync function runAgentLogin(args: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n credentialName: string;\n}): Promise<boolean> {\n console.log(`\\nAsking the agent to log in as \"${args.credentialName}\"...`);\n\n const res = await fetch(\n `${args.apiUrl}/org/properties/${args.propertyId}/credentials/${args.credentialId}/mcp-test/stream`,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${args.token}`,\n Accept: 'text/event-stream',\n },\n }\n );\n\n if (!res.ok || !res.body) {\n console.error(`Agent login could not start (HTTP ${res.status}).`);\n return false;\n }\n\n let success: boolean | null = null;\n let errorMessage: string | null = null;\n\n const parser = createParser({\n onEvent: (event: EventSourceMessage) => {\n if (!event.data) return;\n let data: unknown;\n try {\n data = JSON.parse(event.data);\n } catch {\n return;\n }\n\n switch (event.event) {\n case 'status': {\n const { message } = data as { message?: string };\n if (message) console.log(` ${message}`);\n break;\n }\n case 'log': {\n const { level, message } = data as { level?: string; message?: string };\n if (message && level !== 'debug') {\n console.log(` ${message}`);\n }\n break;\n }\n case 'complete': {\n const summary = data as { ok?: boolean; message?: string | null };\n success = summary.ok === true;\n if (!success && summary.message) errorMessage = summary.message;\n break;\n }\n case 'error': {\n const { message } = data as { message?: string };\n errorMessage = message ?? 'Agent login failed';\n success = false;\n break;\n }\n }\n },\n });\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n parser.feed(decoder.decode(value, { stream: true }));\n if (success !== null && !success && errorMessage) break;\n }\n\n if (success) {\n console.log('\\nLogin state refreshed by agent. Run `canary local start` to begin.');\n return true;\n }\n\n console.error(`\\nAgent login failed: ${errorMessage ?? 'unknown error'}`);\n return false;\n}\n\nasync function runManualLogin(args: {\n apiUrl: string;\n token: string;\n propertyId: string;\n credentialId: string;\n url: string;\n}): Promise<void> {\n console.log(`\\nOpening browser at ${args.url}...`);\n const sessionResult = await createSession({\n name: 'local-login',\n url: args.url,\n });\n\n if (!sessionResult.ok || !sessionResult.data) {\n console.error(`Failed to start browser: ${sessionResult.error ?? 'Unknown error'}`);\n process.exitCode = 1;\n return;\n }\n\n const sessionId = sessionResult.data.id;\n\n console.log('Log in, then press Enter when done.');\n\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n await new Promise<void>((resolve) => {\n rl.question('', () => {\n rl.close();\n resolve();\n });\n });\n\n console.log('Extracting login state...');\n const storageResult = await getSessionStorageState(sessionId);\n\n if (!storageResult.ok || !storageResult.data) {\n console.error(`Failed to extract storage state: ${storageResult.error ?? 'Unknown error'}`);\n await deleteSession(sessionId);\n process.exitCode = 1;\n return;\n }\n\n console.log('Saving login state...');\n const uploadResult = await uploadStorageState({\n apiUrl: args.apiUrl,\n token: args.token,\n propertyId: args.propertyId,\n credentialId: args.credentialId,\n storageState: storageResult.data,\n });\n\n if (!uploadResult.ok) {\n console.error(`Failed to save login state: ${uploadResult.error ?? 'Unknown error'}`);\n await deleteSession(sessionId);\n process.exitCode = 1;\n return;\n }\n\n await deleteSession(sessionId);\n console.log('\\nLogin state refreshed! Run `canary local start` to begin.');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAMA,OAAO,aAAa;AACpB,SAAS,oBAA6C;AAuBtD,eAAsB,cAAc,MAAgB;AAClD,QAAM,SAAS,MAAM,cAAc,IAAI;AACvC,QAAM,eAAe,YAAY,MAAM,YAAY;AACnD,QAAM,UAAU,YAAY,MAAM,eAAe;AACjD,QAAM,iBAAiB,YAAY,MAAM,cAAc;AACvD,QAAM,WAAW,YAAY,MAAM,QAAQ;AAE3C,MAAI,YAAY,aAAa,WAAW,aAAa,UAAU;AAC7D,YAAQ,MAAM,8CAA8C,QAAQ,IAAI;AACxE,YAAQ,WAAW;AACnB;AAAA,EACF;AAGA,QAAM,WAAW,MAAM,eAAe,OAAO,QAAQ,OAAO,OAAO,YAAY;AAC/E,MAAI,CAAC,UAAU;AACb,YAAQ,WAAW;AACnB;AAAA,EACF;AAGA,QAAM,OAAO,MAAM;AAAA,IACjB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,mBAAmB,SAAS,EAAE;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,GAAG;AACrB,YAAQ,MAAM,6DAA6D;AAC3E,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,SAAS;AACX,UAAM,QAAQ,KAAK;AAAA,MACjB,CAAC,MAAM,EAAE,OAAO,WAAW,EAAE,KAAK,YAAY,MAAM,QAAQ,YAAY;AAAA,IAC1E;AACA,QAAI,CAAC,OAAO;AACV,cAAQ,MAAM,gBAAgB,OAAO,cAAc;AACnD,cAAQ,MAAM,yBAAyB;AACvC,iBAAW,KAAK,MAAM;AACpB,gBAAQ,MAAM,OAAO,EAAE,IAAI,KAAK,EAAE,GAAG,GAAG;AAAA,MAC1C;AACA,cAAQ,WAAW;AACnB;AAAA,IACF;AACA,kBAAc;AAAA,EAChB,WAAW,KAAK,WAAW,GAAG;AAC5B,kBAAc,KAAK,CAAC;AAAA,EACtB,OAAO;AACL,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,KAAK,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE,IAAI,WAAM,EAAE,GAAG,IAAI,OAAO,EAAE,EAAE;AAAA,IAC/D;AACA,QAAI,CAAC,QAAQ;AACX,cAAQ,WAAW;AACnB;AAAA,IACF;AACA,kBAAc;AAAA,EAChB;AAGA,QAAM,iBAAiB,MAAM;AAAA,IAC3B,OAAO;AAAA,IACP,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACF;AAEA,QAAM,iBAAiB,eAAe;AAAA,IACpC,CAAC,MAAM,EAAE,eAAe,SAAS;AAAA,EACnC;AAEA,MAAI,eAAe,WAAW,GAAG;AAC/B,YAAQ,MAAM,yCAAyC;AACvD,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,gBAAgB;AAClB,UAAM,QAAQ,eAAe;AAAA,MAC3B,CAAC,MAAM,EAAE,OAAO,kBAAkB,EAAE,KAAK,YAAY,MAAM,eAAe,YAAY;AAAA,IACxF;AACA,QAAI,CAAC,OAAO;AACV,cAAQ,MAAM,eAAe,cAAc,cAAc;AACzD,cAAQ,MAAM,wBAAwB;AACtC,iBAAW,KAAK,gBAAgB;AAC9B,gBAAQ,MAAM,OAAO,EAAE,IAAI,EAAE;AAAA,MAC/B;AACA,cAAQ,WAAW;AACnB;AAAA,IACF;AACA,iBAAa;AAAA,EACf,WAAW,eAAe,WAAW,GAAG;AACtC,iBAAa,eAAe,CAAC;AAAA,EAC/B,OAAO;AACL,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,eAAe,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,EAAE,EAAE;AAAA,IACzD;AACA,QAAI,CAAC,QAAQ;AACX,cAAQ,WAAW;AACnB;AAAA,IACF;AACA,iBAAa;AAAA,EACf;AAGA,QAAM,SAAS,MAAM;AAAA,IACnB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AACA,QAAM,gBAAgB;AAAA,IACpB,QAAQ,qBACN,OAAO,MAAM,YACb,OAAO,MAAM,aACZ,OAAO,YAAY,YAAY;AAAA,EACpC;AAEA,MAAI;AACJ,MAAI,aAAa,WAAW,aAAa,UAAU;AACjD,QAAI,aAAa,WAAW,CAAC,eAAe;AAC1C,cAAQ;AAAA,QACN;AAAA,MACF;AACA,cAAQ,WAAW;AACnB;AAAA,IACF;AACA,WAAO;AAAA,EACT,WAAW,eAAe;AACxB,UAAM,SAAS,MAAM,aAAiC,iCAAiC;AAAA,MACrF,EAAE,OAAO,iEAA4D,OAAO,QAAQ;AAAA,MACpF,EAAE,OAAO,yCAAyC,OAAO,SAAS;AAAA,IACpE,CAAC;AACD,QAAI,CAAC,QAAQ;AACX,cAAQ,WAAW;AACnB;AAAA,IACF;AACA,WAAO;AAAA,EACT,OAAO;AACL,QAAI,CAAC,QAAQ,mBAAmB;AAC9B,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,SAAS;AACpB,UAAM,KAAK,MAAM,cAAc;AAAA,MAC7B,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO;AAAA,MACd,YAAY,SAAS;AAAA,MACrB,cAAc,WAAW;AAAA,MACzB,gBAAgB,WAAW;AAAA,IAC7B,CAAC;AACD,QAAI,CAAC,IAAI;AACP,cAAQ,IAAI,yCAAyC;AACrD,YAAM,eAAe;AAAA,QACnB,QAAQ,OAAO;AAAA,QACf,OAAO,OAAO;AAAA,QACd,YAAY,SAAS;AAAA,QACrB,cAAc,WAAW;AAAA,QACzB,KAAK,YAAY;AAAA,MACnB,CAAC;AAAA,IACH;AACA;AAAA,EACF;AAEA,QAAM,eAAe;AAAA,IACnB,QAAQ,OAAO;AAAA,IACf,OAAO,OAAO;AAAA,IACd,YAAY,SAAS;AAAA,IACrB,cAAc,WAAW;AAAA,IACzB,KAAK,YAAY;AAAA,EACnB,CAAC;AACH;AAWA,eAAe,yBACb,QACA,OACA,YACA,cACqC;AACrC,QAAM,SAAS,MAAM,WAIlB,QAAQ,OAAO,OAAO,mBAAmB,UAAU,gBAAgB,YAAY,EAAE;AACpF,MAAI,CAAC,OAAO,MAAM,CAAC,OAAO,WAAY,QAAO;AAC7C,SAAO,OAAO;AAChB;AAEA,eAAe,cAAc,MAMR;AACnB,UAAQ,IAAI;AAAA,iCAAoC,KAAK,cAAc,MAAM;AAEzE,QAAM,MAAM,MAAM;AAAA,IAChB,GAAG,KAAK,MAAM,mBAAmB,KAAK,UAAU,gBAAgB,KAAK,YAAY;AAAA,IACjF;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU,KAAK,KAAK;AAAA,QACnC,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM;AACxB,YAAQ,MAAM,qCAAqC,IAAI,MAAM,IAAI;AACjE,WAAO;AAAA,EACT;AAEA,MAAI,UAA0B;AAC9B,MAAI,eAA8B;AAElC,QAAM,SAAS,aAAa;AAAA,IAC1B,SAAS,CAAC,UAA8B;AACtC,UAAI,CAAC,MAAM,KAAM;AACjB,UAAI;AACJ,UAAI;AACF,eAAO,KAAK,MAAM,MAAM,IAAI;AAAA,MAC9B,QAAQ;AACN;AAAA,MACF;AAEA,cAAQ,MAAM,OAAO;AAAA,QACnB,KAAK,UAAU;AACb,gBAAM,EAAE,QAAQ,IAAI;AACpB,cAAI,QAAS,SAAQ,IAAI,KAAK,OAAO,EAAE;AACvC;AAAA,QACF;AAAA,QACA,KAAK,OAAO;AACV,gBAAM,EAAE,OAAO,QAAQ,IAAI;AAC3B,cAAI,WAAW,UAAU,SAAS;AAChC,oBAAQ,IAAI,KAAK,OAAO,EAAE;AAAA,UAC5B;AACA;AAAA,QACF;AAAA,QACA,KAAK,YAAY;AACf,gBAAM,UAAU;AAChB,oBAAU,QAAQ,OAAO;AACzB,cAAI,CAAC,WAAW,QAAQ,QAAS,gBAAe,QAAQ;AACxD;AAAA,QACF;AAAA,QACA,KAAK,SAAS;AACZ,gBAAM,EAAE,QAAQ,IAAI;AACpB,yBAAe,WAAW;AAC1B,oBAAU;AACV;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,SAAS,IAAI,KAAK,UAAU;AAClC,QAAM,UAAU,IAAI,YAAY;AAEhC,SAAO,MAAM;AACX,UAAM,EAAE,OAAO,KAAK,IAAI,MAAM,OAAO,KAAK;AAC1C,QAAI,KAAM;AACV,WAAO,KAAK,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,CAAC;AACnD,QAAI,YAAY,QAAQ,CAAC,WAAW,aAAc;AAAA,EACpD;AAEA,MAAI,SAAS;AACX,YAAQ,IAAI,sEAAsE;AAClF,WAAO;AAAA,EACT;AAEA,UAAQ,MAAM;AAAA,sBAAyB,gBAAgB,eAAe,EAAE;AACxE,SAAO;AACT;AAEA,eAAe,eAAe,MAMZ;AAChB,UAAQ,IAAI;AAAA,qBAAwB,KAAK,GAAG,KAAK;AACjD,QAAM,gBAAgB,MAAM,cAAc;AAAA,IACxC,MAAM;AAAA,IACN,KAAK,KAAK;AAAA,EACZ,CAAC;AAED,MAAI,CAAC,cAAc,MAAM,CAAC,cAAc,MAAM;AAC5C,YAAQ,MAAM,4BAA4B,cAAc,SAAS,eAAe,EAAE;AAClF,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,QAAM,YAAY,cAAc,KAAK;AAErC,UAAQ,IAAI,qCAAqC;AAEjD,QAAM,WAAW,MAAM,OAAO,UAAe;AAC7C,QAAM,KAAK,SAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AACpF,QAAM,IAAI,QAAc,CAAC,YAAY;AACnC,OAAG,SAAS,IAAI,MAAM;AACpB,SAAG,MAAM;AACT,cAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AAED,UAAQ,IAAI,2BAA2B;AACvC,QAAM,gBAAgB,MAAM,uBAAuB,SAAS;AAE5D,MAAI,CAAC,cAAc,MAAM,CAAC,cAAc,MAAM;AAC5C,YAAQ,MAAM,oCAAoC,cAAc,SAAS,eAAe,EAAE;AAC1F,UAAM,cAAc,SAAS;AAC7B,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,UAAQ,IAAI,uBAAuB;AACnC,QAAM,eAAe,MAAM,mBAAmB;AAAA,IAC5C,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK;AAAA,IACZ,YAAY,KAAK;AAAA,IACjB,cAAc,KAAK;AAAA,IACnB,cAAc,cAAc;AAAA,EAC9B,CAAC;AAED,MAAI,CAAC,aAAa,IAAI;AACpB,YAAQ,MAAM,+BAA+B,aAAa,SAAS,eAAe,EAAE;AACpF,UAAM,cAAc,SAAS;AAC7B,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,QAAM,cAAc,SAAS;AAC7B,UAAQ,IAAI,6DAA6D;AAC3E;","names":[]}
|