@gravity-rail/cli 0.7.1 → 0.7.2
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/cli-utils.js +0 -1
- package/dist/{errors-4MAJGD3C.js → errors-SMY7LZJB.js} +1 -2
- package/dist/gr.js +335 -1706
- package/dist/gr.js.map +1 -1
- package/dist/lib.d.ts +15 -12
- package/dist/lib.js +6352 -5468
- package/dist/lib.js.map +1 -1
- package/dist/register-special-commands.js +1 -1670
- package/dist/register-special-commands.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-424PT5DM.js +0 -23
- package/dist/errors-4MAJGD3C.js.map +0 -1
- /package/dist/{chunk-424PT5DM.js.map → errors-SMY7LZJB.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli-utils/config.ts","../src/cli-utils/auth.ts","../src/cli-utils/ui.ts","../src/cli-utils/agui.ts","../src/cli-utils/index.ts","../src/lib/errors.ts","../src/lib/pagination.ts","../src/lib/output.ts","../../client/src/index.ts","../../client/src/api/admin.ts","../../client/src/client/client.ts","../../client/src/client/bindings/admin.ts","../src/lib/realm.ts","../src/lib/org-auth.ts","../src/lib/pinned-fetch.ts","../src/lib/context.ts","../src/lib/concierge-api.ts","../src/commands/account-verify-phone.ts","../src/commands/auth-browser.ts","../src/commands/manage.ts","../src/lib/cli-client-context.ts","../src/lib/chat-session.ts","../src/lib/concierge-agui-loop.ts","../src/lib/cli-hitl.ts","../src/lib/local-files.ts","../src/lib/trusted-dirs.ts","../src/lib/realtime-client.ts","../src/lib/chat-tui.ts","../src/lib/audio.ts","../src/commands/concierge.ts","../src/commands/dev.ts","../src/commands/get-started.ts","../src/commands/login.ts","../src/commands/organizations.ts","../src/commands/whoami.ts","../src/register-special-commands.ts"],"sourcesContent":["/**\n * CLI configuration for remote environments\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { dirname, join, resolve } from 'path';\n\nexport interface EnvironmentConfig {\n apiUrl: string;\n frontendUrl: string;\n}\n\nexport const ENVIRONMENTS: Record<string, EnvironmentConfig> = {\n dev: {\n apiUrl: 'https://api.gravityrail.test:5054',\n frontendUrl: 'https://app.gravityrail.test:3000',\n },\n prod: {\n apiUrl: 'https://api.gravityrail.com',\n frontendUrl: 'https://app.gravityrail.com',\n },\n staging: {\n apiUrl: 'https://api.gr-staging.com',\n frontendUrl: 'https://app.gr-staging.com',\n },\n};\n\nexport const CALLBACK_PORT = 31337;\nexport const CALLBACK_PATH = '/oauth/callback';\nexport const REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;\n\n/**\n * Detect worktree port overrides from docker-compose.override.yml.\n * The override file is generated by worktree-setup.sh and contains lines like:\n * - '5250:5050' (API)\n * - '3200:3000' (Frontend)\n * We extract the host port for the default internal ports (5050, 3000).\n */\nfunction detectWorktreePorts(): { apiPort?: number; frontendPort?: number } {\n // Walk up from cwd to find docker-compose.override.yml\n let dir = resolve(process.cwd());\n let overridePath: string | undefined;\n while (true) {\n const candidate = join(dir, 'docker-compose.override.yml');\n\n if (existsSync(candidate)) {\n overridePath = candidate;\n break;\n }\n const parent = dirname(dir);\n if (parent === dir) break; // reached filesystem root\n dir = parent;\n }\n if (!overridePath) return {};\n\n let content: string;\n try {\n content = readFileSync(overridePath, 'utf-8');\n } catch {\n return {};\n }\n\n // Only use this if it's a worktree override (generated by worktree-setup.sh)\n if (!content.includes('worktree-setup.sh')) return {};\n\n // Match port mappings: - 'HOST:CONTAINER'\n let apiPort: number | undefined;\n let frontendPort: number | undefined;\n for (const match of content.matchAll(/-\\s*'(\\d+):(\\d+)'/g)) {\n const host = parseInt(match[1]!, 10);\n const container = parseInt(match[2]!, 10);\n if (container === 5050) apiPort = host;\n if (container === 3000) frontendPort = host;\n }\n return { apiPort, frontendPort };\n}\n\nexport function getEnvironmentConfig(env: string): EnvironmentConfig {\n // Handle dev-cloud environments: --env dev-cloud:NAMESPACE\n if (env.startsWith('dev-cloud:')) {\n const namespace = env.slice('dev-cloud:'.length);\n if (!namespace) {\n throw new Error('dev-cloud environment requires a namespace: --env dev-cloud:NAMESPACE');\n }\n return {\n apiUrl: `https://${namespace}-api.gravityrail-dev.com`,\n frontendUrl: `https://${namespace}-app.gravityrail-dev.com`,\n };\n }\n\n const config = ENVIRONMENTS[env];\n if (!config) {\n throw new Error(\n `Invalid environment: ${env}. Use 'dev', 'staging', 'prod', or 'dev-cloud:NAMESPACE'.`\n );\n }\n\n // Allow env var overrides (used by code interpreter sandboxes)\n const apiUrl = process.env.GRAVITY_RAIL_API_URL || config.apiUrl;\n const frontendUrl = process.env.GRAVITY_RAIL_FRONTEND_URL || config.frontendUrl;\n if (apiUrl !== config.apiUrl || frontendUrl !== config.frontendUrl) {\n return { apiUrl, frontendUrl };\n }\n\n // For dev, detect worktree port overrides\n if (env === 'dev') {\n const ports = detectWorktreePorts();\n if (ports.apiPort || ports.frontendPort) {\n return {\n apiUrl: ports.apiPort ? `https://api.gravityrail.test:${ports.apiPort}` : config.apiUrl,\n frontendUrl: ports.frontendPort\n ? `https://app.gravityrail.test:${ports.frontendPort}`\n : config.frontendUrl,\n };\n }\n }\n\n return config;\n}\n","/**\n * CLI OAuth2 authentication utilities\n *\n * Provides OAuth2 with PKCE flow for CLI tools, including:\n * - Credential caching (per environment)\n * - Dynamic client registration\n * - Token refresh\n * - Browser-based authorization\n */\n\nimport { createServer } from 'http';\nimport { createHash, randomBytes } from 'crypto';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { exec } from 'child_process';\nimport { EnvironmentConfig, CALLBACK_PORT, CALLBACK_PATH, REDIRECT_URI } from './config';\n\nexport interface CLICredentials {\n clientId: string;\n clientSecret: string;\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n}\n\nexport interface AuthResult {\n accessToken: string;\n credentials?: CLICredentials;\n}\n\n/**\n * Manages CLI credentials storage (flat format, one file per environment)\n */\nexport class CredentialsManager {\n private cacheDir: string;\n private apiUrl?: string;\n\n constructor(rootDir: string, apiUrl?: string) {\n this.cacheDir = join(rootDir, '.gr-cli');\n this.apiUrl = apiUrl;\n }\n\n private getCredentialsPath(env: string): string {\n // For localhost dev URLs with non-default ports (worktrees), include the\n // port in the filename so each worktree has isolated credentials.\n if (this.apiUrl) {\n try {\n const url = new URL(this.apiUrl);\n if (url.hostname === 'localhost' && url.port && url.port !== '5050') {\n return join(this.cacheDir, `credentials-${env}-${url.port}.json`);\n }\n } catch {\n // ignore invalid URLs\n }\n }\n return join(this.cacheDir, `credentials-${env}.json`);\n }\n\n load(env: string): CLICredentials | null {\n const credsPath = this.getCredentialsPath(env);\n if (!existsSync(credsPath)) {\n return null;\n }\n\n try {\n const raw = JSON.parse(readFileSync(credsPath, 'utf-8'));\n\n let creds: CLICredentials;\n if (raw.clientId !== undefined) {\n creds = raw;\n } else if (raw.default) {\n // Migrate from old org-namespaced format to flat\n creds = raw.default;\n this.save(env, creds);\n } else {\n return null;\n }\n\n // Check if access token is expired\n if (creds.expiresAt) {\n const expiresAt = new Date(creds.expiresAt);\n if (expiresAt <= new Date()) {\n if (creds.refreshToken) {\n return creds;\n }\n return null;\n }\n }\n\n return creds;\n } catch {\n return null;\n }\n }\n\n save(env: string, creds: CLICredentials): void {\n if (!existsSync(this.cacheDir)) {\n mkdirSync(this.cacheDir, { recursive: true });\n }\n const credsPath = this.getCredentialsPath(env);\n writeFileSync(credsPath, JSON.stringify(creds, null, 2));\n try {\n chmodSync(credsPath, 0o600);\n } catch {\n // Ignore permission errors on Windows\n }\n }\n\n clear(env: string): void {\n const credsPath = this.getCredentialsPath(env);\n if (!existsSync(credsPath)) {\n return;\n }\n try {\n unlinkSync(credsPath);\n } catch {\n // Ignore\n }\n }\n\n getCacheDir(): string {\n return this.cacheDir;\n }\n}\n\nfunction stderr(msg: string): void {\n process.stderr.write(msg + '\\n');\n}\n\n/**\n * Parse an OAuth error response body, checking the JSON `error` field first,\n * falling back to text matching.\n */\nfunction isOAuthError(body: string, errorCode: string): boolean {\n try {\n const parsed = JSON.parse(body);\n if (parsed.error === errorCode) return true;\n } catch {\n // Not JSON — fall through to text match\n }\n return body.includes(errorCode);\n}\n\n/**\n * Validate and extract fields from an OAuth token response.\n * Throws on malformed responses per RFC 6749 §5.1.\n */\nfunction validateTokenResponse(tokenData: Record<string, unknown>): {\n accessToken: string;\n refreshToken?: string;\n expiresIn: number;\n} {\n if (!tokenData.access_token || typeof tokenData.access_token !== 'string') {\n throw new Error('Token response missing access_token');\n }\n\n if (tokenData.token_type && String(tokenData.token_type).toLowerCase() !== 'bearer') {\n throw new Error(`Unsupported token type: ${tokenData.token_type}`);\n }\n\n let expiresIn = 86400; // default 24h\n if (tokenData.expires_in != null) {\n const raw = Number(tokenData.expires_in);\n if (!Number.isFinite(raw) || raw < 60 || raw > 31536000) {\n stderr(` Warning: unusual expires_in value (${tokenData.expires_in}), using default`);\n } else {\n expiresIn = raw;\n }\n }\n\n return {\n accessToken: tokenData.access_token,\n refreshToken:\n typeof tokenData.refresh_token === 'string' ? tokenData.refresh_token : undefined,\n expiresIn,\n };\n}\n\n/**\n * Generate PKCE code verifier and challenge\n */\nexport function generatePKCE(): { codeVerifier: string; codeChallenge: string } {\n const codeVerifier = randomBytes(64).toString('base64url').slice(0, 128);\n const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');\n return { codeVerifier, codeChallenge };\n}\n\n/**\n * Open a URL in the default browser\n */\nexport function openBrowser(url: string): void {\n const platform = process.platform;\n let cmd: string;\n if (platform === 'darwin') {\n cmd = `open \"${url}\"`;\n } else if (platform === 'win32') {\n cmd = `start \"\" \"${url}\"`;\n } else {\n cmd = `xdg-open \"${url}\"`;\n }\n\n exec(cmd, (err) => {\n if (err) {\n stderr(' Could not open browser automatically.');\n }\n });\n}\n\n/**\n * Start a local HTTP server to receive the OAuth callback\n */\nexport function startCallbackServer(): Promise<{ code: string; state: string }> {\n return new Promise((resolve, reject) => {\n let authCode: string | null = null;\n let error: string | null = null;\n let receivedState: string | null = null;\n\n const server = createServer((req, res) => {\n const url = new URL(req.url!, `http://localhost:${CALLBACK_PORT}`);\n\n if (url.pathname !== CALLBACK_PATH) {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n if (url.searchParams.has('error')) {\n error = url.searchParams.get('error');\n const errorDesc = url.searchParams.get('error_description') || 'Unknown error';\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <head><title>Authorization Failed</title></head>\n <body style=\"font-family: system-ui; text-align: center; padding: 50px;\">\n <h1 style=\"color: #dc2626;\">Authorization Failed</h1>\n <p>${errorDesc}</p>\n <p>You can close this window.</p>\n </body>\n </html>\n `);\n server.close();\n reject(new Error(`Authorization failed: ${error}`));\n } else if (url.searchParams.has('code')) {\n authCode = url.searchParams.get('code')!;\n receivedState = url.searchParams.get('state')!;\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <head><title>Authorization Successful</title></head>\n <body style=\"font-family: system-ui; text-align: center; padding: 50px;\">\n <h1 style=\"color: #16a34a;\">Authorization Successful!</h1>\n <p>You can close this window and return to the terminal.</p>\n <script>setTimeout(() => window.close(), 2000);</script>\n </body>\n </html>\n `);\n server.close();\n resolve({ code: authCode, state: receivedState });\n } else {\n res.writeHead(400);\n res.end('Missing code parameter');\n }\n });\n\n server.listen(CALLBACK_PORT, 'localhost', () => {\n // Server started\n });\n\n // Timeout after 5 minutes (unref so it doesn't keep the process alive)\n const timeout = setTimeout(\n () => {\n if (!authCode && !error) {\n server.close();\n reject(new Error('Authorization timeout - no response received'));\n }\n },\n 5 * 60 * 1000\n );\n timeout.unref();\n });\n}\n\n/**\n * Register a new OAuth client dynamically\n */\nasync function dynamicClientRegistration(\n envConfig: EnvironmentConfig,\n clientName: string = 'Gravity CLI'\n): Promise<{ client_id: string; client_secret: string }> {\n stderr(' Registering OAuth client...');\n\n const registrationUrl = `${envConfig.apiUrl}/api/v2/oauth/register`;\n\n const registrationData = {\n client_name: clientName,\n redirect_uris: [REDIRECT_URI],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'client_secret_basic',\n scope: 'workspace:admin',\n };\n\n const response = await fetch(registrationUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(registrationData),\n });\n\n if (!response.ok) {\n throw new Error(`Client registration failed: ${response.status} - ${await response.text()}`);\n }\n\n return (await response.json()) as { client_id: string; client_secret: string };\n}\n\nexport interface OAuthFlowOptions {\n env: string;\n envConfig: EnvironmentConfig;\n credentialsManager: CredentialsManager;\n clientName?: string;\n}\n\n/**\n * Perform the full OAuth2 browser-based flow with PKCE.\n *\n * This always opens the browser for authorization. It never returns a cached\n * token — that's the job of createAuthenticatedContext. The only thing reused\n * is the registered OAuth client ID (which is identity, not auth).\n */\nexport async function performOAuthFlow(options: OAuthFlowOptions): Promise<AuthResult> {\n const { env, envConfig, credentialsManager, clientName = 'Gravity CLI' } = options;\n let hasRetried = false;\n\n while (true) {\n // Reuse registered client credentials if available, otherwise register\n let creds = credentialsManager.load(env);\n if (!creds || !creds.clientId) {\n const registration = await dynamicClientRegistration(envConfig, clientName);\n creds = {\n clientId: registration.client_id,\n clientSecret: registration.client_secret,\n };\n credentialsManager.save(env, creds);\n } else {\n stderr(' Using cached client credentials');\n }\n\n const { codeVerifier, codeChallenge } = generatePKCE();\n const state = randomBytes(32).toString('base64url');\n\n const authParams = new URLSearchParams({\n response_type: 'code',\n client_id: creds.clientId,\n redirect_uri: REDIRECT_URI,\n scope: 'workspace:admin',\n state: state,\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n });\n\n const authUrl = `${envConfig.apiUrl}/api/v2/oauth/authorize?${authParams}`;\n\n const callbackPromise = startCallbackServer();\n\n stderr('\\n Opening browser for authorization...');\n stderr(` If browser doesn't open, visit:\\n ${authUrl}\\n`);\n openBrowser(authUrl);\n\n stderr(' Waiting for authorization (timeout: 5 minutes)...');\n let code: string;\n let receivedState: string;\n try {\n ({ code, state: receivedState } = await callbackPromise);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (!hasRetried && isOAuthError(msg, 'invalid_client')) {\n stderr(' Cached client credentials expired, re-registering...');\n credentialsManager.clear(env);\n hasRetried = true;\n continue;\n }\n throw err;\n }\n\n if (receivedState !== state) {\n throw new Error('State mismatch - possible CSRF attack');\n }\n\n stderr(' Authorization code received!');\n stderr(' Exchanging code for tokens...');\n\n const tokenUrl = `${envConfig.apiUrl}/api/v2/oauth/token`;\n const authHeader = Buffer.from(`${creds.clientId}:${creds.clientSecret}`).toString('base64');\n\n const tokenResponse = await fetch(tokenUrl, {\n method: 'POST',\n headers: {\n Authorization: `Basic ${authHeader}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code: code,\n redirect_uri: REDIRECT_URI,\n code_verifier: codeVerifier,\n }),\n });\n\n if (!tokenResponse.ok) {\n const body = await tokenResponse.text();\n if (!hasRetried && isOAuthError(body, 'invalid_client')) {\n stderr(' Cached client credentials expired, re-registering...');\n credentialsManager.clear(env);\n hasRetried = true;\n continue;\n }\n throw new Error(`Token exchange failed: ${tokenResponse.status} - ${body}`);\n }\n\n const tokenData = (await tokenResponse.json()) as Record<string, unknown>;\n const { accessToken, refreshToken, expiresIn } = validateTokenResponse(tokenData);\n\n creds.accessToken = accessToken;\n creds.refreshToken = refreshToken ?? creds.refreshToken;\n creds.expiresAt = new Date(Date.now() + expiresIn * 1000).toISOString();\n\n credentialsManager.save(env, creds);\n stderr(' Authentication successful!');\n\n return { accessToken, credentials: creds };\n }\n}\n\n/**\n * Refresh an access token using a stored refresh token.\n * Returns updated credentials on success, null on failure.\n */\nexport async function refreshAccessToken(\n envConfig: EnvironmentConfig,\n creds: CLICredentials,\n credentialsManager: CredentialsManager,\n env: string\n): Promise<CLICredentials | null> {\n if (!creds.refreshToken || !creds.clientId || !creds.clientSecret) {\n stderr(' Cannot refresh: missing credentials (re-login required)');\n return null;\n }\n\n const tokenUrl = `${envConfig.apiUrl}/api/v2/oauth/token`;\n const authHeader = Buffer.from(`${creds.clientId}:${creds.clientSecret}`).toString('base64');\n\n try {\n const response = await fetch(tokenUrl, {\n method: 'POST',\n headers: {\n Authorization: `Basic ${authHeader}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: creds.refreshToken,\n }),\n });\n\n if (!response.ok) {\n const body = await response.text();\n const isExpiredRefresh = isOAuthError(body, 'invalid_grant');\n if (isExpiredRefresh) {\n stderr(' Refresh token expired, re-login required');\n } else {\n stderr(` Token refresh failed (${response.status}), clearing credentials`);\n }\n credentialsManager.clear(env);\n return null;\n }\n\n const tokenData = (await response.json()) as Record<string, unknown>;\n const { accessToken, refreshToken, expiresIn } = validateTokenResponse(tokenData);\n\n const updated: CLICredentials = {\n ...creds,\n accessToken,\n refreshToken: refreshToken ?? creds.refreshToken,\n expiresAt: new Date(Date.now() + expiresIn * 1000).toISOString(),\n };\n\n credentialsManager.save(env, updated);\n return updated;\n } catch (err) {\n stderr(` Token refresh error: ${err instanceof Error ? err.message : 'unknown'}`);\n credentialsManager.clear(env);\n return null;\n }\n}\n","/**\n * CLI terminal UI utilities\n *\n * Provides interactive terminal UI components for CLI tools\n */\n\nimport * as readline from 'readline';\n\nexport interface SelectOption<T> {\n item: T;\n label: string;\n detail?: string;\n}\n\nexport interface SelectFromListOptions<T> {\n title?: string;\n labelFn?: (item: T) => string;\n detailFn?: (item: T) => string | null;\n env?: string;\n emptyMessage?: string;\n allowNew?: boolean;\n newLabel?: string;\n}\n\nexport interface SelectResult<T> {\n item: T | null;\n isNew: boolean;\n}\n\nconst NEW_ITEM_MARKER = Symbol('NEW_ITEM');\n\n/**\n * Interactive list picker using arrow keys\n */\nexport async function selectFromList<T>(\n items: T[],\n options: SelectFromListOptions<T> = {}\n): Promise<SelectResult<T>> {\n const {\n title = 'Select an item',\n labelFn = (item: T) => String((item as any).name || (item as any).title || item),\n detailFn = null,\n env = null,\n emptyMessage = 'No items found.',\n allowNew = false,\n newLabel = 'Create new...',\n } = options;\n\n if ((!items || items.length === 0) && !allowNew) {\n console.log(`\\n ${emptyMessage}`);\n return { item: null, isNew: false };\n }\n\n // Prepend \"Create new\" option if allowed\n const displayItems: (T | typeof NEW_ITEM_MARKER)[] = allowNew\n ? [NEW_ITEM_MARKER, ...items]\n : items;\n\n return new Promise((resolve) => {\n let selectedIndex = allowNew ? 1 : 0;\n let filterText = '';\n\n const getFilteredItems = (): (T | typeof NEW_ITEM_MARKER)[] => {\n if (!filterText) return displayItems;\n const lower = filterText.toLowerCase();\n return displayItems.filter((item) => {\n if (item === NEW_ITEM_MARKER) return true;\n const label = labelFn(item);\n return label.toLowerCase().includes(lower);\n });\n };\n\n const render = (): void => {\n const filtered = getFilteredItems();\n\n // Clear screen and move cursor to top\n process.stdout.write('\\x1B[2J\\x1B[H');\n\n console.log('='.repeat(60));\n console.log(`${title} (↑/↓ to move, Enter to select, Esc to cancel)`);\n console.log('='.repeat(60));\n if (env) {\n console.log(`Environment: ${env}`);\n }\n console.log(`Filter: ${filterText}${filterText ? '' : '(type to filter)'}`);\n console.log('');\n\n if (filtered.length === 0) {\n console.log(` ${emptyMessage}`);\n console.log('');\n return;\n }\n\n // Show up to 15 items around the selected one\n const maxVisible = 15;\n let startIdx = Math.max(0, selectedIndex - Math.floor(maxVisible / 2));\n let endIdx = Math.min(filtered.length, startIdx + maxVisible);\n if (endIdx - startIdx < maxVisible && startIdx > 0) {\n startIdx = Math.max(0, endIdx - maxVisible);\n }\n\n if (startIdx > 0) {\n console.log(` ... ${startIdx} more above ...`);\n }\n\n for (let i = startIdx; i < endIdx; i++) {\n const item = filtered[i]!;\n const prefix = i === selectedIndex ? '> ' : ' ';\n\n let line: string;\n if (item === NEW_ITEM_MARKER) {\n line = `\\x1B[32m${newLabel}\\x1B[0m`; // Green color for \"Create new\"\n } else {\n const typedItem = item as T;\n line = labelFn(typedItem);\n if (detailFn) {\n const detail = detailFn(typedItem);\n if (detail) {\n line = `${line} \\x1B[90m${detail}\\x1B[0m`;\n }\n }\n }\n\n if (i === selectedIndex) {\n console.log(`\\x1B[7m${prefix}${line}\\x1B[0m`);\n } else {\n console.log(`${prefix}${line}`);\n }\n }\n\n if (endIdx < filtered.length) {\n console.log(` ... ${filtered.length - endIdx} more below ...`);\n }\n\n console.log('');\n console.log(` ${filtered.length} item(s)`);\n };\n\n // Set up raw mode for arrow key input\n readline.emitKeypressEvents(process.stdin);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n }\n\n render();\n\n const handleKeypress = (str: string | undefined, key: readline.Key): void => {\n const filtered = getFilteredItems();\n\n if (key.name === 'up') {\n selectedIndex = Math.max(0, selectedIndex - 1);\n render();\n } else if (key.name === 'down') {\n selectedIndex = Math.min(filtered.length - 1, selectedIndex + 1);\n render();\n } else if (key.name === 'return') {\n cleanup();\n if (filtered.length > 0 && selectedIndex < filtered.length) {\n const selected = filtered[selectedIndex]!;\n if (selected === NEW_ITEM_MARKER) {\n resolve({ item: null, isNew: true });\n } else {\n resolve({ item: selected as T, isNew: false });\n }\n } else {\n resolve({ item: null, isNew: false });\n }\n } else if (key.name === 'escape' || (key.ctrl && key.name === 'c')) {\n cleanup();\n resolve({ item: null, isNew: false });\n } else if (key.name === 'backspace') {\n filterText = filterText.slice(0, -1);\n selectedIndex = allowNew ? 0 : 0;\n render();\n } else if (str && str.length === 1 && !key.ctrl && !key.meta) {\n filterText += str;\n selectedIndex = allowNew ? 0 : 0;\n render();\n }\n };\n\n const cleanup = (): void => {\n process.stdin.removeListener('keypress', handleKeypress);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(false);\n }\n process.stdin.pause();\n process.stdout.write('\\x1B[2J\\x1B[H');\n };\n\n process.stdin.on('keypress', handleKeypress);\n process.stdin.resume();\n });\n}\n\n/**\n * Print a table of items\n */\nexport function printTable<T>(\n items: T[],\n columns: Array<{\n header: string;\n getValue: (item: T) => string;\n maxWidth?: number;\n }>,\n options: { title?: string; env?: string } = {}\n): void {\n if (!items || items.length === 0) {\n console.log('\\nNo items found.');\n return;\n }\n\n if (options.title) {\n console.log(`\\n=== ${options.title} ===`);\n }\n if (options.env) {\n console.log(`Environment: ${options.env}`);\n }\n console.log('');\n\n // Calculate column widths\n const widths = columns.map((col) => {\n const maxContent = Math.max(...items.map((item) => String(col.getValue(item) ?? '').length));\n const width = Math.max(col.header.length, maxContent);\n return col.maxWidth ? Math.min(width, col.maxWidth) : width;\n });\n\n // Print header\n const headerLine = columns.map((col, i) => col.header.padEnd(widths[i]!)).join(' ');\n console.log(headerLine);\n console.log(widths.map((w) => '-'.repeat(w)).join(' '));\n\n // Print rows\n for (const item of items) {\n const row = columns\n .map((col, i) => {\n const value = String(col.getValue(item) ?? '');\n const width = widths[i]!;\n return value.slice(0, width).padEnd(width);\n })\n .join(' ');\n console.log(row);\n }\n\n console.log('');\n console.log(`Total: ${items.length} item(s)`);\n}\n\n/**\n * Format a timestamp for display\n */\nexport function formatTimestamp(isoString: string | null | undefined): string {\n if (!isoString) return '';\n const date = new Date(isoString);\n const now = new Date();\n const diff = now.getTime() - date.getTime();\n\n if (diff < 60000) return 'just now';\n if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;\n if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;\n if (diff < 604800000) return `${Math.floor(diff / 86400000)}d ago`;\n\n return date.toLocaleDateString();\n}\n\n/**\n * Wrap text to a maximum width\n */\nexport function wrapText(text: string, width: number = 70): string[] {\n const words = text.split(' ');\n const lines: string[] = [];\n let currentLine = '';\n\n for (const word of words) {\n if (currentLine.length + word.length + 1 <= width) {\n currentLine += (currentLine ? ' ' : '') + word;\n } else {\n if (currentLine) lines.push(currentLine);\n currentLine = word;\n }\n }\n if (currentLine) lines.push(currentLine);\n return lines;\n}\n\n/**\n * Print a chat message with formatting\n */\nexport function printMessage(\n content: string,\n role: 'user' | 'assistant' | 'system',\n indent: string = ' '\n): void {\n const roleColors: Record<string, string> = {\n user: '\\x1B[34m', // Blue\n assistant: '\\x1B[32m', // Green\n system: '\\x1B[90m', // Gray\n };\n const resetColor = '\\x1B[0m';\n const color = roleColors[role] || resetColor;\n\n const label = role === 'user' ? 'You' : role === 'assistant' ? 'Assistant' : 'System';\n console.log(`${indent}${color}[${label}]${resetColor}`);\n\n const lines = content.split('\\n');\n for (const line of lines) {\n const wrapped = wrapText(line, 70);\n for (const wrappedLine of wrapped) {\n console.log(`${indent} ${wrappedLine}`);\n }\n }\n console.log('');\n}\n\n/**\n * Clear the terminal screen\n */\nexport function clearScreen(): void {\n process.stdout.write('\\x1B[2J\\x1B[H');\n}\n","/**\n * AG-UI Client for CLI chat interactions\n *\n * Implements the AG-UI (Agent-User Interaction) protocol for streaming\n * chat responses. See: https://docs.ag-ui.com/concepts/events\n */\n\nimport type { ConciergeAppContextPayload } from '../lib/cli-client-context';\n\n/**\n * AG-UI event types\n */\nexport type AGUIEventType =\n | 'RUN_STARTED'\n | 'RUN_FINISHED'\n | 'RUN_ERROR'\n | 'TEXT_MESSAGE_START'\n | 'TEXT_MESSAGE_CONTENT'\n | 'TEXT_MESSAGE_END'\n | 'TOOL_CALL_START'\n | 'TOOL_CALL_ARGS'\n | 'TOOL_CALL_END'\n | 'TOOL_CALL_RESULT'\n | 'STATE_SNAPSHOT'\n | 'STATE_DELTA'\n // Lowercase variants (some backends use these)\n | 'run_started'\n | 'run_finished'\n | 'run_error'\n | 'text_message_start'\n | 'text_message_content'\n | 'text_message_end'\n | 'tool_call_start'\n | 'tool_call_args'\n | 'tool_call_end'\n | 'tool_call_result'\n | 'state_snapshot'\n | 'state_delta'\n | 'done';\n\nexport interface AGUIEvent {\n type: AGUIEventType;\n messageId?: string;\n role?: string;\n delta?: string;\n content?: string;\n message?: string;\n code?: string;\n toolCallId?: string;\n toolCallName?: string;\n result?: any;\n snapshot?: any;\n operations?: any[];\n [key: string]: any;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n}\n\nexport interface AGUIClientOptions {\n baseUrl: string;\n workspaceUuid?: string;\n chatId?: number; // Numeric chat ID (not UUID)\n /** Full URL override — when provided, baseUrl/workspaceUuid/chatId are ignored for POST */\n endpointUrl?: string;\n accessToken: string;\n debug?: boolean;\n /** Model field sent in request body (default: 'manager'). Set to undefined to omit. */\n model?: string;\n /** Concierge / client context forwarded to the API (e.g. CLI surface hints). */\n appContext?: ConciergeAppContextPayload;\n}\n\n/**\n * AG-UI Client for streaming chat responses\n */\nexport class AGUIClient {\n private endpointUrl: string;\n private baseUrl: string;\n private workspaceUuid: string;\n private chatId: number;\n private accessToken: string;\n private debug: boolean;\n private model: string | undefined;\n private appContext: ConciergeAppContextPayload | undefined;\n\n constructor(options: AGUIClientOptions) {\n this.baseUrl = options.baseUrl;\n this.workspaceUuid = options.workspaceUuid ?? '';\n this.chatId = options.chatId ?? 0;\n if (!options.endpointUrl && (!options.workspaceUuid || options.chatId === undefined)) {\n throw new Error('AGUIClient requires workspaceUuid and chatId, or endpointUrl');\n }\n this.endpointUrl =\n options.endpointUrl ??\n `${options.baseUrl}/api/v2/w/${options.workspaceUuid}/web-chat/${options.chatId}/chat/agui`;\n this.accessToken = options.accessToken;\n this.debug = options.debug ?? false;\n this.model = 'model' in options ? options.model : 'manager';\n this.appContext = options.appContext;\n }\n\n private inferenceStatusUrl(): string | null {\n // chatId is `number`; treat 0 / negative as \"no chat\" (use <= 0 instead of\n // a falsy check so a deliberate sentinel of 0 doesn't accidentally mean\n // \"valid chat\").\n if (!this.workspaceUuid || this.chatId <= 0) return null;\n return `${this.baseUrl}/api/v2/w/${this.workspaceUuid}/chats/${this.chatId}/inference/status`;\n }\n\n private async waitForInferenceInactive(maxWaitMs = 60_000): Promise<boolean> {\n const url = this.inferenceStatusUrl();\n if (!url) return false;\n const deadline = Date.now() + maxWaitMs;\n while (Date.now() < deadline) {\n try {\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${this.accessToken}` },\n });\n if (res.ok) {\n const body = (await res.json()) as { active?: boolean };\n if (!body.active) return true;\n }\n } catch (err) {\n // Transient network errors (DNS blips, connection resets) shouldn't\n // crash the 409-retry loop. Log under --debug and keep polling\n // until the deadline; the caller will fall back to the original\n // 409 error if we can't confirm inactive in time.\n if (this.debug) {\n console.log(\n `[DEBUG] waitForInferenceInactive fetch failed: ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n }\n }\n await new Promise((r) => setTimeout(r, 2000));\n }\n return false;\n }\n\n /**\n * Send messages and stream the response\n */\n async sendMessage(\n messages: ChatMessage[],\n onEvent: (event: AGUIEvent) => void,\n options?: AguiStreamOptions\n ): Promise<void> {\n return this.streamRequest({ messages }, onEvent, options);\n }\n\n /**\n * Stream an AG-UI request (initial messages or HITL resume).\n */\n async streamRequest(\n request: AguiRequestBody,\n onEvent: (event: AGUIEvent) => void,\n options?: AguiStreamOptions\n ): Promise<void> {\n const body = JSON.stringify({\n ...(this.model ? { model: this.model } : {}),\n messages: request.messages ?? [],\n ...(this.appContext ? { appContext: this.appContext } : {}),\n ...(request.resumeValue !== undefined ? { resumeValue: request.resumeValue } : {}),\n ...(request.resumeInterruptId ? { resumeInterruptId: request.resumeInterruptId } : {}),\n ...(options?.autoApprove ? { context: { autoApprove: true } } : {}),\n });\n\n if (this.debug) {\n console.log(`\\n[DEBUG] POST ${this.endpointUrl}`);\n console.log(\n `[DEBUG] Body: ${request.resumeValue !== undefined ? 'resume' : `${(request.messages ?? []).length} message(s)`}`\n );\n }\n\n await this.postStream(body, onEvent, options);\n }\n\n private async postStream(\n body: string,\n onEvent: (event: AGUIEvent) => void,\n options?: AguiStreamOptions,\n conflictRetries = 0\n ): Promise<void> {\n const response = await fetch(this.endpointUrl, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.accessToken}`,\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n },\n body,\n });\n\n if (this.debug) {\n console.log(`[DEBUG] Response status: ${response.status}`);\n }\n\n if (response.status === 409 && conflictRetries < 3) {\n const ready = await this.waitForInferenceInactive();\n if (ready) {\n await this.postStream(body, onEvent, options, conflictRetries + 1);\n return;\n }\n }\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => '');\n if (this.debug) {\n console.log(`[DEBUG] Error response: ${errorText}`);\n }\n throw new Error(\n `Chat request failed: ${response.status}${errorText ? `: ${errorText.slice(0, 200)}` : ''}`\n );\n }\n\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') {\n onEvent({ type: 'done' });\n continue;\n }\n try {\n const event = JSON.parse(data) as AGUIEvent;\n onEvent(event);\n } catch {\n // Ignore parse errors for malformed events\n }\n }\n }\n }\n }\n}\n\nexport interface AguiStreamOptions {\n autoApprove?: boolean;\n}\n\nexport interface AguiRequestBody {\n messages?: ChatMessage[];\n resumeValue?: string;\n resumeInterruptId?: string;\n}\n\n/**\n * Helper to check if an event is a text content event\n */\nexport function isTextContentEvent(event: AGUIEvent): boolean {\n const type = event.type.toLowerCase();\n return type === 'text_message_content';\n}\n\n/**\n * Helper to check if an event is an error event\n */\nexport function isErrorEvent(event: AGUIEvent): boolean {\n const type = event.type.toLowerCase();\n return type === 'run_error';\n}\n\n/**\n * Helper to extract text delta from an event\n */\nexport function getTextDelta(event: AGUIEvent): string | null {\n if (isTextContentEvent(event) && event.delta) {\n return event.delta;\n }\n return null;\n}\n\n/**\n * Helper to extract error message from an event\n */\nexport function getErrorMessage(event: AGUIEvent): string | null {\n if (isErrorEvent(event)) {\n return event.message || event.code || 'Unknown error';\n }\n return null;\n}\n","/**\n * CLI utilities for Gravity Rail\n *\n * This module provides utilities for building CLI tools that interact\n * with the Gravity Rail API, including:\n *\n * - OAuth2 authentication with PKCE\n * - Credential caching\n * - Interactive terminal UI\n * - AG-UI streaming chat client\n */\n\n// Configuration\nexport {\n ENVIRONMENTS,\n CALLBACK_PORT,\n CALLBACK_PATH,\n REDIRECT_URI,\n getEnvironmentConfig,\n type EnvironmentConfig,\n} from './config';\n\n// Authentication\nexport {\n CredentialsManager,\n generatePKCE,\n openBrowser,\n startCallbackServer,\n performOAuthFlow,\n refreshAccessToken,\n type CLICredentials,\n type AuthResult,\n type OAuthFlowOptions,\n} from './auth';\n\n// Terminal UI\nexport {\n selectFromList,\n printTable,\n formatTimestamp,\n wrapText,\n printMessage,\n clearScreen,\n type SelectFromListOptions,\n type SelectResult,\n} from './ui';\n\n// AG-UI Client\nexport {\n AGUIClient,\n isTextContentEvent,\n isErrorEvent,\n getTextDelta,\n getErrorMessage,\n type AGUIEvent,\n type AGUIEventType,\n type ChatMessage as AGUIChatMessage,\n type AGUIClientOptions,\n} from './agui';\n","export class CLIError extends Error {\n constructor(\n message: string,\n public exitCode: number = 1\n ) {\n super(message);\n this.name = 'CLIError';\n }\n}\n\nexport class AuthRequiredError extends CLIError {\n constructor(message = 'Not authenticated. Run `gr login` or set GRAVITY_RAIL_API_KEY.') {\n super(message, 2);\n this.name = 'AuthRequiredError';\n }\n}\n\nexport function handleError(err: unknown): never {\n if (err instanceof CLIError) {\n process.stderr.write(`Error: ${err.message}\\n`);\n process.exit(err.exitCode);\n }\n\n if (err instanceof Error) {\n process.stderr.write(`Error: ${err.message}\\n`);\n if ('errors' in err && Array.isArray((err as any).errors)) {\n for (const e of (err as any).errors) {\n process.stderr.write(` - ${e}\\n`);\n }\n }\n if ('statusCode' in err && (err as any).statusCode === 401) {\n process.stderr.write(\n `\\nHint: Run \"gr login\" to authenticate, or set GRAVITY_RAIL_API_KEY for non-interactive use.\\n`\n );\n }\n process.exit(1);\n }\n\n process.stderr.write(`Error: ${String(err)}\\n`);\n process.exit(1);\n}\n","import type { ArgDef, ParsedArgs } from './types';\nimport { CLIError } from './errors';\n\n// ── Response shape detection ─────────────────────────────────────────\n\n/** Metadata extracted from a paginated API response */\nexport interface PaginationMeta {\n /** Total number of items across all pages (page-based only) */\n total?: number;\n /** Current page number (page-based only) */\n page?: number;\n /** Total pages (page-based only) */\n totalPages?: number;\n /** Whether more pages exist (cursor-based only) */\n hasMore?: boolean;\n /** Cursor for next page (cursor-based only) */\n nextCursor?: string;\n}\n\n/** Explicit pagination contract passed from commands to outputData */\nexport interface ListResult {\n items: unknown[];\n meta?: PaginationMeta;\n supportsAll?: boolean;\n}\n\n/** Type guard: is the value a ListResult (explicit contract)? */\nexport function isListResult(data: unknown): data is ListResult {\n if (!data || typeof data !== 'object' || Array.isArray(data)) return false;\n const obj = data as Record<string, unknown>;\n return (\n Array.isArray(obj.items) &&\n ('supportsAll' in obj ||\n ('meta' in obj && (obj.meta === undefined || typeof obj.meta === 'object')))\n );\n}\n\n/** Check if a response looks like a page-based paginated envelope.\n * Matches both `{ items, total, totalPages, page }` (standard) and\n * `{ items, total, page, pageSize }` (legacy — e.g. InvitationListResponse,\n * InquiryListResponse). This is a pure type guard with no side effects;\n * totalPages computation for legacy shapes happens in extractPaginationMeta. */\nexport function isPagePaginatedResponse(data: unknown): data is {\n items: unknown[];\n total: number;\n page: number;\n totalPages?: number;\n pageSize?: number;\n} {\n if (!data || typeof data !== 'object') return false;\n const obj = data as Record<string, unknown>;\n if (!Array.isArray(obj.items) || typeof obj.page !== 'number') return false;\n\n // Standard shape: has totalPages\n if (typeof obj.totalPages === 'number') return true;\n\n // Legacy shape: has total + pageSize but no totalPages\n if (typeof obj.total === 'number' && typeof obj.pageSize === 'number') return true;\n\n return false;\n}\n\n/** Check if a response looks like a cursor-based paginated envelope */\nexport function isCursorPaginatedResponse(data: unknown): data is {\n items: unknown[];\n hasMore: boolean;\n nextCursor?: string;\n} {\n if (!data || typeof data !== 'object') return false;\n const obj = data as Record<string, unknown>;\n return Array.isArray(obj.items) && typeof obj.hasMore === 'boolean';\n}\n\n/** Check if a response is any paginated envelope ({ items: [...], ... }) */\nexport function isPaginatedResponse(data: unknown): boolean {\n return isPagePaginatedResponse(data) || isCursorPaginatedResponse(data);\n}\n\n/** Extract pagination metadata from a response, or return undefined for non-paginated responses.\n * For legacy shapes without totalPages, computes it from total/pageSize. */\nexport function extractPaginationMeta(data: unknown): PaginationMeta | undefined {\n if (isPagePaginatedResponse(data)) {\n const totalPages =\n data.totalPages ?? (data.pageSize ? Math.ceil(data.total / data.pageSize) : undefined);\n return {\n total: data.total,\n page: data.page,\n totalPages,\n };\n }\n if (isCursorPaginatedResponse(data)) {\n return {\n hasMore: data.hasMore,\n nextCursor: data.nextCursor,\n };\n }\n return undefined;\n}\n\n// ── Warning formatting ───────────────────────────────────────────────\n\n/** Format a pagination warning for stderr. Returns undefined if no warning needed.\n * When `supportsAll` is false, the \"Use --all\" hint is omitted because the\n * command does not actually expose the --all flag. */\nexport function formatPaginationWarning(\n meta: PaginationMeta | undefined,\n supportsAll: boolean = true\n): string | undefined {\n if (!meta) return undefined;\n\n const allHint = supportsAll ? ' Use --all to fetch all pages.' : '';\n\n // Page-based: warn when there are multiple pages\n if (meta.totalPages !== undefined && meta.totalPages > 1) {\n const pageNum = meta.page ?? 1;\n return `Showing page ${pageNum} of ${meta.totalPages} (${meta.total} total items).${allHint}`;\n }\n\n // Cursor-based: warn when more pages exist\n if (meta.hasMore === true) {\n return `More results available.${allHint}`;\n }\n\n return undefined;\n}\n\n// ── Unwrapping ───────────────────────────────────────────────────────\n\n/** Unwrap items from a paginated response or return the data as-is if it's an array */\nexport function unwrapItems(data: unknown): unknown[] {\n if (Array.isArray(data)) return data;\n if (\n data &&\n typeof data === 'object' &&\n 'items' in data &&\n Array.isArray((data as Record<string, unknown>).items)\n ) {\n return (data as Record<string, unknown>).items as unknown[];\n }\n return [data];\n}\n\n// ── Arg definitions ──────────────────────────────────────────────────\n\n/** Default pagination args for list commands (page, page-size, all). No search. */\nexport const LIST_PAGINATION_ARGS: ArgDef[] = [\n { name: 'page', description: 'Page number' },\n { name: 'page-size', description: 'Page size' },\n { name: 'all', description: 'Fetch all pages and return combined results', isFlag: true },\n];\n\n// ── Arg-to-options helpers ───────────────────────────────────────────\n\n/** Convert parsed CLI args to API pagination options */\nexport function parsePaginationArgs(args: ParsedArgs): {\n page?: number;\n pageSize?: number;\n all?: boolean;\n} {\n const result: { page?: number; pageSize?: number; all?: boolean } = {};\n\n if (args.all === true) {\n result.all = true;\n }\n\n if (args.page !== undefined) {\n const num = Number(args.page);\n if (isNaN(num) || num < 1) throw new CLIError('--page must be a positive integer');\n result.page = num;\n }\n\n if (args['page-size'] !== undefined) {\n const num = Number(args['page-size']);\n if (isNaN(num) || num < 1) throw new CLIError('--page-size must be a positive integer');\n if (num > 100) throw new CLIError('--page-size must be at most 100 (API limit)');\n result.pageSize = num;\n }\n\n return result;\n}\n\n// ── fetchAll helpers ─────────────────────────────────────────────────\n\nconst MAX_PAGE_SIZE = 100;\nconst MAX_PAGES = 200; // Safety limit to prevent infinite loops\n\n/**\n * Fetch all pages from a page-based paginated endpoint.\n * The fetcher receives { page, pageSize } and should return the raw API response.\n * Throws CLIError if MAX_PAGES is reached without exhausting all pages.\n */\nexport async function fetchAllPages(\n fetcher: (opts: { page: number; pageSize: number }) => Promise<unknown>\n): Promise<unknown[]> {\n const allItems: unknown[] = [];\n let page = 1;\n\n while (page <= MAX_PAGES) {\n const result = await fetcher({ page, pageSize: MAX_PAGE_SIZE });\n const items = unwrapItems(result);\n allItems.push(...items);\n\n // Use server metadata for termination\n const meta = extractPaginationMeta(result);\n if (meta?.totalPages !== undefined) {\n if (page >= meta.totalPages) break;\n } else if (!isPagePaginatedResponse(result)) {\n // Raw array or no metadata — single fetch is enough\n if (items.length < MAX_PAGE_SIZE) break;\n }\n\n if (page === MAX_PAGES) {\n throw new CLIError(\n `Reached maximum page limit (${MAX_PAGES}). Results may be incomplete.`\n );\n }\n\n page++;\n }\n\n return allItems;\n}\n\n/**\n * Fetch all pages from a cursor-based paginated endpoint.\n * The fetcher receives { cursor? } and should return the raw API response.\n * Throws CLIError if MAX_PAGES is reached without exhausting all pages.\n */\nexport async function fetchAllCursorPages(\n fetcher: (opts: { cursor?: string }) => Promise<unknown>\n): Promise<unknown[]> {\n const allItems: unknown[] = [];\n let cursor: string | undefined;\n let pages = 0;\n\n while (pages < MAX_PAGES) {\n const result = await fetcher({ cursor });\n const items = unwrapItems(result);\n allItems.push(...items);\n pages++;\n\n if (isCursorPaginatedResponse(result) && result.hasMore && result.nextCursor) {\n cursor = result.nextCursor;\n } else {\n break;\n }\n\n if (pages === MAX_PAGES) {\n throw new CLIError(\n `Reached maximum page limit (${MAX_PAGES}). Results may be incomplete.`\n );\n }\n }\n\n return allItems;\n}\n\n// ── ListResult factory ──────────────────────────────────────────────\n\n/**\n * Wrap a raw API response into a ListResult with explicit pagination metadata.\n * Works with both page-based and cursor-based responses, as well as plain arrays.\n *\n * @param data - Raw API response (paginated envelope or plain array)\n * @param supportsAll - Whether the calling command exposes --all\n */\nexport function listResult(data: unknown, supportsAll: boolean = false): ListResult {\n return {\n items: unwrapItems(data),\n meta: extractPaginationMeta(data),\n supportsAll,\n };\n}\n","import { printTable } from '../cli-utils';\nimport {\n type PaginationMeta,\n isListResult,\n extractPaginationMeta,\n formatPaginationWarning,\n unwrapItems,\n} from './pagination';\n\nexport type OutputFormat = 'json' | 'jsonl' | 'table';\n\nexport interface OutputOptions {\n outputFormat: OutputFormat;\n}\n\nexport interface TableColumn<T> {\n header: string;\n getValue: (item: T) => string;\n maxWidth?: number;\n}\n\n/** Detect default output format based on whether stdout is a TTY */\nexport function detectOutputFormat(explicit?: string): OutputFormat {\n if (explicit) return explicit as OutputFormat;\n return process.stdout.isTTY ? 'table' : 'json';\n}\n\n/**\n * Write a list of items to stdout in the requested format.\n *\n * Accepts:\n * - A `ListResult` (explicit contract with items, meta, supportsAll) — preferred.\n * - Raw arrays, paginated responses ({ items: [...] }), or any object — legacy.\n *\n * When a `ListResult` is passed, its explicit `meta` and `supportsAll` are used.\n * When raw data is passed, pagination metadata is auto-detected with\n * `supportsAll: false` as the safe default.\n *\n * The optional `paginationMeta` and `supportsAll` parameters are kept for\n * backward compatibility but are ignored when a `ListResult` is passed.\n */\nexport function outputData(\n data: unknown,\n opts: OutputOptions,\n columns?: TableColumn<any>[],\n paginationMeta?: PaginationMeta,\n supportsAll?: boolean\n): void {\n let items: unknown[];\n let meta: PaginationMeta | undefined;\n let allSupported: boolean;\n\n if (isListResult(data)) {\n // Explicit contract: use ListResult fields directly\n items = data.items;\n meta = data.meta;\n allSupported = data.supportsAll ?? false;\n } else {\n // Legacy path: auto-detect from raw data\n items = unwrapItems(data);\n meta = paginationMeta ?? extractPaginationMeta(data);\n allSupported = supportsAll ?? false;\n }\n\n const warning = formatPaginationWarning(meta, allSupported);\n if (warning) {\n process.stderr.write(warning + '\\n');\n }\n\n switch (opts.outputFormat) {\n case 'json':\n process.stdout.write(JSON.stringify(items, null, 2) + '\\n');\n break;\n case 'jsonl':\n for (const item of items) {\n process.stdout.write(JSON.stringify(item) + '\\n');\n }\n break;\n case 'table':\n if (columns) {\n printTable(items, columns);\n } else {\n process.stdout.write(JSON.stringify(items, null, 2) + '\\n');\n }\n break;\n }\n}\n\n/** Write a single object to stdout in the requested format */\nexport function outputSingle<T>(data: T, opts: OutputOptions, columns?: TableColumn<T>[]): void {\n switch (opts.outputFormat) {\n case 'json':\n process.stdout.write(JSON.stringify(data, null, 2) + '\\n');\n break;\n case 'jsonl':\n process.stdout.write(JSON.stringify(data) + '\\n');\n break;\n case 'table':\n if (columns) {\n printTable([data], columns);\n } else {\n process.stdout.write(JSON.stringify(data, null, 2) + '\\n');\n }\n break;\n }\n}\n\n/** Common column factory helpers for domain files */\nexport const COL = {\n id: (): TableColumn<any> => ({ header: 'ID', getValue: (item) => String(item.id ?? '') }),\n uuid: (): TableColumn<any> => ({ header: 'UUID', getValue: (item) => item.uuid ?? '' }),\n name: (): TableColumn<any> => ({ header: 'NAME', getValue: (item) => item.name ?? '' }),\n status: (): TableColumn<any> => ({ header: 'STATUS', getValue: (item) => item.status ?? '' }),\n created: (): TableColumn<any> => ({\n header: 'CREATED',\n getValue: (item) => item.created_at ?? '',\n }),\n updated: (): TableColumn<any> => ({\n header: 'UPDATED',\n getValue: (item) => item.updated_at ?? '',\n }),\n description: (): TableColumn<any> => ({\n header: 'DESCRIPTION',\n getValue: (item) => item.description ?? '',\n }),\n enabled: (): TableColumn<any> => ({\n header: 'ENABLED',\n getValue: (item) => String(item.enabled ?? ''),\n }),\n};\n\n/** Write a status/progress message to stderr (never pollutes stdout) */\nexport function stderr(msg: string): void {\n process.stderr.write(msg + '\\n');\n}\n","/**\n * @gravity-rail/client — Internal full-surface API client.\n *\n * Re-exports the entire public SDK surface via `@gravity-rail/sdk/internal`\n * (which includes admin TypeScript types), and adds the admin runtime classes\n * (`AdminApi`, `ApiClient`, `AdminBindings`, `bindAdminMethods`).\n *\n * Consumers in the monorepo should continue importing from `@gravity-rail/client`\n * as before — nothing externally visible has changed. The admin runtime classes\n * are physically absent from the public `@gravity-rail/sdk` package.\n */\n\nexport * from '@gravity-rail/sdk/internal';\n\n// Admin-only runtime\nexport { AdminApi } from './api/admin';\nexport type {\n AdminActivityEvent,\n AdminActivityEventListParams,\n AdminActivityEventListResponse,\n} from './api/admin';\nexport { ApiClient } from './client/client';\nexport type { AdminBindings } from './client/bindings/admin';\nexport { bindAdminMethods } from './client/bindings/admin';\n","import {\n AccountLookupResponse,\n CreateCustomerRequest,\n CreateResellerRequest,\n Customer,\n DataExportResponse,\n DeletionCancelResponse,\n DeletionRequestResponse,\n CustomerAccount,\n LinkResellerAccountRequest,\n Reseller,\n ResellerAccount,\n UpdateCustomerRequest,\n UpdateResellerRequest,\n AccountSortField,\n AdminAccount,\n AdminBulkWorkflowAccessValidationResponse,\n HealthDetailRequest,\n HealthMetricsRequest,\n HealthMetricsResponse,\n WorkspaceHealthDetail,\n AdminAccountFormData,\n AdminAccountMembership,\n AdminAccountOrgMembership,\n AdminOrganization,\n AdminUpdateProductRequest,\n AdminChat,\n AdminChatDetail,\n AdminChatsOptions,\n MemberOrgView,\n AdminWorkspace,\n AdminWorkspaceFormData,\n AdminWorkspaceMemberFormData,\n UsageDashboardResponse,\n CompareWithStripeResponse,\n UsageReport,\n UsageReportRequest,\n VoiceMetricsResponse,\n AdminTemporalDetailQuery,\n AdminTemporalFailedQuery,\n AdminTemporalStuckQuery,\n AdminTemporalSummaryQuery,\n FailedWorkflowsResponse,\n StuckWorkflowsResponse,\n TemporalAdminConfig,\n TemporalSummaryResponse,\n WorkflowDetailResponse,\n CreateOrganizationRequest,\n CreateProductRequest,\n GenerateSummariesResponse,\n Inbox,\n InboxMappingDetailResponse,\n LogoUploadRequest,\n LogoUploadResponse,\n Member,\n MemberRole,\n MergeMembersRequest,\n MergeMembersResponse,\n MissingMembershipItem,\n OrgMember,\n PaginatedResponse,\n PaginatedSubscriptionsResponse,\n PhoneNumber,\n UnmappedPhoneNumber,\n Product,\n ChangeWorkspaceProductRequest,\n ChangeWorkspaceProductResponse,\n ProvisionPlanRequest,\n ProvisionPlanResponse,\n SiteMapping,\n SiteMappingFormData,\n SortOrder,\n StripeCustomer,\n StripeCustomerCreateRequest,\n StripeCustomerUpdateRequest,\n StripePaymentMethod,\n BillingPeriod,\n Invoice,\n RecordPaymentRequest,\n DirectSubscriptionCreateRequest,\n StripeSubscriptionCreateRequest,\n StripeSubscriptionUpdateRequest,\n Subscription,\n SyncProductToStripeRequest,\n SyncProductToStripeResponse,\n ThemesListResponse,\n OrgA2PStatus,\n ProviderPhoneNumber,\n UpdateOrganizationRequest,\n Workspace,\n WorkspaceHealthResponse,\n WorkspaceSortField,\n AttachSupportRequestResourceRequest,\n CreateOutboundSupportRequestRequest,\n CreateSupportRequestCommentRequest,\n CreateSupportRequestNoteRequest,\n SupportRequest,\n SupportRequestListParams,\n SupportRequestListResponse,\n UpdateSupportRequestAttributesRequest,\n UpdateSupportRequestStatusRequest,\n} from '@gravity-rail/sdk/internal';\nimport { BaseApiClient } from '@gravity-rail/sdk/internal';\n\nfunction supportRequestParams(params?: SupportRequestListParams): string {\n const searchParams = new URLSearchParams();\n if (params?.page) searchParams.append('page', params.page.toString());\n if (params?.pageSize) searchParams.append('pageSize', params.pageSize.toString());\n if (params?.status) searchParams.append('status', params.status);\n if (params?.supportRequestType) {\n searchParams.append('supportRequestType', params.supportRequestType);\n }\n if (params?.severity) searchParams.append('severity', params.severity);\n if (params?.source) searchParams.append('source', params.source);\n if (params?.organizationId !== undefined) {\n searchParams.append('organizationId', params.organizationId.toString());\n }\n if (params?.workspaceId !== undefined) {\n searchParams.append('workspaceId', params.workspaceId.toString());\n }\n if (params?.linearLinked !== undefined) {\n searchParams.append('linearLinked', params.linearLinked.toString());\n }\n const query = searchParams.toString();\n return query ? `?${query}` : '';\n}\n\nexport class AdminApi extends BaseApiClient {\n // Support Requests API\n async listSupportRequestsAsAdmin(\n params?: SupportRequestListParams\n ): Promise<SupportRequestListResponse> {\n return this.fetch<SupportRequestListResponse>(\n `admin/support-requests${supportRequestParams(params)}`\n );\n }\n\n async getSupportRequestAsAdmin(uuid: string): Promise<SupportRequest> {\n return this.fetch<SupportRequest>(`admin/support-requests/${uuid}`);\n }\n\n async commentOnSupportRequestAsAdmin(\n uuid: string,\n data: CreateSupportRequestCommentRequest\n ): Promise<SupportRequest> {\n return this.fetch<SupportRequest>(`admin/support-requests/${uuid}/comments`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async noteOnSupportRequestAsAdmin(\n uuid: string,\n data: CreateSupportRequestNoteRequest\n ): Promise<SupportRequest> {\n return this.fetch<SupportRequest>(`admin/support-requests/${uuid}/notes`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async updateSupportRequestStatusAsAdmin(\n uuid: string,\n data: UpdateSupportRequestStatusRequest\n ): Promise<SupportRequest> {\n return this.fetch<SupportRequest>(`admin/support-requests/${uuid}/status`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async updateSupportRequestAttributesAsAdmin(\n uuid: string,\n data: UpdateSupportRequestAttributesRequest\n ): Promise<SupportRequest> {\n return this.fetch<SupportRequest>(`admin/support-requests/${uuid}/attributes`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async createSupportRequestLinearIssueAsAdmin(uuid: string): Promise<SupportRequest> {\n return this.fetch<SupportRequest>(`admin/support-requests/${uuid}/linear-issue`, {\n method: 'POST',\n });\n }\n\n // Proactive Support: outbound (us→customer) requests + resources\n async createOutboundSupportRequestAsAdmin(\n data: CreateOutboundSupportRequestRequest\n ): Promise<SupportRequest> {\n return this.fetch<SupportRequest>('admin/support-requests/outbound', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async attachSupportRequestResourceAsAdmin(\n uuid: string,\n data: AttachSupportRequestResourceRequest\n ): Promise<SupportRequest> {\n return this.fetch<SupportRequest>(`admin/support-requests/${uuid}/resources`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async revokeSupportRequestResourceAsAdmin(\n uuid: string,\n resourceUuid: string\n ): Promise<SupportRequest> {\n return this.fetch<SupportRequest>(\n `admin/support-requests/${uuid}/resources/${resourceUuid}/revoke`,\n { method: 'POST' }\n );\n }\n\n // Admin Accounts API\n async getAccounts(options: {\n search?: string;\n createdAfter?: string;\n createdBefore?: string;\n isActive?: boolean;\n organizationId?: number;\n workspaceId?: number;\n pendingDeletion?: boolean;\n sortBy?: AccountSortField;\n sortOrder?: SortOrder;\n page?: number;\n pageSize?: number;\n }): Promise<PaginatedResponse<AdminAccount>> {\n const params = new URLSearchParams();\n if (options.search) params.append('search', options.search);\n if (options.createdAfter) params.append('created_after', options.createdAfter);\n if (options.createdBefore) params.append('created_before', options.createdBefore);\n if (options.sortBy) params.append('sortBy', options.sortBy);\n if (options.sortOrder) params.append('sortOrder', options.sortOrder);\n if (options.page) params.append('page', options.page.toString());\n if (options.pageSize) params.append('pageSize', options.pageSize.toString());\n if (options.isActive !== undefined) params.append('isActive', options.isActive.toString());\n if (options.organizationId !== undefined)\n params.append('organizationId', options.organizationId.toString());\n if (options.workspaceId !== undefined)\n params.append('workspaceId', options.workspaceId.toString());\n if (options.pendingDeletion !== undefined)\n params.append('pendingDeletion', options.pendingDeletion.toString());\n\n return this.fetch<PaginatedResponse<AdminAccount>>(`admin/accounts?${params.toString()}`);\n }\n\n async getAccountDetails(id: string | number): Promise<AdminAccount> {\n return this.fetch<AdminAccount>(`admin/accounts/${id}`);\n }\n\n async getAccountByUuid(uuid: string): Promise<AdminAccount> {\n return this.fetch<AdminAccount>(`admin/accounts/${uuid}`);\n }\n\n async getAccountMemberships(accountId: number): Promise<AdminAccountMembership[]> {\n return this.fetch<AdminAccountMembership[]>(`admin/accounts/${accountId}/memberships`);\n }\n\n async getAccountOrgMemberships(accountId: number): Promise<AdminAccountOrgMembership[]> {\n return this.fetch<AdminAccountOrgMembership[]>(`admin/accounts/${accountId}/org-memberships`);\n }\n\n async createAccountOrgMembership(\n accountId: number,\n organizationId: number,\n role: 'member' | 'admin' | 'owner' = 'member'\n ): Promise<{\n accountId: number;\n organizationId: number;\n organizationUuid: string;\n organizationName: string;\n role: string;\n message: string;\n }> {\n return this.fetch(`admin/accounts/${accountId}/org-memberships`, {\n method: 'POST',\n body: JSON.stringify({ organizationId, role }),\n });\n }\n\n async deleteAccountOrgMembership(\n accountId: number,\n organizationId: number\n ): Promise<{\n status: string;\n message: string;\n workspaceMembershipsRemoved: number;\n }> {\n return this.fetch(`admin/accounts/${accountId}/org-memberships/${organizationId}`, {\n method: 'DELETE',\n });\n }\n\n async getAccountMembership(\n accountId: number,\n workspaceId: string\n ): Promise<AdminAccountMembership> {\n return this.fetch<AdminAccountMembership>(\n `admin/accounts/${accountId}/memberships/${workspaceId}`\n );\n }\n\n async updateAccountMembership(\n accountId: number,\n workspaceId: string,\n updates: AdminWorkspaceMemberFormData\n ): Promise<AdminAccountMembership> {\n return this.fetch<AdminAccountMembership>(\n `admin/accounts/${accountId}/memberships/${workspaceId}`,\n {\n method: 'PUT',\n body: JSON.stringify(updates),\n }\n );\n }\n\n async createAccountMembership(\n accountId: number,\n workspaceId: string,\n data: { memberRoleId: number }\n ): Promise<AdminAccountMembership> {\n return this.fetch<AdminAccountMembership>(\n `admin/accounts/${accountId}/memberships/${workspaceId}`,\n {\n method: 'POST',\n body: JSON.stringify(data),\n }\n );\n }\n\n async deleteAccountMembership(accountId: number, workspaceId: string): Promise<void> {\n return this.fetch<void>(`admin/accounts/${accountId}/memberships/${workspaceId}`, {\n method: 'DELETE',\n });\n }\n\n async updateAccountAsAdmin(\n id: string | number,\n updates: AdminAccountFormData\n ): Promise<AdminAccount> {\n return this.fetch<AdminAccount>(`admin/accounts/${id}`, {\n method: 'PUT',\n body: JSON.stringify(updates),\n });\n }\n\n async createAccountAsAdmin(data: AdminAccountFormData): Promise<AdminAccount> {\n return this.fetch<AdminAccount>('admin/accounts', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async deleteAccountAsAdmin(id: number): Promise<void> {\n return this.fetch(`admin/accounts/${id}`, {\n method: 'DELETE',\n });\n }\n\n // GDPR Data Subject Rights (superuser only)\n\n async exportAccountData(accountId: number): Promise<DataExportResponse> {\n return this.fetch(`admin/data-rights/${accountId}/export`, {\n method: 'POST',\n });\n }\n\n async requestAccountDeletion(accountId: number): Promise<DeletionRequestResponse> {\n return this.fetch(`admin/data-rights/${accountId}/delete`, {\n method: 'POST',\n });\n }\n\n async cancelAccountDeletion(accountId: number): Promise<DeletionCancelResponse> {\n return this.fetch(`admin/data-rights/${accountId}/cancel-delete`, {\n method: 'POST',\n });\n }\n\n /**\n * Look up an account by email or phone. Returns verification status.\n * Used to check if a verified account exists before creating a new one.\n */\n async lookupAccount(options: {\n email?: string;\n phone?: string;\n }): Promise<AccountLookupResponse> {\n const params = new URLSearchParams();\n if (options.email) params.append('email', options.email);\n if (options.phone) params.append('phone', options.phone);\n\n return this.fetch<AccountLookupResponse>(`admin/accounts/lookup?${params.toString()}`);\n }\n\n // Admin Organizations API\n async getOrganizations(options?: {\n search?: string;\n page?: number;\n pageSize?: number;\n noSubscription?: boolean;\n sortBy?: string;\n sortOrder?: 'asc' | 'desc';\n }): Promise<PaginatedResponse<AdminOrganization>> {\n const params = new URLSearchParams();\n if (options?.search) params.append('search', options.search);\n if (options?.page) params.append('page', options.page.toString());\n if (options?.pageSize) params.append('pageSize', options.pageSize.toString());\n if (options?.noSubscription) params.append('no_subscription', 'true');\n if (options?.sortBy) params.append('sortBy', options.sortBy);\n if (options?.sortOrder) params.append('sortOrder', options.sortOrder);\n\n return this.fetch<PaginatedResponse<AdminOrganization>>(\n `admin/organizations?${params.toString()}`\n );\n }\n\n /**\n * Get organization by ID or UUID.\n * Returns different response based on user's role:\n * - Admins/Owners: AdminOrganization with full details\n * - Members: MemberOrgView with basic info and workspace list\n *\n * Use `viewType` field to determine the response type:\n * - 'admin': AdminOrganization\n * - 'member': MemberOrgView\n */\n async getOrganization(idOrUuid: number | string): Promise<AdminOrganization | MemberOrgView> {\n return this.fetch<AdminOrganization | MemberOrgView>(`o/${idOrUuid}`);\n }\n\n /**\n * Get organization by numeric ID or UUID via admin endpoint.\n * Does NOT require organization membership — superuser-only.\n */\n async getOrganizationAsAdmin(idOrUuid: number | string): Promise<AdminOrganization> {\n return this.fetch<AdminOrganization>(`admin/organizations/${idOrUuid}`);\n }\n\n async getOrganizationMembersAsAdmin(\n organizationId: number,\n options?: { search?: string; role?: string; page?: number; pageSize?: number }\n ): Promise<PaginatedResponse<OrgMember>> {\n const params = new URLSearchParams();\n if (options?.search) params.append('search', options.search);\n if (options?.role) params.append('role', options.role);\n if (options?.page) params.append('page', options.page.toString());\n if (options?.pageSize) params.append('pageSize', options.pageSize.toString());\n const qs = params.toString();\n return this.fetch<PaginatedResponse<OrgMember>>(\n `admin/organizations/${organizationId}/members${qs ? `?${qs}` : ''}`\n );\n }\n\n async createOrganization(data: CreateOrganizationRequest): Promise<AdminOrganization> {\n return this.fetch<AdminOrganization>('admin/organizations', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async updateOrganization(\n id: number,\n data: UpdateOrganizationRequest\n ): Promise<AdminOrganization> {\n return this.fetch<AdminOrganization>(`admin/organizations/${id}`, {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n async deleteOrganization(id: number): Promise<void> {\n return this.fetch(`admin/organizations/${id}`, {\n method: 'DELETE',\n });\n }\n\n /**\n * Join an organization with a specified role (superuser only).\n * Creates or updates membership in the target org.\n * @param orgUuid - Organization UUID or numeric ID as string\n */\n async joinOrganization(\n orgUuid: string,\n role: 'member' | 'admin' | 'owner' = 'owner'\n ): Promise<{\n accountId: number;\n organizationId: number;\n organizationUuid: string;\n email: string | null;\n role: string;\n message: string;\n }> {\n return this.fetch(`admin/organizations/${orgUuid}/join`, {\n method: 'POST',\n body: JSON.stringify({ role }),\n });\n }\n\n /**\n * Leave an organization (superuser only).\n * @param orgUuid - Organization UUID or numeric ID as string\n */\n async leaveOrganization(orgUuid: string): Promise<{ status: string; message: string }> {\n return this.fetch(`admin/organizations/${orgUuid}/join`, {\n method: 'DELETE',\n });\n }\n\n async generateLogoUploadUrl(\n organizationUuid: string,\n data: LogoUploadRequest\n ): Promise<LogoUploadResponse> {\n return this.fetch<LogoUploadResponse>(`o/${organizationUuid}/logo-upload-url`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n // Organization Members API - moved to OrgApi at /api/v2/o/{org_uuid}/members\n // See packages/client/src/api/org.ts\n\n // Organization Invitations API - moved to OrgApi at /api/v2/o/{org_uuid}/invitations\n // See packages/client/src/api/org.ts\n\n // Admin Products API\n async importProducts(workspaceId: number): Promise<void> {\n return this.fetch('admin/import-products', {\n method: 'POST',\n body: JSON.stringify({ workspaceId }),\n });\n }\n\n // ===== Product CRUD =====\n\n async createProductAsAdmin(product: CreateProductRequest): Promise<Product> {\n return this.fetch<Product>('admin/products', {\n method: 'POST',\n body: JSON.stringify(product),\n });\n }\n\n async getProductsAsAdmin(workspaceUuid?: string, productTypes?: string[]): Promise<Product[]> {\n const params = new URLSearchParams();\n if (workspaceUuid) {\n params.append('workspace_uuid', workspaceUuid);\n }\n if (productTypes && productTypes.length > 0) {\n productTypes.forEach((type) => params.append('product_types', type));\n }\n const queryString = params.toString();\n return this.fetch<Product[]>(`admin/products${queryString ? `?${queryString}` : ''}`);\n }\n\n async getProductAsAdmin(productId: number): Promise<Product> {\n return this.fetch<Product>(`admin/products/${productId}`);\n }\n\n async updateProductAsAdmin(\n product_id: number,\n product: AdminUpdateProductRequest\n ): Promise<Product> {\n return this.fetch<Product>(`admin/products/${product_id}`, {\n method: 'PUT',\n body: JSON.stringify(product),\n });\n }\n\n async deleteProductAsAdmin(productId: number): Promise<{ message: string }> {\n return this.fetch<{ message: string }>(`admin/products/${productId}`, {\n method: 'DELETE',\n });\n }\n\n // Admin Workspace API\n async getWorkspacesAsAdmin(\n options: {\n page?: number;\n pageSize?: number;\n sortBy?: WorkspaceSortField;\n sortOrder?: SortOrder;\n search?: string;\n isReseller?: boolean;\n organizationId?: number;\n noActiveSubscription?: boolean;\n } = {}\n ): Promise<PaginatedResponse<AdminWorkspace>> {\n const params = new URLSearchParams();\n if (options.page !== undefined) params.append('page', options.page.toString());\n if (options.pageSize !== undefined) params.append('pageSize', options.pageSize.toString());\n if (options.sortBy) params.append('sortBy', options.sortBy);\n if (options.sortOrder) params.append('sortOrder', options.sortOrder);\n if (options.search) params.append('search', options.search);\n if (options.isReseller !== undefined)\n params.append('isReseller', options.isReseller.toString());\n if (options.organizationId !== undefined)\n params.append('organizationId', options.organizationId.toString());\n if (options.noActiveSubscription) params.append('noActiveSubscription', 'true');\n\n return this.fetch<PaginatedResponse<AdminWorkspace>>(`admin/workspaces?${params.toString()}`);\n }\n\n async getWorkspaceAsAdmin(wid: string): Promise<AdminWorkspace> {\n return this.fetch<AdminWorkspace>(`admin/workspaces/${wid}`);\n }\n\n async getWorkspaceByNumericIdAsAdmin(workspace_id: number): Promise<AdminWorkspace> {\n return this.fetch<AdminWorkspace>(`admin/workspaces/id/${workspace_id}`);\n }\n\n async createWorkspaceAsAdmin(ws: AdminWorkspaceFormData): Promise<Workspace> {\n return this.fetch<Workspace>('admin/workspaces', {\n method: 'POST',\n body: JSON.stringify(ws),\n });\n }\n\n async updateWorkspaceAsAdmin(wid: string, ws: AdminWorkspaceFormData): Promise<Workspace> {\n return this.fetch<Workspace>(`admin/workspaces/${wid}`, {\n method: 'PUT',\n body: JSON.stringify(ws),\n });\n }\n\n async deleteWorkspaceAsAdmin(wid: string): Promise<void> {\n return this.fetch(`admin/workspaces/${wid}`, {\n method: 'DELETE',\n });\n }\n\n async createSchemaAsAdmin(wid: string): Promise<AdminWorkspace> {\n return this.fetch(`admin/workspaces/${wid}/provision/create`, {\n method: 'POST',\n });\n }\n\n async migrateSchemaAsAdmin(wid: string): Promise<AdminWorkspace> {\n return this.fetch(`admin/workspaces/${wid}/provision/migrate`, {\n method: 'POST',\n });\n }\n\n async provisionWorkspaceAsAdmin(wid: string): Promise<AdminWorkspace> {\n return this.fetch(`admin/workspaces/${wid}/provision`, {\n method: 'POST',\n });\n }\n\n async refreshProvisionStatusAsAdmin(wid: string): Promise<AdminWorkspace> {\n return this.fetch(`admin/workspaces/${wid}/provision/refresh`, {\n method: 'POST',\n });\n }\n\n async enableMaintenanceMode(wid: string): Promise<AdminWorkspace> {\n return this.fetch(`admin/workspaces/${wid}/maintenance`, {\n method: 'PUT',\n });\n }\n\n async disableMaintenanceMode(wid: string): Promise<AdminWorkspace> {\n return this.fetch(`admin/workspaces/${wid}/maintenance`, {\n method: 'DELETE',\n });\n }\n\n // ===== Workspace Health Check =====\n\n async getWorkspaceHealth(workspaceUuid: string): Promise<WorkspaceHealthResponse> {\n return this.fetch<WorkspaceHealthResponse>(`admin/workspaces/${workspaceUuid}/health`);\n }\n\n async provisionPlanFeatures(\n workspaceUuid: string,\n request?: ProvisionPlanRequest\n ): Promise<ProvisionPlanResponse> {\n return this.fetch<ProvisionPlanResponse>(`admin/workspaces/${workspaceUuid}/provision-plan`, {\n method: 'POST',\n body: JSON.stringify(request || {}),\n });\n }\n\n /**\n * Switch a workspace's plan product on its active SubscriptionItem.\n *\n * Superuser only. Re-syncs ``workspace.features`` from the new product\n * and emits a ``WORKSPACE_PRODUCT_CHANGED`` audit event identifying the\n * actor, target workspace, prior and new product, and feature diff.\n *\n * Stripe is not touched here; price-id changes belong to the dedicated\n * Stripe sync surface (``syncProductToStripe``).\n */\n async changeWorkspaceProduct(\n workspaceUuid: string,\n productId: number\n ): Promise<ChangeWorkspaceProductResponse> {\n const body: ChangeWorkspaceProductRequest = { productId };\n return this.fetch<ChangeWorkspaceProductResponse>(\n `admin/workspaces/${workspaceUuid}/product`,\n {\n method: 'POST',\n body: JSON.stringify(body),\n }\n );\n }\n\n // ===== Workflow Access Validation =====\n\n async validateWorkflowAccessAsAdmin(\n workspaceUuid?: string\n ): Promise<AdminBulkWorkflowAccessValidationResponse> {\n const params = new URLSearchParams();\n if (workspaceUuid) params.append('workspace_uuid', workspaceUuid);\n const qs = params.toString();\n return this.fetch<AdminBulkWorkflowAccessValidationResponse>(\n `admin/workspaces/validate-workflow-access${qs ? `?${qs}` : ''}`\n );\n }\n\n async mergeMembers(wid: string, request: MergeMembersRequest): Promise<MergeMembersResponse> {\n return this.fetch<MergeMembersResponse>(`admin/workspaces/${wid}/merge-members`, {\n method: 'POST',\n body: JSON.stringify(request),\n });\n }\n\n async getAdminWorkspaceMember(wid: string): Promise<Member> {\n return this.fetch(`admin/workspaces/${wid}/me`, {\n method: 'GET',\n });\n }\n\n async createAdminWorkspaceMember(\n wid: string,\n data: AdminWorkspaceMemberFormData\n ): Promise<void> {\n return this.fetch(`admin/workspaces/${wid}/me`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async updateAdminWorkspaceMember(\n wid: string,\n data: AdminWorkspaceMemberFormData\n ): Promise<void> {\n return this.fetch(`admin/workspaces/${wid}/me`, {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n async unarchiveAdminWorkspaceMember(wid: string): Promise<Member> {\n return this.fetch(`admin/workspaces/${wid}/me/unarchive`, {\n method: 'POST',\n });\n }\n\n async getAdminWorkspaceMemberRoles(wid: string): Promise<MemberRole[]> {\n return this.fetch<MemberRole[]>(`admin/workspaces/${wid}/member-roles`);\n }\n\n async getUnmappedPhoneNumbers(): Promise<UnmappedPhoneNumber[]> {\n return this.fetch<UnmappedPhoneNumber[]>(`admin/phone-numbers/unmapped`);\n }\n\n async getWorkspaceUnmappedPhoneNumbers(workspaceId: number): Promise<UnmappedPhoneNumber[]> {\n return this.fetch<UnmappedPhoneNumber[]>(\n `admin/phone-numbers/workspace/${workspaceId}/unmapped`\n );\n }\n\n async getWorkspacePhoneNumbersAsAdmin(workspaceRef: string): Promise<PhoneNumber[]> {\n return this.fetch<PhoneNumber[]>(`admin/workspaces/${workspaceRef}/phone-numbers`);\n }\n\n // Phone Numbers API (Provider phone numbers from Twilio, AWS, etc.)\n async getProviderPhoneNumbers(\n options: {\n search?: string;\n isAssigned?: boolean;\n provider?: string;\n organizationId?: number;\n sortBy?: string;\n sortOrder?: string;\n page?: number;\n pageSize?: number;\n } = {}\n ): Promise<PaginatedResponse<ProviderPhoneNumber>> {\n const params = new URLSearchParams();\n if (options.page) params.append('page', options.page.toString());\n if (options.pageSize) params.append('pageSize', options.pageSize.toString());\n if (options.search) params.append('search', options.search);\n if (options.isAssigned !== undefined)\n params.append('is_assigned', String(options.isAssigned));\n if (options.provider) params.append('provider', options.provider);\n if (options.organizationId !== undefined)\n params.append('organizationId', options.organizationId.toString());\n if (options.sortBy) params.append('sortBy', options.sortBy);\n if (options.sortOrder) params.append('sortOrder', options.sortOrder);\n\n return this.fetch<PaginatedResponse<ProviderPhoneNumber>>(\n `admin/phone-numbers${params.toString() ? `?${params.toString()}` : ''}`\n );\n }\n\n async getProviderPhoneNumber(id: number): Promise<ProviderPhoneNumber> {\n return this.fetch<ProviderPhoneNumber>(`admin/phone-numbers/${id}`);\n }\n\n async updateProviderPhoneNumber(\n id: number,\n data: { organizationId: number | null }\n ): Promise<ProviderPhoneNumber> {\n return this.fetch<ProviderPhoneNumber>(`admin/phone-numbers/${id}`, {\n method: 'PATCH',\n body: JSON.stringify(data),\n });\n }\n\n async mapMainAccountPhone(data: {\n phoneNumber: string;\n workspaceUuid: string;\n name?: string;\n }): Promise<ProviderPhoneNumber> {\n return this.fetch<ProviderPhoneNumber>(`admin/phone-numbers/map-from-main-account`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async unmapPhoneNumber(data: {\n phoneNumber: string;\n }): Promise<{ status: string; phoneNumber: string }> {\n return this.fetch<{ status: string; phoneNumber: string }>(`admin/phone-numbers/unmap`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async searchAvailablePhoneNumbersAsAdmin(data: {\n organizationId: number;\n country?: string;\n numberType?: string;\n areaCode?: string;\n contains?: string;\n limit?: number;\n }): Promise<\n Array<{\n phoneNumber: string;\n friendlyName: string;\n locality: string | null;\n region: string | null;\n isoCountry: string;\n voiceEnabled: boolean;\n smsEnabled: boolean;\n }>\n > {\n return this.fetch(`admin/phone-numbers/search`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async purchasePhoneNumberAsAdmin(data: {\n organizationId: number;\n phoneNumber: string;\n numberType?: string;\n }): Promise<ProviderPhoneNumber> {\n return this.fetch<ProviderPhoneNumber>(`admin/phone-numbers/purchase`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async getOrgA2PStatusAsAdmin(organizationId: number): Promise<OrgA2PStatus> {\n return this.fetch<OrgA2PStatus>(`admin/organizations/${organizationId}/a2p-status`);\n }\n\n async resetOrgA2PStatusAsAdmin(organizationId: number): Promise<{ status: string }> {\n return this.fetch(`admin/organizations/${organizationId}/a2p-status`, {\n method: 'DELETE',\n });\n }\n\n // Site Mappings API\n async getSiteMappings(options?: {\n search?: string;\n page?: number;\n pageSize?: number;\n }): Promise<PaginatedResponse<SiteMapping>> {\n const queryParams = new URLSearchParams();\n if (options?.search) queryParams.append('search', options.search);\n if (options?.page) queryParams.append('page', options.page.toString());\n if (options?.pageSize) queryParams.append('pageSize', options.pageSize.toString());\n\n const queryString = queryParams.toString();\n const url = `admin/site-mappings${queryString ? `?${queryString}` : ''}`;\n\n return this.fetch<PaginatedResponse<SiteMapping>>(url);\n }\n\n async getSiteMapping(siteId: number): Promise<SiteMapping> {\n return this.fetch<SiteMapping>(`admin/site-mappings/${siteId}`);\n }\n\n async updateSiteMapping(siteId: number, data: SiteMappingFormData): Promise<SiteMapping> {\n return this.fetch<SiteMapping>(`admin/site-mappings/${siteId}`, {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n async updateSiteMappingWorkspace(siteId: number, workspaceId: number): Promise<SiteMapping> {\n return this.updateSiteMapping(siteId, {\n workspaceId,\n siteUuid: '', // These fields are required by the type but will be ignored on the server\n });\n }\n\n async adminDeleteSiteMapping(siteId: number): Promise<void> {\n return this.fetch<void>(`admin/site-mappings/${siteId}`, {\n method: 'DELETE',\n });\n }\n\n async createSiteMapping(mapping: SiteMappingFormData): Promise<SiteMapping> {\n return this.fetch<SiteMapping>(`admin/site-mappings`, {\n method: 'POST',\n body: JSON.stringify(mapping),\n });\n }\n\n // Keep for backward compatibility\n async createOrUpdateSiteMapping(\n wid: string,\n mapping: SiteMappingFormData\n ): Promise<SiteMapping> {\n return this.fetch<SiteMapping>(`admin/workspaces/${wid}/site-mappings`, {\n method: 'POST',\n body: JSON.stringify(mapping),\n });\n }\n\n async deleteSiteMapping(wid: string, siteUuid: string): Promise<void> {\n return this.fetch(`admin/workspaces/${wid}/site-mappings/${siteUuid}`, {\n method: 'DELETE',\n });\n }\n\n async getWorkspaceInboxesAsAdmin(\n workspaceUuid: string\n ): Promise<{ items: Inbox[]; total: number }> {\n return this.fetch<{ items: Inbox[]; total: number }>(\n `admin/workspaces/${workspaceUuid}/inboxes`\n );\n }\n\n // Admin Inbox Mappings API\n async getInboxMappings(\n options: {\n page?: number;\n pageSize?: number;\n search?: string;\n workspaceId?: number;\n } = {}\n ): Promise<PaginatedResponse<InboxMappingDetailResponse>> {\n const params = new URLSearchParams();\n if (options.page) params.append('page', options.page.toString());\n if (options.pageSize) params.append('pageSize', options.pageSize.toString());\n if (options.search) params.append('search', options.search);\n if (options.workspaceId) params.append('workspaceId', options.workspaceId.toString());\n\n return this.fetch<PaginatedResponse<InboxMappingDetailResponse>>(\n `admin/inbox-mappings${params.toString() ? `?${params.toString()}` : ''}`\n );\n }\n\n async getInboxMapping(id: number): Promise<InboxMappingDetailResponse> {\n return this.fetch<InboxMappingDetailResponse>(`admin/inbox-mappings/${id}`);\n }\n\n async updateInboxMapping(id: number, workspaceId: number): Promise<InboxMappingDetailResponse> {\n return this.fetch<InboxMappingDetailResponse>(`admin/inbox-mappings/${id}`, {\n method: 'PUT',\n body: JSON.stringify({ workspaceId }),\n });\n }\n\n async deleteAdminInboxMapping(id: number): Promise<void> {\n return this.fetch(`admin/inbox-mappings/${id}`, {\n method: 'DELETE',\n });\n }\n\n // Evaluation API\n async generateChatSummaries(options: {\n afterDate?: Date;\n onlyWithoutSummaries?: boolean;\n }): Promise<GenerateSummariesResponse> {\n return this.fetch<GenerateSummariesResponse>('admin/generate-summaries', {\n method: 'POST',\n body: JSON.stringify({\n after_date: options.afterDate\n ? options.afterDate.toISOString().split('T')[0] +\n 'T' +\n options.afterDate.toTimeString().split(' ')[0]\n : undefined,\n only_without_summaries: options.onlyWithoutSummaries ?? true,\n }),\n });\n }\n\n async executeQuery(options: { query: string; workspaceUuid?: string }): Promise<{\n columns: string[];\n rows: any[][];\n rowCount: number;\n }> {\n return this.fetch<{\n columns: string[];\n rows: any[][];\n rowCount: number;\n }>('admin/execute-query', {\n method: 'POST',\n body: JSON.stringify({\n query: options.query,\n workspace_uuid: options.workspaceUuid,\n }),\n });\n }\n\n /**\n * Resolve a Langfuse trace UI URL from a trace ID, chat ID, or message ID.\n *\n * URL-only: never fetches Langfuse payloads, Message content, or\n * tool arguments. Exactly one of ``traceId``, ``chatId``, or\n * ``messageId`` must be set; chat/message forms require a\n * workspaceUuid. See\n * docs/development/observability/llm-call-investigation.md.\n */\n async getTraceUrl(options: {\n traceId?: string;\n chatId?: number;\n messageId?: string;\n workspaceUuid?: string;\n }): Promise<{\n trace_id: string | null;\n observation_id: string | null;\n langfuse_url: string | null;\n }> {\n return this.fetch<{\n trace_id: string | null;\n observation_id: string | null;\n langfuse_url: string | null;\n }>('admin/trace/url', {\n method: 'POST',\n body: JSON.stringify({\n trace_id: options.traceId,\n chat_id: options.chatId,\n message_id: options.messageId,\n workspace_uuid: options.workspaceUuid,\n }),\n });\n }\n\n // Admin Themes API\n async listAllThemes(): Promise<ThemesListResponse> {\n return this.fetch<ThemesListResponse>('admin/themes/list');\n }\n\n // Missing Memberships API\n async getMissingMemberships(workspaceId: string): Promise<MissingMembershipItem[]> {\n return this.fetch<MissingMembershipItem[]>(\n `admin/workspaces/${workspaceId}/missing-memberships`\n );\n }\n\n async linkMissingMembership(\n workspaceId: string,\n memberId: number,\n accountId: number\n ): Promise<{ success: boolean; message: string }> {\n return this.fetch<{ success: boolean; message: string }>(\n `admin/workspaces/${workspaceId}/link-membership?member_id=${memberId}&account_id=${accountId}`,\n {\n method: 'POST',\n }\n );\n }\n\n // Bulk Phone Classification API\n async startBulkPhoneClassification(\n workspaceUuid: string,\n includeUnknown: boolean = false\n ): Promise<{\n success: boolean;\n message: string;\n job_id: string;\n workspace_uuid: string;\n include_unknown: boolean;\n }> {\n const params = new URLSearchParams();\n params.append('include_unknown', includeUnknown.toString());\n\n return this.fetch<{\n success: boolean;\n message: string;\n job_id: string;\n workspace_uuid: string;\n include_unknown: boolean;\n }>(`admin/workspaces/${workspaceUuid}/bulk-classify-phones?${params.toString()}`, {\n method: 'POST',\n });\n }\n\n // Bulk TOS Acceptance API\n async startBulkTOSAcceptance(workspaceUuid: string): Promise<{\n success: boolean;\n message: string;\n updated_count: number;\n workspace_uuid: string;\n }> {\n return this.fetch<{\n success: boolean;\n message: string;\n updated_count: number;\n workspace_uuid: string;\n }>(`admin/workspaces/${workspaceUuid}/bulk-accept-tos`, {\n method: 'POST',\n });\n }\n\n // Token Usage Backfill API\n async startTokenUsageBackfill(workspaceUuid: string): Promise<{\n success: boolean;\n message: string;\n job_id: string;\n workspace_uuid: string;\n }> {\n return this.fetch<{\n success: boolean;\n message: string;\n job_id: string;\n workspace_uuid: string;\n }>(`admin/workspaces/${workspaceUuid}/backfill-token-usage`, {\n method: 'POST',\n });\n }\n\n // ===== Admin Chat Endpoints =====\n\n async listWorkspaceChats(\n workspaceUuid: string,\n options?: AdminChatsOptions\n ): Promise<PaginatedResponse<AdminChat>> {\n const params = new URLSearchParams();\n if (options?.page) params.set('page', String(options.page));\n if (options?.pageSize) params.set('pageSize', String(options.pageSize));\n if (options?.search) params.set('search', options.search);\n if (options?.chatType) params.set('chatType', options.chatType);\n if (options?.channel) params.set('channel', options.channel);\n if (options?.archived !== undefined) params.set('archived', String(options.archived));\n const qs = params.toString();\n return this.fetch<PaginatedResponse<AdminChat>>(\n `admin/workspaces/${workspaceUuid}/chats${qs ? `?${qs}` : ''}`\n );\n }\n\n async getWorkspaceChat(\n workspaceUuid: string,\n chatId: number,\n options?: { page?: number; pageSize?: number }\n ): Promise<AdminChatDetail> {\n const params = new URLSearchParams();\n if (options?.page) params.set('page', String(options.page));\n if (options?.pageSize) params.set('pageSize', String(options.pageSize));\n const qs = params.toString();\n return this.fetch<AdminChatDetail>(\n `admin/workspaces/${workspaceUuid}/chats/${chatId}${qs ? `?${qs}` : ''}`\n );\n }\n\n // Update chat message content\n async updateChatMessage(\n workspaceUuid: string,\n chatId: number,\n messageId: string,\n content: string\n ): Promise<{\n success: boolean;\n message: string;\n messageId: string;\n chatId: number;\n workspaceUuid: string;\n }> {\n return this.fetch<{\n success: boolean;\n message: string;\n messageId: string;\n chatId: number;\n workspaceUuid: string;\n }>(`admin/workspaces/${workspaceUuid}/chats/${chatId}/messages/${messageId}`, {\n method: 'POST',\n body: JSON.stringify({ content }),\n });\n }\n\n async rateWorkspaceChatMessage(\n workspaceUuid: string,\n chatId: number,\n messageId: string,\n rating: number,\n comment?: string\n ): Promise<{ status: string; detail?: string }> {\n return this.fetch<{ status: string; detail?: string }>(\n `admin/workspaces/${workspaceUuid}/chats/${chatId}/messages/${messageId}/rate`,\n {\n method: 'POST',\n body: JSON.stringify({ rating, comment }),\n }\n );\n }\n\n // ===== Stripe Customer Management =====\n\n async getStripeCustomer(accountId: number): Promise<StripeCustomer> {\n return this.fetch<StripeCustomer>(`admin/accounts/${accountId}/stripe/customer`);\n }\n\n async createStripeCustomer(\n accountId: number,\n data: StripeCustomerCreateRequest\n ): Promise<StripeCustomer> {\n return this.fetch<StripeCustomer>(`admin/accounts/${accountId}/stripe/customer`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async updateStripeCustomer(\n accountId: number,\n data: StripeCustomerUpdateRequest\n ): Promise<StripeCustomer> {\n return this.fetch<StripeCustomer>(`admin/accounts/${accountId}/stripe/customer`, {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n // ===== Customer Management =====\n\n async createCustomerFromAccount(accountId: number): Promise<Customer> {\n return this.fetch<Customer>(`admin/accounts/${accountId}/customer`, {\n method: 'POST',\n });\n }\n\n async getCustomers(options?: {\n search?: string;\n page?: number;\n pageSize?: number;\n }): Promise<PaginatedResponse<Customer>> {\n const params = new URLSearchParams();\n if (options?.search) params.set('search', options.search);\n if (options?.page) params.set('page', String(options.page));\n if (options?.pageSize) params.set('page_size', String(options.pageSize));\n const qs = params.toString();\n return this.fetch<PaginatedResponse<Customer>>(`admin/customers${qs ? `?${qs}` : ''}`);\n }\n\n async getCustomer(customerId: number): Promise<Customer> {\n return this.fetch<Customer>(`admin/customers/${customerId}`);\n }\n\n async createCustomer(data: CreateCustomerRequest): Promise<Customer> {\n return this.fetch<Customer>('admin/customers', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async updateCustomer(customerId: number, data: UpdateCustomerRequest): Promise<Customer> {\n return this.fetch<Customer>(`admin/customers/${customerId}`, {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n async syncCustomerToStripe(customerId: number): Promise<Customer> {\n return this.fetch<Customer>(`admin/customers/${customerId}/stripe/sync`, {\n method: 'POST',\n });\n }\n\n async getCustomerAccounts(customerId: number): Promise<CustomerAccount[]> {\n return this.fetch<CustomerAccount[]>(`admin/customers/${customerId}/accounts`);\n }\n\n async linkCustomerToAccount(\n customerId: number,\n accountId: number,\n role?: string\n ): Promise<CustomerAccount> {\n return this.fetch<CustomerAccount>(`admin/customers/${customerId}/accounts`, {\n method: 'POST',\n body: JSON.stringify({ accountId, role }),\n });\n }\n\n async unlinkCustomerFromAccount(customerId: number, accountId: number): Promise<void> {\n await this.fetch<void>(`admin/customers/${customerId}/accounts/${accountId}`, {\n method: 'DELETE',\n });\n }\n\n // ===== Stripe Subscription Management =====\n\n async getStripeSubscriptions(accountId: number): Promise<Subscription[]> {\n return this.fetch<Subscription[]>(`admin/accounts/${accountId}/stripe/subscriptions`);\n }\n\n async createStripeSubscription(\n customerId: number,\n data: StripeSubscriptionCreateRequest\n ): Promise<Subscription> {\n return this.fetch<Subscription>(`admin/customers/${customerId}/stripe/subscriptions`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async createDirectSubscription(\n customerId: number,\n data: DirectSubscriptionCreateRequest\n ): Promise<Subscription> {\n return this.fetch<Subscription>(`admin/customers/${customerId}/direct/subscriptions`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async updateStripeSubscription(\n accountId: number,\n subscriptionId: string,\n data: StripeSubscriptionUpdateRequest\n ): Promise<Subscription> {\n return this.fetch<Subscription>(\n `admin/accounts/${accountId}/stripe/subscriptions/${subscriptionId}`,\n {\n method: 'PUT',\n body: JSON.stringify(data),\n }\n );\n }\n\n async cancelStripeSubscription(\n accountId: number,\n subscriptionId: string\n ): Promise<{ message: string; status: string }> {\n return this.fetch<{ message: string; status: string }>(\n `admin/accounts/${accountId}/stripe/subscriptions/${subscriptionId}`,\n {\n method: 'DELETE',\n }\n );\n }\n\n async provisionWorkspaceForSubscription(\n accountId: number,\n subscriptionId: string\n ): Promise<AdminWorkspace> {\n return this.fetch<AdminWorkspace>(\n `admin/accounts/${accountId}/stripe/subscriptions/${subscriptionId}/provision`,\n {\n method: 'POST',\n }\n );\n }\n\n async associateWorkspaceWithSubscription(\n accountId: number,\n subscriptionId: string,\n workspaceId: string | number\n ): Promise<Subscription> {\n return this.fetch<Subscription>(\n `admin/accounts/${accountId}/stripe/subscriptions/${subscriptionId}/associate?workspace_id=${workspaceId}`,\n {\n method: 'POST',\n }\n );\n }\n\n async createSubscriptionPaymentLink(\n accountId: number,\n subscriptionId: string\n ): Promise<{\n needsPayment: boolean;\n paymentUrl?: string;\n amountDue?: number;\n currency?: string;\n status: string;\n invoiceId?: string;\n invoiceStatus?: string;\n dueDate?: number;\n message?: string;\n }> {\n return this.fetch<{\n needsPayment: boolean;\n paymentUrl?: string;\n amountDue?: number;\n currency?: string;\n status: string;\n invoiceId?: string;\n invoiceStatus?: string;\n dueDate?: number;\n message?: string;\n }>(`admin/accounts/${accountId}/stripe/subscriptions/${subscriptionId}/payment-link`, {\n method: 'POST',\n });\n }\n\n // ===== Stripe Payment Methods Management =====\n\n async createSetupIntent(accountId: number): Promise<{\n clientSecret: string;\n setupIntentId: string;\n status: string;\n }> {\n return this.fetch<{\n clientSecret: string;\n setupIntentId: string;\n status: string;\n }>(`admin/accounts/${accountId}/stripe/setup-intent`, {\n method: 'POST',\n });\n }\n\n async getStripePaymentMethods(accountId: number): Promise<StripePaymentMethod[]> {\n return this.fetch<StripePaymentMethod[]>(\n `admin/accounts/${accountId}/stripe/payment-methods`\n );\n }\n\n async attachStripePaymentMethod(\n accountId: number,\n paymentMethodId: string,\n setAsDefault: boolean = false\n ): Promise<{\n success: boolean;\n message: string;\n paymentMethodId: string;\n type: string;\n }> {\n return this.fetch<{\n success: boolean;\n message: string;\n paymentMethodId: string;\n type: string;\n }>(`admin/accounts/${accountId}/stripe/payment-methods/${paymentMethodId}/attach`, {\n method: 'POST',\n body: JSON.stringify({ setAsDefault }),\n });\n }\n\n async detachStripePaymentMethod(\n accountId: number,\n paymentMethodId: string\n ): Promise<{ success: string; message: string }> {\n return this.fetch<{ success: string; message: string }>(\n `admin/accounts/${accountId}/stripe/payment-methods/${paymentMethodId}`,\n {\n method: 'DELETE',\n }\n );\n }\n\n async setDefaultStripePaymentMethod(\n accountId: number,\n paymentMethodId: string\n ): Promise<{ success: string; message: string }> {\n return this.fetch<{ success: string; message: string }>(\n `admin/accounts/${accountId}/stripe/payment-methods/${paymentMethodId}/set-default`,\n {\n method: 'PUT',\n }\n );\n }\n\n // ===== Convert Direct Subscription to Stripe =====\n\n async convertSubscriptionToStripe(\n customerId: number,\n subscriptionId: number\n ): Promise<Subscription> {\n return this.fetch<Subscription>(\n `admin/customers/${customerId}/subscriptions/${subscriptionId}/convert-to-stripe`,\n { method: 'POST' }\n );\n }\n\n // ===== Customer-Level Stripe Payment Methods =====\n\n async createCustomerSetupIntent(customerId: number): Promise<{\n clientSecret: string;\n setupIntentId: string;\n status: string;\n }> {\n return this.fetch<{\n clientSecret: string;\n setupIntentId: string;\n status: string;\n }>(`admin/customers/${customerId}/stripe/setup-intent`, {\n method: 'POST',\n });\n }\n\n async getCustomerPaymentMethods(customerId: number): Promise<StripePaymentMethod[]> {\n return this.fetch<StripePaymentMethod[]>(\n `admin/customers/${customerId}/stripe/payment-methods`\n );\n }\n\n async attachCustomerPaymentMethod(\n customerId: number,\n paymentMethodId: string,\n setAsDefault: boolean = false\n ): Promise<{\n success: boolean;\n message: string;\n paymentMethodId: string;\n type: string;\n }> {\n return this.fetch<{\n success: boolean;\n message: string;\n paymentMethodId: string;\n type: string;\n }>(`admin/customers/${customerId}/stripe/payment-methods/${paymentMethodId}/attach`, {\n method: 'POST',\n body: JSON.stringify({ setAsDefault }),\n });\n }\n\n async detachCustomerPaymentMethod(\n customerId: number,\n paymentMethodId: string\n ): Promise<{ success: string; message: string }> {\n return this.fetch<{ success: string; message: string }>(\n `admin/customers/${customerId}/stripe/payment-methods/${paymentMethodId}`,\n {\n method: 'DELETE',\n }\n );\n }\n\n async setDefaultCustomerPaymentMethod(\n customerId: number,\n paymentMethodId: string\n ): Promise<{ success: string; message: string }> {\n return this.fetch<{ success: string; message: string }>(\n `admin/customers/${customerId}/stripe/payment-methods/${paymentMethodId}/set-default`,\n {\n method: 'PUT',\n }\n );\n }\n\n // ===== Workspace Organization Migration =====\n\n async previewWorkspaceOrganizationChange(\n workspaceUuid: string,\n targetOrganizationId: number,\n newCreatorId: number\n ): Promise<{\n targetOrganization: { id: number; name: string };\n newCreator: { id: number; name: string; email: string };\n currentOrganization: { id: number | null; name: string | null };\n impact: {\n accountsToMove: number;\n accountsToDuplicate: number;\n accountsToRemap: number;\n totalMembers: number;\n };\n details: {\n movableAccounts: Array<{\n id: number;\n uuid: string;\n name: string;\n email: string | null;\n phone: string | null;\n }>;\n duplicateAccounts: Array<{\n id: number;\n uuid: string;\n name: string;\n email: string | null;\n phone: string | null;\n }>;\n remappableAccounts: Array<{\n currentAccount: {\n id: number;\n uuid: string;\n name: string;\n email: string | null;\n phone: string | null;\n };\n targetAccount: {\n id: number;\n uuid: string;\n name: string;\n email: string | null;\n phone: string | null;\n };\n }>;\n };\n }> {\n return this.fetch<{\n targetOrganization: { id: number; name: string };\n newCreator: { id: number; name: string; email: string };\n currentOrganization: { id: number | null; name: string | null };\n impact: {\n accountsToMove: number;\n accountsToDuplicate: number;\n accountsToRemap: number;\n totalMembers: number;\n };\n details: {\n movableAccounts: Array<{\n id: number;\n uuid: string;\n name: string;\n email: string | null;\n phone: string | null;\n }>;\n duplicateAccounts: Array<{\n id: number;\n uuid: string;\n name: string;\n email: string | null;\n phone: string | null;\n }>;\n remappableAccounts: Array<{\n currentAccount: {\n id: number;\n uuid: string;\n name: string;\n email: string | null;\n phone: string | null;\n };\n targetAccount: {\n id: number;\n uuid: string;\n name: string;\n email: string | null;\n phone: string | null;\n };\n }>;\n };\n }>(`admin/workspaces/${workspaceUuid}/change-org/preview`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n targetOrganizationId,\n newCreatorId,\n }),\n });\n }\n\n async changeWorkspaceOrganization(\n workspaceUuid: string,\n targetOrganizationId: number,\n newCreatorId: number\n ): Promise<{\n success: boolean;\n workspace: {\n uuid: string;\n name: string;\n organizationId: number;\n creatorId: number;\n };\n migration: {\n accountsMoved: number;\n accountsCreated: number;\n accountsRemapped: number;\n };\n }> {\n return this.fetch<{\n success: boolean;\n workspace: {\n uuid: string;\n name: string;\n organizationId: number;\n creatorId: number;\n };\n migration: {\n accountsMoved: number;\n accountsCreated: number;\n accountsRemapped: number;\n };\n }>(`admin/workspaces/${workspaceUuid}/change-org`, {\n method: 'POST',\n body: JSON.stringify({\n targetOrganizationId,\n newCreatorId,\n }),\n });\n }\n\n // ===== Stripe Invoice Management =====\n\n async createStripeInvoice(\n accountId: number,\n data: {\n customer: string;\n description?: string;\n collectionMethod: 'charge_automatically' | 'send_invoice';\n daysUntilDue?: number;\n autoAdvance?: boolean;\n metadata?: Record<string, string>;\n }\n ): Promise<{\n id: string;\n number: string;\n status: string;\n collectionMethod: string;\n amountDue: number;\n amountPaid: number;\n amountRemaining: number;\n currency: string;\n created: number;\n dueDate: number | null;\n paid: boolean;\n hostedInvoiceUrl: string | null;\n invoicePdf: string | null;\n customerEmail: string | null;\n description: string | null;\n }> {\n return this.fetch<{\n id: string;\n number: string;\n status: string;\n collectionMethod: string;\n amountDue: number;\n amountPaid: number;\n amountRemaining: number;\n currency: string;\n created: number;\n dueDate: number | null;\n paid: boolean;\n hostedInvoiceUrl: string | null;\n invoicePdf: string | null;\n customerEmail: string | null;\n description: string | null;\n }>(`admin/accounts/${accountId}/stripe/invoices`, {\n method: 'POST',\n body: JSON.stringify({\n customer: data.customer,\n description: data.description,\n collection_method: data.collectionMethod,\n days_until_due: data.daysUntilDue,\n auto_advance: data.autoAdvance,\n metadata: data.metadata,\n }),\n });\n }\n\n async getStripeInvoices(\n accountId: number,\n options?: { limit?: number; startingAfter?: string }\n ): Promise<\n Array<{\n id: string;\n number: string;\n status: string;\n collectionMethod: string;\n amountDue: number;\n amountPaid: number;\n amountRemaining: number;\n currency: string;\n created: number;\n dueDate: number | null;\n paid: boolean;\n hostedInvoiceUrl: string | null;\n invoicePdf: string | null;\n description: string | null;\n periodStart: number | null;\n periodEnd: number | null;\n }>\n > {\n const params = new URLSearchParams();\n if (options?.limit) params.append('limit', options.limit.toString());\n if (options?.startingAfter) params.append('starting_after', options.startingAfter);\n\n return this.fetch<\n Array<{\n id: string;\n number: string;\n status: string;\n collectionMethod: string;\n amountDue: number;\n amountPaid: number;\n amountRemaining: number;\n currency: string;\n created: number;\n dueDate: number | null;\n paid: boolean;\n hostedInvoiceUrl: string | null;\n invoicePdf: string | null;\n description: string | null;\n periodStart: number | null;\n periodEnd: number | null;\n }>\n >(`admin/accounts/${accountId}/stripe/invoices?${params.toString()}`);\n }\n\n async getStripeUpcomingInvoice(\n accountId: number,\n subscriptionId?: string\n ): Promise<{\n amountDue: number;\n amountPaid: number;\n amountRemaining: number;\n currency: string;\n periodStart: number;\n periodEnd: number;\n subtotal: number;\n tax: number;\n total: number;\n lineItems: Array<{\n id: string;\n description: string | null;\n amount: number;\n currency: string;\n quantity: number;\n unitAmount: number;\n productName: string | null;\n productDescription: string | null;\n period: {\n start: number;\n end: number;\n };\n }>;\n customer: string;\n subscription: string | null;\n }> {\n const params = new URLSearchParams();\n if (subscriptionId) params.append('subscription_id', subscriptionId);\n\n return this.fetch<{\n amountDue: number;\n amountPaid: number;\n amountRemaining: number;\n currency: string;\n periodStart: number;\n periodEnd: number;\n subtotal: number;\n tax: number;\n total: number;\n lineItems: Array<{\n id: string;\n description: string | null;\n amount: number;\n currency: string;\n quantity: number;\n unitAmount: number;\n productName: string | null;\n productDescription: string | null;\n period: {\n start: number;\n end: number;\n };\n }>;\n customer: string;\n subscription: string | null;\n }>(`admin/accounts/${accountId}/stripe/upcoming-invoice?${params.toString()}`);\n }\n\n // Billing Dashboard API\n async getWorkspaceUsageDashboard(workspaceUuid: string): Promise<UsageDashboardResponse> {\n return this.fetch<UsageDashboardResponse>(\n `admin/workspaces/${workspaceUuid}/usage-dashboard`\n );\n }\n\n // Product Stripe Sync API\n async compareProductsWithStripe(workspaceUuid?: string): Promise<CompareWithStripeResponse> {\n const params = workspaceUuid ? `?workspace_uuid=${encodeURIComponent(workspaceUuid)}` : '';\n return this.fetch<CompareWithStripeResponse>(`admin/products/compare-stripe${params}`);\n }\n\n async syncProductToStripe(\n productId: number,\n request?: SyncProductToStripeRequest\n ): Promise<SyncProductToStripeResponse> {\n return this.fetch<SyncProductToStripeResponse>(`admin/products/${productId}/sync-stripe`, {\n method: 'POST',\n body: JSON.stringify({ ...request, productId }),\n });\n }\n\n // Search Stripe products\n async searchStripeProducts(\n query: string,\n limit: number = 10\n ): Promise<\n Array<{\n id: string;\n name: string;\n description: string | null;\n active: boolean;\n created: number;\n metadata: Record<string, string>;\n }>\n > {\n const params = new URLSearchParams({ query, limit: limit.toString() });\n return this.fetch<\n Array<{\n id: string;\n name: string;\n description: string | null;\n active: boolean;\n created: number;\n metadata: Record<string, string>;\n }>\n >(`admin/products/stripe/search?${params.toString()}`);\n }\n\n // ===== Subscriptions API =====\n\n async getSubscriptionsAsAdmin(options?: {\n productId?: number;\n productType?: string;\n customerId?: number;\n organizationId?: number;\n accountId?: number;\n isDirect?: boolean;\n status?: string;\n page?: number;\n pageSize?: number;\n }): Promise<PaginatedSubscriptionsResponse> {\n const params = new URLSearchParams();\n if (options?.productId) params.append('product_id', options.productId.toString());\n if (options?.productType) params.append('product_type', options.productType);\n if (options?.customerId) params.append('customer_id', options.customerId.toString());\n if (options?.organizationId)\n params.append('organization_id', options.organizationId.toString());\n if (options?.accountId) params.append('account_id', options.accountId.toString());\n if (options?.isDirect !== undefined) params.append('is_direct', options.isDirect.toString());\n if (options?.status) params.append('status', options.status);\n if (options?.page) params.append('page', options.page.toString());\n if (options?.pageSize) params.append('page_size', options.pageSize.toString());\n const queryString = params.toString();\n return this.fetch<PaginatedSubscriptionsResponse>(\n `admin/subscriptions${queryString ? `?${queryString}` : ''}`\n );\n }\n\n async getSubscriptionAsAdmin(subscriptionId: number): Promise<Subscription> {\n return this.fetch<Subscription>(`admin/subscriptions/${subscriptionId}`);\n }\n\n async updateSubscriptionStatusAsAdmin(\n subscriptionId: number,\n subscriptionStatus: string\n ): Promise<Subscription> {\n return this.fetch<Subscription>(`admin/subscriptions/${subscriptionId}`, {\n method: 'PUT',\n body: JSON.stringify({ subscription_status: subscriptionStatus }),\n });\n }\n\n async updateSubscriptionCreditSettingsAsAdmin(\n subscriptionId: number,\n settings: {\n extra_usage_enabled?: boolean;\n reload_amount_cents?: number | null;\n reload_threshold_cents?: number | null;\n monthly_reload_limit_cents?: number | null;\n }\n ): Promise<Subscription> {\n return this.fetch<Subscription>(`admin/subscriptions/${subscriptionId}`, {\n method: 'PUT',\n body: JSON.stringify(settings),\n });\n }\n\n /** Grant credits to a subscription (superuser only). */\n async grantCreditsAsAdmin(\n subscriptionId: number,\n creditUnits: number,\n grantType: string,\n reason: string\n ): Promise<{\n success: boolean;\n grantId: number;\n creditUnits: number;\n grantedBy: string;\n reason: string;\n }> {\n return this.fetch(`admin/subscriptions/${subscriptionId}/grant-credits`, {\n method: 'POST',\n body: JSON.stringify({ credit_units: creditUnits, grant_type: grantType, reason }),\n });\n }\n\n /** List credit grants for a subscription (superuser only). */\n async listCreditGrantsAsAdmin(subscriptionId: number): Promise<\n {\n id: number;\n uuid: string;\n grantType: string;\n creditUnits: number;\n remainingUnits: number;\n amountCents: number;\n status: string;\n effectiveAt: string | null;\n expiresAt: string | null;\n createdAt: string | null;\n createdBy: string | null;\n reason: string | null;\n }[]\n > {\n return this.fetch(`admin/subscriptions/${subscriptionId}/credit-grants`);\n }\n\n // ===== Usage API =====\n\n async getUsageReport(request: UsageReportRequest): Promise<UsageReport> {\n return this.fetch<UsageReport>('admin/usage', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n }\n\n // Voice Metrics API\n async getVoiceMetrics(options?: {\n hours?: number;\n period?: number;\n workspace_uuid?: string;\n organization_id?: number;\n engine?: string;\n channel?: string;\n }): Promise<VoiceMetricsResponse> {\n const params = new URLSearchParams();\n if (options?.hours) params.append('hours', options.hours.toString());\n if (options?.period) params.append('period', options.period.toString());\n if (options?.workspace_uuid) params.append('workspace_uuid', options.workspace_uuid);\n if (options?.organization_id != null)\n params.append('organization_id', options.organization_id.toString());\n if (options?.engine) params.append('engine', options.engine);\n if (options?.channel) params.append('channel', options.channel);\n const qs = params.toString();\n return this.fetch<VoiceMetricsResponse>(`admin/voice-metrics${qs ? `?${qs}` : ''}`);\n }\n\n // Health Dashboard API\n async getHealthMetrics(request: HealthMetricsRequest): Promise<HealthMetricsResponse> {\n return this.fetch<HealthMetricsResponse>('admin/health/metrics', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n }\n\n async getHealthDetail(\n workspaceUuid: string,\n request: HealthDetailRequest\n ): Promise<WorkspaceHealthDetail> {\n return this.fetch<WorkspaceHealthDetail>(`admin/health/detail/${workspaceUuid}`, {\n method: 'POST',\n body: JSON.stringify(request),\n });\n }\n\n // ===== Reseller Management =====\n\n async getResellers(options?: {\n search?: string;\n page?: number;\n pageSize?: number;\n }): Promise<PaginatedResponse<Reseller>> {\n const params = new URLSearchParams();\n if (options?.search) params.set('search', options.search);\n if (options?.page) params.set('page', String(options.page));\n if (options?.pageSize) params.set('page_size', String(options.pageSize));\n const qs = params.toString();\n return this.fetch<PaginatedResponse<Reseller>>(`admin/resellers${qs ? `?${qs}` : ''}`);\n }\n\n async getReseller(resellerId: number): Promise<Reseller> {\n return this.fetch<Reseller>(`admin/resellers/${resellerId}`);\n }\n\n async createReseller(data: CreateResellerRequest): Promise<Reseller> {\n return this.fetch<Reseller>('admin/resellers', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async updateReseller(resellerId: number, data: UpdateResellerRequest): Promise<Reseller> {\n return this.fetch<Reseller>(`admin/resellers/${resellerId}`, {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n async getResellerAccounts(resellerId: number): Promise<ResellerAccount[]> {\n return this.fetch<ResellerAccount[]>(`admin/resellers/${resellerId}/accounts`);\n }\n\n async linkResellerToAccount(\n resellerId: number,\n data: LinkResellerAccountRequest\n ): Promise<ResellerAccount> {\n return this.fetch<ResellerAccount>(`admin/resellers/${resellerId}/accounts`, {\n method: 'POST',\n body: JSON.stringify({ account_id: data.accountId, role: data.role }),\n });\n }\n\n async unlinkResellerFromAccount(resellerId: number, accountId: number): Promise<void> {\n await this.fetch<void>(`admin/resellers/${resellerId}/accounts/${accountId}`, {\n method: 'DELETE',\n });\n }\n\n // ===== Invoice Management =====\n\n async generateInvoice(data: {\n subscriptionId: number;\n periodStart: string;\n periodEnd: string;\n regenerate?: boolean;\n }): Promise<Invoice> {\n return this.fetch<Invoice>('admin/invoices/generate', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async getInvoices(\n subscriptionId?: number,\n pageOpts?: { page?: number; pageSize?: number }\n ): Promise<PaginatedResponse<Invoice>> {\n const params = new URLSearchParams();\n if (subscriptionId !== undefined) params.set('subscription_id', String(subscriptionId));\n if (pageOpts?.page !== undefined) params.set('page', String(pageOpts.page));\n if (pageOpts?.pageSize !== undefined) params.set('pageSize', String(pageOpts.pageSize));\n const qs = params.toString();\n return this.fetch<PaginatedResponse<Invoice>>(`admin/invoices${qs ? `?${qs}` : ''}`);\n }\n\n async getBillingPeriods(subscriptionId: number): Promise<BillingPeriod[]> {\n return this.fetch<BillingPeriod[]>(\n `admin/invoices/periods?subscription_id=${subscriptionId}`\n );\n }\n\n async getInvoiceDownloadUrl(\n invoiceId: number\n ): Promise<{ downloadUrl: string; invoiceNumber: string }> {\n return this.fetch<{ downloadUrl: string; invoiceNumber: string }>(\n `admin/invoices/${invoiceId}/download`\n );\n }\n\n async getReceiptDownloadUrl(\n invoiceId: number\n ): Promise<{ downloadUrl: string; invoiceNumber: string }> {\n return this.fetch<{ downloadUrl: string; invoiceNumber: string }>(\n `admin/invoices/${invoiceId}/receipt`\n );\n }\n\n async recordInvoicePayment(invoiceId: number, data: RecordPaymentRequest): Promise<Invoice> {\n return this.fetch<Invoice>(`admin/invoices/${invoiceId}/record-payment`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n // ===== Admin Temporal Inspection (PHI-safe, read-only) =====\n\n /**\n * Server-enforced bounds for admin Temporal queries (lookback, thresholds,\n * page sizes, history event cap). Superuser only.\n */\n async getTemporalAdminConfig(): Promise<TemporalAdminConfig> {\n return this.fetch<TemporalAdminConfig>('admin/temporal/config');\n }\n\n /**\n * List recent Temporal workflows in FAILED, TIMED_OUT, or TERMINATED\n * status. Returns only PHI-safe operational metadata. Superuser only.\n *\n * Pass `options.status` to filter to a single status and enable\n * deep pagination via `nextPageToken`. Merged mode (no status) returns\n * the first page only and always emits `nextPageToken: null`.\n */\n async listFailedTemporalWorkflows(\n options: AdminTemporalFailedQuery = {}\n ): Promise<FailedWorkflowsResponse> {\n const params = new URLSearchParams();\n if (options.lookbackHours !== undefined)\n params.set('lookback_hours', String(options.lookbackHours));\n if (options.pageSize !== undefined) params.set('page_size', String(options.pageSize));\n if (options.status) params.set('status', String(options.status));\n if (options.nextPageToken) params.set('next_page_token', options.nextPageToken);\n appendTemporalWorkspaceParams(params, options);\n const qs = params.toString();\n return this.fetch<FailedWorkflowsResponse>(\n `admin/temporal/workflows/failed${qs ? `?${qs}` : ''}`\n );\n }\n\n /**\n * List open Temporal workflows older than the stuck threshold.\n * Superuser only.\n */\n async listStuckTemporalWorkflows(\n options: AdminTemporalStuckQuery = {}\n ): Promise<StuckWorkflowsResponse> {\n const params = new URLSearchParams();\n if (options.thresholdMinutes !== undefined)\n params.set('threshold_minutes', String(options.thresholdMinutes));\n if (options.pageSize !== undefined) params.set('page_size', String(options.pageSize));\n if (options.nextPageToken) params.set('next_page_token', options.nextPageToken);\n appendTemporalWorkspaceParams(params, options);\n const qs = params.toString();\n return this.fetch<StuckWorkflowsResponse>(\n `admin/temporal/workflows/stuck${qs ? `?${qs}` : ''}`\n );\n }\n\n /**\n * Return grouped counts for recent Temporal executions. Superuser only.\n */\n async getTemporalSummary(\n options: AdminTemporalSummaryQuery = {}\n ): Promise<TemporalSummaryResponse> {\n const params = new URLSearchParams();\n if (options.lookbackHours !== undefined)\n params.set('lookback_hours', String(options.lookbackHours));\n appendTemporalWorkspaceParams(params, options);\n const qs = params.toString();\n return this.fetch<TemporalSummaryResponse>(\n `admin/temporal/workflows/summary${qs ? `?${qs}` : ''}`\n );\n }\n\n /**\n * Fetch metadata + bounded sanitized history summary for one Temporal\n * workflow. Superuser only. Does not return raw events or payloads.\n */\n async getTemporalWorkflowDetail(\n workflowId: string,\n options: AdminTemporalDetailQuery = {}\n ): Promise<WorkflowDetailResponse> {\n const params = new URLSearchParams();\n if (options.runId) params.set('run_id', options.runId);\n appendTemporalWorkspaceParams(params, options);\n const qs = params.toString();\n const encoded = encodeURIComponent(workflowId);\n return this.fetch<WorkflowDetailResponse>(\n `admin/temporal/workflows/${encoded}${qs ? `?${qs}` : ''}`\n );\n }\n\n // ── Customer activity events (cross-workspace operator feed) ──────────────\n async listCustomerActivityEvents(\n params: AdminActivityEventListParams = {}\n ): Promise<AdminActivityEventListResponse> {\n const qs = new URLSearchParams();\n if (params.page) qs.set('page', String(params.page));\n if (params.pageSize) qs.set('pageSize', String(params.pageSize));\n if (params.status) qs.set('status', params.status);\n if (params.subjectType) qs.set('subjectType', params.subjectType);\n if (params.source) qs.set('source', params.source);\n if (params.severity) qs.set('severity', params.severity);\n if (params.disposition) qs.set('disposition', params.disposition);\n if (params.workspaceId !== undefined) qs.set('workspaceId', String(params.workspaceId));\n if (params.organizationId !== undefined)\n qs.set('organizationId', String(params.organizationId));\n if (params.accountId !== undefined) qs.set('accountId', String(params.accountId));\n const query = qs.toString();\n return this.fetch<AdminActivityEventListResponse>(\n `admin/customer-activity${query ? `?${query}` : ''}`\n );\n }\n\n async getCustomerActivityEvent(uuid: string): Promise<AdminActivityEvent> {\n return this.fetch<AdminActivityEvent>(`admin/customer-activity/${uuid}`);\n }\n\n async setCustomerActivityEventDisposition(\n uuid: string,\n data: { disposition: string; status?: string }\n ): Promise<AdminActivityEvent> {\n return this.fetch<AdminActivityEvent>(`admin/customer-activity/${uuid}/disposition`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async setCustomerActivityEventStatus(\n uuid: string,\n data: { status: string }\n ): Promise<AdminActivityEvent> {\n return this.fetch<AdminActivityEvent>(`admin/customer-activity/${uuid}/status`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n async reclassifyCustomerActivityEvent(uuid: string): Promise<AdminActivityEvent> {\n return this.fetch<AdminActivityEvent>(`admin/customer-activity/${uuid}/reclassify`, {\n method: 'POST',\n });\n }\n}\n\nexport interface AdminActivityEvent {\n id: number;\n uuid: string;\n accountId?: number | null;\n organizationId?: number | null;\n workspaceId?: number | null;\n workspaceUuid?: string | null;\n subjectType: string;\n subjectRef: string;\n eventType: string;\n title?: string | null;\n labels: string[];\n severity?: string | null;\n confidence?: number | null;\n score?: number | null;\n source: string;\n dedupeKey?: string | null;\n detectorName?: string | null;\n detectorVersion?: string | null;\n modelId?: string | null;\n promptVersion?: string | null;\n status: string;\n disposition?: string | null;\n supportRequestId?: number | null;\n resourceId?: number | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface AdminActivityEventListParams {\n page?: number;\n pageSize?: number;\n status?: string;\n subjectType?: string;\n source?: string;\n severity?: string;\n disposition?: string;\n workspaceId?: number;\n organizationId?: number;\n accountId?: number;\n}\n\nexport interface AdminActivityEventListResponse {\n items: AdminActivityEvent[];\n total: number;\n page: number;\n pageSize: number;\n totalPages: number;\n}\n\n/**\n * Append the workspace filter params for admin Temporal endpoints.\n *\n * The server accepts a repeated `workspace_uuid` query parameter. For\n * backward compatibility with callers (including `gr admin temporal`)\n * that still pass a single `workspaceUuid`, we normalize both inputs\n * into the same repeated-parameter wire shape: a single value is\n * appended once; explicit `workspaceUuids` entries are appended in\n * order. Duplicates and blanks are dropped client-side so the final\n * URL stays compact.\n */\nfunction appendTemporalWorkspaceParams(\n params: URLSearchParams,\n options: {\n workspaceUuid?: string;\n workspaceUuids?: string[];\n }\n): void {\n const seen = new Set<string>();\n const push = (raw: string | undefined) => {\n if (!raw) return;\n const trimmed = raw.trim();\n if (!trimmed || seen.has(trimmed)) return;\n seen.add(trimmed);\n params.append('workspace_uuid', trimmed);\n };\n if (options.workspaceUuids) {\n for (const value of options.workspaceUuids) push(value);\n }\n push(options.workspaceUuid);\n}\n","import { GravityRailClient } from '@gravity-rail/sdk';\nimport { AdminApi } from '../api/admin';\nimport { AdminBindings, bindAdminMethods } from './bindings/admin';\n\n/**\n * ApiClient extends GravityRailClient with admin/superuser methods.\n *\n * This is the full-featured client used internally. For the public SDK,\n * use {@link GravityRailClient} from @gravity-rail/sdk which excludes\n * admin functionality.\n */\nexport class ApiClient extends GravityRailClient implements AdminBindings {\n // Admin API\n listSupportRequestsAsAdmin!: AdminBindings['listSupportRequestsAsAdmin'];\n getSupportRequestAsAdmin!: AdminBindings['getSupportRequestAsAdmin'];\n commentOnSupportRequestAsAdmin!: AdminBindings['commentOnSupportRequestAsAdmin'];\n noteOnSupportRequestAsAdmin!: AdminBindings['noteOnSupportRequestAsAdmin'];\n updateSupportRequestStatusAsAdmin!: AdminBindings['updateSupportRequestStatusAsAdmin'];\n updateSupportRequestAttributesAsAdmin!: AdminBindings['updateSupportRequestAttributesAsAdmin'];\n createSupportRequestLinearIssueAsAdmin!: AdminBindings['createSupportRequestLinearIssueAsAdmin'];\n createOutboundSupportRequestAsAdmin!: AdminBindings['createOutboundSupportRequestAsAdmin'];\n attachSupportRequestResourceAsAdmin!: AdminBindings['attachSupportRequestResourceAsAdmin'];\n revokeSupportRequestResourceAsAdmin!: AdminBindings['revokeSupportRequestResourceAsAdmin'];\n listCustomerActivityEvents!: AdminBindings['listCustomerActivityEvents'];\n getCustomerActivityEvent!: AdminBindings['getCustomerActivityEvent'];\n setCustomerActivityEventDisposition!: AdminBindings['setCustomerActivityEventDisposition'];\n setCustomerActivityEventStatus!: AdminBindings['setCustomerActivityEventStatus'];\n reclassifyCustomerActivityEvent!: AdminBindings['reclassifyCustomerActivityEvent'];\n getAccounts!: AdminBindings['getAccounts'];\n getAccountDetails!: AdminBindings['getAccountDetails'];\n getAccountByUuid!: AdminBindings['getAccountByUuid'];\n getAccountMemberships!: AdminBindings['getAccountMemberships'];\n getAccountOrgMemberships!: AdminBindings['getAccountOrgMemberships'];\n createAccountOrgMembership!: AdminBindings['createAccountOrgMembership'];\n deleteAccountOrgMembership!: AdminBindings['deleteAccountOrgMembership'];\n getAccountMembership!: AdminBindings['getAccountMembership'];\n updateAccountMembership!: AdminBindings['updateAccountMembership'];\n createAccountMembership!: AdminBindings['createAccountMembership'];\n deleteAccountMembership!: AdminBindings['deleteAccountMembership'];\n updateAccountAsAdmin!: AdminBindings['updateAccountAsAdmin'];\n createAccountAsAdmin!: AdminBindings['createAccountAsAdmin'];\n deleteAccountAsAdmin!: AdminBindings['deleteAccountAsAdmin'];\n lookupAccount!: AdminBindings['lookupAccount'];\n exportAccountData!: AdminBindings['exportAccountData'];\n requestAccountDeletion!: AdminBindings['requestAccountDeletion'];\n cancelAccountDeletion!: AdminBindings['cancelAccountDeletion'];\n getOrganizations!: AdminBindings['getOrganizations'];\n getOrganization!: AdminBindings['getOrganization'];\n getOrganizationAsAdmin!: AdminBindings['getOrganizationAsAdmin'];\n getOrganizationMembersAsAdmin!: AdminBindings['getOrganizationMembersAsAdmin'];\n createOrganization!: AdminBindings['createOrganization'];\n updateOrganization!: AdminBindings['updateOrganization'];\n deleteOrganization!: AdminBindings['deleteOrganization'];\n joinOrganization!: AdminBindings['joinOrganization'];\n leaveOrganization!: AdminBindings['leaveOrganization'];\n generateLogoUploadUrl!: AdminBindings['generateLogoUploadUrl'];\n importProducts!: AdminBindings['importProducts'];\n createProductAsAdmin!: AdminBindings['createProductAsAdmin'];\n getProductsAsAdmin!: AdminBindings['getProductsAsAdmin'];\n getProductAsAdmin!: AdminBindings['getProductAsAdmin'];\n updateProductAsAdmin!: AdminBindings['updateProductAsAdmin'];\n deleteProductAsAdmin!: AdminBindings['deleteProductAsAdmin'];\n getWorkspacesAsAdmin!: AdminBindings['getWorkspacesAsAdmin'];\n getWorkspaceAsAdmin!: AdminBindings['getWorkspaceAsAdmin'];\n getWorkspaceByNumericIdAsAdmin!: AdminBindings['getWorkspaceByNumericIdAsAdmin'];\n createWorkspaceAsAdmin!: AdminBindings['createWorkspaceAsAdmin'];\n updateWorkspaceAsAdmin!: AdminBindings['updateWorkspaceAsAdmin'];\n deleteWorkspaceAsAdmin!: AdminBindings['deleteWorkspaceAsAdmin'];\n createSchemaAsAdmin!: AdminBindings['createSchemaAsAdmin'];\n migrateSchemaAsAdmin!: AdminBindings['migrateSchemaAsAdmin'];\n provisionWorkspaceAsAdmin!: AdminBindings['provisionWorkspaceAsAdmin'];\n refreshProvisionStatusAsAdmin!: AdminBindings['refreshProvisionStatusAsAdmin'];\n enableMaintenanceMode!: AdminBindings['enableMaintenanceMode'];\n disableMaintenanceMode!: AdminBindings['disableMaintenanceMode'];\n getWorkspaceHealth!: AdminBindings['getWorkspaceHealth'];\n provisionPlanFeatures!: AdminBindings['provisionPlanFeatures'];\n changeWorkspaceProduct!: AdminBindings['changeWorkspaceProduct'];\n validateWorkflowAccessAsAdmin!: AdminBindings['validateWorkflowAccessAsAdmin'];\n mergeMembers!: AdminBindings['mergeMembers'];\n getAdminWorkspaceMember!: AdminBindings['getAdminWorkspaceMember'];\n createAdminWorkspaceMember!: AdminBindings['createAdminWorkspaceMember'];\n updateAdminWorkspaceMember!: AdminBindings['updateAdminWorkspaceMember'];\n unarchiveAdminWorkspaceMember!: AdminBindings['unarchiveAdminWorkspaceMember'];\n getAdminWorkspaceMemberRoles!: AdminBindings['getAdminWorkspaceMemberRoles'];\n getMissingMemberships!: AdminBindings['getMissingMemberships'];\n linkMissingMembership!: AdminBindings['linkMissingMembership'];\n getUnmappedPhoneNumbers!: AdminBindings['getUnmappedPhoneNumbers'];\n getWorkspaceUnmappedPhoneNumbers!: AdminBindings['getWorkspaceUnmappedPhoneNumbers'];\n getWorkspacePhoneNumbersAsAdmin!: AdminBindings['getWorkspacePhoneNumbersAsAdmin'];\n getProviderPhoneNumbers!: AdminBindings['getProviderPhoneNumbers'];\n getProviderPhoneNumber!: AdminBindings['getProviderPhoneNumber'];\n updateProviderPhoneNumber!: AdminBindings['updateProviderPhoneNumber'];\n mapMainAccountPhone!: AdminBindings['mapMainAccountPhone'];\n unmapPhoneNumber!: AdminBindings['unmapPhoneNumber'];\n searchAvailablePhoneNumbersAsAdmin!: AdminBindings['searchAvailablePhoneNumbersAsAdmin'];\n purchasePhoneNumberAsAdmin!: AdminBindings['purchasePhoneNumberAsAdmin'];\n startBulkPhoneClassification!: AdminBindings['startBulkPhoneClassification'];\n getOrgA2PStatusAsAdmin!: AdminBindings['getOrgA2PStatusAsAdmin'];\n resetOrgA2PStatusAsAdmin!: AdminBindings['resetOrgA2PStatusAsAdmin'];\n getSiteMappings!: AdminBindings['getSiteMappings'];\n getSiteMapping!: AdminBindings['getSiteMapping'];\n updateSiteMapping!: AdminBindings['updateSiteMapping'];\n updateSiteMappingWorkspace!: AdminBindings['updateSiteMappingWorkspace'];\n adminDeleteSiteMapping!: AdminBindings['adminDeleteSiteMapping'];\n createSiteMapping!: AdminBindings['createSiteMapping'];\n createOrUpdateSiteMapping!: AdminBindings['createOrUpdateSiteMapping'];\n deleteSiteMapping!: AdminBindings['deleteSiteMapping'];\n getInboxMappings!: AdminBindings['getInboxMappings'];\n getInboxMapping!: AdminBindings['getInboxMapping'];\n updateInboxMapping!: AdminBindings['updateInboxMapping'];\n deleteAdminInboxMapping!: AdminBindings['deleteAdminInboxMapping'];\n generateChatSummaries!: AdminBindings['generateChatSummaries'];\n executeQuery!: AdminBindings['executeQuery'];\n getTraceUrl!: AdminBindings['getTraceUrl'];\n listAllThemes!: AdminBindings['listAllThemes'];\n startBulkTOSAcceptance!: AdminBindings['startBulkTOSAcceptance'];\n startTokenUsageBackfill!: AdminBindings['startTokenUsageBackfill'];\n updateChatMessage!: AdminBindings['updateChatMessage'];\n createCustomerFromAccount!: AdminBindings['createCustomerFromAccount'];\n getCustomers!: AdminBindings['getCustomers'];\n getCustomer!: AdminBindings['getCustomer'];\n createCustomer!: AdminBindings['createCustomer'];\n updateCustomer!: AdminBindings['updateCustomer'];\n getCustomerAccounts!: AdminBindings['getCustomerAccounts'];\n linkCustomerToAccount!: AdminBindings['linkCustomerToAccount'];\n unlinkCustomerFromAccount!: AdminBindings['unlinkCustomerFromAccount'];\n syncCustomerToStripe!: AdminBindings['syncCustomerToStripe'];\n getStripeCustomer!: AdminBindings['getStripeCustomer'];\n createStripeCustomer!: AdminBindings['createStripeCustomer'];\n updateStripeCustomer!: AdminBindings['updateStripeCustomer'];\n getStripeSubscriptions!: AdminBindings['getStripeSubscriptions'];\n createStripeSubscription!: AdminBindings['createStripeSubscription'];\n createDirectSubscription!: AdminBindings['createDirectSubscription'];\n updateStripeSubscription!: AdminBindings['updateStripeSubscription'];\n cancelStripeSubscription!: AdminBindings['cancelStripeSubscription'];\n provisionWorkspaceForSubscription!: AdminBindings['provisionWorkspaceForSubscription'];\n associateWorkspaceWithSubscription!: AdminBindings['associateWorkspaceWithSubscription'];\n createSubscriptionPaymentLink!: AdminBindings['createSubscriptionPaymentLink'];\n createSetupIntent!: AdminBindings['createSetupIntent'];\n getStripePaymentMethods!: AdminBindings['getStripePaymentMethods'];\n attachStripePaymentMethod!: AdminBindings['attachStripePaymentMethod'];\n detachStripePaymentMethod!: AdminBindings['detachStripePaymentMethod'];\n setDefaultStripePaymentMethod!: AdminBindings['setDefaultStripePaymentMethod'];\n createCustomerSetupIntent!: AdminBindings['createCustomerSetupIntent'];\n getCustomerPaymentMethods!: AdminBindings['getCustomerPaymentMethods'];\n attachCustomerPaymentMethod!: AdminBindings['attachCustomerPaymentMethod'];\n detachCustomerPaymentMethod!: AdminBindings['detachCustomerPaymentMethod'];\n setDefaultCustomerPaymentMethod!: AdminBindings['setDefaultCustomerPaymentMethod'];\n convertSubscriptionToStripe!: AdminBindings['convertSubscriptionToStripe'];\n previewWorkspaceOrganizationChange!: AdminBindings['previewWorkspaceOrganizationChange'];\n changeWorkspaceOrganization!: AdminBindings['changeWorkspaceOrganization'];\n createStripeInvoice!: AdminBindings['createStripeInvoice'];\n getStripeInvoices!: AdminBindings['getStripeInvoices'];\n getStripeUpcomingInvoice!: AdminBindings['getStripeUpcomingInvoice'];\n getWorkspaceUsageDashboard!: AdminBindings['getWorkspaceUsageDashboard'];\n compareProductsWithStripe!: AdminBindings['compareProductsWithStripe'];\n syncProductToStripe!: AdminBindings['syncProductToStripe'];\n searchStripeProducts!: AdminBindings['searchStripeProducts'];\n getUsageReport!: AdminBindings['getUsageReport'];\n getSubscriptionsAsAdmin!: AdminBindings['getSubscriptionsAsAdmin'];\n getSubscriptionAsAdmin!: AdminBindings['getSubscriptionAsAdmin'];\n updateSubscriptionStatusAsAdmin!: AdminBindings['updateSubscriptionStatusAsAdmin'];\n updateSubscriptionCreditSettingsAsAdmin!: AdminBindings['updateSubscriptionCreditSettingsAsAdmin'];\n grantCreditsAsAdmin!: AdminBindings['grantCreditsAsAdmin'];\n listCreditGrantsAsAdmin!: AdminBindings['listCreditGrantsAsAdmin'];\n getVoiceMetrics!: AdminBindings['getVoiceMetrics'];\n getHealthMetrics!: AdminBindings['getHealthMetrics'];\n getHealthDetail!: AdminBindings['getHealthDetail'];\n getWorkspaceInboxesAsAdmin!: AdminBindings['getWorkspaceInboxesAsAdmin'];\n listWorkspaceChats!: AdminBindings['listWorkspaceChats'];\n getWorkspaceChat!: AdminBindings['getWorkspaceChat'];\n rateWorkspaceChatMessage!: AdminBindings['rateWorkspaceChatMessage'];\n getTemporalAdminConfig!: AdminBindings['getTemporalAdminConfig'];\n listFailedTemporalWorkflows!: AdminBindings['listFailedTemporalWorkflows'];\n listStuckTemporalWorkflows!: AdminBindings['listStuckTemporalWorkflows'];\n getTemporalSummary!: AdminBindings['getTemporalSummary'];\n getTemporalWorkflowDetail!: AdminBindings['getTemporalWorkflowDetail'];\n getResellers!: AdminBindings['getResellers'];\n getReseller!: AdminBindings['getReseller'];\n createReseller!: AdminBindings['createReseller'];\n updateReseller!: AdminBindings['updateReseller'];\n getResellerAccounts!: AdminBindings['getResellerAccounts'];\n linkResellerToAccount!: AdminBindings['linkResellerToAccount'];\n unlinkResellerFromAccount!: AdminBindings['unlinkResellerFromAccount'];\n getBillingPeriods!: AdminBindings['getBillingPeriods'];\n generateInvoice!: AdminBindings['generateInvoice'];\n getInvoices!: AdminBindings['getInvoices'];\n getInvoiceDownloadUrl!: AdminBindings['getInvoiceDownloadUrl'];\n getReceiptDownloadUrl!: AdminBindings['getReceiptDownloadUrl'];\n recordInvoicePayment!: AdminBindings['recordInvoicePayment'];\n\n protected adminApi: AdminApi;\n\n constructor(apiKey: string | undefined, baseUrl: string, customFetch?: typeof fetch) {\n super(apiKey, baseUrl, customFetch);\n this.adminApi = new AdminApi(apiKey, baseUrl, customFetch);\n bindAdminMethods(this, this.adminApi);\n }\n\n /**\n * Propagates acting member switches to the admin API module as well.\n */\n override setActingMember(memberUuid: string | undefined) {\n super.setActingMember(memberUuid);\n if (typeof this.adminApi.setActingMember === 'function') {\n this.adminApi.setActingMember(memberUuid);\n }\n }\n\n // setOrgToken is intentionally NOT overridden here. Admin routes\n // (/api/v2/admin/*) are protected by the bearer token's superuser claim and\n // ignore X-Org-Token entirely, so propagating an org token to adminApi is\n // dead code that would only obscure auth flow if admin route logic changes.\n}\n","import { AdminApi } from '../../api';\n\nexport interface AdminBindings {\n // Support Requests\n listSupportRequestsAsAdmin: AdminApi['listSupportRequestsAsAdmin'];\n getSupportRequestAsAdmin: AdminApi['getSupportRequestAsAdmin'];\n commentOnSupportRequestAsAdmin: AdminApi['commentOnSupportRequestAsAdmin'];\n noteOnSupportRequestAsAdmin: AdminApi['noteOnSupportRequestAsAdmin'];\n updateSupportRequestStatusAsAdmin: AdminApi['updateSupportRequestStatusAsAdmin'];\n updateSupportRequestAttributesAsAdmin: AdminApi['updateSupportRequestAttributesAsAdmin'];\n createSupportRequestLinearIssueAsAdmin: AdminApi['createSupportRequestLinearIssueAsAdmin'];\n createOutboundSupportRequestAsAdmin: AdminApi['createOutboundSupportRequestAsAdmin'];\n attachSupportRequestResourceAsAdmin: AdminApi['attachSupportRequestResourceAsAdmin'];\n revokeSupportRequestResourceAsAdmin: AdminApi['revokeSupportRequestResourceAsAdmin'];\n\n // Customer activity events\n listCustomerActivityEvents: AdminApi['listCustomerActivityEvents'];\n getCustomerActivityEvent: AdminApi['getCustomerActivityEvent'];\n setCustomerActivityEventDisposition: AdminApi['setCustomerActivityEventDisposition'];\n setCustomerActivityEventStatus: AdminApi['setCustomerActivityEventStatus'];\n reclassifyCustomerActivityEvent: AdminApi['reclassifyCustomerActivityEvent'];\n\n // Accounts\n getAccounts: AdminApi['getAccounts'];\n getAccountDetails: AdminApi['getAccountDetails'];\n getAccountByUuid: AdminApi['getAccountByUuid'];\n getAccountMemberships: AdminApi['getAccountMemberships'];\n getAccountOrgMemberships: AdminApi['getAccountOrgMemberships'];\n createAccountOrgMembership: AdminApi['createAccountOrgMembership'];\n deleteAccountOrgMembership: AdminApi['deleteAccountOrgMembership'];\n getAccountMembership: AdminApi['getAccountMembership'];\n updateAccountMembership: AdminApi['updateAccountMembership'];\n createAccountMembership: AdminApi['createAccountMembership'];\n deleteAccountMembership: AdminApi['deleteAccountMembership'];\n updateAccountAsAdmin: AdminApi['updateAccountAsAdmin'];\n createAccountAsAdmin: AdminApi['createAccountAsAdmin'];\n deleteAccountAsAdmin: AdminApi['deleteAccountAsAdmin'];\n lookupAccount: AdminApi['lookupAccount'];\n exportAccountData: AdminApi['exportAccountData'];\n requestAccountDeletion: AdminApi['requestAccountDeletion'];\n cancelAccountDeletion: AdminApi['cancelAccountDeletion'];\n\n // Organizations\n getOrganizations: AdminApi['getOrganizations'];\n getOrganization: AdminApi['getOrganization'];\n getOrganizationAsAdmin: AdminApi['getOrganizationAsAdmin'];\n getOrganizationMembersAsAdmin: AdminApi['getOrganizationMembersAsAdmin'];\n createOrganization: AdminApi['createOrganization'];\n updateOrganization: AdminApi['updateOrganization'];\n deleteOrganization: AdminApi['deleteOrganization'];\n joinOrganization: AdminApi['joinOrganization'];\n leaveOrganization: AdminApi['leaveOrganization'];\n generateLogoUploadUrl: AdminApi['generateLogoUploadUrl'];\n\n // Products\n importProducts: AdminApi['importProducts'];\n createProductAsAdmin: AdminApi['createProductAsAdmin'];\n getProductsAsAdmin: AdminApi['getProductsAsAdmin'];\n getProductAsAdmin: AdminApi['getProductAsAdmin'];\n updateProductAsAdmin: AdminApi['updateProductAsAdmin'];\n deleteProductAsAdmin: AdminApi['deleteProductAsAdmin'];\n\n // Workspaces\n getWorkspacesAsAdmin: AdminApi['getWorkspacesAsAdmin'];\n getWorkspaceAsAdmin: AdminApi['getWorkspaceAsAdmin'];\n getWorkspaceByNumericIdAsAdmin: AdminApi['getWorkspaceByNumericIdAsAdmin'];\n createWorkspaceAsAdmin: AdminApi['createWorkspaceAsAdmin'];\n updateWorkspaceAsAdmin: AdminApi['updateWorkspaceAsAdmin'];\n deleteWorkspaceAsAdmin: AdminApi['deleteWorkspaceAsAdmin'];\n createSchemaAsAdmin: AdminApi['createSchemaAsAdmin'];\n migrateSchemaAsAdmin: AdminApi['migrateSchemaAsAdmin'];\n provisionWorkspaceAsAdmin: AdminApi['provisionWorkspaceAsAdmin'];\n refreshProvisionStatusAsAdmin: AdminApi['refreshProvisionStatusAsAdmin'];\n enableMaintenanceMode: AdminApi['enableMaintenanceMode'];\n disableMaintenanceMode: AdminApi['disableMaintenanceMode'];\n getWorkspaceHealth: AdminApi['getWorkspaceHealth'];\n provisionPlanFeatures: AdminApi['provisionPlanFeatures'];\n changeWorkspaceProduct: AdminApi['changeWorkspaceProduct'];\n validateWorkflowAccessAsAdmin: AdminApi['validateWorkflowAccessAsAdmin'];\n\n // Members\n mergeMembers: AdminApi['mergeMembers'];\n getAdminWorkspaceMember: AdminApi['getAdminWorkspaceMember'];\n createAdminWorkspaceMember: AdminApi['createAdminWorkspaceMember'];\n updateAdminWorkspaceMember: AdminApi['updateAdminWorkspaceMember'];\n unarchiveAdminWorkspaceMember: AdminApi['unarchiveAdminWorkspaceMember'];\n getAdminWorkspaceMemberRoles: AdminApi['getAdminWorkspaceMemberRoles'];\n getMissingMemberships: AdminApi['getMissingMemberships'];\n linkMissingMembership: AdminApi['linkMissingMembership'];\n\n // Phone Numbers\n getUnmappedPhoneNumbers: AdminApi['getUnmappedPhoneNumbers'];\n getWorkspaceUnmappedPhoneNumbers: AdminApi['getWorkspaceUnmappedPhoneNumbers'];\n getWorkspacePhoneNumbersAsAdmin: AdminApi['getWorkspacePhoneNumbersAsAdmin'];\n getProviderPhoneNumbers: AdminApi['getProviderPhoneNumbers'];\n getProviderPhoneNumber: AdminApi['getProviderPhoneNumber'];\n updateProviderPhoneNumber: AdminApi['updateProviderPhoneNumber'];\n mapMainAccountPhone: AdminApi['mapMainAccountPhone'];\n unmapPhoneNumber: AdminApi['unmapPhoneNumber'];\n searchAvailablePhoneNumbersAsAdmin: AdminApi['searchAvailablePhoneNumbersAsAdmin'];\n purchasePhoneNumberAsAdmin: AdminApi['purchasePhoneNumberAsAdmin'];\n startBulkPhoneClassification: AdminApi['startBulkPhoneClassification'];\n getOrgA2PStatusAsAdmin: AdminApi['getOrgA2PStatusAsAdmin'];\n resetOrgA2PStatusAsAdmin: AdminApi['resetOrgA2PStatusAsAdmin'];\n\n // Site Mappings\n getSiteMappings: AdminApi['getSiteMappings'];\n getSiteMapping: AdminApi['getSiteMapping'];\n updateSiteMapping: AdminApi['updateSiteMapping'];\n updateSiteMappingWorkspace: AdminApi['updateSiteMappingWorkspace'];\n adminDeleteSiteMapping: AdminApi['adminDeleteSiteMapping'];\n createSiteMapping: AdminApi['createSiteMapping'];\n createOrUpdateSiteMapping: AdminApi['createOrUpdateSiteMapping'];\n deleteSiteMapping: AdminApi['deleteSiteMapping'];\n\n // Admin Workspace Inboxes\n getWorkspaceInboxesAsAdmin: AdminApi['getWorkspaceInboxesAsAdmin'];\n\n // Inbox Mappings\n getInboxMappings: AdminApi['getInboxMappings'];\n getInboxMapping: AdminApi['getInboxMapping'];\n updateInboxMapping: AdminApi['updateInboxMapping'];\n deleteAdminInboxMapping: AdminApi['deleteAdminInboxMapping'];\n\n // Utilities\n generateChatSummaries: AdminApi['generateChatSummaries'];\n executeQuery: AdminApi['executeQuery'];\n getTraceUrl: AdminApi['getTraceUrl'];\n listAllThemes: AdminApi['listAllThemes'];\n startBulkTOSAcceptance: AdminApi['startBulkTOSAcceptance'];\n startTokenUsageBackfill: AdminApi['startTokenUsageBackfill'];\n updateChatMessage: AdminApi['updateChatMessage'];\n\n // Customer Management\n createCustomerFromAccount: AdminApi['createCustomerFromAccount'];\n getCustomers: AdminApi['getCustomers'];\n getCustomer: AdminApi['getCustomer'];\n createCustomer: AdminApi['createCustomer'];\n updateCustomer: AdminApi['updateCustomer'];\n getCustomerAccounts: AdminApi['getCustomerAccounts'];\n linkCustomerToAccount: AdminApi['linkCustomerToAccount'];\n unlinkCustomerFromAccount: AdminApi['unlinkCustomerFromAccount'];\n syncCustomerToStripe: AdminApi['syncCustomerToStripe'];\n\n // Stripe Customer Management\n getStripeCustomer: AdminApi['getStripeCustomer'];\n createStripeCustomer: AdminApi['createStripeCustomer'];\n updateStripeCustomer: AdminApi['updateStripeCustomer'];\n\n // Stripe Subscription Management\n getStripeSubscriptions: AdminApi['getStripeSubscriptions'];\n createStripeSubscription: AdminApi['createStripeSubscription'];\n createDirectSubscription: AdminApi['createDirectSubscription'];\n updateStripeSubscription: AdminApi['updateStripeSubscription'];\n cancelStripeSubscription: AdminApi['cancelStripeSubscription'];\n provisionWorkspaceForSubscription: AdminApi['provisionWorkspaceForSubscription'];\n associateWorkspaceWithSubscription: AdminApi['associateWorkspaceWithSubscription'];\n createSubscriptionPaymentLink: AdminApi['createSubscriptionPaymentLink'];\n\n // Stripe Payment Methods (account-level — deprecated, use customer-level)\n createSetupIntent: AdminApi['createSetupIntent'];\n getStripePaymentMethods: AdminApi['getStripePaymentMethods'];\n attachStripePaymentMethod: AdminApi['attachStripePaymentMethod'];\n detachStripePaymentMethod: AdminApi['detachStripePaymentMethod'];\n setDefaultStripePaymentMethod: AdminApi['setDefaultStripePaymentMethod'];\n\n // Convert direct subscription to Stripe\n convertSubscriptionToStripe: AdminApi['convertSubscriptionToStripe'];\n\n // Stripe Payment Methods (customer-level)\n createCustomerSetupIntent: AdminApi['createCustomerSetupIntent'];\n getCustomerPaymentMethods: AdminApi['getCustomerPaymentMethods'];\n attachCustomerPaymentMethod: AdminApi['attachCustomerPaymentMethod'];\n detachCustomerPaymentMethod: AdminApi['detachCustomerPaymentMethod'];\n setDefaultCustomerPaymentMethod: AdminApi['setDefaultCustomerPaymentMethod'];\n\n previewWorkspaceOrganizationChange: AdminApi['previewWorkspaceOrganizationChange'];\n changeWorkspaceOrganization: AdminApi['changeWorkspaceOrganization'];\n\n // Stripe Invoices\n createStripeInvoice: AdminApi['createStripeInvoice'];\n getStripeInvoices: AdminApi['getStripeInvoices'];\n getStripeUpcomingInvoice: AdminApi['getStripeUpcomingInvoice'];\n\n // Invoices\n getBillingPeriods: AdminApi['getBillingPeriods'];\n generateInvoice: AdminApi['generateInvoice'];\n getInvoices: AdminApi['getInvoices'];\n getInvoiceDownloadUrl: AdminApi['getInvoiceDownloadUrl'];\n getReceiptDownloadUrl: AdminApi['getReceiptDownloadUrl'];\n recordInvoicePayment: AdminApi['recordInvoicePayment'];\n\n // Billing Dashboard\n getWorkspaceUsageDashboard: AdminApi['getWorkspaceUsageDashboard'];\n\n // Product Stripe Sync\n compareProductsWithStripe: AdminApi['compareProductsWithStripe'];\n syncProductToStripe: AdminApi['syncProductToStripe'];\n searchStripeProducts: AdminApi['searchStripeProducts'];\n\n // Usage API\n getUsageReport: AdminApi['getUsageReport'];\n\n // Subscriptions Admin API\n getSubscriptionsAsAdmin: AdminApi['getSubscriptionsAsAdmin'];\n getSubscriptionAsAdmin: AdminApi['getSubscriptionAsAdmin'];\n updateSubscriptionStatusAsAdmin: AdminApi['updateSubscriptionStatusAsAdmin'];\n updateSubscriptionCreditSettingsAsAdmin: AdminApi['updateSubscriptionCreditSettingsAsAdmin'];\n grantCreditsAsAdmin: AdminApi['grantCreditsAsAdmin'];\n listCreditGrantsAsAdmin: AdminApi['listCreditGrantsAsAdmin'];\n\n // Voice Metrics API\n getVoiceMetrics: AdminApi['getVoiceMetrics'];\n\n // Health Dashboard API\n getHealthMetrics: AdminApi['getHealthMetrics'];\n getHealthDetail: AdminApi['getHealthDetail'];\n\n // Admin Chat Endpoints\n listWorkspaceChats: AdminApi['listWorkspaceChats'];\n getWorkspaceChat: AdminApi['getWorkspaceChat'];\n rateWorkspaceChatMessage: AdminApi['rateWorkspaceChatMessage'];\n\n // Admin Temporal Inspection\n getTemporalAdminConfig: AdminApi['getTemporalAdminConfig'];\n listFailedTemporalWorkflows: AdminApi['listFailedTemporalWorkflows'];\n listStuckTemporalWorkflows: AdminApi['listStuckTemporalWorkflows'];\n getTemporalSummary: AdminApi['getTemporalSummary'];\n getTemporalWorkflowDetail: AdminApi['getTemporalWorkflowDetail'];\n\n // Reseller Management\n getResellers: AdminApi['getResellers'];\n getReseller: AdminApi['getReseller'];\n createReseller: AdminApi['createReseller'];\n updateReseller: AdminApi['updateReseller'];\n getResellerAccounts: AdminApi['getResellerAccounts'];\n linkResellerToAccount: AdminApi['linkResellerToAccount'];\n unlinkResellerFromAccount: AdminApi['unlinkResellerFromAccount'];\n}\n\nexport function bindAdminMethods(target: AdminBindings, admin: AdminApi): void {\n // Support Requests\n target.listSupportRequestsAsAdmin = admin.listSupportRequestsAsAdmin.bind(admin);\n target.getSupportRequestAsAdmin = admin.getSupportRequestAsAdmin.bind(admin);\n target.commentOnSupportRequestAsAdmin = admin.commentOnSupportRequestAsAdmin.bind(admin);\n target.noteOnSupportRequestAsAdmin = admin.noteOnSupportRequestAsAdmin.bind(admin);\n target.updateSupportRequestStatusAsAdmin = admin.updateSupportRequestStatusAsAdmin.bind(admin);\n target.updateSupportRequestAttributesAsAdmin =\n admin.updateSupportRequestAttributesAsAdmin.bind(admin);\n target.createSupportRequestLinearIssueAsAdmin =\n admin.createSupportRequestLinearIssueAsAdmin.bind(admin);\n target.createOutboundSupportRequestAsAdmin =\n admin.createOutboundSupportRequestAsAdmin.bind(admin);\n target.attachSupportRequestResourceAsAdmin =\n admin.attachSupportRequestResourceAsAdmin.bind(admin);\n target.revokeSupportRequestResourceAsAdmin =\n admin.revokeSupportRequestResourceAsAdmin.bind(admin);\n target.listCustomerActivityEvents = admin.listCustomerActivityEvents.bind(admin);\n target.getCustomerActivityEvent = admin.getCustomerActivityEvent.bind(admin);\n target.setCustomerActivityEventDisposition =\n admin.setCustomerActivityEventDisposition.bind(admin);\n target.setCustomerActivityEventStatus = admin.setCustomerActivityEventStatus.bind(admin);\n target.reclassifyCustomerActivityEvent = admin.reclassifyCustomerActivityEvent.bind(admin);\n\n // Accounts\n target.getAccounts = admin.getAccounts.bind(admin);\n target.getAccountDetails = admin.getAccountDetails.bind(admin);\n target.getAccountByUuid = admin.getAccountByUuid.bind(admin);\n target.getAccountMemberships = admin.getAccountMemberships.bind(admin);\n target.getAccountOrgMemberships = admin.getAccountOrgMemberships.bind(admin);\n target.createAccountOrgMembership = admin.createAccountOrgMembership.bind(admin);\n target.deleteAccountOrgMembership = admin.deleteAccountOrgMembership.bind(admin);\n target.getAccountMembership = admin.getAccountMembership.bind(admin);\n target.updateAccountMembership = admin.updateAccountMembership.bind(admin);\n target.createAccountMembership = admin.createAccountMembership.bind(admin);\n target.deleteAccountMembership = admin.deleteAccountMembership.bind(admin);\n target.updateAccountAsAdmin = admin.updateAccountAsAdmin.bind(admin);\n target.createAccountAsAdmin = admin.createAccountAsAdmin.bind(admin);\n target.deleteAccountAsAdmin = admin.deleteAccountAsAdmin.bind(admin);\n target.lookupAccount = admin.lookupAccount.bind(admin);\n target.exportAccountData = admin.exportAccountData.bind(admin);\n target.requestAccountDeletion = admin.requestAccountDeletion.bind(admin);\n target.cancelAccountDeletion = admin.cancelAccountDeletion.bind(admin);\n\n // Organizations\n target.getOrganizations = admin.getOrganizations.bind(admin);\n target.getOrganization = admin.getOrganization.bind(admin);\n target.getOrganizationAsAdmin = admin.getOrganizationAsAdmin.bind(admin);\n target.getOrganizationMembersAsAdmin = admin.getOrganizationMembersAsAdmin.bind(admin);\n target.createOrganization = admin.createOrganization.bind(admin);\n target.updateOrganization = admin.updateOrganization.bind(admin);\n target.deleteOrganization = admin.deleteOrganization.bind(admin);\n target.joinOrganization = admin.joinOrganization.bind(admin);\n target.leaveOrganization = admin.leaveOrganization.bind(admin);\n target.generateLogoUploadUrl = admin.generateLogoUploadUrl.bind(admin);\n\n // Products\n target.importProducts = admin.importProducts.bind(admin);\n target.createProductAsAdmin = admin.createProductAsAdmin.bind(admin);\n target.getProductsAsAdmin = admin.getProductsAsAdmin.bind(admin);\n target.getProductAsAdmin = admin.getProductAsAdmin.bind(admin);\n target.updateProductAsAdmin = admin.updateProductAsAdmin.bind(admin);\n target.deleteProductAsAdmin = admin.deleteProductAsAdmin.bind(admin);\n\n // Workspaces\n target.getWorkspacesAsAdmin = admin.getWorkspacesAsAdmin.bind(admin);\n target.getWorkspaceAsAdmin = admin.getWorkspaceAsAdmin.bind(admin);\n target.getWorkspaceByNumericIdAsAdmin = admin.getWorkspaceByNumericIdAsAdmin.bind(admin);\n target.createWorkspaceAsAdmin = admin.createWorkspaceAsAdmin.bind(admin);\n target.updateWorkspaceAsAdmin = admin.updateWorkspaceAsAdmin.bind(admin);\n target.deleteWorkspaceAsAdmin = admin.deleteWorkspaceAsAdmin.bind(admin);\n target.createSchemaAsAdmin = admin.createSchemaAsAdmin.bind(admin);\n target.migrateSchemaAsAdmin = admin.migrateSchemaAsAdmin.bind(admin);\n target.provisionWorkspaceAsAdmin = admin.provisionWorkspaceAsAdmin.bind(admin);\n target.refreshProvisionStatusAsAdmin = admin.refreshProvisionStatusAsAdmin.bind(admin);\n target.enableMaintenanceMode = admin.enableMaintenanceMode.bind(admin);\n target.disableMaintenanceMode = admin.disableMaintenanceMode.bind(admin);\n target.getWorkspaceHealth = admin.getWorkspaceHealth.bind(admin);\n target.provisionPlanFeatures = admin.provisionPlanFeatures.bind(admin);\n target.changeWorkspaceProduct = admin.changeWorkspaceProduct.bind(admin);\n target.validateWorkflowAccessAsAdmin = admin.validateWorkflowAccessAsAdmin.bind(admin);\n\n // Members\n target.mergeMembers = admin.mergeMembers.bind(admin);\n target.getAdminWorkspaceMember = admin.getAdminWorkspaceMember.bind(admin);\n target.createAdminWorkspaceMember = admin.createAdminWorkspaceMember.bind(admin);\n target.updateAdminWorkspaceMember = admin.updateAdminWorkspaceMember.bind(admin);\n target.unarchiveAdminWorkspaceMember = admin.unarchiveAdminWorkspaceMember.bind(admin);\n target.getAdminWorkspaceMemberRoles = admin.getAdminWorkspaceMemberRoles.bind(admin);\n target.getMissingMemberships = admin.getMissingMemberships.bind(admin);\n target.linkMissingMembership = admin.linkMissingMembership.bind(admin);\n\n // Phone Numbers\n target.getUnmappedPhoneNumbers = admin.getUnmappedPhoneNumbers.bind(admin);\n target.getWorkspaceUnmappedPhoneNumbers = admin.getWorkspaceUnmappedPhoneNumbers.bind(admin);\n target.getWorkspacePhoneNumbersAsAdmin = admin.getWorkspacePhoneNumbersAsAdmin.bind(admin);\n target.getProviderPhoneNumbers = admin.getProviderPhoneNumbers.bind(admin);\n target.getProviderPhoneNumber = admin.getProviderPhoneNumber.bind(admin);\n target.updateProviderPhoneNumber = admin.updateProviderPhoneNumber.bind(admin);\n target.mapMainAccountPhone = admin.mapMainAccountPhone.bind(admin);\n target.unmapPhoneNumber = admin.unmapPhoneNumber.bind(admin);\n target.searchAvailablePhoneNumbersAsAdmin = admin.searchAvailablePhoneNumbersAsAdmin.bind(admin);\n target.purchasePhoneNumberAsAdmin = admin.purchasePhoneNumberAsAdmin.bind(admin);\n target.startBulkPhoneClassification = admin.startBulkPhoneClassification.bind(admin);\n target.getOrgA2PStatusAsAdmin = admin.getOrgA2PStatusAsAdmin.bind(admin);\n target.resetOrgA2PStatusAsAdmin = admin.resetOrgA2PStatusAsAdmin.bind(admin);\n\n // Site Mappings\n target.getSiteMappings = admin.getSiteMappings.bind(admin);\n target.getSiteMapping = admin.getSiteMapping.bind(admin);\n target.updateSiteMapping = admin.updateSiteMapping.bind(admin);\n target.updateSiteMappingWorkspace = admin.updateSiteMappingWorkspace.bind(admin);\n target.adminDeleteSiteMapping = admin.adminDeleteSiteMapping.bind(admin);\n target.createSiteMapping = admin.createSiteMapping.bind(admin);\n target.createOrUpdateSiteMapping = admin.createOrUpdateSiteMapping.bind(admin);\n target.deleteSiteMapping = admin.deleteSiteMapping.bind(admin);\n\n // Inbox Mappings\n target.getInboxMappings = admin.getInboxMappings.bind(admin);\n target.getInboxMapping = admin.getInboxMapping.bind(admin);\n target.updateInboxMapping = admin.updateInboxMapping.bind(admin);\n target.deleteAdminInboxMapping = admin.deleteAdminInboxMapping.bind(admin);\n\n // Utilities\n target.generateChatSummaries = admin.generateChatSummaries.bind(admin);\n target.executeQuery = admin.executeQuery.bind(admin);\n target.getTraceUrl = admin.getTraceUrl.bind(admin);\n target.listAllThemes = admin.listAllThemes.bind(admin);\n target.startBulkTOSAcceptance = admin.startBulkTOSAcceptance.bind(admin);\n target.startTokenUsageBackfill = admin.startTokenUsageBackfill.bind(admin);\n target.updateChatMessage = admin.updateChatMessage.bind(admin);\n\n // Customer Management\n target.createCustomerFromAccount = admin.createCustomerFromAccount.bind(admin);\n target.getCustomers = admin.getCustomers.bind(admin);\n target.getCustomer = admin.getCustomer.bind(admin);\n target.createCustomer = admin.createCustomer.bind(admin);\n target.updateCustomer = admin.updateCustomer.bind(admin);\n target.getCustomerAccounts = admin.getCustomerAccounts.bind(admin);\n target.linkCustomerToAccount = admin.linkCustomerToAccount.bind(admin);\n target.unlinkCustomerFromAccount = admin.unlinkCustomerFromAccount.bind(admin);\n target.syncCustomerToStripe = admin.syncCustomerToStripe.bind(admin);\n\n // Stripe Customer Management\n target.getStripeCustomer = admin.getStripeCustomer.bind(admin);\n target.createStripeCustomer = admin.createStripeCustomer.bind(admin);\n target.updateStripeCustomer = admin.updateStripeCustomer.bind(admin);\n\n // Stripe Subscription Management\n target.getStripeSubscriptions = admin.getStripeSubscriptions.bind(admin);\n target.createStripeSubscription = admin.createStripeSubscription.bind(admin);\n target.createDirectSubscription = admin.createDirectSubscription.bind(admin);\n target.updateStripeSubscription = admin.updateStripeSubscription.bind(admin);\n target.cancelStripeSubscription = admin.cancelStripeSubscription.bind(admin);\n target.provisionWorkspaceForSubscription = admin.provisionWorkspaceForSubscription.bind(admin);\n target.associateWorkspaceWithSubscription = admin.associateWorkspaceWithSubscription.bind(admin);\n target.createSubscriptionPaymentLink = admin.createSubscriptionPaymentLink.bind(admin);\n\n // Stripe Payment Methods (account-level — deprecated)\n target.createSetupIntent = admin.createSetupIntent.bind(admin);\n target.getStripePaymentMethods = admin.getStripePaymentMethods.bind(admin);\n target.attachStripePaymentMethod = admin.attachStripePaymentMethod.bind(admin);\n target.detachStripePaymentMethod = admin.detachStripePaymentMethod.bind(admin);\n target.setDefaultStripePaymentMethod = admin.setDefaultStripePaymentMethod.bind(admin);\n\n // Convert direct subscription to Stripe\n target.convertSubscriptionToStripe = admin.convertSubscriptionToStripe.bind(admin);\n\n // Stripe Payment Methods (customer-level)\n target.createCustomerSetupIntent = admin.createCustomerSetupIntent.bind(admin);\n target.getCustomerPaymentMethods = admin.getCustomerPaymentMethods.bind(admin);\n target.attachCustomerPaymentMethod = admin.attachCustomerPaymentMethod.bind(admin);\n target.detachCustomerPaymentMethod = admin.detachCustomerPaymentMethod.bind(admin);\n target.setDefaultCustomerPaymentMethod = admin.setDefaultCustomerPaymentMethod.bind(admin);\n\n target.previewWorkspaceOrganizationChange = admin.previewWorkspaceOrganizationChange.bind(admin);\n target.changeWorkspaceOrganization = admin.changeWorkspaceOrganization.bind(admin);\n\n // Stripe Invoices\n target.createStripeInvoice = admin.createStripeInvoice.bind(admin);\n target.getStripeInvoices = admin.getStripeInvoices.bind(admin);\n target.getStripeUpcomingInvoice = admin.getStripeUpcomingInvoice.bind(admin);\n\n // Invoices\n target.getBillingPeriods = admin.getBillingPeriods.bind(admin);\n target.generateInvoice = admin.generateInvoice.bind(admin);\n target.getInvoices = admin.getInvoices.bind(admin);\n target.getInvoiceDownloadUrl = admin.getInvoiceDownloadUrl.bind(admin);\n target.getReceiptDownloadUrl = admin.getReceiptDownloadUrl.bind(admin);\n target.recordInvoicePayment = admin.recordInvoicePayment.bind(admin);\n\n // Billing Dashboard\n target.getWorkspaceUsageDashboard = admin.getWorkspaceUsageDashboard.bind(admin);\n\n // Product Stripe Sync\n target.compareProductsWithStripe = admin.compareProductsWithStripe.bind(admin);\n target.syncProductToStripe = admin.syncProductToStripe.bind(admin);\n target.searchStripeProducts = admin.searchStripeProducts.bind(admin);\n\n // Usage API\n target.getUsageReport = admin.getUsageReport.bind(admin);\n\n // Subscriptions Admin API\n target.getSubscriptionsAsAdmin = admin.getSubscriptionsAsAdmin.bind(admin);\n target.getSubscriptionAsAdmin = admin.getSubscriptionAsAdmin.bind(admin);\n target.updateSubscriptionStatusAsAdmin = admin.updateSubscriptionStatusAsAdmin.bind(admin);\n target.updateSubscriptionCreditSettingsAsAdmin =\n admin.updateSubscriptionCreditSettingsAsAdmin.bind(admin);\n target.grantCreditsAsAdmin = admin.grantCreditsAsAdmin.bind(admin);\n target.listCreditGrantsAsAdmin = admin.listCreditGrantsAsAdmin.bind(admin);\n\n // Voice Metrics API\n target.getVoiceMetrics = admin.getVoiceMetrics.bind(admin);\n\n // Health Dashboard API\n target.getHealthMetrics = admin.getHealthMetrics.bind(admin);\n target.getHealthDetail = admin.getHealthDetail.bind(admin);\n\n // Admin Workspace Inboxes\n target.getWorkspaceInboxesAsAdmin = admin.getWorkspaceInboxesAsAdmin.bind(admin);\n\n // Admin Chat Endpoints\n target.listWorkspaceChats = admin.listWorkspaceChats.bind(admin);\n target.getWorkspaceChat = admin.getWorkspaceChat.bind(admin);\n target.rateWorkspaceChatMessage = admin.rateWorkspaceChatMessage.bind(admin);\n\n // Admin Temporal Inspection\n target.getTemporalAdminConfig = admin.getTemporalAdminConfig.bind(admin);\n target.listFailedTemporalWorkflows = admin.listFailedTemporalWorkflows.bind(admin);\n target.listStuckTemporalWorkflows = admin.listStuckTemporalWorkflows.bind(admin);\n target.getTemporalSummary = admin.getTemporalSummary.bind(admin);\n target.getTemporalWorkflowDetail = admin.getTemporalWorkflowDetail.bind(admin);\n\n // Reseller Management\n target.getResellers = admin.getResellers.bind(admin);\n target.getReseller = admin.getReseller.bind(admin);\n target.createReseller = admin.createReseller.bind(admin);\n target.updateReseller = admin.updateReseller.bind(admin);\n target.getResellerAccounts = admin.getResellerAccounts.bind(admin);\n target.linkResellerToAccount = admin.linkResellerToAccount.bind(admin);\n target.unlinkResellerFromAccount = admin.unlinkResellerFromAccount.bind(admin);\n}\n","import { execSync } from 'child_process';\nimport { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'fs';\nimport { dirname, join } from 'path';\n\nexport interface RealmCredentials {\n token: string;\n workspaceUuid?: string;\n}\n\n/** Walk up from cwd looking for dev-realms.json (like finding package.json) */\nfunction findDevRealmsFile(): string {\n let dir = process.cwd();\n while (dir !== dirname(dir)) {\n const candidate = join(dir, 'dev-realms.json');\n if (existsSync(candidate)) return candidate;\n dir = dirname(dir);\n }\n throw new Error('Cannot find dev-realms.json in any parent directory');\n}\n\nconst DEV_CLOUD_CACHE_DIR = '.dev-cloud';\nconst CACHE_MAX_AGE_MS = 60 * 60 * 1000; // 1 hour\n\nfunction findRepoRoot(): string | undefined {\n let dir = process.cwd();\n while (dir !== dirname(dir)) {\n if (existsSync(join(dir, '.git'))) {\n return dir;\n }\n dir = dirname(dir);\n }\n return undefined;\n}\n\nfunction getDevCloudCacheDir(namespace: string): string {\n const repoRoot = findRepoRoot();\n const base = repoRoot ?? process.cwd();\n return join(base, DEV_CLOUD_CACHE_DIR, namespace);\n}\n\nfunction fetchDevCloudRealms(namespace: string): string {\n const k8sNamespace = `dev-cloud-${namespace}`;\n const cmd = `kubectl exec -n ${k8sNamespace} deploy/env -c devbox -- cat /workspace/dev-realms.json`;\n try {\n return execSync(cmd, { encoding: 'utf-8', timeout: 30000 });\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `Failed to fetch dev-realms.json from dev-cloud pod \"${namespace}\": ${message}`\n );\n }\n}\n\n/**\n * Load (and cache) the dev-realms.json file from a dev-cloud pod.\n * Returns the path to the cached file.\n */\nexport function loadDevCloudRealmFile(namespace: string): string {\n const cacheDir = getDevCloudCacheDir(namespace);\n const cachePath = join(cacheDir, 'dev-realms.json');\n\n // Check cache freshness\n if (existsSync(cachePath)) {\n const stat = statSync(cachePath);\n const age = Date.now() - stat.mtimeMs;\n if (age < CACHE_MAX_AGE_MS) {\n return cachePath;\n }\n }\n\n // Fetch from pod\n const content = fetchDevCloudRealms(namespace);\n mkdirSync(cacheDir, { recursive: true });\n writeFileSync(cachePath, content, 'utf-8');\n return cachePath;\n}\n\nexport function loadRealmCredentials(realm: string, devRealmsPath?: string): RealmCredentials {\n const filePath = devRealmsPath ?? findDevRealmsFile();\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(readFileSync(filePath, 'utf-8'));\n } catch {\n throw new Error(`Cannot read dev-realms.json at ${filePath}`);\n }\n\n const parts = realm.split('/');\n if (parts.length === 1) {\n // Account-level: --realm dr-chen\n const accounts = data._accounts as Record<string, { token?: string }> | undefined;\n const account = accounts?.[parts[0]!];\n if (!account?.token) {\n throw new Error(`Realm account \"${parts[0]}\" not found in dev-realms.json`);\n }\n return { token: account.token };\n } else {\n // Workspace/member: --realm boston-nephrology-clinic/dr-chen\n const [wsName, memberName] = parts;\n const ws = data[wsName!] as\n | { workspaceUuid?: string; members?: Record<string, { token?: string }> }\n | undefined;\n if (!ws) {\n throw new Error(`Realm workspace \"${wsName}\" not found in dev-realms.json`);\n }\n const member = ws.members?.[memberName!];\n if (!member?.token) {\n throw new Error(`Realm member \"${memberName}\" not found in workspace \"${wsName}\"`);\n }\n return { token: member.token, workspaceUuid: ws.workspaceUuid };\n }\n}\n","/**\n * CLI handler for organization-level authentication challenges.\n *\n * When a workspace API call returns a 401 with WWW-Authenticate: Bearer realm=\"org\",\n * the SDK calls this handler. The CLI attempts to satisfy the challenge by:\n *\n * 1. POSTing to /api/v2/o/{org_uuid}/join with the existing bearer token.\n * This works for organizations that allow internal (non-SSO) authentication.\n * The response Set-Cookie header contains the org JWE token.\n *\n * 2. If the org requires SSO, falls back to opening the auth URL in the browser\n * and prompting the user to complete authentication manually, then errors.\n */\n\nimport { execFile } from 'child_process';\nimport type { ApiClient } from '@gravity-rail/client';\nimport type { OrgAuthInfo } from '@gravity-rail/sdk';\nimport { stderr } from './output';\n\nconst ORG_AUTH_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** Parse an org token value from Set-Cookie header strings. */\nfunction extractOrgTokenFromSetCookies(\n setCookieValues: string[],\n preferredCookieName: string\n): string | undefined {\n let fallback: string | undefined;\n\n for (const value of setCookieValues) {\n const nameValue = value.split(';')[0]?.trim() ?? '';\n const eqIdx = nameValue.indexOf('=');\n if (eqIdx === -1) continue;\n\n const name = nameValue.slice(0, eqIdx).trim();\n const tokenValue = nameValue.slice(eqIdx + 1).trim() || undefined;\n if (!tokenValue) continue;\n\n if (name === preferredCookieName) return tokenValue;\n // Accept any orgToken... or orgSession... cookie as a fallback\n if (!fallback && (name.startsWith('orgToken') || name.startsWith('orgSession'))) {\n fallback = tokenValue;\n }\n }\n\n return fallback;\n}\n\n/**\n * Attempt to satisfy an org auth challenge via the direct join endpoint.\n * Returns the org token string on success, null when SSO is required.\n * Throws on unexpected network / server errors.\n */\nasync function tryDirectJoin(\n apiUrl: string,\n accessToken: string,\n orgAuthInfo: OrgAuthInfo\n): Promise<string | null> {\n const response = await fetch(`${apiUrl}/api/v2/o/${orgAuthInfo.orgUuid}/join`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n },\n body: '{}',\n });\n\n if (response.status === 400) {\n // Org requires SSO — direct join is not permitted for this account\n return null;\n }\n\n if (!response.ok) {\n // Don't include the response body — the backend currently returns safe\n // JSON, but a future change could put PHI or other sensitive data there.\n // Status code is sufficient to disambiguate the failure mode.\n throw new Error(`Org join failed (HTTP ${response.status})`);\n }\n\n // Read Set-Cookie headers to extract the org token value.\n // Node ≥18 exposes getSetCookie() on Headers; fall back to get() for older runtimes.\n const rawHeaders = response.headers as Headers & {\n getSetCookie?: () => string[];\n };\n const setCookies: string[] =\n rawHeaders.getSetCookie?.() ??\n (rawHeaders.get('set-cookie') ? [rawHeaders.get('set-cookie')!] : []);\n\n if (setCookies.length === 0) {\n throw new Error('Org join succeeded but no Set-Cookie header returned');\n }\n\n const orgToken = extractOrgTokenFromSetCookies(setCookies, orgAuthInfo.cookieName);\n if (!orgToken) {\n throw new Error('Org join succeeded but org token cookie not found in Set-Cookie');\n }\n\n return orgToken;\n}\n\n/**\n * Validate that an auth URL is safe to hand to the OS URL opener.\n *\n * `open` / `xdg-open` / `cmd.exe start` will follow any URI scheme the OS\n * registers — including `file://`, `javascript:`, and custom app handlers —\n * so a compromised/MITMed server returning an attacker-controlled `authUrl`\n * could trigger arbitrary URI execution. Restrict to http(s) and require\n * the same parent domain as the configured API host (e.g. SSO login on\n * `app.gravityrail.com` is allowed when the API is `api.gravityrail.com`,\n * but `attacker.example` against `api.gravityrail.com` is rejected).\n *\n * \"Same parent domain\" is a last-2-labels match. This is a heuristic — it\n * does not consult the Public Suffix List, so `foo.co.uk` and `bar.co.uk`\n * would falsely match — but Gravity Rail's auth hosts do not live under\n * those ccTLDs, and the alternative (vendoring `psl`) is overkill for a CLI\n * gating check. The configured `apiUrl` is itself a trust anchor controlled\n * by the user; the threat is a hostile *response* from that API (or a MITM)\n * pivoting the URL opener.\n */\nfunction isAllowedAuthUrl(url: string, apiUrl: string): boolean {\n try {\n const parsed = new URL(url);\n const api = new URL(apiUrl);\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') return false;\n if (parsed.hostname === api.hostname) return true;\n\n const lastTwo = (host: string): string => {\n const parts = host.split('.').filter(Boolean);\n return parts.length >= 2 ? parts.slice(-2).join('.') : host;\n };\n // Reject IP-literal hosts from the parent-domain heuristic — last-2\n // labels of \"1.2.3.4\" would naively match \"3.4\" and admit anything.\n const isIp = /^[0-9.]+$|^\\[.*\\]$/.test(parsed.hostname);\n if (isIp) return false;\n\n return lastTwo(parsed.hostname) === lastTwo(api.hostname);\n } catch {\n return false;\n }\n}\n\n/** Open a URL in the system browser (cross-platform). */\nfunction openBrowser(url: string): void {\n let command: string;\n let args: string[];\n\n if (process.platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (process.platform === 'win32') {\n command = 'cmd.exe';\n args = ['/c', 'start', '', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n execFile(command, args, (_err) => {\n // Failure is non-fatal — the URL is printed to stderr so the user can open it manually.\n });\n}\n\n/**\n * Register a CLI org-auth handler on the given client.\n *\n * The handler satisfies org-auth 401 challenges without relying on browser\n * cookies (which are not available in Node.js):\n *\n * - Non-SSO orgs: calls the join endpoint directly and reads the org token\n * from the Set-Cookie response header, then sets it via client.setOrgToken().\n * The SDK retries the original request with X-Org-Token on the next call.\n *\n * - SSO orgs: opens the browser at the authUrl and returns a timeout error\n * after ORG_AUTH_TIMEOUT_MS, because the SSO token is only ever set as a\n * browser cookie that the CLI cannot intercept.\n */\nexport function registerOrgAuthHandler(\n apiClient: ApiClient,\n apiUrl: string,\n accessToken: string\n): void {\n apiClient.setOrgAuthHandler(async (orgAuthInfo: OrgAuthInfo): Promise<void> => {\n // Fast path: non-SSO org — join directly and extract the token.\n try {\n const orgToken = await tryDirectJoin(apiUrl, accessToken, orgAuthInfo);\n if (orgToken !== null) {\n // Set the token on the client so the SDK's fallback check (this.orgToken)\n // picks it up after the handler resolves (Node.js has no document.cookie).\n // Pass the org_uuid so the SDK can detect a stale token if the next\n // request targets a different org.\n apiClient.setOrgToken(orgToken, orgAuthInfo.orgUuid);\n return;\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr(`Warning: org direct-join failed (${msg}); trying browser auth`);\n }\n\n // Slow path: SSO org — the browser must complete the flow. Reject the\n // auth URL up-front if it doesn't match the configured API origin so a\n // hostile server can't pivot the OS URL opener to a `javascript:` /\n // `file://` / custom-scheme handler.\n if (!isAllowedAuthUrl(orgAuthInfo.authUrl, apiUrl)) {\n throw new Error(\n `Refusing to open organization auth URL: scheme/host does not match the configured API host. ` +\n `Re-run with the expected --api-url, or contact support.`\n );\n }\n\n stderr(`\\nThis workspace requires organization SSO authentication.`);\n stderr(`Opening browser to complete authentication...`);\n stderr(` ${orgAuthInfo.authUrl}\\n`);\n stderr(`If the browser does not open, visit the URL above manually.`);\n stderr(\n `After signing in, re-run the command — the CLI cannot receive the SSO token directly.`\n );\n openBrowser(orgAuthInfo.authUrl);\n\n // Reject after timeout so the CLI doesn't hang indefinitely.\n await new Promise<void>((_, reject) => {\n const t = setTimeout(\n () =>\n reject(\n new Error(\n 'Organization authentication timed out.\\n' +\n 'Please complete authentication in the browser, then re-run the command.'\n )\n ),\n ORG_AUTH_TIMEOUT_MS\n );\n // Unref so the timeout doesn't keep the Node.js event loop alive\n // if the parent process is otherwise done.\n t.unref?.();\n });\n });\n}\n","/** Optional DNS pin + audit headers for code-interpreter sandboxes. */\n\nimport { Agent, fetch as undiciFetch, type RequestInit as UndiciRequestInit } from 'undici';\n\nexport interface SandboxAuditHeaders {\n chatId?: number;\n sessionId?: string;\n toolCallId?: string;\n}\n\n/** Subset of sandbox env used when building fetch (kept here to avoid circular imports). */\nexport interface SandboxFetchEnv {\n apiUrl: string;\n apiIp?: string;\n chatId?: number;\n sessionId?: string;\n toolCallId?: string;\n}\n\n/**\n * Route API hostname traffic to a pinned private ENI IP when present.\n *\n * AgentCore sandboxes cannot reach the API ALB's public IPs; Python sandboxes\n * patch urllib3 at the socket layer. Node uses undici with `connect.servername`\n * so TLS SNI still matches the real hostname while the TCP connection targets\n * the pinned private IP (Host header is also set for HTTP routing).\n */\nexport function createPinnedFetch(apiUrl: string, apiIp?: string): typeof fetch {\n if (!apiIp) return fetch;\n\n let parsed: URL;\n try {\n parsed = new URL(apiUrl);\n } catch {\n return fetch;\n }\n const hostname = parsed.hostname;\n\n const dispatcher = new Agent({\n connect: {\n servername: hostname,\n },\n });\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n\n let reqUrl: URL;\n try {\n reqUrl = new URL(url, apiUrl);\n } catch {\n return fetch(input, init);\n }\n\n const headers = new Headers(init?.headers);\n if (reqUrl.hostname === hostname) {\n headers.set('Host', hostname);\n reqUrl = new URL(reqUrl.href);\n reqUrl.hostname = apiIp;\n }\n\n return undiciFetch(reqUrl, {\n ...(init as UndiciRequestInit | undefined),\n headers,\n dispatcher,\n }) as unknown as Promise<Response>;\n };\n}\n\nexport function withAuditHeaders(\n fetchFn: typeof fetch,\n headers: SandboxAuditHeaders\n): typeof fetch {\n const { chatId, sessionId, toolCallId } = headers;\n if (chatId === undefined && !sessionId && !toolCallId) {\n return fetchFn;\n }\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const reqHeaders = new Headers(init?.headers);\n if (chatId !== undefined) {\n reqHeaders.set('X-GR-Chat-Id', String(chatId));\n }\n if (sessionId) {\n reqHeaders.set('X-GR-Session-Id', sessionId);\n }\n if (toolCallId) {\n reqHeaders.set('X-GR-Tool-Call-Id', toolCallId);\n }\n return fetchFn(input, { ...init, headers: reqHeaders });\n };\n}\n\n/** Build fetch for sandbox sessions from explicit env (AgentCore-safe — no process.env). */\nexport function createSandboxFetch(env: SandboxFetchEnv): typeof fetch {\n let fetchFn = createPinnedFetch(env.apiUrl, env.apiIp);\n return withAuditHeaders(fetchFn, {\n chatId: env.chatId,\n sessionId: env.sessionId,\n toolCallId: env.toolCallId,\n });\n}\n\n/** Build fetch for sandbox sessions from GRAVITY_RAIL_* env vars. */\nexport function createSandboxFetchFromEnv(apiUrl: string): typeof fetch {\n const apiIp = process.env.GRAVITY_RAIL_API_IP;\n let fetchFn = createPinnedFetch(apiUrl, apiIp);\n\n const chatIdRaw = process.env.GRAVITY_RAIL_CHAT_ID;\n const chatId = chatIdRaw ? Number(chatIdRaw) : undefined;\n return withAuditHeaders(fetchFn, {\n chatId: chatId !== undefined && Number.isFinite(chatId) ? chatId : undefined,\n sessionId: process.env.GRAVITY_RAIL_SESSION_ID,\n toolCallId: process.env.GRAVITY_RAIL_TOOL_CALL_ID,\n });\n}\n","import { ApiClient as GravityRailClient } from '@gravity-rail/client';\nimport {\n CredentialsManager,\n getEnvironmentConfig,\n refreshAccessToken,\n type CLICredentials,\n type EnvironmentConfig,\n} from '../cli-utils';\nimport { homedir } from 'os';\nimport { detectOutputFormat, type OutputFormat } from './output';\nimport { loadDevCloudRealmFile, loadRealmCredentials } from './realm';\nimport { AuthRequiredError } from './errors';\nimport { registerOrgAuthHandler } from './org-auth';\nimport { createSandboxFetchFromEnv } from './pinned-fetch';\n\n/** Build an authenticated API client with the CLI org-auth handler registered. */\nfunction makeApiClient(accessToken: string, apiUrl: string): GravityRailClient {\n const fetchFn = createSandboxFetchFromEnv(apiUrl);\n const apiClient = new GravityRailClient(accessToken, apiUrl, fetchFn);\n registerOrgAuthHandler(apiClient, apiUrl, accessToken);\n return apiClient;\n}\n\n/** Try to silently refresh an expired access token. Returns an AuthenticatedContext or null. */\nasync function tryTokenRefresh(\n ctx: CommandContext,\n creds: CLICredentials\n): Promise<AuthenticatedContext | null> {\n if (!creds.refreshToken) return null;\n const refreshed = await refreshAccessToken(\n ctx.envConfig,\n creds,\n ctx.credentialsManager,\n ctx.env\n );\n if (!refreshed?.accessToken) return null;\n const apiClient = makeApiClient(refreshed.accessToken, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: refreshed.accessToken, apiClient };\n}\n\nexport interface GlobalOptions {\n env: string;\n realm?: string;\n /** Override API base URL (also: GRAVITY_RAIL_API_URL env var). */\n apiUrl?: string;\n outputFormat?: string;\n verbose?: boolean;\n allowWrite?: boolean;\n}\n\nexport interface PublicGlobalOptions {\n env?: string;\n apiUrl?: string;\n frontendUrl?: string;\n outputFormat?: string;\n verbose?: boolean;\n allowWrite?: boolean;\n}\n\nexport interface CommandContext {\n env: string;\n envConfig: EnvironmentConfig;\n outputFormat: OutputFormat;\n verbose: boolean;\n allowWrite: boolean;\n credentialsManager: CredentialsManager;\n}\n\nexport interface AuthenticatedContext extends CommandContext {\n accessToken: string;\n apiClient: GravityRailClient;\n realmWorkspace?: string;\n}\n\n/** Create a base command context (no auth required) */\nexport function createContext(opts: GlobalOptions): CommandContext {\n const baseConfig = getEnvironmentConfig(opts.env);\n const apiUrl = opts.apiUrl || process.env.GRAVITY_RAIL_API_URL || baseConfig.apiUrl;\n const envConfig = apiUrl === baseConfig.apiUrl ? baseConfig : { ...baseConfig, apiUrl };\n const credentialsManager = new CredentialsManager(homedir(), envConfig.apiUrl);\n return {\n env: opts.env,\n envConfig,\n outputFormat: detectOutputFormat(opts.outputFormat),\n verbose: opts.verbose ?? false,\n allowWrite: opts.allowWrite ?? false,\n credentialsManager,\n };\n}\n\n/** Create an authenticated command context. Tries realm, env var, then cached token. Never auto-triggers OAuth. */\nexport async function createAuthenticatedContext(\n opts: GlobalOptions\n): Promise<AuthenticatedContext> {\n // eslint-disable-next-line @eslint-react/naming-convention-context-name -- CLI handler context, not React\n const ctx = createContext(opts);\n\n // Try --realm first (dev-only shortcut using dev-realms.json)\n if (opts.realm) {\n let devRealmsPath: string | undefined;\n if (opts.env.startsWith('dev-cloud:')) {\n const namespace = opts.env.slice('dev-cloud:'.length);\n devRealmsPath = loadDevCloudRealmFile(namespace);\n }\n const { token, workspaceUuid } = loadRealmCredentials(opts.realm, devRealmsPath);\n const apiClient = makeApiClient(token, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: token, apiClient, realmWorkspace: workspaceUuid };\n }\n\n // Try GRAVITY_RAIL_API_KEY first\n const apiKey = process.env.GRAVITY_RAIL_API_KEY;\n if (apiKey) {\n const apiClient = makeApiClient(apiKey, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: apiKey, apiClient };\n }\n\n // Try cached credentials (from `gr login`)\n const creds = ctx.credentialsManager.load(ctx.env);\n if (creds?.accessToken) {\n const buffer = 5 * 60 * 1000;\n const notExpired =\n !creds.expiresAt || new Date(creds.expiresAt) > new Date(Date.now() + buffer);\n if (notExpired) {\n const apiClient = makeApiClient(creds.accessToken, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: creds.accessToken, apiClient };\n }\n\n // Token expired — try refresh\n const refreshed = await tryTokenRefresh(ctx, creds);\n if (refreshed) return refreshed;\n }\n\n throw new AuthRequiredError();\n}\n\n/**\n * Narrow a handler context to `AuthenticatedContext`.\n *\n * Handler `ctx` is typed as `AuthenticatedContext | CommandContext` so that\n * `requiresAuth: false` handlers can also share the type. At runtime, every\n * handler that did not opt out of auth will receive an `AuthenticatedContext`,\n * but TypeScript cannot verify this — call this helper before accessing\n * `apiClient` / `accessToken`.\n *\n * Throws if called from a handler that did not declare `requiresAuth`.\n */\nexport function requireAuth(ctx: AuthenticatedContext | CommandContext): AuthenticatedContext {\n if (!('apiClient' in ctx)) {\n throw new Error('Command handler accessed apiClient without declaring requiresAuth');\n }\n return ctx;\n}\n\n/** Create a base command context for the public CLI (defaults to prod) */\nexport function createPublicContext(opts: PublicGlobalOptions): CommandContext {\n const env = opts.env ?? 'prod';\n const envConfig = opts.apiUrl\n ? {\n apiUrl: opts.apiUrl,\n frontendUrl:\n opts.frontendUrl ||\n process.env.GRAVITY_RAIL_FRONTEND_URL ||\n 'https://app.gravityrail.com',\n }\n : getEnvironmentConfig(env);\n const credentialsManager = new CredentialsManager(homedir(), envConfig.apiUrl);\n return {\n env,\n envConfig,\n outputFormat: detectOutputFormat(opts.outputFormat),\n verbose: opts.verbose ?? false,\n allowWrite: opts.allowWrite ?? false,\n credentialsManager,\n };\n}\n\n/** Create an authenticated context for the public CLI. Tries env var, then cached token. */\nexport async function createPublicAuthenticatedContext(\n opts: PublicGlobalOptions\n): Promise<AuthenticatedContext> {\n const ctx = createPublicContext(opts);\n\n const apiKey = process.env.GRAVITY_RAIL_API_KEY;\n if (apiKey) {\n const apiClient = makeApiClient(apiKey, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: apiKey, apiClient };\n }\n\n const creds = ctx.credentialsManager.load(ctx.env);\n if (creds?.accessToken) {\n const buffer = 5 * 60 * 1000;\n const notExpired =\n !creds.expiresAt || new Date(creds.expiresAt) > new Date(Date.now() + buffer);\n if (notExpired) {\n const apiClient = makeApiClient(creds.accessToken, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: creds.accessToken, apiClient };\n }\n\n // Token expired — try refresh\n const refreshed = await tryTokenRefresh(ctx, creds);\n if (refreshed) return refreshed;\n }\n\n throw new AuthRequiredError();\n}\n","/**\n * Concierge API client — direct HTTP calls to the global concierge endpoints.\n *\n * The concierge is account-level (no workspace), so these bypass the ApiClient\n * which is workspace-oriented.\n */\n\nimport type { AuthenticatedContext } from './context';\n\nexport interface ConciergeChat {\n id: number;\n uuid: string;\n chatType: string;\n title: string | null;\n threadId: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ConciergeMessage {\n id: string;\n role: string;\n content: string;\n createdAt: string | null;\n toolCalls: any[] | null;\n toolCallId: string | null;\n}\n\nfunction baseUrl(ctx: AuthenticatedContext): string {\n return `${ctx.envConfig.apiUrl}/api/v2/concierge`;\n}\n\nfunction authHeaders(ctx: AuthenticatedContext): Record<string, string> {\n return {\n Authorization: `Bearer ${ctx.accessToken}`,\n 'Content-Type': 'application/json',\n };\n}\n\nfunction toCamelChat(raw: any): ConciergeChat {\n return {\n id: raw.id,\n uuid: raw.uuid,\n chatType: raw.chat_type,\n title: raw.title,\n threadId: raw.thread_id,\n createdAt: raw.created_at,\n updatedAt: raw.updated_at,\n };\n}\n\nfunction toCamelMessage(raw: any): ConciergeMessage {\n return {\n id: raw.id,\n role: raw.role,\n content: raw.content ?? '',\n createdAt: raw.createdAt ?? raw.created_at ?? null,\n toolCalls: raw.toolCalls ?? raw.tool_calls ?? null,\n toolCallId: raw.toolCallId ?? raw.tool_call_id ?? null,\n };\n}\n\nexport async function listConciergeChats(ctx: AuthenticatedContext): Promise<ConciergeChat[]> {\n const res = await fetch(`${baseUrl(ctx)}/chats`, { headers: authHeaders(ctx) });\n if (!res.ok) throw new Error(`Failed to list concierge chats: ${res.status}`);\n const data = await res.json();\n return (data as any[]).map(toCamelChat);\n}\n\nexport async function createConciergeChat(\n ctx: AuthenticatedContext,\n title?: string\n): Promise<ConciergeChat> {\n const res = await fetch(`${baseUrl(ctx)}/chats`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ title: title ?? null }),\n });\n if (!res.ok) throw new Error(`Failed to create concierge chat: ${res.status}`);\n return toCamelChat(await res.json());\n}\n\nexport async function getConciergeChat(\n ctx: AuthenticatedContext,\n chatId: number\n): Promise<ConciergeChat> {\n const res = await fetch(`${baseUrl(ctx)}/chats/${chatId}`, { headers: authHeaders(ctx) });\n if (!res.ok) throw new Error(`Failed to get concierge chat ${chatId}: ${res.status}`);\n return toCamelChat(await res.json());\n}\n\nexport interface ConciergeCallResult {\n callSid: string;\n startedAt: string;\n}\n\nexport interface ConciergeSmsResult {\n messageSid: string;\n conversationId: string;\n}\n\nexport async function originateConciergeCall(\n ctx: AuthenticatedContext,\n kind = 'concierge_setup'\n): Promise<ConciergeCallResult> {\n const res = await fetch(`${baseUrl(ctx)}/calls`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ kind }),\n });\n if (res.status === 412) {\n throw new Error('Your account phone is not verified. Run `gr account verify-phone` first.');\n }\n if (!res.ok) {\n const detail = await res.text();\n throw new Error(`Failed to start concierge call: ${res.status} ${detail}`);\n }\n return (await res.json()) as ConciergeCallResult;\n}\n\nexport async function originateConciergeSms(\n ctx: AuthenticatedContext,\n kind = 'concierge_setup'\n): Promise<ConciergeSmsResult> {\n const res = await fetch(`${baseUrl(ctx)}/sms`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ kind }),\n });\n if (res.status === 412) {\n throw new Error('Your account phone is not verified. Run `gr account verify-phone` first.');\n }\n if (!res.ok) {\n const detail = await res.text();\n throw new Error(`Failed to start concierge SMS: ${res.status} ${detail}`);\n }\n return (await res.json()) as ConciergeSmsResult;\n}\n\nexport async function startAccountPhoneVerify(\n ctx: AuthenticatedContext,\n phone: string\n): Promise<void> {\n const res = await fetch(`${ctx.envConfig.apiUrl}/api/v2/account/phone/verify/start`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ phone }),\n });\n if (!res.ok) {\n const detail = await res.text();\n throw new Error(`Failed to send verification code: ${res.status} ${detail}`);\n }\n}\n\nexport async function confirmAccountPhoneVerify(\n ctx: AuthenticatedContext,\n code: string\n): Promise<void> {\n const res = await fetch(`${ctx.envConfig.apiUrl}/api/v2/account/phone/verify/confirm`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ code }),\n });\n if (!res.ok) {\n const detail = await res.text();\n throw new Error(`Failed to confirm verification code: ${res.status} ${detail}`);\n }\n}\n\nexport async function getConciergeChatMessages(\n ctx: AuthenticatedContext,\n chatId: number\n): Promise<ConciergeMessage[]> {\n const res = await fetch(`${baseUrl(ctx)}/chats/${chatId}/messages`, {\n headers: authHeaders(ctx),\n });\n if (!res.ok)\n throw new Error(`Failed to get concierge messages for chat ${chatId}: ${res.status}`);\n const data = await res.json();\n return (data as any[]).map(toCamelMessage);\n}\n","/**\n * `gr account verify-phone` — verify account phone for concierge PSTN/SMS.\n */\n\nimport * as readline from 'node:readline/promises';\nimport { stdin as input, stdout as output } from 'node:process';\nimport { confirmAccountPhoneVerify, startAccountPhoneVerify } from '../lib/concierge-api';\nimport { requireAuth } from '../lib/context';\nimport type { CommandHandlerContext } from '../lib/types';\n\nconst TCPA_NOTICE =\n 'By verifying you agree to receive calls and SMS from Gravity Rail at this number.';\n\nexport async function accountVerifyPhoneCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const phoneArg = typeof hctx.args.phone === 'string' ? hctx.args.phone : undefined;\n\n process.stderr.write(`${TCPA_NOTICE}\\n`);\n\n const phone = phoneArg ?? (await promptLine('Phone number (E.164, e.g. +15551234567): '));\n if (!phone.trim()) {\n throw new Error('Phone number is required');\n }\n\n await startAccountPhoneVerify(ctx, phone.trim());\n process.stderr.write('Verification code sent via SMS.\\n');\n\n const code = await promptLine('Enter 6-digit code: ');\n await confirmAccountPhoneVerify(ctx, code.trim());\n process.stderr.write(\n 'Phone verified. You can use `gr concierge chat --call` or `gr concierge chat --sms`.\\n'\n );\n}\n\nasync function promptLine(question: string): Promise<string> {\n const rl = readline.createInterface({ input, output });\n try {\n return (await rl.question(question)) ?? '';\n } finally {\n rl.close();\n }\n}\n","import { execFile } from 'child_process';\nimport { stderr } from '../lib/output';\nimport type { AuthenticatedContext } from '../lib/context';\n\n/**\n * Open an authenticated browser session using the CLI's existing credentials.\n *\n * Flow:\n * 1. Get the current account's email from the CLI session\n * 2. Request a magic link via the API (token returned directly since caller is authenticated)\n * 3. Open the magic link URL in the default browser (or print it with --no-open)\n */\nexport async function authBrowserCommand(\n ctx: AuthenticatedContext,\n args: Record<string, unknown>\n): Promise<void> {\n const noOpen = Boolean(args['no-open']);\n\n // Get current account email\n const account = await ctx.apiClient.getUserAccount();\n if (!account.email) {\n process.stderr.write('Error: No email associated with current account\\n');\n process.exit(1);\n }\n\n // Request magic link — since we're authenticated, the API returns the token directly\n const response = await ctx.apiClient.requestMagicLink(account.email);\n\n if (!response.success || !response.magicLinkUrl) {\n process.stderr.write('Error: Failed to create magic link\\n');\n process.exit(1);\n }\n\n const url = response.magicLinkUrl;\n\n if (noOpen) {\n // Just print the URL to stdout for scripting/manual use\n process.stdout.write(url + '\\n');\n return;\n }\n\n // Open in default browser\n stderr(`Opening browser for ${account.email} (${ctx.env})...`);\n openUrl(url);\n stderr('Browser opened. Link expires in 15 minutes.');\n}\n\n/** Open a URL in the default browser (cross-platform). Uses execFile to avoid shell injection. */\nfunction openUrl(url: string): void {\n const platform = process.platform;\n\n let command: string;\n let args: string[];\n\n if (platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (platform === 'win32') {\n command = 'cmd.exe';\n args = ['/c', 'start', '', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n execFile(command, args, (err) => {\n if (err) {\n // Non-fatal — user can copy the URL from --no-open output\n process.stderr.write('Warning: Could not open browser automatically\\n');\n }\n });\n}\n","import type { ApiClient } from '@gravity-rail/client';\nimport type { Chat } from '@gravity-rail/sdk';\nimport { formatTimestamp, selectFromList } from '../cli-utils';\nimport { CLIError } from '../lib/errors';\nimport { requireAuth, type AuthenticatedContext } from '../lib/context';\nimport type { CommandHandlerContext } from '../lib/types';\nimport { buildCliConciergeAppContext } from '../lib/cli-client-context';\nimport { runChatSession, type ChatSession } from '../lib/chat-session';\n\n// ─── Entry point ─────────────────────────────────────────────────────────────\n\nexport async function manageCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const { workspace, args } = hctx;\n\n const asMember = typeof args['as-member'] === 'string' ? args['as-member'] : undefined;\n const chatIdArg = typeof args['chat-id'] === 'string' ? args['chat-id'] : undefined;\n const message = typeof args.message === 'string' ? args.message : undefined;\n\n const chat = await getOrCreateChat(ctx, workspace, chatIdArg, asMember, 'manager', !!message);\n const session = buildWorkspaceSession(ctx, workspace, chat, 'Workspace Manager', {\n appContext: buildCliConciergeAppContext(),\n allowWrite: true,\n trustCwd: !!args['trust-cwd'],\n trustDir: typeof args['trust-dir'] === 'string' ? args['trust-dir'] : undefined,\n });\n // Print the chat ID up-front so a user who Ctrl-Cs mid-stream can still\n // reattach with `gr manage --chat-id ${id}`. The post-session repeat\n // (after `runChatSession`) is intentional — a second \"Chat #N\" line on\n // clean exit gives copy/paste-friendly anchors at both ends of long\n // streams without any extra parsing.\n process.stderr.write(`Chat #${session.chatId}\\n`);\n await runChatSession(session, args);\n process.stderr.write(`Chat #${session.chatId}\\n`);\n}\n\nexport async function chatCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const { workspace, args } = hctx;\n const chatIdArg = typeof args['chat-id'] === 'string' ? args['chat-id'] : undefined;\n const workflowId = typeof args.workflow === 'string' ? args.workflow : undefined;\n const memberId = typeof args.member === 'string' ? args.member : undefined;\n\n let chat: Chat;\n if (chatIdArg) {\n const id = Number(chatIdArg);\n if (isNaN(id)) throw new CLIError('--chat-id must be a number');\n chat = await ctx.apiClient.getChat(workspace, id);\n } else if (workflowId) {\n chat = await createAssignmentChat(ctx.apiClient, workspace, Number(workflowId), memberId);\n } else if (memberId) {\n chat = await createMemberChat(ctx.apiClient, workspace, memberId);\n } else {\n throw new CLIError(\n 'Specify --workflow <id>, --member <id>, or --chat-id <id>.\\n' +\n 'Use \"gr manage\" for workspace manager chats.'\n );\n }\n\n const session = buildWorkspaceSession(ctx, workspace, chat, 'Chat');\n await runChatSession(session, args);\n}\n\n// ─── Session builder ─────────────────────────────────────────────────────────\n\nfunction buildWorkspaceSession(\n ctx: AuthenticatedContext,\n workspace: string,\n chat: Chat,\n label: string,\n extra?: Pick<ChatSession, 'appContext' | 'allowWrite' | 'trustCwd' | 'trustDir'>\n): ChatSession {\n const wsBase = ctx.envConfig.apiUrl.replace(/^https:/, 'wss:').replace(/^http:/, 'ws:');\n return {\n ctx,\n workspaceUuid: workspace,\n chatId: chat.id,\n chatUuid: chat.uuid,\n chatTitle: chat.title || chat.uuid,\n aguiEndpointUrl: `${ctx.envConfig.apiUrl}/api/v2/w/${workspace}/web-chat/${chat.id}/chat/agui`,\n wsUrl: `${wsBase}/api/v2/w/${workspace}/realtime/stream-ws`,\n loadMessages: () => ctx.apiClient.getChatMessages(workspace, chat.id, 50).catch(() => []),\n label,\n model: 'manager',\n ...extra,\n };\n}\n\n// ─── Chat selection ──────────────────────────────────────────────────────────\n\nasync function getOrCreateChat(\n ctx: AuthenticatedContext,\n workspace: string,\n chatIdArg: string | undefined,\n asMemberId: string | undefined,\n chatType: 'manager' | 'assignment' | 'member' | 'contributor' | 'developer',\n skipSelection: boolean = false\n): Promise<Chat> {\n if (chatIdArg) {\n const chatId = Number(chatIdArg);\n if (isNaN(chatId)) throw new CLIError('--chat-id must be a number');\n return ctx.apiClient.getChat(workspace, chatId);\n }\n\n if (skipSelection) {\n return createManagerChat(ctx.apiClient, workspace, asMemberId);\n }\n\n const chatsResponse = await ctx.apiClient.getChats(workspace, {\n chatType,\n sortBy: 'updatedAt',\n sortOrder: 'desc',\n pageSize: 20,\n });\n const chats = chatsResponse.items || [];\n\n const { item: selectedChat, isNew } = await selectFromList(chats, {\n title: 'Select a chat or create a new one',\n labelFn: (chat) => chat.title || `Chat ${chat.uuid.slice(0, 8)}...`,\n detailFn: (chat) => {\n const time = formatTimestamp(chat.updatedAt);\n const msgCount = chat.messageCount || 0;\n return `${msgCount} msg${msgCount !== 1 ? 's' : ''} - ${time}`;\n },\n emptyMessage: 'No existing chats.',\n allowNew: true,\n newLabel: '+ Start new chat',\n });\n\n if (!selectedChat && !isNew) {\n throw new CLIError('No chat selected.');\n }\n\n if (isNew) {\n return createManagerChat(ctx.apiClient, workspace, asMemberId);\n }\n return selectedChat!;\n}\n\nasync function createManagerChat(\n apiClient: ApiClient,\n workspace: string,\n asMemberId: string | undefined\n): Promise<Chat> {\n const data: Record<string, any> = {\n chatType: 'manager',\n channel: 'web-chat',\n };\n if (asMemberId) {\n data.memberId = Number(asMemberId);\n }\n const chat = await apiClient.createChat(workspace, data as any);\n process.stderr.write(`Created chat #${chat.id}\\n`);\n return chat;\n}\n\nasync function createAssignmentChat(\n apiClient: ApiClient,\n workspace: string,\n workflowId: number,\n asMemberId: string | undefined\n): Promise<Chat> {\n if (isNaN(workflowId)) throw new CLIError('--workflow must be a number');\n const data: Record<string, any> = {\n chatType: 'assignment',\n channel: 'web-chat',\n workflowId,\n };\n if (asMemberId) {\n data.memberId = Number(asMemberId);\n }\n const chat = await apiClient.createChat(workspace, data as any);\n process.stderr.write(`Created assignment chat #${chat.id} (workflow ${workflowId})\\n`);\n return chat;\n}\n\nasync function createMemberChat(\n apiClient: ApiClient,\n workspace: string,\n memberId: string\n): Promise<Chat> {\n const id = Number(memberId);\n if (isNaN(id)) throw new CLIError('--member must be a number');\n const data: Record<string, any> = {\n chatType: 'member',\n channel: 'web-chat',\n memberId: id,\n };\n const chat = await apiClient.createChat(workspace, data as any);\n process.stderr.write(`Created DM chat #${chat.id} (member ${memberId})\\n`);\n return chat;\n}\n","import path from 'path';\n\nexport interface ConciergeAppContextPayload {\n clientSurface: 'cli';\n cliContext: {\n shell?: string;\n os: string;\n cwdBasename: string;\n };\n channel: 'text';\n}\n\n/** Build ConciergeAppContext for AG-UI requests from the CLI. */\nexport function buildCliConciergeAppContext(): ConciergeAppContextPayload {\n const shell = process.env.SHELL ? path.basename(process.env.SHELL) : undefined;\n return {\n clientSurface: 'cli',\n channel: 'text',\n cliContext: {\n shell,\n os: process.platform,\n cwdBasename: path.basename(process.cwd()),\n },\n };\n}\n","/**\n * Shared chat session infrastructure.\n *\n * Defines the ChatSession abstraction consumed by all chat modes (text, realtime, voice).\n * Entry points (manage, chat, concierge) construct a ChatSession and pass it here.\n */\n\nimport {\n AGUIClient,\n clearScreen,\n getErrorMessage,\n getTextDelta,\n printMessage,\n type AGUIChatMessage,\n} from '../cli-utils';\nimport type { ConciergeAppContextPayload } from './cli-client-context';\nimport { runConciergeAguiLoop } from './concierge-agui-loop';\nimport * as readline from 'readline';\nimport { CLIError } from './errors';\nimport type { AuthenticatedContext } from './context';\nimport { RealtimeClient } from './realtime-client';\nimport { ChatTUI, type ChatItem } from './chat-tui';\nimport {\n checkSoxAvailable,\n listInputDevices,\n listOutputDevices,\n selectDevice,\n MicCapture,\n AudioPlayer,\n} from './audio';\n\n// ─── ChatSession abstraction ─────────────────────────────────────────────────\n\n/** Everything a chat mode needs — constructed differently per entry point. */\nexport interface ChatSession {\n ctx: AuthenticatedContext;\n workspaceUuid: string;\n chatId: number;\n chatUuid: string;\n chatTitle: string;\n aguiEndpointUrl: string;\n wsUrl: string;\n loadMessages: () => Promise<any[]>;\n /** Display label: \"Workspace Manager\", \"Concierge\", etc. */\n label: string;\n /** AGUI request model field. Undefined = omit from body. */\n model?: string;\n /** Concierge client context (CLI surface, etc.). */\n appContext?: ConciergeAppContextPayload;\n /** Whether --allow-write was passed (local file writes). */\n allowWrite?: boolean;\n /** Directory-trust flags for lazy local-file HITL. */\n trustCwd?: boolean;\n trustDir?: string;\n}\n\n// ─── Mode dispatcher ─────────────────────────────────────────────────────────\n\nexport async function runChatSession(\n session: ChatSession,\n args: Record<string, any>\n): Promise<void> {\n const debug = !!args.debug;\n const isVoice = !!args.voice;\n const isRealtime = !!args.realtime || isVoice;\n const message = typeof args.message === 'string' ? args.message : undefined;\n const autoApprove = !!args['auto-approve'];\n\n if (args['list-devices']) {\n await listAudioDevices();\n return;\n }\n\n if (!message && !process.stdin.isTTY) {\n throw new CLIError(\n 'Interactive mode requires a TTY. Use --message for non-interactive mode.'\n );\n }\n\n const allowWrite = !!args['allow-write'] || !!session.allowWrite;\n if (message) {\n await singleTurnChatSession(session, message, debug, autoApprove, allowWrite);\n } else if (isVoice) {\n await voiceChatSession(session, vadMode(args), args, debug);\n } else if (isRealtime) {\n await realtimeChatSession(session, vadMode(args), debug);\n } else {\n await interactiveChatSession(session, debug, autoApprove, allowWrite);\n }\n}\n\nexport function vadMode(args: Record<string, any>): 'client' | 'server' {\n return (typeof args.vad === 'string' ? args.vad : 'server') as 'client' | 'server';\n}\n\n// ─── Single-turn text mode (SSE) ────────────────────────────────────────────\n\nasync function singleTurnChatSession(\n session: ChatSession,\n message: string,\n debug: boolean,\n autoApprove: boolean = false,\n allowWrite: boolean = false\n): Promise<void> {\n const aguiClient = new AGUIClient({\n baseUrl: session.ctx.envConfig.apiUrl,\n workspaceUuid: session.workspaceUuid,\n chatId: session.chatId,\n endpointUrl: session.aguiEndpointUrl,\n accessToken: session.ctx.accessToken,\n debug,\n model: session.model,\n appContext: session.appContext,\n });\n\n // Stream all SSE events. The AGUI stream includes tool calls, tool\n // results, and text content across all inference turns. We accumulate\n // text and show tool call progress, then poll for final text if the\n // stream ended mid-turn (e.g. after tool calls with no final text).\n const onEvent = (event: { type?: string; name?: string }) => {\n const type = event.type?.toLowerCase() ?? '';\n if (type === 'tool_call_start') {\n const name =\n (event as Record<string, any>).toolCallName ??\n (event as Record<string, any>).name ??\n '';\n process.stderr.write(` [${name}]\\n`);\n }\n };\n\n const { streamText, hasToolCalls } = await runConciergeAguiLoop(\n aguiClient,\n [{ role: 'user', content: message }],\n onEvent,\n {\n autoApprove,\n allowWrite: allowWrite || !!session.allowWrite,\n debug,\n trustCwd: session.trustCwd,\n trustDir: session.trustDir,\n nonInteractive: true,\n }\n );\n\n // If we got text from the stream, print it\n if (streamText) {\n process.stdout.write(`\\x1B[32mAssistant:\\x1B[0m ${streamText}\\n`);\n return;\n }\n\n // No text in stream (tool calls only) — poll for the final response\n if (hasToolCalls) {\n process.stderr.write(' (waiting for completion...)\\n');\n const maxWaitMs = 180_000;\n const pollIntervalMs = 2000;\n const startTime = Date.now();\n let finalText = '';\n\n while (Date.now() - startTime < maxWaitMs) {\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n try {\n const msgs = await session.loadMessages();\n // Find the last assistant message with actual text\n for (let i = msgs.length - 1; i >= 0; i--) {\n const m = msgs[i];\n if (m.role === 'assistant' && m.content && !m.tool_calls?.length) {\n finalText = m.content;\n break;\n }\n }\n if (finalText) break;\n } catch {\n // keep polling\n }\n }\n\n process.stdout.write(`\\x1B[32mAssistant:\\x1B[0m ${finalText || '(no text response)'}\\n`);\n } else {\n process.stdout.write(`\\x1B[32mAssistant:\\x1B[0m (no response)\\n`);\n }\n}\n\n// ─── Interactive text mode (SSE) ─────────────────────────────────────────────\n\nasync function interactiveChatSession(\n session: ChatSession,\n debug: boolean,\n autoApprove: boolean,\n allowWrite: boolean\n): Promise<void> {\n const aguiClient = new AGUIClient({\n baseUrl: session.ctx.envConfig.apiUrl,\n workspaceUuid: session.workspaceUuid,\n chatId: session.chatId,\n endpointUrl: session.aguiEndpointUrl,\n accessToken: session.ctx.accessToken,\n debug,\n model: session.model,\n appContext: session.appContext,\n });\n\n clearScreen();\n console.log('='.repeat(60));\n console.log(session.label);\n console.log('='.repeat(60));\n console.log(`Chat: ${session.chatTitle}`);\n console.log(\"Type your message and press Enter. Type 'exit' or Ctrl+C to quit.\");\n console.log('='.repeat(60));\n console.log('');\n\n const existingMessages = await session.loadMessages();\n if (existingMessages.length > 0) {\n console.log('\\x1B[90m--- Previous messages ---\\x1B[0m\\n');\n for (const msg of existingMessages.slice(-10)) {\n const text = typeof msg.content === 'string' ? msg.content : '';\n if (text && text.trim()) {\n printMessage(text, msg.role as 'user' | 'assistant' | 'system');\n }\n }\n console.log('\\x1B[90m--- End of history ---\\x1B[0m\\n');\n }\n\n const conversationMessages: AGUIChatMessage[] = [];\n for (const msg of existingMessages.slice(-10)) {\n const text = typeof msg.content === 'string' ? msg.content : '';\n if (text && text.trim() && (msg.role === 'user' || msg.role === 'assistant')) {\n conversationMessages.push({ role: msg.role, content: text });\n }\n }\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n\n return new Promise<void>((resolve) => {\n const prompt = (): void => {\n rl.question('\\x1B[34mYou:\\x1B[0m ', async (input) => {\n const trimmed = input.trim();\n if (!trimmed) {\n prompt();\n return;\n }\n if (trimmed.toLowerCase() === 'exit' || trimmed.toLowerCase() === 'quit') {\n console.log('\\nGoodbye!');\n rl.close();\n return;\n }\n\n conversationMessages.push({ role: 'user', content: trimmed });\n process.stdout.write('\\n\\x1B[32mAssistant:\\x1B[0m ');\n let assistantContent = '';\n\n try {\n const { streamText } = await runConciergeAguiLoop(\n aguiClient,\n conversationMessages,\n (event) => {\n const delta = getTextDelta(event);\n if (delta) {\n process.stdout.write(delta);\n assistantContent += delta;\n }\n const errorMsg = getErrorMessage(event);\n if (errorMsg) console.log(`\\n\\x1B[31mError: ${errorMsg}\\x1B[0m`);\n },\n {\n autoApprove,\n allowWrite: allowWrite || !!session.allowWrite,\n debug,\n trustCwd: session.trustCwd,\n trustDir: session.trustDir,\n }\n );\n if (streamText && !assistantContent) {\n assistantContent = streamText;\n process.stdout.write(streamText);\n }\n if (assistantContent) {\n conversationMessages.push({ role: 'assistant', content: assistantContent });\n }\n console.log('\\n');\n } catch (error) {\n console.log(\n `\\n\\x1B[31mError: ${error instanceof Error ? error.message : error}\\x1B[0m\\n`\n );\n }\n\n prompt();\n });\n };\n\n rl.on('close', () => {\n console.log('\\nGoodbye!');\n resolve();\n });\n prompt();\n });\n}\n\n// ─── Shared helpers for realtime modes ───────────────────────────────────────\n\nexport function buildHistory(messages: any[]): ChatItem[] {\n const history: ChatItem[] = [];\n for (const msg of messages.slice(-30)) {\n const text = typeof msg.content === 'string' ? msg.content : '';\n if (msg.role === 'user' || msg.role === 'assistant') {\n if (text.trim()) {\n history.push({ role: msg.role, content: text });\n }\n if (msg.role === 'assistant' && msg.tool_calls) {\n for (const tc of msg.tool_calls) {\n history.push({\n kind: 'tool_call',\n id: tc.id,\n name: tc.function.name,\n args: tc.function.arguments || '',\n done: true,\n });\n }\n }\n } else if (msg.role === 'tool') {\n const toolName = (msg as any).name || 'tool';\n history.push({\n kind: 'tool_result',\n toolCallId: (msg as any).tool_call_id || '',\n toolName,\n content: text,\n });\n }\n }\n return history;\n}\n\nexport function wireRealtimeEvents(client: RealtimeClient, tui: ChatTUI): void {\n client.on('text_start', () => tui.streamStart());\n client.on('text_delta', (data: any) => tui.streamDelta(data.delta));\n client.on('text_end', () => tui.streamEnd());\n\n client.on('tool_call_start', (data: any) => {\n tui.toolCallStart(data.toolCallId, data.toolCallName);\n });\n client.on('tool_call_args', (data: any) => {\n tui.toolCallArgs(data.toolCallId, data.delta);\n });\n client.on('tool_call_end', (data: any) => {\n tui.toolCallEnd(data.toolCallId);\n });\n client.on('tool_call_result', (data: any) => {\n const toolName = tui.findToolCallName(data.toolCallId);\n const content = typeof data.result === 'string' ? data.result : JSON.stringify(data.result);\n tui.toolCallResult(data.toolCallId, toolName, content);\n });\n\n client.on('run_error', (data: any) => {\n tui.showError(data.message);\n });\n\n client.on('error', (err: Error) => {\n tui.showError(`Connection: ${err.message}`);\n });\n\n client.on('ws_recv', (msg: any) => tui.logDebug('in', msg));\n client.on('ws_send', (msg: any) => tui.logDebug('out', msg));\n}\n\n// ─── Realtime text mode (WebSocket + TUI) ────────────────────────────────────\n\nasync function realtimeChatSession(\n session: ChatSession,\n vad: 'client' | 'server',\n debug: boolean\n): Promise<void> {\n const client = new RealtimeClient({\n url: session.wsUrl,\n token: session.ctx.accessToken,\n chatId: session.chatId,\n vadMode: vad,\n debug,\n });\n\n process.stderr.write(`Connecting to ${session.label.toLowerCase()}...\\n`);\n\n try {\n await client.connect();\n } catch (err) {\n throw new CLIError(`Failed to connect: ${err instanceof Error ? err.message : err}`);\n }\n\n const existingMessages = await session.loadMessages();\n const history = buildHistory(existingMessages);\n\n const tui = new ChatTUI({\n onSend: (text) => {\n client.sendTextMessage(text);\n },\n onExit: () => {\n client.close();\n },\n debug,\n env: session.ctx.env,\n });\n\n wireRealtimeEvents(client, tui);\n\n client.on('closed', () => {\n tui.stop();\n console.log('Disconnected.');\n });\n\n tui.loadHistory(history);\n tui.start();\n\n await new Promise<void>((resolve) => {\n client.once('closed', resolve);\n });\n}\n\n// ─── Voice mode (WebSocket + mic + speaker + TUI) ────────────────────────────\n\nasync function voiceChatSession(\n session: ChatSession,\n vad: 'client' | 'server',\n args: Record<string, string | boolean | undefined>,\n debug: boolean\n): Promise<void> {\n if (!checkSoxAvailable()) {\n throw new CLIError(\n 'Voice mode requires SoX. Install it:\\n' +\n ' macOS: brew install sox\\n' +\n ' Linux: apt install sox\\n' +\n ' Windows: choco install sox'\n );\n }\n\n const inputDeviceName =\n typeof args['input-device'] === 'string' ? args['input-device'] : undefined;\n const outputDeviceName =\n typeof args['output-device'] === 'string' ? args['output-device'] : undefined;\n\n let inputDeviceId: string | undefined;\n let outputDeviceId: string | undefined;\n\n if (!inputDeviceName || !outputDeviceName) {\n process.stderr.write('\\n Audio Devices\\n');\n }\n\n if (inputDeviceName) {\n inputDeviceId = inputDeviceName;\n } else {\n const inputDevices = await listInputDevices();\n const selected = await selectDevice(inputDevices, 'Input (microphone)');\n inputDeviceId = selected.id;\n }\n\n if (outputDeviceName) {\n outputDeviceId = outputDeviceName;\n } else {\n const outputDevices = await listOutputDevices();\n const selected = await selectDevice(outputDevices, 'Output (speaker)');\n outputDeviceId = selected.id;\n }\n\n const client = new RealtimeClient({\n url: session.wsUrl,\n token: session.ctx.accessToken,\n chatId: session.chatId,\n vadMode: vad,\n debug,\n });\n\n process.stderr.write(`\\nConnecting to ${session.label.toLowerCase()}...\\n`);\n\n try {\n await client.connect();\n } catch (err) {\n throw new CLIError(`Failed to connect: ${err instanceof Error ? err.message : err}`);\n }\n\n const existingMessages = await session.loadMessages();\n const history = buildHistory(existingMessages);\n\n const mic = new MicCapture((pcm16) => {\n if (!client.isConnected()) return;\n client.sendAudio(pcm16);\n });\n const player = new AudioPlayer(outputDeviceId);\n\n function cleanup(): void {\n mic.stop();\n player.stop();\n client.close();\n }\n\n const tui = new ChatTUI({\n onSend: (text) => {\n client.sendTextMessage(text);\n },\n onExit: () => {\n cleanup();\n },\n debug,\n env: session.ctx.env,\n });\n\n wireRealtimeEvents(client, tui);\n\n client.on('audio', (data: any) => {\n player.write(data.pcm16);\n });\n\n client.on('audio_end', (data: any) => {\n player.endResponse(data?.messageId);\n });\n\n client.on('interrupt', () => {\n const playbackMs = player.getPlaybackTimeMs();\n const messageId = player.playingMessageId;\n\n if (playbackMs !== null && playbackMs > 0 && player.isPlaying) {\n client.sendInterrupt(playbackMs, messageId);\n player.stop();\n\n if (debug) {\n tui.logDebug('in', {\n type: 'CUSTOM',\n name: 'voice.interrupt',\n value: { action: 'echoed', audioEndMs: playbackMs, messageId },\n });\n }\n } else if (debug) {\n tui.logDebug('in', {\n type: 'CUSTOM',\n name: 'voice.interrupt',\n value: { action: 'ignored', wasPlaying: player.isPlaying },\n });\n }\n });\n\n client.on('truncate', (data: any) => {\n player.stop();\n tui.truncateAssistant(\n data.content ?? '',\n data.originalContent,\n data.truncationReason ?? 'barge_in',\n data.truncatedAtMs\n );\n });\n\n client.on('response_message', (data: any) => {\n if (data.role === 'user' && data.content) {\n tui.addTranscription(data.content);\n }\n });\n\n client.on('closed', () => {\n tui.stop();\n cleanup();\n console.log('Disconnected.');\n });\n\n tui.loadHistory(history);\n tui.start();\n\n mic.start(inputDeviceId);\n\n await new Promise<void>((resolve) => {\n client.once('closed', resolve);\n });\n}\n\n// ─── Device listing ──────────────────────────────────────────────────────────\n\nexport async function listAudioDevices(): Promise<void> {\n if (!checkSoxAvailable()) {\n throw new CLIError(\n 'Device listing requires SoX. Install it:\\n' +\n ' macOS: brew install sox\\n' +\n ' Linux: apt install sox\\n' +\n ' Windows: choco install sox'\n );\n }\n\n const inputs = await listInputDevices();\n const outputs = await listOutputDevices();\n\n console.log('Input devices (microphone):');\n for (const dev of inputs) {\n const marker = dev.isDefault ? ' (default)' : '';\n console.log(` ${dev.id}: ${dev.name}${marker}`);\n }\n\n console.log('\\nOutput devices (speaker):');\n for (const dev of outputs) {\n const marker = dev.isDefault ? ' (default)' : '';\n console.log(` ${dev.id}: ${dev.name}${marker}`);\n }\n}\n","/**\n * Concierge AG-UI turn loop with HITL resume (local files, present_choice).\n */\n\nimport {\n AGUIClient,\n getErrorMessage,\n getTextDelta,\n type AGUIEvent,\n type ChatMessage as AGUIChatMessage,\n} from '../cli-utils/agui';\nimport { extractHumanInputRequest, handleCliHitlInterrupt } from './cli-hitl';\n\nconst MAX_HITL_ROUNDS = 25;\n\nexport async function runConciergeAguiLoop(\n client: AGUIClient,\n initialMessages: AGUIChatMessage[],\n onEvent: (event: AGUIEvent) => void,\n opts: {\n autoApprove: boolean;\n allowWrite: boolean;\n debug?: boolean;\n trustCwd?: boolean;\n trustDir?: string;\n nonInteractive?: boolean;\n }\n): Promise<{ streamText: string; hasToolCalls: boolean }> {\n let streamText = '';\n let hasToolCalls = false;\n let resume: { resumeValue: string; resumeInterruptId?: string } | undefined;\n\n for (let round = 0; round < MAX_HITL_ROUNDS; round++) {\n let hitlPayload: unknown = null;\n\n await client.streamRequest(\n resume\n ? {\n messages: [],\n resumeValue: resume.resumeValue,\n resumeInterruptId: resume.resumeInterruptId,\n }\n : { messages: initialMessages },\n (event) => {\n onEvent(event);\n const delta = getTextDelta(event);\n if (delta) streamText += delta;\n const type = event.type?.toLowerCase() ?? '';\n if (type === 'tool_call_start') hasToolCalls = true;\n const errorMsg = getErrorMessage(event);\n if (errorMsg) process.stderr.write(`\\x1B[31mError: ${errorMsg}\\x1B[0m\\n`);\n const hitl = extractHumanInputRequest(event as Record<string, unknown>);\n if (hitl) hitlPayload = hitl;\n },\n { autoApprove: opts.autoApprove }\n );\n\n if (!hitlPayload) {\n break;\n }\n\n const next = await handleCliHitlInterrupt(hitlPayload, {\n allowWrite: opts.allowWrite,\n autoApprove: opts.autoApprove,\n trustCwd: opts.trustCwd,\n trustDir: opts.trustDir,\n nonInteractive: opts.nonInteractive,\n });\n if (!next) {\n process.stderr.write(\n ' [HITL] Unsupported interrupt in CLI — open app.gravityrail.com/setup to continue.\\n'\n );\n break;\n }\n resume = next;\n streamText = '';\n }\n\n return { streamText, hasToolCalls };\n}\n","/**\n * Handle concierge HITL interrupts in the CLI (local file ops, etc.).\n */\n\nimport readline from 'readline';\nimport {\n executeCliLocalFileAction,\n isCliLocalFileInterrupt,\n type CliLocalFileInterrupt,\n} from './local-files';\nimport { resolveDirectoryTrust } from './trusted-dirs';\n\nexport type { CliLocalFileInterrupt };\n\nexport interface HitlResumePayload {\n resumeValue: string;\n resumeInterruptId?: string;\n}\n\nexport function extractHumanInputRequest(event: Record<string, unknown>): unknown | null {\n const type = String(event.type ?? '').toUpperCase();\n if (type === 'CUSTOM' && event.name === 'human_input_request') {\n return event.value;\n }\n if (event.name === 'human_input_request') {\n return event.value;\n }\n return null;\n}\n\nexport async function handleCliHitlInterrupt(\n value: unknown,\n opts: {\n allowWrite: boolean;\n autoApprove: boolean;\n trustCwd?: boolean;\n trustDir?: string;\n /** When true, skip the trust prompt and fail if the directory is untrusted. */\n nonInteractive?: boolean;\n }\n): Promise<HitlResumePayload | null> {\n if (!value || typeof value !== 'object') return null;\n const payload = value as Record<string, unknown>;\n\n if (isCliLocalFileInterrupt(payload)) {\n const interrupt = payload as CliLocalFileInterrupt;\n if (typeof payload.interrupt_id === 'string') {\n interrupt.interrupt_id = payload.interrupt_id;\n }\n return handleCliLocalFile(interrupt, opts);\n }\n\n if (payload.type === 'present_choice') {\n return handlePresentChoiceTerminal(payload);\n }\n\n return null;\n}\n\nasync function handleCliLocalFile(\n interrupt: CliLocalFileInterrupt,\n opts: {\n allowWrite: boolean;\n trustCwd?: boolean;\n trustDir?: string;\n nonInteractive?: boolean;\n }\n): Promise<HitlResumePayload> {\n const trust = await resolveDirectoryTrust({\n cwd: process.cwd(),\n trustCwd: opts.trustCwd,\n trustDir: opts.trustDir,\n // Interactive sessions: prompt on first local-file use (review feedback).\n nonInteractive: opts.nonInteractive ?? process.stdin.isTTY !== true,\n });\n if (trust !== 'trusted') {\n return {\n resumeValue: JSON.stringify({\n ok: false,\n error: 'Directory not trusted for local file access. Re-run with --trust-cwd or --trust-dir <path>, or approve trust interactively when prompted.',\n }),\n resumeInterruptId: interrupt.interrupt_id,\n };\n }\n\n process.stderr.write(`\\n[local ${interrupt.action}] ${interrupt.path}\\n`);\n const result = executeCliLocalFileAction(process.cwd(), interrupt, {\n allowWrite: opts.allowWrite,\n });\n return {\n resumeValue: JSON.stringify(result),\n resumeInterruptId: interrupt.interrupt_id,\n };\n}\n\nasync function handlePresentChoiceTerminal(\n payload: Record<string, unknown>\n): Promise<HitlResumePayload | null> {\n const prompt =\n (typeof payload.user_prompt === 'string' && payload.user_prompt) ||\n (typeof payload.description === 'string' && payload.description) ||\n 'Choose an option';\n const markup = typeof payload.openui_markup === 'string' ? payload.openui_markup : '';\n process.stderr.write(`\\n${prompt}\\n`);\n if (markup) {\n process.stderr.write(`${markup.slice(0, 2000)}\\n`);\n }\n if (!process.stdin.isTTY) {\n return {\n resumeValue: '',\n resumeInterruptId:\n typeof payload.interrupt_id === 'string' ? payload.interrupt_id : undefined,\n };\n }\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n const answer = await new Promise<string>((resolve) => {\n rl.question('Your choice (value): ', resolve);\n });\n rl.close();\n return {\n resumeValue: answer.trim(),\n resumeInterruptId:\n typeof payload.interrupt_id === 'string' ? payload.interrupt_id : undefined,\n };\n}\n","/**\n * Sandboxed local filesystem operations for CLI-executed concierge tools.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nconst DEFAULT_MAX_READ_BYTES = 50_000;\nconst ABSOLUTE_MAX_READ_BYTES = 1_000_000;\n\nexport interface CliLocalFileInterrupt {\n type: 'cli_local_file';\n action: 'read_file' | 'list_dir' | 'write_file';\n path: string;\n content?: string;\n max_bytes?: number;\n interrupt_id?: string;\n}\n\nexport interface CliLocalFileResult {\n ok: boolean;\n content?: string;\n error?: string;\n}\n\nfunction resolveSafePath(root: string, relativePath: string): string | null {\n const rootResolved = path.resolve(root);\n const target = path.resolve(rootResolved, relativePath || '.');\n if (target !== rootResolved && !target.startsWith(rootResolved + path.sep)) {\n return null;\n }\n // Reject any component along the path that is a symlink — `path.resolve`\n // does not follow symlinks but `fs.statSync`/`readFileSync` do, so a\n // symlink inside the trusted dir could otherwise read or write a file\n // outside of it. ``lstatSync`` reports the link itself and never the\n // target.\n let cursor = rootResolved;\n const rest = path.relative(rootResolved, target);\n if (rest && rest !== '.') {\n for (const segment of rest.split(path.sep)) {\n cursor = path.join(cursor, segment);\n try {\n const lstat = fs.lstatSync(cursor);\n if (lstat.isSymbolicLink()) {\n return null;\n }\n } catch {\n // Missing path components are fine — the caller decides what to do\n // with a non-existent target.\n break;\n }\n }\n }\n return target;\n}\n\nexport function executeCliLocalFileAction(\n root: string,\n interrupt: CliLocalFileInterrupt,\n opts: { allowWrite: boolean }\n): CliLocalFileResult {\n const safe = resolveSafePath(root, interrupt.path);\n if (!safe) {\n return { ok: false, error: 'Path escapes trusted directory' };\n }\n\n try {\n switch (interrupt.action) {\n case 'read_file': {\n if (!fs.existsSync(safe)) {\n return { ok: false, error: 'File not found' };\n }\n const stat = fs.lstatSync(safe);\n if (stat.isSymbolicLink()) {\n return { ok: false, error: 'Path escapes trusted directory' };\n }\n if (!stat.isFile()) {\n return { ok: false, error: 'Not a file' };\n }\n const requested = Number.isFinite(interrupt.max_bytes)\n ? Math.max(1, Math.min(Number(interrupt.max_bytes), ABSOLUTE_MAX_READ_BYTES))\n : DEFAULT_MAX_READ_BYTES;\n if (stat.size > requested) {\n const buf = fs.readFileSync(safe, { encoding: 'utf8' });\n return {\n ok: true,\n content: buf.slice(0, requested) + `\\n\\n[truncated at ${requested} bytes]`,\n };\n }\n return { ok: true, content: fs.readFileSync(safe, 'utf8') };\n }\n case 'list_dir': {\n if (!fs.existsSync(safe)) {\n return { ok: false, error: 'Directory not found' };\n }\n const entries = fs.readdirSync(safe, { withFileTypes: true });\n const lines = entries\n .slice(0, 200)\n .map((e) => (e.isDirectory() ? `${e.name}/` : e.name));\n if (entries.length > 200) {\n lines.push(`... and ${entries.length - 200} more`);\n }\n return { ok: true, content: lines.join('\\n') };\n }\n case 'write_file': {\n if (!opts.allowWrite) {\n return { ok: false, error: 'Write requires --allow-write' };\n }\n if (interrupt.content === undefined) {\n return { ok: false, error: 'Missing content for write_file' };\n }\n fs.mkdirSync(path.dirname(safe), { recursive: true });\n fs.writeFileSync(safe, interrupt.content, 'utf8');\n return { ok: true, content: 'written' };\n }\n default:\n return { ok: false, error: `Unknown action: ${interrupt.action}` };\n }\n } catch (e) {\n return { ok: false, error: sanitizeLocalFileError(e) };\n }\n}\n\nfunction sanitizeLocalFileError(e: unknown): string {\n if (e && typeof e === 'object' && 'code' in e) {\n const code = (e as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') return 'File or directory not found';\n if (code === 'EACCES' || code === 'EPERM') return 'Permission denied';\n if (code === 'EISDIR') return 'Not a file';\n if (code === 'ENOTDIR') return 'Not a directory';\n }\n return 'Local file operation failed';\n}\n\nexport function isCliLocalFileInterrupt(value: unknown): value is CliLocalFileInterrupt {\n if (typeof value !== 'object' || value === null) return false;\n const v = value as Record<string, unknown>;\n return v.type === 'cli_local_file' && typeof v.action === 'string' && typeof v.path === 'string';\n}\n","/**\n * Directory-trust store for CLI file-capable surfaces.\n *\n * Separates input trust from --allow-write (output mutations). Trust is\n * path-keyed (VS Code workspace-trust model): a grant applies to the directory\n * path, not to individual file contents — new files dropped into a trusted path\n * are readable without re-prompting.\n *\n * See docs/public/cli-get-started.md and gr-feedback trust-directory spec.\n */\n\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport readline from 'readline';\n\nexport type DirectoryTrustDecision = 'once' | 'always' | 'denied';\n\nexport type DirectoryTrustStatus = 'trusted' | 'denied';\n\nexport interface TrustedDirsStore {\n version: 1;\n /** Absolute paths the user chose \"trust always\" for. */\n always: string[];\n}\n\nconst STORE_VERSION = 1 as const;\n\nfunction storePath(): string {\n const base =\n process.env.XDG_CONFIG_HOME ??\n (process.platform === 'win32'\n ? path.join(process.env.APPDATA ?? os.homedir(), 'gravityrail')\n : path.join(os.homedir(), '.config', 'gravityrail'));\n return path.join(base, 'trusted-dirs.json');\n}\n\nexport function loadTrustedDirsStore(): TrustedDirsStore {\n const file = storePath();\n try {\n const raw = JSON.parse(fs.readFileSync(file, 'utf8')) as TrustedDirsStore;\n if (raw?.version === STORE_VERSION && Array.isArray(raw.always)) {\n return { version: STORE_VERSION, always: raw.always.map((p) => path.resolve(p)) };\n }\n } catch {\n // Missing or corrupt — treat as empty.\n }\n return { version: STORE_VERSION, always: [] };\n}\n\nfunction saveTrustedDirsStore(store: TrustedDirsStore): void {\n const file = storePath();\n const dir = path.dirname(file);\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n fs.writeFileSync(file, JSON.stringify(store, null, 2) + '\\n', { mode: 0o600 });\n}\n\nexport function isDirectoryTrusted(dirPath: string, opts?: { trustCwdFlag?: boolean }): boolean {\n if (opts?.trustCwdFlag) return true;\n const resolved = path.resolve(dirPath);\n const store = loadTrustedDirsStore();\n return store.always.includes(resolved);\n}\n\nasync function promptTrustInteractive(dirPath: string): Promise<DirectoryTrustDecision> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n const question = (q: string) => new Promise<string>((resolve) => rl.question(q, resolve));\n\n process.stderr.write(\n `\\nGravity Rail may read files in:\\n ${dirPath}\\n\\n` +\n `File contents can influence the assistant. Do you trust the files in this directory?\\n` +\n ` [1] Trust once (this session)\\n` +\n ` [2] Trust always (remember for this path)\\n` +\n ` [3] No — do not read local files\\n\\n` +\n `Choice [1/2/3] (default 3): `\n );\n const answer = (await question('')).trim() || '3';\n rl.close();\n\n if (answer === '1') return 'once';\n if (answer === '2') return 'always';\n return 'denied';\n}\n\nconst sessionTrusted = new Set<string>();\n\nexport interface DirectoryTrustOptions {\n cwd?: string;\n /** Explicit grant for CI/headless — trust files in this absolute path. */\n trustDir?: string;\n /** Explicit grant — trust process.cwd(). */\n trustCwd?: boolean;\n nonInteractive?: boolean;\n}\n\n/**\n * Resolve directory trust before local file tools run. Does not throw — callers\n * return a tool error to the model when status is `denied`.\n */\nexport async function resolveDirectoryTrust(\n opts: DirectoryTrustOptions\n): Promise<DirectoryTrustStatus> {\n const dir = path.resolve(opts.trustDir ?? opts.cwd ?? process.cwd());\n\n if (isDirectoryTrusted(dir, { trustCwdFlag: opts.trustCwd })) return 'trusted';\n if (sessionTrusted.has(dir)) return 'trusted';\n\n // --trust-dir <path> grants trust for that path (headless escape hatch).\n if (opts.trustDir && path.resolve(opts.trustDir) === dir) {\n sessionTrusted.add(dir);\n return 'trusted';\n }\n\n if (opts.trustCwd) {\n sessionTrusted.add(dir);\n return 'trusted';\n }\n\n if (!process.stdin.isTTY || opts.nonInteractive) {\n return 'denied';\n }\n\n const decision = await promptTrustInteractive(dir);\n if (decision === 'denied') {\n return 'denied';\n }\n if (decision === 'always') {\n const store = loadTrustedDirsStore();\n if (!store.always.includes(dir)) {\n store.always.push(dir);\n saveTrustedDirsStore(store);\n }\n }\n sessionTrusted.add(dir);\n return 'trusted';\n}\n\n/** @deprecated Use resolveDirectoryTrust — kept for tests migrating off session-start gates. */\nexport async function requireDirectoryTrust(opts: DirectoryTrustOptions): Promise<void> {\n const { CLIError } = await import('./errors');\n const dir = path.resolve(opts.trustDir ?? opts.cwd ?? process.cwd());\n const status = await resolveDirectoryTrust(opts);\n if (status === 'trusted') return;\n\n throw new CLIError(\n `Directory not trusted: ${dir}\\n\\n` +\n `Re-run with --trust-cwd (or --trust-dir <path>) after reviewing files in that directory, ` +\n `or run interactively to approve trust when a local file tool is first used.`\n );\n}\n","/**\n * WebSocket-based AG-UI Realtime Client for CLI\n *\n * Handles the AG-UI protocol over WebSocket for realtime voice and text\n * interactions with the Workspace Manager. Adapted from the browser\n * implementation in src/components/voice/ws-unified.ts.\n *\n * Uses the native WebSocket global (Node.js 22+).\n */\n\nimport { EventEmitter } from 'events';\n\n// AG-UI event format over WebSocket\ninterface AGUIWebSocketEvent {\n type: string;\n name?: string;\n value?: any;\n messageId?: string;\n delta?: string;\n role?: string;\n message?: string;\n code?: string;\n toolCallId?: string;\n toolCallName?: string;\n [key: string]: any;\n}\n\nexport interface RealtimeClientOptions {\n /** WebSocket URL (wss://...) */\n url: string;\n /** JWT access token for authentication */\n token: string;\n /** Chat ID to connect to (null to create a new chat) */\n chatId: number | null;\n /** VAD mode: 'server' (default) or 'client' */\n vadMode?: 'client' | 'server';\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Realtime WebSocket client for AG-UI protocol.\n *\n * Events:\n * - connected: Login success with chat/member/assistant IDs\n * - audio: Received audio PCM16 buffer\n * - text_start/text_delta/text_end: Streaming text message\n * - transcription: User speech transcription\n * - response_message: Full message object\n * - tool_call_start/tool_call_args/tool_call_end: Tool calls\n * - run_error: Run error from server\n * - error: Connection/protocol error\n * - closed: WebSocket closed\n */\nexport class RealtimeClient extends EventEmitter {\n private ws: WebSocket | null = null;\n private connected = false;\n private options: Required<RealtimeClientOptions>;\n\n constructor(options: RealtimeClientOptions) {\n super();\n this.options = {\n vadMode: 'server',\n debug: false,\n ...options,\n };\n }\n\n /** Connect to the realtime WebSocket endpoint */\n connect(): Promise<void> {\n if (typeof globalThis.WebSocket === 'undefined') {\n return Promise.reject(\n new Error('WebSocket not available. Node.js 22+ is required for realtime mode.')\n );\n }\n\n return new Promise((resolve, reject) => {\n const params = new URLSearchParams();\n if (this.options.vadMode) {\n params.append('vad', this.options.vadMode);\n }\n const url = params.toString()\n ? `${this.options.url}?${params.toString()}`\n : this.options.url;\n\n if (this.options.debug) {\n process.stderr.write(`[debug] Connecting to ${url}\\n`);\n }\n\n this.ws = new WebSocket(url);\n\n this.ws.onerror = (event: Event) => {\n const msg = event instanceof ErrorEvent ? event.message : 'WebSocket connection failed';\n if (!this.connected) {\n reject(new Error(msg));\n } else {\n this.emit('error', new Error(msg));\n }\n };\n\n this.ws.onclose = (event: CloseEvent) => {\n const reason = event.code === 1006 ? 'Connection lost' : event.reason || 'Closed';\n this.connected = false;\n this.emit('closed', { reason, code: event.code });\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n try {\n const data = typeof event.data === 'string' ? event.data : event.data.toString();\n const parsed: AGUIWebSocketEvent = JSON.parse(data);\n this.emit('ws_recv', parsed);\n this.handleEvent(parsed);\n } catch {\n if (this.options.debug) {\n process.stderr.write(`[debug] Failed to parse message\\n`);\n }\n }\n };\n\n this.ws.onopen = () => {\n if (this.options.debug) {\n process.stderr.write('[debug] WebSocket connected, sending login\\n');\n }\n this.sendCustom('voice.login', {\n token: this.options.token,\n chat_id: this.options.chatId,\n vad: this.options.vadMode,\n });\n };\n\n // Wait for login_success or timeout\n const timeout = setTimeout(() => {\n if (!this.connected) {\n this.close();\n reject(new Error('Connection timeout - no login response within 10s'));\n }\n }, 10000);\n\n this.once('connected', () => {\n clearTimeout(timeout);\n resolve();\n });\n\n this.once('error', () => {\n clearTimeout(timeout);\n });\n });\n }\n\n private handleEvent(event: AGUIWebSocketEvent): void {\n switch (event.type) {\n case 'CUSTOM':\n this.handleCustomEvent(event.name || '', event.value);\n break;\n\n case 'TEXT_MESSAGE_START':\n this.emit('text_start', { messageId: event.messageId || '' });\n break;\n case 'TEXT_MESSAGE_CONTENT':\n this.emit('text_delta', {\n messageId: event.messageId || '',\n delta: event.delta || '',\n });\n break;\n case 'TEXT_MESSAGE_END':\n this.emit('text_end', { messageId: event.messageId || '' });\n break;\n\n case 'TOOL_CALL_START':\n this.emit('tool_call_start', {\n toolCallId: event.toolCallId || '',\n toolCallName: event.toolCallName || '',\n });\n break;\n case 'TOOL_CALL_ARGS':\n this.emit('tool_call_args', {\n toolCallId: event.toolCallId || '',\n delta: event.delta || '',\n });\n break;\n case 'TOOL_CALL_END':\n this.emit('tool_call_end', { toolCallId: event.toolCallId || '' });\n break;\n case 'TOOL_CALL_RESULT':\n this.emit('tool_call_result', {\n toolCallId: event.toolCallId || '',\n result: event.result,\n });\n break;\n\n case 'RUN_STARTED':\n this.emit('run_started', { runId: event.runId });\n break;\n case 'RUN_FINISHED':\n this.emit('run_finished', { runId: event.runId });\n break;\n case 'RUN_ERROR':\n this.emit('run_error', {\n message: event.message || 'Unknown error',\n code: event.code,\n });\n break;\n\n default:\n if (this.options.debug) {\n process.stderr.write(`[debug] Unknown event type: ${event.type}\\n`);\n }\n }\n }\n\n private handleCustomEvent(name: string, value: any): void {\n switch (name) {\n case 'voice.login_success':\n this.connected = true;\n this.emit('connected', {\n chatId: value?.chat_id,\n memberId: value?.member_id,\n assistantId: value?.assistant_id,\n });\n break;\n\n case 'voice.audio':\n if (value?.data) {\n const pcm16 = Buffer.from(value.data, 'base64');\n this.emit('audio', { pcm16, messageId: value.message_id });\n }\n break;\n\n case 'voice.audio_begin':\n this.emit('audio_begin', { messageId: value?.message_id });\n break;\n case 'voice.audio_end':\n this.emit('audio_end', { messageId: value?.message_id });\n break;\n\n case 'voice.interrupt':\n this.emit('interrupt', { messageId: value?.message_id });\n break;\n\n case 'voice.response_message':\n if (value) {\n this.emit('response_message', value);\n }\n break;\n\n case 'voice.transcription':\n if (value) {\n this.emit('transcription', { text: value.text, role: value.role });\n }\n break;\n\n case 'voice.truncate':\n if (value) {\n this.emit('truncate', {\n messageId: value.message_id,\n content: value.content,\n originalContent: value.original_content,\n truncationReason: value.truncation_reason || 'barge_in',\n truncatedAtMs: value.audio_end_ms,\n });\n }\n break;\n\n case 'app.data_update':\n case 'app.navigation':\n case 'app.notification':\n break;\n\n default:\n if (this.options.debug) {\n process.stderr.write(`[debug] Unknown CUSTOM event: ${name}\\n`);\n }\n }\n }\n\n private sendCustom(name: string, value?: any): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n return;\n }\n const event: AGUIWebSocketEvent = { type: 'CUSTOM', name };\n if (value !== undefined) {\n event.value = value;\n }\n this.emit('ws_send', event);\n this.ws.send(JSON.stringify(event));\n }\n\n /** Send raw PCM16 audio data (will be base64-encoded) */\n sendAudio(pcm16: Buffer): void {\n this.sendCustom('voice.audio', {\n data: pcm16.toString('base64'),\n format: 'pcm16',\n sample_rate: 24000,\n });\n }\n\n /** Signal the start of an audio utterance */\n sendAudioBegin(messageId: string): void {\n this.sendCustom('voice.audio_begin', { message_id: messageId });\n }\n\n /** Signal the end of an audio utterance */\n sendAudioEnd(): void {\n this.sendCustom('voice.audio_end');\n }\n\n /** Send a text message (triggers AI inference) */\n sendTextMessage(content: string): void {\n this.sendCustom('voice.user_message', {\n message: { role: 'user', content },\n });\n }\n\n /** Send interrupt signal with playback position */\n sendInterrupt(audioEndMs: number, messageId?: string): void {\n this.sendCustom('voice.interrupt', {\n audio_end_ms: audioEndMs,\n message_id: messageId,\n });\n }\n\n /** Check if the client is connected */\n isConnected(): boolean {\n return this.connected && this.ws?.readyState === WebSocket.OPEN;\n }\n\n /** Close the connection */\n close(): void {\n this.connected = false;\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n}\n","/**\n * Chat TUI — terminal chat interface using ANSI escape codes.\n *\n * Layout (normal):\n * Rows 1..R-2: Message area (full width)\n * Row R-1: Separator + hints\n * Row R: Input (\"You: ...\")\n *\n * Layout (debug):\n * Rows 1..R-2: Chat (left) │ Debug log (right)\n * Row R-1: Separator + hints\n * Row R: Input (\"You: ...\")\n *\n * Keyboard:\n * Up/Down Scroll 1 line\n * Page Up/Down Scroll 1 page\n * Ctrl+B Page up (less-style)\n * Ctrl+F Page down (less-style)\n * Home/End Top / bottom\n * Ctrl+O Toggle detail expansion (tool calls + debug messages)\n * Ctrl+D Toggle debug panel (when --debug)\n * Ctrl+C / exit Quit\n *\n * Mouse:\n * Scroll wheel Scroll 3 lines\n *\n * Zero external dependencies — only Node.js built-ins.\n */\n\nimport { createWriteStream, type WriteStream } from 'fs';\n\n// ─── Public types ─────────────────────────────────────────────────────────────\n\nexport interface ChatMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n /** Reason the message was truncated (voice interruption) */\n truncationReason?: string;\n /** Ms offset where truncation occurred */\n truncatedAtMs?: number;\n /** The full original content before truncation */\n originalContent?: string;\n}\n\nexport interface ChatTUIOptions {\n /** Called when the user sends a message */\n onSend: (text: string) => void;\n /** Called when the user exits (Ctrl+C, 'exit', 'quit') */\n onExit: () => void;\n /** Enable debug panel showing WebSocket traffic */\n debug?: boolean;\n /** Environment name (e.g. 'dev', 'staging', 'prod') — controls debug log file creation */\n env?: string;\n}\n\n// ─── Item types ───────────────────────────────────────────────────────────────\n\nexport interface ToolCallItem {\n kind: 'tool_call';\n id: string;\n name: string;\n args: string;\n done: boolean;\n}\n\nexport interface ToolResultItem {\n kind: 'tool_result';\n toolCallId: string;\n toolName: string;\n content: string;\n}\n\nexport type ChatItem = ChatMessage | ToolCallItem | ToolResultItem;\n\nfunction isToolCall(item: ChatItem): item is ToolCallItem {\n return 'kind' in item && (item as ToolCallItem).kind === 'tool_call';\n}\n\nfunction isToolResult(item: ChatItem): item is ToolResultItem {\n return 'kind' in item && (item as ToolResultItem).kind === 'tool_result';\n}\n\n/** Friendly label for truncation reason */\nfunction getTruncationLabel(reason: string, truncatedAtMs?: number): string {\n const timeStr = truncatedAtMs ? ` at ${(truncatedAtMs / 1000).toFixed(1)}s` : '';\n switch (reason) {\n case 'barge_in':\n return `interrupted: user spoke${timeStr}`;\n case 'client_interrupt':\n return `interrupted${timeStr}`;\n case 'user_cancel':\n return `cancelled by user${timeStr}`;\n case 'error':\n return `error${timeStr}`;\n default:\n return `interrupted${timeStr}`;\n }\n}\n\n/** Extract the unspoken portion of a truncated message */\nfunction getExtraContent(\n content: string | undefined,\n originalContent: string | undefined\n): string | null {\n if (!content || !originalContent) return null;\n const stripped = content.replace(/—interrupted$/, '');\n if (originalContent.startsWith(stripped)) {\n const extra = originalContent.slice(stripped.length);\n return extra.length > 0 ? extra : null;\n }\n return originalContent !== content ? originalContent : null;\n}\n\n// ─── Debug log entry ──────────────────────────────────────────────────────────\n\ninterface DebugEntry {\n direction: 'in' | 'out';\n summary: string; // one-line summary (always shown)\n detail: string; // full JSON (shown when expanded)\n ts: string; // HH:MM:SS\n}\n\n// ─── ANSI helpers ─────────────────────────────────────────────────────────────\n\nconst CSI = '\\x1B[';\nconst HIDE_CURSOR = `${CSI}?25l`;\nconst SHOW_CURSOR = `${CSI}?25h`;\nconst ALT_SCREEN_ON = `${CSI}?1049h`;\nconst ALT_SCREEN_OFF = `${CSI}?1049l`;\nconst CLEAR_EOL = `${CSI}K`;\nconst RESET = `${CSI}0m`;\nconst MOUSE_ON = `${CSI}?1000h${CSI}?1006h`; // Button events + SGR extended\nconst MOUSE_OFF = `${CSI}?1000l${CSI}?1006l`;\n\nconst BLUE = `${CSI}34m`;\nconst GREEN = `${CSI}32m`;\nconst GRAY = `${CSI}90m`;\nconst YELLOW = `${CSI}33m`;\nconst ORANGE = `${CSI}38;5;208m`; // 256-color orange — inbound\nconst LIGHT_BLUE = `${CSI}38;5;117m`; // 256-color light blue — outbound\nconst DIM = `${CSI}2m`;\nconst DIM_ITALIC_GRAY = `${CSI}2;3;90m`; // dim + italic + gray\n\nfunction moveTo(row: number, col: number): string {\n return `${CSI}${row};${col}H`;\n}\n\n// ─── ChatTUI ──────────────────────────────────────────────────────────────────\n\nexport class ChatTUI {\n private items: ChatItem[] = [];\n private inputBuffer = '';\n private isStreaming = false;\n private streamContent = '';\n private scrollOffset = 0;\n private expandDetails = false;\n private rows = 24;\n private cols = 80;\n private started = false;\n private renderTimer: ReturnType<typeof setTimeout> | null = null;\n private displayLinesCache: string[] | null = null;\n private debugLinesCache: string[] | null = null;\n private options: ChatTUIOptions;\n\n // Debug panel state\n private debugEntries: DebugEntry[] = [];\n private debugPanelVisible = false;\n private debugLogStream: WriteStream | null = null;\n\n // Escape sequence accumulator for raw stdin parsing\n private escBuf = '';\n private escTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: ChatTUIOptions) {\n this.options = options;\n this.debugPanelVisible = !!options.debug;\n }\n\n /** Whether the debug panel is currently being rendered */\n private get debugVisible(): boolean {\n return this.debugPanelVisible;\n }\n\n // ─── Lifecycle ──────────────────────────────────────────────────────\n\n start(): void {\n this.updateDimensions();\n process.stdout.write(ALT_SCREEN_ON + MOUSE_ON);\n process.stdout.write(`${CSI}1;${Math.max(1, this.rows - 2)}r`);\n\n // Raw mode + direct data handler (not readline — we parse escape seqs ourselves)\n process.stdin.setEncoding('utf8');\n if (process.stdin.isTTY) process.stdin.setRawMode(true);\n process.stdin.on('data', this.onData);\n process.stdin.resume();\n\n process.stdout.on('resize', this.onResize);\n process.on('exit', this.restoreTerminal);\n\n // Debug log file — only write to disk in dev/staging (never in prod to avoid PHI on disk)\n if (this.options.debug && this.options.env !== 'prod') {\n this.debugLogStream = createWriteStream('gr-cli-realtime-debug.log', { flags: 'a' });\n this.debugLogStream.write(`\\n--- session ${new Date().toISOString()} ---\\n`);\n }\n\n this.started = true;\n this.render();\n }\n\n stop(): void {\n if (!this.started) return;\n this.started = false;\n if (this.renderTimer) {\n clearTimeout(this.renderTimer);\n this.renderTimer = null;\n }\n this.clearEsc();\n if (this.debugLogStream) {\n this.debugLogStream.end();\n this.debugLogStream = null;\n }\n this.restoreTerminal();\n process.stdout.removeListener('resize', this.onResize);\n process.stdin.removeListener('data', this.onData);\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n process.stdin.pause();\n process.removeListener('exit', this.restoreTerminal);\n }\n\n // ─── Chat state ────────────────────────────────────────────────────\n\n loadHistory(items: ChatItem[]): void {\n this.items = items.filter((item) => (isToolCall(item) ? true : item.content?.trim()));\n this.dirty();\n }\n\n streamStart(): void {\n this.isStreaming = true;\n this.streamContent = '';\n this.scrollOffset = 0;\n this.dirty();\n }\n\n streamDelta(delta: string): void {\n this.streamContent += delta;\n this.dirty();\n }\n\n streamEnd(): void {\n if (this.streamContent.trim()) {\n this.items.push({ role: 'assistant', content: this.streamContent });\n }\n this.isStreaming = false;\n this.streamContent = '';\n this.dirty();\n }\n\n toolCallStart(id: string, name: string): void {\n this.items.push({ kind: 'tool_call', id, name, args: '', done: false });\n this.dirty();\n }\n\n toolCallArgs(id: string, delta: string): void {\n const tc = this.findToolCall(id);\n if (tc) {\n tc.args += delta;\n this.dirty();\n }\n }\n\n toolCallEnd(id: string): void {\n const tc = this.findToolCall(id);\n if (tc) {\n tc.done = true;\n this.dirty();\n }\n }\n\n /** Add a transcription of the user's spoken words (voice mode) */\n addTranscription(text: string): void {\n this.items.push({ role: 'user', content: text });\n this.scrollOffset = 0;\n this.dirty();\n }\n\n /**\n * Truncate the most recent assistant message (voice interruption).\n * Replaces its content with the spoken portion and stores the original.\n */\n truncateAssistant(\n content: string,\n originalContent: string | undefined,\n reason: string,\n truncatedAtMs?: number\n ): void {\n // If currently streaming, commit the stream first\n if (this.isStreaming) {\n this.isStreaming = false;\n this.streamContent = '';\n }\n\n // Find the last assistant message and update it\n for (let i = this.items.length - 1; i >= 0; i--) {\n const item = this.items[i]!;\n if ('role' in item && item.role === 'assistant') {\n item.content = content;\n item.truncationReason = reason;\n item.truncatedAtMs = truncatedAtMs;\n item.originalContent = originalContent;\n this.dirty();\n return;\n }\n }\n\n // No existing assistant message — push the truncated content\n this.items.push({\n role: 'assistant',\n content,\n truncationReason: reason,\n truncatedAtMs: truncatedAtMs,\n originalContent,\n });\n this.dirty();\n }\n\n toolCallResult(toolCallId: string, toolName: string, content: string): void {\n this.items.push({ kind: 'tool_result', toolCallId, toolName, content });\n this.dirty();\n }\n\n /** Find the tool name for a given tool call ID */\n findToolCallName(toolCallId: string): string {\n for (let i = this.items.length - 1; i >= 0; i--) {\n const item = this.items[i]!;\n if (isToolCall(item) && item.id === toolCallId) return item.name;\n }\n return 'tool';\n }\n\n showError(msg: string): void {\n this.items.push({ role: 'system', content: `Error: ${msg}` });\n this.dirty();\n }\n\n // ─── Debug panel ──────────────────────────────────────────────────\n\n /** Log a WebSocket message to the debug panel and (optionally) log file */\n logDebug(direction: 'in' | 'out', raw: any): void {\n const redacted = redactAudio(raw);\n const now = new Date();\n const ts = `${pad2(now.getHours())}:${pad2(now.getMinutes())}:${pad2(now.getSeconds())}`;\n\n // Write to log file (JSON lines, with full redacted payload)\n if (this.debugLogStream) {\n const logLine = JSON.stringify({ ts: now.toISOString(), dir: direction, ...redacted });\n this.debugLogStream.write(logLine + '\\n');\n }\n\n // Add to in-memory debug panel\n const summary = buildDebugSummary(direction, redacted);\n let detail: string;\n try {\n detail = JSON.stringify(redacted, null, 2);\n } catch {\n detail = String(redacted);\n }\n this.debugEntries.push({ direction, summary, detail, ts });\n // Cap at 500 entries to prevent memory growth\n if (this.debugEntries.length > 500) {\n this.debugEntries = this.debugEntries.slice(-300);\n }\n this.debugLinesCache = null;\n this.dirty();\n }\n\n // ─── Private helpers ──────────────────────────────────────────────\n\n private findToolCall(id: string): ToolCallItem | undefined {\n for (let i = this.items.length - 1; i >= 0; i--) {\n const item = this.items[i]!;\n if (isToolCall(item) && item.id === id) return item;\n }\n return undefined;\n }\n\n private dirty(): void {\n this.displayLinesCache = null;\n this.debugLinesCache = null;\n this.scheduleRender();\n }\n\n private restoreTerminal = (): void => {\n process.stdout.write(`${MOUSE_OFF}${CSI}r${ALT_SCREEN_OFF}${SHOW_CURSOR}`);\n };\n\n private updateDimensions(): void {\n this.rows = process.stdout.rows || 24;\n this.cols = process.stdout.columns || 80;\n }\n\n /** Width of the chat (left) panel */\n private chatWidth(): number {\n if (!this.debugVisible) return this.cols;\n // 60% for chat, 40% for debug, with 1 col for divider\n return Math.max(30, Math.floor(this.cols * 0.6) - 1);\n }\n\n /** Width of the debug (right) panel */\n private debugWidth(): number {\n if (!this.debugVisible) return 0;\n return this.cols - this.chatWidth() - 1; // -1 for divider\n }\n\n private scrollHeight(): number {\n return Math.max(1, this.rows - 2);\n }\n\n private pageSize(): number {\n return Math.max(1, this.rows - 4);\n }\n\n // ─── Scroll ───────────────────────────────────────────────────────\n\n private scrollUp(lines: number): void {\n const total = this.getDisplayLines().length;\n const max = Math.max(0, total - this.scrollHeight());\n this.scrollOffset = Math.min(max, this.scrollOffset + lines);\n this.render();\n }\n\n private scrollDown(lines: number): void {\n this.scrollOffset = Math.max(0, this.scrollOffset - lines);\n this.render();\n }\n\n private scrollToTop(): void {\n const total = this.getDisplayLines().length;\n this.scrollOffset = Math.max(0, total - this.scrollHeight());\n this.render();\n }\n\n private scrollToBottom(): void {\n this.scrollOffset = 0;\n this.render();\n }\n\n // ─── Raw stdin parsing ────────────────────────────────────────────\n //\n // We parse stdin directly instead of using readline.emitKeypressEvents\n // because readline doesn't understand SGR mouse sequences and leaks\n // their contents into keypress events as regular characters.\n\n private onData = (data: string): void => {\n for (let i = 0; i < data.length; i++) {\n const ch = data[i]!;\n\n // Accumulating an escape sequence\n if (this.escBuf) {\n this.escBuf += ch;\n\n if (this.escBuf.length === 2) {\n if (ch !== '[') {\n // Not a CSI sequence (Alt+key etc.) — discard\n this.clearEsc();\n }\n continue;\n }\n\n // \\x1B[... — wait for a terminating character (letter or ~)\n if (/[A-Za-z~]/.test(ch)) {\n this.handleCSI(this.escBuf.slice(2, -1), ch);\n this.clearEsc();\n } else if (this.escBuf.length > 32) {\n this.clearEsc(); // safety bail\n }\n continue;\n }\n\n // Start of escape sequence\n if (ch === '\\x1B') {\n this.escBuf = '\\x1B';\n this.escTimer = setTimeout(() => {\n // Bare ESC with no follow-up — ignore\n this.escBuf = '';\n this.escTimer = null;\n }, 100);\n continue;\n }\n\n // Regular byte\n this.handleByte(ch);\n }\n };\n\n private clearEsc(): void {\n this.escBuf = '';\n if (this.escTimer) {\n clearTimeout(this.escTimer);\n this.escTimer = null;\n }\n }\n\n /** Handle a parsed CSI sequence: params is everything between \\x1B[ and the final char */\n private handleCSI(params: string, code: string): void {\n // Mouse SGR: \\x1B[<button;col;rowM (press) or m (release)\n if (params.startsWith('<') && (code === 'M' || code === 'm')) {\n if (code === 'm') return; // ignore button release\n const parts = params.slice(1).split(';');\n if (parts.length >= 1) {\n const button = parseInt(parts[0]!, 10);\n if (button === 64) this.scrollUp(3);\n else if (button === 65) this.scrollDown(3);\n }\n return;\n }\n\n // Arrow keys (no params)\n if (!params) {\n if (code === 'A') {\n this.scrollUp(1);\n return;\n }\n if (code === 'B') {\n this.scrollDown(1);\n return;\n }\n // Home/End (xterm-style)\n if (code === 'H') {\n this.scrollToTop();\n return;\n }\n if (code === 'F') {\n this.scrollToBottom();\n return;\n }\n }\n\n // Tilde sequences: Page Up (5~), Page Down (6~), Home (1~), End (4~)\n if (code === '~') {\n if (params === '5') {\n this.scrollUp(this.pageSize());\n return;\n }\n if (params === '6') {\n this.scrollDown(this.pageSize());\n return;\n }\n if (params === '1') {\n this.scrollToTop();\n return;\n }\n if (params === '4') {\n this.scrollToBottom();\n return;\n }\n }\n }\n\n /** Handle a single non-escape byte */\n private handleByte(ch: string): void {\n const code = ch.charCodeAt(0);\n\n // Ctrl+C → exit\n if (code === 0x03) {\n this.stop();\n this.options.onExit();\n return;\n }\n\n // Ctrl+B → page up (less-style)\n if (code === 0x02) {\n this.scrollUp(this.pageSize());\n return;\n }\n\n // Ctrl+F → page down (less-style)\n if (code === 0x06) {\n this.scrollDown(this.pageSize());\n return;\n }\n\n // Ctrl+D → toggle debug panel visibility (always available)\n if (code === 0x04) {\n this.debugPanelVisible = !this.debugPanelVisible;\n this.displayLinesCache = null;\n this.debugLinesCache = null;\n this.render();\n return;\n }\n\n // Ctrl+O → toggle detail expansion (tool calls + debug messages)\n if (code === 0x0f) {\n this.expandDetails = !this.expandDetails;\n this.displayLinesCache = null;\n this.debugLinesCache = null;\n this.render();\n return;\n }\n\n // Enter\n if (code === 0x0d) {\n this.handleEnter();\n return;\n }\n\n // Backspace (0x7F on most terminals, 0x08 on some)\n if (code === 0x7f || code === 0x08) {\n if (this.inputBuffer.length > 0) {\n this.inputBuffer = this.inputBuffer.slice(0, -1);\n this.renderInputLine();\n }\n return;\n }\n\n // Ignore other control characters\n if (code < 0x20) return;\n\n // Printable character → add to input\n this.inputBuffer += ch;\n this.renderInputLine();\n }\n\n private handleEnter(): void {\n const text = this.inputBuffer.trim();\n this.inputBuffer = '';\n if (!text) {\n this.renderInputLine();\n return;\n }\n if (text.toLowerCase() === 'exit' || text.toLowerCase() === 'quit') {\n this.stop();\n this.options.onExit();\n return;\n }\n this.items.push({ role: 'user', content: text });\n this.scrollOffset = 0;\n this.displayLinesCache = null;\n this.render();\n this.options.onSend(text);\n }\n\n // ─── Events ───────────────────────────────────────────────────────\n\n private onResize = (): void => {\n this.updateDimensions();\n process.stdout.write(`${CSI}1;${Math.max(1, this.rows - 2)}r`);\n this.displayLinesCache = null;\n this.debugLinesCache = null;\n this.render();\n };\n\n // ─── Rendering ────────────────────────────────────────────────────\n\n private scheduleRender(): void {\n if (!this.started || this.renderTimer) return;\n this.renderTimer = setTimeout(() => {\n this.renderTimer = null;\n this.render();\n }, 30);\n }\n\n private getDisplayLines(): string[] {\n if (!this.displayLinesCache) {\n this.displayLinesCache = this.buildDisplayLines();\n }\n return this.displayLinesCache;\n }\n\n private getDebugLines(): string[] {\n if (!this.debugLinesCache) {\n this.debugLinesCache = this.buildDebugLines();\n }\n return this.debugLinesCache;\n }\n\n private render(): void {\n if (!this.started) return;\n this.updateDimensions();\n\n const sh = this.scrollHeight();\n const displayLines = this.getDisplayLines();\n const total = displayLines.length;\n\n // Clamp scroll offset\n const maxOff = Math.max(0, total - sh);\n if (this.scrollOffset > maxOff) this.scrollOffset = maxOff;\n\n // Select visible slice for chat\n let visible: string[];\n if (total <= sh) {\n visible = [...new Array<string>(sh - total).fill(''), ...displayLines];\n } else {\n const end = total - this.scrollOffset;\n const start = end - sh;\n visible = displayLines.slice(start, end);\n }\n\n const buf: string[] = [HIDE_CURSOR];\n\n if (this.debugVisible) {\n this.renderSplitScreen(buf, visible, sh);\n } else {\n for (let i = 0; i < sh; i++) {\n buf.push(moveTo(i + 1, 1), visible[i] || '', CLEAR_EOL);\n }\n }\n\n // Separator with hints (row R-1)\n buf.push(moveTo(this.rows - 1, 1), this.buildSeparator(), CLEAR_EOL);\n\n // Input (row R)\n buf.push(moveTo(this.rows, 1), `${BLUE}You:${RESET} ${this.inputBuffer}${CLEAR_EOL}`);\n\n buf.push(SHOW_CURSOR);\n process.stdout.write(buf.join(''));\n }\n\n private renderSplitScreen(buf: string[], chatVisible: string[], sh: number): void {\n const cw = this.chatWidth();\n const dw = this.debugWidth();\n const divCol = cw + 1;\n\n // Debug panel: auto-scroll to bottom (always show latest)\n const debugLines = this.getDebugLines();\n const debugTotal = debugLines.length;\n let debugVisible: string[];\n if (debugTotal <= sh) {\n debugVisible = [...new Array<string>(sh - debugTotal).fill(''), ...debugLines];\n } else {\n debugVisible = debugLines.slice(debugTotal - sh);\n }\n\n for (let i = 0; i < sh; i++) {\n const chatLine = truncateAnsi(chatVisible[i] || '', cw);\n const debugLine = truncateAnsi(debugVisible[i] || '', dw);\n buf.push(\n moveTo(i + 1, 1),\n chatLine,\n CLEAR_EOL, // clear to end handles rest, but we need to position divider\n moveTo(i + 1, divCol),\n `${DIM}\\u2502${RESET}`,\n debugLine\n );\n // Clear remainder of the debug area\n buf.push(CLEAR_EOL);\n }\n }\n\n private renderInputLine(): void {\n process.stdout.write(\n `${moveTo(this.rows, 1)}${BLUE}You:${RESET} ${this.inputBuffer}${CLEAR_EOL}`\n );\n }\n\n // ─── Separator ────────────────────────────────────────────────────\n\n private buildSeparator(): string {\n const hints: string[] = [];\n\n if (this.scrollOffset > 0) {\n hints.push(`\\u2191${this.scrollOffset}`);\n }\n\n const hasDetails =\n this.items.some((i) => isToolCall(i) || isToolResult(i)) || this.options.debug;\n if (hasDetails) {\n hints.push(`^O ${this.expandDetails ? 'collapse' : 'details'}`);\n }\n\n if (this.options.debug) {\n hints.push(`^D ${this.debugPanelVisible ? 'hide' : 'show'} debug`);\n }\n\n const lineWidth = Math.min(this.cols, 60);\n\n if (!hints.length) {\n return `${GRAY}${'\\u2500'.repeat(lineWidth)}${RESET}`;\n }\n\n const hintStr = ` ${hints.join(' ')} `;\n const dashes = Math.max(0, lineWidth - hintStr.length);\n const left = Math.max(2, Math.floor(dashes / 2));\n const right = Math.max(2, dashes - left);\n return `${GRAY}${'\\u2500'.repeat(left)}${hintStr}${'\\u2500'.repeat(right)}${RESET}`;\n }\n\n // ─── Chat display line building ───────────────────────────────────\n\n private buildDisplayLines(): string[] {\n const lines: string[] = [];\n const w = this.chatWidth();\n\n for (const item of this.items) {\n if (isToolCall(item)) {\n this.appendToolCallLines(lines, item, w);\n } else if (isToolResult(item)) {\n this.appendToolResultLines(lines, item, w);\n } else {\n this.appendMessageLines(lines, item, w);\n }\n lines.push('');\n }\n\n if (this.isStreaming) {\n this.appendStreamLines(lines, w);\n }\n\n return lines;\n }\n\n private appendToolCallLines(lines: string[], tc: ToolCallItem, width: number): void {\n const status = tc.done ? 'Called' : 'Calling';\n const summary = ` ${GRAY}${status} ${tc.name}${tc.done ? '' : '...'}${RESET}`;\n\n if (!this.expandDetails) {\n lines.push(summary);\n return;\n }\n\n lines.push(summary);\n if (tc.args) {\n let formatted = tc.args;\n try {\n formatted = JSON.stringify(JSON.parse(tc.args), null, 2);\n } catch {\n // use raw\n }\n const indent = ' ';\n for (const argLine of formatted.split('\\n')) {\n for (const wl of this.wrapText(argLine, width - indent.length)) {\n lines.push(`${indent}${GRAY}${wl}${RESET}`);\n }\n }\n }\n }\n\n private appendToolResultLines(lines: string[], tr: ToolResultItem, width: number): void {\n if (!this.expandDetails) {\n // Collapsed: show truncated one-liner\n const maxLen = width - 10;\n const preview = tr.content.replace(/\\n/g, ' ').slice(0, maxLen);\n const truncated = preview.length < tr.content.length ? '...' : '';\n lines.push(` ${GRAY}\\u2192 ${tr.toolName}: ${preview}${truncated}${RESET}`);\n return;\n }\n\n lines.push(` ${GRAY}\\u2192 ${tr.toolName} result:${RESET}`);\n let formatted = tr.content;\n try {\n formatted = JSON.stringify(JSON.parse(tr.content), null, 2);\n } catch {\n // use raw\n }\n const indent = ' ';\n for (const resultLine of formatted.split('\\n')) {\n for (const wl of this.wrapText(resultLine, width - indent.length)) {\n lines.push(`${indent}${GRAY}${wl}${RESET}`);\n }\n }\n }\n\n private appendMessageLines(lines: string[], msg: ChatMessage, width: number): void {\n if (msg.role === 'system') {\n for (const para of msg.content.split('\\n')) {\n for (const wl of this.wrapText(para, width - 2)) {\n lines.push(` ${GRAY}${wl}${RESET}`);\n }\n }\n return;\n }\n\n const isUser = msg.role === 'user';\n const label = isUser ? `${BLUE}You:${RESET} ` : `${GREEN}Assistant:${RESET} `;\n const labelWidth = isUser ? 5 : 12;\n const indent = ' '.repeat(labelWidth);\n let first = true;\n\n // Strip the \"—interrupted\" suffix from content for display\n const displayContent = msg.truncationReason\n ? msg.content.replace(/—interrupted$/, '')\n : msg.content;\n\n for (const para of displayContent.split('\\n')) {\n for (const wl of this.wrapText(para, width - labelWidth)) {\n lines.push(first ? label + wl : indent + wl);\n first = false;\n }\n }\n\n // Truncation indicator\n if (msg.truncationReason) {\n const reasonLabel = getTruncationLabel(msg.truncationReason, msg.truncatedAtMs);\n lines.push(`${indent}${YELLOW}[${reasonLabel}]${RESET}`);\n\n // Show unspoken text in dim italic gray\n const extra = getExtraContent(msg.content, msg.originalContent);\n if (extra) {\n for (const para of extra.split('\\n')) {\n for (const wl of this.wrapText(para, width - labelWidth)) {\n lines.push(`${indent}${DIM_ITALIC_GRAY}${wl}${RESET}`);\n }\n }\n }\n }\n }\n\n private appendStreamLines(lines: string[], width: number): void {\n const label = `${GREEN}Assistant:${RESET} `;\n const labelWidth = 12;\n const indent = ' '.repeat(labelWidth);\n\n if (!this.streamContent) {\n lines.push(label);\n return;\n }\n\n let first = true;\n for (const para of this.streamContent.split('\\n')) {\n for (const wl of this.wrapText(para, width - labelWidth)) {\n lines.push(first ? label + wl : indent + wl);\n first = false;\n }\n }\n }\n\n // ─── Debug display line building ──────────────────────────────────\n\n private buildDebugLines(): string[] {\n const lines: string[] = [];\n const dw = this.debugWidth();\n if (dw <= 0) return lines;\n\n for (const entry of this.debugEntries) {\n const color = entry.direction === 'in' ? ORANGE : LIGHT_BLUE;\n const arrow = entry.direction === 'in' ? '\\u25bc' : '\\u25b2'; // ▼ in, ▲ out\n const prefix = `${DIM}${entry.ts}${RESET} ${color}${arrow}${RESET} `;\n const prefixWidth = entry.ts.length + 3; // \"HH:MM:SS ▼ \"\n\n if (!this.expandDetails) {\n // Collapsed: single summary line, truncated\n const maxSummary = dw - prefixWidth;\n const summaryText = entry.summary.slice(0, maxSummary);\n lines.push(`${prefix}${color}${summaryText}${RESET}`);\n } else {\n // Expanded: summary + full detail\n lines.push(`${prefix}${color}${entry.summary}${RESET}`);\n const indent = ' '.repeat(prefixWidth);\n for (const detailLine of entry.detail.split('\\n')) {\n for (const wl of this.wrapText(detailLine, dw - prefixWidth)) {\n lines.push(`${indent}${color}${DIM}${wl}${RESET}`);\n }\n }\n lines.push(''); // blank line between expanded entries\n }\n }\n\n return lines;\n }\n\n // ─── Text utilities ───────────────────────────────────────────────\n\n private wrapText(text: string, maxWidth: number): string[] {\n if (maxWidth <= 0) maxWidth = 1;\n if (!text) return [''];\n if (text.length <= maxWidth) return [text];\n\n const words = text.split(' ');\n const result: string[] = [];\n let current = '';\n\n for (const word of words) {\n if (!current) {\n current = word;\n } else if (current.length + 1 + word.length <= maxWidth) {\n current += ' ' + word;\n } else {\n result.push(current);\n current = word;\n }\n }\n if (current) result.push(current);\n\n return result.length ? result : [''];\n }\n}\n\n// ─── Module-level helpers ─────────────────────────────────────────────────────\n\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n);\n}\n\n/** Truncate a string (which may contain ANSI codes) to fit in maxCols visible characters */\nfunction truncateAnsi(s: string, maxCols: number): string {\n if (maxCols <= 0) return '';\n let visible = 0;\n let i = 0;\n while (i < s.length && visible < maxCols) {\n if (s[i] === '\\x1B') {\n // Skip ANSI sequence\n const end = s.indexOf('m', i);\n if (end !== -1) {\n i = end + 1;\n } else {\n i++;\n }\n } else {\n visible++;\n i++;\n }\n }\n // Append RESET to close any open ANSI sequences\n return s.slice(0, i) + RESET;\n}\n\n/** Redact audio PCM buffers from WebSocket messages for debug display (does not redact text content) */\nfunction redactAudio(msg: any): any {\n if (!msg || typeof msg !== 'object') return msg;\n const clone = { ...msg };\n // Redact voice.audio CUSTOM events\n if (clone.type === 'CUSTOM' && clone.value && typeof clone.value === 'object') {\n const name = clone.name || '';\n if (name === 'voice.audio' && clone.value.data) {\n clone.value = { ...clone.value, data: '[audio]' };\n }\n }\n return clone;\n}\n\n/** Build a one-line summary of a WebSocket message for the collapsed debug view */\nfunction buildDebugSummary(_direction: 'in' | 'out', msg: any): string {\n if (!msg || typeof msg !== 'object') return String(msg);\n\n if (msg.type === 'CUSTOM') {\n const name = msg.name || '?';\n // For audio, just show the event name\n if (name === 'voice.audio') return name;\n // For other CUSTOM events, show name + compact value hint\n if (msg.value && typeof msg.value === 'object') {\n const keys = Object.keys(msg.value);\n if (keys.length <= 3) {\n return `${name} {${keys.join(', ')}}`;\n }\n return `${name} {${keys.length} keys}`;\n }\n return name;\n }\n\n // Standard AG-UI events: TEXT_MESSAGE_CONTENT, TOOL_CALL_START, etc.\n const type = msg.type || '?';\n if (msg.delta) {\n const preview = msg.delta.length > 30 ? msg.delta.slice(0, 30) + '...' : msg.delta;\n return `${type} \"${preview}\"`;\n }\n if (msg.toolCallName) {\n return `${type} ${msg.toolCallName}`;\n }\n return type;\n}\n","/**\n * Audio I/O for CLI using SoX (Sound eXchange)\n *\n * Uses the `rec` command for microphone capture and `play` for audio playback.\n * SoX is cross-platform and available via:\n * macOS: brew install sox\n * Linux: apt install sox\n * Windows: choco install sox\n */\n\nimport { spawn, execSync, spawnSync, type ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\nimport * as readline from 'readline';\n\nconst SAMPLE_RATE = 24000;\n// 100ms of PCM16 audio at 24kHz mono = 4800 bytes\nconst MIC_CHUNK_BYTES = 4800;\n\nexport interface AudioDevice {\n id: string;\n name: string;\n isDefault: boolean;\n}\n\n/** Check if SoX is installed and available */\nexport function checkSoxAvailable(): boolean {\n try {\n execSync('which sox', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\n/** List audio input devices via SoX */\nexport async function listInputDevices(): Promise<AudioDevice[]> {\n return listDevices('rec');\n}\n\n/** List audio output devices via SoX */\nexport async function listOutputDevices(): Promise<AudioDevice[]> {\n return listDevices('play');\n}\n\nfunction listDevices(command: string): Promise<AudioDevice[]> {\n return new Promise((resolve) => {\n try {\n // spawnSync avoids shell interpolation — command and args are always separate\n const proc = spawnSync(command, ['--list-devices'], {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'pipe'],\n timeout: 5000,\n });\n // SoX outputs device list to stderr; combine both streams to be safe\n const output = (proc.stdout ?? '') + (proc.stderr ?? '');\n\n const devices: AudioDevice[] = [];\n const lines = output.split('\\n');\n for (const line of lines) {\n // Parse lines like: \" Input Device 0 : Built-in Microphone\"\n // or \" Output Device 0 : Built-in Output\"\n const match = line.match(/(?:Input|Output)\\s+Device\\s+(\\d+)\\s*:\\s*(.+)/i);\n if (match && match[1] && match[2]) {\n devices.push({\n id: match[1],\n name: match[2].trim(),\n isDefault: devices.length === 0, // First device is typically the default\n });\n }\n }\n\n // If SoX didn't give us devices, return a default entry\n if (devices.length === 0) {\n devices.push({ id: 'default', name: 'System Default', isDefault: true });\n }\n\n resolve(devices);\n } catch {\n // Fallback to system default\n resolve([{ id: 'default', name: 'System Default', isDefault: true }]);\n }\n });\n}\n\n/** Interactively select an audio device */\nexport async function selectDevice(devices: AudioDevice[], label: string): Promise<AudioDevice> {\n if (devices.length <= 1) {\n return devices[0]!;\n }\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n terminal: true,\n });\n\n process.stderr.write(`\\n ${label}:\\n`);\n for (let i = 0; i < devices.length; i++) {\n const dev = devices[i]!;\n const marker = dev.isDefault ? ' (default)' : '';\n process.stderr.write(` ${i + 1}. ${dev.name}${marker}\\n`);\n }\n\n return new Promise((resolve) => {\n const defaultIdx = devices.findIndex((d) => d.isDefault);\n const defaultNum = defaultIdx >= 0 ? defaultIdx + 1 : 1;\n\n rl.question(` Select [${defaultNum}]: `, (answer) => {\n rl.close();\n const num = answer.trim() ? parseInt(answer.trim(), 10) : defaultNum;\n const idx = Math.max(0, Math.min(devices.length - 1, num - 1));\n resolve(devices[idx]!);\n });\n });\n}\n\n/**\n * Microphone capture via SoX `rec`.\n * Streams raw PCM16 signed 16-bit LE mono audio at 24kHz.\n */\nexport class MicCapture {\n private process: ChildProcess | null = null;\n private onData: (pcm16: Buffer) => void;\n private buffer = Buffer.alloc(0);\n\n constructor(onData: (pcm16: Buffer) => void) {\n this.onData = onData;\n }\n\n /** Start recording from the microphone */\n start(deviceId?: string): void {\n const args = [\n '-q', // quiet\n '-t',\n 'raw', // raw PCM output\n '-r',\n String(SAMPLE_RATE),\n '-e',\n 'signed-integer',\n '-b',\n '16', // 16-bit\n '-c',\n '1', // mono\n '-L', // little-endian\n '-', // stdout\n ];\n\n const env = { ...process.env };\n if (deviceId && deviceId !== 'default') {\n env.AUDIODEV = deviceId;\n }\n\n this.process = spawn('rec', args, {\n env,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n this.process.stdout?.on('data', (data: Buffer) => {\n // Accumulate data and emit in consistent chunk sizes\n this.buffer = Buffer.concat([this.buffer, data]);\n while (this.buffer.length >= MIC_CHUNK_BYTES) {\n const chunk = this.buffer.subarray(0, MIC_CHUNK_BYTES);\n this.buffer = this.buffer.subarray(MIC_CHUNK_BYTES);\n this.onData(Buffer.from(chunk));\n }\n });\n\n this.process.stderr?.on('data', (data: Buffer) => {\n // SoX outputs warnings/errors to stderr - ignore unless debugging\n const msg = data.toString().trim();\n if (msg && !msg.includes('WARN')) {\n process.stderr.write(`[mic] ${msg}\\n`);\n }\n });\n\n this.process.on('error', (err) => {\n process.stderr.write(`[mic] Process error: ${err.message}\\n`);\n });\n }\n\n /** Stop recording */\n stop(): void {\n if (this.process) {\n this.process.kill('SIGTERM');\n this.process = null;\n }\n this.buffer = Buffer.alloc(0);\n }\n}\n\n/**\n * Audio playback via SoX `play`.\n * Accepts raw PCM16 signed 16-bit LE mono audio at 24kHz.\n *\n * Streams audio to SoX's stdin so playback begins immediately on the first\n * chunk — no waiting for the full response. Queues back-to-back responses\n * so a second response never kills the first mid-playback.\n *\n * Events:\n * - 'playing': SoX process spawned for a response\n * - 'done': All queued responses finished (or playback was stopped)\n */\nexport class AudioPlayer extends EventEmitter {\n private process: ChildProcess | null = null;\n private deviceId?: string;\n\n // When true, we own the SoX process's stdin and are actively streaming to it.\n // When false with a process, the stdin has been closed and SoX is draining.\n private streaming = false;\n\n // Buffer chunks when another response is already playing\n private pendingChunks: Buffer[] = [];\n private pendingBytes = 0;\n\n // Queue of complete response buffers waiting to play\n private queue: { audio: Buffer; messageId?: string }[] = [];\n\n // Playback position tracking for barge-in\n private currentMessageId?: string;\n private playbackStartTime = 0; // Date.now() when SoX started\n private bytesWritten = 0; // total bytes piped to SoX for duration estimation\n\n constructor(deviceId?: string) {\n super();\n this.deviceId = deviceId;\n }\n\n /** Check if audio is currently playing or queued */\n get isPlaying(): boolean {\n return this.process !== null || this.queue.length > 0;\n }\n\n /** Get the message ID of the currently playing audio */\n get playingMessageId(): string | undefined {\n return this.currentMessageId;\n }\n\n /** Duration of audio written so far in ms */\n private get currentDurationMs(): number {\n // PCM16 mono 24kHz = 48000 bytes/sec\n return (this.bytesWritten / (SAMPLE_RATE * 2)) * 1000;\n }\n\n /**\n * Estimate current playback position in milliseconds.\n * Uses wall-clock time since SoX started playing.\n */\n getPlaybackTimeMs(): number | null {\n if (!this.process || this.playbackStartTime === 0) return null;\n const elapsed = Date.now() - this.playbackStartTime;\n return Math.min(elapsed, this.currentDurationMs);\n }\n\n /**\n * Stream PCM16 audio data for playback.\n * On the first chunk, spawns SoX and begins playback immediately.\n */\n write(pcm16: Buffer): void {\n if (this.process && !this.streaming) {\n // A previous response is still playing/draining — buffer for later\n this.pendingChunks.push(pcm16);\n this.pendingBytes += pcm16.length;\n return;\n }\n\n if (!this.process) {\n this.spawnSoxProcess();\n }\n\n this.process!.stdin!.write(pcm16);\n this.bytesWritten += pcm16.length;\n }\n\n /**\n * End the current audio response.\n * If streaming, closes stdin to let SoX finish playing.\n * If buffering behind another response, adds to the queue.\n */\n endResponse(messageId?: string): void {\n if (this.streaming && this.process) {\n this.currentMessageId = messageId;\n this.streaming = false;\n this.process.stdin!.end();\n } else if (this.pendingChunks.length > 0) {\n const audio = Buffer.concat(this.pendingChunks);\n this.pendingChunks = [];\n this.pendingBytes = 0;\n this.queue.push({ audio, messageId });\n }\n }\n\n /** Stop current playback, discard all queued audio */\n stop(): void {\n this.pendingChunks = [];\n this.pendingBytes = 0;\n this.queue = [];\n this.streaming = false;\n\n const wasPlaying = this.process !== null;\n if (this.process) {\n try {\n this.process.stdin?.destroy();\n this.process.kill('SIGTERM');\n } catch {\n // Ignore\n }\n this.process = null;\n }\n this.currentMessageId = undefined;\n this.playbackStartTime = 0;\n this.bytesWritten = 0;\n if (wasPlaying) {\n this.emit('done');\n }\n }\n\n /** Spawn a SoX `play` process reading raw PCM from stdin */\n private spawnSoxProcess(): void {\n this.bytesWritten = 0;\n this.currentMessageId = undefined;\n\n const args = [\n '-q', // quiet\n '-t',\n 'raw',\n '-r',\n String(SAMPLE_RATE),\n '-e',\n 'signed-integer',\n '-b',\n '16',\n '-c',\n '1',\n '-L', // little-endian\n '-', // read from stdin\n ];\n\n const env = { ...process.env };\n if (this.deviceId && this.deviceId !== 'default') {\n env.AUDIODEV = this.deviceId;\n }\n\n const proc = spawn('play', args, {\n env,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n proc.on('error', (err) => {\n process.stderr.write(`[player] Process error: ${err.message}\\n`);\n });\n\n proc.on('exit', (code, _signal) => {\n // 143 = SIGTERM (normal stop/interrupt)\n if (code !== null && code !== 0 && code !== 143) {\n process.stderr.write(`[player] SoX exited with code ${code}\\n`);\n }\n if (this.process === proc) {\n this.process = null;\n this.streaming = false;\n if (this.queue.length > 0) {\n const next = this.queue.shift()!;\n this.playQueued(next.audio, next.messageId);\n } else {\n this.emit('done');\n }\n }\n });\n\n proc.stderr?.on('data', (data: Buffer) => {\n const msg = data.toString().trim();\n if (msg) {\n process.stderr.write(`[player:sox] ${msg}\\n`);\n }\n });\n\n proc.stdout?.resume();\n\n this.process = proc;\n this.streaming = true;\n this.playbackStartTime = Date.now();\n this.emit('playing');\n }\n\n /** Play a complete pre-buffered response (from the queue) */\n private playQueued(audio: Buffer, messageId?: string): void {\n this.spawnSoxProcess();\n this.currentMessageId = messageId;\n this.process!.stdin!.write(audio);\n this.bytesWritten = audio.length;\n this.process!.stdin!.end();\n this.streaming = false;\n }\n}\n","/**\n * Concierge chat command — interactive chat with the global concierge agent.\n *\n * Supports the same modes as workspace manager chat (text, realtime, voice)\n * but without requiring a workspace.\n */\n\nimport { formatTimestamp, selectFromList } from '../cli-utils';\nimport {\n createConciergeChat,\n getConciergeChat,\n getConciergeChatMessages,\n listConciergeChats,\n originateConciergeCall,\n originateConciergeSms,\n type ConciergeChat,\n} from '../lib/concierge-api';\nimport { requireAuth, type AuthenticatedContext } from '../lib/context';\nimport { CLIError } from '../lib/errors';\nimport type { CommandHandlerContext } from '../lib/types';\nimport { buildCliConciergeAppContext } from '../lib/cli-client-context';\nimport { runChatSession, type ChatSession } from '../lib/chat-session';\n\nexport async function conciergeOutboundCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const { args } = hctx;\n\n if (args.call && args.sms) {\n throw new CLIError('--call and --sms are mutually exclusive');\n }\n if (args.call) {\n const result = await originateConciergeCall(ctx);\n process.stderr.write(\n `Concierge call started. callSid=${result.callSid} startedAt=${result.startedAt}\\n`\n );\n return;\n }\n if (args.sms) {\n const result = await originateConciergeSms(ctx);\n process.stderr.write(\n `Concierge SMS started. messageSid=${result.messageSid} conversationId=${result.conversationId}\\n`\n );\n return;\n }\n\n throw new CLIError(\n 'Use `gr concierge chat --call`, `gr concierge chat --sms`, or `gr concierge chat` for interactive mode.'\n );\n}\n\nexport async function conciergeCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const { args } = hctx;\n\n if (args.call || args.sms) {\n if (args.call && args.sms) {\n throw new CLIError('--call and --sms are mutually exclusive');\n }\n if (args.voice || args.realtime) {\n throw new CLIError('--call/--sms cannot be combined with --voice or --realtime');\n }\n await conciergeOutboundCommand(hctx);\n return;\n }\n\n const chatIdArg = typeof args['chat-id'] === 'string' ? args['chat-id'] : undefined;\n const message = typeof args.message === 'string' ? args.message : undefined;\n\n const chat = await getOrCreateConciergeChat(ctx, chatIdArg, !!message);\n const session = buildConciergeSession(ctx, chat, args);\n await runChatSession(session, args);\n}\n\nfunction buildConciergeSession(\n ctx: AuthenticatedContext,\n chat: ConciergeChat,\n args: Record<string, unknown>\n): ChatSession {\n const wsBase = ctx.envConfig.apiUrl.replace(/^https:/, 'wss:').replace(/^http:/, 'ws:');\n return {\n ctx,\n workspaceUuid: '',\n chatId: chat.id,\n chatUuid: chat.uuid,\n chatTitle: chat.title || chat.uuid,\n aguiEndpointUrl: `${ctx.envConfig.apiUrl}/api/v2/concierge/chats/${chat.id}/chat/agui`,\n wsUrl: `${wsBase}/api/v2/concierge/voice/stream-ws`,\n loadMessages: () => getConciergeChatMessages(ctx, chat.id).catch(() => []),\n label: 'Concierge',\n model: undefined, // concierge doesn't send model field\n appContext: buildCliConciergeAppContext(),\n allowWrite: true,\n trustCwd: !!args['trust-cwd'],\n trustDir: typeof args['trust-dir'] === 'string' ? args['trust-dir'] : undefined,\n };\n}\n\nasync function getOrCreateConciergeChat(\n ctx: AuthenticatedContext,\n chatIdArg: string | undefined,\n skipSelection: boolean\n): Promise<ConciergeChat> {\n if (chatIdArg) {\n const id = Number(chatIdArg);\n if (isNaN(id)) throw new CLIError('--chat-id must be a number');\n return getConciergeChat(ctx, id);\n }\n\n if (skipSelection) {\n const chat = await createConciergeChat(ctx);\n process.stderr.write(`Created concierge chat #${chat.id}\\n`);\n return chat;\n }\n\n const chats = await listConciergeChats(ctx);\n\n const { item: selectedChat, isNew } = await selectFromList(chats, {\n title: 'Select a concierge chat or create a new one',\n labelFn: (c) => c.title || `Chat ${c.uuid.slice(0, 8)}...`,\n detailFn: (c) => formatTimestamp(c.updatedAt),\n emptyMessage: 'No existing concierge chats.',\n allowNew: true,\n newLabel: '+ Start new chat',\n });\n\n if (!selectedChat && !isNew) {\n throw new CLIError('No chat selected.');\n }\n\n if (isNew) {\n const chat = await createConciergeChat(ctx);\n process.stderr.write(`Created concierge chat #${chat.id}\\n`);\n return chat;\n }\n return selectedChat!;\n}\n","import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { join } from 'path';\nimport type { AuthenticatedContext } from '../lib/context';\nimport { CLIError } from '../lib/errors';\nimport { stderr } from '../lib/output';\n\nexport async function devImportLocalCommand(\n ctx: AuthenticatedContext,\n workspace: string\n): Promise<void> {\n stderr(`Exporting workspace ${workspace}...`);\n const exportData = await ctx.apiClient.exportWorkspace(workspace);\n\n stderr('Export successful!');\n stderr(` Workflows: ${(exportData.workflows || []).length}`);\n stderr(` Tasks: ${(exportData.tasks || []).length}`);\n stderr(` Data Types: ${(exportData.dataTypes || []).length}`);\n stderr(` Sites: ${(exportData.sites || []).length}`);\n\n const slug = workspace.slice(0, 8);\n const importCacheDir = join(ctx.credentialsManager.getCacheDir(), 'imports');\n if (!existsSync(importCacheDir)) {\n mkdirSync(importCacheDir, { recursive: true });\n }\n const filename = `ws-${slug}-${workspace}.json`;\n const filepath = join(importCacheDir, filename);\n writeFileSync(filepath, JSON.stringify(exportData, null, 2));\n stderr(`Saved to: ${filepath}`);\n\n stderr('Running dev:restore...');\n const rootDir = findProjectRoot();\n const relativePath = filepath.replace(rootDir + '/', '');\n\n try {\n const result = execSync(`yarn dev:restore ${relativePath}`, {\n cwd: rootDir,\n stdio: 'pipe',\n encoding: 'utf-8',\n });\n process.stderr.write(result);\n\n const failed =\n (result.includes('Failed/Skipped: ') && !result.includes('Failed/Skipped: 0')) ||\n result.includes('Successfully restored: 0');\n\n if (failed) throw new CLIError('Import failed');\n } catch (error: unknown) {\n if (error instanceof CLIError) throw error;\n const execError = error as { stdout?: string; stderr?: string };\n if (execError.stdout) process.stderr.write(execError.stdout);\n if (execError.stderr) process.stderr.write(execError.stderr);\n throw new CLIError('dev:restore failed');\n }\n\n stderr(`Import complete: ${workspace}`);\n}\n\nfunction findProjectRoot(): string {\n let dir = process.cwd();\n while (dir !== '/') {\n const pkgPath = join(dir, 'package.json');\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n if (pkg.workspaces) return dir;\n } catch {\n // continue\n }\n }\n dir = join(dir, '..');\n }\n return process.cwd();\n}\n","/**\n * `gr get-started` / `gr setup` — bootstrap instructions for humans and LLM agents.\n */\n\nimport type { CommandHandlerContext } from '../lib/types';\nimport { requireAuth } from '../lib/context';\n\nconst WEB_SETUP = 'https://app.gravityrail.com/setup';\nconst WEB_GET_STARTED = 'https://app.gravityrail.com/get-started';\n\nconst HUMAN_GUIDE = `Gravity Rail — getting started\n\n1. Authenticate: gr login --env prod\n Confirm: gr whoami\n\n2. Recommended path — concierge (no workspace required):\n gr concierge chat --allow-write\n The concierge can create your org (auto-created on first login), list products,\n start Stripe checkout, and create your first workspace.\n\n3. Verify workspaces: gr workspaces list\n\n4. Web wizards (human-friendly): ${WEB_SETUP} and ${WEB_GET_STARTED}\n\nHeadless boundary: Stripe checkout needs a human in a browser — the concierge returns\na checkout URL; an agent should hand that link to the user, not loop on payment.\n\nAgent-readable steps: gr get-started --format llm\n`;\n\nconst LLM_GUIDE = `# Gravity Rail CLI bootstrap (agent instructions)\n\n## Preconditions\n- Install: \\`npm install -g @gravity-rail/cli\\` or \\`npx @gravity-rail/cli\\`\n- Authenticate: \\`gr login --env prod\\` (interactive OAuth). Verify with \\`gr whoami\\`.\n- **Monorepo dev:** from gravity-team with Docker dev up, use \\`yarn gr <cmd> --realm superadmin\\` (reads \\`dev-realms.json\\`; no browser). Rebuild: \\`yarn workspace @gravity-rail/gr-cli build\\`.\n\n## Important facts\n- **Agents/CI:** do not leave stdin open on read-only commands; use \\`GRAVITY_RAIL_API_KEY\\` or redirect stdin from /dev/null. Commands only read stdin when \\`--data\\`/\\`--file\\` is passed.\n- Use \\`--env dev|staging|prod\\` (default prod) so credentials match the target; \\`gr whoami\\` shows the active env.\n- After login, an **organization is created automatically** — do not create a duplicate org unless \\`gr organizations list\\` is empty.\n- **Workspace is required** for workflow/agent/task commands (\\`-w <workspace-uuid>\\`).\n- **Concierge does not require \\`-w\\`** — use it for first-run setup.\n\n## Recommended path (concierge-driven)\n\\`\\`\\`bash\ngr concierge chat --allow-write --message \"Help me set up my first Gravity Rail workspace\"\n\\`\\`\\`\nFlags for unattended turns:\n- \\`--message\\` / \\`-m\\`: single-turn (non-interactive)\n- \\`--auto-approve\\`: skip HITL tool approval where policy allows\n- \\`--allow-write\\`: required for create/update tools\n\nThe concierge can: list/create orgs, list org/workspace products, create Stripe checkout sessions, create workspace specs, and \\`create_workspace\\`.\n\n## Manual CLI path (if not using concierge)\n1. \\`gr whoami\\` — confirm account\n2. \\`gr organizations list\\` — note org slug/UUID\n3. \\`gr concierge chat\\` OR web: ${WEB_GET_STARTED}\n4. Product purchase: concierge returns Stripe checkout URL → **human must complete in browser**\n5. \\`gr workspaces list\\` — pick workspace UUID for \\`-w\\`\n\n## Support (account-level, no workspace)\n\\`\\`\\`bash\ngr support create --type question --title \"...\" --description \"...\" --allow-write\ngr support list\n\\`\\`\\`\n\n## Web fallbacks\n- Concierge / setup: ${WEB_SETUP}\n- Wizard: ${WEB_GET_STARTED}\n\n## Headless limits (do not retry forever)\n- Stripe payment / checkout: requires human browser\n- OAuth login: requires human browser\n- Directory trust for future local-file tools: use \\`--trust-cwd\\` only after user confirms files are safe\n\n## Local project files (CLI only)\nAfter directory trust + \\`--allow-write\\`, the concierge can use \\`read_local_file\\`, \\`list_local_dir\\`, \\`write_local_file\\` (client-executed via HITL).\n\n## Verify success\n\\`gr workspaces list\\` then \\`gr workflows list -w <uuid>\\` or \\`gr agents list -w <uuid>\\`\n\n## Local phone / voice QA (monorepo dev)\n\\`\\`\\`bash\nyarn dev:twilio-ngrok --start-ngrok --url gravityrail.ngrok.io dev.<you> -w acme-demo\nyarn gr phone setup\nyarn gr account verify-phone --phone +1… --allow-write --realm superadmin\nyarn gr concierge chat --call --allow-write --realm superadmin\nyarn gr phone outbound --realm acme-demo/acme-admin --workflow-id 1 --allow-write\n\\`\\`\\`\nSee \\`.claude/skills/phone-voice-qa/SKILL.md\\` and \\`./scripts/e2e-voice-phone-matrix.sh\\`.\n`;\n\nexport async function getStartedCommand(hctx: CommandHandlerContext): Promise<void> {\n const format = hctx.args.format ?? hctx.args.agent;\n const isLlm =\n format === 'llm' || format === 'agent' || hctx.args['format'] === 'llm' || !!hctx.args.agent;\n\n if (!isLlm) {\n try {\n requireAuth(hctx.ctx);\n } catch {\n // Pre-login users can still read the guide.\n }\n process.stdout.write(HUMAN_GUIDE);\n return;\n }\n\n process.stdout.write(LLM_GUIDE);\n}\n","import { GravityRailClient } from '@gravity-rail/sdk';\nimport { performOAuthFlow } from '../cli-utils';\nimport type { CommandContext } from '../lib/context';\nimport { stderr } from '../lib/output';\n\nexport async function loginCommand(ctx: CommandContext): Promise<void> {\n const { accessToken } = await performOAuthFlow({\n env: ctx.env,\n envConfig: ctx.envConfig,\n credentialsManager: ctx.credentialsManager,\n });\n\n const apiClient = new GravityRailClient(accessToken, ctx.envConfig.apiUrl);\n const account = await apiClient.getUserAccount();\n stderr(`Logged in as ${account.name} (${account.email})`);\n}\n\nexport async function logoutCommand(ctx: CommandContext): Promise<void> {\n ctx.credentialsManager.clear(ctx.env);\n stderr(`Credentials cleared for ${ctx.env}`);\n}\n","import type { AuthenticatedContext } from '../lib/context';\nimport { outputData, type TableColumn } from '../lib/output';\n\n// The return type of getMyOrganizations references the admin-only\n// AdminAccountOrgMembership type, which is not re-exported from the public\n// @gravity-rail/sdk surface. We infer the element shape from the runtime\n// method signature here.\ntype OrgMembership = Awaited<\n ReturnType<AuthenticatedContext['apiClient']['getMyOrganizations']>\n>[number];\n\nconst COLUMNS: TableColumn<OrgMembership>[] = [\n { header: 'NAME', getValue: (o) => o.organizationName || '', maxWidth: 35 },\n { header: 'SLUG', getValue: (o) => o.organizationSlug || '', maxWidth: 25 },\n { header: 'UUID', getValue: (o) => o.organizationUuid },\n { header: 'ROLE', getValue: (o) => o.role || '' },\n];\n\nexport async function organizationsListCommand(ctx: AuthenticatedContext): Promise<void> {\n const organizations = await ctx.apiClient.getMyOrganizations();\n outputData(organizations, ctx, COLUMNS);\n}\n","import type { Account } from '@gravity-rail/sdk';\nimport type { AuthenticatedContext } from '../lib/context';\nimport { outputSingle, type TableColumn } from '../lib/output';\n\nconst COLUMNS: TableColumn<Account>[] = [\n { header: 'NAME', getValue: (a) => a.name || '', maxWidth: 30 },\n { header: 'EMAIL', getValue: (a) => a.email || '', maxWidth: 40 },\n { header: 'UUID', getValue: (a) => a.uuid },\n { header: 'ENV', getValue: () => '' },\n { header: 'SUPERUSER', getValue: (a) => (a.isSuperuser ? 'yes' : 'no') },\n];\n\nexport async function whoamiCommand(ctx: AuthenticatedContext): Promise<void> {\n const account = await ctx.apiClient.getUserAccount();\n const columns = COLUMNS.map((col) =>\n col.header === 'ENV' ? { ...col, getValue: () => ctx.env } : col\n );\n outputSingle(account, ctx, columns);\n}\n","import { authBrowserCommand } from './commands/auth-browser';\nimport { chatCommand, manageCommand } from './commands/manage';\nimport { conciergeCommand, conciergeOutboundCommand } from './commands/concierge';\nimport { devImportLocalCommand } from './commands/dev';\nimport { getStartedCommand } from './commands/get-started';\nimport { loginCommand, logoutCommand } from './commands/login';\nimport { organizationsListCommand } from './commands/organizations';\nimport { whoamiCommand } from './commands/whoami';\nimport { requireAuth } from './lib/context';\nimport type { CommandRegistry } from './lib/registry';\nimport type { CommandHandlerContext } from './lib/types';\n\n/**\n * Register top-level CLI commands that do not belong to a domain module\n * (login, manage, concierge, etc.). Used by both the public `@gravity-rail/cli`\n * binary and the internal `@gravity-rail/gr-cli` wrapper.\n */\nexport function registerSpecialCommands(registry: CommandRegistry): void {\n registry.registerCommand({\n path: ['login'],\n description: 'Authenticate via OAuth',\n requiresAuth: false,\n handler: async ({ ctx }) => {\n await loginCommand(ctx);\n },\n });\n\n registry.registerCommand({\n path: ['logout'],\n description: 'Clear cached credentials',\n requiresAuth: false,\n handler: async ({ ctx }) => {\n await logoutCommand(ctx);\n },\n });\n\n registry.registerCommand({\n path: ['auth', 'browser'],\n description: 'Open an authenticated browser session using CLI credentials',\n args: [\n { name: 'no-open', description: 'Print the URL instead of opening browser', isFlag: true },\n ],\n handler: async ({ ctx, args }) => {\n await authBrowserCommand(requireAuth(ctx), args);\n },\n });\n\n registry.registerCommand({\n path: ['manage'],\n description: 'Interactive workspace manager chat (text, realtime, or voice)',\n requiresWorkspace: true,\n mutates: true,\n args: [\n { name: 'realtime', description: 'Use WebSocket realtime connection', isFlag: true },\n { name: 'voice', description: 'Enable voice mode (microphone + speaker)', isFlag: true },\n { name: 'message', alias: 'm', description: 'Single-turn: send one message and exit' },\n { name: 'as-member', description: 'Chat as a specific member (by numeric ID)' },\n { name: 'chat-id', description: 'Resume an existing chat by numeric ID' },\n { name: 'vad', description: 'Voice activity detection: server (default) or client' },\n { name: 'list-devices', description: 'List audio devices and exit', isFlag: true },\n { name: 'input-device', description: 'Microphone device name or ID' },\n { name: 'output-device', description: 'Speaker device name or ID' },\n { name: 'debug', description: 'Enable debug logging', isFlag: true },\n {\n name: 'auto-approve',\n description: 'Auto-approve all tool calls (skip HITL)',\n isFlag: true,\n },\n {\n name: 'trust-cwd',\n description: 'Trust files in the current working directory (non-interactive)',\n isFlag: true,\n },\n {\n name: 'trust-dir',\n description: 'Trust files in this directory (non-interactive; absolute path)',\n },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await manageCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['chat'],\n description: 'Chat with a workflow, member, or existing chat (text, realtime, or voice)',\n requiresWorkspace: true,\n mutates: true,\n args: [\n { name: 'workflow', description: 'Start assignment chat with workflow (by numeric ID)' },\n { name: 'member', description: 'Start DM with a member (by numeric ID)' },\n { name: 'chat-id', description: 'Resume an existing chat by numeric ID' },\n { name: 'realtime', description: 'Use WebSocket realtime connection', isFlag: true },\n { name: 'voice', description: 'Enable voice mode (microphone + speaker)', isFlag: true },\n { name: 'message', alias: 'm', description: 'Single-turn: send one message and exit' },\n { name: 'vad', description: 'Voice activity detection: server (default) or client' },\n { name: 'list-devices', description: 'List audio devices and exit', isFlag: true },\n { name: 'input-device', description: 'Microphone device name or ID' },\n { name: 'output-device', description: 'Speaker device name or ID' },\n { name: 'debug', description: 'Enable debug logging', isFlag: true },\n {\n name: 'auto-approve',\n description: 'Auto-approve all tool calls (skip HITL)',\n isFlag: true,\n },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await chatCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['get-started'],\n description: 'Bootstrap instructions for new users and LLM agents',\n requiresAuth: false,\n args: [\n {\n name: 'format',\n description: 'Output format: llm (agent-readable) or default (human)',\n },\n {\n name: 'agent',\n description: 'Alias for --format llm',\n isFlag: true,\n },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await getStartedCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['setup'],\n description: 'Alias for get-started — bootstrap instructions',\n requiresAuth: false,\n args: [\n { name: 'format', description: 'Output format: llm or default' },\n { name: 'agent', description: 'Alias for --format llm', isFlag: true },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await getStartedCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['concierge'],\n description: 'Call or SMS your verified phone via the Concierge (server-side)',\n requiresWorkspace: false,\n mutates: true,\n args: [\n { name: 'call', description: 'Ring your verified account phone', isFlag: true },\n { name: 'sms', description: 'Start an SMS thread on your verified phone', isFlag: true },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await conciergeOutboundCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['account', 'verify-phone'],\n description: 'Verify your account phone for concierge chat --call / --sms',\n requiresWorkspace: false,\n mutates: true,\n args: [{ name: 'phone', description: 'E.164 phone number (optional; prompts if omitted)' }],\n handler: async (hctx: CommandHandlerContext) => {\n const { accountVerifyPhoneCommand } = await import('./commands/account-verify-phone');\n await accountVerifyPhoneCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['concierge', 'chat'],\n description: 'Interactive concierge chat (text, realtime, or voice)',\n requiresWorkspace: false,\n mutates: true,\n args: [\n { name: 'realtime', description: 'Use WebSocket realtime connection', isFlag: true },\n { name: 'voice', description: 'Enable voice mode (microphone + speaker)', isFlag: true },\n {\n name: 'call',\n description: 'Ring your verified account phone (server-side)',\n isFlag: true,\n },\n {\n name: 'sms',\n description: 'SMS your verified account phone (server-side)',\n isFlag: true,\n },\n { name: 'message', alias: 'm', description: 'Single-turn: send one message and exit' },\n { name: 'chat-id', description: 'Resume an existing chat by numeric ID' },\n { name: 'vad', description: 'Voice activity detection: server (default) or client' },\n { name: 'list-devices', description: 'List audio devices and exit', isFlag: true },\n { name: 'input-device', description: 'Microphone device name or ID' },\n { name: 'output-device', description: 'Speaker device name or ID' },\n { name: 'debug', description: 'Enable debug logging', isFlag: true },\n {\n name: 'auto-approve',\n description: 'Auto-approve all tool calls (skip HITL)',\n isFlag: true,\n },\n {\n name: 'trust-cwd',\n description: 'Trust files in the current working directory (non-interactive)',\n isFlag: true,\n },\n {\n name: 'trust-dir',\n description: 'Trust files in this directory (non-interactive; absolute path)',\n },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await conciergeCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['dev', 'import-local'],\n description: 'Import remote workspace locally',\n requiresWorkspace: true,\n handler: async ({ ctx, workspace }) => {\n await devImportLocalCommand(requireAuth(ctx), workspace);\n },\n });\n\n registry.registerCommand({\n path: ['whoami'],\n description: 'Show current user info',\n handler: async ({ ctx }) => {\n await whoamiCommand(requireAuth(ctx));\n },\n });\n\n registry.registerCommand({\n path: ['organizations', 'list'],\n description: 'List organizations',\n handler: async ({ ctx }) => {\n await organizationsListCommand(requireAuth(ctx));\n },\n });\n\n registry.registerCommand({\n path: ['orgs', 'list'],\n description: 'List organizations',\n handler: async ({ ctx }) => {\n await organizationsListCommand(requireAuth(ctx));\n },\n });\n}\n"],"mappings":"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","names":["readFileSync","existsSync","join","resolve","resolve","stderr","baseUrl","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","execFile","readline","stderr","readline","path","fs","path","readline","resolve","readline","resolve","readline","resolve","execSync","EventEmitter","readline","resolve","output","resolve","input","existsSync","mkdirSync","writeFileSync","readFileSync","execSync","join","stderr","GravityRailClient","stderr","COLUMNS","accountVerifyPhoneCommand"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli-utils/config.ts","../src/cli-utils/auth.ts","../src/cli-utils/ui.ts","../src/cli-utils/agui.ts","../src/cli-utils/index.ts","../src/lib/errors.ts","../src/lib/pagination.ts","../src/lib/output.ts","../src/lib/realm.ts","../src/lib/org-auth.ts","../src/lib/pinned-fetch.ts","../src/lib/context.ts","../src/lib/concierge-api.ts","../src/commands/account-verify-phone.ts","../src/commands/auth-browser.ts","../src/commands/manage.ts","../src/lib/cli-client-context.ts","../src/lib/chat-session.ts","../src/lib/concierge-agui-loop.ts","../src/lib/cli-hitl.ts","../src/lib/local-files.ts","../src/lib/trusted-dirs.ts","../src/lib/realtime-client.ts","../src/lib/chat-tui.ts","../src/lib/audio.ts","../src/commands/concierge.ts","../src/commands/dev.ts","../src/commands/get-started.ts","../src/commands/login.ts","../src/commands/organizations.ts","../src/commands/whoami.ts","../src/register-special-commands.ts"],"sourcesContent":["/**\n * CLI configuration for remote environments\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { dirname, join, resolve } from 'path';\n\nexport interface EnvironmentConfig {\n apiUrl: string;\n frontendUrl: string;\n}\n\nexport const ENVIRONMENTS: Record<string, EnvironmentConfig> = {\n dev: {\n apiUrl: 'https://api.gravityrail.test:5054',\n frontendUrl: 'https://app.gravityrail.test:3000',\n },\n prod: {\n apiUrl: 'https://api.gravityrail.com',\n frontendUrl: 'https://app.gravityrail.com',\n },\n staging: {\n apiUrl: 'https://api.gr-staging.com',\n frontendUrl: 'https://app.gr-staging.com',\n },\n};\n\nexport const CALLBACK_PORT = 31337;\nexport const CALLBACK_PATH = '/oauth/callback';\nexport const REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;\n\n/**\n * Detect worktree port overrides from docker-compose.override.yml.\n * The override file is generated by worktree-setup.sh and contains lines like:\n * - '5250:5050' (API)\n * - '3200:3000' (Frontend)\n * We extract the host port for the default internal ports (5050, 3000).\n */\nfunction detectWorktreePorts(): { apiPort?: number; frontendPort?: number } {\n // Walk up from cwd to find docker-compose.override.yml\n let dir = resolve(process.cwd());\n let overridePath: string | undefined;\n while (true) {\n const candidate = join(dir, 'docker-compose.override.yml');\n\n if (existsSync(candidate)) {\n overridePath = candidate;\n break;\n }\n const parent = dirname(dir);\n if (parent === dir) break; // reached filesystem root\n dir = parent;\n }\n if (!overridePath) return {};\n\n let content: string;\n try {\n content = readFileSync(overridePath, 'utf-8');\n } catch {\n return {};\n }\n\n // Only use this if it's a worktree override (generated by worktree-setup.sh)\n if (!content.includes('worktree-setup.sh')) return {};\n\n // Match port mappings: - 'HOST:CONTAINER'\n let apiPort: number | undefined;\n let frontendPort: number | undefined;\n for (const match of content.matchAll(/-\\s*'(\\d+):(\\d+)'/g)) {\n const host = parseInt(match[1]!, 10);\n const container = parseInt(match[2]!, 10);\n if (container === 5050) apiPort = host;\n if (container === 3000) frontendPort = host;\n }\n return { apiPort, frontendPort };\n}\n\nexport function getEnvironmentConfig(env: string): EnvironmentConfig {\n // Handle dev-cloud environments: --env dev-cloud:NAMESPACE\n if (env.startsWith('dev-cloud:')) {\n const namespace = env.slice('dev-cloud:'.length);\n if (!namespace) {\n throw new Error('dev-cloud environment requires a namespace: --env dev-cloud:NAMESPACE');\n }\n return {\n apiUrl: `https://${namespace}-api.gravityrail-dev.com`,\n frontendUrl: `https://${namespace}-app.gravityrail-dev.com`,\n };\n }\n\n const config = ENVIRONMENTS[env];\n if (!config) {\n throw new Error(\n `Invalid environment: ${env}. Use 'dev', 'staging', 'prod', or 'dev-cloud:NAMESPACE'.`\n );\n }\n\n // Allow env var overrides (used by code interpreter sandboxes)\n const apiUrl = process.env.GRAVITY_RAIL_API_URL || config.apiUrl;\n const frontendUrl = process.env.GRAVITY_RAIL_FRONTEND_URL || config.frontendUrl;\n if (apiUrl !== config.apiUrl || frontendUrl !== config.frontendUrl) {\n return { apiUrl, frontendUrl };\n }\n\n // For dev, detect worktree port overrides\n if (env === 'dev') {\n const ports = detectWorktreePorts();\n if (ports.apiPort || ports.frontendPort) {\n return {\n apiUrl: ports.apiPort ? `https://api.gravityrail.test:${ports.apiPort}` : config.apiUrl,\n frontendUrl: ports.frontendPort\n ? `https://app.gravityrail.test:${ports.frontendPort}`\n : config.frontendUrl,\n };\n }\n }\n\n return config;\n}\n","/**\n * CLI OAuth2 authentication utilities\n *\n * Provides OAuth2 with PKCE flow for CLI tools, including:\n * - Credential caching (per environment)\n * - Dynamic client registration\n * - Token refresh\n * - Browser-based authorization\n */\n\nimport { createServer } from 'http';\nimport { createHash, randomBytes } from 'crypto';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { exec } from 'child_process';\nimport { EnvironmentConfig, CALLBACK_PORT, CALLBACK_PATH, REDIRECT_URI } from './config';\n\nexport interface CLICredentials {\n clientId: string;\n clientSecret: string;\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n}\n\nexport interface AuthResult {\n accessToken: string;\n credentials?: CLICredentials;\n}\n\n/**\n * Manages CLI credentials storage (flat format, one file per environment)\n */\nexport class CredentialsManager {\n private cacheDir: string;\n private apiUrl?: string;\n\n constructor(rootDir: string, apiUrl?: string) {\n this.cacheDir = join(rootDir, '.gr-cli');\n this.apiUrl = apiUrl;\n }\n\n private getCredentialsPath(env: string): string {\n // For localhost dev URLs with non-default ports (worktrees), include the\n // port in the filename so each worktree has isolated credentials.\n if (this.apiUrl) {\n try {\n const url = new URL(this.apiUrl);\n if (url.hostname === 'localhost' && url.port && url.port !== '5050') {\n return join(this.cacheDir, `credentials-${env}-${url.port}.json`);\n }\n } catch {\n // ignore invalid URLs\n }\n }\n return join(this.cacheDir, `credentials-${env}.json`);\n }\n\n load(env: string): CLICredentials | null {\n const credsPath = this.getCredentialsPath(env);\n if (!existsSync(credsPath)) {\n return null;\n }\n\n try {\n const raw = JSON.parse(readFileSync(credsPath, 'utf-8'));\n\n let creds: CLICredentials;\n if (raw.clientId !== undefined) {\n creds = raw;\n } else if (raw.default) {\n // Migrate from old org-namespaced format to flat\n creds = raw.default;\n this.save(env, creds);\n } else {\n return null;\n }\n\n // Check if access token is expired\n if (creds.expiresAt) {\n const expiresAt = new Date(creds.expiresAt);\n if (expiresAt <= new Date()) {\n if (creds.refreshToken) {\n return creds;\n }\n return null;\n }\n }\n\n return creds;\n } catch {\n return null;\n }\n }\n\n save(env: string, creds: CLICredentials): void {\n if (!existsSync(this.cacheDir)) {\n mkdirSync(this.cacheDir, { recursive: true });\n }\n const credsPath = this.getCredentialsPath(env);\n writeFileSync(credsPath, JSON.stringify(creds, null, 2));\n try {\n chmodSync(credsPath, 0o600);\n } catch {\n // Ignore permission errors on Windows\n }\n }\n\n clear(env: string): void {\n const credsPath = this.getCredentialsPath(env);\n if (!existsSync(credsPath)) {\n return;\n }\n try {\n unlinkSync(credsPath);\n } catch {\n // Ignore\n }\n }\n\n getCacheDir(): string {\n return this.cacheDir;\n }\n}\n\nfunction stderr(msg: string): void {\n process.stderr.write(msg + '\\n');\n}\n\n/**\n * Parse an OAuth error response body, checking the JSON `error` field first,\n * falling back to text matching.\n */\nfunction isOAuthError(body: string, errorCode: string): boolean {\n try {\n const parsed = JSON.parse(body);\n if (parsed.error === errorCode) return true;\n } catch {\n // Not JSON — fall through to text match\n }\n return body.includes(errorCode);\n}\n\n/**\n * Validate and extract fields from an OAuth token response.\n * Throws on malformed responses per RFC 6749 §5.1.\n */\nfunction validateTokenResponse(tokenData: Record<string, unknown>): {\n accessToken: string;\n refreshToken?: string;\n expiresIn: number;\n} {\n if (!tokenData.access_token || typeof tokenData.access_token !== 'string') {\n throw new Error('Token response missing access_token');\n }\n\n if (tokenData.token_type && String(tokenData.token_type).toLowerCase() !== 'bearer') {\n throw new Error(`Unsupported token type: ${tokenData.token_type}`);\n }\n\n let expiresIn = 86400; // default 24h\n if (tokenData.expires_in != null) {\n const raw = Number(tokenData.expires_in);\n if (!Number.isFinite(raw) || raw < 60 || raw > 31536000) {\n stderr(` Warning: unusual expires_in value (${tokenData.expires_in}), using default`);\n } else {\n expiresIn = raw;\n }\n }\n\n return {\n accessToken: tokenData.access_token,\n refreshToken:\n typeof tokenData.refresh_token === 'string' ? tokenData.refresh_token : undefined,\n expiresIn,\n };\n}\n\n/**\n * Generate PKCE code verifier and challenge\n */\nexport function generatePKCE(): { codeVerifier: string; codeChallenge: string } {\n const codeVerifier = randomBytes(64).toString('base64url').slice(0, 128);\n const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');\n return { codeVerifier, codeChallenge };\n}\n\n/**\n * Open a URL in the default browser\n */\nexport function openBrowser(url: string): void {\n const platform = process.platform;\n let cmd: string;\n if (platform === 'darwin') {\n cmd = `open \"${url}\"`;\n } else if (platform === 'win32') {\n cmd = `start \"\" \"${url}\"`;\n } else {\n cmd = `xdg-open \"${url}\"`;\n }\n\n exec(cmd, (err) => {\n if (err) {\n stderr(' Could not open browser automatically.');\n }\n });\n}\n\n/**\n * Start a local HTTP server to receive the OAuth callback\n */\nexport function startCallbackServer(): Promise<{ code: string; state: string }> {\n return new Promise((resolve, reject) => {\n let authCode: string | null = null;\n let error: string | null = null;\n let receivedState: string | null = null;\n\n const server = createServer((req, res) => {\n const url = new URL(req.url!, `http://localhost:${CALLBACK_PORT}`);\n\n if (url.pathname !== CALLBACK_PATH) {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n if (url.searchParams.has('error')) {\n error = url.searchParams.get('error');\n const errorDesc = url.searchParams.get('error_description') || 'Unknown error';\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <head><title>Authorization Failed</title></head>\n <body style=\"font-family: system-ui; text-align: center; padding: 50px;\">\n <h1 style=\"color: #dc2626;\">Authorization Failed</h1>\n <p>${errorDesc}</p>\n <p>You can close this window.</p>\n </body>\n </html>\n `);\n server.close();\n reject(new Error(`Authorization failed: ${error}`));\n } else if (url.searchParams.has('code')) {\n authCode = url.searchParams.get('code')!;\n receivedState = url.searchParams.get('state')!;\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <head><title>Authorization Successful</title></head>\n <body style=\"font-family: system-ui; text-align: center; padding: 50px;\">\n <h1 style=\"color: #16a34a;\">Authorization Successful!</h1>\n <p>You can close this window and return to the terminal.</p>\n <script>setTimeout(() => window.close(), 2000);</script>\n </body>\n </html>\n `);\n server.close();\n resolve({ code: authCode, state: receivedState });\n } else {\n res.writeHead(400);\n res.end('Missing code parameter');\n }\n });\n\n server.listen(CALLBACK_PORT, 'localhost', () => {\n // Server started\n });\n\n // Timeout after 5 minutes (unref so it doesn't keep the process alive)\n const timeout = setTimeout(\n () => {\n if (!authCode && !error) {\n server.close();\n reject(new Error('Authorization timeout - no response received'));\n }\n },\n 5 * 60 * 1000\n );\n timeout.unref();\n });\n}\n\n/**\n * Register a new OAuth client dynamically\n */\nasync function dynamicClientRegistration(\n envConfig: EnvironmentConfig,\n clientName: string = 'Gravity CLI'\n): Promise<{ client_id: string; client_secret: string }> {\n stderr(' Registering OAuth client...');\n\n const registrationUrl = `${envConfig.apiUrl}/api/v2/oauth/register`;\n\n const registrationData = {\n client_name: clientName,\n redirect_uris: [REDIRECT_URI],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'client_secret_basic',\n scope: 'workspace:admin',\n };\n\n const response = await fetch(registrationUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(registrationData),\n });\n\n if (!response.ok) {\n throw new Error(`Client registration failed: ${response.status} - ${await response.text()}`);\n }\n\n return (await response.json()) as { client_id: string; client_secret: string };\n}\n\nexport interface OAuthFlowOptions {\n env: string;\n envConfig: EnvironmentConfig;\n credentialsManager: CredentialsManager;\n clientName?: string;\n}\n\n/**\n * Perform the full OAuth2 browser-based flow with PKCE.\n *\n * This always opens the browser for authorization. It never returns a cached\n * token — that's the job of createAuthenticatedContext. The only thing reused\n * is the registered OAuth client ID (which is identity, not auth).\n */\nexport async function performOAuthFlow(options: OAuthFlowOptions): Promise<AuthResult> {\n const { env, envConfig, credentialsManager, clientName = 'Gravity CLI' } = options;\n let hasRetried = false;\n\n while (true) {\n // Reuse registered client credentials if available, otherwise register\n let creds = credentialsManager.load(env);\n if (!creds || !creds.clientId) {\n const registration = await dynamicClientRegistration(envConfig, clientName);\n creds = {\n clientId: registration.client_id,\n clientSecret: registration.client_secret,\n };\n credentialsManager.save(env, creds);\n } else {\n stderr(' Using cached client credentials');\n }\n\n const { codeVerifier, codeChallenge } = generatePKCE();\n const state = randomBytes(32).toString('base64url');\n\n const authParams = new URLSearchParams({\n response_type: 'code',\n client_id: creds.clientId,\n redirect_uri: REDIRECT_URI,\n scope: 'workspace:admin',\n state: state,\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n });\n\n const authUrl = `${envConfig.apiUrl}/api/v2/oauth/authorize?${authParams}`;\n\n const callbackPromise = startCallbackServer();\n\n stderr('\\n Opening browser for authorization...');\n stderr(` If browser doesn't open, visit:\\n ${authUrl}\\n`);\n openBrowser(authUrl);\n\n stderr(' Waiting for authorization (timeout: 5 minutes)...');\n let code: string;\n let receivedState: string;\n try {\n ({ code, state: receivedState } = await callbackPromise);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (!hasRetried && isOAuthError(msg, 'invalid_client')) {\n stderr(' Cached client credentials expired, re-registering...');\n credentialsManager.clear(env);\n hasRetried = true;\n continue;\n }\n throw err;\n }\n\n if (receivedState !== state) {\n throw new Error('State mismatch - possible CSRF attack');\n }\n\n stderr(' Authorization code received!');\n stderr(' Exchanging code for tokens...');\n\n const tokenUrl = `${envConfig.apiUrl}/api/v2/oauth/token`;\n const authHeader = Buffer.from(`${creds.clientId}:${creds.clientSecret}`).toString('base64');\n\n const tokenResponse = await fetch(tokenUrl, {\n method: 'POST',\n headers: {\n Authorization: `Basic ${authHeader}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code: code,\n redirect_uri: REDIRECT_URI,\n code_verifier: codeVerifier,\n }),\n });\n\n if (!tokenResponse.ok) {\n const body = await tokenResponse.text();\n if (!hasRetried && isOAuthError(body, 'invalid_client')) {\n stderr(' Cached client credentials expired, re-registering...');\n credentialsManager.clear(env);\n hasRetried = true;\n continue;\n }\n throw new Error(`Token exchange failed: ${tokenResponse.status} - ${body}`);\n }\n\n const tokenData = (await tokenResponse.json()) as Record<string, unknown>;\n const { accessToken, refreshToken, expiresIn } = validateTokenResponse(tokenData);\n\n creds.accessToken = accessToken;\n creds.refreshToken = refreshToken ?? creds.refreshToken;\n creds.expiresAt = new Date(Date.now() + expiresIn * 1000).toISOString();\n\n credentialsManager.save(env, creds);\n stderr(' Authentication successful!');\n\n return { accessToken, credentials: creds };\n }\n}\n\n/**\n * Refresh an access token using a stored refresh token.\n * Returns updated credentials on success, null on failure.\n */\nexport async function refreshAccessToken(\n envConfig: EnvironmentConfig,\n creds: CLICredentials,\n credentialsManager: CredentialsManager,\n env: string\n): Promise<CLICredentials | null> {\n if (!creds.refreshToken || !creds.clientId || !creds.clientSecret) {\n stderr(' Cannot refresh: missing credentials (re-login required)');\n return null;\n }\n\n const tokenUrl = `${envConfig.apiUrl}/api/v2/oauth/token`;\n const authHeader = Buffer.from(`${creds.clientId}:${creds.clientSecret}`).toString('base64');\n\n try {\n const response = await fetch(tokenUrl, {\n method: 'POST',\n headers: {\n Authorization: `Basic ${authHeader}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: creds.refreshToken,\n }),\n });\n\n if (!response.ok) {\n const body = await response.text();\n const isExpiredRefresh = isOAuthError(body, 'invalid_grant');\n if (isExpiredRefresh) {\n stderr(' Refresh token expired, re-login required');\n } else {\n stderr(` Token refresh failed (${response.status}), clearing credentials`);\n }\n credentialsManager.clear(env);\n return null;\n }\n\n const tokenData = (await response.json()) as Record<string, unknown>;\n const { accessToken, refreshToken, expiresIn } = validateTokenResponse(tokenData);\n\n const updated: CLICredentials = {\n ...creds,\n accessToken,\n refreshToken: refreshToken ?? creds.refreshToken,\n expiresAt: new Date(Date.now() + expiresIn * 1000).toISOString(),\n };\n\n credentialsManager.save(env, updated);\n return updated;\n } catch (err) {\n stderr(` Token refresh error: ${err instanceof Error ? err.message : 'unknown'}`);\n credentialsManager.clear(env);\n return null;\n }\n}\n","/**\n * CLI terminal UI utilities\n *\n * Provides interactive terminal UI components for CLI tools\n */\n\nimport * as readline from 'readline';\n\nexport interface SelectOption<T> {\n item: T;\n label: string;\n detail?: string;\n}\n\nexport interface SelectFromListOptions<T> {\n title?: string;\n labelFn?: (item: T) => string;\n detailFn?: (item: T) => string | null;\n env?: string;\n emptyMessage?: string;\n allowNew?: boolean;\n newLabel?: string;\n}\n\nexport interface SelectResult<T> {\n item: T | null;\n isNew: boolean;\n}\n\nconst NEW_ITEM_MARKER = Symbol('NEW_ITEM');\n\n/**\n * Interactive list picker using arrow keys\n */\nexport async function selectFromList<T>(\n items: T[],\n options: SelectFromListOptions<T> = {}\n): Promise<SelectResult<T>> {\n const {\n title = 'Select an item',\n labelFn = (item: T) => String((item as any).name || (item as any).title || item),\n detailFn = null,\n env = null,\n emptyMessage = 'No items found.',\n allowNew = false,\n newLabel = 'Create new...',\n } = options;\n\n if ((!items || items.length === 0) && !allowNew) {\n console.log(`\\n ${emptyMessage}`);\n return { item: null, isNew: false };\n }\n\n // Prepend \"Create new\" option if allowed\n const displayItems: (T | typeof NEW_ITEM_MARKER)[] = allowNew\n ? [NEW_ITEM_MARKER, ...items]\n : items;\n\n return new Promise((resolve) => {\n let selectedIndex = allowNew ? 1 : 0;\n let filterText = '';\n\n const getFilteredItems = (): (T | typeof NEW_ITEM_MARKER)[] => {\n if (!filterText) return displayItems;\n const lower = filterText.toLowerCase();\n return displayItems.filter((item) => {\n if (item === NEW_ITEM_MARKER) return true;\n const label = labelFn(item);\n return label.toLowerCase().includes(lower);\n });\n };\n\n const render = (): void => {\n const filtered = getFilteredItems();\n\n // Clear screen and move cursor to top\n process.stdout.write('\\x1B[2J\\x1B[H');\n\n console.log('='.repeat(60));\n console.log(`${title} (↑/↓ to move, Enter to select, Esc to cancel)`);\n console.log('='.repeat(60));\n if (env) {\n console.log(`Environment: ${env}`);\n }\n console.log(`Filter: ${filterText}${filterText ? '' : '(type to filter)'}`);\n console.log('');\n\n if (filtered.length === 0) {\n console.log(` ${emptyMessage}`);\n console.log('');\n return;\n }\n\n // Show up to 15 items around the selected one\n const maxVisible = 15;\n let startIdx = Math.max(0, selectedIndex - Math.floor(maxVisible / 2));\n let endIdx = Math.min(filtered.length, startIdx + maxVisible);\n if (endIdx - startIdx < maxVisible && startIdx > 0) {\n startIdx = Math.max(0, endIdx - maxVisible);\n }\n\n if (startIdx > 0) {\n console.log(` ... ${startIdx} more above ...`);\n }\n\n for (let i = startIdx; i < endIdx; i++) {\n const item = filtered[i]!;\n const prefix = i === selectedIndex ? '> ' : ' ';\n\n let line: string;\n if (item === NEW_ITEM_MARKER) {\n line = `\\x1B[32m${newLabel}\\x1B[0m`; // Green color for \"Create new\"\n } else {\n const typedItem = item as T;\n line = labelFn(typedItem);\n if (detailFn) {\n const detail = detailFn(typedItem);\n if (detail) {\n line = `${line} \\x1B[90m${detail}\\x1B[0m`;\n }\n }\n }\n\n if (i === selectedIndex) {\n console.log(`\\x1B[7m${prefix}${line}\\x1B[0m`);\n } else {\n console.log(`${prefix}${line}`);\n }\n }\n\n if (endIdx < filtered.length) {\n console.log(` ... ${filtered.length - endIdx} more below ...`);\n }\n\n console.log('');\n console.log(` ${filtered.length} item(s)`);\n };\n\n // Set up raw mode for arrow key input\n readline.emitKeypressEvents(process.stdin);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n }\n\n render();\n\n const handleKeypress = (str: string | undefined, key: readline.Key): void => {\n const filtered = getFilteredItems();\n\n if (key.name === 'up') {\n selectedIndex = Math.max(0, selectedIndex - 1);\n render();\n } else if (key.name === 'down') {\n selectedIndex = Math.min(filtered.length - 1, selectedIndex + 1);\n render();\n } else if (key.name === 'return') {\n cleanup();\n if (filtered.length > 0 && selectedIndex < filtered.length) {\n const selected = filtered[selectedIndex]!;\n if (selected === NEW_ITEM_MARKER) {\n resolve({ item: null, isNew: true });\n } else {\n resolve({ item: selected as T, isNew: false });\n }\n } else {\n resolve({ item: null, isNew: false });\n }\n } else if (key.name === 'escape' || (key.ctrl && key.name === 'c')) {\n cleanup();\n resolve({ item: null, isNew: false });\n } else if (key.name === 'backspace') {\n filterText = filterText.slice(0, -1);\n selectedIndex = allowNew ? 0 : 0;\n render();\n } else if (str && str.length === 1 && !key.ctrl && !key.meta) {\n filterText += str;\n selectedIndex = allowNew ? 0 : 0;\n render();\n }\n };\n\n const cleanup = (): void => {\n process.stdin.removeListener('keypress', handleKeypress);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(false);\n }\n process.stdin.pause();\n process.stdout.write('\\x1B[2J\\x1B[H');\n };\n\n process.stdin.on('keypress', handleKeypress);\n process.stdin.resume();\n });\n}\n\n/**\n * Print a table of items\n */\nexport function printTable<T>(\n items: T[],\n columns: Array<{\n header: string;\n getValue: (item: T) => string;\n maxWidth?: number;\n }>,\n options: { title?: string; env?: string } = {}\n): void {\n if (!items || items.length === 0) {\n console.log('\\nNo items found.');\n return;\n }\n\n if (options.title) {\n console.log(`\\n=== ${options.title} ===`);\n }\n if (options.env) {\n console.log(`Environment: ${options.env}`);\n }\n console.log('');\n\n // Calculate column widths\n const widths = columns.map((col) => {\n const maxContent = Math.max(...items.map((item) => String(col.getValue(item) ?? '').length));\n const width = Math.max(col.header.length, maxContent);\n return col.maxWidth ? Math.min(width, col.maxWidth) : width;\n });\n\n // Print header\n const headerLine = columns.map((col, i) => col.header.padEnd(widths[i]!)).join(' ');\n console.log(headerLine);\n console.log(widths.map((w) => '-'.repeat(w)).join(' '));\n\n // Print rows\n for (const item of items) {\n const row = columns\n .map((col, i) => {\n const value = String(col.getValue(item) ?? '');\n const width = widths[i]!;\n return value.slice(0, width).padEnd(width);\n })\n .join(' ');\n console.log(row);\n }\n\n console.log('');\n console.log(`Total: ${items.length} item(s)`);\n}\n\n/**\n * Format a timestamp for display\n */\nexport function formatTimestamp(isoString: string | null | undefined): string {\n if (!isoString) return '';\n const date = new Date(isoString);\n const now = new Date();\n const diff = now.getTime() - date.getTime();\n\n if (diff < 60000) return 'just now';\n if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;\n if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;\n if (diff < 604800000) return `${Math.floor(diff / 86400000)}d ago`;\n\n return date.toLocaleDateString();\n}\n\n/**\n * Wrap text to a maximum width\n */\nexport function wrapText(text: string, width: number = 70): string[] {\n const words = text.split(' ');\n const lines: string[] = [];\n let currentLine = '';\n\n for (const word of words) {\n if (currentLine.length + word.length + 1 <= width) {\n currentLine += (currentLine ? ' ' : '') + word;\n } else {\n if (currentLine) lines.push(currentLine);\n currentLine = word;\n }\n }\n if (currentLine) lines.push(currentLine);\n return lines;\n}\n\n/**\n * Print a chat message with formatting\n */\nexport function printMessage(\n content: string,\n role: 'user' | 'assistant' | 'system',\n indent: string = ' '\n): void {\n const roleColors: Record<string, string> = {\n user: '\\x1B[34m', // Blue\n assistant: '\\x1B[32m', // Green\n system: '\\x1B[90m', // Gray\n };\n const resetColor = '\\x1B[0m';\n const color = roleColors[role] || resetColor;\n\n const label = role === 'user' ? 'You' : role === 'assistant' ? 'Assistant' : 'System';\n console.log(`${indent}${color}[${label}]${resetColor}`);\n\n const lines = content.split('\\n');\n for (const line of lines) {\n const wrapped = wrapText(line, 70);\n for (const wrappedLine of wrapped) {\n console.log(`${indent} ${wrappedLine}`);\n }\n }\n console.log('');\n}\n\n/**\n * Clear the terminal screen\n */\nexport function clearScreen(): void {\n process.stdout.write('\\x1B[2J\\x1B[H');\n}\n","/**\n * AG-UI Client for CLI chat interactions\n *\n * Implements the AG-UI (Agent-User Interaction) protocol for streaming\n * chat responses. See: https://docs.ag-ui.com/concepts/events\n */\n\nimport type { ConciergeAppContextPayload } from '../lib/cli-client-context';\n\n/**\n * AG-UI event types\n */\nexport type AGUIEventType =\n | 'RUN_STARTED'\n | 'RUN_FINISHED'\n | 'RUN_ERROR'\n | 'TEXT_MESSAGE_START'\n | 'TEXT_MESSAGE_CONTENT'\n | 'TEXT_MESSAGE_END'\n | 'TOOL_CALL_START'\n | 'TOOL_CALL_ARGS'\n | 'TOOL_CALL_END'\n | 'TOOL_CALL_RESULT'\n | 'STATE_SNAPSHOT'\n | 'STATE_DELTA'\n // Lowercase variants (some backends use these)\n | 'run_started'\n | 'run_finished'\n | 'run_error'\n | 'text_message_start'\n | 'text_message_content'\n | 'text_message_end'\n | 'tool_call_start'\n | 'tool_call_args'\n | 'tool_call_end'\n | 'tool_call_result'\n | 'state_snapshot'\n | 'state_delta'\n | 'done';\n\nexport interface AGUIEvent {\n type: AGUIEventType;\n messageId?: string;\n role?: string;\n delta?: string;\n content?: string;\n message?: string;\n code?: string;\n toolCallId?: string;\n toolCallName?: string;\n result?: any;\n snapshot?: any;\n operations?: any[];\n [key: string]: any;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n}\n\nexport interface AGUIClientOptions {\n baseUrl: string;\n workspaceUuid?: string;\n chatId?: number; // Numeric chat ID (not UUID)\n /** Full URL override — when provided, baseUrl/workspaceUuid/chatId are ignored for POST */\n endpointUrl?: string;\n accessToken: string;\n debug?: boolean;\n /** Model field sent in request body (default: 'manager'). Set to undefined to omit. */\n model?: string;\n /** Concierge / client context forwarded to the API (e.g. CLI surface hints). */\n appContext?: ConciergeAppContextPayload;\n}\n\n/**\n * AG-UI Client for streaming chat responses\n */\nexport class AGUIClient {\n private endpointUrl: string;\n private baseUrl: string;\n private workspaceUuid: string;\n private chatId: number;\n private accessToken: string;\n private debug: boolean;\n private model: string | undefined;\n private appContext: ConciergeAppContextPayload | undefined;\n\n constructor(options: AGUIClientOptions) {\n this.baseUrl = options.baseUrl;\n this.workspaceUuid = options.workspaceUuid ?? '';\n this.chatId = options.chatId ?? 0;\n if (!options.endpointUrl && (!options.workspaceUuid || options.chatId === undefined)) {\n throw new Error('AGUIClient requires workspaceUuid and chatId, or endpointUrl');\n }\n this.endpointUrl =\n options.endpointUrl ??\n `${options.baseUrl}/api/v2/w/${options.workspaceUuid}/web-chat/${options.chatId}/chat/agui`;\n this.accessToken = options.accessToken;\n this.debug = options.debug ?? false;\n this.model = 'model' in options ? options.model : 'manager';\n this.appContext = options.appContext;\n }\n\n private inferenceStatusUrl(): string | null {\n // chatId is `number`; treat 0 / negative as \"no chat\" (use <= 0 instead of\n // a falsy check so a deliberate sentinel of 0 doesn't accidentally mean\n // \"valid chat\").\n if (!this.workspaceUuid || this.chatId <= 0) return null;\n return `${this.baseUrl}/api/v2/w/${this.workspaceUuid}/chats/${this.chatId}/inference/status`;\n }\n\n private async waitForInferenceInactive(maxWaitMs = 60_000): Promise<boolean> {\n const url = this.inferenceStatusUrl();\n if (!url) return false;\n const deadline = Date.now() + maxWaitMs;\n while (Date.now() < deadline) {\n try {\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${this.accessToken}` },\n });\n if (res.ok) {\n const body = (await res.json()) as { active?: boolean };\n if (!body.active) return true;\n }\n } catch (err) {\n // Transient network errors (DNS blips, connection resets) shouldn't\n // crash the 409-retry loop. Log under --debug and keep polling\n // until the deadline; the caller will fall back to the original\n // 409 error if we can't confirm inactive in time.\n if (this.debug) {\n console.log(\n `[DEBUG] waitForInferenceInactive fetch failed: ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n }\n }\n await new Promise((r) => setTimeout(r, 2000));\n }\n return false;\n }\n\n /**\n * Send messages and stream the response\n */\n async sendMessage(\n messages: ChatMessage[],\n onEvent: (event: AGUIEvent) => void,\n options?: AguiStreamOptions\n ): Promise<void> {\n return this.streamRequest({ messages }, onEvent, options);\n }\n\n /**\n * Stream an AG-UI request (initial messages or HITL resume).\n */\n async streamRequest(\n request: AguiRequestBody,\n onEvent: (event: AGUIEvent) => void,\n options?: AguiStreamOptions\n ): Promise<void> {\n const body = JSON.stringify({\n ...(this.model ? { model: this.model } : {}),\n messages: request.messages ?? [],\n ...(this.appContext ? { appContext: this.appContext } : {}),\n ...(request.resumeValue !== undefined ? { resumeValue: request.resumeValue } : {}),\n ...(request.resumeInterruptId ? { resumeInterruptId: request.resumeInterruptId } : {}),\n ...(options?.autoApprove ? { context: { autoApprove: true } } : {}),\n });\n\n if (this.debug) {\n console.log(`\\n[DEBUG] POST ${this.endpointUrl}`);\n console.log(\n `[DEBUG] Body: ${request.resumeValue !== undefined ? 'resume' : `${(request.messages ?? []).length} message(s)`}`\n );\n }\n\n await this.postStream(body, onEvent, options);\n }\n\n private async postStream(\n body: string,\n onEvent: (event: AGUIEvent) => void,\n options?: AguiStreamOptions,\n conflictRetries = 0\n ): Promise<void> {\n const response = await fetch(this.endpointUrl, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.accessToken}`,\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n },\n body,\n });\n\n if (this.debug) {\n console.log(`[DEBUG] Response status: ${response.status}`);\n }\n\n if (response.status === 409 && conflictRetries < 3) {\n const ready = await this.waitForInferenceInactive();\n if (ready) {\n await this.postStream(body, onEvent, options, conflictRetries + 1);\n return;\n }\n }\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => '');\n if (this.debug) {\n console.log(`[DEBUG] Error response: ${errorText}`);\n }\n throw new Error(\n `Chat request failed: ${response.status}${errorText ? `: ${errorText.slice(0, 200)}` : ''}`\n );\n }\n\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') {\n onEvent({ type: 'done' });\n continue;\n }\n try {\n const event = JSON.parse(data) as AGUIEvent;\n onEvent(event);\n } catch {\n // Ignore parse errors for malformed events\n }\n }\n }\n }\n }\n}\n\nexport interface AguiStreamOptions {\n autoApprove?: boolean;\n}\n\nexport interface AguiRequestBody {\n messages?: ChatMessage[];\n resumeValue?: string;\n resumeInterruptId?: string;\n}\n\n/**\n * Helper to check if an event is a text content event\n */\nexport function isTextContentEvent(event: AGUIEvent): boolean {\n const type = event.type.toLowerCase();\n return type === 'text_message_content';\n}\n\n/**\n * Helper to check if an event is an error event\n */\nexport function isErrorEvent(event: AGUIEvent): boolean {\n const type = event.type.toLowerCase();\n return type === 'run_error';\n}\n\n/**\n * Helper to extract text delta from an event\n */\nexport function getTextDelta(event: AGUIEvent): string | null {\n if (isTextContentEvent(event) && event.delta) {\n return event.delta;\n }\n return null;\n}\n\n/**\n * Helper to extract error message from an event\n */\nexport function getErrorMessage(event: AGUIEvent): string | null {\n if (isErrorEvent(event)) {\n return event.message || event.code || 'Unknown error';\n }\n return null;\n}\n","/**\n * CLI utilities for Gravity Rail\n *\n * This module provides utilities for building CLI tools that interact\n * with the Gravity Rail API, including:\n *\n * - OAuth2 authentication with PKCE\n * - Credential caching\n * - Interactive terminal UI\n * - AG-UI streaming chat client\n */\n\n// Configuration\nexport {\n ENVIRONMENTS,\n CALLBACK_PORT,\n CALLBACK_PATH,\n REDIRECT_URI,\n getEnvironmentConfig,\n type EnvironmentConfig,\n} from './config';\n\n// Authentication\nexport {\n CredentialsManager,\n generatePKCE,\n openBrowser,\n startCallbackServer,\n performOAuthFlow,\n refreshAccessToken,\n type CLICredentials,\n type AuthResult,\n type OAuthFlowOptions,\n} from './auth';\n\n// Terminal UI\nexport {\n selectFromList,\n printTable,\n formatTimestamp,\n wrapText,\n printMessage,\n clearScreen,\n type SelectFromListOptions,\n type SelectResult,\n} from './ui';\n\n// AG-UI Client\nexport {\n AGUIClient,\n isTextContentEvent,\n isErrorEvent,\n getTextDelta,\n getErrorMessage,\n type AGUIEvent,\n type AGUIEventType,\n type ChatMessage as AGUIChatMessage,\n type AGUIClientOptions,\n} from './agui';\n","export class CLIError extends Error {\n constructor(\n message: string,\n public exitCode: number = 1\n ) {\n super(message);\n this.name = 'CLIError';\n }\n}\n\nexport class AuthRequiredError extends CLIError {\n constructor(message = 'Not authenticated. Run `gr login` or set GRAVITY_RAIL_API_KEY.') {\n super(message, 2);\n this.name = 'AuthRequiredError';\n }\n}\n\nexport function handleError(err: unknown): never {\n if (err instanceof CLIError) {\n process.stderr.write(`Error: ${err.message}\\n`);\n process.exit(err.exitCode);\n }\n\n if (err instanceof Error) {\n process.stderr.write(`Error: ${err.message}\\n`);\n if ('errors' in err && Array.isArray((err as any).errors)) {\n for (const e of (err as any).errors) {\n process.stderr.write(` - ${e}\\n`);\n }\n }\n if ('statusCode' in err && (err as any).statusCode === 401) {\n process.stderr.write(\n `\\nHint: Run \"gr login\" to authenticate, or set GRAVITY_RAIL_API_KEY for non-interactive use.\\n`\n );\n }\n process.exit(1);\n }\n\n process.stderr.write(`Error: ${String(err)}\\n`);\n process.exit(1);\n}\n","import type { ArgDef, ParsedArgs } from './types';\nimport { CLIError } from './errors';\n\n// ── Response shape detection ─────────────────────────────────────────\n\n/** Metadata extracted from a paginated API response */\nexport interface PaginationMeta {\n /** Total number of items across all pages (page-based only) */\n total?: number;\n /** Current page number (page-based only) */\n page?: number;\n /** Total pages (page-based only) */\n totalPages?: number;\n /** Whether more pages exist (cursor-based only) */\n hasMore?: boolean;\n /** Cursor for next page (cursor-based only) */\n nextCursor?: string;\n}\n\n/** Explicit pagination contract passed from commands to outputData */\nexport interface ListResult {\n items: unknown[];\n meta?: PaginationMeta;\n supportsAll?: boolean;\n}\n\n/** Type guard: is the value a ListResult (explicit contract)? */\nexport function isListResult(data: unknown): data is ListResult {\n if (!data || typeof data !== 'object' || Array.isArray(data)) return false;\n const obj = data as Record<string, unknown>;\n return (\n Array.isArray(obj.items) &&\n ('supportsAll' in obj ||\n ('meta' in obj && (obj.meta === undefined || typeof obj.meta === 'object')))\n );\n}\n\n/** Check if a response looks like a page-based paginated envelope.\n * Matches both `{ items, total, totalPages, page }` (standard) and\n * `{ items, total, page, pageSize }` (legacy — e.g. InvitationListResponse,\n * InquiryListResponse). This is a pure type guard with no side effects;\n * totalPages computation for legacy shapes happens in extractPaginationMeta. */\nexport function isPagePaginatedResponse(data: unknown): data is {\n items: unknown[];\n total: number;\n page: number;\n totalPages?: number;\n pageSize?: number;\n} {\n if (!data || typeof data !== 'object') return false;\n const obj = data as Record<string, unknown>;\n if (!Array.isArray(obj.items) || typeof obj.page !== 'number') return false;\n\n // Standard shape: has totalPages\n if (typeof obj.totalPages === 'number') return true;\n\n // Legacy shape: has total + pageSize but no totalPages\n if (typeof obj.total === 'number' && typeof obj.pageSize === 'number') return true;\n\n return false;\n}\n\n/** Check if a response looks like a cursor-based paginated envelope */\nexport function isCursorPaginatedResponse(data: unknown): data is {\n items: unknown[];\n hasMore: boolean;\n nextCursor?: string;\n} {\n if (!data || typeof data !== 'object') return false;\n const obj = data as Record<string, unknown>;\n return Array.isArray(obj.items) && typeof obj.hasMore === 'boolean';\n}\n\n/** Check if a response is any paginated envelope ({ items: [...], ... }) */\nexport function isPaginatedResponse(data: unknown): boolean {\n return isPagePaginatedResponse(data) || isCursorPaginatedResponse(data);\n}\n\n/** Extract pagination metadata from a response, or return undefined for non-paginated responses.\n * For legacy shapes without totalPages, computes it from total/pageSize. */\nexport function extractPaginationMeta(data: unknown): PaginationMeta | undefined {\n if (isPagePaginatedResponse(data)) {\n const totalPages =\n data.totalPages ?? (data.pageSize ? Math.ceil(data.total / data.pageSize) : undefined);\n return {\n total: data.total,\n page: data.page,\n totalPages,\n };\n }\n if (isCursorPaginatedResponse(data)) {\n return {\n hasMore: data.hasMore,\n nextCursor: data.nextCursor,\n };\n }\n return undefined;\n}\n\n// ── Warning formatting ───────────────────────────────────────────────\n\n/** Format a pagination warning for stderr. Returns undefined if no warning needed.\n * When `supportsAll` is false, the \"Use --all\" hint is omitted because the\n * command does not actually expose the --all flag. */\nexport function formatPaginationWarning(\n meta: PaginationMeta | undefined,\n supportsAll: boolean = true\n): string | undefined {\n if (!meta) return undefined;\n\n const allHint = supportsAll ? ' Use --all to fetch all pages.' : '';\n\n // Page-based: warn when there are multiple pages\n if (meta.totalPages !== undefined && meta.totalPages > 1) {\n const pageNum = meta.page ?? 1;\n return `Showing page ${pageNum} of ${meta.totalPages} (${meta.total} total items).${allHint}`;\n }\n\n // Cursor-based: warn when more pages exist\n if (meta.hasMore === true) {\n return `More results available.${allHint}`;\n }\n\n return undefined;\n}\n\n// ── Unwrapping ───────────────────────────────────────────────────────\n\n/** Unwrap items from a paginated response or return the data as-is if it's an array */\nexport function unwrapItems(data: unknown): unknown[] {\n if (Array.isArray(data)) return data;\n if (\n data &&\n typeof data === 'object' &&\n 'items' in data &&\n Array.isArray((data as Record<string, unknown>).items)\n ) {\n return (data as Record<string, unknown>).items as unknown[];\n }\n return [data];\n}\n\n// ── Arg definitions ──────────────────────────────────────────────────\n\n/** Default pagination args for list commands (page, page-size, all). No search. */\nexport const LIST_PAGINATION_ARGS: ArgDef[] = [\n { name: 'page', description: 'Page number' },\n { name: 'page-size', description: 'Page size' },\n { name: 'all', description: 'Fetch all pages and return combined results', isFlag: true },\n];\n\n// ── Arg-to-options helpers ───────────────────────────────────────────\n\n/** Convert parsed CLI args to API pagination options */\nexport function parsePaginationArgs(args: ParsedArgs): {\n page?: number;\n pageSize?: number;\n all?: boolean;\n} {\n const result: { page?: number; pageSize?: number; all?: boolean } = {};\n\n if (args.all === true) {\n result.all = true;\n }\n\n if (args.page !== undefined) {\n const num = Number(args.page);\n if (isNaN(num) || num < 1) throw new CLIError('--page must be a positive integer');\n result.page = num;\n }\n\n if (args['page-size'] !== undefined) {\n const num = Number(args['page-size']);\n if (isNaN(num) || num < 1) throw new CLIError('--page-size must be a positive integer');\n if (num > 100) throw new CLIError('--page-size must be at most 100 (API limit)');\n result.pageSize = num;\n }\n\n return result;\n}\n\n// ── fetchAll helpers ─────────────────────────────────────────────────\n\nconst MAX_PAGE_SIZE = 100;\nconst MAX_PAGES = 200; // Safety limit to prevent infinite loops\n\n/**\n * Fetch all pages from a page-based paginated endpoint.\n * The fetcher receives { page, pageSize } and should return the raw API response.\n * Throws CLIError if MAX_PAGES is reached without exhausting all pages.\n */\nexport async function fetchAllPages(\n fetcher: (opts: { page: number; pageSize: number }) => Promise<unknown>\n): Promise<unknown[]> {\n const allItems: unknown[] = [];\n let page = 1;\n\n while (page <= MAX_PAGES) {\n const result = await fetcher({ page, pageSize: MAX_PAGE_SIZE });\n const items = unwrapItems(result);\n allItems.push(...items);\n\n // Use server metadata for termination\n const meta = extractPaginationMeta(result);\n if (meta?.totalPages !== undefined) {\n if (page >= meta.totalPages) break;\n } else if (!isPagePaginatedResponse(result)) {\n // Raw array or no metadata — single fetch is enough\n if (items.length < MAX_PAGE_SIZE) break;\n }\n\n if (page === MAX_PAGES) {\n throw new CLIError(\n `Reached maximum page limit (${MAX_PAGES}). Results may be incomplete.`\n );\n }\n\n page++;\n }\n\n return allItems;\n}\n\n/**\n * Fetch all pages from a cursor-based paginated endpoint.\n * The fetcher receives { cursor? } and should return the raw API response.\n * Throws CLIError if MAX_PAGES is reached without exhausting all pages.\n */\nexport async function fetchAllCursorPages(\n fetcher: (opts: { cursor?: string }) => Promise<unknown>\n): Promise<unknown[]> {\n const allItems: unknown[] = [];\n let cursor: string | undefined;\n let pages = 0;\n\n while (pages < MAX_PAGES) {\n const result = await fetcher({ cursor });\n const items = unwrapItems(result);\n allItems.push(...items);\n pages++;\n\n if (isCursorPaginatedResponse(result) && result.hasMore && result.nextCursor) {\n cursor = result.nextCursor;\n } else {\n break;\n }\n\n if (pages === MAX_PAGES) {\n throw new CLIError(\n `Reached maximum page limit (${MAX_PAGES}). Results may be incomplete.`\n );\n }\n }\n\n return allItems;\n}\n\n// ── ListResult factory ──────────────────────────────────────────────\n\n/**\n * Wrap a raw API response into a ListResult with explicit pagination metadata.\n * Works with both page-based and cursor-based responses, as well as plain arrays.\n *\n * @param data - Raw API response (paginated envelope or plain array)\n * @param supportsAll - Whether the calling command exposes --all\n */\nexport function listResult(data: unknown, supportsAll: boolean = false): ListResult {\n return {\n items: unwrapItems(data),\n meta: extractPaginationMeta(data),\n supportsAll,\n };\n}\n","import { printTable } from '../cli-utils';\nimport {\n type PaginationMeta,\n isListResult,\n extractPaginationMeta,\n formatPaginationWarning,\n unwrapItems,\n} from './pagination';\n\nexport type OutputFormat = 'json' | 'jsonl' | 'table';\n\nexport interface OutputOptions {\n outputFormat: OutputFormat;\n}\n\nexport interface TableColumn<T> {\n header: string;\n getValue: (item: T) => string;\n maxWidth?: number;\n}\n\n/** Detect default output format based on whether stdout is a TTY */\nexport function detectOutputFormat(explicit?: string): OutputFormat {\n if (explicit) return explicit as OutputFormat;\n return process.stdout.isTTY ? 'table' : 'json';\n}\n\n/**\n * Write a list of items to stdout in the requested format.\n *\n * Accepts:\n * - A `ListResult` (explicit contract with items, meta, supportsAll) — preferred.\n * - Raw arrays, paginated responses ({ items: [...] }), or any object — legacy.\n *\n * When a `ListResult` is passed, its explicit `meta` and `supportsAll` are used.\n * When raw data is passed, pagination metadata is auto-detected with\n * `supportsAll: false` as the safe default.\n *\n * The optional `paginationMeta` and `supportsAll` parameters are kept for\n * backward compatibility but are ignored when a `ListResult` is passed.\n */\nexport function outputData(\n data: unknown,\n opts: OutputOptions,\n columns?: TableColumn<any>[],\n paginationMeta?: PaginationMeta,\n supportsAll?: boolean\n): void {\n let items: unknown[];\n let meta: PaginationMeta | undefined;\n let allSupported: boolean;\n\n if (isListResult(data)) {\n // Explicit contract: use ListResult fields directly\n items = data.items;\n meta = data.meta;\n allSupported = data.supportsAll ?? false;\n } else {\n // Legacy path: auto-detect from raw data\n items = unwrapItems(data);\n meta = paginationMeta ?? extractPaginationMeta(data);\n allSupported = supportsAll ?? false;\n }\n\n const warning = formatPaginationWarning(meta, allSupported);\n if (warning) {\n process.stderr.write(warning + '\\n');\n }\n\n switch (opts.outputFormat) {\n case 'json':\n process.stdout.write(JSON.stringify(items, null, 2) + '\\n');\n break;\n case 'jsonl':\n for (const item of items) {\n process.stdout.write(JSON.stringify(item) + '\\n');\n }\n break;\n case 'table':\n if (columns) {\n printTable(items, columns);\n } else {\n process.stdout.write(JSON.stringify(items, null, 2) + '\\n');\n }\n break;\n }\n}\n\n/** Write a single object to stdout in the requested format */\nexport function outputSingle<T>(data: T, opts: OutputOptions, columns?: TableColumn<T>[]): void {\n switch (opts.outputFormat) {\n case 'json':\n process.stdout.write(JSON.stringify(data, null, 2) + '\\n');\n break;\n case 'jsonl':\n process.stdout.write(JSON.stringify(data) + '\\n');\n break;\n case 'table':\n if (columns) {\n printTable([data], columns);\n } else {\n process.stdout.write(JSON.stringify(data, null, 2) + '\\n');\n }\n break;\n }\n}\n\n/** Common column factory helpers for domain files */\nexport const COL = {\n id: (): TableColumn<any> => ({ header: 'ID', getValue: (item) => String(item.id ?? '') }),\n uuid: (): TableColumn<any> => ({ header: 'UUID', getValue: (item) => item.uuid ?? '' }),\n name: (): TableColumn<any> => ({ header: 'NAME', getValue: (item) => item.name ?? '' }),\n status: (): TableColumn<any> => ({ header: 'STATUS', getValue: (item) => item.status ?? '' }),\n created: (): TableColumn<any> => ({\n header: 'CREATED',\n getValue: (item) => item.created_at ?? '',\n }),\n updated: (): TableColumn<any> => ({\n header: 'UPDATED',\n getValue: (item) => item.updated_at ?? '',\n }),\n description: (): TableColumn<any> => ({\n header: 'DESCRIPTION',\n getValue: (item) => item.description ?? '',\n }),\n enabled: (): TableColumn<any> => ({\n header: 'ENABLED',\n getValue: (item) => String(item.enabled ?? ''),\n }),\n};\n\n/** Write a status/progress message to stderr (never pollutes stdout) */\nexport function stderr(msg: string): void {\n process.stderr.write(msg + '\\n');\n}\n","import { execSync } from 'child_process';\nimport { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'fs';\nimport { dirname, join } from 'path';\n\nexport interface RealmCredentials {\n token: string;\n workspaceUuid?: string;\n}\n\n/** Walk up from cwd looking for dev-realms.json (like finding package.json) */\nfunction findDevRealmsFile(): string {\n let dir = process.cwd();\n while (dir !== dirname(dir)) {\n const candidate = join(dir, 'dev-realms.json');\n if (existsSync(candidate)) return candidate;\n dir = dirname(dir);\n }\n throw new Error('Cannot find dev-realms.json in any parent directory');\n}\n\nconst DEV_CLOUD_CACHE_DIR = '.dev-cloud';\nconst CACHE_MAX_AGE_MS = 60 * 60 * 1000; // 1 hour\n\nfunction findRepoRoot(): string | undefined {\n let dir = process.cwd();\n while (dir !== dirname(dir)) {\n if (existsSync(join(dir, '.git'))) {\n return dir;\n }\n dir = dirname(dir);\n }\n return undefined;\n}\n\nfunction getDevCloudCacheDir(namespace: string): string {\n const repoRoot = findRepoRoot();\n const base = repoRoot ?? process.cwd();\n return join(base, DEV_CLOUD_CACHE_DIR, namespace);\n}\n\nfunction fetchDevCloudRealms(namespace: string): string {\n const k8sNamespace = `dev-cloud-${namespace}`;\n const cmd = `kubectl exec -n ${k8sNamespace} deploy/env -c devbox -- cat /workspace/dev-realms.json`;\n try {\n return execSync(cmd, { encoding: 'utf-8', timeout: 30000 });\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `Failed to fetch dev-realms.json from dev-cloud pod \"${namespace}\": ${message}`\n );\n }\n}\n\n/**\n * Load (and cache) the dev-realms.json file from a dev-cloud pod.\n * Returns the path to the cached file.\n */\nexport function loadDevCloudRealmFile(namespace: string): string {\n const cacheDir = getDevCloudCacheDir(namespace);\n const cachePath = join(cacheDir, 'dev-realms.json');\n\n // Check cache freshness\n if (existsSync(cachePath)) {\n const stat = statSync(cachePath);\n const age = Date.now() - stat.mtimeMs;\n if (age < CACHE_MAX_AGE_MS) {\n return cachePath;\n }\n }\n\n // Fetch from pod\n const content = fetchDevCloudRealms(namespace);\n mkdirSync(cacheDir, { recursive: true });\n writeFileSync(cachePath, content, 'utf-8');\n return cachePath;\n}\n\nexport function loadRealmCredentials(realm: string, devRealmsPath?: string): RealmCredentials {\n const filePath = devRealmsPath ?? findDevRealmsFile();\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(readFileSync(filePath, 'utf-8'));\n } catch {\n throw new Error(`Cannot read dev-realms.json at ${filePath}`);\n }\n\n const parts = realm.split('/');\n if (parts.length === 1) {\n // Account-level: --realm dr-chen\n const accounts = data._accounts as Record<string, { token?: string }> | undefined;\n const account = accounts?.[parts[0]!];\n if (!account?.token) {\n throw new Error(`Realm account \"${parts[0]}\" not found in dev-realms.json`);\n }\n return { token: account.token };\n } else {\n // Workspace/member: --realm boston-nephrology-clinic/dr-chen\n const [wsName, memberName] = parts;\n const ws = data[wsName!] as\n | { workspaceUuid?: string; members?: Record<string, { token?: string }> }\n | undefined;\n if (!ws) {\n throw new Error(`Realm workspace \"${wsName}\" not found in dev-realms.json`);\n }\n const member = ws.members?.[memberName!];\n if (!member?.token) {\n throw new Error(`Realm member \"${memberName}\" not found in workspace \"${wsName}\"`);\n }\n return { token: member.token, workspaceUuid: ws.workspaceUuid };\n }\n}\n","/**\n * CLI handler for organization-level authentication challenges.\n *\n * When a workspace API call returns a 401 with WWW-Authenticate: Bearer realm=\"org\",\n * the SDK calls this handler. The CLI attempts to satisfy the challenge by:\n *\n * 1. POSTing to /api/v2/o/{org_uuid}/join with the existing bearer token.\n * This works for organizations that allow internal (non-SSO) authentication.\n * The response Set-Cookie header contains the org JWE token.\n *\n * 2. If the org requires SSO, falls back to opening the auth URL in the browser\n * and prompting the user to complete authentication manually, then errors.\n */\n\nimport { execFile } from 'child_process';\nimport type { GravityRailClient } from '@gravity-rail/sdk';\nimport type { OrgAuthInfo } from '@gravity-rail/sdk';\nimport { stderr } from './output';\n\nconst ORG_AUTH_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** Parse an org token value from Set-Cookie header strings. */\nfunction extractOrgTokenFromSetCookies(\n setCookieValues: string[],\n preferredCookieName: string\n): string | undefined {\n let fallback: string | undefined;\n\n for (const value of setCookieValues) {\n const nameValue = value.split(';')[0]?.trim() ?? '';\n const eqIdx = nameValue.indexOf('=');\n if (eqIdx === -1) continue;\n\n const name = nameValue.slice(0, eqIdx).trim();\n const tokenValue = nameValue.slice(eqIdx + 1).trim() || undefined;\n if (!tokenValue) continue;\n\n if (name === preferredCookieName) return tokenValue;\n // Accept any orgToken... or orgSession... cookie as a fallback\n if (!fallback && (name.startsWith('orgToken') || name.startsWith('orgSession'))) {\n fallback = tokenValue;\n }\n }\n\n return fallback;\n}\n\n/**\n * Attempt to satisfy an org auth challenge via the direct join endpoint.\n * Returns the org token string on success, null when SSO is required.\n * Throws on unexpected network / server errors.\n */\nasync function tryDirectJoin(\n apiUrl: string,\n accessToken: string,\n orgAuthInfo: OrgAuthInfo\n): Promise<string | null> {\n const response = await fetch(`${apiUrl}/api/v2/o/${orgAuthInfo.orgUuid}/join`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n },\n body: '{}',\n });\n\n if (response.status === 400) {\n // Org requires SSO — direct join is not permitted for this account\n return null;\n }\n\n if (!response.ok) {\n // Don't include the response body — the backend currently returns safe\n // JSON, but a future change could put PHI or other sensitive data there.\n // Status code is sufficient to disambiguate the failure mode.\n throw new Error(`Org join failed (HTTP ${response.status})`);\n }\n\n // Read Set-Cookie headers to extract the org token value.\n // Node ≥18 exposes getSetCookie() on Headers; fall back to get() for older runtimes.\n const rawHeaders = response.headers as Headers & {\n getSetCookie?: () => string[];\n };\n const setCookies: string[] =\n rawHeaders.getSetCookie?.() ??\n (rawHeaders.get('set-cookie') ? [rawHeaders.get('set-cookie')!] : []);\n\n if (setCookies.length === 0) {\n throw new Error('Org join succeeded but no Set-Cookie header returned');\n }\n\n const orgToken = extractOrgTokenFromSetCookies(setCookies, orgAuthInfo.cookieName);\n if (!orgToken) {\n throw new Error('Org join succeeded but org token cookie not found in Set-Cookie');\n }\n\n return orgToken;\n}\n\n/**\n * Validate that an auth URL is safe to hand to the OS URL opener.\n *\n * `open` / `xdg-open` / `cmd.exe start` will follow any URI scheme the OS\n * registers — including `file://`, `javascript:`, and custom app handlers —\n * so a compromised/MITMed server returning an attacker-controlled `authUrl`\n * could trigger arbitrary URI execution. Restrict to http(s) and require\n * the same parent domain as the configured API host (e.g. SSO login on\n * `app.gravityrail.com` is allowed when the API is `api.gravityrail.com`,\n * but `attacker.example` against `api.gravityrail.com` is rejected).\n *\n * \"Same parent domain\" is a last-2-labels match. This is a heuristic — it\n * does not consult the Public Suffix List, so `foo.co.uk` and `bar.co.uk`\n * would falsely match — but Gravity Rail's auth hosts do not live under\n * those ccTLDs, and the alternative (vendoring `psl`) is overkill for a CLI\n * gating check. The configured `apiUrl` is itself a trust anchor controlled\n * by the user; the threat is a hostile *response* from that API (or a MITM)\n * pivoting the URL opener.\n */\nfunction isAllowedAuthUrl(url: string, apiUrl: string): boolean {\n try {\n const parsed = new URL(url);\n const api = new URL(apiUrl);\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') return false;\n if (parsed.hostname === api.hostname) return true;\n\n const lastTwo = (host: string): string => {\n const parts = host.split('.').filter(Boolean);\n return parts.length >= 2 ? parts.slice(-2).join('.') : host;\n };\n // Reject IP-literal hosts from the parent-domain heuristic — last-2\n // labels of \"1.2.3.4\" would naively match \"3.4\" and admit anything.\n const isIp = /^[0-9.]+$|^\\[.*\\]$/.test(parsed.hostname);\n if (isIp) return false;\n\n return lastTwo(parsed.hostname) === lastTwo(api.hostname);\n } catch {\n return false;\n }\n}\n\n/** Open a URL in the system browser (cross-platform). */\nfunction openBrowser(url: string): void {\n let command: string;\n let args: string[];\n\n if (process.platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (process.platform === 'win32') {\n command = 'cmd.exe';\n args = ['/c', 'start', '', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n execFile(command, args, (_err) => {\n // Failure is non-fatal — the URL is printed to stderr so the user can open it manually.\n });\n}\n\n/**\n * Register a CLI org-auth handler on the given client.\n *\n * The handler satisfies org-auth 401 challenges without relying on browser\n * cookies (which are not available in Node.js):\n *\n * - Non-SSO orgs: calls the join endpoint directly and reads the org token\n * from the Set-Cookie response header, then sets it via client.setOrgToken().\n * The SDK retries the original request with X-Org-Token on the next call.\n *\n * - SSO orgs: opens the browser at the authUrl and returns a timeout error\n * after ORG_AUTH_TIMEOUT_MS, because the SSO token is only ever set as a\n * browser cookie that the CLI cannot intercept.\n */\nexport function registerOrgAuthHandler(\n apiClient: GravityRailClient,\n apiUrl: string,\n accessToken: string\n): void {\n apiClient.setOrgAuthHandler(async (orgAuthInfo: OrgAuthInfo): Promise<void> => {\n // Fast path: non-SSO org — join directly and extract the token.\n try {\n const orgToken = await tryDirectJoin(apiUrl, accessToken, orgAuthInfo);\n if (orgToken !== null) {\n // Set the token on the client so the SDK's fallback check (this.orgToken)\n // picks it up after the handler resolves (Node.js has no document.cookie).\n // Pass the org_uuid so the SDK can detect a stale token if the next\n // request targets a different org.\n apiClient.setOrgToken(orgToken, orgAuthInfo.orgUuid);\n return;\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr(`Warning: org direct-join failed (${msg}); trying browser auth`);\n }\n\n // Slow path: SSO org — the browser must complete the flow. Reject the\n // auth URL up-front if it doesn't match the configured API origin so a\n // hostile server can't pivot the OS URL opener to a `javascript:` /\n // `file://` / custom-scheme handler.\n if (!isAllowedAuthUrl(orgAuthInfo.authUrl, apiUrl)) {\n throw new Error(\n `Refusing to open organization auth URL: scheme/host does not match the configured API host. ` +\n `Re-run with the expected --api-url, or contact support.`\n );\n }\n\n stderr(`\\nThis workspace requires organization SSO authentication.`);\n stderr(`Opening browser to complete authentication...`);\n stderr(` ${orgAuthInfo.authUrl}\\n`);\n stderr(`If the browser does not open, visit the URL above manually.`);\n stderr(\n `After signing in, re-run the command — the CLI cannot receive the SSO token directly.`\n );\n openBrowser(orgAuthInfo.authUrl);\n\n // Reject after timeout so the CLI doesn't hang indefinitely.\n await new Promise<void>((_, reject) => {\n const t = setTimeout(\n () =>\n reject(\n new Error(\n 'Organization authentication timed out.\\n' +\n 'Please complete authentication in the browser, then re-run the command.'\n )\n ),\n ORG_AUTH_TIMEOUT_MS\n );\n // Unref so the timeout doesn't keep the Node.js event loop alive\n // if the parent process is otherwise done.\n t.unref?.();\n });\n });\n}\n","/** Optional DNS pin + audit headers for code-interpreter sandboxes. */\n\nimport { Agent, fetch as undiciFetch, type RequestInit as UndiciRequestInit } from 'undici';\n\nexport interface SandboxAuditHeaders {\n chatId?: number;\n sessionId?: string;\n toolCallId?: string;\n}\n\n/** Subset of sandbox env used when building fetch (kept here to avoid circular imports). */\nexport interface SandboxFetchEnv {\n apiUrl: string;\n apiIp?: string;\n chatId?: number;\n sessionId?: string;\n toolCallId?: string;\n}\n\n/**\n * Route API hostname traffic to a pinned private ENI IP when present.\n *\n * AgentCore sandboxes cannot reach the API ALB's public IPs; Python sandboxes\n * patch urllib3 at the socket layer. Node uses undici with `connect.servername`\n * so TLS SNI still matches the real hostname while the TCP connection targets\n * the pinned private IP (Host header is also set for HTTP routing).\n */\nexport function createPinnedFetch(apiUrl: string, apiIp?: string): typeof fetch {\n if (!apiIp) return fetch;\n\n let parsed: URL;\n try {\n parsed = new URL(apiUrl);\n } catch {\n return fetch;\n }\n const hostname = parsed.hostname;\n\n const dispatcher = new Agent({\n connect: {\n servername: hostname,\n },\n });\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n\n let reqUrl: URL;\n try {\n reqUrl = new URL(url, apiUrl);\n } catch {\n return fetch(input, init);\n }\n\n const headers = new Headers(init?.headers);\n if (reqUrl.hostname === hostname) {\n headers.set('Host', hostname);\n reqUrl = new URL(reqUrl.href);\n reqUrl.hostname = apiIp;\n }\n\n return undiciFetch(reqUrl, {\n ...(init as UndiciRequestInit | undefined),\n headers,\n dispatcher,\n }) as unknown as Promise<Response>;\n };\n}\n\nexport function withAuditHeaders(\n fetchFn: typeof fetch,\n headers: SandboxAuditHeaders\n): typeof fetch {\n const { chatId, sessionId, toolCallId } = headers;\n if (chatId === undefined && !sessionId && !toolCallId) {\n return fetchFn;\n }\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const reqHeaders = new Headers(init?.headers);\n if (chatId !== undefined) {\n reqHeaders.set('X-GR-Chat-Id', String(chatId));\n }\n if (sessionId) {\n reqHeaders.set('X-GR-Session-Id', sessionId);\n }\n if (toolCallId) {\n reqHeaders.set('X-GR-Tool-Call-Id', toolCallId);\n }\n return fetchFn(input, { ...init, headers: reqHeaders });\n };\n}\n\n/** Build fetch for sandbox sessions from explicit env (AgentCore-safe — no process.env). */\nexport function createSandboxFetch(env: SandboxFetchEnv): typeof fetch {\n let fetchFn = createPinnedFetch(env.apiUrl, env.apiIp);\n return withAuditHeaders(fetchFn, {\n chatId: env.chatId,\n sessionId: env.sessionId,\n toolCallId: env.toolCallId,\n });\n}\n\n/** Build fetch for sandbox sessions from GRAVITY_RAIL_* env vars. */\nexport function createSandboxFetchFromEnv(apiUrl: string): typeof fetch {\n const apiIp = process.env.GRAVITY_RAIL_API_IP;\n let fetchFn = createPinnedFetch(apiUrl, apiIp);\n\n const chatIdRaw = process.env.GRAVITY_RAIL_CHAT_ID;\n const chatId = chatIdRaw ? Number(chatIdRaw) : undefined;\n return withAuditHeaders(fetchFn, {\n chatId: chatId !== undefined && Number.isFinite(chatId) ? chatId : undefined,\n sessionId: process.env.GRAVITY_RAIL_SESSION_ID,\n toolCallId: process.env.GRAVITY_RAIL_TOOL_CALL_ID,\n });\n}\n","import { GravityRailClient } from '@gravity-rail/sdk';\nimport {\n CredentialsManager,\n getEnvironmentConfig,\n refreshAccessToken,\n type CLICredentials,\n type EnvironmentConfig,\n} from '../cli-utils';\nimport { homedir } from 'os';\nimport { detectOutputFormat, type OutputFormat } from './output';\nimport { loadDevCloudRealmFile, loadRealmCredentials } from './realm';\nimport { AuthRequiredError } from './errors';\nimport { registerOrgAuthHandler } from './org-auth';\nimport { createSandboxFetchFromEnv } from './pinned-fetch';\n\n/** Build an authenticated API client with the CLI org-auth handler registered. */\nfunction makeApiClient(accessToken: string, apiUrl: string): GravityRailClient {\n const fetchFn = createSandboxFetchFromEnv(apiUrl);\n const apiClient = new GravityRailClient(accessToken, apiUrl, fetchFn);\n registerOrgAuthHandler(apiClient, apiUrl, accessToken);\n return apiClient;\n}\n\n/** Try to silently refresh an expired access token. Returns an AuthenticatedContext or null. */\nasync function tryTokenRefresh(\n ctx: CommandContext,\n creds: CLICredentials\n): Promise<AuthenticatedContext | null> {\n if (!creds.refreshToken) return null;\n const refreshed = await refreshAccessToken(\n ctx.envConfig,\n creds,\n ctx.credentialsManager,\n ctx.env\n );\n if (!refreshed?.accessToken) return null;\n const apiClient = makeApiClient(refreshed.accessToken, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: refreshed.accessToken, apiClient };\n}\n\nexport interface GlobalOptions {\n env: string;\n realm?: string;\n /** Override API base URL (also: GRAVITY_RAIL_API_URL env var). */\n apiUrl?: string;\n outputFormat?: string;\n verbose?: boolean;\n allowWrite?: boolean;\n}\n\nexport interface PublicGlobalOptions {\n env?: string;\n apiUrl?: string;\n frontendUrl?: string;\n outputFormat?: string;\n verbose?: boolean;\n allowWrite?: boolean;\n}\n\nexport interface CommandContext {\n env: string;\n envConfig: EnvironmentConfig;\n outputFormat: OutputFormat;\n verbose: boolean;\n allowWrite: boolean;\n credentialsManager: CredentialsManager;\n}\n\nexport interface AuthenticatedContext extends CommandContext {\n accessToken: string;\n apiClient: GravityRailClient;\n realmWorkspace?: string;\n}\n\n/** Create a base command context (no auth required) */\nexport function createContext(opts: GlobalOptions): CommandContext {\n const baseConfig = getEnvironmentConfig(opts.env);\n const apiUrl = opts.apiUrl || process.env.GRAVITY_RAIL_API_URL || baseConfig.apiUrl;\n const envConfig = apiUrl === baseConfig.apiUrl ? baseConfig : { ...baseConfig, apiUrl };\n const credentialsManager = new CredentialsManager(homedir(), envConfig.apiUrl);\n return {\n env: opts.env,\n envConfig,\n outputFormat: detectOutputFormat(opts.outputFormat),\n verbose: opts.verbose ?? false,\n allowWrite: opts.allowWrite ?? false,\n credentialsManager,\n };\n}\n\n/** Create an authenticated command context. Tries realm, env var, then cached token. Never auto-triggers OAuth. */\nexport async function createAuthenticatedContext(\n opts: GlobalOptions\n): Promise<AuthenticatedContext> {\n // eslint-disable-next-line @eslint-react/naming-convention-context-name -- CLI handler context, not React\n const ctx = createContext(opts);\n\n // Try --realm first (dev-only shortcut using dev-realms.json)\n if (opts.realm) {\n let devRealmsPath: string | undefined;\n if (opts.env.startsWith('dev-cloud:')) {\n const namespace = opts.env.slice('dev-cloud:'.length);\n devRealmsPath = loadDevCloudRealmFile(namespace);\n }\n const { token, workspaceUuid } = loadRealmCredentials(opts.realm, devRealmsPath);\n const apiClient = makeApiClient(token, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: token, apiClient, realmWorkspace: workspaceUuid };\n }\n\n // Try GRAVITY_RAIL_API_KEY first\n const apiKey = process.env.GRAVITY_RAIL_API_KEY;\n if (apiKey) {\n const apiClient = makeApiClient(apiKey, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: apiKey, apiClient };\n }\n\n // Try cached credentials (from `gr login`)\n const creds = ctx.credentialsManager.load(ctx.env);\n if (creds?.accessToken) {\n const buffer = 5 * 60 * 1000;\n const notExpired =\n !creds.expiresAt || new Date(creds.expiresAt) > new Date(Date.now() + buffer);\n if (notExpired) {\n const apiClient = makeApiClient(creds.accessToken, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: creds.accessToken, apiClient };\n }\n\n // Token expired — try refresh\n const refreshed = await tryTokenRefresh(ctx, creds);\n if (refreshed) return refreshed;\n }\n\n throw new AuthRequiredError();\n}\n\n/**\n * Narrow a handler context to `AuthenticatedContext`.\n *\n * Handler `ctx` is typed as `AuthenticatedContext | CommandContext` so that\n * `requiresAuth: false` handlers can also share the type. At runtime, every\n * handler that did not opt out of auth will receive an `AuthenticatedContext`,\n * but TypeScript cannot verify this — call this helper before accessing\n * `apiClient` / `accessToken`.\n *\n * Throws if called from a handler that did not declare `requiresAuth`.\n */\nexport function requireAuth(ctx: AuthenticatedContext | CommandContext): AuthenticatedContext {\n if (!('apiClient' in ctx)) {\n throw new Error('Command handler accessed apiClient without declaring requiresAuth');\n }\n return ctx;\n}\n\n/** Create a base command context for the public CLI (defaults to prod) */\nexport function createPublicContext(opts: PublicGlobalOptions): CommandContext {\n const env = opts.env ?? 'prod';\n const envConfig = opts.apiUrl\n ? {\n apiUrl: opts.apiUrl,\n frontendUrl:\n opts.frontendUrl ||\n process.env.GRAVITY_RAIL_FRONTEND_URL ||\n 'https://app.gravityrail.com',\n }\n : getEnvironmentConfig(env);\n const credentialsManager = new CredentialsManager(homedir(), envConfig.apiUrl);\n return {\n env,\n envConfig,\n outputFormat: detectOutputFormat(opts.outputFormat),\n verbose: opts.verbose ?? false,\n allowWrite: opts.allowWrite ?? false,\n credentialsManager,\n };\n}\n\n/** Create an authenticated context for the public CLI. Tries env var, then cached token. */\nexport async function createPublicAuthenticatedContext(\n opts: PublicGlobalOptions\n): Promise<AuthenticatedContext> {\n const ctx = createPublicContext(opts);\n\n const apiKey = process.env.GRAVITY_RAIL_API_KEY;\n if (apiKey) {\n const apiClient = makeApiClient(apiKey, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: apiKey, apiClient };\n }\n\n const creds = ctx.credentialsManager.load(ctx.env);\n if (creds?.accessToken) {\n const buffer = 5 * 60 * 1000;\n const notExpired =\n !creds.expiresAt || new Date(creds.expiresAt) > new Date(Date.now() + buffer);\n if (notExpired) {\n const apiClient = makeApiClient(creds.accessToken, ctx.envConfig.apiUrl);\n return { ...ctx, accessToken: creds.accessToken, apiClient };\n }\n\n // Token expired — try refresh\n const refreshed = await tryTokenRefresh(ctx, creds);\n if (refreshed) return refreshed;\n }\n\n throw new AuthRequiredError();\n}\n","/**\n * Concierge API client — direct HTTP calls to the global concierge endpoints.\n *\n * The concierge is account-level (no workspace), so these bypass the ApiClient\n * which is workspace-oriented.\n */\n\nimport type { AuthenticatedContext } from './context';\n\nexport interface ConciergeChat {\n id: number;\n uuid: string;\n chatType: string;\n title: string | null;\n threadId: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ConciergeMessage {\n id: string;\n role: string;\n content: string;\n createdAt: string | null;\n toolCalls: any[] | null;\n toolCallId: string | null;\n}\n\nfunction baseUrl(ctx: AuthenticatedContext): string {\n return `${ctx.envConfig.apiUrl}/api/v2/concierge`;\n}\n\nfunction authHeaders(ctx: AuthenticatedContext): Record<string, string> {\n return {\n Authorization: `Bearer ${ctx.accessToken}`,\n 'Content-Type': 'application/json',\n };\n}\n\nfunction toCamelChat(raw: any): ConciergeChat {\n return {\n id: raw.id,\n uuid: raw.uuid,\n chatType: raw.chat_type,\n title: raw.title,\n threadId: raw.thread_id,\n createdAt: raw.created_at,\n updatedAt: raw.updated_at,\n };\n}\n\nfunction toCamelMessage(raw: any): ConciergeMessage {\n return {\n id: raw.id,\n role: raw.role,\n content: raw.content ?? '',\n createdAt: raw.createdAt ?? raw.created_at ?? null,\n toolCalls: raw.toolCalls ?? raw.tool_calls ?? null,\n toolCallId: raw.toolCallId ?? raw.tool_call_id ?? null,\n };\n}\n\nexport async function listConciergeChats(ctx: AuthenticatedContext): Promise<ConciergeChat[]> {\n const res = await fetch(`${baseUrl(ctx)}/chats`, { headers: authHeaders(ctx) });\n if (!res.ok) throw new Error(`Failed to list concierge chats: ${res.status}`);\n const data = await res.json();\n return (data as any[]).map(toCamelChat);\n}\n\nexport async function createConciergeChat(\n ctx: AuthenticatedContext,\n title?: string\n): Promise<ConciergeChat> {\n const res = await fetch(`${baseUrl(ctx)}/chats`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ title: title ?? null }),\n });\n if (!res.ok) throw new Error(`Failed to create concierge chat: ${res.status}`);\n return toCamelChat(await res.json());\n}\n\nexport async function getConciergeChat(\n ctx: AuthenticatedContext,\n chatId: number\n): Promise<ConciergeChat> {\n const res = await fetch(`${baseUrl(ctx)}/chats/${chatId}`, { headers: authHeaders(ctx) });\n if (!res.ok) throw new Error(`Failed to get concierge chat ${chatId}: ${res.status}`);\n return toCamelChat(await res.json());\n}\n\nexport interface ConciergeCallResult {\n callSid: string;\n startedAt: string;\n}\n\nexport interface ConciergeSmsResult {\n messageSid: string;\n conversationId: string;\n}\n\nexport async function originateConciergeCall(\n ctx: AuthenticatedContext,\n kind = 'concierge_setup'\n): Promise<ConciergeCallResult> {\n const res = await fetch(`${baseUrl(ctx)}/calls`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ kind }),\n });\n if (res.status === 412) {\n throw new Error('Your account phone is not verified. Run `gr account verify-phone` first.');\n }\n if (!res.ok) {\n const detail = await res.text();\n throw new Error(`Failed to start concierge call: ${res.status} ${detail}`);\n }\n return (await res.json()) as ConciergeCallResult;\n}\n\nexport async function originateConciergeSms(\n ctx: AuthenticatedContext,\n kind = 'concierge_setup'\n): Promise<ConciergeSmsResult> {\n const res = await fetch(`${baseUrl(ctx)}/sms`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ kind }),\n });\n if (res.status === 412) {\n throw new Error('Your account phone is not verified. Run `gr account verify-phone` first.');\n }\n if (!res.ok) {\n const detail = await res.text();\n throw new Error(`Failed to start concierge SMS: ${res.status} ${detail}`);\n }\n return (await res.json()) as ConciergeSmsResult;\n}\n\nexport async function startAccountPhoneVerify(\n ctx: AuthenticatedContext,\n phone: string\n): Promise<void> {\n const res = await fetch(`${ctx.envConfig.apiUrl}/api/v2/account/phone/verify/start`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ phone }),\n });\n if (!res.ok) {\n const detail = await res.text();\n throw new Error(`Failed to send verification code: ${res.status} ${detail}`);\n }\n}\n\nexport async function confirmAccountPhoneVerify(\n ctx: AuthenticatedContext,\n code: string\n): Promise<void> {\n const res = await fetch(`${ctx.envConfig.apiUrl}/api/v2/account/phone/verify/confirm`, {\n method: 'POST',\n headers: authHeaders(ctx),\n body: JSON.stringify({ code }),\n });\n if (!res.ok) {\n const detail = await res.text();\n throw new Error(`Failed to confirm verification code: ${res.status} ${detail}`);\n }\n}\n\nexport async function getConciergeChatMessages(\n ctx: AuthenticatedContext,\n chatId: number\n): Promise<ConciergeMessage[]> {\n const res = await fetch(`${baseUrl(ctx)}/chats/${chatId}/messages`, {\n headers: authHeaders(ctx),\n });\n if (!res.ok)\n throw new Error(`Failed to get concierge messages for chat ${chatId}: ${res.status}`);\n const data = await res.json();\n return (data as any[]).map(toCamelMessage);\n}\n","/**\n * `gr account verify-phone` — verify account phone for concierge PSTN/SMS.\n */\n\nimport * as readline from 'node:readline/promises';\nimport { stdin as input, stdout as output } from 'node:process';\nimport { confirmAccountPhoneVerify, startAccountPhoneVerify } from '../lib/concierge-api';\nimport { requireAuth } from '../lib/context';\nimport type { CommandHandlerContext } from '../lib/types';\n\nconst TCPA_NOTICE =\n 'By verifying you agree to receive calls and SMS from Gravity Rail at this number.';\n\nexport async function accountVerifyPhoneCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const phoneArg = typeof hctx.args.phone === 'string' ? hctx.args.phone : undefined;\n\n process.stderr.write(`${TCPA_NOTICE}\\n`);\n\n const phone = phoneArg ?? (await promptLine('Phone number (E.164, e.g. +15551234567): '));\n if (!phone.trim()) {\n throw new Error('Phone number is required');\n }\n\n await startAccountPhoneVerify(ctx, phone.trim());\n process.stderr.write('Verification code sent via SMS.\\n');\n\n const code = await promptLine('Enter 6-digit code: ');\n await confirmAccountPhoneVerify(ctx, code.trim());\n process.stderr.write(\n 'Phone verified. You can use `gr concierge chat --call` or `gr concierge chat --sms`.\\n'\n );\n}\n\nasync function promptLine(question: string): Promise<string> {\n const rl = readline.createInterface({ input, output });\n try {\n return (await rl.question(question)) ?? '';\n } finally {\n rl.close();\n }\n}\n","import { execFile } from 'child_process';\nimport { stderr } from '../lib/output';\nimport type { AuthenticatedContext } from '../lib/context';\n\n/**\n * Open an authenticated browser session using the CLI's existing credentials.\n *\n * Flow:\n * 1. Get the current account's email from the CLI session\n * 2. Request a magic link via the API (token returned directly since caller is authenticated)\n * 3. Open the magic link URL in the default browser (or print it with --no-open)\n */\nexport async function authBrowserCommand(\n ctx: AuthenticatedContext,\n args: Record<string, unknown>\n): Promise<void> {\n const noOpen = Boolean(args['no-open']);\n\n // Get current account email\n const account = await ctx.apiClient.getUserAccount();\n if (!account.email) {\n process.stderr.write('Error: No email associated with current account\\n');\n process.exit(1);\n }\n\n // Request magic link — since we're authenticated, the API returns the token directly\n const response = await ctx.apiClient.requestMagicLink(account.email);\n\n if (!response.success || !response.magicLinkUrl) {\n process.stderr.write('Error: Failed to create magic link\\n');\n process.exit(1);\n }\n\n const url = response.magicLinkUrl;\n\n if (noOpen) {\n // Just print the URL to stdout for scripting/manual use\n process.stdout.write(url + '\\n');\n return;\n }\n\n // Open in default browser\n stderr(`Opening browser for ${account.email} (${ctx.env})...`);\n openUrl(url);\n stderr('Browser opened. Link expires in 15 minutes.');\n}\n\n/** Open a URL in the default browser (cross-platform). Uses execFile to avoid shell injection. */\nfunction openUrl(url: string): void {\n const platform = process.platform;\n\n let command: string;\n let args: string[];\n\n if (platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (platform === 'win32') {\n command = 'cmd.exe';\n args = ['/c', 'start', '', url];\n } else {\n command = 'xdg-open';\n args = [url];\n }\n\n execFile(command, args, (err) => {\n if (err) {\n // Non-fatal — user can copy the URL from --no-open output\n process.stderr.write('Warning: Could not open browser automatically\\n');\n }\n });\n}\n","import type { GravityRailClient } from '@gravity-rail/sdk';\nimport type { Chat } from '@gravity-rail/sdk';\nimport { formatTimestamp, selectFromList } from '../cli-utils';\nimport { CLIError } from '../lib/errors';\nimport { requireAuth, type AuthenticatedContext } from '../lib/context';\nimport type { CommandHandlerContext } from '../lib/types';\nimport { buildCliConciergeAppContext } from '../lib/cli-client-context';\nimport { runChatSession, type ChatSession } from '../lib/chat-session';\n\n// ─── Entry point ─────────────────────────────────────────────────────────────\n\nexport async function manageCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const { workspace, args } = hctx;\n\n const asMember = typeof args['as-member'] === 'string' ? args['as-member'] : undefined;\n const chatIdArg = typeof args['chat-id'] === 'string' ? args['chat-id'] : undefined;\n const message = typeof args.message === 'string' ? args.message : undefined;\n\n const chat = await getOrCreateChat(ctx, workspace, chatIdArg, asMember, 'manager', !!message);\n const session = buildWorkspaceSession(ctx, workspace, chat, 'Workspace Manager', {\n appContext: buildCliConciergeAppContext(),\n allowWrite: true,\n trustCwd: !!args['trust-cwd'],\n trustDir: typeof args['trust-dir'] === 'string' ? args['trust-dir'] : undefined,\n });\n // Print the chat ID up-front so a user who Ctrl-Cs mid-stream can still\n // reattach with `gr manage --chat-id ${id}`. The post-session repeat\n // (after `runChatSession`) is intentional — a second \"Chat #N\" line on\n // clean exit gives copy/paste-friendly anchors at both ends of long\n // streams without any extra parsing.\n process.stderr.write(`Chat #${session.chatId}\\n`);\n await runChatSession(session, args);\n process.stderr.write(`Chat #${session.chatId}\\n`);\n}\n\nexport async function chatCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const { workspace, args } = hctx;\n const chatIdArg = typeof args['chat-id'] === 'string' ? args['chat-id'] : undefined;\n const workflowId = typeof args.workflow === 'string' ? args.workflow : undefined;\n const memberId = typeof args.member === 'string' ? args.member : undefined;\n\n let chat: Chat;\n if (chatIdArg) {\n const id = Number(chatIdArg);\n if (isNaN(id)) throw new CLIError('--chat-id must be a number');\n chat = await ctx.apiClient.getChat(workspace, id);\n } else if (workflowId) {\n chat = await createAssignmentChat(ctx.apiClient, workspace, Number(workflowId), memberId);\n } else if (memberId) {\n chat = await createMemberChat(ctx.apiClient, workspace, memberId);\n } else {\n throw new CLIError(\n 'Specify --workflow <id>, --member <id>, or --chat-id <id>.\\n' +\n 'Use \"gr manage\" for workspace manager chats.'\n );\n }\n\n const session = buildWorkspaceSession(ctx, workspace, chat, 'Chat');\n await runChatSession(session, args);\n}\n\n// ─── Session builder ─────────────────────────────────────────────────────────\n\nfunction buildWorkspaceSession(\n ctx: AuthenticatedContext,\n workspace: string,\n chat: Chat,\n label: string,\n extra?: Pick<ChatSession, 'appContext' | 'allowWrite' | 'trustCwd' | 'trustDir'>\n): ChatSession {\n const wsBase = ctx.envConfig.apiUrl.replace(/^https:/, 'wss:').replace(/^http:/, 'ws:');\n return {\n ctx,\n workspaceUuid: workspace,\n chatId: chat.id,\n chatUuid: chat.uuid,\n chatTitle: chat.title || chat.uuid,\n aguiEndpointUrl: `${ctx.envConfig.apiUrl}/api/v2/w/${workspace}/web-chat/${chat.id}/chat/agui`,\n wsUrl: `${wsBase}/api/v2/w/${workspace}/realtime/stream-ws`,\n loadMessages: () => ctx.apiClient.getChatMessages(workspace, chat.id, 50).catch(() => []),\n label,\n model: 'manager',\n ...extra,\n };\n}\n\n// ─── Chat selection ──────────────────────────────────────────────────────────\n\nasync function getOrCreateChat(\n ctx: AuthenticatedContext,\n workspace: string,\n chatIdArg: string | undefined,\n asMemberId: string | undefined,\n chatType: 'manager' | 'assignment' | 'member' | 'contributor' | 'developer',\n skipSelection: boolean = false\n): Promise<Chat> {\n if (chatIdArg) {\n const chatId = Number(chatIdArg);\n if (isNaN(chatId)) throw new CLIError('--chat-id must be a number');\n return ctx.apiClient.getChat(workspace, chatId);\n }\n\n if (skipSelection) {\n return createManagerChat(ctx.apiClient, workspace, asMemberId);\n }\n\n const chatsResponse = await ctx.apiClient.getChats(workspace, {\n chatType,\n sortBy: 'updatedAt',\n sortOrder: 'desc',\n pageSize: 20,\n });\n const chats = chatsResponse.items || [];\n\n const { item: selectedChat, isNew } = await selectFromList(chats, {\n title: 'Select a chat or create a new one',\n labelFn: (chat) => chat.title || `Chat ${chat.uuid.slice(0, 8)}...`,\n detailFn: (chat) => {\n const time = formatTimestamp(chat.updatedAt);\n const msgCount = chat.messageCount || 0;\n return `${msgCount} msg${msgCount !== 1 ? 's' : ''} - ${time}`;\n },\n emptyMessage: 'No existing chats.',\n allowNew: true,\n newLabel: '+ Start new chat',\n });\n\n if (!selectedChat && !isNew) {\n throw new CLIError('No chat selected.');\n }\n\n if (isNew) {\n return createManagerChat(ctx.apiClient, workspace, asMemberId);\n }\n return selectedChat!;\n}\n\nasync function createManagerChat(\n apiClient: GravityRailClient,\n workspace: string,\n asMemberId: string | undefined\n): Promise<Chat> {\n const data: Record<string, any> = {\n chatType: 'manager',\n channel: 'web-chat',\n };\n if (asMemberId) {\n data.memberId = Number(asMemberId);\n }\n const chat = await apiClient.createChat(workspace, data as any);\n process.stderr.write(`Created chat #${chat.id}\\n`);\n return chat;\n}\n\nasync function createAssignmentChat(\n apiClient: GravityRailClient,\n workspace: string,\n workflowId: number,\n asMemberId: string | undefined\n): Promise<Chat> {\n if (isNaN(workflowId)) throw new CLIError('--workflow must be a number');\n const data: Record<string, any> = {\n chatType: 'assignment',\n channel: 'web-chat',\n workflowId,\n };\n if (asMemberId) {\n data.memberId = Number(asMemberId);\n }\n const chat = await apiClient.createChat(workspace, data as any);\n process.stderr.write(`Created assignment chat #${chat.id} (workflow ${workflowId})\\n`);\n return chat;\n}\n\nasync function createMemberChat(\n apiClient: GravityRailClient,\n workspace: string,\n memberId: string\n): Promise<Chat> {\n const id = Number(memberId);\n if (isNaN(id)) throw new CLIError('--member must be a number');\n const data: Record<string, any> = {\n chatType: 'member',\n channel: 'web-chat',\n memberId: id,\n };\n const chat = await apiClient.createChat(workspace, data as any);\n process.stderr.write(`Created DM chat #${chat.id} (member ${memberId})\\n`);\n return chat;\n}\n","import path from 'path';\n\nexport interface ConciergeAppContextPayload {\n clientSurface: 'cli';\n cliContext: {\n shell?: string;\n os: string;\n cwdBasename: string;\n };\n channel: 'text';\n}\n\n/** Build ConciergeAppContext for AG-UI requests from the CLI. */\nexport function buildCliConciergeAppContext(): ConciergeAppContextPayload {\n const shell = process.env.SHELL ? path.basename(process.env.SHELL) : undefined;\n return {\n clientSurface: 'cli',\n channel: 'text',\n cliContext: {\n shell,\n os: process.platform,\n cwdBasename: path.basename(process.cwd()),\n },\n };\n}\n","/**\n * Shared chat session infrastructure.\n *\n * Defines the ChatSession abstraction consumed by all chat modes (text, realtime, voice).\n * Entry points (manage, chat, concierge) construct a ChatSession and pass it here.\n */\n\nimport {\n AGUIClient,\n clearScreen,\n getErrorMessage,\n getTextDelta,\n printMessage,\n type AGUIChatMessage,\n} from '../cli-utils';\nimport type { ConciergeAppContextPayload } from './cli-client-context';\nimport { runConciergeAguiLoop } from './concierge-agui-loop';\nimport * as readline from 'readline';\nimport { CLIError } from './errors';\nimport type { AuthenticatedContext } from './context';\nimport { RealtimeClient } from './realtime-client';\nimport { ChatTUI, type ChatItem } from './chat-tui';\nimport {\n checkSoxAvailable,\n listInputDevices,\n listOutputDevices,\n selectDevice,\n MicCapture,\n AudioPlayer,\n} from './audio';\n\n// ─── ChatSession abstraction ─────────────────────────────────────────────────\n\n/** Everything a chat mode needs — constructed differently per entry point. */\nexport interface ChatSession {\n ctx: AuthenticatedContext;\n workspaceUuid: string;\n chatId: number;\n chatUuid: string;\n chatTitle: string;\n aguiEndpointUrl: string;\n wsUrl: string;\n loadMessages: () => Promise<any[]>;\n /** Display label: \"Workspace Manager\", \"Concierge\", etc. */\n label: string;\n /** AGUI request model field. Undefined = omit from body. */\n model?: string;\n /** Concierge client context (CLI surface, etc.). */\n appContext?: ConciergeAppContextPayload;\n /** Whether --allow-write was passed (local file writes). */\n allowWrite?: boolean;\n /** Directory-trust flags for lazy local-file HITL. */\n trustCwd?: boolean;\n trustDir?: string;\n}\n\n// ─── Mode dispatcher ─────────────────────────────────────────────────────────\n\nexport async function runChatSession(\n session: ChatSession,\n args: Record<string, any>\n): Promise<void> {\n const debug = !!args.debug;\n const isVoice = !!args.voice;\n const isRealtime = !!args.realtime || isVoice;\n const message = typeof args.message === 'string' ? args.message : undefined;\n const autoApprove = !!args['auto-approve'];\n\n if (args['list-devices']) {\n await listAudioDevices();\n return;\n }\n\n if (!message && !process.stdin.isTTY) {\n throw new CLIError(\n 'Interactive mode requires a TTY. Use --message for non-interactive mode.'\n );\n }\n\n const allowWrite = !!args['allow-write'] || !!session.allowWrite;\n if (message) {\n await singleTurnChatSession(session, message, debug, autoApprove, allowWrite);\n } else if (isVoice) {\n await voiceChatSession(session, vadMode(args), args, debug);\n } else if (isRealtime) {\n await realtimeChatSession(session, vadMode(args), debug);\n } else {\n await interactiveChatSession(session, debug, autoApprove, allowWrite);\n }\n}\n\nexport function vadMode(args: Record<string, any>): 'client' | 'server' {\n return (typeof args.vad === 'string' ? args.vad : 'server') as 'client' | 'server';\n}\n\n// ─── Single-turn text mode (SSE) ────────────────────────────────────────────\n\nasync function singleTurnChatSession(\n session: ChatSession,\n message: string,\n debug: boolean,\n autoApprove: boolean = false,\n allowWrite: boolean = false\n): Promise<void> {\n const aguiClient = new AGUIClient({\n baseUrl: session.ctx.envConfig.apiUrl,\n workspaceUuid: session.workspaceUuid,\n chatId: session.chatId,\n endpointUrl: session.aguiEndpointUrl,\n accessToken: session.ctx.accessToken,\n debug,\n model: session.model,\n appContext: session.appContext,\n });\n\n // Stream all SSE events. The AGUI stream includes tool calls, tool\n // results, and text content across all inference turns. We accumulate\n // text and show tool call progress, then poll for final text if the\n // stream ended mid-turn (e.g. after tool calls with no final text).\n const onEvent = (event: { type?: string; name?: string }) => {\n const type = event.type?.toLowerCase() ?? '';\n if (type === 'tool_call_start') {\n const name =\n (event as Record<string, any>).toolCallName ??\n (event as Record<string, any>).name ??\n '';\n process.stderr.write(` [${name}]\\n`);\n }\n };\n\n const { streamText, hasToolCalls } = await runConciergeAguiLoop(\n aguiClient,\n [{ role: 'user', content: message }],\n onEvent,\n {\n autoApprove,\n allowWrite: allowWrite || !!session.allowWrite,\n debug,\n trustCwd: session.trustCwd,\n trustDir: session.trustDir,\n nonInteractive: true,\n }\n );\n\n // If we got text from the stream, print it\n if (streamText) {\n process.stdout.write(`\\x1B[32mAssistant:\\x1B[0m ${streamText}\\n`);\n return;\n }\n\n // No text in stream (tool calls only) — poll for the final response\n if (hasToolCalls) {\n process.stderr.write(' (waiting for completion...)\\n');\n const maxWaitMs = 180_000;\n const pollIntervalMs = 2000;\n const startTime = Date.now();\n let finalText = '';\n\n while (Date.now() - startTime < maxWaitMs) {\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n try {\n const msgs = await session.loadMessages();\n // Find the last assistant message with actual text\n for (let i = msgs.length - 1; i >= 0; i--) {\n const m = msgs[i];\n if (m.role === 'assistant' && m.content && !m.tool_calls?.length) {\n finalText = m.content;\n break;\n }\n }\n if (finalText) break;\n } catch {\n // keep polling\n }\n }\n\n process.stdout.write(`\\x1B[32mAssistant:\\x1B[0m ${finalText || '(no text response)'}\\n`);\n } else {\n process.stdout.write(`\\x1B[32mAssistant:\\x1B[0m (no response)\\n`);\n }\n}\n\n// ─── Interactive text mode (SSE) ─────────────────────────────────────────────\n\nasync function interactiveChatSession(\n session: ChatSession,\n debug: boolean,\n autoApprove: boolean,\n allowWrite: boolean\n): Promise<void> {\n const aguiClient = new AGUIClient({\n baseUrl: session.ctx.envConfig.apiUrl,\n workspaceUuid: session.workspaceUuid,\n chatId: session.chatId,\n endpointUrl: session.aguiEndpointUrl,\n accessToken: session.ctx.accessToken,\n debug,\n model: session.model,\n appContext: session.appContext,\n });\n\n clearScreen();\n console.log('='.repeat(60));\n console.log(session.label);\n console.log('='.repeat(60));\n console.log(`Chat: ${session.chatTitle}`);\n console.log(\"Type your message and press Enter. Type 'exit' or Ctrl+C to quit.\");\n console.log('='.repeat(60));\n console.log('');\n\n const existingMessages = await session.loadMessages();\n if (existingMessages.length > 0) {\n console.log('\\x1B[90m--- Previous messages ---\\x1B[0m\\n');\n for (const msg of existingMessages.slice(-10)) {\n const text = typeof msg.content === 'string' ? msg.content : '';\n if (text && text.trim()) {\n printMessage(text, msg.role as 'user' | 'assistant' | 'system');\n }\n }\n console.log('\\x1B[90m--- End of history ---\\x1B[0m\\n');\n }\n\n const conversationMessages: AGUIChatMessage[] = [];\n for (const msg of existingMessages.slice(-10)) {\n const text = typeof msg.content === 'string' ? msg.content : '';\n if (text && text.trim() && (msg.role === 'user' || msg.role === 'assistant')) {\n conversationMessages.push({ role: msg.role, content: text });\n }\n }\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n\n return new Promise<void>((resolve) => {\n const prompt = (): void => {\n rl.question('\\x1B[34mYou:\\x1B[0m ', async (input) => {\n const trimmed = input.trim();\n if (!trimmed) {\n prompt();\n return;\n }\n if (trimmed.toLowerCase() === 'exit' || trimmed.toLowerCase() === 'quit') {\n console.log('\\nGoodbye!');\n rl.close();\n return;\n }\n\n conversationMessages.push({ role: 'user', content: trimmed });\n process.stdout.write('\\n\\x1B[32mAssistant:\\x1B[0m ');\n let assistantContent = '';\n\n try {\n const { streamText } = await runConciergeAguiLoop(\n aguiClient,\n conversationMessages,\n (event) => {\n const delta = getTextDelta(event);\n if (delta) {\n process.stdout.write(delta);\n assistantContent += delta;\n }\n const errorMsg = getErrorMessage(event);\n if (errorMsg) console.log(`\\n\\x1B[31mError: ${errorMsg}\\x1B[0m`);\n },\n {\n autoApprove,\n allowWrite: allowWrite || !!session.allowWrite,\n debug,\n trustCwd: session.trustCwd,\n trustDir: session.trustDir,\n }\n );\n if (streamText && !assistantContent) {\n assistantContent = streamText;\n process.stdout.write(streamText);\n }\n if (assistantContent) {\n conversationMessages.push({ role: 'assistant', content: assistantContent });\n }\n console.log('\\n');\n } catch (error) {\n console.log(\n `\\n\\x1B[31mError: ${error instanceof Error ? error.message : error}\\x1B[0m\\n`\n );\n }\n\n prompt();\n });\n };\n\n rl.on('close', () => {\n console.log('\\nGoodbye!');\n resolve();\n });\n prompt();\n });\n}\n\n// ─── Shared helpers for realtime modes ───────────────────────────────────────\n\nexport function buildHistory(messages: any[]): ChatItem[] {\n const history: ChatItem[] = [];\n for (const msg of messages.slice(-30)) {\n const text = typeof msg.content === 'string' ? msg.content : '';\n if (msg.role === 'user' || msg.role === 'assistant') {\n if (text.trim()) {\n history.push({ role: msg.role, content: text });\n }\n if (msg.role === 'assistant' && msg.tool_calls) {\n for (const tc of msg.tool_calls) {\n history.push({\n kind: 'tool_call',\n id: tc.id,\n name: tc.function.name,\n args: tc.function.arguments || '',\n done: true,\n });\n }\n }\n } else if (msg.role === 'tool') {\n const toolName = (msg as any).name || 'tool';\n history.push({\n kind: 'tool_result',\n toolCallId: (msg as any).tool_call_id || '',\n toolName,\n content: text,\n });\n }\n }\n return history;\n}\n\nexport function wireRealtimeEvents(client: RealtimeClient, tui: ChatTUI): void {\n client.on('text_start', () => tui.streamStart());\n client.on('text_delta', (data: any) => tui.streamDelta(data.delta));\n client.on('text_end', () => tui.streamEnd());\n\n client.on('tool_call_start', (data: any) => {\n tui.toolCallStart(data.toolCallId, data.toolCallName);\n });\n client.on('tool_call_args', (data: any) => {\n tui.toolCallArgs(data.toolCallId, data.delta);\n });\n client.on('tool_call_end', (data: any) => {\n tui.toolCallEnd(data.toolCallId);\n });\n client.on('tool_call_result', (data: any) => {\n const toolName = tui.findToolCallName(data.toolCallId);\n const content = typeof data.result === 'string' ? data.result : JSON.stringify(data.result);\n tui.toolCallResult(data.toolCallId, toolName, content);\n });\n\n client.on('run_error', (data: any) => {\n tui.showError(data.message);\n });\n\n client.on('error', (err: Error) => {\n tui.showError(`Connection: ${err.message}`);\n });\n\n client.on('ws_recv', (msg: any) => tui.logDebug('in', msg));\n client.on('ws_send', (msg: any) => tui.logDebug('out', msg));\n}\n\n// ─── Realtime text mode (WebSocket + TUI) ────────────────────────────────────\n\nasync function realtimeChatSession(\n session: ChatSession,\n vad: 'client' | 'server',\n debug: boolean\n): Promise<void> {\n const client = new RealtimeClient({\n url: session.wsUrl,\n token: session.ctx.accessToken,\n chatId: session.chatId,\n vadMode: vad,\n debug,\n });\n\n process.stderr.write(`Connecting to ${session.label.toLowerCase()}...\\n`);\n\n try {\n await client.connect();\n } catch (err) {\n throw new CLIError(`Failed to connect: ${err instanceof Error ? err.message : err}`);\n }\n\n const existingMessages = await session.loadMessages();\n const history = buildHistory(existingMessages);\n\n const tui = new ChatTUI({\n onSend: (text) => {\n client.sendTextMessage(text);\n },\n onExit: () => {\n client.close();\n },\n debug,\n env: session.ctx.env,\n });\n\n wireRealtimeEvents(client, tui);\n\n client.on('closed', () => {\n tui.stop();\n console.log('Disconnected.');\n });\n\n tui.loadHistory(history);\n tui.start();\n\n await new Promise<void>((resolve) => {\n client.once('closed', resolve);\n });\n}\n\n// ─── Voice mode (WebSocket + mic + speaker + TUI) ────────────────────────────\n\nasync function voiceChatSession(\n session: ChatSession,\n vad: 'client' | 'server',\n args: Record<string, string | boolean | undefined>,\n debug: boolean\n): Promise<void> {\n if (!checkSoxAvailable()) {\n throw new CLIError(\n 'Voice mode requires SoX. Install it:\\n' +\n ' macOS: brew install sox\\n' +\n ' Linux: apt install sox\\n' +\n ' Windows: choco install sox'\n );\n }\n\n const inputDeviceName =\n typeof args['input-device'] === 'string' ? args['input-device'] : undefined;\n const outputDeviceName =\n typeof args['output-device'] === 'string' ? args['output-device'] : undefined;\n\n let inputDeviceId: string | undefined;\n let outputDeviceId: string | undefined;\n\n if (!inputDeviceName || !outputDeviceName) {\n process.stderr.write('\\n Audio Devices\\n');\n }\n\n if (inputDeviceName) {\n inputDeviceId = inputDeviceName;\n } else {\n const inputDevices = await listInputDevices();\n const selected = await selectDevice(inputDevices, 'Input (microphone)');\n inputDeviceId = selected.id;\n }\n\n if (outputDeviceName) {\n outputDeviceId = outputDeviceName;\n } else {\n const outputDevices = await listOutputDevices();\n const selected = await selectDevice(outputDevices, 'Output (speaker)');\n outputDeviceId = selected.id;\n }\n\n const client = new RealtimeClient({\n url: session.wsUrl,\n token: session.ctx.accessToken,\n chatId: session.chatId,\n vadMode: vad,\n debug,\n });\n\n process.stderr.write(`\\nConnecting to ${session.label.toLowerCase()}...\\n`);\n\n try {\n await client.connect();\n } catch (err) {\n throw new CLIError(`Failed to connect: ${err instanceof Error ? err.message : err}`);\n }\n\n const existingMessages = await session.loadMessages();\n const history = buildHistory(existingMessages);\n\n const mic = new MicCapture((pcm16) => {\n if (!client.isConnected()) return;\n client.sendAudio(pcm16);\n });\n const player = new AudioPlayer(outputDeviceId);\n\n function cleanup(): void {\n mic.stop();\n player.stop();\n client.close();\n }\n\n const tui = new ChatTUI({\n onSend: (text) => {\n client.sendTextMessage(text);\n },\n onExit: () => {\n cleanup();\n },\n debug,\n env: session.ctx.env,\n });\n\n wireRealtimeEvents(client, tui);\n\n client.on('audio', (data: any) => {\n player.write(data.pcm16);\n });\n\n client.on('audio_end', (data: any) => {\n player.endResponse(data?.messageId);\n });\n\n client.on('interrupt', () => {\n const playbackMs = player.getPlaybackTimeMs();\n const messageId = player.playingMessageId;\n\n if (playbackMs !== null && playbackMs > 0 && player.isPlaying) {\n client.sendInterrupt(playbackMs, messageId);\n player.stop();\n\n if (debug) {\n tui.logDebug('in', {\n type: 'CUSTOM',\n name: 'voice.interrupt',\n value: { action: 'echoed', audioEndMs: playbackMs, messageId },\n });\n }\n } else if (debug) {\n tui.logDebug('in', {\n type: 'CUSTOM',\n name: 'voice.interrupt',\n value: { action: 'ignored', wasPlaying: player.isPlaying },\n });\n }\n });\n\n client.on('truncate', (data: any) => {\n player.stop();\n tui.truncateAssistant(\n data.content ?? '',\n data.originalContent,\n data.truncationReason ?? 'barge_in',\n data.truncatedAtMs\n );\n });\n\n client.on('response_message', (data: any) => {\n if (data.role === 'user' && data.content) {\n tui.addTranscription(data.content);\n }\n });\n\n client.on('closed', () => {\n tui.stop();\n cleanup();\n console.log('Disconnected.');\n });\n\n tui.loadHistory(history);\n tui.start();\n\n mic.start(inputDeviceId);\n\n await new Promise<void>((resolve) => {\n client.once('closed', resolve);\n });\n}\n\n// ─── Device listing ──────────────────────────────────────────────────────────\n\nexport async function listAudioDevices(): Promise<void> {\n if (!checkSoxAvailable()) {\n throw new CLIError(\n 'Device listing requires SoX. Install it:\\n' +\n ' macOS: brew install sox\\n' +\n ' Linux: apt install sox\\n' +\n ' Windows: choco install sox'\n );\n }\n\n const inputs = await listInputDevices();\n const outputs = await listOutputDevices();\n\n console.log('Input devices (microphone):');\n for (const dev of inputs) {\n const marker = dev.isDefault ? ' (default)' : '';\n console.log(` ${dev.id}: ${dev.name}${marker}`);\n }\n\n console.log('\\nOutput devices (speaker):');\n for (const dev of outputs) {\n const marker = dev.isDefault ? ' (default)' : '';\n console.log(` ${dev.id}: ${dev.name}${marker}`);\n }\n}\n","/**\n * Concierge AG-UI turn loop with HITL resume (local files, present_choice).\n */\n\nimport {\n AGUIClient,\n getErrorMessage,\n getTextDelta,\n type AGUIEvent,\n type ChatMessage as AGUIChatMessage,\n} from '../cli-utils/agui';\nimport { extractHumanInputRequest, handleCliHitlInterrupt } from './cli-hitl';\n\nconst MAX_HITL_ROUNDS = 25;\n\nexport async function runConciergeAguiLoop(\n client: AGUIClient,\n initialMessages: AGUIChatMessage[],\n onEvent: (event: AGUIEvent) => void,\n opts: {\n autoApprove: boolean;\n allowWrite: boolean;\n debug?: boolean;\n trustCwd?: boolean;\n trustDir?: string;\n nonInteractive?: boolean;\n }\n): Promise<{ streamText: string; hasToolCalls: boolean }> {\n let streamText = '';\n let hasToolCalls = false;\n let resume: { resumeValue: string; resumeInterruptId?: string } | undefined;\n\n for (let round = 0; round < MAX_HITL_ROUNDS; round++) {\n let hitlPayload: unknown = null;\n\n await client.streamRequest(\n resume\n ? {\n messages: [],\n resumeValue: resume.resumeValue,\n resumeInterruptId: resume.resumeInterruptId,\n }\n : { messages: initialMessages },\n (event) => {\n onEvent(event);\n const delta = getTextDelta(event);\n if (delta) streamText += delta;\n const type = event.type?.toLowerCase() ?? '';\n if (type === 'tool_call_start') hasToolCalls = true;\n const errorMsg = getErrorMessage(event);\n if (errorMsg) process.stderr.write(`\\x1B[31mError: ${errorMsg}\\x1B[0m\\n`);\n const hitl = extractHumanInputRequest(event as Record<string, unknown>);\n if (hitl) hitlPayload = hitl;\n },\n { autoApprove: opts.autoApprove }\n );\n\n if (!hitlPayload) {\n break;\n }\n\n const next = await handleCliHitlInterrupt(hitlPayload, {\n allowWrite: opts.allowWrite,\n autoApprove: opts.autoApprove,\n trustCwd: opts.trustCwd,\n trustDir: opts.trustDir,\n nonInteractive: opts.nonInteractive,\n });\n if (!next) {\n process.stderr.write(\n ' [HITL] Unsupported interrupt in CLI — open app.gravityrail.com/setup to continue.\\n'\n );\n break;\n }\n resume = next;\n streamText = '';\n }\n\n return { streamText, hasToolCalls };\n}\n","/**\n * Handle concierge HITL interrupts in the CLI (local file ops, etc.).\n */\n\nimport readline from 'readline';\nimport {\n executeCliLocalFileAction,\n isCliLocalFileInterrupt,\n type CliLocalFileInterrupt,\n} from './local-files';\nimport { resolveDirectoryTrust } from './trusted-dirs';\n\nexport type { CliLocalFileInterrupt };\n\nexport interface HitlResumePayload {\n resumeValue: string;\n resumeInterruptId?: string;\n}\n\nexport function extractHumanInputRequest(event: Record<string, unknown>): unknown | null {\n const type = String(event.type ?? '').toUpperCase();\n if (type === 'CUSTOM' && event.name === 'human_input_request') {\n return event.value;\n }\n if (event.name === 'human_input_request') {\n return event.value;\n }\n return null;\n}\n\nexport async function handleCliHitlInterrupt(\n value: unknown,\n opts: {\n allowWrite: boolean;\n autoApprove: boolean;\n trustCwd?: boolean;\n trustDir?: string;\n /** When true, skip the trust prompt and fail if the directory is untrusted. */\n nonInteractive?: boolean;\n }\n): Promise<HitlResumePayload | null> {\n if (!value || typeof value !== 'object') return null;\n const payload = value as Record<string, unknown>;\n\n if (isCliLocalFileInterrupt(payload)) {\n const interrupt = payload as CliLocalFileInterrupt;\n if (typeof payload.interrupt_id === 'string') {\n interrupt.interrupt_id = payload.interrupt_id;\n }\n return handleCliLocalFile(interrupt, opts);\n }\n\n if (payload.type === 'present_choice') {\n return handlePresentChoiceTerminal(payload);\n }\n\n return null;\n}\n\nasync function handleCliLocalFile(\n interrupt: CliLocalFileInterrupt,\n opts: {\n allowWrite: boolean;\n trustCwd?: boolean;\n trustDir?: string;\n nonInteractive?: boolean;\n }\n): Promise<HitlResumePayload> {\n const trust = await resolveDirectoryTrust({\n cwd: process.cwd(),\n trustCwd: opts.trustCwd,\n trustDir: opts.trustDir,\n // Interactive sessions: prompt on first local-file use (review feedback).\n nonInteractive: opts.nonInteractive ?? process.stdin.isTTY !== true,\n });\n if (trust !== 'trusted') {\n return {\n resumeValue: JSON.stringify({\n ok: false,\n error: 'Directory not trusted for local file access. Re-run with --trust-cwd or --trust-dir <path>, or approve trust interactively when prompted.',\n }),\n resumeInterruptId: interrupt.interrupt_id,\n };\n }\n\n process.stderr.write(`\\n[local ${interrupt.action}] ${interrupt.path}\\n`);\n const result = executeCliLocalFileAction(process.cwd(), interrupt, {\n allowWrite: opts.allowWrite,\n });\n return {\n resumeValue: JSON.stringify(result),\n resumeInterruptId: interrupt.interrupt_id,\n };\n}\n\nasync function handlePresentChoiceTerminal(\n payload: Record<string, unknown>\n): Promise<HitlResumePayload | null> {\n const prompt =\n (typeof payload.user_prompt === 'string' && payload.user_prompt) ||\n (typeof payload.description === 'string' && payload.description) ||\n 'Choose an option';\n const markup = typeof payload.openui_markup === 'string' ? payload.openui_markup : '';\n process.stderr.write(`\\n${prompt}\\n`);\n if (markup) {\n process.stderr.write(`${markup.slice(0, 2000)}\\n`);\n }\n if (!process.stdin.isTTY) {\n return {\n resumeValue: '',\n resumeInterruptId:\n typeof payload.interrupt_id === 'string' ? payload.interrupt_id : undefined,\n };\n }\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n const answer = await new Promise<string>((resolve) => {\n rl.question('Your choice (value): ', resolve);\n });\n rl.close();\n return {\n resumeValue: answer.trim(),\n resumeInterruptId:\n typeof payload.interrupt_id === 'string' ? payload.interrupt_id : undefined,\n };\n}\n","/**\n * Sandboxed local filesystem operations for CLI-executed concierge tools.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nconst DEFAULT_MAX_READ_BYTES = 50_000;\nconst ABSOLUTE_MAX_READ_BYTES = 1_000_000;\n\nexport interface CliLocalFileInterrupt {\n type: 'cli_local_file';\n action: 'read_file' | 'list_dir' | 'write_file';\n path: string;\n content?: string;\n max_bytes?: number;\n interrupt_id?: string;\n}\n\nexport interface CliLocalFileResult {\n ok: boolean;\n content?: string;\n error?: string;\n}\n\nfunction resolveSafePath(root: string, relativePath: string): string | null {\n const rootResolved = path.resolve(root);\n const target = path.resolve(rootResolved, relativePath || '.');\n if (target !== rootResolved && !target.startsWith(rootResolved + path.sep)) {\n return null;\n }\n // Reject any component along the path that is a symlink — `path.resolve`\n // does not follow symlinks but `fs.statSync`/`readFileSync` do, so a\n // symlink inside the trusted dir could otherwise read or write a file\n // outside of it. ``lstatSync`` reports the link itself and never the\n // target.\n let cursor = rootResolved;\n const rest = path.relative(rootResolved, target);\n if (rest && rest !== '.') {\n for (const segment of rest.split(path.sep)) {\n cursor = path.join(cursor, segment);\n try {\n const lstat = fs.lstatSync(cursor);\n if (lstat.isSymbolicLink()) {\n return null;\n }\n } catch {\n // Missing path components are fine — the caller decides what to do\n // with a non-existent target.\n break;\n }\n }\n }\n return target;\n}\n\nexport function executeCliLocalFileAction(\n root: string,\n interrupt: CliLocalFileInterrupt,\n opts: { allowWrite: boolean }\n): CliLocalFileResult {\n const safe = resolveSafePath(root, interrupt.path);\n if (!safe) {\n return { ok: false, error: 'Path escapes trusted directory' };\n }\n\n try {\n switch (interrupt.action) {\n case 'read_file': {\n if (!fs.existsSync(safe)) {\n return { ok: false, error: 'File not found' };\n }\n const stat = fs.lstatSync(safe);\n if (stat.isSymbolicLink()) {\n return { ok: false, error: 'Path escapes trusted directory' };\n }\n if (!stat.isFile()) {\n return { ok: false, error: 'Not a file' };\n }\n const requested = Number.isFinite(interrupt.max_bytes)\n ? Math.max(1, Math.min(Number(interrupt.max_bytes), ABSOLUTE_MAX_READ_BYTES))\n : DEFAULT_MAX_READ_BYTES;\n if (stat.size > requested) {\n const buf = fs.readFileSync(safe, { encoding: 'utf8' });\n return {\n ok: true,\n content: buf.slice(0, requested) + `\\n\\n[truncated at ${requested} bytes]`,\n };\n }\n return { ok: true, content: fs.readFileSync(safe, 'utf8') };\n }\n case 'list_dir': {\n if (!fs.existsSync(safe)) {\n return { ok: false, error: 'Directory not found' };\n }\n const entries = fs.readdirSync(safe, { withFileTypes: true });\n const lines = entries\n .slice(0, 200)\n .map((e) => (e.isDirectory() ? `${e.name}/` : e.name));\n if (entries.length > 200) {\n lines.push(`... and ${entries.length - 200} more`);\n }\n return { ok: true, content: lines.join('\\n') };\n }\n case 'write_file': {\n if (!opts.allowWrite) {\n return { ok: false, error: 'Write requires --allow-write' };\n }\n if (interrupt.content === undefined) {\n return { ok: false, error: 'Missing content for write_file' };\n }\n fs.mkdirSync(path.dirname(safe), { recursive: true });\n fs.writeFileSync(safe, interrupt.content, 'utf8');\n return { ok: true, content: 'written' };\n }\n default:\n return { ok: false, error: `Unknown action: ${interrupt.action}` };\n }\n } catch (e) {\n return { ok: false, error: sanitizeLocalFileError(e) };\n }\n}\n\nfunction sanitizeLocalFileError(e: unknown): string {\n if (e && typeof e === 'object' && 'code' in e) {\n const code = (e as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') return 'File or directory not found';\n if (code === 'EACCES' || code === 'EPERM') return 'Permission denied';\n if (code === 'EISDIR') return 'Not a file';\n if (code === 'ENOTDIR') return 'Not a directory';\n }\n return 'Local file operation failed';\n}\n\nexport function isCliLocalFileInterrupt(value: unknown): value is CliLocalFileInterrupt {\n if (typeof value !== 'object' || value === null) return false;\n const v = value as Record<string, unknown>;\n return v.type === 'cli_local_file' && typeof v.action === 'string' && typeof v.path === 'string';\n}\n","/**\n * Directory-trust store for CLI file-capable surfaces.\n *\n * Separates input trust from --allow-write (output mutations). Trust is\n * path-keyed (VS Code workspace-trust model): a grant applies to the directory\n * path, not to individual file contents — new files dropped into a trusted path\n * are readable without re-prompting.\n *\n * See docs/public/cli-get-started.md and gr-feedback trust-directory spec.\n */\n\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport readline from 'readline';\n\nexport type DirectoryTrustDecision = 'once' | 'always' | 'denied';\n\nexport type DirectoryTrustStatus = 'trusted' | 'denied';\n\nexport interface TrustedDirsStore {\n version: 1;\n /** Absolute paths the user chose \"trust always\" for. */\n always: string[];\n}\n\nconst STORE_VERSION = 1 as const;\n\nfunction storePath(): string {\n const base =\n process.env.XDG_CONFIG_HOME ??\n (process.platform === 'win32'\n ? path.join(process.env.APPDATA ?? os.homedir(), 'gravityrail')\n : path.join(os.homedir(), '.config', 'gravityrail'));\n return path.join(base, 'trusted-dirs.json');\n}\n\nexport function loadTrustedDirsStore(): TrustedDirsStore {\n const file = storePath();\n try {\n const raw = JSON.parse(fs.readFileSync(file, 'utf8')) as TrustedDirsStore;\n if (raw?.version === STORE_VERSION && Array.isArray(raw.always)) {\n return { version: STORE_VERSION, always: raw.always.map((p) => path.resolve(p)) };\n }\n } catch {\n // Missing or corrupt — treat as empty.\n }\n return { version: STORE_VERSION, always: [] };\n}\n\nfunction saveTrustedDirsStore(store: TrustedDirsStore): void {\n const file = storePath();\n const dir = path.dirname(file);\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n fs.writeFileSync(file, JSON.stringify(store, null, 2) + '\\n', { mode: 0o600 });\n}\n\nexport function isDirectoryTrusted(dirPath: string, opts?: { trustCwdFlag?: boolean }): boolean {\n if (opts?.trustCwdFlag) return true;\n const resolved = path.resolve(dirPath);\n const store = loadTrustedDirsStore();\n return store.always.includes(resolved);\n}\n\nasync function promptTrustInteractive(dirPath: string): Promise<DirectoryTrustDecision> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n const question = (q: string) => new Promise<string>((resolve) => rl.question(q, resolve));\n\n process.stderr.write(\n `\\nGravity Rail may read files in:\\n ${dirPath}\\n\\n` +\n `File contents can influence the assistant. Do you trust the files in this directory?\\n` +\n ` [1] Trust once (this session)\\n` +\n ` [2] Trust always (remember for this path)\\n` +\n ` [3] No — do not read local files\\n\\n` +\n `Choice [1/2/3] (default 3): `\n );\n const answer = (await question('')).trim() || '3';\n rl.close();\n\n if (answer === '1') return 'once';\n if (answer === '2') return 'always';\n return 'denied';\n}\n\nconst sessionTrusted = new Set<string>();\n\nexport interface DirectoryTrustOptions {\n cwd?: string;\n /** Explicit grant for CI/headless — trust files in this absolute path. */\n trustDir?: string;\n /** Explicit grant — trust process.cwd(). */\n trustCwd?: boolean;\n nonInteractive?: boolean;\n}\n\n/**\n * Resolve directory trust before local file tools run. Does not throw — callers\n * return a tool error to the model when status is `denied`.\n */\nexport async function resolveDirectoryTrust(\n opts: DirectoryTrustOptions\n): Promise<DirectoryTrustStatus> {\n const dir = path.resolve(opts.trustDir ?? opts.cwd ?? process.cwd());\n\n if (isDirectoryTrusted(dir, { trustCwdFlag: opts.trustCwd })) return 'trusted';\n if (sessionTrusted.has(dir)) return 'trusted';\n\n // --trust-dir <path> grants trust for that path (headless escape hatch).\n if (opts.trustDir && path.resolve(opts.trustDir) === dir) {\n sessionTrusted.add(dir);\n return 'trusted';\n }\n\n if (opts.trustCwd) {\n sessionTrusted.add(dir);\n return 'trusted';\n }\n\n if (!process.stdin.isTTY || opts.nonInteractive) {\n return 'denied';\n }\n\n const decision = await promptTrustInteractive(dir);\n if (decision === 'denied') {\n return 'denied';\n }\n if (decision === 'always') {\n const store = loadTrustedDirsStore();\n if (!store.always.includes(dir)) {\n store.always.push(dir);\n saveTrustedDirsStore(store);\n }\n }\n sessionTrusted.add(dir);\n return 'trusted';\n}\n\n/** @deprecated Use resolveDirectoryTrust — kept for tests migrating off session-start gates. */\nexport async function requireDirectoryTrust(opts: DirectoryTrustOptions): Promise<void> {\n const { CLIError } = await import('./errors');\n const dir = path.resolve(opts.trustDir ?? opts.cwd ?? process.cwd());\n const status = await resolveDirectoryTrust(opts);\n if (status === 'trusted') return;\n\n throw new CLIError(\n `Directory not trusted: ${dir}\\n\\n` +\n `Re-run with --trust-cwd (or --trust-dir <path>) after reviewing files in that directory, ` +\n `or run interactively to approve trust when a local file tool is first used.`\n );\n}\n","/**\n * WebSocket-based AG-UI Realtime Client for CLI\n *\n * Handles the AG-UI protocol over WebSocket for realtime voice and text\n * interactions with the Workspace Manager. Adapted from the browser\n * implementation in src/components/voice/ws-unified.ts.\n *\n * Uses the native WebSocket global (Node.js 22+).\n */\n\nimport { EventEmitter } from 'events';\n\n// AG-UI event format over WebSocket\ninterface AGUIWebSocketEvent {\n type: string;\n name?: string;\n value?: any;\n messageId?: string;\n delta?: string;\n role?: string;\n message?: string;\n code?: string;\n toolCallId?: string;\n toolCallName?: string;\n [key: string]: any;\n}\n\nexport interface RealtimeClientOptions {\n /** WebSocket URL (wss://...) */\n url: string;\n /** JWT access token for authentication */\n token: string;\n /** Chat ID to connect to (null to create a new chat) */\n chatId: number | null;\n /** VAD mode: 'server' (default) or 'client' */\n vadMode?: 'client' | 'server';\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Realtime WebSocket client for AG-UI protocol.\n *\n * Events:\n * - connected: Login success with chat/member/assistant IDs\n * - audio: Received audio PCM16 buffer\n * - text_start/text_delta/text_end: Streaming text message\n * - transcription: User speech transcription\n * - response_message: Full message object\n * - tool_call_start/tool_call_args/tool_call_end: Tool calls\n * - run_error: Run error from server\n * - error: Connection/protocol error\n * - closed: WebSocket closed\n */\nexport class RealtimeClient extends EventEmitter {\n private ws: WebSocket | null = null;\n private connected = false;\n private options: Required<RealtimeClientOptions>;\n\n constructor(options: RealtimeClientOptions) {\n super();\n this.options = {\n vadMode: 'server',\n debug: false,\n ...options,\n };\n }\n\n /** Connect to the realtime WebSocket endpoint */\n connect(): Promise<void> {\n if (typeof globalThis.WebSocket === 'undefined') {\n return Promise.reject(\n new Error('WebSocket not available. Node.js 22+ is required for realtime mode.')\n );\n }\n\n return new Promise((resolve, reject) => {\n const params = new URLSearchParams();\n if (this.options.vadMode) {\n params.append('vad', this.options.vadMode);\n }\n const url = params.toString()\n ? `${this.options.url}?${params.toString()}`\n : this.options.url;\n\n if (this.options.debug) {\n process.stderr.write(`[debug] Connecting to ${url}\\n`);\n }\n\n this.ws = new WebSocket(url);\n\n this.ws.onerror = (event: Event) => {\n const msg = event instanceof ErrorEvent ? event.message : 'WebSocket connection failed';\n if (!this.connected) {\n reject(new Error(msg));\n } else {\n this.emit('error', new Error(msg));\n }\n };\n\n this.ws.onclose = (event: CloseEvent) => {\n const reason = event.code === 1006 ? 'Connection lost' : event.reason || 'Closed';\n this.connected = false;\n this.emit('closed', { reason, code: event.code });\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n try {\n const data = typeof event.data === 'string' ? event.data : event.data.toString();\n const parsed: AGUIWebSocketEvent = JSON.parse(data);\n this.emit('ws_recv', parsed);\n this.handleEvent(parsed);\n } catch {\n if (this.options.debug) {\n process.stderr.write(`[debug] Failed to parse message\\n`);\n }\n }\n };\n\n this.ws.onopen = () => {\n if (this.options.debug) {\n process.stderr.write('[debug] WebSocket connected, sending login\\n');\n }\n this.sendCustom('voice.login', {\n token: this.options.token,\n chat_id: this.options.chatId,\n vad: this.options.vadMode,\n });\n };\n\n // Wait for login_success or timeout\n const timeout = setTimeout(() => {\n if (!this.connected) {\n this.close();\n reject(new Error('Connection timeout - no login response within 10s'));\n }\n }, 10000);\n\n this.once('connected', () => {\n clearTimeout(timeout);\n resolve();\n });\n\n this.once('error', () => {\n clearTimeout(timeout);\n });\n });\n }\n\n private handleEvent(event: AGUIWebSocketEvent): void {\n switch (event.type) {\n case 'CUSTOM':\n this.handleCustomEvent(event.name || '', event.value);\n break;\n\n case 'TEXT_MESSAGE_START':\n this.emit('text_start', { messageId: event.messageId || '' });\n break;\n case 'TEXT_MESSAGE_CONTENT':\n this.emit('text_delta', {\n messageId: event.messageId || '',\n delta: event.delta || '',\n });\n break;\n case 'TEXT_MESSAGE_END':\n this.emit('text_end', { messageId: event.messageId || '' });\n break;\n\n case 'TOOL_CALL_START':\n this.emit('tool_call_start', {\n toolCallId: event.toolCallId || '',\n toolCallName: event.toolCallName || '',\n });\n break;\n case 'TOOL_CALL_ARGS':\n this.emit('tool_call_args', {\n toolCallId: event.toolCallId || '',\n delta: event.delta || '',\n });\n break;\n case 'TOOL_CALL_END':\n this.emit('tool_call_end', { toolCallId: event.toolCallId || '' });\n break;\n case 'TOOL_CALL_RESULT':\n this.emit('tool_call_result', {\n toolCallId: event.toolCallId || '',\n result: event.result,\n });\n break;\n\n case 'RUN_STARTED':\n this.emit('run_started', { runId: event.runId });\n break;\n case 'RUN_FINISHED':\n this.emit('run_finished', { runId: event.runId });\n break;\n case 'RUN_ERROR':\n this.emit('run_error', {\n message: event.message || 'Unknown error',\n code: event.code,\n });\n break;\n\n default:\n if (this.options.debug) {\n process.stderr.write(`[debug] Unknown event type: ${event.type}\\n`);\n }\n }\n }\n\n private handleCustomEvent(name: string, value: any): void {\n switch (name) {\n case 'voice.login_success':\n this.connected = true;\n this.emit('connected', {\n chatId: value?.chat_id,\n memberId: value?.member_id,\n assistantId: value?.assistant_id,\n });\n break;\n\n case 'voice.audio':\n if (value?.data) {\n const pcm16 = Buffer.from(value.data, 'base64');\n this.emit('audio', { pcm16, messageId: value.message_id });\n }\n break;\n\n case 'voice.audio_begin':\n this.emit('audio_begin', { messageId: value?.message_id });\n break;\n case 'voice.audio_end':\n this.emit('audio_end', { messageId: value?.message_id });\n break;\n\n case 'voice.interrupt':\n this.emit('interrupt', { messageId: value?.message_id });\n break;\n\n case 'voice.response_message':\n if (value) {\n this.emit('response_message', value);\n }\n break;\n\n case 'voice.transcription':\n if (value) {\n this.emit('transcription', { text: value.text, role: value.role });\n }\n break;\n\n case 'voice.truncate':\n if (value) {\n this.emit('truncate', {\n messageId: value.message_id,\n content: value.content,\n originalContent: value.original_content,\n truncationReason: value.truncation_reason || 'barge_in',\n truncatedAtMs: value.audio_end_ms,\n });\n }\n break;\n\n case 'app.data_update':\n case 'app.navigation':\n case 'app.notification':\n break;\n\n default:\n if (this.options.debug) {\n process.stderr.write(`[debug] Unknown CUSTOM event: ${name}\\n`);\n }\n }\n }\n\n private sendCustom(name: string, value?: any): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n return;\n }\n const event: AGUIWebSocketEvent = { type: 'CUSTOM', name };\n if (value !== undefined) {\n event.value = value;\n }\n this.emit('ws_send', event);\n this.ws.send(JSON.stringify(event));\n }\n\n /** Send raw PCM16 audio data (will be base64-encoded) */\n sendAudio(pcm16: Buffer): void {\n this.sendCustom('voice.audio', {\n data: pcm16.toString('base64'),\n format: 'pcm16',\n sample_rate: 24000,\n });\n }\n\n /** Signal the start of an audio utterance */\n sendAudioBegin(messageId: string): void {\n this.sendCustom('voice.audio_begin', { message_id: messageId });\n }\n\n /** Signal the end of an audio utterance */\n sendAudioEnd(): void {\n this.sendCustom('voice.audio_end');\n }\n\n /** Send a text message (triggers AI inference) */\n sendTextMessage(content: string): void {\n this.sendCustom('voice.user_message', {\n message: { role: 'user', content },\n });\n }\n\n /** Send interrupt signal with playback position */\n sendInterrupt(audioEndMs: number, messageId?: string): void {\n this.sendCustom('voice.interrupt', {\n audio_end_ms: audioEndMs,\n message_id: messageId,\n });\n }\n\n /** Check if the client is connected */\n isConnected(): boolean {\n return this.connected && this.ws?.readyState === WebSocket.OPEN;\n }\n\n /** Close the connection */\n close(): void {\n this.connected = false;\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n}\n","/**\n * Chat TUI — terminal chat interface using ANSI escape codes.\n *\n * Layout (normal):\n * Rows 1..R-2: Message area (full width)\n * Row R-1: Separator + hints\n * Row R: Input (\"You: ...\")\n *\n * Layout (debug):\n * Rows 1..R-2: Chat (left) │ Debug log (right)\n * Row R-1: Separator + hints\n * Row R: Input (\"You: ...\")\n *\n * Keyboard:\n * Up/Down Scroll 1 line\n * Page Up/Down Scroll 1 page\n * Ctrl+B Page up (less-style)\n * Ctrl+F Page down (less-style)\n * Home/End Top / bottom\n * Ctrl+O Toggle detail expansion (tool calls + debug messages)\n * Ctrl+D Toggle debug panel (when --debug)\n * Ctrl+C / exit Quit\n *\n * Mouse:\n * Scroll wheel Scroll 3 lines\n *\n * Zero external dependencies — only Node.js built-ins.\n */\n\nimport { createWriteStream, type WriteStream } from 'fs';\n\n// ─── Public types ─────────────────────────────────────────────────────────────\n\nexport interface ChatMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n /** Reason the message was truncated (voice interruption) */\n truncationReason?: string;\n /** Ms offset where truncation occurred */\n truncatedAtMs?: number;\n /** The full original content before truncation */\n originalContent?: string;\n}\n\nexport interface ChatTUIOptions {\n /** Called when the user sends a message */\n onSend: (text: string) => void;\n /** Called when the user exits (Ctrl+C, 'exit', 'quit') */\n onExit: () => void;\n /** Enable debug panel showing WebSocket traffic */\n debug?: boolean;\n /** Environment name (e.g. 'dev', 'staging', 'prod') — controls debug log file creation */\n env?: string;\n}\n\n// ─── Item types ───────────────────────────────────────────────────────────────\n\nexport interface ToolCallItem {\n kind: 'tool_call';\n id: string;\n name: string;\n args: string;\n done: boolean;\n}\n\nexport interface ToolResultItem {\n kind: 'tool_result';\n toolCallId: string;\n toolName: string;\n content: string;\n}\n\nexport type ChatItem = ChatMessage | ToolCallItem | ToolResultItem;\n\nfunction isToolCall(item: ChatItem): item is ToolCallItem {\n return 'kind' in item && (item as ToolCallItem).kind === 'tool_call';\n}\n\nfunction isToolResult(item: ChatItem): item is ToolResultItem {\n return 'kind' in item && (item as ToolResultItem).kind === 'tool_result';\n}\n\n/** Friendly label for truncation reason */\nfunction getTruncationLabel(reason: string, truncatedAtMs?: number): string {\n const timeStr = truncatedAtMs ? ` at ${(truncatedAtMs / 1000).toFixed(1)}s` : '';\n switch (reason) {\n case 'barge_in':\n return `interrupted: user spoke${timeStr}`;\n case 'client_interrupt':\n return `interrupted${timeStr}`;\n case 'user_cancel':\n return `cancelled by user${timeStr}`;\n case 'error':\n return `error${timeStr}`;\n default:\n return `interrupted${timeStr}`;\n }\n}\n\n/** Extract the unspoken portion of a truncated message */\nfunction getExtraContent(\n content: string | undefined,\n originalContent: string | undefined\n): string | null {\n if (!content || !originalContent) return null;\n const stripped = content.replace(/—interrupted$/, '');\n if (originalContent.startsWith(stripped)) {\n const extra = originalContent.slice(stripped.length);\n return extra.length > 0 ? extra : null;\n }\n return originalContent !== content ? originalContent : null;\n}\n\n// ─── Debug log entry ──────────────────────────────────────────────────────────\n\ninterface DebugEntry {\n direction: 'in' | 'out';\n summary: string; // one-line summary (always shown)\n detail: string; // full JSON (shown when expanded)\n ts: string; // HH:MM:SS\n}\n\n// ─── ANSI helpers ─────────────────────────────────────────────────────────────\n\nconst CSI = '\\x1B[';\nconst HIDE_CURSOR = `${CSI}?25l`;\nconst SHOW_CURSOR = `${CSI}?25h`;\nconst ALT_SCREEN_ON = `${CSI}?1049h`;\nconst ALT_SCREEN_OFF = `${CSI}?1049l`;\nconst CLEAR_EOL = `${CSI}K`;\nconst RESET = `${CSI}0m`;\nconst MOUSE_ON = `${CSI}?1000h${CSI}?1006h`; // Button events + SGR extended\nconst MOUSE_OFF = `${CSI}?1000l${CSI}?1006l`;\n\nconst BLUE = `${CSI}34m`;\nconst GREEN = `${CSI}32m`;\nconst GRAY = `${CSI}90m`;\nconst YELLOW = `${CSI}33m`;\nconst ORANGE = `${CSI}38;5;208m`; // 256-color orange — inbound\nconst LIGHT_BLUE = `${CSI}38;5;117m`; // 256-color light blue — outbound\nconst DIM = `${CSI}2m`;\nconst DIM_ITALIC_GRAY = `${CSI}2;3;90m`; // dim + italic + gray\n\nfunction moveTo(row: number, col: number): string {\n return `${CSI}${row};${col}H`;\n}\n\n// ─── ChatTUI ──────────────────────────────────────────────────────────────────\n\nexport class ChatTUI {\n private items: ChatItem[] = [];\n private inputBuffer = '';\n private isStreaming = false;\n private streamContent = '';\n private scrollOffset = 0;\n private expandDetails = false;\n private rows = 24;\n private cols = 80;\n private started = false;\n private renderTimer: ReturnType<typeof setTimeout> | null = null;\n private displayLinesCache: string[] | null = null;\n private debugLinesCache: string[] | null = null;\n private options: ChatTUIOptions;\n\n // Debug panel state\n private debugEntries: DebugEntry[] = [];\n private debugPanelVisible = false;\n private debugLogStream: WriteStream | null = null;\n\n // Escape sequence accumulator for raw stdin parsing\n private escBuf = '';\n private escTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: ChatTUIOptions) {\n this.options = options;\n this.debugPanelVisible = !!options.debug;\n }\n\n /** Whether the debug panel is currently being rendered */\n private get debugVisible(): boolean {\n return this.debugPanelVisible;\n }\n\n // ─── Lifecycle ──────────────────────────────────────────────────────\n\n start(): void {\n this.updateDimensions();\n process.stdout.write(ALT_SCREEN_ON + MOUSE_ON);\n process.stdout.write(`${CSI}1;${Math.max(1, this.rows - 2)}r`);\n\n // Raw mode + direct data handler (not readline — we parse escape seqs ourselves)\n process.stdin.setEncoding('utf8');\n if (process.stdin.isTTY) process.stdin.setRawMode(true);\n process.stdin.on('data', this.onData);\n process.stdin.resume();\n\n process.stdout.on('resize', this.onResize);\n process.on('exit', this.restoreTerminal);\n\n // Debug log file — only write to disk in dev/staging (never in prod to avoid PHI on disk)\n if (this.options.debug && this.options.env !== 'prod') {\n this.debugLogStream = createWriteStream('gr-cli-realtime-debug.log', { flags: 'a' });\n this.debugLogStream.write(`\\n--- session ${new Date().toISOString()} ---\\n`);\n }\n\n this.started = true;\n this.render();\n }\n\n stop(): void {\n if (!this.started) return;\n this.started = false;\n if (this.renderTimer) {\n clearTimeout(this.renderTimer);\n this.renderTimer = null;\n }\n this.clearEsc();\n if (this.debugLogStream) {\n this.debugLogStream.end();\n this.debugLogStream = null;\n }\n this.restoreTerminal();\n process.stdout.removeListener('resize', this.onResize);\n process.stdin.removeListener('data', this.onData);\n if (process.stdin.isTTY) process.stdin.setRawMode(false);\n process.stdin.pause();\n process.removeListener('exit', this.restoreTerminal);\n }\n\n // ─── Chat state ────────────────────────────────────────────────────\n\n loadHistory(items: ChatItem[]): void {\n this.items = items.filter((item) => (isToolCall(item) ? true : item.content?.trim()));\n this.dirty();\n }\n\n streamStart(): void {\n this.isStreaming = true;\n this.streamContent = '';\n this.scrollOffset = 0;\n this.dirty();\n }\n\n streamDelta(delta: string): void {\n this.streamContent += delta;\n this.dirty();\n }\n\n streamEnd(): void {\n if (this.streamContent.trim()) {\n this.items.push({ role: 'assistant', content: this.streamContent });\n }\n this.isStreaming = false;\n this.streamContent = '';\n this.dirty();\n }\n\n toolCallStart(id: string, name: string): void {\n this.items.push({ kind: 'tool_call', id, name, args: '', done: false });\n this.dirty();\n }\n\n toolCallArgs(id: string, delta: string): void {\n const tc = this.findToolCall(id);\n if (tc) {\n tc.args += delta;\n this.dirty();\n }\n }\n\n toolCallEnd(id: string): void {\n const tc = this.findToolCall(id);\n if (tc) {\n tc.done = true;\n this.dirty();\n }\n }\n\n /** Add a transcription of the user's spoken words (voice mode) */\n addTranscription(text: string): void {\n this.items.push({ role: 'user', content: text });\n this.scrollOffset = 0;\n this.dirty();\n }\n\n /**\n * Truncate the most recent assistant message (voice interruption).\n * Replaces its content with the spoken portion and stores the original.\n */\n truncateAssistant(\n content: string,\n originalContent: string | undefined,\n reason: string,\n truncatedAtMs?: number\n ): void {\n // If currently streaming, commit the stream first\n if (this.isStreaming) {\n this.isStreaming = false;\n this.streamContent = '';\n }\n\n // Find the last assistant message and update it\n for (let i = this.items.length - 1; i >= 0; i--) {\n const item = this.items[i]!;\n if ('role' in item && item.role === 'assistant') {\n item.content = content;\n item.truncationReason = reason;\n item.truncatedAtMs = truncatedAtMs;\n item.originalContent = originalContent;\n this.dirty();\n return;\n }\n }\n\n // No existing assistant message — push the truncated content\n this.items.push({\n role: 'assistant',\n content,\n truncationReason: reason,\n truncatedAtMs: truncatedAtMs,\n originalContent,\n });\n this.dirty();\n }\n\n toolCallResult(toolCallId: string, toolName: string, content: string): void {\n this.items.push({ kind: 'tool_result', toolCallId, toolName, content });\n this.dirty();\n }\n\n /** Find the tool name for a given tool call ID */\n findToolCallName(toolCallId: string): string {\n for (let i = this.items.length - 1; i >= 0; i--) {\n const item = this.items[i]!;\n if (isToolCall(item) && item.id === toolCallId) return item.name;\n }\n return 'tool';\n }\n\n showError(msg: string): void {\n this.items.push({ role: 'system', content: `Error: ${msg}` });\n this.dirty();\n }\n\n // ─── Debug panel ──────────────────────────────────────────────────\n\n /** Log a WebSocket message to the debug panel and (optionally) log file */\n logDebug(direction: 'in' | 'out', raw: any): void {\n const redacted = redactAudio(raw);\n const now = new Date();\n const ts = `${pad2(now.getHours())}:${pad2(now.getMinutes())}:${pad2(now.getSeconds())}`;\n\n // Write to log file (JSON lines, with full redacted payload)\n if (this.debugLogStream) {\n const logLine = JSON.stringify({ ts: now.toISOString(), dir: direction, ...redacted });\n this.debugLogStream.write(logLine + '\\n');\n }\n\n // Add to in-memory debug panel\n const summary = buildDebugSummary(direction, redacted);\n let detail: string;\n try {\n detail = JSON.stringify(redacted, null, 2);\n } catch {\n detail = String(redacted);\n }\n this.debugEntries.push({ direction, summary, detail, ts });\n // Cap at 500 entries to prevent memory growth\n if (this.debugEntries.length > 500) {\n this.debugEntries = this.debugEntries.slice(-300);\n }\n this.debugLinesCache = null;\n this.dirty();\n }\n\n // ─── Private helpers ──────────────────────────────────────────────\n\n private findToolCall(id: string): ToolCallItem | undefined {\n for (let i = this.items.length - 1; i >= 0; i--) {\n const item = this.items[i]!;\n if (isToolCall(item) && item.id === id) return item;\n }\n return undefined;\n }\n\n private dirty(): void {\n this.displayLinesCache = null;\n this.debugLinesCache = null;\n this.scheduleRender();\n }\n\n private restoreTerminal = (): void => {\n process.stdout.write(`${MOUSE_OFF}${CSI}r${ALT_SCREEN_OFF}${SHOW_CURSOR}`);\n };\n\n private updateDimensions(): void {\n this.rows = process.stdout.rows || 24;\n this.cols = process.stdout.columns || 80;\n }\n\n /** Width of the chat (left) panel */\n private chatWidth(): number {\n if (!this.debugVisible) return this.cols;\n // 60% for chat, 40% for debug, with 1 col for divider\n return Math.max(30, Math.floor(this.cols * 0.6) - 1);\n }\n\n /** Width of the debug (right) panel */\n private debugWidth(): number {\n if (!this.debugVisible) return 0;\n return this.cols - this.chatWidth() - 1; // -1 for divider\n }\n\n private scrollHeight(): number {\n return Math.max(1, this.rows - 2);\n }\n\n private pageSize(): number {\n return Math.max(1, this.rows - 4);\n }\n\n // ─── Scroll ───────────────────────────────────────────────────────\n\n private scrollUp(lines: number): void {\n const total = this.getDisplayLines().length;\n const max = Math.max(0, total - this.scrollHeight());\n this.scrollOffset = Math.min(max, this.scrollOffset + lines);\n this.render();\n }\n\n private scrollDown(lines: number): void {\n this.scrollOffset = Math.max(0, this.scrollOffset - lines);\n this.render();\n }\n\n private scrollToTop(): void {\n const total = this.getDisplayLines().length;\n this.scrollOffset = Math.max(0, total - this.scrollHeight());\n this.render();\n }\n\n private scrollToBottom(): void {\n this.scrollOffset = 0;\n this.render();\n }\n\n // ─── Raw stdin parsing ────────────────────────────────────────────\n //\n // We parse stdin directly instead of using readline.emitKeypressEvents\n // because readline doesn't understand SGR mouse sequences and leaks\n // their contents into keypress events as regular characters.\n\n private onData = (data: string): void => {\n for (let i = 0; i < data.length; i++) {\n const ch = data[i]!;\n\n // Accumulating an escape sequence\n if (this.escBuf) {\n this.escBuf += ch;\n\n if (this.escBuf.length === 2) {\n if (ch !== '[') {\n // Not a CSI sequence (Alt+key etc.) — discard\n this.clearEsc();\n }\n continue;\n }\n\n // \\x1B[... — wait for a terminating character (letter or ~)\n if (/[A-Za-z~]/.test(ch)) {\n this.handleCSI(this.escBuf.slice(2, -1), ch);\n this.clearEsc();\n } else if (this.escBuf.length > 32) {\n this.clearEsc(); // safety bail\n }\n continue;\n }\n\n // Start of escape sequence\n if (ch === '\\x1B') {\n this.escBuf = '\\x1B';\n this.escTimer = setTimeout(() => {\n // Bare ESC with no follow-up — ignore\n this.escBuf = '';\n this.escTimer = null;\n }, 100);\n continue;\n }\n\n // Regular byte\n this.handleByte(ch);\n }\n };\n\n private clearEsc(): void {\n this.escBuf = '';\n if (this.escTimer) {\n clearTimeout(this.escTimer);\n this.escTimer = null;\n }\n }\n\n /** Handle a parsed CSI sequence: params is everything between \\x1B[ and the final char */\n private handleCSI(params: string, code: string): void {\n // Mouse SGR: \\x1B[<button;col;rowM (press) or m (release)\n if (params.startsWith('<') && (code === 'M' || code === 'm')) {\n if (code === 'm') return; // ignore button release\n const parts = params.slice(1).split(';');\n if (parts.length >= 1) {\n const button = parseInt(parts[0]!, 10);\n if (button === 64) this.scrollUp(3);\n else if (button === 65) this.scrollDown(3);\n }\n return;\n }\n\n // Arrow keys (no params)\n if (!params) {\n if (code === 'A') {\n this.scrollUp(1);\n return;\n }\n if (code === 'B') {\n this.scrollDown(1);\n return;\n }\n // Home/End (xterm-style)\n if (code === 'H') {\n this.scrollToTop();\n return;\n }\n if (code === 'F') {\n this.scrollToBottom();\n return;\n }\n }\n\n // Tilde sequences: Page Up (5~), Page Down (6~), Home (1~), End (4~)\n if (code === '~') {\n if (params === '5') {\n this.scrollUp(this.pageSize());\n return;\n }\n if (params === '6') {\n this.scrollDown(this.pageSize());\n return;\n }\n if (params === '1') {\n this.scrollToTop();\n return;\n }\n if (params === '4') {\n this.scrollToBottom();\n return;\n }\n }\n }\n\n /** Handle a single non-escape byte */\n private handleByte(ch: string): void {\n const code = ch.charCodeAt(0);\n\n // Ctrl+C → exit\n if (code === 0x03) {\n this.stop();\n this.options.onExit();\n return;\n }\n\n // Ctrl+B → page up (less-style)\n if (code === 0x02) {\n this.scrollUp(this.pageSize());\n return;\n }\n\n // Ctrl+F → page down (less-style)\n if (code === 0x06) {\n this.scrollDown(this.pageSize());\n return;\n }\n\n // Ctrl+D → toggle debug panel visibility (always available)\n if (code === 0x04) {\n this.debugPanelVisible = !this.debugPanelVisible;\n this.displayLinesCache = null;\n this.debugLinesCache = null;\n this.render();\n return;\n }\n\n // Ctrl+O → toggle detail expansion (tool calls + debug messages)\n if (code === 0x0f) {\n this.expandDetails = !this.expandDetails;\n this.displayLinesCache = null;\n this.debugLinesCache = null;\n this.render();\n return;\n }\n\n // Enter\n if (code === 0x0d) {\n this.handleEnter();\n return;\n }\n\n // Backspace (0x7F on most terminals, 0x08 on some)\n if (code === 0x7f || code === 0x08) {\n if (this.inputBuffer.length > 0) {\n this.inputBuffer = this.inputBuffer.slice(0, -1);\n this.renderInputLine();\n }\n return;\n }\n\n // Ignore other control characters\n if (code < 0x20) return;\n\n // Printable character → add to input\n this.inputBuffer += ch;\n this.renderInputLine();\n }\n\n private handleEnter(): void {\n const text = this.inputBuffer.trim();\n this.inputBuffer = '';\n if (!text) {\n this.renderInputLine();\n return;\n }\n if (text.toLowerCase() === 'exit' || text.toLowerCase() === 'quit') {\n this.stop();\n this.options.onExit();\n return;\n }\n this.items.push({ role: 'user', content: text });\n this.scrollOffset = 0;\n this.displayLinesCache = null;\n this.render();\n this.options.onSend(text);\n }\n\n // ─── Events ───────────────────────────────────────────────────────\n\n private onResize = (): void => {\n this.updateDimensions();\n process.stdout.write(`${CSI}1;${Math.max(1, this.rows - 2)}r`);\n this.displayLinesCache = null;\n this.debugLinesCache = null;\n this.render();\n };\n\n // ─── Rendering ────────────────────────────────────────────────────\n\n private scheduleRender(): void {\n if (!this.started || this.renderTimer) return;\n this.renderTimer = setTimeout(() => {\n this.renderTimer = null;\n this.render();\n }, 30);\n }\n\n private getDisplayLines(): string[] {\n if (!this.displayLinesCache) {\n this.displayLinesCache = this.buildDisplayLines();\n }\n return this.displayLinesCache;\n }\n\n private getDebugLines(): string[] {\n if (!this.debugLinesCache) {\n this.debugLinesCache = this.buildDebugLines();\n }\n return this.debugLinesCache;\n }\n\n private render(): void {\n if (!this.started) return;\n this.updateDimensions();\n\n const sh = this.scrollHeight();\n const displayLines = this.getDisplayLines();\n const total = displayLines.length;\n\n // Clamp scroll offset\n const maxOff = Math.max(0, total - sh);\n if (this.scrollOffset > maxOff) this.scrollOffset = maxOff;\n\n // Select visible slice for chat\n let visible: string[];\n if (total <= sh) {\n visible = [...new Array<string>(sh - total).fill(''), ...displayLines];\n } else {\n const end = total - this.scrollOffset;\n const start = end - sh;\n visible = displayLines.slice(start, end);\n }\n\n const buf: string[] = [HIDE_CURSOR];\n\n if (this.debugVisible) {\n this.renderSplitScreen(buf, visible, sh);\n } else {\n for (let i = 0; i < sh; i++) {\n buf.push(moveTo(i + 1, 1), visible[i] || '', CLEAR_EOL);\n }\n }\n\n // Separator with hints (row R-1)\n buf.push(moveTo(this.rows - 1, 1), this.buildSeparator(), CLEAR_EOL);\n\n // Input (row R)\n buf.push(moveTo(this.rows, 1), `${BLUE}You:${RESET} ${this.inputBuffer}${CLEAR_EOL}`);\n\n buf.push(SHOW_CURSOR);\n process.stdout.write(buf.join(''));\n }\n\n private renderSplitScreen(buf: string[], chatVisible: string[], sh: number): void {\n const cw = this.chatWidth();\n const dw = this.debugWidth();\n const divCol = cw + 1;\n\n // Debug panel: auto-scroll to bottom (always show latest)\n const debugLines = this.getDebugLines();\n const debugTotal = debugLines.length;\n let debugVisible: string[];\n if (debugTotal <= sh) {\n debugVisible = [...new Array<string>(sh - debugTotal).fill(''), ...debugLines];\n } else {\n debugVisible = debugLines.slice(debugTotal - sh);\n }\n\n for (let i = 0; i < sh; i++) {\n const chatLine = truncateAnsi(chatVisible[i] || '', cw);\n const debugLine = truncateAnsi(debugVisible[i] || '', dw);\n buf.push(\n moveTo(i + 1, 1),\n chatLine,\n CLEAR_EOL, // clear to end handles rest, but we need to position divider\n moveTo(i + 1, divCol),\n `${DIM}\\u2502${RESET}`,\n debugLine\n );\n // Clear remainder of the debug area\n buf.push(CLEAR_EOL);\n }\n }\n\n private renderInputLine(): void {\n process.stdout.write(\n `${moveTo(this.rows, 1)}${BLUE}You:${RESET} ${this.inputBuffer}${CLEAR_EOL}`\n );\n }\n\n // ─── Separator ────────────────────────────────────────────────────\n\n private buildSeparator(): string {\n const hints: string[] = [];\n\n if (this.scrollOffset > 0) {\n hints.push(`\\u2191${this.scrollOffset}`);\n }\n\n const hasDetails =\n this.items.some((i) => isToolCall(i) || isToolResult(i)) || this.options.debug;\n if (hasDetails) {\n hints.push(`^O ${this.expandDetails ? 'collapse' : 'details'}`);\n }\n\n if (this.options.debug) {\n hints.push(`^D ${this.debugPanelVisible ? 'hide' : 'show'} debug`);\n }\n\n const lineWidth = Math.min(this.cols, 60);\n\n if (!hints.length) {\n return `${GRAY}${'\\u2500'.repeat(lineWidth)}${RESET}`;\n }\n\n const hintStr = ` ${hints.join(' ')} `;\n const dashes = Math.max(0, lineWidth - hintStr.length);\n const left = Math.max(2, Math.floor(dashes / 2));\n const right = Math.max(2, dashes - left);\n return `${GRAY}${'\\u2500'.repeat(left)}${hintStr}${'\\u2500'.repeat(right)}${RESET}`;\n }\n\n // ─── Chat display line building ───────────────────────────────────\n\n private buildDisplayLines(): string[] {\n const lines: string[] = [];\n const w = this.chatWidth();\n\n for (const item of this.items) {\n if (isToolCall(item)) {\n this.appendToolCallLines(lines, item, w);\n } else if (isToolResult(item)) {\n this.appendToolResultLines(lines, item, w);\n } else {\n this.appendMessageLines(lines, item, w);\n }\n lines.push('');\n }\n\n if (this.isStreaming) {\n this.appendStreamLines(lines, w);\n }\n\n return lines;\n }\n\n private appendToolCallLines(lines: string[], tc: ToolCallItem, width: number): void {\n const status = tc.done ? 'Called' : 'Calling';\n const summary = ` ${GRAY}${status} ${tc.name}${tc.done ? '' : '...'}${RESET}`;\n\n if (!this.expandDetails) {\n lines.push(summary);\n return;\n }\n\n lines.push(summary);\n if (tc.args) {\n let formatted = tc.args;\n try {\n formatted = JSON.stringify(JSON.parse(tc.args), null, 2);\n } catch {\n // use raw\n }\n const indent = ' ';\n for (const argLine of formatted.split('\\n')) {\n for (const wl of this.wrapText(argLine, width - indent.length)) {\n lines.push(`${indent}${GRAY}${wl}${RESET}`);\n }\n }\n }\n }\n\n private appendToolResultLines(lines: string[], tr: ToolResultItem, width: number): void {\n if (!this.expandDetails) {\n // Collapsed: show truncated one-liner\n const maxLen = width - 10;\n const preview = tr.content.replace(/\\n/g, ' ').slice(0, maxLen);\n const truncated = preview.length < tr.content.length ? '...' : '';\n lines.push(` ${GRAY}\\u2192 ${tr.toolName}: ${preview}${truncated}${RESET}`);\n return;\n }\n\n lines.push(` ${GRAY}\\u2192 ${tr.toolName} result:${RESET}`);\n let formatted = tr.content;\n try {\n formatted = JSON.stringify(JSON.parse(tr.content), null, 2);\n } catch {\n // use raw\n }\n const indent = ' ';\n for (const resultLine of formatted.split('\\n')) {\n for (const wl of this.wrapText(resultLine, width - indent.length)) {\n lines.push(`${indent}${GRAY}${wl}${RESET}`);\n }\n }\n }\n\n private appendMessageLines(lines: string[], msg: ChatMessage, width: number): void {\n if (msg.role === 'system') {\n for (const para of msg.content.split('\\n')) {\n for (const wl of this.wrapText(para, width - 2)) {\n lines.push(` ${GRAY}${wl}${RESET}`);\n }\n }\n return;\n }\n\n const isUser = msg.role === 'user';\n const label = isUser ? `${BLUE}You:${RESET} ` : `${GREEN}Assistant:${RESET} `;\n const labelWidth = isUser ? 5 : 12;\n const indent = ' '.repeat(labelWidth);\n let first = true;\n\n // Strip the \"—interrupted\" suffix from content for display\n const displayContent = msg.truncationReason\n ? msg.content.replace(/—interrupted$/, '')\n : msg.content;\n\n for (const para of displayContent.split('\\n')) {\n for (const wl of this.wrapText(para, width - labelWidth)) {\n lines.push(first ? label + wl : indent + wl);\n first = false;\n }\n }\n\n // Truncation indicator\n if (msg.truncationReason) {\n const reasonLabel = getTruncationLabel(msg.truncationReason, msg.truncatedAtMs);\n lines.push(`${indent}${YELLOW}[${reasonLabel}]${RESET}`);\n\n // Show unspoken text in dim italic gray\n const extra = getExtraContent(msg.content, msg.originalContent);\n if (extra) {\n for (const para of extra.split('\\n')) {\n for (const wl of this.wrapText(para, width - labelWidth)) {\n lines.push(`${indent}${DIM_ITALIC_GRAY}${wl}${RESET}`);\n }\n }\n }\n }\n }\n\n private appendStreamLines(lines: string[], width: number): void {\n const label = `${GREEN}Assistant:${RESET} `;\n const labelWidth = 12;\n const indent = ' '.repeat(labelWidth);\n\n if (!this.streamContent) {\n lines.push(label);\n return;\n }\n\n let first = true;\n for (const para of this.streamContent.split('\\n')) {\n for (const wl of this.wrapText(para, width - labelWidth)) {\n lines.push(first ? label + wl : indent + wl);\n first = false;\n }\n }\n }\n\n // ─── Debug display line building ──────────────────────────────────\n\n private buildDebugLines(): string[] {\n const lines: string[] = [];\n const dw = this.debugWidth();\n if (dw <= 0) return lines;\n\n for (const entry of this.debugEntries) {\n const color = entry.direction === 'in' ? ORANGE : LIGHT_BLUE;\n const arrow = entry.direction === 'in' ? '\\u25bc' : '\\u25b2'; // ▼ in, ▲ out\n const prefix = `${DIM}${entry.ts}${RESET} ${color}${arrow}${RESET} `;\n const prefixWidth = entry.ts.length + 3; // \"HH:MM:SS ▼ \"\n\n if (!this.expandDetails) {\n // Collapsed: single summary line, truncated\n const maxSummary = dw - prefixWidth;\n const summaryText = entry.summary.slice(0, maxSummary);\n lines.push(`${prefix}${color}${summaryText}${RESET}`);\n } else {\n // Expanded: summary + full detail\n lines.push(`${prefix}${color}${entry.summary}${RESET}`);\n const indent = ' '.repeat(prefixWidth);\n for (const detailLine of entry.detail.split('\\n')) {\n for (const wl of this.wrapText(detailLine, dw - prefixWidth)) {\n lines.push(`${indent}${color}${DIM}${wl}${RESET}`);\n }\n }\n lines.push(''); // blank line between expanded entries\n }\n }\n\n return lines;\n }\n\n // ─── Text utilities ───────────────────────────────────────────────\n\n private wrapText(text: string, maxWidth: number): string[] {\n if (maxWidth <= 0) maxWidth = 1;\n if (!text) return [''];\n if (text.length <= maxWidth) return [text];\n\n const words = text.split(' ');\n const result: string[] = [];\n let current = '';\n\n for (const word of words) {\n if (!current) {\n current = word;\n } else if (current.length + 1 + word.length <= maxWidth) {\n current += ' ' + word;\n } else {\n result.push(current);\n current = word;\n }\n }\n if (current) result.push(current);\n\n return result.length ? result : [''];\n }\n}\n\n// ─── Module-level helpers ─────────────────────────────────────────────────────\n\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n);\n}\n\n/** Truncate a string (which may contain ANSI codes) to fit in maxCols visible characters */\nfunction truncateAnsi(s: string, maxCols: number): string {\n if (maxCols <= 0) return '';\n let visible = 0;\n let i = 0;\n while (i < s.length && visible < maxCols) {\n if (s[i] === '\\x1B') {\n // Skip ANSI sequence\n const end = s.indexOf('m', i);\n if (end !== -1) {\n i = end + 1;\n } else {\n i++;\n }\n } else {\n visible++;\n i++;\n }\n }\n // Append RESET to close any open ANSI sequences\n return s.slice(0, i) + RESET;\n}\n\n/** Redact audio PCM buffers from WebSocket messages for debug display (does not redact text content) */\nfunction redactAudio(msg: any): any {\n if (!msg || typeof msg !== 'object') return msg;\n const clone = { ...msg };\n // Redact voice.audio CUSTOM events\n if (clone.type === 'CUSTOM' && clone.value && typeof clone.value === 'object') {\n const name = clone.name || '';\n if (name === 'voice.audio' && clone.value.data) {\n clone.value = { ...clone.value, data: '[audio]' };\n }\n }\n return clone;\n}\n\n/** Build a one-line summary of a WebSocket message for the collapsed debug view */\nfunction buildDebugSummary(_direction: 'in' | 'out', msg: any): string {\n if (!msg || typeof msg !== 'object') return String(msg);\n\n if (msg.type === 'CUSTOM') {\n const name = msg.name || '?';\n // For audio, just show the event name\n if (name === 'voice.audio') return name;\n // For other CUSTOM events, show name + compact value hint\n if (msg.value && typeof msg.value === 'object') {\n const keys = Object.keys(msg.value);\n if (keys.length <= 3) {\n return `${name} {${keys.join(', ')}}`;\n }\n return `${name} {${keys.length} keys}`;\n }\n return name;\n }\n\n // Standard AG-UI events: TEXT_MESSAGE_CONTENT, TOOL_CALL_START, etc.\n const type = msg.type || '?';\n if (msg.delta) {\n const preview = msg.delta.length > 30 ? msg.delta.slice(0, 30) + '...' : msg.delta;\n return `${type} \"${preview}\"`;\n }\n if (msg.toolCallName) {\n return `${type} ${msg.toolCallName}`;\n }\n return type;\n}\n","/**\n * Audio I/O for CLI using SoX (Sound eXchange)\n *\n * Uses the `rec` command for microphone capture and `play` for audio playback.\n * SoX is cross-platform and available via:\n * macOS: brew install sox\n * Linux: apt install sox\n * Windows: choco install sox\n */\n\nimport { spawn, execSync, spawnSync, type ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\nimport * as readline from 'readline';\n\nconst SAMPLE_RATE = 24000;\n// 100ms of PCM16 audio at 24kHz mono = 4800 bytes\nconst MIC_CHUNK_BYTES = 4800;\n\nexport interface AudioDevice {\n id: string;\n name: string;\n isDefault: boolean;\n}\n\n/** Check if SoX is installed and available */\nexport function checkSoxAvailable(): boolean {\n try {\n execSync('which sox', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\n/** List audio input devices via SoX */\nexport async function listInputDevices(): Promise<AudioDevice[]> {\n return listDevices('rec');\n}\n\n/** List audio output devices via SoX */\nexport async function listOutputDevices(): Promise<AudioDevice[]> {\n return listDevices('play');\n}\n\nfunction listDevices(command: string): Promise<AudioDevice[]> {\n return new Promise((resolve) => {\n try {\n // spawnSync avoids shell interpolation — command and args are always separate\n const proc = spawnSync(command, ['--list-devices'], {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'pipe'],\n timeout: 5000,\n });\n // SoX outputs device list to stderr; combine both streams to be safe\n const output = (proc.stdout ?? '') + (proc.stderr ?? '');\n\n const devices: AudioDevice[] = [];\n const lines = output.split('\\n');\n for (const line of lines) {\n // Parse lines like: \" Input Device 0 : Built-in Microphone\"\n // or \" Output Device 0 : Built-in Output\"\n const match = line.match(/(?:Input|Output)\\s+Device\\s+(\\d+)\\s*:\\s*(.+)/i);\n if (match && match[1] && match[2]) {\n devices.push({\n id: match[1],\n name: match[2].trim(),\n isDefault: devices.length === 0, // First device is typically the default\n });\n }\n }\n\n // If SoX didn't give us devices, return a default entry\n if (devices.length === 0) {\n devices.push({ id: 'default', name: 'System Default', isDefault: true });\n }\n\n resolve(devices);\n } catch {\n // Fallback to system default\n resolve([{ id: 'default', name: 'System Default', isDefault: true }]);\n }\n });\n}\n\n/** Interactively select an audio device */\nexport async function selectDevice(devices: AudioDevice[], label: string): Promise<AudioDevice> {\n if (devices.length <= 1) {\n return devices[0]!;\n }\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n terminal: true,\n });\n\n process.stderr.write(`\\n ${label}:\\n`);\n for (let i = 0; i < devices.length; i++) {\n const dev = devices[i]!;\n const marker = dev.isDefault ? ' (default)' : '';\n process.stderr.write(` ${i + 1}. ${dev.name}${marker}\\n`);\n }\n\n return new Promise((resolve) => {\n const defaultIdx = devices.findIndex((d) => d.isDefault);\n const defaultNum = defaultIdx >= 0 ? defaultIdx + 1 : 1;\n\n rl.question(` Select [${defaultNum}]: `, (answer) => {\n rl.close();\n const num = answer.trim() ? parseInt(answer.trim(), 10) : defaultNum;\n const idx = Math.max(0, Math.min(devices.length - 1, num - 1));\n resolve(devices[idx]!);\n });\n });\n}\n\n/**\n * Microphone capture via SoX `rec`.\n * Streams raw PCM16 signed 16-bit LE mono audio at 24kHz.\n */\nexport class MicCapture {\n private process: ChildProcess | null = null;\n private onData: (pcm16: Buffer) => void;\n private buffer = Buffer.alloc(0);\n\n constructor(onData: (pcm16: Buffer) => void) {\n this.onData = onData;\n }\n\n /** Start recording from the microphone */\n start(deviceId?: string): void {\n const args = [\n '-q', // quiet\n '-t',\n 'raw', // raw PCM output\n '-r',\n String(SAMPLE_RATE),\n '-e',\n 'signed-integer',\n '-b',\n '16', // 16-bit\n '-c',\n '1', // mono\n '-L', // little-endian\n '-', // stdout\n ];\n\n const env = { ...process.env };\n if (deviceId && deviceId !== 'default') {\n env.AUDIODEV = deviceId;\n }\n\n this.process = spawn('rec', args, {\n env,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n this.process.stdout?.on('data', (data: Buffer) => {\n // Accumulate data and emit in consistent chunk sizes\n this.buffer = Buffer.concat([this.buffer, data]);\n while (this.buffer.length >= MIC_CHUNK_BYTES) {\n const chunk = this.buffer.subarray(0, MIC_CHUNK_BYTES);\n this.buffer = this.buffer.subarray(MIC_CHUNK_BYTES);\n this.onData(Buffer.from(chunk));\n }\n });\n\n this.process.stderr?.on('data', (data: Buffer) => {\n // SoX outputs warnings/errors to stderr - ignore unless debugging\n const msg = data.toString().trim();\n if (msg && !msg.includes('WARN')) {\n process.stderr.write(`[mic] ${msg}\\n`);\n }\n });\n\n this.process.on('error', (err) => {\n process.stderr.write(`[mic] Process error: ${err.message}\\n`);\n });\n }\n\n /** Stop recording */\n stop(): void {\n if (this.process) {\n this.process.kill('SIGTERM');\n this.process = null;\n }\n this.buffer = Buffer.alloc(0);\n }\n}\n\n/**\n * Audio playback via SoX `play`.\n * Accepts raw PCM16 signed 16-bit LE mono audio at 24kHz.\n *\n * Streams audio to SoX's stdin so playback begins immediately on the first\n * chunk — no waiting for the full response. Queues back-to-back responses\n * so a second response never kills the first mid-playback.\n *\n * Events:\n * - 'playing': SoX process spawned for a response\n * - 'done': All queued responses finished (or playback was stopped)\n */\nexport class AudioPlayer extends EventEmitter {\n private process: ChildProcess | null = null;\n private deviceId?: string;\n\n // When true, we own the SoX process's stdin and are actively streaming to it.\n // When false with a process, the stdin has been closed and SoX is draining.\n private streaming = false;\n\n // Buffer chunks when another response is already playing\n private pendingChunks: Buffer[] = [];\n private pendingBytes = 0;\n\n // Queue of complete response buffers waiting to play\n private queue: { audio: Buffer; messageId?: string }[] = [];\n\n // Playback position tracking for barge-in\n private currentMessageId?: string;\n private playbackStartTime = 0; // Date.now() when SoX started\n private bytesWritten = 0; // total bytes piped to SoX for duration estimation\n\n constructor(deviceId?: string) {\n super();\n this.deviceId = deviceId;\n }\n\n /** Check if audio is currently playing or queued */\n get isPlaying(): boolean {\n return this.process !== null || this.queue.length > 0;\n }\n\n /** Get the message ID of the currently playing audio */\n get playingMessageId(): string | undefined {\n return this.currentMessageId;\n }\n\n /** Duration of audio written so far in ms */\n private get currentDurationMs(): number {\n // PCM16 mono 24kHz = 48000 bytes/sec\n return (this.bytesWritten / (SAMPLE_RATE * 2)) * 1000;\n }\n\n /**\n * Estimate current playback position in milliseconds.\n * Uses wall-clock time since SoX started playing.\n */\n getPlaybackTimeMs(): number | null {\n if (!this.process || this.playbackStartTime === 0) return null;\n const elapsed = Date.now() - this.playbackStartTime;\n return Math.min(elapsed, this.currentDurationMs);\n }\n\n /**\n * Stream PCM16 audio data for playback.\n * On the first chunk, spawns SoX and begins playback immediately.\n */\n write(pcm16: Buffer): void {\n if (this.process && !this.streaming) {\n // A previous response is still playing/draining — buffer for later\n this.pendingChunks.push(pcm16);\n this.pendingBytes += pcm16.length;\n return;\n }\n\n if (!this.process) {\n this.spawnSoxProcess();\n }\n\n this.process!.stdin!.write(pcm16);\n this.bytesWritten += pcm16.length;\n }\n\n /**\n * End the current audio response.\n * If streaming, closes stdin to let SoX finish playing.\n * If buffering behind another response, adds to the queue.\n */\n endResponse(messageId?: string): void {\n if (this.streaming && this.process) {\n this.currentMessageId = messageId;\n this.streaming = false;\n this.process.stdin!.end();\n } else if (this.pendingChunks.length > 0) {\n const audio = Buffer.concat(this.pendingChunks);\n this.pendingChunks = [];\n this.pendingBytes = 0;\n this.queue.push({ audio, messageId });\n }\n }\n\n /** Stop current playback, discard all queued audio */\n stop(): void {\n this.pendingChunks = [];\n this.pendingBytes = 0;\n this.queue = [];\n this.streaming = false;\n\n const wasPlaying = this.process !== null;\n if (this.process) {\n try {\n this.process.stdin?.destroy();\n this.process.kill('SIGTERM');\n } catch {\n // Ignore\n }\n this.process = null;\n }\n this.currentMessageId = undefined;\n this.playbackStartTime = 0;\n this.bytesWritten = 0;\n if (wasPlaying) {\n this.emit('done');\n }\n }\n\n /** Spawn a SoX `play` process reading raw PCM from stdin */\n private spawnSoxProcess(): void {\n this.bytesWritten = 0;\n this.currentMessageId = undefined;\n\n const args = [\n '-q', // quiet\n '-t',\n 'raw',\n '-r',\n String(SAMPLE_RATE),\n '-e',\n 'signed-integer',\n '-b',\n '16',\n '-c',\n '1',\n '-L', // little-endian\n '-', // read from stdin\n ];\n\n const env = { ...process.env };\n if (this.deviceId && this.deviceId !== 'default') {\n env.AUDIODEV = this.deviceId;\n }\n\n const proc = spawn('play', args, {\n env,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n proc.on('error', (err) => {\n process.stderr.write(`[player] Process error: ${err.message}\\n`);\n });\n\n proc.on('exit', (code, _signal) => {\n // 143 = SIGTERM (normal stop/interrupt)\n if (code !== null && code !== 0 && code !== 143) {\n process.stderr.write(`[player] SoX exited with code ${code}\\n`);\n }\n if (this.process === proc) {\n this.process = null;\n this.streaming = false;\n if (this.queue.length > 0) {\n const next = this.queue.shift()!;\n this.playQueued(next.audio, next.messageId);\n } else {\n this.emit('done');\n }\n }\n });\n\n proc.stderr?.on('data', (data: Buffer) => {\n const msg = data.toString().trim();\n if (msg) {\n process.stderr.write(`[player:sox] ${msg}\\n`);\n }\n });\n\n proc.stdout?.resume();\n\n this.process = proc;\n this.streaming = true;\n this.playbackStartTime = Date.now();\n this.emit('playing');\n }\n\n /** Play a complete pre-buffered response (from the queue) */\n private playQueued(audio: Buffer, messageId?: string): void {\n this.spawnSoxProcess();\n this.currentMessageId = messageId;\n this.process!.stdin!.write(audio);\n this.bytesWritten = audio.length;\n this.process!.stdin!.end();\n this.streaming = false;\n }\n}\n","/**\n * Concierge chat command — interactive chat with the global concierge agent.\n *\n * Supports the same modes as workspace manager chat (text, realtime, voice)\n * but without requiring a workspace.\n */\n\nimport { formatTimestamp, selectFromList } from '../cli-utils';\nimport {\n createConciergeChat,\n getConciergeChat,\n getConciergeChatMessages,\n listConciergeChats,\n originateConciergeCall,\n originateConciergeSms,\n type ConciergeChat,\n} from '../lib/concierge-api';\nimport { requireAuth, type AuthenticatedContext } from '../lib/context';\nimport { CLIError } from '../lib/errors';\nimport type { CommandHandlerContext } from '../lib/types';\nimport { buildCliConciergeAppContext } from '../lib/cli-client-context';\nimport { runChatSession, type ChatSession } from '../lib/chat-session';\n\nexport async function conciergeOutboundCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const { args } = hctx;\n\n if (args.call && args.sms) {\n throw new CLIError('--call and --sms are mutually exclusive');\n }\n if (args.call) {\n const result = await originateConciergeCall(ctx);\n process.stderr.write(\n `Concierge call started. callSid=${result.callSid} startedAt=${result.startedAt}\\n`\n );\n return;\n }\n if (args.sms) {\n const result = await originateConciergeSms(ctx);\n process.stderr.write(\n `Concierge SMS started. messageSid=${result.messageSid} conversationId=${result.conversationId}\\n`\n );\n return;\n }\n\n throw new CLIError(\n 'Use `gr concierge chat --call`, `gr concierge chat --sms`, or `gr concierge chat` for interactive mode.'\n );\n}\n\nexport async function conciergeCommand(hctx: CommandHandlerContext): Promise<void> {\n const ctx = requireAuth(hctx.ctx);\n const { args } = hctx;\n\n if (args.call || args.sms) {\n if (args.call && args.sms) {\n throw new CLIError('--call and --sms are mutually exclusive');\n }\n if (args.voice || args.realtime) {\n throw new CLIError('--call/--sms cannot be combined with --voice or --realtime');\n }\n await conciergeOutboundCommand(hctx);\n return;\n }\n\n const chatIdArg = typeof args['chat-id'] === 'string' ? args['chat-id'] : undefined;\n const message = typeof args.message === 'string' ? args.message : undefined;\n\n const chat = await getOrCreateConciergeChat(ctx, chatIdArg, !!message);\n const session = buildConciergeSession(ctx, chat, args);\n await runChatSession(session, args);\n}\n\nfunction buildConciergeSession(\n ctx: AuthenticatedContext,\n chat: ConciergeChat,\n args: Record<string, unknown>\n): ChatSession {\n const wsBase = ctx.envConfig.apiUrl.replace(/^https:/, 'wss:').replace(/^http:/, 'ws:');\n return {\n ctx,\n workspaceUuid: '',\n chatId: chat.id,\n chatUuid: chat.uuid,\n chatTitle: chat.title || chat.uuid,\n aguiEndpointUrl: `${ctx.envConfig.apiUrl}/api/v2/concierge/chats/${chat.id}/chat/agui`,\n wsUrl: `${wsBase}/api/v2/concierge/voice/stream-ws`,\n loadMessages: () => getConciergeChatMessages(ctx, chat.id).catch(() => []),\n label: 'Concierge',\n model: undefined, // concierge doesn't send model field\n appContext: buildCliConciergeAppContext(),\n allowWrite: true,\n trustCwd: !!args['trust-cwd'],\n trustDir: typeof args['trust-dir'] === 'string' ? args['trust-dir'] : undefined,\n };\n}\n\nasync function getOrCreateConciergeChat(\n ctx: AuthenticatedContext,\n chatIdArg: string | undefined,\n skipSelection: boolean\n): Promise<ConciergeChat> {\n if (chatIdArg) {\n const id = Number(chatIdArg);\n if (isNaN(id)) throw new CLIError('--chat-id must be a number');\n return getConciergeChat(ctx, id);\n }\n\n if (skipSelection) {\n const chat = await createConciergeChat(ctx);\n process.stderr.write(`Created concierge chat #${chat.id}\\n`);\n return chat;\n }\n\n const chats = await listConciergeChats(ctx);\n\n const { item: selectedChat, isNew } = await selectFromList(chats, {\n title: 'Select a concierge chat or create a new one',\n labelFn: (c) => c.title || `Chat ${c.uuid.slice(0, 8)}...`,\n detailFn: (c) => formatTimestamp(c.updatedAt),\n emptyMessage: 'No existing concierge chats.',\n allowNew: true,\n newLabel: '+ Start new chat',\n });\n\n if (!selectedChat && !isNew) {\n throw new CLIError('No chat selected.');\n }\n\n if (isNew) {\n const chat = await createConciergeChat(ctx);\n process.stderr.write(`Created concierge chat #${chat.id}\\n`);\n return chat;\n }\n return selectedChat!;\n}\n","import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { join } from 'path';\nimport type { AuthenticatedContext } from '../lib/context';\nimport { CLIError } from '../lib/errors';\nimport { stderr } from '../lib/output';\n\nexport async function devImportLocalCommand(\n ctx: AuthenticatedContext,\n workspace: string\n): Promise<void> {\n stderr(`Exporting workspace ${workspace}...`);\n const exportData = await ctx.apiClient.exportWorkspace(workspace);\n\n stderr('Export successful!');\n stderr(` Workflows: ${(exportData.workflows || []).length}`);\n stderr(` Tasks: ${(exportData.tasks || []).length}`);\n stderr(` Data Types: ${(exportData.dataTypes || []).length}`);\n stderr(` Sites: ${(exportData.sites || []).length}`);\n\n const slug = workspace.slice(0, 8);\n const importCacheDir = join(ctx.credentialsManager.getCacheDir(), 'imports');\n if (!existsSync(importCacheDir)) {\n mkdirSync(importCacheDir, { recursive: true });\n }\n const filename = `ws-${slug}-${workspace}.json`;\n const filepath = join(importCacheDir, filename);\n writeFileSync(filepath, JSON.stringify(exportData, null, 2));\n stderr(`Saved to: ${filepath}`);\n\n stderr('Running dev:restore...');\n const rootDir = findProjectRoot();\n const relativePath = filepath.replace(rootDir + '/', '');\n\n try {\n const result = execSync(`yarn dev:restore ${relativePath}`, {\n cwd: rootDir,\n stdio: 'pipe',\n encoding: 'utf-8',\n });\n process.stderr.write(result);\n\n const failed =\n (result.includes('Failed/Skipped: ') && !result.includes('Failed/Skipped: 0')) ||\n result.includes('Successfully restored: 0');\n\n if (failed) throw new CLIError('Import failed');\n } catch (error: unknown) {\n if (error instanceof CLIError) throw error;\n const execError = error as { stdout?: string; stderr?: string };\n if (execError.stdout) process.stderr.write(execError.stdout);\n if (execError.stderr) process.stderr.write(execError.stderr);\n throw new CLIError('dev:restore failed');\n }\n\n stderr(`Import complete: ${workspace}`);\n}\n\nfunction findProjectRoot(): string {\n let dir = process.cwd();\n while (dir !== '/') {\n const pkgPath = join(dir, 'package.json');\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n if (pkg.workspaces) return dir;\n } catch {\n // continue\n }\n }\n dir = join(dir, '..');\n }\n return process.cwd();\n}\n","/**\n * `gr get-started` / `gr setup` — bootstrap instructions for humans and LLM agents.\n */\n\nimport type { CommandHandlerContext } from '../lib/types';\nimport { requireAuth } from '../lib/context';\n\nconst WEB_SETUP = 'https://app.gravityrail.com/setup';\nconst WEB_GET_STARTED = 'https://app.gravityrail.com/get-started';\n\nconst HUMAN_GUIDE = `Gravity Rail — getting started\n\n1. Authenticate: gr login --env prod\n Confirm: gr whoami\n\n2. Recommended path — concierge (no workspace required):\n gr concierge chat --allow-write\n The concierge can create your org (auto-created on first login), list products,\n start Stripe checkout, and create your first workspace.\n\n3. Verify workspaces: gr workspaces list\n\n4. Web wizards (human-friendly): ${WEB_SETUP} and ${WEB_GET_STARTED}\n\nHeadless boundary: Stripe checkout needs a human in a browser — the concierge returns\na checkout URL; an agent should hand that link to the user, not loop on payment.\n\nAgent-readable steps: gr get-started --format llm\n`;\n\nconst LLM_GUIDE = `# Gravity Rail CLI bootstrap (agent instructions)\n\n## Preconditions\n- Install: \\`npm install -g @gravity-rail/cli\\` or \\`npx @gravity-rail/cli\\`\n- Authenticate: \\`gr login --env prod\\` (interactive OAuth). Verify with \\`gr whoami\\`.\n- **Monorepo dev:** from gravity-team with Docker dev up, use \\`yarn gr <cmd> --realm superadmin\\` (reads \\`dev-realms.json\\`; no browser). Rebuild: \\`yarn workspace @gravity-rail/gr-cli build\\`.\n\n## Important facts\n- **Agents/CI:** do not leave stdin open on read-only commands; use \\`GRAVITY_RAIL_API_KEY\\` or redirect stdin from /dev/null. Commands only read stdin when \\`--data\\`/\\`--file\\` is passed.\n- Use \\`--env dev|staging|prod\\` (default prod) so credentials match the target; \\`gr whoami\\` shows the active env.\n- After login, an **organization is created automatically** — do not create a duplicate org unless \\`gr organizations list\\` is empty.\n- **Workspace is required** for workflow/agent/task commands (\\`-w <workspace-uuid>\\`).\n- **Concierge does not require \\`-w\\`** — use it for first-run setup.\n\n## Recommended path (concierge-driven)\n\\`\\`\\`bash\ngr concierge chat --allow-write --message \"Help me set up my first Gravity Rail workspace\"\n\\`\\`\\`\nFlags for unattended turns:\n- \\`--message\\` / \\`-m\\`: single-turn (non-interactive)\n- \\`--auto-approve\\`: skip HITL tool approval where policy allows\n- \\`--allow-write\\`: required for create/update tools\n\nThe concierge can: list/create orgs, list org/workspace products, create Stripe checkout sessions, create workspace specs, and \\`create_workspace\\`.\n\n## Manual CLI path (if not using concierge)\n1. \\`gr whoami\\` — confirm account\n2. \\`gr organizations list\\` — note org slug/UUID\n3. \\`gr concierge chat\\` OR web: ${WEB_GET_STARTED}\n4. Product purchase: concierge returns Stripe checkout URL → **human must complete in browser**\n5. \\`gr workspaces list\\` — pick workspace UUID for \\`-w\\`\n\n## Support (account-level, no workspace)\n\\`\\`\\`bash\ngr support create --type question --title \"...\" --description \"...\" --allow-write\ngr support list\n\\`\\`\\`\n\n## Web fallbacks\n- Concierge / setup: ${WEB_SETUP}\n- Wizard: ${WEB_GET_STARTED}\n\n## Headless limits (do not retry forever)\n- Stripe payment / checkout: requires human browser\n- OAuth login: requires human browser\n- Directory trust for future local-file tools: use \\`--trust-cwd\\` only after user confirms files are safe\n\n## Local project files (CLI only)\nAfter directory trust + \\`--allow-write\\`, the concierge can use \\`read_local_file\\`, \\`list_local_dir\\`, \\`write_local_file\\` (client-executed via HITL).\n\n## Verify success\n\\`gr workspaces list\\` then \\`gr workflows list -w <uuid>\\` or \\`gr agents list -w <uuid>\\`\n\n## Local phone / voice QA (monorepo dev)\n\\`\\`\\`bash\nyarn dev:twilio-ngrok --start-ngrok --url gravityrail.ngrok.io dev.<you> -w acme-demo\nyarn gr phone setup\nyarn gr account verify-phone --phone +1… --allow-write --realm superadmin\nyarn gr concierge chat --call --allow-write --realm superadmin\nyarn gr phone outbound --realm acme-demo/acme-admin --workflow-id 1 --allow-write\n\\`\\`\\`\nSee \\`.claude/skills/phone-voice-qa/SKILL.md\\` and \\`./scripts/e2e-voice-phone-matrix.sh\\`.\n`;\n\nexport async function getStartedCommand(hctx: CommandHandlerContext): Promise<void> {\n const format = hctx.args.format ?? hctx.args.agent;\n const isLlm =\n format === 'llm' || format === 'agent' || hctx.args['format'] === 'llm' || !!hctx.args.agent;\n\n if (!isLlm) {\n try {\n requireAuth(hctx.ctx);\n } catch {\n // Pre-login users can still read the guide.\n }\n process.stdout.write(HUMAN_GUIDE);\n return;\n }\n\n process.stdout.write(LLM_GUIDE);\n}\n","import { GravityRailClient } from '@gravity-rail/sdk';\nimport { performOAuthFlow } from '../cli-utils';\nimport type { CommandContext } from '../lib/context';\nimport { stderr } from '../lib/output';\n\nexport async function loginCommand(ctx: CommandContext): Promise<void> {\n const { accessToken } = await performOAuthFlow({\n env: ctx.env,\n envConfig: ctx.envConfig,\n credentialsManager: ctx.credentialsManager,\n });\n\n const apiClient = new GravityRailClient(accessToken, ctx.envConfig.apiUrl);\n const account = await apiClient.getUserAccount();\n stderr(`Logged in as ${account.name} (${account.email})`);\n}\n\nexport async function logoutCommand(ctx: CommandContext): Promise<void> {\n ctx.credentialsManager.clear(ctx.env);\n stderr(`Credentials cleared for ${ctx.env}`);\n}\n","import type { AuthenticatedContext } from '../lib/context';\nimport { outputData, type TableColumn } from '../lib/output';\n\n// The return type of getMyOrganizations references the admin-only\n// AdminAccountOrgMembership type, which is not re-exported from the public\n// @gravity-rail/sdk surface. We infer the element shape from the runtime\n// method signature here.\ntype OrgMembership = Awaited<\n ReturnType<AuthenticatedContext['apiClient']['getMyOrganizations']>\n>[number];\n\nconst COLUMNS: TableColumn<OrgMembership>[] = [\n { header: 'NAME', getValue: (o) => o.organizationName || '', maxWidth: 35 },\n { header: 'SLUG', getValue: (o) => o.organizationSlug || '', maxWidth: 25 },\n { header: 'UUID', getValue: (o) => o.organizationUuid },\n { header: 'ROLE', getValue: (o) => o.role || '' },\n];\n\nexport async function organizationsListCommand(ctx: AuthenticatedContext): Promise<void> {\n const organizations = await ctx.apiClient.getMyOrganizations();\n outputData(organizations, ctx, COLUMNS);\n}\n","import type { Account } from '@gravity-rail/sdk';\nimport type { AuthenticatedContext } from '../lib/context';\nimport { outputSingle, type TableColumn } from '../lib/output';\n\nconst COLUMNS: TableColumn<Account>[] = [\n { header: 'NAME', getValue: (a) => a.name || '', maxWidth: 30 },\n { header: 'EMAIL', getValue: (a) => a.email || '', maxWidth: 40 },\n { header: 'UUID', getValue: (a) => a.uuid },\n { header: 'ENV', getValue: () => '' },\n { header: 'SUPERUSER', getValue: (a) => (a.isSuperuser ? 'yes' : 'no') },\n];\n\nexport async function whoamiCommand(ctx: AuthenticatedContext): Promise<void> {\n const account = await ctx.apiClient.getUserAccount();\n const columns = COLUMNS.map((col) =>\n col.header === 'ENV' ? { ...col, getValue: () => ctx.env } : col\n );\n outputSingle(account, ctx, columns);\n}\n","import { authBrowserCommand } from './commands/auth-browser';\nimport { chatCommand, manageCommand } from './commands/manage';\nimport { conciergeCommand, conciergeOutboundCommand } from './commands/concierge';\nimport { devImportLocalCommand } from './commands/dev';\nimport { getStartedCommand } from './commands/get-started';\nimport { loginCommand, logoutCommand } from './commands/login';\nimport { organizationsListCommand } from './commands/organizations';\nimport { whoamiCommand } from './commands/whoami';\nimport { requireAuth } from './lib/context';\nimport type { CommandRegistry } from './lib/registry';\nimport type { CommandHandlerContext } from './lib/types';\n\n/**\n * Register top-level CLI commands that do not belong to a domain module\n * (login, manage, concierge, etc.). Used by both the public `@gravity-rail/cli`\n * binary and the internal `@gravity-rail/gr-cli` wrapper.\n */\nexport function registerSpecialCommands(registry: CommandRegistry): void {\n registry.registerCommand({\n path: ['login'],\n description: 'Authenticate via OAuth',\n requiresAuth: false,\n handler: async ({ ctx }) => {\n await loginCommand(ctx);\n },\n });\n\n registry.registerCommand({\n path: ['logout'],\n description: 'Clear cached credentials',\n requiresAuth: false,\n handler: async ({ ctx }) => {\n await logoutCommand(ctx);\n },\n });\n\n registry.registerCommand({\n path: ['auth', 'browser'],\n description: 'Open an authenticated browser session using CLI credentials',\n args: [\n { name: 'no-open', description: 'Print the URL instead of opening browser', isFlag: true },\n ],\n handler: async ({ ctx, args }) => {\n await authBrowserCommand(requireAuth(ctx), args);\n },\n });\n\n registry.registerCommand({\n path: ['manage'],\n description: 'Interactive workspace manager chat (text, realtime, or voice)',\n requiresWorkspace: true,\n mutates: true,\n args: [\n { name: 'realtime', description: 'Use WebSocket realtime connection', isFlag: true },\n { name: 'voice', description: 'Enable voice mode (microphone + speaker)', isFlag: true },\n { name: 'message', alias: 'm', description: 'Single-turn: send one message and exit' },\n { name: 'as-member', description: 'Chat as a specific member (by numeric ID)' },\n { name: 'chat-id', description: 'Resume an existing chat by numeric ID' },\n { name: 'vad', description: 'Voice activity detection: server (default) or client' },\n { name: 'list-devices', description: 'List audio devices and exit', isFlag: true },\n { name: 'input-device', description: 'Microphone device name or ID' },\n { name: 'output-device', description: 'Speaker device name or ID' },\n { name: 'debug', description: 'Enable debug logging', isFlag: true },\n {\n name: 'auto-approve',\n description: 'Auto-approve all tool calls (skip HITL)',\n isFlag: true,\n },\n {\n name: 'trust-cwd',\n description: 'Trust files in the current working directory (non-interactive)',\n isFlag: true,\n },\n {\n name: 'trust-dir',\n description: 'Trust files in this directory (non-interactive; absolute path)',\n },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await manageCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['chat'],\n description: 'Chat with a workflow, member, or existing chat (text, realtime, or voice)',\n requiresWorkspace: true,\n mutates: true,\n args: [\n { name: 'workflow', description: 'Start assignment chat with workflow (by numeric ID)' },\n { name: 'member', description: 'Start DM with a member (by numeric ID)' },\n { name: 'chat-id', description: 'Resume an existing chat by numeric ID' },\n { name: 'realtime', description: 'Use WebSocket realtime connection', isFlag: true },\n { name: 'voice', description: 'Enable voice mode (microphone + speaker)', isFlag: true },\n { name: 'message', alias: 'm', description: 'Single-turn: send one message and exit' },\n { name: 'vad', description: 'Voice activity detection: server (default) or client' },\n { name: 'list-devices', description: 'List audio devices and exit', isFlag: true },\n { name: 'input-device', description: 'Microphone device name or ID' },\n { name: 'output-device', description: 'Speaker device name or ID' },\n { name: 'debug', description: 'Enable debug logging', isFlag: true },\n {\n name: 'auto-approve',\n description: 'Auto-approve all tool calls (skip HITL)',\n isFlag: true,\n },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await chatCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['get-started'],\n description: 'Bootstrap instructions for new users and LLM agents',\n requiresAuth: false,\n args: [\n {\n name: 'format',\n description: 'Output format: llm (agent-readable) or default (human)',\n },\n {\n name: 'agent',\n description: 'Alias for --format llm',\n isFlag: true,\n },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await getStartedCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['setup'],\n description: 'Alias for get-started — bootstrap instructions',\n requiresAuth: false,\n args: [\n { name: 'format', description: 'Output format: llm or default' },\n { name: 'agent', description: 'Alias for --format llm', isFlag: true },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await getStartedCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['concierge'],\n description: 'Call or SMS your verified phone via the Concierge (server-side)',\n requiresWorkspace: false,\n mutates: true,\n args: [\n { name: 'call', description: 'Ring your verified account phone', isFlag: true },\n { name: 'sms', description: 'Start an SMS thread on your verified phone', isFlag: true },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await conciergeOutboundCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['account', 'verify-phone'],\n description: 'Verify your account phone for concierge chat --call / --sms',\n requiresWorkspace: false,\n mutates: true,\n args: [{ name: 'phone', description: 'E.164 phone number (optional; prompts if omitted)' }],\n handler: async (hctx: CommandHandlerContext) => {\n const { accountVerifyPhoneCommand } = await import('./commands/account-verify-phone');\n await accountVerifyPhoneCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['concierge', 'chat'],\n description: 'Interactive concierge chat (text, realtime, or voice)',\n requiresWorkspace: false,\n mutates: true,\n args: [\n { name: 'realtime', description: 'Use WebSocket realtime connection', isFlag: true },\n { name: 'voice', description: 'Enable voice mode (microphone + speaker)', isFlag: true },\n {\n name: 'call',\n description: 'Ring your verified account phone (server-side)',\n isFlag: true,\n },\n {\n name: 'sms',\n description: 'SMS your verified account phone (server-side)',\n isFlag: true,\n },\n { name: 'message', alias: 'm', description: 'Single-turn: send one message and exit' },\n { name: 'chat-id', description: 'Resume an existing chat by numeric ID' },\n { name: 'vad', description: 'Voice activity detection: server (default) or client' },\n { name: 'list-devices', description: 'List audio devices and exit', isFlag: true },\n { name: 'input-device', description: 'Microphone device name or ID' },\n { name: 'output-device', description: 'Speaker device name or ID' },\n { name: 'debug', description: 'Enable debug logging', isFlag: true },\n {\n name: 'auto-approve',\n description: 'Auto-approve all tool calls (skip HITL)',\n isFlag: true,\n },\n {\n name: 'trust-cwd',\n description: 'Trust files in the current working directory (non-interactive)',\n isFlag: true,\n },\n {\n name: 'trust-dir',\n description: 'Trust files in this directory (non-interactive; absolute path)',\n },\n ],\n handler: async (hctx: CommandHandlerContext) => {\n await conciergeCommand(hctx);\n },\n });\n\n registry.registerCommand({\n path: ['dev', 'import-local'],\n description: 'Import remote workspace locally',\n requiresWorkspace: true,\n handler: async ({ ctx, workspace }) => {\n await devImportLocalCommand(requireAuth(ctx), workspace);\n },\n });\n\n registry.registerCommand({\n path: ['whoami'],\n description: 'Show current user info',\n handler: async ({ ctx }) => {\n await whoamiCommand(requireAuth(ctx));\n },\n });\n\n registry.registerCommand({\n path: ['organizations', 'list'],\n description: 'List organizations',\n handler: async ({ ctx }) => {\n await organizationsListCommand(requireAuth(ctx));\n },\n });\n\n registry.registerCommand({\n path: ['orgs', 'list'],\n description: 'List organizations',\n handler: async ({ ctx }) => {\n await organizationsListCommand(requireAuth(ctx));\n },\n });\n}\n"],"mappings":"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","names":["readFileSync","existsSync","join","resolve","resolve","stderr","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","execFile","readline","stderr","readline","path","fs","path","readline","resolve","readline","resolve","readline","resolve","execSync","EventEmitter","readline","resolve","output","resolve","input","existsSync","mkdirSync","writeFileSync","readFileSync","execSync","join","stderr","GravityRailClient","stderr","COLUMNS","accountVerifyPhoneCommand"]}
|