@canaryai/cli 0.2.12 → 0.2.13
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/{chunk-PWWQGYFG.js → chunk-ACRIE2YR.js} +5 -2
- package/dist/chunk-ACRIE2YR.js.map +1 -0
- package/dist/{chunk-ERSNYLMZ.js → chunk-BOS2YLKH.js} +12 -8
- package/dist/chunk-BOS2YLKH.js.map +1 -0
- package/dist/{chunk-MSMC6UXW.js → chunk-IFOJT3A5.js} +1002 -253
- package/dist/chunk-IFOJT3A5.js.map +1 -0
- package/dist/{chunk-Q7WFBG5C.js → chunk-SVU2XTYZ.js} +19 -5
- package/dist/chunk-SVU2XTYZ.js.map +1 -0
- package/dist/{chunk-A44B2PEA.js → chunk-SYPQF57S.js} +40 -8
- package/dist/chunk-SYPQF57S.js.map +1 -0
- package/dist/{chunk-CEW4BDXD.js → chunk-Z3F373YR.js} +13 -6
- package/dist/chunk-Z3F373YR.js.map +1 -0
- package/dist/{debug-workflow-53ULOFJC.js → debug-workflow-K2LL6CO4.js} +10 -12
- package/dist/debug-workflow-K2LL6CO4.js.map +1 -0
- package/dist/{docs-BEE3LOCO.js → docs-SR7CW24Y.js} +19 -14
- package/dist/docs-SR7CW24Y.js.map +1 -0
- package/dist/{feature-flag-CYTDV4ZB.js → feature-flag-BIPFVVNC.js} +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +36 -30
- package/dist/index.js.map +1 -1
- package/dist/{init-M6I3MG3D.js → init-KXAVWHYE.js} +4 -4
- package/dist/{issues-NLM72HLU.js → issues-EWVB52CA.js} +37 -18
- package/dist/issues-EWVB52CA.js.map +1 -0
- package/dist/{knobs-O35GAU5M.js → knobs-VYABZESR.js} +3 -3
- package/dist/{list-4K4EIGAT.js → list-RCPYLS36.js} +3 -3
- package/dist/list-RCPYLS36.js.map +1 -0
- package/dist/{local-NHXXPHZ3.js → local-34FX3M5K.js} +6 -6
- package/dist/{local-browser-VAZORCO3.js → local-browser-VPOSJS52.js} +4 -4
- package/dist/{login-ZLP64YQP.js → login-MSIM2VIH.js} +4 -4
- package/dist/{mcp-ZF5G5DCB.js → mcp-YBR7G254.js} +7 -10
- package/dist/mcp-YBR7G254.js.map +1 -0
- package/dist/{psql-2YPIRMDY.js → psql-XO5BB5L5.js} +2 -2
- package/dist/{record-V6QKFFH3.js → record-DXXQHPGT.js} +7 -7
- package/dist/record-DXXQHPGT.js.map +1 -0
- package/dist/{redis-A7GWM23E.js → redis-CQTBPZ6F.js} +2 -2
- package/dist/{release-7TI7EIGD.js → release-DW7RPQSQ.js} +2 -2
- package/dist/runner/preload.js +1 -1
- package/dist/{session-UGNJXRUW.js → session-XQGCLWNC.js} +33 -12
- package/dist/{session-UGNJXRUW.js.map → session-XQGCLWNC.js.map} +1 -1
- package/dist/{skill-ORWAPBDW.js → skill-2TXI3IKP.js} +1 -1
- package/dist/skill-2TXI3IKP.js.map +1 -0
- package/dist/{src-4VIDSK4A.js → src-F7LQ5PY2.js} +8 -2
- package/dist/{start-E532F3BU.js → start-ZOMUD6LW.js} +4 -4
- package/dist/test.js +1 -1
- package/dist/test.js.map +1 -1
- package/dist/{workflow-HXIUXRFI.js → workflow-5UZTKX7X.js} +21 -10
- package/dist/workflow-5UZTKX7X.js.map +1 -0
- package/package.json +1 -2
- package/dist/chunk-A44B2PEA.js.map +0 -1
- package/dist/chunk-CEW4BDXD.js.map +0 -1
- package/dist/chunk-ERSNYLMZ.js.map +0 -1
- package/dist/chunk-MSMC6UXW.js.map +0 -1
- package/dist/chunk-PWWQGYFG.js.map +0 -1
- package/dist/chunk-Q7WFBG5C.js.map +0 -1
- package/dist/debug-workflow-53ULOFJC.js.map +0 -1
- package/dist/docs-BEE3LOCO.js.map +0 -1
- package/dist/issues-NLM72HLU.js.map +0 -1
- package/dist/list-4K4EIGAT.js.map +0 -1
- package/dist/mcp-ZF5G5DCB.js.map +0 -1
- package/dist/record-V6QKFFH3.js.map +0 -1
- package/dist/skill-ORWAPBDW.js.map +0 -1
- package/dist/workflow-HXIUXRFI.js.map +0 -1
- /package/dist/{feature-flag-CYTDV4ZB.js.map → feature-flag-BIPFVVNC.js.map} +0 -0
- /package/dist/{init-M6I3MG3D.js.map → init-KXAVWHYE.js.map} +0 -0
- /package/dist/{knobs-O35GAU5M.js.map → knobs-VYABZESR.js.map} +0 -0
- /package/dist/{local-NHXXPHZ3.js.map → local-34FX3M5K.js.map} +0 -0
- /package/dist/{local-browser-VAZORCO3.js.map → local-browser-VPOSJS52.js.map} +0 -0
- /package/dist/{login-ZLP64YQP.js.map → login-MSIM2VIH.js.map} +0 -0
- /package/dist/{psql-2YPIRMDY.js.map → psql-XO5BB5L5.js.map} +0 -0
- /package/dist/{redis-A7GWM23E.js.map → redis-CQTBPZ6F.js.map} +0 -0
- /package/dist/{release-7TI7EIGD.js.map → release-DW7RPQSQ.js.map} +0 -0
- /package/dist/{src-4VIDSK4A.js.map → src-F7LQ5PY2.js.map} +0 -0
- /package/dist/{start-E532F3BU.js.map → start-ZOMUD6LW.js.map} +0 -0
|
@@ -0,0 +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 } 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 IssueOccurrence = {\n id: string;\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};\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 | 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};\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 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 * 100)}% 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 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 = getArgValue(argv, '--property-id');\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 console.log(JSON.stringify({ data: result.data, pagination: result.pagination }, null, 2));\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 console.log(\n ` [${icon}] ${truncate(issue.title, 60)} ${statusLabel} ${lastSeen} (${issue.occurrenceCount}x) ${issue.id}`\n );\n }\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 markdownOutput = getArgValue(argv, '--format') === 'markdown';\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 const { consoleErrors, networkErrors } = await fetchDiagnostics(apiUrl, token, issue);\n\n if (jsonOutput) {\n console.log(JSON.stringify({ ...result.data, consoleErrors, networkErrors }, null, 2));\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 (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 * 100)}%)`);\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\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 '',\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 ' --property-id <uuid> Filter by property',\n ' --page <n> Page number (default: 1)',\n ' --page-size <n> Page size (default: 25)',\n '',\n 'Output options:',\n ' --json Output raw JSON',\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 default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printIssuesHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
fetchList,
|
|
5
5
|
parseLifecycleStage,
|
|
6
6
|
toLifecycleLabel
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-BOS2YLKH.js";
|
|
8
8
|
import {
|
|
9
9
|
getArgValue,
|
|
10
10
|
hasFlag,
|
|
11
11
|
resolveConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ACRIE2YR.js";
|
|
13
13
|
import "./chunk-XAA5VQ5N.js";
|
|
14
14
|
import "./chunk-VKVL7WBN.js";
|
|
15
15
|
|
|
@@ -286,4 +286,4 @@ async function runKnobs(argv) {
|
|
|
286
286
|
export {
|
|
287
287
|
runKnobs
|
|
288
288
|
};
|
|
289
|
-
//# sourceMappingURL=knobs-
|
|
289
|
+
//# sourceMappingURL=knobs-VYABZESR.js.map
|
|
@@ -2,10 +2,10 @@ import { createRequire as __cr } from "module"; const require = __cr(import.meta
|
|
|
2
2
|
import {
|
|
3
3
|
fetchList,
|
|
4
4
|
fetchProperties
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BOS2YLKH.js";
|
|
6
6
|
import {
|
|
7
7
|
resolveConfig
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ACRIE2YR.js";
|
|
9
9
|
import "./chunk-XAA5VQ5N.js";
|
|
10
10
|
import "./chunk-VKVL7WBN.js";
|
|
11
11
|
|
|
@@ -54,4 +54,4 @@ async function runLocalList(argv) {
|
|
|
54
54
|
export {
|
|
55
55
|
runLocalList
|
|
56
56
|
};
|
|
57
|
-
//# sourceMappingURL=list-
|
|
57
|
+
//# sourceMappingURL=list-RCPYLS36.js.map
|
|
@@ -0,0 +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":";;;;;;;;;;;;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,7 @@
|
|
|
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-ACRIE2YR.js";
|
|
5
5
|
import "./chunk-VKVL7WBN.js";
|
|
6
6
|
|
|
7
7
|
// src/local/index.ts
|
|
@@ -32,22 +32,22 @@ async function runLocal(argv) {
|
|
|
32
32
|
}
|
|
33
33
|
switch (subcommand) {
|
|
34
34
|
case "init": {
|
|
35
|
-
const { runLocalInit } = await import("./init-
|
|
35
|
+
const { runLocalInit } = await import("./init-KXAVWHYE.js");
|
|
36
36
|
await runLocalInit(rest);
|
|
37
37
|
break;
|
|
38
38
|
}
|
|
39
39
|
case "start": {
|
|
40
|
-
const { runLocalStart } = await import("./start-
|
|
40
|
+
const { runLocalStart } = await import("./start-ZOMUD6LW.js");
|
|
41
41
|
await runLocalStart(rest);
|
|
42
42
|
break;
|
|
43
43
|
}
|
|
44
44
|
case "list": {
|
|
45
|
-
const { runLocalList } = await import("./list-
|
|
45
|
+
const { runLocalList } = await import("./list-RCPYLS36.js");
|
|
46
46
|
await runLocalList(rest);
|
|
47
47
|
break;
|
|
48
48
|
}
|
|
49
49
|
case "login": {
|
|
50
|
-
const { runLocalLogin } = await import("./login-
|
|
50
|
+
const { runLocalLogin } = await import("./login-MSIM2VIH.js");
|
|
51
51
|
await runLocalLogin(rest);
|
|
52
52
|
break;
|
|
53
53
|
}
|
|
@@ -60,4 +60,4 @@ async function runLocal(argv) {
|
|
|
60
60
|
export {
|
|
61
61
|
runLocal
|
|
62
62
|
};
|
|
63
|
-
//# sourceMappingURL=local-
|
|
63
|
+
//# sourceMappingURL=local-34FX3M5K.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
LocalBrowserHost
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SVU2XTYZ.js";
|
|
5
5
|
import {
|
|
6
6
|
readStoredToken
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-ACRIE2YR.js";
|
|
8
|
+
import "./chunk-IFOJT3A5.js";
|
|
9
9
|
import "./chunk-XAA5VQ5N.js";
|
|
10
10
|
import "./chunk-P5Z2Y5VV.js";
|
|
11
11
|
import "./chunk-VKVL7WBN.js";
|
|
@@ -141,4 +141,4 @@ async function runLocalBrowser(args) {
|
|
|
141
141
|
export {
|
|
142
142
|
runLocalBrowser
|
|
143
143
|
};
|
|
144
|
-
//# sourceMappingURL=local-browser-
|
|
144
|
+
//# sourceMappingURL=local-browser-VPOSJS52.js.map
|
|
@@ -4,15 +4,15 @@ import {
|
|
|
4
4
|
promptChoice,
|
|
5
5
|
selectProperty,
|
|
6
6
|
uploadStorageState
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-BOS2YLKH.js";
|
|
8
8
|
import {
|
|
9
9
|
createSession,
|
|
10
10
|
deleteSession,
|
|
11
11
|
getSessionStorageState
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-Z3F373YR.js";
|
|
13
13
|
import {
|
|
14
14
|
resolveConfig
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ACRIE2YR.js";
|
|
16
16
|
import "./chunk-XAA5VQ5N.js";
|
|
17
17
|
import "./chunk-VKVL7WBN.js";
|
|
18
18
|
|
|
@@ -127,4 +127,4 @@ Opening browser at ${selectedEnv.url}...`);
|
|
|
127
127
|
export {
|
|
128
128
|
runLocalLogin
|
|
129
129
|
};
|
|
130
|
-
//# sourceMappingURL=login-
|
|
130
|
+
//# sourceMappingURL=login-MSIM2VIH.js.map
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
LocalBrowserHost
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SVU2XTYZ.js";
|
|
5
5
|
import {
|
|
6
6
|
callTool,
|
|
7
7
|
createSession,
|
|
8
8
|
deleteAllSessions,
|
|
9
9
|
deleteSession,
|
|
10
10
|
resolveTargetSession
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-Z3F373YR.js";
|
|
12
12
|
import {
|
|
13
13
|
readStoredToken
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ACRIE2YR.js";
|
|
15
15
|
import {
|
|
16
16
|
getBrowserToolDefinitionsWithLifecycle
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IFOJT3A5.js";
|
|
18
18
|
import "./chunk-XAA5VQ5N.js";
|
|
19
19
|
import "./chunk-P5Z2Y5VV.js";
|
|
20
20
|
import "./chunk-VKVL7WBN.js";
|
|
@@ -347,16 +347,13 @@ async function handleBrowserTool(name, args) {
|
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
// src/mcp/index.ts
|
|
350
|
-
async function runMcp(
|
|
350
|
+
async function runMcp(_argv) {
|
|
351
351
|
const server = new Server(
|
|
352
352
|
{ name: "canary-cli", version: "0.1.0" },
|
|
353
353
|
{ capabilities: { tools: {} } }
|
|
354
354
|
);
|
|
355
355
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
356
|
-
tools: [
|
|
357
|
-
...getSessionToolDefinitions(),
|
|
358
|
-
...getBrowserMCPToolDefinitions()
|
|
359
|
-
]
|
|
356
|
+
tools: [...getSessionToolDefinitions(), ...getBrowserMCPToolDefinitions()]
|
|
360
357
|
}));
|
|
361
358
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
362
359
|
const tool = req.params.name;
|
|
@@ -374,4 +371,4 @@ async function runMcp(argv) {
|
|
|
374
371
|
export {
|
|
375
372
|
runMcp
|
|
376
373
|
};
|
|
377
|
-
//# sourceMappingURL=mcp-
|
|
374
|
+
//# sourceMappingURL=mcp-YBR7G254.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/index.ts","../src/mcp/tool-helpers.ts","../src/mcp/session-tools.ts","../src/mcp/browser-tools.ts"],"sourcesContent":["/**\n * MCP Server for Canary CLI.\n *\n * Combines cloud-relay session tools and direct browser tools\n * into a single MCP server.\n *\n * @module\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { toolText } from './tool-helpers';\nimport { getSessionToolDefinitions, handleSessionTool } from './session-tools';\nimport { getBrowserMCPToolDefinitions, handleBrowserTool } from './browser-tools';\n\nexport async function runMcp(_argv: string[]) {\n const server = new Server(\n { name: 'canary-cli', version: '0.1.0' },\n { capabilities: { tools: {} } }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [...getSessionToolDefinitions(), ...getBrowserMCPToolDefinitions()],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = req.params.name;\n const args = (req.params.arguments ?? {}) as Record<string, unknown>;\n\n // Try browser tools first (browser_* prefix)\n const browserResult = await handleBrowserTool(tool, args);\n if (browserResult) return browserResult;\n\n // Try session tools (local_* prefix)\n const sessionResult = await handleSessionTool(tool, args);\n if (sessionResult) return sessionResult;\n\n return toolText(`Unknown tool: ${tool}`);\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n return new Promise<void>(() => undefined);\n}\n","/**\n * MCP tool response helpers.\n *\n * @module\n */\n\nimport type { ToolResult } from '@chatsdet/browser-core';\n\nexport function toolText(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nexport function toolJson(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n\n/**\n * Convert a BrowserToolExecutor result to MCP SDK content blocks.\n */\nexport function formatMCPContent(result: ToolResult) {\n if (typeof result === 'string') {\n return { content: [{ type: 'text' as const, text: result }] };\n }\n\n // MCPContentResult with text and optional images\n const content: Array<{ type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string }> = [];\n\n if (result.text) {\n content.push({ type: 'text', text: result.text });\n }\n\n for (const img of result.images ?? []) {\n content.push({ type: 'image', data: img.data, mimeType: img.mimeType });\n }\n\n return { content };\n}\n","/**\n * Cloud-relay session tools for the MCP server.\n *\n * These tools proxy browser control through the cloud API via WebSocket.\n *\n * @module\n */\n\nimport { readStoredToken } from '../auth';\nimport { LocalBrowserHost } from '../local-browser/host';\nimport type { LocalBrowserMode } from '../local-browser/protocol';\nimport { toolJson } from './tool-helpers';\n\nimport process from 'node:process';\n\ntype LocalBrowserStartInput = {\n mode?: LocalBrowserMode;\n cdpUrl?: string;\n headless?: boolean;\n storageStatePath?: string;\n instructions?: string;\n};\n\ntype LocalBrowserStopInput = {\n sessionId: string;\n};\n\ntype LocalBrowserStatusInput = {\n sessionId: string;\n};\n\ninterface BrowserSession {\n sessionId: string;\n host: LocalBrowserHost;\n startedAt: number;\n mode: LocalBrowserMode;\n}\n\n// Global browser sessions managed by MCP\nconst browserSessions = new Map<string, BrowserSession>();\n\nconst DEFAULT_API_URL = 'https://api.trycanary.ai';\n\nfunction resolveApiUrl(input?: string): string {\n return input ?? process.env.CANARY_API_URL ?? DEFAULT_API_URL;\n}\n\nasync function resolveToken(): Promise<string> {\n const token = process.env.CANARY_API_TOKEN ?? (await readStoredToken());\n if (!token) {\n throw new Error('Missing token. Run `canary login` first or set CANARY_API_TOKEN.');\n }\n return token;\n}\n\nexport function getSessionToolDefinitions() {\n return [\n {\n name: 'local_browser_start',\n description:\n 'Start a local browser session that connects to the cloud agent. The cloud agent can then control this browser to test local applications. Returns sessionId for tracking.',\n inputSchema: {\n type: 'object',\n properties: {\n mode: {\n type: 'string',\n enum: ['playwright', 'cdp'],\n description:\n \"Browser mode: 'playwright' for fresh browser, 'cdp' to connect to existing Chrome\",\n },\n cdpUrl: {\n type: 'string',\n description: \"CDP endpoint URL when mode is 'cdp' (e.g. http://localhost:9222)\",\n },\n headless: {\n type: 'boolean',\n description: 'Run browser headless (default: true for playwright mode)',\n },\n storageStatePath: {\n type: 'string',\n description: 'Path to Playwright storage state JSON for pre-authenticated sessions',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n },\n },\n },\n {\n name: 'local_browser_status',\n description: 'Check the status of a local browser session.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_stop',\n description: 'Stop a local browser session and close the browser.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_list',\n description: 'List all active local browser sessions.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'local_browser_run',\n description:\n 'Start a test run on an active local browser session. The cloud agent will control the local browser according to the instructions.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID from local_browser_start',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n startUrl: {\n type: 'string',\n description: 'Optional URL to navigate to before starting',\n },\n },\n required: ['sessionId', 'instructions'],\n },\n },\n ];\n}\n\nexport async function handleSessionTool(tool: string, args: Record<string, unknown>) {\n const token = await resolveToken();\n\n if (tool === 'local_browser_start') {\n const input = args as unknown as LocalBrowserStartInput;\n const apiUrl = resolveApiUrl();\n const mode = input.mode ?? 'playwright';\n\n const sessionResponse = await fetch(`${apiUrl}/local-browser/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n browserMode: mode,\n instructions: input.instructions ?? null,\n }),\n });\n\n if (!sessionResponse.ok) {\n const text = await sessionResponse.text();\n return toolJson({ ok: false, error: `Failed to create session: ${text}` });\n }\n\n const session = (await sessionResponse.json()) as {\n ok: boolean;\n sessionId: string;\n wsToken: string;\n expiresAt: string;\n };\n\n const host = new LocalBrowserHost({\n apiUrl,\n wsToken: session.wsToken,\n sessionId: session.sessionId,\n browserMode: mode,\n cdpUrl: input.cdpUrl,\n headless: input.headless ?? true,\n storageStatePath: input.storageStatePath,\n onLog: (level, message) => {\n if (level === 'error') {\n console.error(`[LocalBrowser] ${message}`);\n }\n },\n });\n\n host.start().catch((err) => {\n console.error('Failed to start local browser:', err);\n browserSessions.delete(session.sessionId);\n });\n\n browserSessions.set(session.sessionId, {\n sessionId: session.sessionId,\n host,\n startedAt: Date.now(),\n mode,\n });\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode,\n expiresAt: session.expiresAt,\n note: 'Browser session started. The cloud agent can now control this browser. Use local_browser_stop to end the session.',\n });\n }\n\n if (tool === 'local_browser_status') {\n const input = args as unknown as LocalBrowserStatusInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode: session.mode,\n startedAt: new Date(session.startedAt).toISOString(),\n uptimeMs: Date.now() - session.startedAt,\n });\n }\n\n if (tool === 'local_browser_stop') {\n const input = args as unknown as LocalBrowserStopInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n await session.host.stop();\n browserSessions.delete(input.sessionId);\n\n return toolJson({\n ok: true,\n sessionId: input.sessionId,\n note: 'Browser session stopped and browser closed.',\n });\n }\n\n if (tool === 'local_browser_list') {\n const sessions = Array.from(browserSessions.values()).map((s) => ({\n sessionId: s.sessionId,\n mode: s.mode,\n startedAt: new Date(s.startedAt).toISOString(),\n uptimeMs: Date.now() - s.startedAt,\n }));\n\n return toolJson({\n ok: true,\n count: sessions.length,\n sessions,\n });\n }\n\n if (tool === 'local_browser_run') {\n const input = args as unknown as {\n sessionId: string;\n instructions: string;\n startUrl?: string;\n };\n const apiUrl = resolveApiUrl();\n\n const session = browserSessions.get(input.sessionId);\n if (!session) {\n return toolJson({\n ok: false,\n error: 'Session not found locally. Make sure you started it with local_browser_start.',\n sessionId: input.sessionId,\n });\n }\n\n const response = await fetch(`${apiUrl}/local-browser/sessions/${input.sessionId}/run`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n instructions: input.instructions,\n startUrl: input.startUrl ?? null,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n return toolJson({ ok: false, error: `Failed to start run: ${text}` });\n }\n\n const result = (await response.json()) as { ok: boolean; jobId: string; sessionId: string };\n\n return toolJson({\n ok: true,\n jobId: result.jobId,\n sessionId: result.sessionId,\n note: 'Test run started. The cloud agent is now controlling your local browser. You can watch the browser to see the test in action.',\n });\n }\n\n return null; // Not handled\n}\n","/**\n * Browser MCP tool registration — daemon adapter.\n *\n * Thin layer that maps MCP tool calls to the session daemon,\n * ensuring the CLI gets the SAME semantic diff, snapshot formatting,\n * click validation, auto-snapshot, and recovery notices as the cloud agent.\n *\n * The daemon owns all browser sessions. MCP is just a protocol adapter.\n *\n * @module\n */\n\nimport { getBrowserToolDefinitionsWithLifecycle } from '@chatsdet/browser-core';\nimport {\n createSession,\n deleteSession,\n deleteAllSessions,\n callTool,\n resolveTargetSession,\n} from '../session/daemon-client.js';\nimport { formatMCPContent, toolJson } from './tool-helpers';\nimport type { ToolResult } from '@chatsdet/browser-core';\n\n/** Track the active session ID within this MCP server instance */\nlet activeSessionId: string | null = null;\n\n/**\n * Get tool definitions for browser MCP tools (including lifecycle).\n */\nexport function getBrowserMCPToolDefinitions() {\n return getBrowserToolDefinitionsWithLifecycle();\n}\n\n/**\n * Handle a browser tool call.\n * Returns null if the tool name is not a browser tool.\n */\nexport async function handleBrowserTool(name: string, args: Record<string, unknown>) {\n // Lifecycle tools\n if (name === 'browser_start') {\n try {\n const result = await createSession({\n headless: (args.headless as boolean) ?? false,\n storageStatePath: args.storageStatePath as string | undefined,\n });\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error });\n }\n\n activeSessionId = result.data!.id;\n return toolJson({\n ok: true,\n sessionId: activeSessionId,\n note: 'Browser started. You can now use browser_navigate, browser_click, and other browser tools.',\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (name === 'browser_stop') {\n try {\n if (activeSessionId) {\n await deleteSession(activeSessionId);\n activeSessionId = null;\n } else {\n // Stop all sessions if no specific one tracked\n await deleteAllSessions();\n }\n return toolJson({ ok: true, note: 'Browser stopped and cleaned up.' });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n // All other browser_* tools require an active session\n if (!name.startsWith('browser_')) return null;\n\n try {\n // Resolve target session: prefer tracked MCP session, then auto-resolve\n let sessionId = activeSessionId;\n if (!sessionId) {\n try {\n const target = await resolveTargetSession();\n sessionId = target.id;\n activeSessionId = sessionId;\n } catch {\n return toolJson({\n ok: false,\n error: 'No active browser session. Start one with browser_start first.',\n });\n }\n }\n\n // Strip 'browser_' prefix for the daemon tool name\n const toolName = name.replace(/^browser_/, '');\n const result = await callTool(sessionId, toolName, args);\n\n if (!result.ok) {\n // If session not found, clear tracking and report error\n if (result.error?.includes('not found')) {\n activeSessionId = null;\n }\n return toolJson({ ok: false, error: result.error, tool: name });\n }\n\n // Convert daemon response back to ToolResult format for MCP formatting\n const toolResult: ToolResult = result.images?.length\n ? { text: result.text ?? '', images: result.images }\n : (result.text ?? '');\n\n return formatMCPContent(toolResult);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return toolJson({ ok: false, error: message, tool: name });\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,7 +2,7 @@ import { createRequire as __cr } from "module"; const require = __cr(import.meta
|
|
|
2
2
|
import {
|
|
3
3
|
readStoredApiUrl,
|
|
4
4
|
readStoredToken
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ACRIE2YR.js";
|
|
6
6
|
import "./chunk-VKVL7WBN.js";
|
|
7
7
|
|
|
8
8
|
// src/psql.ts
|
|
@@ -122,4 +122,4 @@ Time: ${json.durationMs}ms`);
|
|
|
122
122
|
export {
|
|
123
123
|
runPsql
|
|
124
124
|
};
|
|
125
|
-
//# sourceMappingURL=psql-
|
|
125
|
+
//# sourceMappingURL=psql-XO5BB5L5.js.map
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
apiRequest,
|
|
4
4
|
downloadStorageState,
|
|
5
5
|
selectCredential
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BOS2YLKH.js";
|
|
7
7
|
import {
|
|
8
8
|
getArgValue,
|
|
9
9
|
hasFlag,
|
|
10
10
|
resolveConfig
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ACRIE2YR.js";
|
|
12
12
|
import {
|
|
13
13
|
getCanaryTmpDir
|
|
14
14
|
} from "./chunk-XAA5VQ5N.js";
|
|
@@ -244,10 +244,12 @@ async function runRecord(argv) {
|
|
|
244
244
|
}
|
|
245
245
|
const navigateUrl = startUrl ?? loginUrl;
|
|
246
246
|
if (!navigateUrl) {
|
|
247
|
-
console.warn(
|
|
247
|
+
console.warn(
|
|
248
|
+
"No start URL provided and no login URL on credential. Browser will open to about:blank."
|
|
249
|
+
);
|
|
248
250
|
}
|
|
249
251
|
console.log("Launching browser...");
|
|
250
|
-
const { PlaywrightClient, consoleLogger, captureElementAtPoint } = await import("./src-
|
|
252
|
+
const { PlaywrightClient, consoleLogger, captureElementAtPoint } = await import("./src-F7LQ5PY2.js");
|
|
251
253
|
const videoDir = path.join(getCanaryTmpDir(), `canary-record-video-${Date.now()}`);
|
|
252
254
|
await fs.mkdir(videoDir, { recursive: true });
|
|
253
255
|
const client = new PlaywrightClient({ logger: consoleLogger });
|
|
@@ -270,7 +272,6 @@ async function runRecord(argv) {
|
|
|
270
272
|
console.warn("Navigation timed out or failed, continuing anyway.");
|
|
271
273
|
});
|
|
272
274
|
}
|
|
273
|
-
const startedAt = /* @__PURE__ */ new Date();
|
|
274
275
|
const events = [];
|
|
275
276
|
let running = true;
|
|
276
277
|
const currentUrl = page.url();
|
|
@@ -333,7 +334,6 @@ async function runRecord(argv) {
|
|
|
333
334
|
if (!running) return;
|
|
334
335
|
running = false;
|
|
335
336
|
clearInterval(pollInterval);
|
|
336
|
-
const endedAt = /* @__PURE__ */ new Date();
|
|
337
337
|
console.log(`
|
|
338
338
|
Recording stopped. ${events.length} events captured.`);
|
|
339
339
|
console.log("Saving video...");
|
|
@@ -394,4 +394,4 @@ Output directory: ${outDir}`);
|
|
|
394
394
|
export {
|
|
395
395
|
runRecord
|
|
396
396
|
};
|
|
397
|
-
//# sourceMappingURL=record-
|
|
397
|
+
//# sourceMappingURL=record-DXXQHPGT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/record.ts","../src/record-interaction-script.ts"],"sourcesContent":["/**\n * `canary record` — Record browser interactions for flow creation.\n *\n * Launches a headed browser, injects an in-page capture script,\n * and records user interactions (clicks, inputs, navigation) enriched\n * with accessibility snapshots and element info. On stop, bundles\n * everything as JSONL + video and uploads to the API.\n *\n * @module record\n */\n\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { getCanaryTmpDir } from '@chatsdet/tmp';\nimport process from 'node:process';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest, selectCredential, downloadStorageState } from './cli-helpers.js';\n\nimport { INTERACTION_CAPTURE_SCRIPT } from './record-interaction-script.js';\n\n/** Minimal recording event types (mirrors @chatsdet/types/recording) */\ninterface RecordingClickEvent {\n type: 'click';\n ts: number;\n x: number;\n y: number;\n tagName: string;\n id?: string;\n testId?: string;\n ariaLabel?: string;\n role?: string;\n textContent?: string;\n className?: string;\n elementInfo?: Record<string, unknown>;\n snapshot?: string;\n}\n\ntype RecordingEvent =\n | RecordingClickEvent\n | {\n type: 'input';\n ts: number;\n tagName: string;\n id?: string;\n inputType?: string;\n ariaLabel?: string;\n value: string;\n isFinal?: boolean;\n }\n | {\n type: 'change';\n ts: number;\n tagName: string;\n id?: string;\n inputType?: string;\n ariaLabel?: string;\n value: string;\n }\n | { type: 'keydown'; ts: number; key: string }\n | { type: 'navigation'; ts: number; url: string; snapshot?: string; navigationType?: string }\n | { type: 'initial-url'; ts: number; url: string; snapshot?: string };\n\ninterface CredentialDetail {\n id: string;\n name: string;\n loginUrl?: string;\n storageStateS3Key?: string | null;\n}\n\nexport async function runRecord(argv: string[]): Promise<void> {\n if (hasFlag(argv, '--help', '-h')) {\n console.log(\n [\n 'Usage: canary record [options]',\n '',\n 'Record browser interactions for flow creation.',\n '',\n 'Options:',\n ' --credential <id> Credential ID (skip interactive selection)',\n ' --url <startUrl> URL to navigate to after launch',\n ' --output <dir> Local output directory (default: temp dir)',\n ' --env <env> Environment (local, dev, prod)',\n ' --no-upload Save locally only, skip API upload',\n '',\n 'Press Ctrl+C to stop recording.',\n ].join('\\n')\n );\n return;\n }\n\n const config = await resolveConfig(argv);\n const credentialArg = getArgValue(argv, '--credential');\n const startUrl = getArgValue(argv, '--url');\n const outputDir = getArgValue(argv, '--output');\n const skipUpload = hasFlag(argv, '--no-upload');\n\n // 1. Fetch and select credential\n console.log('Fetching credentials...');\n const credential = await selectCredential(config.apiUrl, config.token, credentialArg);\n if (!credential) {\n process.exit(1);\n }\n\n console.log(`Using credential: ${credential.name}`);\n\n const propertyId = credential.propertyId;\n\n // 3. Download storage state if available\n let storageStatePath: string | undefined;\n if (credential.storageStateS3Key) {\n console.log('Downloading storage state...');\n storageStatePath = await downloadStorageState({\n apiUrl: config.apiUrl,\n token: config.token,\n propertyId: credential.propertyId,\n credentialId: credential.id,\n });\n if (storageStatePath) {\n console.log('Storage state loaded.');\n } else {\n console.warn('Could not download storage state, continuing without it.');\n }\n }\n\n // 4. Get credential detail for loginUrl\n let loginUrl = credential.loginUrl;\n if (!loginUrl) {\n const detail = await apiRequest<{ ok: boolean; credential?: CredentialDetail }>(\n config.apiUrl,\n config.token,\n 'GET',\n `/org/properties/${propertyId}/credentials/${credential.id}`\n );\n loginUrl = detail.credential?.loginUrl ?? undefined;\n }\n\n // 5. Determine start URL\n const navigateUrl = startUrl ?? loginUrl;\n if (!navigateUrl) {\n console.warn(\n 'No start URL provided and no login URL on credential. Browser will open to about:blank.'\n );\n }\n\n // 6. Launch browser\n console.log('Launching browser...');\n\n // Lazy-load playwright-dependent modules\n const { PlaywrightClient, consoleLogger, captureElementAtPoint } =\n await import('@chatsdet/browser-core');\n\n const videoDir = path.join(getCanaryTmpDir(), `canary-record-video-${Date.now()}`);\n await fs.mkdir(videoDir, { recursive: true });\n\n const client = new PlaywrightClient({ logger: consoleLogger });\n await client.connect({\n browserMode: 'headed',\n storageStatePath,\n recordVideo: { dir: videoDir },\n });\n\n const page = await client.getPageForReplay();\n if (!page) {\n console.error('Failed to get browser page.');\n await client.disconnect();\n process.exit(1);\n }\n\n // 7. Inject interaction capture script\n await page.addInitScript(INTERACTION_CAPTURE_SCRIPT);\n await page.evaluate(INTERACTION_CAPTURE_SCRIPT);\n\n // 8. Navigate\n if (navigateUrl) {\n console.log(`Navigating to ${navigateUrl}`);\n await page.goto(navigateUrl, { waitUntil: 'domcontentloaded', timeout: 30_000 }).catch(() => {\n console.warn('Navigation timed out or failed, continuing anyway.');\n });\n }\n\n const events: RecordingEvent[] = [];\n let running = true;\n\n // Emit initial-url event so we know the starting page\n const currentUrl = page.url();\n const initialUrlEvent: RecordingEvent = {\n type: 'initial-url',\n ts: Date.now(),\n url: currentUrl,\n };\n try {\n const snapshot = await (\n page as unknown as { _snapshotForAI(opts: { mode: string }): Promise<string> }\n )._snapshotForAI({ mode: 'full' });\n (initialUrlEvent as { snapshot?: string }).snapshot = snapshot;\n } catch {\n // Snapshot may fail\n }\n events.push(initialUrlEvent);\n process.stdout.write(` [${events.length}] initial-url → ${currentUrl}\\n`);\n\n console.log('\\nRecording started. Interact with the browser.');\n console.log('Press Ctrl+C to stop recording.\\n');\n\n // 9. Poll loop — collect events from the page\n const pollInterval = setInterval(async () => {\n if (!running) return;\n try {\n const raw = await page.evaluate(() => {\n const evts =\n (window as unknown as { __canaryRecordedEvents?: unknown[] }).__canaryRecordedEvents ??\n [];\n (window as unknown as { __canaryRecordedEvents: unknown[] }).__canaryRecordedEvents = [];\n return evts;\n });\n\n if (!Array.isArray(raw) || raw.length === 0) return;\n\n for (const evt of raw as RecordingEvent[]) {\n // Enrich click events with element info and periodic snapshots\n if (evt.type === 'click') {\n const clickEvt = evt as RecordingClickEvent;\n try {\n const info = await captureElementAtPoint(page, clickEvt.x, clickEvt.y);\n if (info) {\n clickEvt.elementInfo = info as unknown as Record<string, unknown>;\n }\n } catch {\n // Element may have disappeared\n }\n\n // Snapshot every click for full page context\n try {\n const snapshot = await (\n page as unknown as { _snapshotForAI(opts: { mode: string }): Promise<string> }\n )._snapshotForAI({ mode: 'full' });\n clickEvt.snapshot = snapshot;\n } catch {\n // Snapshot may fail during navigation\n }\n }\n\n // Enrich navigation events with snapshot\n if (evt.type === 'navigation') {\n try {\n const snapshot = await (\n page as unknown as { _snapshotForAI(opts: { mode: string }): Promise<string> }\n )._snapshotForAI({ mode: 'full' });\n (evt as { snapshot?: string }).snapshot = snapshot;\n } catch {\n // Snapshot may fail during navigation\n }\n }\n\n events.push(evt);\n const label =\n evt.type === 'click'\n ? `click (${(evt as RecordingClickEvent).tagName})`\n : evt.type === 'input'\n ? `input`\n : evt.type === 'change'\n ? `change (${(evt as { tagName: string }).tagName})`\n : evt.type === 'navigation'\n ? `navigation → ${(evt as { url: string }).url}`\n : evt.type === 'initial-url'\n ? `initial-url → ${(evt as { url: string }).url}`\n : `keydown: ${(evt as { key: string }).key}`;\n process.stdout.write(` [${events.length}] ${label}\\n`);\n }\n } catch {\n // Page may have been closed\n }\n }, 500);\n\n // 10. Handle Ctrl+C\n const cleanup = async () => {\n if (!running) return;\n running = false;\n clearInterval(pollInterval);\n\n console.log(`\\nRecording stopped. ${events.length} events captured.`);\n\n // Save video\n console.log('Saving video...');\n const videoResult = await client.saveVideo();\n await client.disconnect();\n\n // Clean up temp storage state\n if (storageStatePath) {\n await fs.unlink(storageStatePath).catch(() => {});\n }\n\n // Prepare output directory\n const outDir = outputDir ?? path.join(getCanaryTmpDir(), `canary-recording-${Date.now()}`);\n await fs.mkdir(outDir, { recursive: true });\n\n // Write events JSONL\n const eventsPath = path.join(outDir, 'events.jsonl');\n const lines = events.map((e) => JSON.stringify(e)).join('\\n');\n await fs.writeFile(eventsPath, lines, 'utf-8');\n console.log(`Events saved: ${eventsPath}`);\n\n // Copy video if available\n let videoPath: string | undefined;\n if (videoResult?.videoPath) {\n videoPath = path.join(outDir, 'video.webm');\n await fs.copyFile(videoResult.videoPath, videoPath);\n console.log(`Video saved: ${videoPath}`);\n }\n\n // Upload to API\n if (!skipUpload && events.length > 0) {\n console.log('Uploading recording...');\n try {\n const formData = new FormData();\n formData.append('propertyId', propertyId);\n formData.append('credentialId', credential.id);\n\n const eventsBlob = new Blob([lines], { type: 'application/x-ndjson' });\n formData.append('events', eventsBlob, 'events.jsonl');\n\n if (videoPath) {\n const videoBuffer = await fs.readFile(videoPath);\n const videoBlob = new Blob([videoBuffer], { type: 'video/webm' });\n formData.append('video', videoBlob, 'video.webm');\n }\n\n const res = await fetch(`${config.apiUrl}/org/recordings/upload`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${config.token}` },\n body: formData,\n });\n\n const json = (await res.json()) as {\n ok: boolean;\n recordingId?: string;\n error?: string;\n };\n\n if (json.ok) {\n console.log(`Recording uploaded. ID: ${json.recordingId}`);\n } else {\n console.error(`Upload failed: ${json.error ?? 'Unknown error'}`);\n }\n } catch (err) {\n console.error('Upload failed:', err instanceof Error ? err.message : err);\n }\n }\n\n console.log(`\\nOutput directory: ${outDir}`);\n process.exit(0);\n };\n\n process.on('SIGINT', () => void cleanup());\n process.on('SIGTERM', () => void cleanup());\n\n // Also stop if the page is closed\n page.on('close', () => void cleanup());\n}\n","/**\n * In-page interaction capture script injected via addInitScript.\n * Captures user interactions to window.__canaryRecordedEvents.\n *\n * @module record-interaction-script\n */\n\nexport const INTERACTION_CAPTURE_SCRIPT = `\n(function() {\n if (window.__canaryRecordedEvents) return;\n window.__canaryRecordedEvents = [];\n\n function push(event) {\n window.__canaryRecordedEvents.push(event);\n }\n\n // --- Input debouncing ---\n // Accumulate input per element, flush after 500ms idle as a single event\n var inputTimers = new Map();\n var inputState = new Map();\n\n function getElementKey(el) {\n return (el.id || '') + '|' + (el.getAttribute('aria-label') || '') + '|' + (el.tagName || '') + '|' + (el.getAttribute('name') || '');\n }\n\n function flushInput(key) {\n var state = inputState.get(key);\n if (!state) return;\n inputTimers.delete(key);\n inputState.delete(key);\n push({\n type: 'input',\n ts: state.ts,\n tagName: state.tagName,\n id: state.id || undefined,\n inputType: state.inputType || undefined,\n ariaLabel: state.ariaLabel || undefined,\n value: state.value,\n isFinal: true,\n });\n }\n\n function flushAllInputs() {\n inputTimers.forEach(function(timer) { clearTimeout(timer); });\n inputState.forEach(function(_, key) { flushInput(key); });\n }\n\n document.addEventListener('click', function(e) {\n var el = e.target;\n push({\n type: 'click',\n ts: Date.now(),\n x: e.clientX,\n y: e.clientY,\n tagName: el.tagName || '',\n id: el.id || undefined,\n testId: el.getAttribute('data-testid') || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n role: el.getAttribute('role') || undefined,\n textContent: (el.textContent || '').slice(0, 200).trim() || undefined,\n className: el.className && typeof el.className === 'string' ? el.className.slice(0, 200) : undefined,\n });\n }, true);\n\n document.addEventListener('input', function(e) {\n var el = e.target;\n var isPassword = el.type === 'password';\n var key = getElementKey(el);\n\n // Clear previous timer for this element\n var prevTimer = inputTimers.get(key);\n if (prevTimer) clearTimeout(prevTimer);\n\n // Update accumulated state\n inputState.set(key, {\n ts: Date.now(),\n tagName: el.tagName || '',\n id: el.id || undefined,\n inputType: el.type || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n value: isPassword ? '***' : (el.value || ''),\n });\n\n // Schedule flush after 500ms idle\n inputTimers.set(key, setTimeout(function() { flushInput(key); }, 500));\n }, true);\n\n // --- Change events for selects, checkboxes, radios ---\n document.addEventListener('change', function(e) {\n var el = e.target;\n var tagName = el.tagName || '';\n var inputType = (el.type || '').toLowerCase();\n\n // Only capture selects, checkboxes, and radios (text inputs are handled by input debouncing)\n var isSelect = tagName === 'SELECT';\n var isCheckOrRadio = inputType === 'checkbox' || inputType === 'radio';\n if (!isSelect && !isCheckOrRadio) return;\n\n var value;\n if (isCheckOrRadio) {\n value = el.checked ? 'checked' : 'unchecked';\n } else {\n value = el.value || '';\n }\n\n push({\n type: 'change',\n ts: Date.now(),\n tagName: tagName,\n id: el.id || undefined,\n inputType: inputType || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n value: value,\n });\n }, true);\n\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Enter' || e.key === 'Tab' || e.key === 'Escape') {\n push({\n type: 'keydown',\n ts: Date.now(),\n key: e.key,\n });\n }\n }, true);\n\n // --- SPA navigation: patch pushState/replaceState ---\n var origPushState = history.pushState;\n var origReplaceState = history.replaceState;\n\n history.pushState = function() {\n origPushState.apply(this, arguments);\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'pushState',\n });\n };\n\n history.replaceState = function() {\n origReplaceState.apply(this, arguments);\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'replaceState',\n });\n };\n\n window.addEventListener('popstate', function() {\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'popstate',\n });\n });\n\n window.addEventListener('beforeunload', function() {\n flushAllInputs();\n push({\n type: 'navigation',\n ts: Date.now(),\n url: window.location.href,\n navigationType: 'beforeunload',\n });\n });\n})();\n`;\n"],"mappings":"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","names":[]}
|
|
@@ -2,7 +2,7 @@ import { createRequire as __cr } from "module"; const require = __cr(import.meta
|
|
|
2
2
|
import {
|
|
3
3
|
readStoredApiUrl,
|
|
4
4
|
readStoredToken
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ACRIE2YR.js";
|
|
6
6
|
import "./chunk-VKVL7WBN.js";
|
|
7
7
|
|
|
8
8
|
// src/redis.ts
|
|
@@ -128,4 +128,4 @@ Time: ${json_response.durationMs}ms`);
|
|
|
128
128
|
export {
|
|
129
129
|
runRedis
|
|
130
130
|
};
|
|
131
|
-
//# sourceMappingURL=redis-
|
|
131
|
+
//# sourceMappingURL=redis-CQTBPZ6F.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
getArgValue,
|
|
4
4
|
hasFlag,
|
|
5
5
|
resolveConfig
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ACRIE2YR.js";
|
|
7
7
|
import "./chunk-VKVL7WBN.js";
|
|
8
8
|
|
|
9
9
|
// src/release.ts
|
|
@@ -221,4 +221,4 @@ async function runRelease(argv) {
|
|
|
221
221
|
export {
|
|
222
222
|
runRelease
|
|
223
223
|
};
|
|
224
|
-
//# sourceMappingURL=release-
|
|
224
|
+
//# sourceMappingURL=release-DW7RPQSQ.js.map
|
package/dist/runner/preload.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createRequire as __cr } from "module"; const require = __cr(import.meta
|
|
|
2
2
|
import {
|
|
3
3
|
downloadStorageState,
|
|
4
4
|
selectCredential
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BOS2YLKH.js";
|
|
6
6
|
import {
|
|
7
7
|
callTool,
|
|
8
8
|
createSession,
|
|
@@ -12,17 +12,17 @@ import {
|
|
|
12
12
|
listSessions,
|
|
13
13
|
resolveTargetSession,
|
|
14
14
|
swapSessionContext
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-Z3F373YR.js";
|
|
16
16
|
import {
|
|
17
17
|
getArgValue,
|
|
18
18
|
hasFlag,
|
|
19
19
|
resolveConfig
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-ACRIE2YR.js";
|
|
21
21
|
import {
|
|
22
22
|
BrowserToolExecutor,
|
|
23
23
|
PlaywrightClient,
|
|
24
24
|
dispatchBrowserTool
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-IFOJT3A5.js";
|
|
26
26
|
import "./chunk-XAA5VQ5N.js";
|
|
27
27
|
import {
|
|
28
28
|
consoleLogger
|
|
@@ -192,15 +192,24 @@ async function handleListSessions(res) {
|
|
|
192
192
|
async function handleGetSession(sessionId, res) {
|
|
193
193
|
const session = sessions.get(sessionId);
|
|
194
194
|
if (!session) {
|
|
195
|
-
json(res, 404, {
|
|
195
|
+
json(res, 404, {
|
|
196
|
+
ok: false,
|
|
197
|
+
error: `Session "${sessionId}" not found`
|
|
198
|
+
});
|
|
196
199
|
return;
|
|
197
200
|
}
|
|
198
|
-
json(res, 200, {
|
|
201
|
+
json(res, 200, {
|
|
202
|
+
ok: true,
|
|
203
|
+
data: await toSessionInfo(session)
|
|
204
|
+
});
|
|
199
205
|
}
|
|
200
206
|
async function handleDeleteSession(sessionId, res) {
|
|
201
207
|
const session = sessions.get(sessionId);
|
|
202
208
|
if (!session) {
|
|
203
|
-
json(res, 404, {
|
|
209
|
+
json(res, 404, {
|
|
210
|
+
ok: false,
|
|
211
|
+
error: `Session "${sessionId}" not found`
|
|
212
|
+
});
|
|
204
213
|
return;
|
|
205
214
|
}
|
|
206
215
|
try {
|
|
@@ -225,7 +234,10 @@ async function handleDeleteAllSessions(res) {
|
|
|
225
234
|
async function handleSwapContext(sessionId, body, res) {
|
|
226
235
|
const session = sessions.get(sessionId);
|
|
227
236
|
if (!session) {
|
|
228
|
-
json(res, 404, {
|
|
237
|
+
json(res, 404, {
|
|
238
|
+
ok: false,
|
|
239
|
+
error: `Session "${sessionId}" not found`
|
|
240
|
+
});
|
|
229
241
|
return;
|
|
230
242
|
}
|
|
231
243
|
const params = parseJson(body);
|
|
@@ -236,7 +248,10 @@ async function handleSwapContext(sessionId, body, res) {
|
|
|
236
248
|
if (params.credentialName) {
|
|
237
249
|
session.credentialName = params.credentialName;
|
|
238
250
|
}
|
|
239
|
-
json(res, 200, {
|
|
251
|
+
json(res, 200, {
|
|
252
|
+
ok: true,
|
|
253
|
+
data: await toSessionInfo(session)
|
|
254
|
+
});
|
|
240
255
|
} catch (err) {
|
|
241
256
|
json(res, 500, {
|
|
242
257
|
ok: false,
|
|
@@ -247,7 +262,10 @@ async function handleSwapContext(sessionId, body, res) {
|
|
|
247
262
|
async function handleGetStorageState(sessionId, res) {
|
|
248
263
|
const session = sessions.get(sessionId);
|
|
249
264
|
if (!session) {
|
|
250
|
-
json(res, 404, {
|
|
265
|
+
json(res, 404, {
|
|
266
|
+
ok: false,
|
|
267
|
+
error: `Session "${sessionId}" not found`
|
|
268
|
+
});
|
|
251
269
|
return;
|
|
252
270
|
}
|
|
253
271
|
try {
|
|
@@ -263,7 +281,10 @@ async function handleGetStorageState(sessionId, res) {
|
|
|
263
281
|
async function handleToolCall(sessionId, toolName, body, res) {
|
|
264
282
|
const session = sessions.get(sessionId);
|
|
265
283
|
if (!session) {
|
|
266
|
-
json(res, 404, {
|
|
284
|
+
json(res, 404, {
|
|
285
|
+
ok: false,
|
|
286
|
+
error: `Session "${sessionId}" not found`
|
|
287
|
+
});
|
|
267
288
|
return;
|
|
268
289
|
}
|
|
269
290
|
const args = parseJson(body);
|
|
@@ -816,4 +837,4 @@ async function runSession(argv) {
|
|
|
816
837
|
export {
|
|
817
838
|
runSession
|
|
818
839
|
};
|
|
819
|
-
//# sourceMappingURL=session-
|
|
840
|
+
//# sourceMappingURL=session-XQGCLWNC.js.map
|