buildless-cli 0.1.10 → 0.1.11
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/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2232,7 +2232,7 @@ import path from "path";
|
|
|
2232
2232
|
import os from "os";
|
|
2233
2233
|
var defaultWebOrigin = process.env.BLO_WEB_ORIGIN || "https://buildless.online";
|
|
2234
2234
|
var defaultTerminalUrl = process.env.BLO_TERMINAL_URL || "https://buildless.online";
|
|
2235
|
-
var defaultProjectId = process.env.BLO_FIREBASE_PROJECT_ID ||
|
|
2235
|
+
var defaultProjectId = process.env.BLO_FIREBASE_PROJECT_ID || "buildless-online";
|
|
2236
2236
|
var resolveConfigPath = () => {
|
|
2237
2237
|
if (process.env.BLO_CONFIG_PATH) return process.env.BLO_CONFIG_PATH;
|
|
2238
2238
|
const home = os.homedir();
|
|
@@ -2255,8 +2255,14 @@ var loadConfig = () => {
|
|
|
2255
2255
|
return {
|
|
2256
2256
|
path: configPath,
|
|
2257
2257
|
config: {
|
|
2258
|
+
// Merge persisted values (tokens) with authoritative defaults.
|
|
2259
|
+
// Service URLs and project ID always come from defaults (env or
|
|
2260
|
+
// hardcoded prod) so a stale config file can't point the
|
|
2261
|
+
// published CLI at the wrong Firebase project.
|
|
2258
2262
|
...defaults,
|
|
2259
|
-
|
|
2263
|
+
idToken: parsed.idToken,
|
|
2264
|
+
tokenExp: parsed.tokenExp,
|
|
2265
|
+
appCheckToken: parsed.appCheckToken
|
|
2260
2266
|
}
|
|
2261
2267
|
};
|
|
2262
2268
|
} catch (err) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/app.tsx","../src/auth.ts","../src/log.ts","../src/firestore.ts","../src/ui/app-search.tsx","../src/ui/runner.tsx","../src/ai.ts","../src/ui/useRunnerSession.ts","../src/ui/useRunnerRenderSource.ts","../../shared/src/screen-runtime/parsing/fieldParser.ts","../../shared/src/screen-runtime/state/pathUtils.ts","../../shared/src/screen-runtime/actions/actionBuilder.ts","../../shared/src/screen-runtime/rendering/widgetHelpers.ts","../../shared/src/screen-runtime/rendering/screenRenderer.ts","../src/config.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { render } from \"ink\";\nimport { App } from \"./app.js\";\nimport { loadConfig, saveConfig, type CliConfig } from \"./config.js\";\nimport { isTokenValid, startExternalLogin, decodeJwtPayload } from \"./auth.js\";\nimport { log, setVerbose } from \"./log.js\";\n\nconst ensureProjectId = (config: CliConfig): void => {\n if (!config.firebaseProjectId) {\n throw new Error(\n \"Could not determine project. Please reinstall: npm install -g buildless-cli\"\n );\n }\n};\n\nconst runLogin = async (config: CliConfig, configPath: string): Promise<CliConfig> => {\n log(`Starting login flow via ${config.webOrigin}/cli-auth`);\n const result = await startExternalLogin({ webOrigin: config.webOrigin });\n const payload = decodeJwtPayload(result.token);\n const uid = payload?.user_id ?? payload?.sub ?? \"unknown\";\n log(`Login successful: uid=${uid}, exp=${result.exp}, appCheck=${result.appCheckToken ? \"yes\" : \"no\"}`);\n const next: CliConfig = {\n ...config,\n idToken: result.token,\n tokenExp: result.exp ?? undefined,\n appCheckToken: result.appCheckToken,\n };\n saveConfig(configPath, next);\n log(`Config saved to ${configPath}`);\n return next;\n};\n\nconst program = new Command();\nprogram\n .name(\"blo\")\n .description(\"BLO terminal client\")\n .version(\"0.1.0\")\n .option(\"-v, --verbose\", \"Enable verbose debug output\")\n .hook(\"preAction\", () => {\n if (program.opts().verbose) {\n setVerbose(true);\n }\n });\n\nprogram\n .command(\"login\")\n .description(\"Authenticate via external browser\")\n .action(async () => {\n const { config, path } = loadConfig();\n log(`Config loaded from ${path}`);\n ensureProjectId(config);\n const next = await runLogin(config, path);\n process.stdout.write(`Logged in for project ${next.firebaseProjectId}.\\n`);\n });\n\nconst runAction = async (options: { query?: string }) => {\n process.stdout.write(\"\\x1b[2J\\x1b[H\");\n const { config, path } = loadConfig();\n log(`Config loaded from ${path}`);\n log(`Project: ${config.firebaseProjectId}`);\n log(`Terminal URL: ${config.terminalUrl}`);\n log(`Web origin: ${config.webOrigin}`);\n ensureProjectId(config);\n\n let effective = config;\n if (!isTokenValid(config.idToken, config.tokenExp ?? null)) {\n log(\"Token expired or missing, starting login\");\n effective = await runLogin(config, path);\n } else {\n const payload = decodeJwtPayload(config.idToken || \"\");\n const uid = payload?.user_id ?? payload?.sub ?? \"unknown\";\n log(`Token valid: uid=${uid}, expires=${config.tokenExp ? new Date(config.tokenExp * 1000).toISOString() : \"unknown\"}`);\n }\n\n log(`Rendering app with query=${options.query || \"(none)\"}`);\n const { waitUntilExit } = render(\n <App\n config={effective}\n idToken={effective.idToken || \"\"}\n initialQuery={options.query}\n onExit={() => process.exit(0)}\n />\n );\n await waitUntilExit();\n};\n\nprogram\n .command(\"run\")\n .description(\"Search and run a published app\")\n .option(\"-q, --query <query>\", \"Initial search query\")\n .action(runAction);\n\nprogram\n .command(\"list\")\n .description(\"List published apps (interactive)\")\n .option(\"-q, --query <query>\", \"Initial search query\")\n .action(runAction);\n\nconst main = async () => {\n if (process.argv.length <= 2) {\n await program.parseAsync([process.argv[0], process.argv[1], \"run\"]);\n return;\n }\n await program.parseAsync(process.argv);\n};\n\nmain().catch((err) => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n","import React, { useEffect, useState } from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { CliConfig } from \"./config.js\";\nimport { fetchRunnableAppsViaServer, type RunnableApp } from \"./firestore.js\";\nimport { AppSearch } from \"./ui/app-search.js\";\nimport { Runner } from \"./ui/runner.js\";\nimport { log } from \"./log.js\";\n\nexport const App: React.FC<{\n config: CliConfig;\n idToken: string;\n initialQuery?: string;\n onExit: () => void;\n}> = ({ config, idToken, initialQuery, onExit }) => {\n const [apps, setApps] = useState<RunnableApp[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedApp, setSelectedApp] = useState<RunnableApp | null>(null);\n\n useEffect(() => {\n let mounted = true;\n const load = async () => {\n try {\n setLoading(true);\n log(`Loading apps from ${config.terminalUrl}`);\n const results = await fetchRunnableAppsViaServer({\n terminalUrl: config.terminalUrl,\n idToken,\n query: initialQuery,\n });\n if (!mounted) return;\n log(`Loaded ${results.length} apps`);\n setApps(results);\n setError(null);\n } catch (err) {\n if (!mounted) return;\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n if (mounted) setLoading(false);\n }\n };\n void load();\n return () => {\n mounted = false;\n };\n }, [config.firebaseProjectId, config.terminalUrl, idToken, initialQuery]);\n\n if (error) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\">{error}</Text>\n <Text dimColor>Tip: Set BLO_DEBUG=1 for detailed logs.</Text>\n <Text>Press Ctrl+C to exit.</Text>\n </Box>\n );\n }\n\n if (loading) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">Loading apps from {config.terminalUrl}...</Text>\n </Box>\n );\n }\n\n if (apps.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"yellow\">No apps found.</Text>\n <Text dimColor>\n {initialQuery\n ? `No apps matched \"${initialQuery}\". Try without a query filter.`\n : \"Your account has no projects and no published apps are available.\"}\n </Text>\n <Text>Press Ctrl+C to exit.</Text>\n </Box>\n );\n }\n\n if (!selectedApp) {\n return (\n <AppSearch\n apps={apps}\n initialQuery={initialQuery}\n onSelect={(app) => {\n log(`Selected app: ${app.projectId} (version=${app.versionId}, source=${app.versionSource})`);\n setSelectedApp(app);\n }}\n onExit={onExit}\n />\n );\n }\n\n return (\n <Runner\n projectId={selectedApp.projectId}\n versionId={selectedApp.versionId}\n terminalUrl={config.terminalUrl}\n idToken={idToken}\n firebaseProjectId={config.firebaseProjectId}\n appCheckToken={config.appCheckToken}\n onBackToApps={() => {\n log(\"Returning to app list\");\n setSelectedApp(null);\n }}\n onExit={onExit}\n />\n );\n};\n","import { createServer } from \"node:http\";\nimport crypto from \"node:crypto\";\nimport { URL } from \"node:url\";\nimport open from \"open\";\nimport { log } from \"./log.js\";\n\nexport type LoginResult = { token: string; exp: number | null; appCheckToken?: string };\n\ntype LoginOptions = {\n webOrigin: string;\n};\n\nexport const decodeJwtPayload = (token: string): Record<string, unknown> | null => {\n const parts = token.split(\".\");\n if (parts.length < 2) return null;\n try {\n const payload = Buffer.from(parts[1], \"base64url\").toString(\"utf8\");\n return JSON.parse(payload);\n } catch {\n return null;\n }\n};\n\nexport const getTokenExp = (token: string): number | null => {\n const payload = decodeJwtPayload(token);\n if (!payload || typeof payload.exp !== \"number\") return null;\n return payload.exp;\n};\n\nexport const isTokenValid = (token?: string, exp?: number | null): boolean => {\n if (!token) return false;\n if (exp == null) return true;\n const now = Math.floor(Date.now() / 1000);\n return exp - 30 > now;\n};\n\nconst LOGIN_TIMEOUT_MS = 120_000;\n\nexport const startExternalLogin = async (options: LoginOptions): Promise<LoginResult> => {\n const state = crypto.randomBytes(16).toString(\"hex\");\n\n const server = createServer();\n const result = await new Promise<LoginResult>((resolve, reject) => {\n let settled = false;\n const timeout = setTimeout(() => {\n if (settled) return;\n settled = true;\n server.close();\n reject(new Error(\"Login timed out after 2 minutes. Please try again.\"));\n }, LOGIN_TIMEOUT_MS);\n\n server.on(\"request\", (req, res) => {\n if (!req.url) return;\n const url = new URL(req.url, \"http://localhost\");\n if (url.pathname !== \"/callback\") {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not found\");\n return;\n }\n if (settled) {\n res.writeHead(409, { \"Content-Type\": \"text/plain\" });\n res.end(\"Login already handled. You can close this window.\");\n return;\n }\n const token = url.searchParams.get(\"token\") || \"\";\n const returnedState = url.searchParams.get(\"state\") || \"\";\n const appCheckToken = url.searchParams.get(\"appCheckToken\") || undefined;\n if (!token || returnedState !== state) {\n settled = true;\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\n res.end(\"Invalid login response. You can close this window.\");\n clearTimeout(timeout);\n log(`Login callback failed: token=${token ? \"present\" : \"missing\"}, state=${returnedState === state ? \"match\" : \"mismatch\"}`);\n reject(new Error(\"Login failed: invalid callback. Make sure you completed the login in your browser.\"));\n server.close();\n return;\n }\n\n settled = true;\n res.writeHead(200, { \"Content-Type\": \"text/plain\" });\n res.end(\"Login complete. You can close this window.\");\n clearTimeout(timeout);\n const exp = getTokenExp(token);\n log(`Login callback received: exp=${exp}, appCheck=${appCheckToken ? \"yes\" : \"no\"}`);\n resolve({ token, exp, appCheckToken });\n server.close();\n });\n\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n if (!address || typeof address === \"string\") {\n clearTimeout(timeout);\n reject(new Error(\"Failed to start local login server.\"));\n return;\n }\n const callbackUrl = `http://127.0.0.1:${address.port}/callback`;\n const loginUrl = new URL(\"/cli-auth\", options.webOrigin);\n loginUrl.searchParams.set(\"redirect_uri\", callbackUrl);\n loginUrl.searchParams.set(\"state\", state);\n log(`Login server listening on port ${address.port}`);\n log(`Opening browser: ${loginUrl.toString()}`);\n process.stderr.write(\"Opening browser for login...\\n\");\n void open(loginUrl.toString());\n });\n });\n\n return result;\n};\n","let verbose = process.env.BLO_DEBUG === \"1\" || process.env.BLO_DEBUG === \"true\";\n\nexport const setVerbose = (enabled: boolean): void => {\n verbose = enabled;\n};\n\nexport const log = (message: string): void => {\n if (verbose) {\n process.stderr.write(`[blo] ${message}\\n`);\n }\n};\n","import { decodeJwtPayload } from \"./auth.js\";\nimport { log } from \"./log.js\";\n\nexport type RunnableApp = {\n id: string;\n projectId: string;\n versionId: string;\n versionSource: \"published\" | \"latest\" | \"store\";\n publishedVersionId?: string;\n name?: string;\n displayName?: string;\n tagline?: string;\n description?: string;\n accessTier?: string;\n authorName?: string;\n ownerDisplayName?: string;\n appSource?: \"user\" | \"published\";\n};\n\nconst resolveUidFromToken = (idToken: string): string | null => {\n const payload = decodeJwtPayload(idToken);\n if (!payload) return null;\n const uid = payload.user_id ?? payload.sub;\n return typeof uid === \"string\" && uid.trim() ? uid.trim() : null;\n};\n\nconst fromFirestoreValue = (value: any): any => {\n if (value == null || typeof value !== \"object\") return null;\n if (\"stringValue\" in value) return String(value.stringValue);\n if (\"booleanValue\" in value) return Boolean(value.booleanValue);\n if (\"integerValue\" in value) return Number(value.integerValue);\n if (\"doubleValue\" in value) return Number(value.doubleValue);\n if (\"timestampValue\" in value) return String(value.timestampValue);\n if (\"referenceValue\" in value) return String(value.referenceValue);\n if (\"mapValue\" in value) {\n const fields = value.mapValue?.fields || {};\n const output: Record<string, any> = {};\n for (const [key, entry] of Object.entries(fields)) {\n output[key] = fromFirestoreValue(entry);\n }\n return output;\n }\n if (\"arrayValue\" in value) {\n const values = value.arrayValue?.values || [];\n return values.map(fromFirestoreValue);\n }\n if (\"nullValue\" in value) return null;\n return null;\n};\n\nexport const parseDocument = (doc: any): Record<string, any> => {\n const fields = doc?.fields || {};\n const output: Record<string, any> = {};\n for (const [key, entry] of Object.entries(fields)) {\n output[key] = fromFirestoreValue(entry);\n }\n return output;\n};\n\nexport const firestoreDocsBase = (projectId: string): string =>\n `https://firestore.googleapis.com/v1/projects/${encodeURIComponent(projectId)}/databases/(default)/documents`;\n\nexport const parseRunQueryDocs = (rows: Array<{ document?: any }>): any[] =>\n rows.map((row) => row.document).filter(Boolean);\n\nexport const extractDocIdFromName = (name?: string): string | undefined => {\n if (!name) return undefined;\n const chunks = String(name).split(\"/\");\n return chunks[chunks.length - 1] || undefined;\n};\n\nexport const authHeaders = (idToken: string, appCheckToken?: string): Record<string, string> => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${idToken}`,\n };\n if (appCheckToken) {\n headers[\"X-Firebase-AppCheck\"] = appCheckToken;\n }\n return headers;\n};\n\nconst fetchPublishedApps = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n}): Promise<RunnableApp[]> => {\n const { projectId, idToken, appCheckToken } = opts;\n const endpoint = `${firestoreDocsBase(projectId)}:runQuery`;\n const body = {\n structuredQuery: {\n from: [{ collectionId: \"publishedApps\" }],\n where: {\n fieldFilter: {\n field: { fieldPath: \"isPublished\" },\n op: \"EQUAL\",\n value: { booleanValue: true },\n },\n },\n limit: 250,\n },\n };\n\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...authHeaders(idToken, appCheckToken),\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const text = await response.text();\n log(`Failed to fetch published apps (${response.status}): ${text}`);\n throw new Error(`Failed to fetch published apps (${response.status})`);\n }\n\n const rows = (await response.json()) as Array<{ document?: any }>;\n const mapped: Array<RunnableApp | null> = parseRunQueryDocs(rows).map((doc) => {\n const data = parseDocument(doc);\n const projectIdFromDoc = String(data.projectId || \"\").trim();\n const publishedVersionId = String(data.publishedVersionId || \"\").trim();\n if (!projectIdFromDoc || !publishedVersionId) return null;\n return {\n id: projectIdFromDoc,\n projectId: projectIdFromDoc,\n versionId: publishedVersionId,\n versionSource: \"store\" as const,\n publishedVersionId,\n name: data.name ? String(data.name) : undefined,\n displayName: data.displayName ? String(data.displayName) : undefined,\n tagline: data.tagline ? String(data.tagline) : undefined,\n description: data.description ? String(data.description) : undefined,\n accessTier: data.accessTier ? String(data.accessTier) : undefined,\n authorName: data.authorName ? String(data.authorName) : undefined,\n ownerDisplayName: data.ownerDisplayName ? String(data.ownerDisplayName) : undefined,\n appSource: \"published\" as const,\n };\n });\n return mapped.filter((entry): entry is RunnableApp => entry !== null);\n};\n\nconst fetchUserProjectIds = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n uid: string;\n}): Promise<string[]> => {\n const { projectId, idToken, appCheckToken, uid } = opts;\n const endpoint = `${firestoreDocsBase(projectId)}/users/${encodeURIComponent(uid)}`;\n const response = await fetch(endpoint, {\n headers: authHeaders(idToken, appCheckToken),\n });\n\n if (response.status === 404) return [];\n if (!response.ok) {\n const text = await response.text();\n log(`Failed to fetch user profile (${response.status}): ${text}`);\n throw new Error(`Failed to fetch user profile (${response.status})`);\n }\n\n const doc = (await response.json()) as any;\n const data = parseDocument(doc);\n const projectAccess =\n data.projectAccess && typeof data.projectAccess === \"object\"\n ? (data.projectAccess as Record<string, unknown>)\n : {};\n return Object.keys(projectAccess);\n};\n\nconst fetchProjectDoc = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n targetProjectId: string;\n}): Promise<Record<string, any> | null> => {\n const { projectId, idToken, appCheckToken, targetProjectId } = opts;\n const endpoint = `${firestoreDocsBase(projectId)}/projects/${encodeURIComponent(targetProjectId)}`;\n const response = await fetch(endpoint, {\n headers: authHeaders(idToken, appCheckToken),\n });\n\n if (response.status === 404) return null;\n if (!response.ok) {\n const text = await response.text();\n log(`Failed to fetch project ${targetProjectId} (${response.status}): ${text}`);\n throw new Error(`Failed to fetch project ${targetProjectId} (${response.status})`);\n }\n\n const doc = (await response.json()) as any;\n return parseDocument(doc);\n};\n\nconst fetchLatestVersionId = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n targetProjectId: string;\n}): Promise<string | null> => {\n const { projectId, idToken, appCheckToken, targetProjectId } = opts;\n const endpoint = `${firestoreDocsBase(projectId)}/projects/${encodeURIComponent(\n targetProjectId\n )}:runQuery`;\n\n const tryQueries = [\n {\n structuredQuery: {\n from: [{ collectionId: \"versions\" }],\n orderBy: [{ field: { fieldPath: \"updatedAt\" }, direction: \"DESCENDING\" }],\n limit: 1,\n },\n },\n {\n structuredQuery: {\n from: [{ collectionId: \"versions\" }],\n orderBy: [{ field: { fieldPath: \"createdAt\" }, direction: \"DESCENDING\" }],\n limit: 1,\n },\n },\n {\n structuredQuery: {\n from: [{ collectionId: \"versions\" }],\n limit: 1,\n },\n },\n ];\n\n for (const body of tryQueries) {\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...authHeaders(idToken, appCheckToken),\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n continue;\n }\n\n const rows = (await response.json()) as Array<{ document?: any }>;\n const doc = parseRunQueryDocs(rows)[0];\n const docId = extractDocIdFromName(doc?.name);\n if (docId) return docId;\n }\n\n return null;\n};\n\nconst mapProjectToRunnableApp = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n targetProjectId: string;\n}): Promise<RunnableApp | null> => {\n const { projectId, idToken, appCheckToken, targetProjectId } = opts;\n const projectDoc = await fetchProjectDoc({ projectId, idToken, appCheckToken, targetProjectId });\n if (!projectDoc) return null;\n\n const publishedVersionId = String(projectDoc.publishedVersionId || \"\").trim();\n const latestVersionId =\n publishedVersionId ||\n (await fetchLatestVersionId({ projectId, idToken, appCheckToken, targetProjectId })) ||\n \"\";\n const versionId = String(latestVersionId || \"\").trim();\n\n if (!versionId) return null;\n\n const ownerData =\n projectDoc.ownerData && typeof projectDoc.ownerData === \"object\"\n ? (projectDoc.ownerData as Record<string, unknown>)\n : {};\n\n return {\n id: targetProjectId,\n projectId: targetProjectId,\n versionId,\n versionSource: publishedVersionId ? \"published\" : \"latest\",\n publishedVersionId: publishedVersionId || undefined,\n name: projectDoc.name ? String(projectDoc.name) : undefined,\n displayName: projectDoc.displayName ? String(projectDoc.displayName) : undefined,\n description: projectDoc.description ? String(projectDoc.description) : undefined,\n accessTier: projectDoc.accessTier ? String(projectDoc.accessTier) : undefined,\n authorName: projectDoc.authorName ? String(projectDoc.authorName) : undefined,\n ownerDisplayName:\n (typeof ownerData.displayName === \"string\" ? ownerData.displayName : undefined) ||\n (projectDoc.owner ? String(projectDoc.owner) : undefined),\n appSource: \"user\" as const,\n };\n};\n\nconst fetchUserApps = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n}): Promise<RunnableApp[]> => {\n const uid = resolveUidFromToken(opts.idToken);\n if (!uid) {\n throw new Error(\"Failed to decode uid from Firebase ID token.\");\n }\n\n const projectIds = await fetchUserProjectIds({\n projectId: opts.projectId,\n idToken: opts.idToken,\n appCheckToken: opts.appCheckToken,\n uid,\n });\n\n if (!projectIds.length) return [];\n\n const results = await Promise.allSettled(\n projectIds.map((targetProjectId) =>\n mapProjectToRunnableApp({\n projectId: opts.projectId,\n idToken: opts.idToken,\n appCheckToken: opts.appCheckToken,\n targetProjectId,\n })\n )\n );\n\n const apps: RunnableApp[] = [];\n for (const result of results) {\n if (result.status === \"fulfilled\" && result.value) {\n apps.push(result.value);\n } else if (result.status === \"rejected\") {\n process.stderr.write(`Warning: failed to load a project: ${result.reason}\\n`);\n }\n }\n return apps;\n};\n\nexport const fetchRunnableAppsViaServer = async (opts: {\n terminalUrl: string;\n idToken: string;\n query?: string;\n}): Promise<RunnableApp[]> => {\n const { terminalUrl, idToken, query } = opts;\n const url = new URL(\"/api/apps\", terminalUrl);\n if (query) url.searchParams.set(\"q\", query);\n\n log(`Fetching apps: GET ${url.toString()}`);\n const response = await fetch(url.toString(), {\n headers: { Authorization: `Bearer ${idToken}` },\n });\n\n if (!response.ok) {\n let message: string | undefined;\n try {\n const body = await response.json() as { message?: string };\n message = body.message;\n } catch {\n // ignore parse errors\n }\n log(`Fetch apps failed: ${response.status} ${message || \"(no message)\"}`);\n if (response.status === 401) {\n throw new Error(\"Authentication failed. Try 'blo login' to re-authenticate.\");\n }\n if (response.status === 403 && message?.toLowerCase().includes(\"cli access\")) {\n const uid = resolveUidFromToken(idToken) || \"unknown\";\n throw new Error(`CLI access is not enabled for your account (uid: ${uid}). Contact an admin to enable it.`);\n }\n if (response.status >= 500) {\n throw new Error(`Server error (${response.status}). The terminal server may be having issues.`);\n }\n throw new Error(message || `Failed to fetch apps (${response.status})`);\n }\n\n const body = (await response.json()) as { ok?: boolean; apps?: RunnableApp[] };\n const apps = body.apps || [];\n log(`Fetched ${apps.length} apps`);\n return apps;\n};\n\nexport const fetchRunnableApps = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n query?: string;\n}): Promise<RunnableApp[]> => {\n const { projectId, idToken, appCheckToken, query } = opts;\n\n const userApps = await fetchUserApps({ projectId, idToken, appCheckToken });\n let publishedApps: RunnableApp[] = [];\n try {\n publishedApps = await fetchPublishedApps({ projectId, idToken, appCheckToken });\n } catch (err) {\n process.stderr.write(`Warning: failed to fetch published apps: ${err}\\n`);\n }\n\n const byProjectId = new Map<string, RunnableApp>();\n userApps.forEach((app) => {\n byProjectId.set(app.projectId, app);\n });\n publishedApps.forEach((app) => {\n if (!byProjectId.has(app.projectId)) {\n byProjectId.set(app.projectId, app);\n }\n });\n\n const allApps = Array.from(byProjectId.values()).sort((a, b) => {\n const aName = String(a.name || a.projectId).toLowerCase();\n const bName = String(b.name || b.projectId).toLowerCase();\n return aName.localeCompare(bName);\n });\n\n const term = (query || \"\").trim().toLowerCase();\n if (!term) return allApps;\n\n return allApps.filter((app) => filterApp(app, term));\n};\n\nexport const filterApp = (app: RunnableApp, term: string): boolean =>\n [\n app.projectId,\n app.displayName,\n app.name,\n app.tagline,\n app.description,\n app.authorName,\n app.ownerDisplayName,\n app.versionId,\n app.accessTier,\n ]\n .filter(Boolean)\n .some((field) => String(field).toLowerCase().includes(term));\n","import React, { useMemo, useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport { filterApp, type RunnableApp } from \"../firestore.js\";\n\ntype AppFilter = \"all\" | \"user\" | \"published\";\n\ntype Props = {\n apps: RunnableApp[];\n initialQuery?: string;\n onSelect: (app: RunnableApp) => void;\n onExit: () => void;\n};\n\nexport const AppSearch: React.FC<Props> = ({ apps, initialQuery, onSelect, onExit }) => {\n const [query, setQuery] = useState(initialQuery || \"\");\n const [selected, setSelected] = useState(0);\n const [appFilter, setAppFilter] = useState<AppFilter>(\"all\");\n\n const filtered = useMemo(() => {\n let result = apps;\n\n // Filter by app source - apps without appSource are treated as \"user\" apps (local projects)\n if (appFilter === \"user\") {\n result = result.filter((app) => !app.appSource || app.appSource === \"user\");\n } else if (appFilter === \"published\") {\n result = result.filter((app) => app.appSource === \"published\");\n }\n // \"all\" shows everything\n\n // Filter by search term\n const term = query.trim().toLowerCase();\n if (!term) return result;\n return result.filter((app) => filterApp(app, term));\n }, [apps, query, appFilter]);\n\n useInput((input, key) => {\n if (key.ctrl && input === \"c\") {\n onExit();\n return;\n }\n if (key.escape) {\n setQuery(\"\");\n setSelected(0);\n return;\n }\n if (input === \"m\" || input === \"M\") {\n setAppFilter(\"user\");\n setSelected(0);\n return;\n }\n if (input === \"p\" || input === \"P\") {\n setAppFilter(\"published\");\n setSelected(0);\n return;\n }\n if (input === \"a\" || input === \"A\") {\n setAppFilter(\"all\");\n setSelected(0);\n return;\n }\n if (key.upArrow) {\n setSelected((prev) => (filtered.length ? (prev - 1 + filtered.length) % filtered.length : 0));\n return;\n }\n if (key.downArrow) {\n setSelected((prev) => (filtered.length ? (prev + 1) % filtered.length : 0));\n return;\n }\n if (key.return) {\n const app = filtered[selected];\n if (app) onSelect(app);\n return;\n }\n if (key.backspace || key.delete) {\n setQuery((prev) => prev.slice(0, -1));\n setSelected(0);\n return;\n }\n if (input) {\n setQuery((prev) => prev + input);\n setSelected(0);\n }\n });\n\n const maxVisible = Math.max(3, Math.min(20, (process.stdout.rows || 24) - 6));\n const scrollOffset = Math.max(0, Math.min(selected - maxVisible + 1, filtered.length - maxVisible));\n const visible = filtered.slice(scrollOffset, scrollOffset + maxVisible);\n\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">BLO CLI Runner Apps</Text>\n <Text>Search apps: {query || \"(type to filter)\"}</Text>\n <Text>\n Filter:{\" \"}\n <Text color={appFilter === \"all\" ? \"green\" : \"gray\"}>A</Text>\n <Text color=\"gray\">ll | </Text>\n <Text color={appFilter === \"user\" ? \"green\" : \"gray\"}>M</Text>\n <Text color=\"gray\">y | </Text>\n <Text color={appFilter === \"published\" ? \"green\" : \"gray\"}>P</Text>\n <Text color=\"gray\">ublished</Text>\n </Text>\n <Text color=\"gray\">Enter = launch, Esc = clear, Ctrl+C = exit</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {visible.length === 0 ? (\n <Text>No runnable apps found.</Text>\n ) : (\n visible.map((app, index) => {\n const globalIndex = scrollOffset + index;\n const isSelected = globalIndex === selected;\n const label = app.displayName || app.name || app.projectId;\n const author = app.authorName || app.ownerDisplayName || \"Unknown\";\n const versionHint = `${app.versionSource}:${app.versionId}`;\n return (\n <Text key={app.id} color={isSelected ? \"green\" : undefined}>\n {isSelected ? \">\" : \" \"} {label} — {author} ({versionHint})\n </Text>\n );\n })\n )}\n {filtered.length > maxVisible && (\n <Text color=\"gray\">{scrollOffset + visible.length} of {filtered.length} apps</Text>\n )}\n </Box>\n </Box>\n );\n};\n","import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { AiMessage } from \"@blo/shared\";\nimport type { TerminalActionLine, TerminalShortcut } from \"@blo/shared/terminal\";\nimport { callUnifiedChat, loadLatestConversation, createConversation, appendMessage } from \"../ai.js\";\nimport { useRunnerSession } from \"./useRunnerSession.js\";\nimport { useRunnerRenderSource } from \"./useRunnerRenderSource.js\";\n\ntype Props = {\n projectId: string;\n versionId?: string;\n terminalUrl: string;\n idToken: string;\n firebaseProjectId: string;\n appCheckToken?: string;\n onBackToApps: () => void;\n onExit: () => void;\n};\n\ntype FieldValueMap = Record<string, string>;\n\nexport const Runner: React.FC<Props> = ({\n projectId,\n versionId,\n terminalUrl,\n idToken,\n firebaseProjectId,\n appCheckToken,\n onBackToApps,\n onExit,\n}) => {\n const { screen: rawScreen, error, connecting, sessionId, sendMessage } = useRunnerSession({\n projectId,\n versionId,\n terminalUrl,\n idToken,\n });\n\n const [listScrollOffsets, setListScrollOffsets] = useState<Record<string, number>>({});\n const { screen, listScrollInfo, lineWidgetIds } = useRunnerRenderSource(rawScreen, listScrollOffsets);\n\n const [inputMode, setInputMode] = useState(false);\n const [activeInputIndex, setActiveInputIndex] = useState(0);\n const [fieldValues, setFieldValues] = useState<FieldValueMap>({});\n\n // AI chat mode state\n const [aiMode, setAiMode] = useState(false);\n const [aiMessages, setAiMessages] = useState<AiMessage[]>([]);\n const [aiInput, setAiInput] = useState(\"\");\n const [aiLoading, setAiLoading] = useState(false);\n const aiRequestRef = useRef(0);\n const [aiConversationId, setAiConversationId] = useState<string | null>(null);\n const aiMessageSeqRef = useRef(0);\n const [aiHistoryLoading, setAiHistoryLoading] = useState(false);\n\n // Load existing conversation on mount\n useEffect(() => {\n let cancelled = false;\n const vid = versionId || \"published\";\n setAiHistoryLoading(true);\n loadLatestConversation({ firebaseProjectId, idToken, appCheckToken, projectId, versionId: vid })\n .then((result) => {\n if (cancelled) return;\n if (result) {\n setAiConversationId(result.conversationId);\n setAiMessages(result.messages);\n aiMessageSeqRef.current = result.messageCount;\n }\n })\n .catch(() => {})\n .finally(() => { if (!cancelled) setAiHistoryLoading(false); });\n return () => { cancelled = true; };\n }, [firebaseProjectId, idToken, appCheckToken, projectId, versionId]);\n\n const sendAiMessage = async (text: string) => {\n if (!text.trim() || aiLoading) return;\n const userMsg: AiMessage = { role: \"user\", text: text.trim() };\n const updatedMessages = [...aiMessages, userMsg];\n setAiMessages(updatedMessages);\n setAiInput(\"\");\n setAiLoading(true);\n const requestId = ++aiRequestRef.current;\n const vid = versionId || \"published\";\n const persistOpts = { firebaseProjectId, idToken, appCheckToken, projectId, versionId: vid };\n try {\n // Ensure we have a conversation\n let convoId = aiConversationId;\n if (!convoId) {\n convoId = await createConversation(persistOpts);\n setAiConversationId(convoId);\n }\n // Persist user message\n const userSeq = ++aiMessageSeqRef.current;\n appendMessage({ ...persistOpts, conversationId: convoId, role: \"user\", text: text.trim(), seq: userSeq }).catch(() => {});\n\n const response = await callUnifiedChat({\n firebaseProjectId,\n idToken,\n appCheckToken,\n payload: {\n projectId,\n versionId: vid,\n message: text.trim(),\n screenId: rawScreen?.screen,\n conversation: updatedMessages,\n },\n });\n if (requestId !== aiRequestRef.current) return;\n const newMessages: AiMessage[] = [];\n if (response.operations?.length) {\n for (const op of response.operations) {\n const isError = op.result && typeof op.result === \"object\" && \"error\" in (op.result as Record<string, unknown>);\n const summary = isError\n ? `${op.tool}: error - ${(op.result as Record<string, unknown>).error}`\n : `${op.tool}: OK`;\n const toolMsg: AiMessage = { role: \"tool\", text: summary, toolName: op.tool };\n newMessages.push(toolMsg);\n const toolSeq = ++aiMessageSeqRef.current;\n appendMessage({ ...persistOpts, conversationId: convoId!, role: \"tool\", text: summary, toolName: op.tool, seq: toolSeq }).catch(() => {});\n }\n }\n const assistantMsg: AiMessage = { role: \"assistant\", text: response.text };\n newMessages.push(assistantMsg);\n const assistantSeq = ++aiMessageSeqRef.current;\n appendMessage({ ...persistOpts, conversationId: convoId!, role: \"assistant\", text: response.text, seq: assistantSeq }).catch(() => {});\n\n setAiMessages((prev) => [...prev, ...newMessages]);\n } catch (err) {\n if (requestId !== aiRequestRef.current) return;\n const errMsg = err instanceof Error ? err.message : String(err);\n setAiMessages((prev) => [...prev, { role: \"assistant\", text: `Error: ${errMsg}` }]);\n } finally {\n if (requestId === aiRequestRef.current) setAiLoading(false);\n }\n };\n\n const inputFields = useMemo(() => {\n if (!screen) return [];\n if (screen.inputFields && screen.inputFields.length > 0) return screen.inputFields;\n if (screen.inputField) return [screen.inputField];\n return [];\n }, [screen]);\n\n const selectableLines = useMemo(() => {\n return (screen?.actionLines || [])\n .filter((line) => line.selectable && (line.target || line.aidAlias || line.action))\n .sort((a, b) => a.index - b.index);\n }, [screen?.actionLines]);\n\n const shortcutByKey = useMemo(() => {\n const map = new Map<string, TerminalShortcut>();\n for (const s of screen?.shortcuts || []) {\n const k = String(s.key || \"\").trim().toLowerCase();\n if (k) map.set(k, s);\n }\n return map;\n }, [screen?.shortcuts]);\n\n const [selectedLineIndex, setSelectedLineIndex] = useState(0);\n\n useEffect(() => {\n setSelectedLineIndex(0);\n setListScrollOffsets({});\n }, [screen?.sessionId]);\n\n useEffect(() => {\n if (selectableLines.length > 0) {\n setSelectedLineIndex((prev) => Math.min(prev, selectableLines.length - 1));\n }\n }, [selectableLines.length]);\n\n useEffect(() => {\n if (!inputFields.length) {\n setInputMode(false);\n setActiveInputIndex(0);\n return;\n }\n setActiveInputIndex((prev) => Math.min(prev, inputFields.length - 1));\n }, [inputFields.length]);\n\n useEffect(() => {\n if (!inputFields.length) return;\n setFieldValues((prev) => {\n const next = { ...prev };\n for (const field of inputFields) {\n const isNonEditable = (field.maxLength ?? 0) === 0;\n if (isNonEditable || next[field.id] === undefined) {\n next[field.id] = String(field.value || \"\");\n }\n }\n return next;\n });\n }, [inputFields]);\n\n const collectFields = (extra?: Record<string, string>) => {\n return { ...fieldValues, ...extra };\n };\n\n const applySelectedLine = (line: TerminalActionLine) => {\n const fields = collectFields(line.fields);\n if (line.target) {\n sendMessage({ type: \"nav\", target: line.target, fields });\n return;\n }\n if (line.aidAlias) {\n sendMessage({ type: \"aid\", key: line.aidAlias, fields });\n return;\n }\n if (line.action) {\n sendMessage({ type: \"action\", action: line.action, fields });\n }\n };\n\n const executeShortcut = (shortcut: TerminalShortcut) => {\n const fields = collectFields(shortcut.fields);\n if (shortcut.target) {\n sendMessage({ type: \"nav\", target: shortcut.target, fields });\n return;\n }\n if (shortcut.action) {\n sendMessage({ type: \"action\", action: shortcut.action, fields });\n return;\n }\n if (shortcut.aidAlias) {\n sendMessage({ type: \"aid\", key: shortcut.aidAlias, fields });\n }\n };\n\n const toggleActiveCheckbox = () => {\n const activeField = inputFields[activeInputIndex];\n if (!activeField) return;\n const toggleAction = activeField.action ?? { type: \"data.toggleFlag\" as const, path: activeField.id };\n sendMessage({ type: \"action\", action: toggleAction, fields: collectFields() });\n };\n\n const activeField = inputFields[activeInputIndex] ?? null;\n const isEditable = activeField != null && (activeField.maxLength ?? 0) > 0;\n const isMultiLine = isEditable && (activeField.rows ?? 1) > 1;\n\n useInput((input, key) => {\n if (key.ctrl && input === \"c\") {\n onExit();\n return;\n }\n\n if (!screen) return;\n\n // -- AI chat mode --\n if (aiMode) {\n if (key.escape) {\n setAiMode(false);\n return;\n }\n if (key.backspace || key.delete) {\n setAiInput((prev) => prev.slice(0, -1));\n return;\n }\n if (key.return && !aiLoading) {\n void sendAiMessage(aiInput);\n return;\n }\n if (input && !key.ctrl && !key.meta) {\n setAiInput((prev) => prev + input);\n }\n return;\n }\n\n // -- Input mode (typing into a text field) --\n if (inputMode) {\n if (!activeField) return;\n\n if (key.escape) {\n sendMessage({ type: \"aid\", key: \"B\", fields: fieldValues });\n setInputMode(false);\n return;\n }\n\n // Non-editable field (checkbox/select/radio/number/date): arrow keys cycle fields, Enter/Space toggle\n if (!isEditable) {\n if (key.tab || input === \"\\t\" || key.downArrow || key.rightArrow) {\n setActiveInputIndex((prev) => (prev + 1) % inputFields.length);\n return;\n }\n if (key.upArrow || key.leftArrow) {\n setActiveInputIndex((prev) =>\n inputFields.length ? (prev - 1 + inputFields.length) % inputFields.length : 0\n );\n return;\n }\n if (key.return || input === \" \") {\n toggleActiveCheckbox();\n return;\n }\n // Pass through to shortcut handling below\n if (input) {\n const shortcut = shortcutByKey.get(input.toLowerCase());\n if (shortcut) {\n executeShortcut(shortcut);\n return;\n }\n }\n return;\n }\n\n // Editable text field\n if (key.tab || input === \"\\t\") {\n // Tab submits the field values and exits input mode\n sendMessage({ type: \"aid\", key: \"ENTER\", fields: fieldValues });\n setInputMode(false);\n return;\n }\n\n if (key.backspace || key.delete) {\n setFieldValues((prev) => ({\n ...prev,\n [activeField.id]: (prev[activeField.id] || \"\").slice(0, -1),\n }));\n return;\n }\n\n if (key.return) {\n if (isMultiLine) {\n // Enter in multi-line: add newline\n setFieldValues((prev) => {\n const current = prev[activeField.id] || \"\";\n if (current.length >= activeField.maxLength) return prev;\n return { ...prev, [activeField.id]: current + \"\\n\" };\n });\n return;\n }\n // Single-line Enter: submit\n sendMessage({ type: \"aid\", key: \"ENTER\", fields: fieldValues });\n setInputMode(false);\n return;\n }\n\n if (input) {\n setFieldValues((prev) => {\n const current = prev[activeField.id] || \"\";\n if (current.length >= activeField.maxLength) return prev;\n return { ...prev, [activeField.id]: current + input };\n });\n }\n return;\n }\n\n // -- Normal mode (not typing) --\n\n if (input === \"x\" || input === \"q\") {\n onBackToApps();\n return;\n }\n\n if (key.escape) {\n sendMessage({ type: \"aid\", key: \"B\", fields: fieldValues });\n return;\n }\n\n // Ctrl+Enter: ENTER_BACK\n if (key.return && (key.ctrl || key.meta)) {\n sendMessage({ type: \"aid\", key: \"ENTER_BACK\", fields: fieldValues });\n return;\n }\n\n // Space: toggle checkbox when focused on non-editable field\n if (input === \" \" && activeField && !isEditable) {\n toggleActiveCheckbox();\n return;\n }\n\n if (key.return) {\n // Non-editable field focused: toggle checkbox\n if (activeField && !isEditable) {\n toggleActiveCheckbox();\n return;\n }\n // Editable field focused: enter input mode\n if (inputFields.length > 0 && isEditable) {\n setInputMode(true);\n return;\n }\n // Selectable action line: execute it\n const line = selectableLines[selectedLineIndex];\n if (line) {\n applySelectedLine(line);\n return;\n }\n // Default: send ENTER\n sendMessage({ type: \"aid\", key: \"ENTER\", fields: fieldValues });\n return;\n }\n\n // PageUp/PageDown: scroll list by a full page\n if (key.pageUp || key.pageDown) {\n const delta = key.pageDown ? 1 : -1;\n const currentLine = selectableLines[selectedLineIndex];\n const wId = currentLine ? lineWidgetIds?.[currentLine.index] : undefined;\n if (wId && listScrollInfo?.[wId]) {\n const info = listScrollInfo[wId];\n const scrollAmount = delta * info.visibleRows;\n const newOffset = Math.max(0, Math.min(info.offset + scrollAmount, info.totalRows - info.visibleRows));\n if (newOffset !== info.offset) {\n setListScrollOffsets((prev) => ({ ...prev, [wId]: newOffset }));\n }\n }\n return;\n }\n\n // Arrow keys: map to date picker shortcuts (h/l/j/k) when available,\n // otherwise cycle input fields or selectable lines\n if (key.upArrow || key.downArrow || key.leftArrow || key.rightArrow) {\n const arrowMap: Record<string, string> = {\n // ink key names aren't available as event.key, so we check the boolean flags\n };\n let mapped: string | undefined;\n if (key.leftArrow) mapped = \"h\";\n else if (key.rightArrow) mapped = \"l\";\n else if (key.upArrow) mapped = \"k\";\n else if (key.downArrow) mapped = \"j\";\n\n if (mapped) {\n const shortcut = shortcutByKey.get(mapped);\n if (shortcut) {\n executeShortcut(shortcut);\n return;\n }\n }\n\n // Up/Down: cycle input fields if present, otherwise selectable lines\n if (key.upArrow || key.downArrow) {\n const delta = key.downArrow ? 1 : -1;\n if (inputFields.length > 0) {\n setActiveInputIndex((prev) =>\n (prev + delta + inputFields.length) % inputFields.length\n );\n } else if (selectableLines.length > 0) {\n const nextIdx = selectedLineIndex + delta;\n // Check if at boundary and can scroll a list widget\n if (nextIdx < 0 || nextIdx >= selectableLines.length) {\n const currentLine = selectableLines[selectedLineIndex];\n const wId = currentLine ? lineWidgetIds?.[currentLine.index] : undefined;\n if (wId && listScrollInfo?.[wId]) {\n const info = listScrollInfo[wId];\n if (delta > 0 && info.offset + info.visibleRows < info.totalRows) {\n setListScrollOffsets((prev) => ({ ...prev, [wId]: info.offset + 1 }));\n return;\n }\n if (delta < 0 && info.offset > 0) {\n setListScrollOffsets((prev) => ({ ...prev, [wId]: info.offset - 1 }));\n return;\n }\n }\n }\n setSelectedLineIndex((prev) =>\n (prev + delta + selectableLines.length) % selectableLines.length\n );\n }\n }\n return;\n }\n\n if ((key.tab || input === \"\\t\" || input === \"i\") && inputFields.length > 0) {\n setInputMode(true);\n return;\n }\n\n // Shortcut keys (checked before hardcoded aids so screen-defined hotkeys take priority)\n if (input) {\n const shortcut = shortcutByKey.get(input.toLowerCase());\n if (shortcut) {\n executeShortcut(shortcut);\n return;\n }\n }\n\n if (input === \"/\" && !shortcutByKey.has(\"/\")) {\n setAiMode(true);\n return;\n }\n\n if (input === \"b\") {\n sendMessage({ type: \"aid\", key: \"B\", fields: fieldValues });\n return;\n }\n\n if (input === \"c\") {\n sendMessage({ type: \"aid\", key: \"C\", fields: fieldValues });\n return;\n }\n });\n\n // Build a map of lineIndex -> fieldId for all input fields (including multi-line spans)\n // NOTE: all useMemo/useEffect hooks must be before early returns\n const fieldLineMap = useMemo(() => {\n const map = new Map<number, { fieldId: string; rowOffset: number; label: string; rows: number }>();\n for (const field of inputFields) {\n if (typeof field.lineIndex !== \"number\") continue;\n const rows = Math.max(1, Number(field.rows ?? 1));\n const lineStep = Math.max(1, Number((field as { lineStep?: number }).lineStep ?? 1));\n for (let r = 0; r < rows; r++) {\n map.set(field.lineIndex + r * lineStep, {\n fieldId: field.id,\n rowOffset: r,\n label: field.label || field.id,\n rows,\n });\n }\n }\n return map;\n }, [inputFields]);\n\n // Build display lines with inline editing\n const displayLines = useMemo(() => {\n if (!screen) return [];\n const lines = [...(screen.lines || [])];\n if (!inputMode || !activeField || !isEditable) return lines;\n const fieldId = activeField.id;\n const editValue = fieldValues[fieldId] || \"\";\n const label = activeField.label || activeField.id;\n const labelPrefix = label ? `${label}: ` : \"\";\n const indent = \" \".repeat(labelPrefix.length);\n const rows = Math.max(1, Number(activeField.rows ?? 1));\n const lineStep = Math.max(1, Number((activeField as { lineStep?: number }).lineStep ?? 1));\n\n if (typeof activeField.lineIndex !== \"number\") return lines;\n\n // Split the edited value into display rows\n const editLines = editValue.split(/\\r?\\n/);\n const paddedEditLines = editLines.slice(0, rows);\n while (paddedEditLines.length < rows) paddedEditLines.push(\"\");\n\n for (let r = 0; r < rows; r++) {\n const lineIdx = activeField.lineIndex + r * lineStep;\n if (lineIdx >= 0 && lineIdx < lines.length) {\n const prefix = r === 0 ? labelPrefix : indent;\n const text = paddedEditLines[r] || \"\";\n // Show cursor on the last row with content, or last visible row if overflowing\n const cursor = (r === editLines.length - 1 || (r === rows - 1 && editLines.length >= rows)) ? \"\\u2588\" : \"\";\n lines[lineIdx] = `${prefix}${text}${cursor}`;\n }\n }\n return lines;\n }, [screen, inputMode, activeField, isEditable, fieldValues, inputFields]);\n\n // Hints for status bar\n const hintText = useMemo(() => {\n if (aiMode) return \"Type message, Enter=send, Esc=back to app\";\n if (!activeField) return \"Enter=select, /=AI, b=back, Tab/i=edit, arrows=nav, x=apps\";\n if (inputMode && isEditable) {\n return isMultiLine\n ? \"Type to edit, Enter=newline, Tab=submit, Esc=cancel\"\n : \"Type to edit, Enter=submit, Tab=submit, Esc=cancel\";\n }\n if (isEditable) return \"Enter=edit, Tab=next field, arrows=nav, b=back, x=apps\";\n return \"Enter/Space=toggle, arrows=nav, b=back, x=apps\";\n }, [activeField, aiMode, inputMode, isEditable, isMultiLine]);\n\n if (error) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\">Runner error: {error}</Text>\n <Text>Press x to return to apps, or Ctrl+C to exit.</Text>\n </Box>\n );\n }\n\n if (connecting || !screen) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">Starting runner...</Text>\n </Box>\n );\n }\n\n const selectedLine = selectableLines[selectedLineIndex];\n\n if (aiMode) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">\n AI CHAT | project={projectId} | screen={rawScreen?.screen || \"-\"}\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {aiHistoryLoading && (\n <Text color=\"gray\">Loading conversation...</Text>\n )}\n {aiMessages.length === 0 && !aiLoading && !aiHistoryLoading && (\n <Text color=\"gray\">Ask anything about this app or screen.</Text>\n )}\n {aiMessages.map((msg, idx) => {\n const prefix =\n msg.role === \"user\" ? \"You: \" : msg.role === \"tool\" ? `TOOL(${msg.toolName || \"?\"}): ` : \"AI: \";\n const color = msg.role === \"user\" ? \"cyan\" : msg.role === \"tool\" ? \"yellow\" : \"white\";\n return (\n <Box key={idx} flexDirection=\"column\">\n <Text color={color} wrap=\"wrap\">\n {prefix}{msg.text}\n </Text>\n </Box>\n );\n })}\n {aiLoading && <Text color=\"yellow\">Thinking...</Text>}\n </Box>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"green\">> {aiInput}<Text color=\"green\">{\"\\u2588\"}</Text></Text>\n <Text color=\"gray\">{hintText}</Text>\n </Box>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">\n RUNNER | project={projectId} | version={versionId || \"published\"} | session={\n sessionId || \"-\"\n }\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {displayLines.map((line, idx) => {\n const match = selectableLines.findIndex((entry) => entry.index === idx);\n const isSelectedActionLine = match >= 0 && selectableLines[match] === selectedLine;\n const fieldInfo = fieldLineMap.get(idx);\n const isActiveInputLine = fieldInfo != null && fieldInfo.fieldId === activeField?.id;\n const isAnyInputLine = fieldInfo != null;\n const lineColor = isSelectedActionLine\n ? \"green\"\n : isActiveInputLine\n ? inputMode\n ? \"yellow\"\n : \"cyan\"\n : isAnyInputLine\n ? \"cyan\"\n : undefined;\n const lineBackground = isActiveInputLine && inputMode ? \"blackBright\" : undefined;\n // Add spacing before standalone action buttons (like web's isButton marginTop)\n const actionLine = match >= 0 ? selectableLines[match] : undefined;\n const isButton = actionLine && !actionLine.fields;\n const prevWidgetId = idx > 0 ? lineWidgetIds?.[idx - 1] : undefined;\n const curWidgetId = lineWidgetIds?.[idx];\n const needsTopSpace = isButton && prevWidgetId && prevWidgetId !== curWidgetId;\n return (\n <Box key={`${idx}-${line}`} flexDirection=\"column\" marginTop={needsTopSpace ? 1 : 0}>\n <Text\n color={lineColor}\n backgroundColor={lineBackground}\n bold={isActiveInputLine}\n >\n {line}\n </Text>\n </Box>\n );\n })}\n </Box>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"gray\">{screen.statusLine}</Text>\n <Text color=\"gray\">{hintText}</Text>\n </Box>\n </Box>\n );\n};\n","import type { AiMessage, UnifiedChatPayload, UnifiedChatResponse } from \"@blo/shared\";\nimport {\n firestoreDocsBase,\n authHeaders,\n parseRunQueryDocs,\n parseDocument,\n extractDocIdFromName,\n} from \"./firestore.js\";\n\nexport async function callUnifiedChat(opts: {\n firebaseProjectId: string;\n idToken: string;\n appCheckToken?: string;\n payload: UnifiedChatPayload;\n}): Promise<UnifiedChatResponse> {\n const url = `https://us-central1-${opts.firebaseProjectId}.cloudfunctions.net/aiApi`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${opts.idToken}`,\n };\n if (opts.appCheckToken) {\n headers[\"X-Firebase-AppCheck\"] = opts.appCheckToken;\n }\n\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ data: { action: \"unifiedChat\", payload: opts.payload } }),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`AI request failed (${res.status}): ${text}`);\n }\n\n const json = (await res.json()) as { result?: { data?: UnifiedChatResponse } };\n const data = json.result?.data;\n if (!data) throw new Error(\"Unexpected AI response format\");\n return data;\n}\n\n// ── Conversation persistence (Firestore REST) ────────────────────────\n\ntype ConversationOpts = {\n firebaseProjectId: string;\n idToken: string;\n appCheckToken?: string;\n projectId: string;\n versionId: string;\n};\n\nexport async function loadLatestConversation(\n opts: ConversationOpts\n): Promise<{ conversationId: string; messages: AiMessage[]; messageCount: number } | null> {\n const base = firestoreDocsBase(opts.firebaseProjectId);\n const parent = `projects/${opts.projectId}/versions/${opts.versionId}`;\n\n // Fetch up to 50 conversations\n const convoRes = await fetch(`${base}/${parent}:runQuery`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({\n structuredQuery: {\n from: [{ collectionId: \"ai_conversations\" }],\n limit: 50,\n },\n }),\n });\n if (!convoRes.ok) return null;\n\n const convoRows = parseRunQueryDocs((await convoRes.json()) as Array<{ document?: any }>);\n if (!convoRows.length) return null;\n\n // Pick latest by max(updatedAt, createdAt)\n let bestDoc = convoRows[0];\n let bestTime = 0;\n for (const doc of convoRows) {\n const data = parseDocument(doc);\n const t = Math.max(toMs(data.updatedAt), toMs(data.createdAt));\n if (t > bestTime || bestTime === 0) {\n bestTime = t;\n bestDoc = doc;\n }\n }\n const conversationId = extractDocIdFromName(bestDoc?.name);\n if (!conversationId) return null;\n\n // Fetch messages ordered by seq asc\n const msgRes = await fetch(\n `${base}/${parent}/ai_conversations/${encodeURIComponent(conversationId)}:runQuery`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({\n structuredQuery: {\n from: [{ collectionId: \"messages\" }],\n orderBy: [{ field: { fieldPath: \"seq\" }, direction: \"ASCENDING\" }],\n limit: 200,\n },\n }),\n }\n );\n if (!msgRes.ok) return { conversationId, messages: [], messageCount: 0 };\n\n const msgDocs = parseRunQueryDocs((await msgRes.json()) as Array<{ document?: any }>);\n const messages: AiMessage[] = msgDocs.map((doc) => {\n const d = parseDocument(doc);\n return { role: d.role, text: d.text, toolName: d.toolName || undefined };\n });\n\n return { conversationId, messages, messageCount: messages.length };\n}\n\nexport async function createConversation(opts: ConversationOpts): Promise<string> {\n const base = firestoreDocsBase(opts.firebaseProjectId);\n const colPath = `projects/${opts.projectId}/versions/${opts.versionId}/ai_conversations`;\n const now = new Date().toISOString();\n\n const res = await fetch(`${base}/${colPath}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({\n fields: {\n projectId: { stringValue: opts.projectId },\n versionId: { stringValue: opts.versionId },\n createdAt: { timestampValue: now },\n updatedAt: { timestampValue: now },\n },\n }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Failed to create conversation (${res.status}): ${text}`);\n }\n const doc = (await res.json()) as { name?: string };\n const id = extractDocIdFromName(doc.name);\n if (!id) throw new Error(\"Failed to extract conversation ID\");\n return id;\n}\n\nexport async function appendMessage(opts: ConversationOpts & {\n conversationId: string;\n role: string;\n text: string;\n toolName?: string;\n seq: number;\n}): Promise<void> {\n const base = firestoreDocsBase(opts.firebaseProjectId);\n const msgPath = `projects/${opts.projectId}/versions/${opts.versionId}/ai_conversations/${opts.conversationId}/messages`;\n const now = new Date().toISOString();\n\n const fields: Record<string, any> = {\n role: { stringValue: opts.role },\n text: { stringValue: opts.text },\n seq: { integerValue: String(opts.seq) },\n createdAt: { timestampValue: now },\n };\n if (opts.toolName) {\n fields.toolName = { stringValue: opts.toolName };\n }\n\n // Create message doc\n const msgRes = await fetch(`${base}/${msgPath}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({ fields }),\n });\n if (!msgRes.ok) return; // best-effort\n\n // Update conversation updatedAt\n const convoPath = `projects/${opts.projectId}/versions/${opts.versionId}/ai_conversations/${opts.conversationId}`;\n await fetch(`${base}/${convoPath}?updateMask.fieldPaths=updatedAt`, {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({\n fields: { updatedAt: { timestampValue: now } },\n }),\n }).catch(() => {}); // best-effort\n}\n\nfunction toMs(value: unknown): number {\n if (!value) return 0;\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? 0 : parsed;\n }\n return 0;\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport WebSocket from \"ws\";\nimport type {\n TerminalClientMessage,\n TerminalScreenPayload,\n TerminalServerMessage,\n} from \"@blo/shared/terminal\";\nimport { log } from \"../log.js\";\n\nconst toWsBaseUrl = (httpBase: string): string => {\n if (httpBase.startsWith(\"https://\")) return `wss://${httpBase.slice(\"https://\".length)}`;\n if (httpBase.startsWith(\"http://\")) return `ws://${httpBase.slice(\"http://\".length)}`;\n return httpBase;\n};\n\nconst getTerminalSize = (): { rows: number; cols: number } => {\n const cols = Math.max(3, Math.min(300, Number(process.stdout.columns || 80)));\n const rows = Math.max(3, Math.min(200, Number(process.stdout.rows || 24)));\n return { rows, cols };\n};\n\ntype SessionArgs = {\n projectId: string;\n versionId?: string;\n terminalUrl: string;\n idToken: string;\n};\n\nexport const useRunnerSession = ({ projectId, versionId, terminalUrl, idToken }: SessionArgs) => {\n const [screen, setScreen] = useState<TerminalScreenPayload | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [connecting, setConnecting] = useState(true);\n const [sessionId, setSessionId] = useState<string | null>(null);\n const wsRef = useRef<WebSocket | null>(null);\n const lastSentSizeRef = useRef<string>(\"\");\n\n useEffect(() => {\n let cancelled = false;\n const run = async () => {\n try {\n setConnecting(true);\n setError(null);\n const sessionUrl = `${terminalUrl.replace(/\\/+$/, \"\")}/api/sessions`;\n log(`Creating session: POST ${sessionUrl}`);\n log(` projectId=${projectId}, versionId=${versionId || \"(latest)\"}`);\n const response = await fetch(sessionUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${idToken}`,\n },\n body: JSON.stringify({\n projectId,\n versionId,\n runnerVersion: \"cli-dev\",\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n log(`Session create failed: ${response.status} ${text}`);\n if (response.status === 401) {\n throw new Error(\"Authentication failed. Try 'blo login' to re-authenticate.\");\n }\n if (response.status === 403) {\n throw new Error(`Access denied for project ${projectId}: ${text}`);\n }\n if (response.status === 429) {\n throw new Error(\"Rate limited. Please wait a moment and try again.\");\n }\n throw new Error(`Session create failed (${response.status}): ${text}`);\n }\n\n const body = (await response.json()) as\n | { bootstrap?: { sessionId?: string }; screen?: TerminalScreenPayload }\n | TerminalScreenPayload;\n if (cancelled) return;\n\n // POST /api/sessions returns { bootstrap, screen }\n const screenPayload = \"screen\" in body && body.screen && typeof body.screen === \"object\" && \"sessionId\" in body.screen\n ? body.screen as TerminalScreenPayload\n : body as TerminalScreenPayload;\n const sid = screenPayload.sessionId\n || (\"bootstrap\" in body ? body.bootstrap?.sessionId : undefined)\n || \"\";\n\n if (!sid) {\n log(`WARNING: No sessionId in response. Response keys: ${Object.keys(body).join(\", \")}`);\n throw new Error(\"Server returned no session ID. The server may be running an incompatible version.\");\n }\n\n log(`Session created: sessionId=${sid}`);\n log(` screen=${screenPayload.screen}, lines=${screenPayload.lines?.length || 0}`);\n setScreen(screenPayload);\n setSessionId(sid);\n\n const wsBase = toWsBaseUrl(terminalUrl.replace(/\\/+$/, \"\"));\n const wsUrl = `${wsBase}/ws?sessionId=${encodeURIComponent(sid)}`;\n log(`Connecting WebSocket: ${wsUrl}`);\n const ws = new WebSocket(wsUrl);\n wsRef.current = ws;\n ws.onopen = () => {\n log(\"WebSocket connected\");\n ws.send(JSON.stringify({ type: \"init\" } satisfies TerminalClientMessage));\n const size = getTerminalSize();\n const sizeKey = `${size.rows}x${size.cols}`;\n lastSentSizeRef.current = sizeKey;\n log(`Sending resize: ${size.cols}x${size.rows}`);\n ws.send(\n JSON.stringify({\n type: \"resize\",\n rows: size.rows,\n cols: size.cols,\n } satisfies TerminalClientMessage)\n );\n setConnecting(false);\n };\n ws.onmessage = (event) => {\n try {\n const data = JSON.parse(String(event.data)) as TerminalServerMessage;\n if (data.type === \"screen\") {\n log(`Screen update: screen=${data.screen}, lines=${data.lines?.length || 0}`);\n setScreen(data);\n return;\n }\n if (data.type === \"error\") {\n log(`Server error: ${data.message}`);\n setError(data.message);\n }\n } catch (err) {\n log(`Failed to parse server message: ${err}`);\n setError(err instanceof Error ? err.message : String(err));\n }\n };\n ws.onclose = (event) => {\n const code = event.code;\n const reason = event.reason || \"(no reason)\";\n log(`WebSocket closed: code=${code}, reason=${reason}`);\n if (!cancelled) {\n if (code === 1008) {\n setError(`Session rejected by server: ${reason}`);\n } else if (code === 1006) {\n setError(\"Lost connection to server. Check if the terminal server is running.\");\n } else {\n setError(`Connection closed (code ${code}).`);\n }\n }\n };\n ws.onerror = (event) => {\n log(`WebSocket error: ${event.message || \"unknown\"}`);\n if (!cancelled) {\n setError(`Connection error: ${event.message || \"Failed to connect to terminal server.\"}`);\n }\n };\n } catch (err) {\n if (!cancelled) {\n log(`Runner error: ${err}`);\n setError(err instanceof Error ? err.message : String(err));\n }\n }\n };\n\n void run();\n\n return () => {\n cancelled = true;\n wsRef.current?.close();\n wsRef.current = null;\n };\n }, [projectId, versionId, terminalUrl, idToken]);\n\n useEffect(() => {\n if (!sessionId || !process.stdout.isTTY) return;\n const onTerminalResize = () => {\n const ws = wsRef.current;\n if (!ws || ws.readyState !== WebSocket.OPEN) return;\n const size = getTerminalSize();\n const sizeKey = `${size.rows}x${size.cols}`;\n if (lastSentSizeRef.current === sizeKey) return;\n lastSentSizeRef.current = sizeKey;\n log(`Terminal resized: ${size.cols}x${size.rows}`);\n ws.send(\n JSON.stringify({\n type: \"resize\",\n rows: size.rows,\n cols: size.cols,\n } satisfies TerminalClientMessage)\n );\n };\n\n process.stdout.on(\"resize\", onTerminalResize);\n return () => {\n process.stdout.off(\"resize\", onTerminalResize);\n };\n }, [sessionId]);\n\n const sendMessage = (message: TerminalClientMessage) => {\n const ws = wsRef.current;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n log(`Cannot send message (ws ${ws ? `state=${ws.readyState}` : \"null\"}): ${JSON.stringify(message)}`);\n if (ws && ws.readyState >= WebSocket.CLOSING) {\n setError(\"Connection lost. Press x to return to apps.\");\n }\n return;\n }\n log(`Sending: ${JSON.stringify(message)}`);\n ws.send(JSON.stringify(message));\n };\n\n return { screen, error, connecting, sessionId, sendMessage };\n};\n","import { useMemo } from \"react\";\nimport type { TerminalActionLine, TerminalScreenPayload } from \"@blo/shared/terminal\";\nimport type { ListScrollInfo } from \"@blo/shared/screen-runtime\";\nimport { collectScreenSpecContext } from \"@blo/shared/screen-runtime\";\n\nexport const useRunnerRenderSource = (\n screen: TerminalScreenPayload | null,\n listScrollOffsets?: Record<string, number>,\n) => {\n const result = useMemo(() => {\n if (!screen?.screenSpec || !screen?.state) return { screen, listScrollInfo: undefined as Record<string, ListScrollInfo> | undefined };\n\n const ctx = collectScreenSpecContext(screen.screenSpec, {\n activeScreenId: screen.state.activeScreenId || screen.screen,\n fields: screen.state.fields || {},\n fieldErrors: screen.state.fieldErrors || {},\n data: screen.state.data || {},\n statusLine: screen.state.statusLine || screen.statusLine,\n }, { hideHotkeys: false, listScrollOffsets });\n\n const lines = ctx.lines.map((line) => line.text);\n const lineWidgetIds = ctx.lines.map((line) => line.widgetId);\n\n const fieldLineIndexById = new Map<string, number>();\n ctx.lines.forEach((line, idx) => {\n if (line.fieldId && !fieldLineIndexById.has(line.fieldId)) {\n fieldLineIndexById.set(line.fieldId, idx);\n }\n });\n\n const actionLines: TerminalActionLine[] = [];\n ctx.lines.forEach((line, idx) => {\n if (!(line.target || line.aidAlias || line.action)) return;\n actionLines.push({\n index: idx,\n selectable: line.selectable,\n target: line.target,\n aidAlias: line.aidAlias,\n action: line.action,\n fields: line.fields,\n });\n });\n\n const inputFields = ctx.inputFields.map((field) => ({\n ...field,\n lineIndex: fieldLineIndexById.get(field.id),\n }));\n\n const firstMatch = ctx.firstInput\n ? inputFields.find((f) => f.id === ctx.firstInput?.id)\n : undefined;\n const inputField = ctx.firstInput\n ? {\n id: ctx.firstInput.id,\n value: screen.state.fields?.[ctx.firstInput.id] || \"\",\n maxLength: ctx.firstInput.maxLength,\n label: firstMatch?.label,\n lineIndex: fieldLineIndexById.get(ctx.firstInput.id),\n rows: firstMatch?.rows,\n action: firstMatch?.action,\n }\n : undefined;\n\n return {\n screen: {\n ...screen,\n lines,\n actionLines,\n inputFields,\n inputField,\n shortcuts: ctx.shortcuts,\n statusLine: screen.state.statusLine || screen.statusLine,\n } satisfies TerminalScreenPayload,\n listScrollInfo: ctx.listScrollInfo,\n lineWidgetIds,\n };\n }, [screen, listScrollOffsets]);\n\n return result;\n};\n","// ===== Type Guards =====\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n\n// ===== Field Parsing Utilities =====\n\nexport const parseMaxLength = (value: unknown): number => {\n if (typeof value === \"number\" && Number.isFinite(value) && value > 0) {\n return Math.min(Math.floor(value), 512);\n }\n if (typeof value === \"string\") {\n const parsed = Number.parseInt(value, 10);\n if (Number.isFinite(parsed) && parsed > 0) {\n return Math.min(parsed, 512);\n }\n }\n return 80;\n};\n\nexport const parseRows = (value: unknown): number => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return Math.max(1, Math.floor(value));\n }\n if (typeof value === \"string\") {\n const parsed = Number.parseInt(value, 10);\n if (Number.isFinite(parsed)) {\n return Math.max(1, Math.floor(parsed));\n }\n }\n return 1;\n};\n\nexport const toFiniteNumber = (value: unknown): number | null => {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\" && value.trim().length > 0) {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) return parsed;\n }\n return null;\n};\n\n// ===== Hotkey Normalization =====\n\nexport const normalizeHotkey = (value: unknown): string | null => {\n const raw = String(value || \"\").trim().toLowerCase();\n if (!raw) return null;\n if (!/^[a-z0-9]$/.test(raw)) return null;\n return raw;\n};\n","import { isRecord } from \"../parsing/fieldParser.js\";\n\n// ===== Security Constants =====\n\n// Keys that should never be accessed or modified to prevent prototype pollution\nconst DANGEROUS_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nconst isDangerousKey = (key: string): boolean => DANGEROUS_KEYS.has(key);\n\n// ===== Path Resolution =====\n\nexport const resolvePath = (source: unknown, path: string): unknown => {\n if (!path.trim()) return undefined;\n return path.split(\".\").reduce<unknown>((acc, key) => {\n if (!isRecord(acc)) return undefined;\n if (isDangerousKey(key)) return undefined;\n return acc[key];\n }, source);\n};\n\n// ===== String Interpolation =====\n\nexport const interpolate = (template: string, context: Record<string, unknown>): string =>\n template.replace(/\\{\\{\\s*([^}]+)\\s*\\}\\}/g, (_full, exprRaw) => {\n const expr = String(exprRaw || \"\").trim();\n const defaultMatch = expr.match(\n /^([A-Za-z0-9_.]+)\\s*\\|\\s*default\\s*:\\s*(.+)$/\n );\n if (defaultMatch) {\n const path = String(defaultMatch[1] || \"\").trim();\n const fallbackRaw = String(defaultMatch[2] || \"\").trim();\n const resolved = resolvePath(context, path);\n if (resolved != null) {\n return String(resolved);\n }\n const fallback =\n fallbackRaw === \"null\"\n ? null\n : fallbackRaw === \"true\"\n ? true\n : fallbackRaw === \"false\"\n ? false\n : /^-?\\d+(\\.\\d+)?$/.test(fallbackRaw)\n ? Number(fallbackRaw)\n : fallbackRaw.replace(/^[\"']|[\"']$/g, \"\");\n return fallback == null ? \"\" : String(fallback);\n }\n\n const value = resolvePath(context, expr);\n return value == null ? \"\" : String(value);\n });\n\n// ===== Path Mutation =====\n\nexport const setPathValue = (\n target: Record<string, unknown>,\n path: string,\n value: unknown\n): void => {\n const keys = path\n .split(\".\")\n .map((part) => part.trim())\n .filter((k) => k && !isDangerousKey(k));\n if (!keys.length) return;\n let cursor: Record<string, unknown> = target;\n keys.slice(0, -1).forEach((key) => {\n const existing = cursor[key];\n if (!isRecord(existing)) {\n cursor[key] = {};\n }\n cursor = cursor[key] as Record<string, unknown>;\n });\n cursor[keys[keys.length - 1]] = value;\n};\n\n// ===== Collection Utilities =====\n\nexport const getCollectionRecords = (\n root: Record<string, unknown>,\n path: string\n): Array<Record<string, unknown>> => {\n const value = resolvePath(root, path);\n if (!Array.isArray(value)) return [];\n return value.map((item) => (isRecord(item) ? { ...item } : { value: item }));\n};\n\nexport const setCollectionRecords = (\n root: Record<string, unknown>,\n path: string,\n records: Array<Record<string, unknown>>\n) => {\n setPathValue(root, path, records);\n};\n","import { toFiniteNumber } from \"../parsing/fieldParser.js\";\n\n// ===== Action Value Building =====\n\nexport const buildActionValues = (\n actionValues: Record<string, unknown> | undefined,\n valuesFromFields: Record<string, string> | undefined,\n fields: Record<string, string>\n): Record<string, unknown> => {\n const values: Record<string, unknown> = {};\n Object.entries(actionValues || {}).forEach(([key, value]) => {\n values[key] = value;\n });\n Object.entries(valuesFromFields || {}).forEach(([key, fieldId]) => {\n values[key] = String(fields[String(fieldId) || \"\"] || \"\");\n });\n return values;\n};\n\n// ===== Sort Comparison =====\n\nexport const compareSortValues = (left: unknown, right: unknown): number => {\n const leftNum = toFiniteNumber(left);\n const rightNum = toFiniteNumber(right);\n if (leftNum != null && rightNum != null) {\n return leftNum - rightNum;\n }\n const leftText = String(left ?? \"\").toLowerCase();\n const rightText = String(right ?? \"\").toLowerCase();\n return leftText.localeCompare(rightText);\n};\n","import type { ScreenAction, ScreenFieldWidget, ScreenSelectWidget, ScreenCheckboxWidget, ScreenRadioWidget, ScreenNumberWidget, ScreenDateWidget } from \"../../screen-spec.js\";\nimport type { RuntimeState } from \"../types.js\";\nimport { resolvePath } from \"../state/pathUtils.js\";\n\n// ===== Widget Bind Keys =====\n\nexport const fieldBindKey = (widget: ScreenFieldWidget): string =>\n widget.bind.trim() || widget.id;\n\nexport const selectBindKey = (widget: Pick<ScreenSelectWidget, \"bind\" | \"id\">): string =>\n widget.bind.trim() || widget.id;\n\n// ===== Widget Labels =====\n\nexport const fieldLabel = (widget: ScreenFieldWidget): string =>\n widget.label || widget.placeholder || widget.id;\n\nexport const selectLabel = (widget: ScreenSelectWidget): string =>\n widget.label || widget.placeholder || widget.id;\n\n// ===== Widget Value Resolution =====\n\nexport const resolveFieldValue = (\n widget: ScreenFieldWidget,\n state: RuntimeState\n): string => {\n const bindKey = fieldBindKey(widget);\n const fallback = resolvePath(state.data, bindKey);\n if (state.fields[bindKey] != null) {\n return String(state.fields[bindKey] || \"\");\n }\n if (typeof fallback === \"string\" || typeof fallback === \"number\" || typeof fallback === \"boolean\") {\n return String(fallback);\n }\n return \"\";\n};\n\nexport const resolveSelectValue = (\n widget: Pick<ScreenSelectWidget, \"bind\" | \"id\">,\n state: RuntimeState\n): string => {\n const bindKey = selectBindKey(widget);\n if (state.fields[bindKey] != null) {\n return String(state.fields[bindKey] || \"\");\n }\n const fallback = resolvePath(state.data, bindKey);\n if (typeof fallback === \"string\" || typeof fallback === \"number\" || typeof fallback === \"boolean\") {\n return String(fallback);\n }\n return \"\";\n};\n\n// ===== Checkbox / Radio / Number Bind Keys =====\n\nexport const checkboxBindKey = (widget: ScreenCheckboxWidget): string =>\n widget.bind.trim() || widget.id;\n\nexport const radioBindKey = (widget: ScreenRadioWidget): string =>\n widget.bind.trim() || widget.id;\n\nexport const numberBindKey = (widget: ScreenNumberWidget): string =>\n widget.bind.trim() || widget.id;\n\n// ===== Checkbox / Number Value Resolution =====\n\nexport const resolveCheckboxValue = (\n widget: ScreenCheckboxWidget,\n state: RuntimeState\n): boolean => {\n const bindKey = checkboxBindKey(widget);\n if (state.fields[bindKey] != null) {\n const v = state.fields[bindKey];\n return v === \"true\" || v === \"1\";\n }\n const fallback = resolvePath(state.data, bindKey);\n if (typeof fallback === \"string\") {\n return fallback === \"true\" || fallback === \"1\";\n }\n return Boolean(fallback);\n};\n\nexport const resolveNumberValue = (\n widget: ScreenNumberWidget,\n state: RuntimeState\n): number => {\n const bindKey = numberBindKey(widget);\n if (state.fields[bindKey] != null) {\n const v = Number(state.fields[bindKey]);\n return Number.isFinite(v) ? v : 0;\n }\n const fallback = resolvePath(state.data, bindKey);\n if (typeof fallback === \"number\" && Number.isFinite(fallback)) return fallback;\n return 0;\n};\n\n// ===== Date Bind Key & Value Resolution =====\n\nexport const dateBindKey = (widget: ScreenDateWidget): string =>\n widget.bind.trim() || widget.id;\n\nexport const resolveDateValue = (\n widget: ScreenDateWidget,\n state: RuntimeState\n): string => {\n const bindKey = dateBindKey(widget);\n if (state.fields[bindKey] != null) {\n const v = String(state.fields[bindKey] || \"\");\n if (parseISODate(v)) return v;\n }\n const fallback = resolvePath(state.data, bindKey);\n if (typeof fallback === \"string\" && parseISODate(fallback)) return fallback;\n return todayISO();\n};\n\n// ===== Date Utilities (UTC-based, no timezone issues) =====\n\nexport const MONTH_NAMES = [\n \"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\n \"July\", \"August\", \"September\", \"October\", \"November\", \"December\",\n];\n\nconst MONTH_ABBR = [\n \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\",\n];\n\nexport const parseISODate = (str: string): { y: number; m: number; d: number } | null => {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(str);\n if (!match) return null;\n const y = Number(match[1]);\n const m = Number(match[2]);\n const d = Number(match[3]);\n if (m < 1 || m > 12 || d < 1 || d > daysInMonth(y, m)) return null;\n return { y, m, d };\n};\n\nexport const formatDisplayDate = (y: number, m: number, d: number): string =>\n `${MONTH_ABBR[m - 1]} ${d}, ${y}`;\n\nexport const daysInMonth = (y: number, m: number): number => {\n if (m === 2) return (y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0)) ? 29 : 28;\n return [0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m];\n};\n\nexport const dayOfWeek = (y: number, m: number, d: number): number => {\n // Tomohiko Sakamoto's algorithm, returns 0=Sun..6=Sat\n const t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];\n const yr = m < 3 ? y - 1 : y;\n return (yr + Math.floor(yr / 4) - Math.floor(yr / 100) + Math.floor(yr / 400) + t[m - 1] + d) % 7;\n};\n\nconst pad2 = (n: number): string => (n < 10 ? \"0\" + n : String(n));\n\nconst toISO = (y: number, m: number, d: number): string =>\n `${y}-${pad2(m)}-${pad2(d)}`;\n\nexport const shiftDay = (iso: string, delta: number): string => {\n const parsed = parseISODate(iso);\n if (!parsed) return iso;\n const ms = Date.UTC(parsed.y, parsed.m - 1, parsed.d) + delta * 86400000;\n const dt = new Date(ms);\n return toISO(dt.getUTCFullYear(), dt.getUTCMonth() + 1, dt.getUTCDate());\n};\n\nexport const shiftMonth = (iso: string, delta: number): string => {\n const parsed = parseISODate(iso);\n if (!parsed) return iso;\n let newM = parsed.m + delta;\n let newY = parsed.y;\n while (newM > 12) { newM -= 12; newY++; }\n while (newM < 1) { newM += 12; newY--; }\n const clamped = Math.min(parsed.d, daysInMonth(newY, newM));\n return toISO(newY, newM, clamped);\n};\n\nexport const buildCalendarLines = (y: number, m: number, selectedDay: number): string[] => {\n const lines: string[] = [];\n lines.push(` Su Mo Tu We Th Fr Sa`);\n const total = daysInMonth(y, m);\n const startDow = dayOfWeek(y, m, 1);\n let line = \" \".repeat(startDow * 4);\n for (let d = 1; d <= total; d++) {\n // All cells are 4 chars wide for consistent alignment\n line += d === selectedDay ? `[${pad2(d)}]` : ` ${pad2(d)}`;\n const dow = (startDow + d) % 7;\n if (dow === 0 && d < total) {\n lines.push(line.trimEnd());\n line = \"\";\n }\n }\n if (line.trim()) lines.push(line.trimEnd());\n return lines;\n};\n\nexport const todayISO = (): string => {\n const now = new Date();\n return toISO(now.getUTCFullYear(), now.getUTCMonth() + 1, now.getUTCDate());\n};\n\n// ===== Date Picker Rendering =====\n\nexport interface DatePickerState {\n bindPath: string;\n currentISO: string;\n returnScreenId: string;\n}\n\nconst CANCEL_PICKER: ScreenAction = { type: \"data.set\", path: \"__datePicker\", value: null };\nconst CONFIRM_PICKER: ScreenAction = { type: \"date.pick\" };\n\nexport interface DatePickerRenderResult {\n lines: Array<{ text: string }>;\n shortcuts: Array<{ key: string; label: string; action: ScreenAction }>;\n enterAction: ScreenAction;\n cancelAction: ScreenAction;\n}\n\nexport const isDatePickerActive = (\n data: Record<string, unknown>,\n activeScreenId: string\n): DatePickerState | null => {\n const raw = data.__datePicker;\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return null;\n const picker = raw as DatePickerState;\n if (typeof picker.bindPath !== \"string\" || typeof picker.currentISO !== \"string\") return null;\n if (picker.returnScreenId !== activeScreenId) return null;\n return picker;\n};\n\nexport const renderDatePickerLines = (picker: DatePickerState): DatePickerRenderResult => {\n const iso = picker.currentISO;\n const parsed = parseISODate(iso);\n if (!parsed) {\n return { lines: [{ text: \"Invalid date\" }], shortcuts: [], enterAction: CANCEL_PICKER, cancelAction: CANCEL_PICKER };\n }\n\n const p = \"__datePicker.currentISO\";\n const setP = (v: string): ScreenAction => ({ type: \"data.set\", path: p, value: v });\n\n return {\n lines: [\n { text: \"\" },\n { text: \" === Select Date ===\" },\n { text: \"\" },\n { text: ` ${parsed.y}` },\n { text: ` [<] ${MONTH_NAMES[parsed.m - 1]} [>]` },\n { text: \"\" },\n ...buildCalendarLines(parsed.y, parsed.m, parsed.d).map((cl) => ({ text: ` ${cl}` })),\n { text: \"\" },\n { text: ` Selected: ${formatDisplayDate(parsed.y, parsed.m, parsed.d)}` },\n { text: \"\" },\n { text: \" Arrows/H/L: Day J/K: Week\" },\n { text: \" [<] Prev Month [>] Next Month\" },\n { text: \" [[] Prev Year []] Next Year\" },\n { text: \" [T] Today\" },\n { text: \" Enter: Select Esc: Cancel\" },\n ],\n shortcuts: [\n { key: \"<\", label: \"Prev month\", action: setP(shiftMonth(iso, -1)) },\n { key: \">\", label: \"Next month\", action: setP(shiftMonth(iso, 1)) },\n { key: \"h\", label: \"Prev day\", action: setP(shiftDay(iso, -1)) },\n { key: \"l\", label: \"Next day\", action: setP(shiftDay(iso, 1)) },\n { key: \"j\", label: \"Next week\", action: setP(shiftDay(iso, 7)) },\n { key: \"k\", label: \"Prev week\", action: setP(shiftDay(iso, -7)) },\n { key: \"[\", label: \"Prev year\", action: setP(shiftMonth(iso, -12)) },\n { key: \"]\", label: \"Next year\", action: setP(shiftMonth(iso, 12)) },\n { key: \"t\", label: \"Today\", action: { type: \"date.pick\", value: todayISO() } },\n ],\n enterAction: CONFIRM_PICKER,\n cancelAction: CANCEL_PICKER,\n };\n};\n\n// ===== Validation Message Helper =====\n\nexport const toValidationMessage = (\n widget: ScreenFieldWidget | ScreenSelectWidget | ScreenRadioWidget | ScreenDateWidget,\n fallback: string\n): string => {\n const generic = String(widget.validation?.message || \"\").trim();\n return generic || fallback;\n};\n","import type { TerminalScreenSpecV2 } from \"../../screen-spec.js\";\nimport type { RuntimeState, RuntimeRenderContext, ScreenRenderOptions, ListScrollInfo } from \"../types.js\";\nimport { parseMaxLength, parseRows, normalizeHotkey } from \"../parsing/fieldParser.js\";\nimport { interpolate, resolvePath } from \"../state/pathUtils.js\";\nimport { compareSortValues } from \"../actions/actionBuilder.js\";\nimport {\n fieldBindKey,\n selectBindKey,\n checkboxBindKey,\n radioBindKey,\n numberBindKey,\n dateBindKey,\n fieldLabel,\n selectLabel,\n resolveFieldValue,\n resolveSelectValue,\n resolveCheckboxValue,\n resolveNumberValue,\n resolveDateValue,\n parseISODate,\n formatDisplayDate,\n shiftDay,\n shiftMonth,\n buildCalendarLines,\n MONTH_NAMES,\n isDatePickerActive,\n renderDatePickerLines,\n} from \"./widgetHelpers.js\";\n\n// ===== Screen Rendering =====\n\nexport const collectScreenSpecContext = (\n screenSpec: TerminalScreenSpecV2,\n state: RuntimeState,\n options: ScreenRenderOptions = {}\n): RuntimeRenderContext => {\n const ctx: RuntimeRenderContext = { lines: [], shortcuts: [], inputFields: [], actionLines: [], listScrollInfo: {} };\n const hotkeySet = new Set<string>();\n const vars: Record<string, unknown> = {\n ...state.data,\n fields: state.fields,\n };\n const picker = isDatePickerActive(state.data, state.activeScreenId);\n if (picker) {\n const result = renderDatePickerLines(picker);\n return { ...ctx, ...result };\n }\n\n const sortedWidgets = [...screenSpec.widgets].sort((a, b) => {\n const rowA = Number((a as { row?: number }).row || 0);\n const rowB = Number((b as { row?: number }).row || 0);\n if (rowA !== rowB) return rowA - rowB;\n const colA = Number((a as { col?: number }).col || 0);\n const colB = Number((b as { col?: number }).col || 0);\n return colA - colB;\n });\n\n const pushSpacerLines = (count: number) => {\n for (let i = 0; i < count; i += 1) {\n ctx.lines.push({ text: \"\" });\n }\n };\n\n sortedWidgets.forEach((widget) => {\n if (widget.kind === \"text\") {\n ctx.lines.push({\n text: interpolate(widget.text, vars),\n widgetId: widget.id,\n });\n return;\n }\n\n if (widget.kind === \"field\") {\n const bindKey = fieldBindKey(widget);\n const value = resolveFieldValue(widget, state);\n const label = fieldLabel(widget);\n const perRowLength = Math.max(1, parseMaxLength(widget.length));\n const rowCount = Math.max(1, parseRows(widget.rows));\n const lineStep = Math.max(1, Number((widget as { lineStep?: number }).lineStep) || 1);\n const maxLength = Math.min(512, perRowLength * rowCount);\n const labelPrefix = label ? `${label}: ` : \"\";\n const indent = \" \".repeat(labelPrefix.length);\n const rawLines = String(value || \"\").split(/\\r?\\n/);\n const wrappedLines: string[] = [];\n rawLines.forEach((line) => {\n if (line.length === 0) {\n wrappedLines.push(\"\");\n return;\n }\n for (let i = 0; i < line.length; i += perRowLength) {\n wrappedLines.push(line.slice(i, i + perRowLength));\n }\n });\n if (wrappedLines.length === 0) wrappedLines.push(\"\");\n const paddedLines = wrappedLines.slice(0, rowCount);\n while (paddedLines.length < rowCount) paddedLines.push(\"\");\n\n const lineIndex = ctx.lines.length;\n paddedLines.forEach((line, idx) => {\n ctx.lines.push({\n text: `${idx === 0 ? labelPrefix : indent}${line}`,\n widgetId: widget.id,\n fieldId: bindKey,\n });\n const isLast = idx === paddedLines.length - 1;\n if (lineStep > 1 && !isLast) {\n for (let gap = 1; gap < lineStep; gap += 1) {\n ctx.lines.push({\n text: indent,\n widgetId: widget.id,\n fieldId: bindKey,\n });\n }\n }\n });\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n ctx.inputFields.push({\n id: bindKey,\n value,\n maxLength,\n label,\n lineIndex,\n rows: rowCount,\n lineStep,\n });\n if (!ctx.firstInput) {\n ctx.firstInput = {\n id: bindKey,\n maxLength,\n label,\n };\n }\n return;\n }\n\n if (widget.kind === \"action\") {\n const renderedLabel = interpolate(widget.label, vars);\n const hotkey = normalizeHotkey(widget.hotkey);\n const lineLabel = options.hideHotkeys\n ? renderedLabel\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${renderedLabel}`\n : `[ ${renderedLabel} ]`;\n if (widget.action.type === \"nav.goto\") {\n ctx.lines.push({\n text: lineLabel,\n widgetId: widget.id,\n target: widget.action.target,\n });\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n target: widget.action.target,\n });\n }\n return;\n }\n ctx.lines.push({\n text: lineLabel,\n widgetId: widget.id,\n action: widget.action,\n });\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: widget.action,\n });\n }\n return;\n }\n\n if (widget.kind === \"select\") {\n const bindKey = selectBindKey(widget);\n const label = selectLabel(widget);\n const currentValue = resolveSelectValue(widget, state).trim();\n const normalizedCurrent = currentValue.toLowerCase();\n const gap = Math.max(1, Number(widget.gap ?? 2));\n const parts: string[] = [];\n const labelPrefix = label ? `${label} ` : \"\";\n\n widget.options.forEach((option) => {\n const renderedLabel = interpolate(option.label, vars);\n const hotkey = normalizeHotkey(option.hotkey);\n const normalizedOption = String(option.value || \"\").trim().toLowerCase();\n const selected =\n normalizedCurrent.length > 0 && normalizedCurrent === normalizedOption;\n const displayLabel = selected ? `${renderedLabel}*` : renderedLabel;\n const lineLabel = options.hideHotkeys\n ? displayLabel\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${displayLabel}`\n : `[ ${displayLabel} ]`;\n parts.push(lineLabel);\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: {\n type: \"data.set\",\n path: bindKey,\n value: option.value,\n },\n });\n }\n });\n\n const lineIndex = ctx.lines.length;\n ctx.lines.push({\n text: `${labelPrefix}${parts.join(\" \".repeat(gap))}`.trimEnd(),\n widgetId: widget.id,\n fieldId: bindKey,\n });\n\n ctx.inputFields.push({\n id: bindKey,\n value: currentValue,\n maxLength: 0,\n label,\n lineIndex,\n rows: 1,\n });\n\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n return;\n }\n\n if (widget.kind === \"checkbox\") {\n const bindKey = checkboxBindKey(widget);\n const checked = resolveCheckboxValue(widget, state);\n const marker = checked ? \"[X]\" : \"[ ]\";\n const renderedLabel = interpolate(widget.label, vars);\n const hotkey = normalizeHotkey(widget.hotkey);\n const lineLabel = options.hideHotkeys\n ? `${marker} ${renderedLabel}`\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${marker} ${renderedLabel}`\n : `${marker} ${renderedLabel}`;\n const lineIndex = ctx.lines.length;\n ctx.lines.push({ text: lineLabel, widgetId: widget.id, fieldId: bindKey });\n const toggleAction = widget.action ?? { type: \"data.toggleFlag\" as const, path: bindKey };\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: toggleAction,\n });\n }\n // Add to inputFields to make it navigatable\n ctx.inputFields.push({\n id: bindKey,\n value: String(checked),\n maxLength: 0,\n label: renderedLabel,\n lineIndex,\n rows: 1,\n action: toggleAction,\n });\n return;\n }\n\n if (widget.kind === \"radio\") {\n const bindKey = radioBindKey(widget);\n const currentValue = resolveSelectValue(widget, state).trim();\n const normalizedCurrent = currentValue.toLowerCase();\n const gap = Math.max(1, Number(widget.gap ?? 2));\n const parts: string[] = [];\n const label = widget.label ? `${widget.label} ` : \"\";\n\n widget.options.forEach((option) => {\n const renderedLabel = interpolate(option.label, vars);\n const hotkey = normalizeHotkey(option.hotkey);\n const normalizedOption = String(option.value || \"\").trim().toLowerCase();\n const selected =\n normalizedCurrent.length > 0 && normalizedCurrent === normalizedOption;\n const marker = selected ? \"(o)\" : \"( )\";\n const displayLabel = `${marker} ${renderedLabel}`;\n const lineLabel = options.hideHotkeys\n ? displayLabel\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${displayLabel}`\n : displayLabel;\n parts.push(lineLabel);\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: { type: \"data.set\", path: bindKey, value: option.value },\n });\n }\n });\n\n const lineIndex = ctx.lines.length;\n ctx.lines.push({\n text: `${label}${parts.join(\" \".repeat(gap))}`.trimEnd(),\n widgetId: widget.id,\n fieldId: bindKey,\n });\n\n ctx.inputFields.push({\n id: bindKey,\n value: currentValue,\n maxLength: 0,\n label: widget.label || widget.id,\n lineIndex,\n rows: 1,\n });\n\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n return;\n }\n\n if (widget.kind === \"number\") {\n const bindKey = numberBindKey(widget);\n const value = resolveNumberValue(widget, state);\n const label = widget.label || widget.id;\n const step = typeof widget.step === \"number\" && Number.isFinite(widget.step) ? widget.step : 1;\n const incAction = {\n type: \"data.increment\" as const,\n path: bindKey,\n by: step,\n ...(typeof widget.min === \"number\" ? { min: widget.min } : {}),\n ...(typeof widget.max === \"number\" ? { max: widget.max } : {}),\n };\n const decAction = {\n type: \"data.increment\" as const,\n path: bindKey,\n by: -step,\n ...(typeof widget.min === \"number\" ? { min: widget.min } : {}),\n ...(typeof widget.max === \"number\" ? { max: widget.max } : {}),\n };\n\n const lineLabel = options.hideHotkeys\n ? `${label}: [ ${value} ]`\n : `${label}: [ ${value} ] [+][-]`;\n\n const lineIndex = ctx.lines.length;\n ctx.lines.push({ text: lineLabel, widgetId: widget.id, fieldId: bindKey });\n\n if (!options.hideHotkeys) {\n if (!hotkeySet.has(\"+\")) {\n hotkeySet.add(\"+\");\n ctx.shortcuts.push({ key: \"+\", label: `${label} +`, action: incAction });\n }\n if (!hotkeySet.has(\"-\")) {\n hotkeySet.add(\"-\");\n ctx.shortcuts.push({ key: \"-\", label: `${label} -`, action: decAction });\n }\n }\n\n ctx.inputFields.push({\n id: bindKey,\n value: String(value),\n maxLength: 0,\n label,\n lineIndex,\n rows: 1,\n });\n\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n return;\n }\n\n if (widget.kind === \"date\") {\n const bindKey = dateBindKey(widget);\n const iso = resolveDateValue(widget, state);\n const parsed = parseISODate(iso);\n const label = widget.label || widget.id;\n const display = widget.display || \"inline\";\n\n const dateLineIndex = ctx.lines.length;\n\n if (display === \"calendar\" && parsed) {\n const monthLabel = `${MONTH_NAMES[parsed.m - 1]} ${parsed.y}`;\n ctx.lines.push({ text: `${label}: ${monthLabel}`, widgetId: widget.id, fieldId: bindKey });\n\n const navLine = options.hideHotkeys\n ? \"\"\n : `[<] [>]`;\n if (navLine) ctx.lines.push({ text: navLine, widgetId: widget.id });\n\n const calLines = buildCalendarLines(parsed.y, parsed.m, parsed.d);\n for (const cl of calLines) {\n ctx.lines.push({ text: cl, widgetId: widget.id });\n }\n\n if (!options.hideHotkeys) {\n if (!hotkeySet.has(\"<\")) {\n hotkeySet.add(\"<\");\n ctx.shortcuts.push({\n key: \"<\",\n label: `${label} prev month`,\n action: { type: \"data.set\", path: bindKey, value: shiftMonth(iso, -1) },\n });\n }\n if (!hotkeySet.has(\">\")) {\n hotkeySet.add(\">\");\n ctx.shortcuts.push({\n key: \">\",\n label: `${label} next month`,\n action: { type: \"data.set\", path: bindKey, value: shiftMonth(iso, 1) },\n });\n }\n }\n } else if (parsed) {\n // inline display\n const displayStr = formatDisplayDate(parsed.y, parsed.m, parsed.d);\n const lineLabel = options.hideHotkeys\n ? `${label}: ${displayStr}`\n : `${label}: [<] ${displayStr} [>]`;\n ctx.lines.push({ text: lineLabel, widgetId: widget.id, fieldId: bindKey });\n\n if (!options.hideHotkeys) {\n if (!hotkeySet.has(\"<\")) {\n hotkeySet.add(\"<\");\n ctx.shortcuts.push({\n key: \"<\",\n label: `${label} prev day`,\n action: { type: \"data.set\", path: bindKey, value: shiftDay(iso, -1) },\n });\n }\n if (!hotkeySet.has(\">\")) {\n hotkeySet.add(\">\");\n ctx.shortcuts.push({\n key: \">\",\n label: `${label} next day`,\n action: { type: \"data.set\", path: bindKey, value: shiftDay(iso, 1) },\n });\n }\n }\n }\n\n // Enter opens full-screen date picker\n if (!ctx.enterAction) {\n ctx.enterAction = {\n type: \"data.set\",\n path: \"__datePicker\",\n value: {\n bindPath: bindKey,\n currentISO: iso,\n returnScreenId: screenSpec.id,\n },\n };\n }\n\n ctx.inputFields.push({\n id: bindKey,\n value: iso,\n maxLength: 0,\n label,\n lineIndex: dateLineIndex,\n rows: 1,\n });\n\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n return;\n }\n\n if (widget.kind === \"row\") {\n const gap = Math.max(1, Number(widget.gap ?? 2));\n const parts: string[] = [];\n widget.items.forEach((item) => {\n if (item.kind === \"text\") {\n parts.push(interpolate(item.text, vars));\n return;\n }\n const renderedLabel = interpolate(item.label, vars);\n const hotkey = normalizeHotkey(item.hotkey);\n const lineLabel = options.hideHotkeys\n ? renderedLabel\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${renderedLabel}`\n : `[ ${renderedLabel} ]`;\n parts.push(lineLabel);\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: item.action,\n });\n }\n });\n ctx.lines.push({\n text: parts.join(\" \".repeat(gap)),\n widgetId: widget.id,\n });\n return;\n }\n\n if (widget.kind === \"table\") {\n const padCell = (text: string, width: number, align: \"left\" | \"right\" = \"left\"): string => {\n const truncated = text.length > width ? text.slice(0, width) : text;\n return align === \"right\" ? truncated.padStart(width) : truncated.padEnd(width);\n };\n\n const marginTop = Math.max(0, Number(widget.marginTop ?? 1));\n if (marginTop) pushSpacerLines(marginTop);\n\n const listValue = resolvePath(vars, widget.bind);\n let rows = Array.isArray(listValue) ? listValue : [];\n if (widget.whereEqualsPath) {\n rows = rows.filter((item) => {\n const raw = resolvePath(item, widget.whereEqualsPath || \"\");\n return raw === widget.whereEquals;\n });\n }\n const sortByPath = String(widget.sortByPath || \"\").trim();\n if (sortByPath) {\n const direction =\n String(widget.sortDirection || \"asc\").trim().toLowerCase() === \"desc\"\n ? -1\n : 1;\n rows = [...rows].sort((left, right) => {\n const leftValue = resolvePath(left, sortByPath);\n const rightValue = resolvePath(right, sortByPath);\n const primary = compareSortValues(leftValue, rightValue) * direction;\n if (primary !== 0) return primary;\n return compareSortValues(resolvePath(left, \"id\"), resolvePath(right, \"id\"));\n });\n }\n\n const cols = widget.columns;\n const separator = \"+\" + cols.map((c) => \"-\".repeat(c.width)).join(\"+\") + \"+\";\n const headerRow = \"|\" + cols.map((c) => padCell(c.header, c.width)).join(\"|\") + \"|\";\n\n ctx.lines.push({ text: separator, widgetId: widget.id });\n ctx.lines.push({ text: headerRow, widgetId: widget.id });\n ctx.lines.push({ text: separator, widgetId: widget.id });\n\n if (!rows.length) {\n const emptyText = widget.emptyText || \"(no rows)\";\n const totalInner = cols.reduce((sum, c) => sum + c.width, 0) + cols.length - 1;\n const paddedEmpty = emptyText.length > totalInner ? emptyText.slice(0, totalInner) : emptyText.padEnd(totalInner);\n ctx.lines.push({ text: \"|\" + paddedEmpty + \"|\", widgetId: widget.id });\n ctx.lines.push({ text: separator, widgetId: widget.id });\n const marginBottom = Math.max(0, Number(widget.marginBottom ?? 1));\n if (marginBottom) pushSpacerLines(marginBottom);\n return;\n }\n\n const maxVisible = Math.max(1, Number(widget.height) || 10);\n const tableScrollable = rows.length > maxVisible;\n const tableOffset = Math.max(0, Math.min(options.listScrollOffsets?.[widget.id] ?? 0, rows.length - maxVisible));\n const visibleRows = rows.slice(tableOffset, tableOffset + maxVisible);\n\n if (tableScrollable) {\n ctx.lines.push({ text: tableOffset > 0 ? `\\u2191 ${tableOffset} more` : \"\", widgetId: widget.id });\n }\n\n visibleRows.forEach((item, sliceIndex) => {\n const index = tableOffset + sliceIndex;\n const fields: Record<string, string> = {};\n Object.entries(widget.rowActionFields || {}).forEach(([fieldId, valuePath]) => {\n const raw = resolvePath(item, String(valuePath || \"\").trim());\n fields[String(fieldId)] = raw == null ? \"\" : String(raw);\n });\n const rowActionField = String(widget.rowActionField || \"\").trim();\n if (rowActionField) {\n const valuePath = String(widget.rowActionValuePath || \"\").trim() || \"id\";\n const rawValue = resolvePath(item, valuePath);\n fields[rowActionField] = rawValue == null ? \"\" : String(rawValue);\n }\n const hasFields = Object.keys(fields).length > 0;\n const rowAction = widget.rowAction;\n\n const cellTexts = cols.map((c) => {\n const raw = resolvePath(item, c.path);\n return padCell(raw == null ? \"\" : String(raw), c.width, c.align);\n });\n\n ctx.lines.push({\n text: \"|\" + cellTexts.join(\"|\") + \"|\",\n widgetId: widget.id,\n selectable: Boolean(rowAction),\n target: rowAction?.type === \"nav.goto\" ? rowAction.target : undefined,\n action: rowAction && rowAction.type !== \"nav.goto\" ? rowAction : undefined,\n fields: hasFields ? fields : undefined,\n });\n });\n\n // Pad to stable height: always emit exactly maxVisible data-row slots\n const dataRowsEmitted = visibleRows.length;\n for (let pad = dataRowsEmitted; pad < maxVisible; pad++) {\n ctx.lines.push({ text: \"\", widgetId: widget.id });\n }\n\n if (tableScrollable) {\n const belowCount = rows.length - tableOffset - visibleRows.length;\n ctx.lines.push({ text: belowCount > 0 ? `\\u2193 ${belowCount} more` : \"\", widgetId: widget.id });\n }\n\n ctx.lines.push({ text: separator, widgetId: widget.id });\n\n if (rows.length > maxVisible) {\n ctx.listScrollInfo![widget.id] = { totalRows: rows.length, visibleRows: visibleRows.length, offset: tableOffset };\n }\n const marginBottom = Math.max(0, Number(widget.marginBottom ?? 1));\n if (marginBottom) pushSpacerLines(marginBottom);\n return;\n }\n\n if (widget.kind === \"list\") {\n const marginTop = Math.max(0, Number(widget.marginTop ?? 1));\n if (marginTop) pushSpacerLines(marginTop);\n const listValue = resolvePath(vars, widget.bind);\n let rows = Array.isArray(listValue) ? listValue : [];\n if (widget.whereEqualsPath) {\n rows = rows.filter((item) => {\n const raw = resolvePath(item, widget.whereEqualsPath || \"\");\n return raw === widget.whereEquals;\n });\n }\n const sortByPath = String(widget.sortByPath || \"\").trim();\n if (sortByPath) {\n const direction =\n String(widget.sortDirection || \"asc\").trim().toLowerCase() === \"desc\"\n ? -1\n : 1;\n rows = [...rows].sort((left, right) => {\n const leftValue = resolvePath(left, sortByPath);\n const rightValue = resolvePath(right, sortByPath);\n const primary = compareSortValues(leftValue, rightValue) * direction;\n if (primary !== 0) return primary;\n return compareSortValues(resolvePath(left, \"id\"), resolvePath(right, \"id\"));\n });\n }\n if (!rows.length) {\n ctx.lines.push({\n text: widget.emptyText || \"(no rows)\",\n widgetId: widget.id,\n });\n const marginBottom = Math.max(0, Number(widget.marginBottom ?? 1));\n if (marginBottom) pushSpacerLines(marginBottom);\n return;\n }\n const listMaxVisible = Math.max(1, Number(widget.height) || 10);\n const listScrollable = rows.length > listMaxVisible;\n const listOffset = Math.max(0, Math.min(options.listScrollOffsets?.[widget.id] ?? 0, rows.length - listMaxVisible));\n const listVisibleRows = rows.slice(listOffset, listOffset + listMaxVisible);\n\n if (listScrollable) {\n ctx.lines.push({ text: listOffset > 0 ? `\\u2191 ${listOffset} more` : \"\", widgetId: widget.id });\n }\n\n listVisibleRows.forEach((item, sliceIndex) => {\n const index = listOffset + sliceIndex;\n const fields: Record<string, string> = {};\n Object.entries(widget.rowActionFields || {}).forEach(([fieldId, valuePath]) => {\n const raw = resolvePath(item, String(valuePath || \"\").trim());\n fields[String(fieldId)] = raw == null ? \"\" : String(raw);\n });\n const rowActionField = String(widget.rowActionField || \"\").trim();\n if (rowActionField) {\n const valuePath = String(widget.rowActionValuePath || \"\").trim() || \"id\";\n const rawValue = resolvePath(item, valuePath);\n fields[rowActionField] = rawValue == null ? \"\" : String(rawValue);\n }\n const hasFields = Object.keys(fields).length > 0;\n const rowAction = widget.rowAction;\n const lineIndex = ctx.lines.length;\n ctx.lines.push({\n text: interpolate(widget.rowTemplate, {\n ...vars,\n item,\n index: index + 1,\n }),\n widgetId: widget.id,\n selectable: Boolean(rowAction),\n target: rowAction?.type === \"nav.goto\" ? rowAction.target : undefined,\n action:\n rowAction && rowAction.type !== \"nav.goto\" ? rowAction : undefined,\n fields: hasFields ? fields : undefined,\n });\n\n // Add actionLine for clickable rows\n if (rowAction) {\n ctx.actionLines.push({\n index: lineIndex,\n selectable: true,\n target: rowAction.type === \"nav.goto\" ? rowAction.target : undefined,\n action: rowAction.type !== \"nav.goto\" ? rowAction : undefined,\n fields: hasFields ? fields : undefined,\n });\n }\n });\n\n // Pad to stable height: always emit exactly listMaxVisible data-row slots\n const listDataRowsEmitted = listVisibleRows.length;\n for (let pad = listDataRowsEmitted; pad < listMaxVisible; pad++) {\n ctx.lines.push({ text: \"\", widgetId: widget.id });\n }\n\n if (listScrollable) {\n const listBelowCount = rows.length - listOffset - listVisibleRows.length;\n ctx.lines.push({ text: listBelowCount > 0 ? `\\u2193 ${listBelowCount} more` : \"\", widgetId: widget.id });\n }\n\n if (rows.length > listMaxVisible) {\n ctx.listScrollInfo![widget.id] = { totalRows: rows.length, visibleRows: listVisibleRows.length, offset: listOffset };\n }\n const marginBottom = Math.max(0, Number(widget.marginBottom ?? 1));\n if (marginBottom) pushSpacerLines(marginBottom);\n }\n });\n return ctx;\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nexport type CliConfig = {\n webOrigin: string;\n terminalUrl: string;\n firebaseProjectId: string;\n idToken?: string;\n tokenExp?: number;\n appCheckToken?: string;\n};\n\nconst defaultWebOrigin = process.env.BLO_WEB_ORIGIN || \"https://buildless.online\";\nconst defaultTerminalUrl = process.env.BLO_TERMINAL_URL || \"https://buildless.online\";\nconst defaultProjectId =\n process.env.BLO_FIREBASE_PROJECT_ID || process.env.VITE_FIREBASE_PROJECT_ID || \"buildless-online\";\n\nconst resolveConfigPath = (): string => {\n if (process.env.BLO_CONFIG_PATH) return process.env.BLO_CONFIG_PATH;\n const home = os.homedir();\n const configDir = process.env.XDG_CONFIG_HOME || path.join(home, \".config\");\n return path.join(configDir, \"blo\", \"cli.json\");\n};\n\nexport const loadConfig = (): { path: string; config: CliConfig } => {\n const configPath = resolveConfigPath();\n const defaults: CliConfig = {\n webOrigin: defaultWebOrigin,\n terminalUrl: defaultTerminalUrl,\n firebaseProjectId: defaultProjectId,\n };\n\n if (!fs.existsSync(configPath)) {\n return { path: configPath, config: defaults };\n }\n\n try {\n const raw = fs.readFileSync(configPath, \"utf8\");\n const parsed = JSON.parse(raw) as Partial<CliConfig>;\n return {\n path: configPath,\n config: {\n ...defaults,\n ...parsed,\n },\n };\n } catch (err) {\n process.stderr.write(`Warning: failed to parse ${configPath}, using defaults: ${err instanceof Error ? err.message : String(err)}\\n`);\n return { path: configPath, config: defaults };\n }\n};\n\nexport const saveConfig = (configPath: string, config: CliConfig): void => {\n const dir = path.dirname(configPath);\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 0o600 });\n};\n"],"mappings":"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","names":["useEffect","useState","Box","Text","URL","URL","body","useEffect","useMemo","useRef","useState","Box","Text","useInput","useState","useState","useMemo","path","marginBottom","useMemo","jsx","jsxs","useState","useRef","useEffect","useMemo","activeField","useInput","Box","Text","jsx","jsxs","useState","useEffect","Box","Text","jsx","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/app.tsx","../src/auth.ts","../src/log.ts","../src/firestore.ts","../src/ui/app-search.tsx","../src/ui/runner.tsx","../src/ai.ts","../src/ui/useRunnerSession.ts","../src/ui/useRunnerRenderSource.ts","../../shared/src/screen-runtime/parsing/fieldParser.ts","../../shared/src/screen-runtime/state/pathUtils.ts","../../shared/src/screen-runtime/actions/actionBuilder.ts","../../shared/src/screen-runtime/rendering/widgetHelpers.ts","../../shared/src/screen-runtime/rendering/screenRenderer.ts","../src/config.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { render } from \"ink\";\nimport { App } from \"./app.js\";\nimport { loadConfig, saveConfig, type CliConfig } from \"./config.js\";\nimport { isTokenValid, startExternalLogin, decodeJwtPayload } from \"./auth.js\";\nimport { log, setVerbose } from \"./log.js\";\n\nconst ensureProjectId = (config: CliConfig): void => {\n if (!config.firebaseProjectId) {\n throw new Error(\n \"Could not determine project. Please reinstall: npm install -g buildless-cli\"\n );\n }\n};\n\nconst runLogin = async (config: CliConfig, configPath: string): Promise<CliConfig> => {\n log(`Starting login flow via ${config.webOrigin}/cli-auth`);\n const result = await startExternalLogin({ webOrigin: config.webOrigin });\n const payload = decodeJwtPayload(result.token);\n const uid = payload?.user_id ?? payload?.sub ?? \"unknown\";\n log(`Login successful: uid=${uid}, exp=${result.exp}, appCheck=${result.appCheckToken ? \"yes\" : \"no\"}`);\n const next: CliConfig = {\n ...config,\n idToken: result.token,\n tokenExp: result.exp ?? undefined,\n appCheckToken: result.appCheckToken,\n };\n saveConfig(configPath, next);\n log(`Config saved to ${configPath}`);\n return next;\n};\n\nconst program = new Command();\nprogram\n .name(\"blo\")\n .description(\"BLO terminal client\")\n .version(\"0.1.0\")\n .option(\"-v, --verbose\", \"Enable verbose debug output\")\n .hook(\"preAction\", () => {\n if (program.opts().verbose) {\n setVerbose(true);\n }\n });\n\nprogram\n .command(\"login\")\n .description(\"Authenticate via external browser\")\n .action(async () => {\n const { config, path } = loadConfig();\n log(`Config loaded from ${path}`);\n ensureProjectId(config);\n const next = await runLogin(config, path);\n process.stdout.write(`Logged in for project ${next.firebaseProjectId}.\\n`);\n });\n\nconst runAction = async (options: { query?: string }) => {\n process.stdout.write(\"\\x1b[2J\\x1b[H\");\n const { config, path } = loadConfig();\n log(`Config loaded from ${path}`);\n log(`Project: ${config.firebaseProjectId}`);\n log(`Terminal URL: ${config.terminalUrl}`);\n log(`Web origin: ${config.webOrigin}`);\n ensureProjectId(config);\n\n let effective = config;\n if (!isTokenValid(config.idToken, config.tokenExp ?? null)) {\n log(\"Token expired or missing, starting login\");\n effective = await runLogin(config, path);\n } else {\n const payload = decodeJwtPayload(config.idToken || \"\");\n const uid = payload?.user_id ?? payload?.sub ?? \"unknown\";\n log(`Token valid: uid=${uid}, expires=${config.tokenExp ? new Date(config.tokenExp * 1000).toISOString() : \"unknown\"}`);\n }\n\n log(`Rendering app with query=${options.query || \"(none)\"}`);\n const { waitUntilExit } = render(\n <App\n config={effective}\n idToken={effective.idToken || \"\"}\n initialQuery={options.query}\n onExit={() => process.exit(0)}\n />\n );\n await waitUntilExit();\n};\n\nprogram\n .command(\"run\")\n .description(\"Search and run a published app\")\n .option(\"-q, --query <query>\", \"Initial search query\")\n .action(runAction);\n\nprogram\n .command(\"list\")\n .description(\"List published apps (interactive)\")\n .option(\"-q, --query <query>\", \"Initial search query\")\n .action(runAction);\n\nconst main = async () => {\n if (process.argv.length <= 2) {\n await program.parseAsync([process.argv[0], process.argv[1], \"run\"]);\n return;\n }\n await program.parseAsync(process.argv);\n};\n\nmain().catch((err) => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n","import React, { useEffect, useState } from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { CliConfig } from \"./config.js\";\nimport { fetchRunnableAppsViaServer, type RunnableApp } from \"./firestore.js\";\nimport { AppSearch } from \"./ui/app-search.js\";\nimport { Runner } from \"./ui/runner.js\";\nimport { log } from \"./log.js\";\n\nexport const App: React.FC<{\n config: CliConfig;\n idToken: string;\n initialQuery?: string;\n onExit: () => void;\n}> = ({ config, idToken, initialQuery, onExit }) => {\n const [apps, setApps] = useState<RunnableApp[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedApp, setSelectedApp] = useState<RunnableApp | null>(null);\n\n useEffect(() => {\n let mounted = true;\n const load = async () => {\n try {\n setLoading(true);\n log(`Loading apps from ${config.terminalUrl}`);\n const results = await fetchRunnableAppsViaServer({\n terminalUrl: config.terminalUrl,\n idToken,\n query: initialQuery,\n });\n if (!mounted) return;\n log(`Loaded ${results.length} apps`);\n setApps(results);\n setError(null);\n } catch (err) {\n if (!mounted) return;\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n if (mounted) setLoading(false);\n }\n };\n void load();\n return () => {\n mounted = false;\n };\n }, [config.firebaseProjectId, config.terminalUrl, idToken, initialQuery]);\n\n if (error) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\">{error}</Text>\n <Text dimColor>Tip: Set BLO_DEBUG=1 for detailed logs.</Text>\n <Text>Press Ctrl+C to exit.</Text>\n </Box>\n );\n }\n\n if (loading) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">Loading apps from {config.terminalUrl}...</Text>\n </Box>\n );\n }\n\n if (apps.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"yellow\">No apps found.</Text>\n <Text dimColor>\n {initialQuery\n ? `No apps matched \"${initialQuery}\". Try without a query filter.`\n : \"Your account has no projects and no published apps are available.\"}\n </Text>\n <Text>Press Ctrl+C to exit.</Text>\n </Box>\n );\n }\n\n if (!selectedApp) {\n return (\n <AppSearch\n apps={apps}\n initialQuery={initialQuery}\n onSelect={(app) => {\n log(`Selected app: ${app.projectId} (version=${app.versionId}, source=${app.versionSource})`);\n setSelectedApp(app);\n }}\n onExit={onExit}\n />\n );\n }\n\n return (\n <Runner\n projectId={selectedApp.projectId}\n versionId={selectedApp.versionId}\n terminalUrl={config.terminalUrl}\n idToken={idToken}\n firebaseProjectId={config.firebaseProjectId}\n appCheckToken={config.appCheckToken}\n onBackToApps={() => {\n log(\"Returning to app list\");\n setSelectedApp(null);\n }}\n onExit={onExit}\n />\n );\n};\n","import { createServer } from \"node:http\";\nimport crypto from \"node:crypto\";\nimport { URL } from \"node:url\";\nimport open from \"open\";\nimport { log } from \"./log.js\";\n\nexport type LoginResult = { token: string; exp: number | null; appCheckToken?: string };\n\ntype LoginOptions = {\n webOrigin: string;\n};\n\nexport const decodeJwtPayload = (token: string): Record<string, unknown> | null => {\n const parts = token.split(\".\");\n if (parts.length < 2) return null;\n try {\n const payload = Buffer.from(parts[1], \"base64url\").toString(\"utf8\");\n return JSON.parse(payload);\n } catch {\n return null;\n }\n};\n\nexport const getTokenExp = (token: string): number | null => {\n const payload = decodeJwtPayload(token);\n if (!payload || typeof payload.exp !== \"number\") return null;\n return payload.exp;\n};\n\nexport const isTokenValid = (token?: string, exp?: number | null): boolean => {\n if (!token) return false;\n if (exp == null) return true;\n const now = Math.floor(Date.now() / 1000);\n return exp - 30 > now;\n};\n\nconst LOGIN_TIMEOUT_MS = 120_000;\n\nexport const startExternalLogin = async (options: LoginOptions): Promise<LoginResult> => {\n const state = crypto.randomBytes(16).toString(\"hex\");\n\n const server = createServer();\n const result = await new Promise<LoginResult>((resolve, reject) => {\n let settled = false;\n const timeout = setTimeout(() => {\n if (settled) return;\n settled = true;\n server.close();\n reject(new Error(\"Login timed out after 2 minutes. Please try again.\"));\n }, LOGIN_TIMEOUT_MS);\n\n server.on(\"request\", (req, res) => {\n if (!req.url) return;\n const url = new URL(req.url, \"http://localhost\");\n if (url.pathname !== \"/callback\") {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not found\");\n return;\n }\n if (settled) {\n res.writeHead(409, { \"Content-Type\": \"text/plain\" });\n res.end(\"Login already handled. You can close this window.\");\n return;\n }\n const token = url.searchParams.get(\"token\") || \"\";\n const returnedState = url.searchParams.get(\"state\") || \"\";\n const appCheckToken = url.searchParams.get(\"appCheckToken\") || undefined;\n if (!token || returnedState !== state) {\n settled = true;\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\n res.end(\"Invalid login response. You can close this window.\");\n clearTimeout(timeout);\n log(`Login callback failed: token=${token ? \"present\" : \"missing\"}, state=${returnedState === state ? \"match\" : \"mismatch\"}`);\n reject(new Error(\"Login failed: invalid callback. Make sure you completed the login in your browser.\"));\n server.close();\n return;\n }\n\n settled = true;\n res.writeHead(200, { \"Content-Type\": \"text/plain\" });\n res.end(\"Login complete. You can close this window.\");\n clearTimeout(timeout);\n const exp = getTokenExp(token);\n log(`Login callback received: exp=${exp}, appCheck=${appCheckToken ? \"yes\" : \"no\"}`);\n resolve({ token, exp, appCheckToken });\n server.close();\n });\n\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n if (!address || typeof address === \"string\") {\n clearTimeout(timeout);\n reject(new Error(\"Failed to start local login server.\"));\n return;\n }\n const callbackUrl = `http://127.0.0.1:${address.port}/callback`;\n const loginUrl = new URL(\"/cli-auth\", options.webOrigin);\n loginUrl.searchParams.set(\"redirect_uri\", callbackUrl);\n loginUrl.searchParams.set(\"state\", state);\n log(`Login server listening on port ${address.port}`);\n log(`Opening browser: ${loginUrl.toString()}`);\n process.stderr.write(\"Opening browser for login...\\n\");\n void open(loginUrl.toString());\n });\n });\n\n return result;\n};\n","let verbose = process.env.BLO_DEBUG === \"1\" || process.env.BLO_DEBUG === \"true\";\n\nexport const setVerbose = (enabled: boolean): void => {\n verbose = enabled;\n};\n\nexport const log = (message: string): void => {\n if (verbose) {\n process.stderr.write(`[blo] ${message}\\n`);\n }\n};\n","import { decodeJwtPayload } from \"./auth.js\";\nimport { log } from \"./log.js\";\n\nexport type RunnableApp = {\n id: string;\n projectId: string;\n versionId: string;\n versionSource: \"published\" | \"latest\" | \"store\";\n publishedVersionId?: string;\n name?: string;\n displayName?: string;\n tagline?: string;\n description?: string;\n accessTier?: string;\n authorName?: string;\n ownerDisplayName?: string;\n appSource?: \"user\" | \"published\";\n};\n\nconst resolveUidFromToken = (idToken: string): string | null => {\n const payload = decodeJwtPayload(idToken);\n if (!payload) return null;\n const uid = payload.user_id ?? payload.sub;\n return typeof uid === \"string\" && uid.trim() ? uid.trim() : null;\n};\n\nconst fromFirestoreValue = (value: any): any => {\n if (value == null || typeof value !== \"object\") return null;\n if (\"stringValue\" in value) return String(value.stringValue);\n if (\"booleanValue\" in value) return Boolean(value.booleanValue);\n if (\"integerValue\" in value) return Number(value.integerValue);\n if (\"doubleValue\" in value) return Number(value.doubleValue);\n if (\"timestampValue\" in value) return String(value.timestampValue);\n if (\"referenceValue\" in value) return String(value.referenceValue);\n if (\"mapValue\" in value) {\n const fields = value.mapValue?.fields || {};\n const output: Record<string, any> = {};\n for (const [key, entry] of Object.entries(fields)) {\n output[key] = fromFirestoreValue(entry);\n }\n return output;\n }\n if (\"arrayValue\" in value) {\n const values = value.arrayValue?.values || [];\n return values.map(fromFirestoreValue);\n }\n if (\"nullValue\" in value) return null;\n return null;\n};\n\nexport const parseDocument = (doc: any): Record<string, any> => {\n const fields = doc?.fields || {};\n const output: Record<string, any> = {};\n for (const [key, entry] of Object.entries(fields)) {\n output[key] = fromFirestoreValue(entry);\n }\n return output;\n};\n\nexport const firestoreDocsBase = (projectId: string): string =>\n `https://firestore.googleapis.com/v1/projects/${encodeURIComponent(projectId)}/databases/(default)/documents`;\n\nexport const parseRunQueryDocs = (rows: Array<{ document?: any }>): any[] =>\n rows.map((row) => row.document).filter(Boolean);\n\nexport const extractDocIdFromName = (name?: string): string | undefined => {\n if (!name) return undefined;\n const chunks = String(name).split(\"/\");\n return chunks[chunks.length - 1] || undefined;\n};\n\nexport const authHeaders = (idToken: string, appCheckToken?: string): Record<string, string> => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${idToken}`,\n };\n if (appCheckToken) {\n headers[\"X-Firebase-AppCheck\"] = appCheckToken;\n }\n return headers;\n};\n\nconst fetchPublishedApps = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n}): Promise<RunnableApp[]> => {\n const { projectId, idToken, appCheckToken } = opts;\n const endpoint = `${firestoreDocsBase(projectId)}:runQuery`;\n const body = {\n structuredQuery: {\n from: [{ collectionId: \"publishedApps\" }],\n where: {\n fieldFilter: {\n field: { fieldPath: \"isPublished\" },\n op: \"EQUAL\",\n value: { booleanValue: true },\n },\n },\n limit: 250,\n },\n };\n\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...authHeaders(idToken, appCheckToken),\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const text = await response.text();\n log(`Failed to fetch published apps (${response.status}): ${text}`);\n throw new Error(`Failed to fetch published apps (${response.status})`);\n }\n\n const rows = (await response.json()) as Array<{ document?: any }>;\n const mapped: Array<RunnableApp | null> = parseRunQueryDocs(rows).map((doc) => {\n const data = parseDocument(doc);\n const projectIdFromDoc = String(data.projectId || \"\").trim();\n const publishedVersionId = String(data.publishedVersionId || \"\").trim();\n if (!projectIdFromDoc || !publishedVersionId) return null;\n return {\n id: projectIdFromDoc,\n projectId: projectIdFromDoc,\n versionId: publishedVersionId,\n versionSource: \"store\" as const,\n publishedVersionId,\n name: data.name ? String(data.name) : undefined,\n displayName: data.displayName ? String(data.displayName) : undefined,\n tagline: data.tagline ? String(data.tagline) : undefined,\n description: data.description ? String(data.description) : undefined,\n accessTier: data.accessTier ? String(data.accessTier) : undefined,\n authorName: data.authorName ? String(data.authorName) : undefined,\n ownerDisplayName: data.ownerDisplayName ? String(data.ownerDisplayName) : undefined,\n appSource: \"published\" as const,\n };\n });\n return mapped.filter((entry): entry is RunnableApp => entry !== null);\n};\n\nconst fetchUserProjectIds = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n uid: string;\n}): Promise<string[]> => {\n const { projectId, idToken, appCheckToken, uid } = opts;\n const endpoint = `${firestoreDocsBase(projectId)}/users/${encodeURIComponent(uid)}`;\n const response = await fetch(endpoint, {\n headers: authHeaders(idToken, appCheckToken),\n });\n\n if (response.status === 404) return [];\n if (!response.ok) {\n const text = await response.text();\n log(`Failed to fetch user profile (${response.status}): ${text}`);\n throw new Error(`Failed to fetch user profile (${response.status})`);\n }\n\n const doc = (await response.json()) as any;\n const data = parseDocument(doc);\n const projectAccess =\n data.projectAccess && typeof data.projectAccess === \"object\"\n ? (data.projectAccess as Record<string, unknown>)\n : {};\n return Object.keys(projectAccess);\n};\n\nconst fetchProjectDoc = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n targetProjectId: string;\n}): Promise<Record<string, any> | null> => {\n const { projectId, idToken, appCheckToken, targetProjectId } = opts;\n const endpoint = `${firestoreDocsBase(projectId)}/projects/${encodeURIComponent(targetProjectId)}`;\n const response = await fetch(endpoint, {\n headers: authHeaders(idToken, appCheckToken),\n });\n\n if (response.status === 404) return null;\n if (!response.ok) {\n const text = await response.text();\n log(`Failed to fetch project ${targetProjectId} (${response.status}): ${text}`);\n throw new Error(`Failed to fetch project ${targetProjectId} (${response.status})`);\n }\n\n const doc = (await response.json()) as any;\n return parseDocument(doc);\n};\n\nconst fetchLatestVersionId = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n targetProjectId: string;\n}): Promise<string | null> => {\n const { projectId, idToken, appCheckToken, targetProjectId } = opts;\n const endpoint = `${firestoreDocsBase(projectId)}/projects/${encodeURIComponent(\n targetProjectId\n )}:runQuery`;\n\n const tryQueries = [\n {\n structuredQuery: {\n from: [{ collectionId: \"versions\" }],\n orderBy: [{ field: { fieldPath: \"updatedAt\" }, direction: \"DESCENDING\" }],\n limit: 1,\n },\n },\n {\n structuredQuery: {\n from: [{ collectionId: \"versions\" }],\n orderBy: [{ field: { fieldPath: \"createdAt\" }, direction: \"DESCENDING\" }],\n limit: 1,\n },\n },\n {\n structuredQuery: {\n from: [{ collectionId: \"versions\" }],\n limit: 1,\n },\n },\n ];\n\n for (const body of tryQueries) {\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...authHeaders(idToken, appCheckToken),\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n continue;\n }\n\n const rows = (await response.json()) as Array<{ document?: any }>;\n const doc = parseRunQueryDocs(rows)[0];\n const docId = extractDocIdFromName(doc?.name);\n if (docId) return docId;\n }\n\n return null;\n};\n\nconst mapProjectToRunnableApp = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n targetProjectId: string;\n}): Promise<RunnableApp | null> => {\n const { projectId, idToken, appCheckToken, targetProjectId } = opts;\n const projectDoc = await fetchProjectDoc({ projectId, idToken, appCheckToken, targetProjectId });\n if (!projectDoc) return null;\n\n const publishedVersionId = String(projectDoc.publishedVersionId || \"\").trim();\n const latestVersionId =\n publishedVersionId ||\n (await fetchLatestVersionId({ projectId, idToken, appCheckToken, targetProjectId })) ||\n \"\";\n const versionId = String(latestVersionId || \"\").trim();\n\n if (!versionId) return null;\n\n const ownerData =\n projectDoc.ownerData && typeof projectDoc.ownerData === \"object\"\n ? (projectDoc.ownerData as Record<string, unknown>)\n : {};\n\n return {\n id: targetProjectId,\n projectId: targetProjectId,\n versionId,\n versionSource: publishedVersionId ? \"published\" : \"latest\",\n publishedVersionId: publishedVersionId || undefined,\n name: projectDoc.name ? String(projectDoc.name) : undefined,\n displayName: projectDoc.displayName ? String(projectDoc.displayName) : undefined,\n description: projectDoc.description ? String(projectDoc.description) : undefined,\n accessTier: projectDoc.accessTier ? String(projectDoc.accessTier) : undefined,\n authorName: projectDoc.authorName ? String(projectDoc.authorName) : undefined,\n ownerDisplayName:\n (typeof ownerData.displayName === \"string\" ? ownerData.displayName : undefined) ||\n (projectDoc.owner ? String(projectDoc.owner) : undefined),\n appSource: \"user\" as const,\n };\n};\n\nconst fetchUserApps = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n}): Promise<RunnableApp[]> => {\n const uid = resolveUidFromToken(opts.idToken);\n if (!uid) {\n throw new Error(\"Failed to decode uid from Firebase ID token.\");\n }\n\n const projectIds = await fetchUserProjectIds({\n projectId: opts.projectId,\n idToken: opts.idToken,\n appCheckToken: opts.appCheckToken,\n uid,\n });\n\n if (!projectIds.length) return [];\n\n const results = await Promise.allSettled(\n projectIds.map((targetProjectId) =>\n mapProjectToRunnableApp({\n projectId: opts.projectId,\n idToken: opts.idToken,\n appCheckToken: opts.appCheckToken,\n targetProjectId,\n })\n )\n );\n\n const apps: RunnableApp[] = [];\n for (const result of results) {\n if (result.status === \"fulfilled\" && result.value) {\n apps.push(result.value);\n } else if (result.status === \"rejected\") {\n process.stderr.write(`Warning: failed to load a project: ${result.reason}\\n`);\n }\n }\n return apps;\n};\n\nexport const fetchRunnableAppsViaServer = async (opts: {\n terminalUrl: string;\n idToken: string;\n query?: string;\n}): Promise<RunnableApp[]> => {\n const { terminalUrl, idToken, query } = opts;\n const url = new URL(\"/api/apps\", terminalUrl);\n if (query) url.searchParams.set(\"q\", query);\n\n log(`Fetching apps: GET ${url.toString()}`);\n const response = await fetch(url.toString(), {\n headers: { Authorization: `Bearer ${idToken}` },\n });\n\n if (!response.ok) {\n let message: string | undefined;\n try {\n const body = await response.json() as { message?: string };\n message = body.message;\n } catch {\n // ignore parse errors\n }\n log(`Fetch apps failed: ${response.status} ${message || \"(no message)\"}`);\n if (response.status === 401) {\n throw new Error(\"Authentication failed. Try 'blo login' to re-authenticate.\");\n }\n if (response.status === 403 && message?.toLowerCase().includes(\"cli access\")) {\n const uid = resolveUidFromToken(idToken) || \"unknown\";\n throw new Error(`CLI access is not enabled for your account (uid: ${uid}). Contact an admin to enable it.`);\n }\n if (response.status >= 500) {\n throw new Error(`Server error (${response.status}). The terminal server may be having issues.`);\n }\n throw new Error(message || `Failed to fetch apps (${response.status})`);\n }\n\n const body = (await response.json()) as { ok?: boolean; apps?: RunnableApp[] };\n const apps = body.apps || [];\n log(`Fetched ${apps.length} apps`);\n return apps;\n};\n\nexport const fetchRunnableApps = async (opts: {\n projectId: string;\n idToken: string;\n appCheckToken?: string;\n query?: string;\n}): Promise<RunnableApp[]> => {\n const { projectId, idToken, appCheckToken, query } = opts;\n\n const userApps = await fetchUserApps({ projectId, idToken, appCheckToken });\n let publishedApps: RunnableApp[] = [];\n try {\n publishedApps = await fetchPublishedApps({ projectId, idToken, appCheckToken });\n } catch (err) {\n process.stderr.write(`Warning: failed to fetch published apps: ${err}\\n`);\n }\n\n const byProjectId = new Map<string, RunnableApp>();\n userApps.forEach((app) => {\n byProjectId.set(app.projectId, app);\n });\n publishedApps.forEach((app) => {\n if (!byProjectId.has(app.projectId)) {\n byProjectId.set(app.projectId, app);\n }\n });\n\n const allApps = Array.from(byProjectId.values()).sort((a, b) => {\n const aName = String(a.name || a.projectId).toLowerCase();\n const bName = String(b.name || b.projectId).toLowerCase();\n return aName.localeCompare(bName);\n });\n\n const term = (query || \"\").trim().toLowerCase();\n if (!term) return allApps;\n\n return allApps.filter((app) => filterApp(app, term));\n};\n\nexport const filterApp = (app: RunnableApp, term: string): boolean =>\n [\n app.projectId,\n app.displayName,\n app.name,\n app.tagline,\n app.description,\n app.authorName,\n app.ownerDisplayName,\n app.versionId,\n app.accessTier,\n ]\n .filter(Boolean)\n .some((field) => String(field).toLowerCase().includes(term));\n","import React, { useMemo, useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport { filterApp, type RunnableApp } from \"../firestore.js\";\n\ntype AppFilter = \"all\" | \"user\" | \"published\";\n\ntype Props = {\n apps: RunnableApp[];\n initialQuery?: string;\n onSelect: (app: RunnableApp) => void;\n onExit: () => void;\n};\n\nexport const AppSearch: React.FC<Props> = ({ apps, initialQuery, onSelect, onExit }) => {\n const [query, setQuery] = useState(initialQuery || \"\");\n const [selected, setSelected] = useState(0);\n const [appFilter, setAppFilter] = useState<AppFilter>(\"all\");\n\n const filtered = useMemo(() => {\n let result = apps;\n\n // Filter by app source - apps without appSource are treated as \"user\" apps (local projects)\n if (appFilter === \"user\") {\n result = result.filter((app) => !app.appSource || app.appSource === \"user\");\n } else if (appFilter === \"published\") {\n result = result.filter((app) => app.appSource === \"published\");\n }\n // \"all\" shows everything\n\n // Filter by search term\n const term = query.trim().toLowerCase();\n if (!term) return result;\n return result.filter((app) => filterApp(app, term));\n }, [apps, query, appFilter]);\n\n useInput((input, key) => {\n if (key.ctrl && input === \"c\") {\n onExit();\n return;\n }\n if (key.escape) {\n setQuery(\"\");\n setSelected(0);\n return;\n }\n if (input === \"m\" || input === \"M\") {\n setAppFilter(\"user\");\n setSelected(0);\n return;\n }\n if (input === \"p\" || input === \"P\") {\n setAppFilter(\"published\");\n setSelected(0);\n return;\n }\n if (input === \"a\" || input === \"A\") {\n setAppFilter(\"all\");\n setSelected(0);\n return;\n }\n if (key.upArrow) {\n setSelected((prev) => (filtered.length ? (prev - 1 + filtered.length) % filtered.length : 0));\n return;\n }\n if (key.downArrow) {\n setSelected((prev) => (filtered.length ? (prev + 1) % filtered.length : 0));\n return;\n }\n if (key.return) {\n const app = filtered[selected];\n if (app) onSelect(app);\n return;\n }\n if (key.backspace || key.delete) {\n setQuery((prev) => prev.slice(0, -1));\n setSelected(0);\n return;\n }\n if (input) {\n setQuery((prev) => prev + input);\n setSelected(0);\n }\n });\n\n const maxVisible = Math.max(3, Math.min(20, (process.stdout.rows || 24) - 6));\n const scrollOffset = Math.max(0, Math.min(selected - maxVisible + 1, filtered.length - maxVisible));\n const visible = filtered.slice(scrollOffset, scrollOffset + maxVisible);\n\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">BLO CLI Runner Apps</Text>\n <Text>Search apps: {query || \"(type to filter)\"}</Text>\n <Text>\n Filter:{\" \"}\n <Text color={appFilter === \"all\" ? \"green\" : \"gray\"}>A</Text>\n <Text color=\"gray\">ll | </Text>\n <Text color={appFilter === \"user\" ? \"green\" : \"gray\"}>M</Text>\n <Text color=\"gray\">y | </Text>\n <Text color={appFilter === \"published\" ? \"green\" : \"gray\"}>P</Text>\n <Text color=\"gray\">ublished</Text>\n </Text>\n <Text color=\"gray\">Enter = launch, Esc = clear, Ctrl+C = exit</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {visible.length === 0 ? (\n <Text>No runnable apps found.</Text>\n ) : (\n visible.map((app, index) => {\n const globalIndex = scrollOffset + index;\n const isSelected = globalIndex === selected;\n const label = app.displayName || app.name || app.projectId;\n const author = app.authorName || app.ownerDisplayName || \"Unknown\";\n const versionHint = `${app.versionSource}:${app.versionId}`;\n return (\n <Text key={app.id} color={isSelected ? \"green\" : undefined}>\n {isSelected ? \">\" : \" \"} {label} — {author} ({versionHint})\n </Text>\n );\n })\n )}\n {filtered.length > maxVisible && (\n <Text color=\"gray\">{scrollOffset + visible.length} of {filtered.length} apps</Text>\n )}\n </Box>\n </Box>\n );\n};\n","import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { AiMessage } from \"@blo/shared\";\nimport type { TerminalActionLine, TerminalShortcut } from \"@blo/shared/terminal\";\nimport { callUnifiedChat, loadLatestConversation, createConversation, appendMessage } from \"../ai.js\";\nimport { useRunnerSession } from \"./useRunnerSession.js\";\nimport { useRunnerRenderSource } from \"./useRunnerRenderSource.js\";\n\ntype Props = {\n projectId: string;\n versionId?: string;\n terminalUrl: string;\n idToken: string;\n firebaseProjectId: string;\n appCheckToken?: string;\n onBackToApps: () => void;\n onExit: () => void;\n};\n\ntype FieldValueMap = Record<string, string>;\n\nexport const Runner: React.FC<Props> = ({\n projectId,\n versionId,\n terminalUrl,\n idToken,\n firebaseProjectId,\n appCheckToken,\n onBackToApps,\n onExit,\n}) => {\n const { screen: rawScreen, error, connecting, sessionId, sendMessage } = useRunnerSession({\n projectId,\n versionId,\n terminalUrl,\n idToken,\n });\n\n const [listScrollOffsets, setListScrollOffsets] = useState<Record<string, number>>({});\n const { screen, listScrollInfo, lineWidgetIds } = useRunnerRenderSource(rawScreen, listScrollOffsets);\n\n const [inputMode, setInputMode] = useState(false);\n const [activeInputIndex, setActiveInputIndex] = useState(0);\n const [fieldValues, setFieldValues] = useState<FieldValueMap>({});\n\n // AI chat mode state\n const [aiMode, setAiMode] = useState(false);\n const [aiMessages, setAiMessages] = useState<AiMessage[]>([]);\n const [aiInput, setAiInput] = useState(\"\");\n const [aiLoading, setAiLoading] = useState(false);\n const aiRequestRef = useRef(0);\n const [aiConversationId, setAiConversationId] = useState<string | null>(null);\n const aiMessageSeqRef = useRef(0);\n const [aiHistoryLoading, setAiHistoryLoading] = useState(false);\n\n // Load existing conversation on mount\n useEffect(() => {\n let cancelled = false;\n const vid = versionId || \"published\";\n setAiHistoryLoading(true);\n loadLatestConversation({ firebaseProjectId, idToken, appCheckToken, projectId, versionId: vid })\n .then((result) => {\n if (cancelled) return;\n if (result) {\n setAiConversationId(result.conversationId);\n setAiMessages(result.messages);\n aiMessageSeqRef.current = result.messageCount;\n }\n })\n .catch(() => {})\n .finally(() => { if (!cancelled) setAiHistoryLoading(false); });\n return () => { cancelled = true; };\n }, [firebaseProjectId, idToken, appCheckToken, projectId, versionId]);\n\n const sendAiMessage = async (text: string) => {\n if (!text.trim() || aiLoading) return;\n const userMsg: AiMessage = { role: \"user\", text: text.trim() };\n const updatedMessages = [...aiMessages, userMsg];\n setAiMessages(updatedMessages);\n setAiInput(\"\");\n setAiLoading(true);\n const requestId = ++aiRequestRef.current;\n const vid = versionId || \"published\";\n const persistOpts = { firebaseProjectId, idToken, appCheckToken, projectId, versionId: vid };\n try {\n // Ensure we have a conversation\n let convoId = aiConversationId;\n if (!convoId) {\n convoId = await createConversation(persistOpts);\n setAiConversationId(convoId);\n }\n // Persist user message\n const userSeq = ++aiMessageSeqRef.current;\n appendMessage({ ...persistOpts, conversationId: convoId, role: \"user\", text: text.trim(), seq: userSeq }).catch(() => {});\n\n const response = await callUnifiedChat({\n firebaseProjectId,\n idToken,\n appCheckToken,\n payload: {\n projectId,\n versionId: vid,\n message: text.trim(),\n screenId: rawScreen?.screen,\n conversation: updatedMessages,\n },\n });\n if (requestId !== aiRequestRef.current) return;\n const newMessages: AiMessage[] = [];\n if (response.operations?.length) {\n for (const op of response.operations) {\n const isError = op.result && typeof op.result === \"object\" && \"error\" in (op.result as Record<string, unknown>);\n const summary = isError\n ? `${op.tool}: error - ${(op.result as Record<string, unknown>).error}`\n : `${op.tool}: OK`;\n const toolMsg: AiMessage = { role: \"tool\", text: summary, toolName: op.tool };\n newMessages.push(toolMsg);\n const toolSeq = ++aiMessageSeqRef.current;\n appendMessage({ ...persistOpts, conversationId: convoId!, role: \"tool\", text: summary, toolName: op.tool, seq: toolSeq }).catch(() => {});\n }\n }\n const assistantMsg: AiMessage = { role: \"assistant\", text: response.text };\n newMessages.push(assistantMsg);\n const assistantSeq = ++aiMessageSeqRef.current;\n appendMessage({ ...persistOpts, conversationId: convoId!, role: \"assistant\", text: response.text, seq: assistantSeq }).catch(() => {});\n\n setAiMessages((prev) => [...prev, ...newMessages]);\n } catch (err) {\n if (requestId !== aiRequestRef.current) return;\n const errMsg = err instanceof Error ? err.message : String(err);\n setAiMessages((prev) => [...prev, { role: \"assistant\", text: `Error: ${errMsg}` }]);\n } finally {\n if (requestId === aiRequestRef.current) setAiLoading(false);\n }\n };\n\n const inputFields = useMemo(() => {\n if (!screen) return [];\n if (screen.inputFields && screen.inputFields.length > 0) return screen.inputFields;\n if (screen.inputField) return [screen.inputField];\n return [];\n }, [screen]);\n\n const selectableLines = useMemo(() => {\n return (screen?.actionLines || [])\n .filter((line) => line.selectable && (line.target || line.aidAlias || line.action))\n .sort((a, b) => a.index - b.index);\n }, [screen?.actionLines]);\n\n const shortcutByKey = useMemo(() => {\n const map = new Map<string, TerminalShortcut>();\n for (const s of screen?.shortcuts || []) {\n const k = String(s.key || \"\").trim().toLowerCase();\n if (k) map.set(k, s);\n }\n return map;\n }, [screen?.shortcuts]);\n\n const [selectedLineIndex, setSelectedLineIndex] = useState(0);\n\n useEffect(() => {\n setSelectedLineIndex(0);\n setListScrollOffsets({});\n }, [screen?.sessionId]);\n\n useEffect(() => {\n if (selectableLines.length > 0) {\n setSelectedLineIndex((prev) => Math.min(prev, selectableLines.length - 1));\n }\n }, [selectableLines.length]);\n\n useEffect(() => {\n if (!inputFields.length) {\n setInputMode(false);\n setActiveInputIndex(0);\n return;\n }\n setActiveInputIndex((prev) => Math.min(prev, inputFields.length - 1));\n }, [inputFields.length]);\n\n useEffect(() => {\n if (!inputFields.length) return;\n setFieldValues((prev) => {\n const next = { ...prev };\n for (const field of inputFields) {\n const isNonEditable = (field.maxLength ?? 0) === 0;\n if (isNonEditable || next[field.id] === undefined) {\n next[field.id] = String(field.value || \"\");\n }\n }\n return next;\n });\n }, [inputFields]);\n\n const collectFields = (extra?: Record<string, string>) => {\n return { ...fieldValues, ...extra };\n };\n\n const applySelectedLine = (line: TerminalActionLine) => {\n const fields = collectFields(line.fields);\n if (line.target) {\n sendMessage({ type: \"nav\", target: line.target, fields });\n return;\n }\n if (line.aidAlias) {\n sendMessage({ type: \"aid\", key: line.aidAlias, fields });\n return;\n }\n if (line.action) {\n sendMessage({ type: \"action\", action: line.action, fields });\n }\n };\n\n const executeShortcut = (shortcut: TerminalShortcut) => {\n const fields = collectFields(shortcut.fields);\n if (shortcut.target) {\n sendMessage({ type: \"nav\", target: shortcut.target, fields });\n return;\n }\n if (shortcut.action) {\n sendMessage({ type: \"action\", action: shortcut.action, fields });\n return;\n }\n if (shortcut.aidAlias) {\n sendMessage({ type: \"aid\", key: shortcut.aidAlias, fields });\n }\n };\n\n const toggleActiveCheckbox = () => {\n const activeField = inputFields[activeInputIndex];\n if (!activeField) return;\n const toggleAction = activeField.action ?? { type: \"data.toggleFlag\" as const, path: activeField.id };\n sendMessage({ type: \"action\", action: toggleAction, fields: collectFields() });\n };\n\n const activeField = inputFields[activeInputIndex] ?? null;\n const isEditable = activeField != null && (activeField.maxLength ?? 0) > 0;\n const isMultiLine = isEditable && (activeField.rows ?? 1) > 1;\n\n useInput((input, key) => {\n if (key.ctrl && input === \"c\") {\n onExit();\n return;\n }\n\n if (!screen) return;\n\n // -- AI chat mode --\n if (aiMode) {\n if (key.escape) {\n setAiMode(false);\n return;\n }\n if (key.backspace || key.delete) {\n setAiInput((prev) => prev.slice(0, -1));\n return;\n }\n if (key.return && !aiLoading) {\n void sendAiMessage(aiInput);\n return;\n }\n if (input && !key.ctrl && !key.meta) {\n setAiInput((prev) => prev + input);\n }\n return;\n }\n\n // -- Input mode (typing into a text field) --\n if (inputMode) {\n if (!activeField) return;\n\n if (key.escape) {\n sendMessage({ type: \"aid\", key: \"B\", fields: fieldValues });\n setInputMode(false);\n return;\n }\n\n // Non-editable field (checkbox/select/radio/number/date): arrow keys cycle fields, Enter/Space toggle\n if (!isEditable) {\n if (key.tab || input === \"\\t\" || key.downArrow || key.rightArrow) {\n setActiveInputIndex((prev) => (prev + 1) % inputFields.length);\n return;\n }\n if (key.upArrow || key.leftArrow) {\n setActiveInputIndex((prev) =>\n inputFields.length ? (prev - 1 + inputFields.length) % inputFields.length : 0\n );\n return;\n }\n if (key.return || input === \" \") {\n toggleActiveCheckbox();\n return;\n }\n // Pass through to shortcut handling below\n if (input) {\n const shortcut = shortcutByKey.get(input.toLowerCase());\n if (shortcut) {\n executeShortcut(shortcut);\n return;\n }\n }\n return;\n }\n\n // Editable text field\n if (key.tab || input === \"\\t\") {\n // Tab submits the field values and exits input mode\n sendMessage({ type: \"aid\", key: \"ENTER\", fields: fieldValues });\n setInputMode(false);\n return;\n }\n\n if (key.backspace || key.delete) {\n setFieldValues((prev) => ({\n ...prev,\n [activeField.id]: (prev[activeField.id] || \"\").slice(0, -1),\n }));\n return;\n }\n\n if (key.return) {\n if (isMultiLine) {\n // Enter in multi-line: add newline\n setFieldValues((prev) => {\n const current = prev[activeField.id] || \"\";\n if (current.length >= activeField.maxLength) return prev;\n return { ...prev, [activeField.id]: current + \"\\n\" };\n });\n return;\n }\n // Single-line Enter: submit\n sendMessage({ type: \"aid\", key: \"ENTER\", fields: fieldValues });\n setInputMode(false);\n return;\n }\n\n if (input) {\n setFieldValues((prev) => {\n const current = prev[activeField.id] || \"\";\n if (current.length >= activeField.maxLength) return prev;\n return { ...prev, [activeField.id]: current + input };\n });\n }\n return;\n }\n\n // -- Normal mode (not typing) --\n\n if (input === \"x\" || input === \"q\") {\n onBackToApps();\n return;\n }\n\n if (key.escape) {\n sendMessage({ type: \"aid\", key: \"B\", fields: fieldValues });\n return;\n }\n\n // Ctrl+Enter: ENTER_BACK\n if (key.return && (key.ctrl || key.meta)) {\n sendMessage({ type: \"aid\", key: \"ENTER_BACK\", fields: fieldValues });\n return;\n }\n\n // Space: toggle checkbox when focused on non-editable field\n if (input === \" \" && activeField && !isEditable) {\n toggleActiveCheckbox();\n return;\n }\n\n if (key.return) {\n // Non-editable field focused: toggle checkbox\n if (activeField && !isEditable) {\n toggleActiveCheckbox();\n return;\n }\n // Editable field focused: enter input mode\n if (inputFields.length > 0 && isEditable) {\n setInputMode(true);\n return;\n }\n // Selectable action line: execute it\n const line = selectableLines[selectedLineIndex];\n if (line) {\n applySelectedLine(line);\n return;\n }\n // Default: send ENTER\n sendMessage({ type: \"aid\", key: \"ENTER\", fields: fieldValues });\n return;\n }\n\n // PageUp/PageDown: scroll list by a full page\n if (key.pageUp || key.pageDown) {\n const delta = key.pageDown ? 1 : -1;\n const currentLine = selectableLines[selectedLineIndex];\n const wId = currentLine ? lineWidgetIds?.[currentLine.index] : undefined;\n if (wId && listScrollInfo?.[wId]) {\n const info = listScrollInfo[wId];\n const scrollAmount = delta * info.visibleRows;\n const newOffset = Math.max(0, Math.min(info.offset + scrollAmount, info.totalRows - info.visibleRows));\n if (newOffset !== info.offset) {\n setListScrollOffsets((prev) => ({ ...prev, [wId]: newOffset }));\n }\n }\n return;\n }\n\n // Arrow keys: map to date picker shortcuts (h/l/j/k) when available,\n // otherwise cycle input fields or selectable lines\n if (key.upArrow || key.downArrow || key.leftArrow || key.rightArrow) {\n const arrowMap: Record<string, string> = {\n // ink key names aren't available as event.key, so we check the boolean flags\n };\n let mapped: string | undefined;\n if (key.leftArrow) mapped = \"h\";\n else if (key.rightArrow) mapped = \"l\";\n else if (key.upArrow) mapped = \"k\";\n else if (key.downArrow) mapped = \"j\";\n\n if (mapped) {\n const shortcut = shortcutByKey.get(mapped);\n if (shortcut) {\n executeShortcut(shortcut);\n return;\n }\n }\n\n // Up/Down: cycle input fields if present, otherwise selectable lines\n if (key.upArrow || key.downArrow) {\n const delta = key.downArrow ? 1 : -1;\n if (inputFields.length > 0) {\n setActiveInputIndex((prev) =>\n (prev + delta + inputFields.length) % inputFields.length\n );\n } else if (selectableLines.length > 0) {\n const nextIdx = selectedLineIndex + delta;\n // Check if at boundary and can scroll a list widget\n if (nextIdx < 0 || nextIdx >= selectableLines.length) {\n const currentLine = selectableLines[selectedLineIndex];\n const wId = currentLine ? lineWidgetIds?.[currentLine.index] : undefined;\n if (wId && listScrollInfo?.[wId]) {\n const info = listScrollInfo[wId];\n if (delta > 0 && info.offset + info.visibleRows < info.totalRows) {\n setListScrollOffsets((prev) => ({ ...prev, [wId]: info.offset + 1 }));\n return;\n }\n if (delta < 0 && info.offset > 0) {\n setListScrollOffsets((prev) => ({ ...prev, [wId]: info.offset - 1 }));\n return;\n }\n }\n }\n setSelectedLineIndex((prev) =>\n (prev + delta + selectableLines.length) % selectableLines.length\n );\n }\n }\n return;\n }\n\n if ((key.tab || input === \"\\t\" || input === \"i\") && inputFields.length > 0) {\n setInputMode(true);\n return;\n }\n\n // Shortcut keys (checked before hardcoded aids so screen-defined hotkeys take priority)\n if (input) {\n const shortcut = shortcutByKey.get(input.toLowerCase());\n if (shortcut) {\n executeShortcut(shortcut);\n return;\n }\n }\n\n if (input === \"/\" && !shortcutByKey.has(\"/\")) {\n setAiMode(true);\n return;\n }\n\n if (input === \"b\") {\n sendMessage({ type: \"aid\", key: \"B\", fields: fieldValues });\n return;\n }\n\n if (input === \"c\") {\n sendMessage({ type: \"aid\", key: \"C\", fields: fieldValues });\n return;\n }\n });\n\n // Build a map of lineIndex -> fieldId for all input fields (including multi-line spans)\n // NOTE: all useMemo/useEffect hooks must be before early returns\n const fieldLineMap = useMemo(() => {\n const map = new Map<number, { fieldId: string; rowOffset: number; label: string; rows: number }>();\n for (const field of inputFields) {\n if (typeof field.lineIndex !== \"number\") continue;\n const rows = Math.max(1, Number(field.rows ?? 1));\n const lineStep = Math.max(1, Number((field as { lineStep?: number }).lineStep ?? 1));\n for (let r = 0; r < rows; r++) {\n map.set(field.lineIndex + r * lineStep, {\n fieldId: field.id,\n rowOffset: r,\n label: field.label || field.id,\n rows,\n });\n }\n }\n return map;\n }, [inputFields]);\n\n // Build display lines with inline editing\n const displayLines = useMemo(() => {\n if (!screen) return [];\n const lines = [...(screen.lines || [])];\n if (!inputMode || !activeField || !isEditable) return lines;\n const fieldId = activeField.id;\n const editValue = fieldValues[fieldId] || \"\";\n const label = activeField.label || activeField.id;\n const labelPrefix = label ? `${label}: ` : \"\";\n const indent = \" \".repeat(labelPrefix.length);\n const rows = Math.max(1, Number(activeField.rows ?? 1));\n const lineStep = Math.max(1, Number((activeField as { lineStep?: number }).lineStep ?? 1));\n\n if (typeof activeField.lineIndex !== \"number\") return lines;\n\n // Split the edited value into display rows\n const editLines = editValue.split(/\\r?\\n/);\n const paddedEditLines = editLines.slice(0, rows);\n while (paddedEditLines.length < rows) paddedEditLines.push(\"\");\n\n for (let r = 0; r < rows; r++) {\n const lineIdx = activeField.lineIndex + r * lineStep;\n if (lineIdx >= 0 && lineIdx < lines.length) {\n const prefix = r === 0 ? labelPrefix : indent;\n const text = paddedEditLines[r] || \"\";\n // Show cursor on the last row with content, or last visible row if overflowing\n const cursor = (r === editLines.length - 1 || (r === rows - 1 && editLines.length >= rows)) ? \"\\u2588\" : \"\";\n lines[lineIdx] = `${prefix}${text}${cursor}`;\n }\n }\n return lines;\n }, [screen, inputMode, activeField, isEditable, fieldValues, inputFields]);\n\n // Hints for status bar\n const hintText = useMemo(() => {\n if (aiMode) return \"Type message, Enter=send, Esc=back to app\";\n if (!activeField) return \"Enter=select, /=AI, b=back, Tab/i=edit, arrows=nav, x=apps\";\n if (inputMode && isEditable) {\n return isMultiLine\n ? \"Type to edit, Enter=newline, Tab=submit, Esc=cancel\"\n : \"Type to edit, Enter=submit, Tab=submit, Esc=cancel\";\n }\n if (isEditable) return \"Enter=edit, Tab=next field, arrows=nav, b=back, x=apps\";\n return \"Enter/Space=toggle, arrows=nav, b=back, x=apps\";\n }, [activeField, aiMode, inputMode, isEditable, isMultiLine]);\n\n if (error) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\">Runner error: {error}</Text>\n <Text>Press x to return to apps, or Ctrl+C to exit.</Text>\n </Box>\n );\n }\n\n if (connecting || !screen) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">Starting runner...</Text>\n </Box>\n );\n }\n\n const selectedLine = selectableLines[selectedLineIndex];\n\n if (aiMode) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">\n AI CHAT | project={projectId} | screen={rawScreen?.screen || \"-\"}\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {aiHistoryLoading && (\n <Text color=\"gray\">Loading conversation...</Text>\n )}\n {aiMessages.length === 0 && !aiLoading && !aiHistoryLoading && (\n <Text color=\"gray\">Ask anything about this app or screen.</Text>\n )}\n {aiMessages.map((msg, idx) => {\n const prefix =\n msg.role === \"user\" ? \"You: \" : msg.role === \"tool\" ? `TOOL(${msg.toolName || \"?\"}): ` : \"AI: \";\n const color = msg.role === \"user\" ? \"cyan\" : msg.role === \"tool\" ? \"yellow\" : \"white\";\n return (\n <Box key={idx} flexDirection=\"column\">\n <Text color={color} wrap=\"wrap\">\n {prefix}{msg.text}\n </Text>\n </Box>\n );\n })}\n {aiLoading && <Text color=\"yellow\">Thinking...</Text>}\n </Box>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"green\">> {aiInput}<Text color=\"green\">{\"\\u2588\"}</Text></Text>\n <Text color=\"gray\">{hintText}</Text>\n </Box>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">\n RUNNER | project={projectId} | version={versionId || \"published\"} | session={\n sessionId || \"-\"\n }\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {displayLines.map((line, idx) => {\n const match = selectableLines.findIndex((entry) => entry.index === idx);\n const isSelectedActionLine = match >= 0 && selectableLines[match] === selectedLine;\n const fieldInfo = fieldLineMap.get(idx);\n const isActiveInputLine = fieldInfo != null && fieldInfo.fieldId === activeField?.id;\n const isAnyInputLine = fieldInfo != null;\n const lineColor = isSelectedActionLine\n ? \"green\"\n : isActiveInputLine\n ? inputMode\n ? \"yellow\"\n : \"cyan\"\n : isAnyInputLine\n ? \"cyan\"\n : undefined;\n const lineBackground = isActiveInputLine && inputMode ? \"blackBright\" : undefined;\n // Add spacing before standalone action buttons (like web's isButton marginTop)\n const actionLine = match >= 0 ? selectableLines[match] : undefined;\n const isButton = actionLine && !actionLine.fields;\n const prevWidgetId = idx > 0 ? lineWidgetIds?.[idx - 1] : undefined;\n const curWidgetId = lineWidgetIds?.[idx];\n const needsTopSpace = isButton && prevWidgetId && prevWidgetId !== curWidgetId;\n return (\n <Box key={`${idx}-${line}`} flexDirection=\"column\" marginTop={needsTopSpace ? 1 : 0}>\n <Text\n color={lineColor}\n backgroundColor={lineBackground}\n bold={isActiveInputLine}\n >\n {line}\n </Text>\n </Box>\n );\n })}\n </Box>\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"gray\">{screen.statusLine}</Text>\n <Text color=\"gray\">{hintText}</Text>\n </Box>\n </Box>\n );\n};\n","import type { AiMessage, UnifiedChatPayload, UnifiedChatResponse } from \"@blo/shared\";\nimport {\n firestoreDocsBase,\n authHeaders,\n parseRunQueryDocs,\n parseDocument,\n extractDocIdFromName,\n} from \"./firestore.js\";\n\nexport async function callUnifiedChat(opts: {\n firebaseProjectId: string;\n idToken: string;\n appCheckToken?: string;\n payload: UnifiedChatPayload;\n}): Promise<UnifiedChatResponse> {\n const url = `https://us-central1-${opts.firebaseProjectId}.cloudfunctions.net/aiApi`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${opts.idToken}`,\n };\n if (opts.appCheckToken) {\n headers[\"X-Firebase-AppCheck\"] = opts.appCheckToken;\n }\n\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ data: { action: \"unifiedChat\", payload: opts.payload } }),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`AI request failed (${res.status}): ${text}`);\n }\n\n const json = (await res.json()) as { result?: { data?: UnifiedChatResponse } };\n const data = json.result?.data;\n if (!data) throw new Error(\"Unexpected AI response format\");\n return data;\n}\n\n// ── Conversation persistence (Firestore REST) ────────────────────────\n\ntype ConversationOpts = {\n firebaseProjectId: string;\n idToken: string;\n appCheckToken?: string;\n projectId: string;\n versionId: string;\n};\n\nexport async function loadLatestConversation(\n opts: ConversationOpts\n): Promise<{ conversationId: string; messages: AiMessage[]; messageCount: number } | null> {\n const base = firestoreDocsBase(opts.firebaseProjectId);\n const parent = `projects/${opts.projectId}/versions/${opts.versionId}`;\n\n // Fetch up to 50 conversations\n const convoRes = await fetch(`${base}/${parent}:runQuery`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({\n structuredQuery: {\n from: [{ collectionId: \"ai_conversations\" }],\n limit: 50,\n },\n }),\n });\n if (!convoRes.ok) return null;\n\n const convoRows = parseRunQueryDocs((await convoRes.json()) as Array<{ document?: any }>);\n if (!convoRows.length) return null;\n\n // Pick latest by max(updatedAt, createdAt)\n let bestDoc = convoRows[0];\n let bestTime = 0;\n for (const doc of convoRows) {\n const data = parseDocument(doc);\n const t = Math.max(toMs(data.updatedAt), toMs(data.createdAt));\n if (t > bestTime || bestTime === 0) {\n bestTime = t;\n bestDoc = doc;\n }\n }\n const conversationId = extractDocIdFromName(bestDoc?.name);\n if (!conversationId) return null;\n\n // Fetch messages ordered by seq asc\n const msgRes = await fetch(\n `${base}/${parent}/ai_conversations/${encodeURIComponent(conversationId)}:runQuery`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({\n structuredQuery: {\n from: [{ collectionId: \"messages\" }],\n orderBy: [{ field: { fieldPath: \"seq\" }, direction: \"ASCENDING\" }],\n limit: 200,\n },\n }),\n }\n );\n if (!msgRes.ok) return { conversationId, messages: [], messageCount: 0 };\n\n const msgDocs = parseRunQueryDocs((await msgRes.json()) as Array<{ document?: any }>);\n const messages: AiMessage[] = msgDocs.map((doc) => {\n const d = parseDocument(doc);\n return { role: d.role, text: d.text, toolName: d.toolName || undefined };\n });\n\n return { conversationId, messages, messageCount: messages.length };\n}\n\nexport async function createConversation(opts: ConversationOpts): Promise<string> {\n const base = firestoreDocsBase(opts.firebaseProjectId);\n const colPath = `projects/${opts.projectId}/versions/${opts.versionId}/ai_conversations`;\n const now = new Date().toISOString();\n\n const res = await fetch(`${base}/${colPath}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({\n fields: {\n projectId: { stringValue: opts.projectId },\n versionId: { stringValue: opts.versionId },\n createdAt: { timestampValue: now },\n updatedAt: { timestampValue: now },\n },\n }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Failed to create conversation (${res.status}): ${text}`);\n }\n const doc = (await res.json()) as { name?: string };\n const id = extractDocIdFromName(doc.name);\n if (!id) throw new Error(\"Failed to extract conversation ID\");\n return id;\n}\n\nexport async function appendMessage(opts: ConversationOpts & {\n conversationId: string;\n role: string;\n text: string;\n toolName?: string;\n seq: number;\n}): Promise<void> {\n const base = firestoreDocsBase(opts.firebaseProjectId);\n const msgPath = `projects/${opts.projectId}/versions/${opts.versionId}/ai_conversations/${opts.conversationId}/messages`;\n const now = new Date().toISOString();\n\n const fields: Record<string, any> = {\n role: { stringValue: opts.role },\n text: { stringValue: opts.text },\n seq: { integerValue: String(opts.seq) },\n createdAt: { timestampValue: now },\n };\n if (opts.toolName) {\n fields.toolName = { stringValue: opts.toolName };\n }\n\n // Create message doc\n const msgRes = await fetch(`${base}/${msgPath}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({ fields }),\n });\n if (!msgRes.ok) return; // best-effort\n\n // Update conversation updatedAt\n const convoPath = `projects/${opts.projectId}/versions/${opts.versionId}/ai_conversations/${opts.conversationId}`;\n await fetch(`${base}/${convoPath}?updateMask.fieldPaths=updatedAt`, {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\", ...authHeaders(opts.idToken, opts.appCheckToken) },\n body: JSON.stringify({\n fields: { updatedAt: { timestampValue: now } },\n }),\n }).catch(() => {}); // best-effort\n}\n\nfunction toMs(value: unknown): number {\n if (!value) return 0;\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? 0 : parsed;\n }\n return 0;\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport WebSocket from \"ws\";\nimport type {\n TerminalClientMessage,\n TerminalScreenPayload,\n TerminalServerMessage,\n} from \"@blo/shared/terminal\";\nimport { log } from \"../log.js\";\n\nconst toWsBaseUrl = (httpBase: string): string => {\n if (httpBase.startsWith(\"https://\")) return `wss://${httpBase.slice(\"https://\".length)}`;\n if (httpBase.startsWith(\"http://\")) return `ws://${httpBase.slice(\"http://\".length)}`;\n return httpBase;\n};\n\nconst getTerminalSize = (): { rows: number; cols: number } => {\n const cols = Math.max(3, Math.min(300, Number(process.stdout.columns || 80)));\n const rows = Math.max(3, Math.min(200, Number(process.stdout.rows || 24)));\n return { rows, cols };\n};\n\ntype SessionArgs = {\n projectId: string;\n versionId?: string;\n terminalUrl: string;\n idToken: string;\n};\n\nexport const useRunnerSession = ({ projectId, versionId, terminalUrl, idToken }: SessionArgs) => {\n const [screen, setScreen] = useState<TerminalScreenPayload | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [connecting, setConnecting] = useState(true);\n const [sessionId, setSessionId] = useState<string | null>(null);\n const wsRef = useRef<WebSocket | null>(null);\n const lastSentSizeRef = useRef<string>(\"\");\n\n useEffect(() => {\n let cancelled = false;\n const run = async () => {\n try {\n setConnecting(true);\n setError(null);\n const sessionUrl = `${terminalUrl.replace(/\\/+$/, \"\")}/api/sessions`;\n log(`Creating session: POST ${sessionUrl}`);\n log(` projectId=${projectId}, versionId=${versionId || \"(latest)\"}`);\n const response = await fetch(sessionUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${idToken}`,\n },\n body: JSON.stringify({\n projectId,\n versionId,\n runnerVersion: \"cli-dev\",\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n log(`Session create failed: ${response.status} ${text}`);\n if (response.status === 401) {\n throw new Error(\"Authentication failed. Try 'blo login' to re-authenticate.\");\n }\n if (response.status === 403) {\n throw new Error(`Access denied for project ${projectId}: ${text}`);\n }\n if (response.status === 429) {\n throw new Error(\"Rate limited. Please wait a moment and try again.\");\n }\n throw new Error(`Session create failed (${response.status}): ${text}`);\n }\n\n const body = (await response.json()) as\n | { bootstrap?: { sessionId?: string }; screen?: TerminalScreenPayload }\n | TerminalScreenPayload;\n if (cancelled) return;\n\n // POST /api/sessions returns { bootstrap, screen }\n const screenPayload = \"screen\" in body && body.screen && typeof body.screen === \"object\" && \"sessionId\" in body.screen\n ? body.screen as TerminalScreenPayload\n : body as TerminalScreenPayload;\n const sid = screenPayload.sessionId\n || (\"bootstrap\" in body ? body.bootstrap?.sessionId : undefined)\n || \"\";\n\n if (!sid) {\n log(`WARNING: No sessionId in response. Response keys: ${Object.keys(body).join(\", \")}`);\n throw new Error(\"Server returned no session ID. The server may be running an incompatible version.\");\n }\n\n log(`Session created: sessionId=${sid}`);\n log(` screen=${screenPayload.screen}, lines=${screenPayload.lines?.length || 0}`);\n setScreen(screenPayload);\n setSessionId(sid);\n\n const wsBase = toWsBaseUrl(terminalUrl.replace(/\\/+$/, \"\"));\n const wsUrl = `${wsBase}/ws?sessionId=${encodeURIComponent(sid)}`;\n log(`Connecting WebSocket: ${wsUrl}`);\n const ws = new WebSocket(wsUrl);\n wsRef.current = ws;\n ws.onopen = () => {\n log(\"WebSocket connected\");\n ws.send(JSON.stringify({ type: \"init\" } satisfies TerminalClientMessage));\n const size = getTerminalSize();\n const sizeKey = `${size.rows}x${size.cols}`;\n lastSentSizeRef.current = sizeKey;\n log(`Sending resize: ${size.cols}x${size.rows}`);\n ws.send(\n JSON.stringify({\n type: \"resize\",\n rows: size.rows,\n cols: size.cols,\n } satisfies TerminalClientMessage)\n );\n setConnecting(false);\n };\n ws.onmessage = (event) => {\n try {\n const data = JSON.parse(String(event.data)) as TerminalServerMessage;\n if (data.type === \"screen\") {\n log(`Screen update: screen=${data.screen}, lines=${data.lines?.length || 0}`);\n setScreen(data);\n return;\n }\n if (data.type === \"error\") {\n log(`Server error: ${data.message}`);\n setError(data.message);\n }\n } catch (err) {\n log(`Failed to parse server message: ${err}`);\n setError(err instanceof Error ? err.message : String(err));\n }\n };\n ws.onclose = (event) => {\n const code = event.code;\n const reason = event.reason || \"(no reason)\";\n log(`WebSocket closed: code=${code}, reason=${reason}`);\n if (!cancelled) {\n if (code === 1008) {\n setError(`Session rejected by server: ${reason}`);\n } else if (code === 1006) {\n setError(\"Lost connection to server. Check if the terminal server is running.\");\n } else {\n setError(`Connection closed (code ${code}).`);\n }\n }\n };\n ws.onerror = (event) => {\n log(`WebSocket error: ${event.message || \"unknown\"}`);\n if (!cancelled) {\n setError(`Connection error: ${event.message || \"Failed to connect to terminal server.\"}`);\n }\n };\n } catch (err) {\n if (!cancelled) {\n log(`Runner error: ${err}`);\n setError(err instanceof Error ? err.message : String(err));\n }\n }\n };\n\n void run();\n\n return () => {\n cancelled = true;\n wsRef.current?.close();\n wsRef.current = null;\n };\n }, [projectId, versionId, terminalUrl, idToken]);\n\n useEffect(() => {\n if (!sessionId || !process.stdout.isTTY) return;\n const onTerminalResize = () => {\n const ws = wsRef.current;\n if (!ws || ws.readyState !== WebSocket.OPEN) return;\n const size = getTerminalSize();\n const sizeKey = `${size.rows}x${size.cols}`;\n if (lastSentSizeRef.current === sizeKey) return;\n lastSentSizeRef.current = sizeKey;\n log(`Terminal resized: ${size.cols}x${size.rows}`);\n ws.send(\n JSON.stringify({\n type: \"resize\",\n rows: size.rows,\n cols: size.cols,\n } satisfies TerminalClientMessage)\n );\n };\n\n process.stdout.on(\"resize\", onTerminalResize);\n return () => {\n process.stdout.off(\"resize\", onTerminalResize);\n };\n }, [sessionId]);\n\n const sendMessage = (message: TerminalClientMessage) => {\n const ws = wsRef.current;\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n log(`Cannot send message (ws ${ws ? `state=${ws.readyState}` : \"null\"}): ${JSON.stringify(message)}`);\n if (ws && ws.readyState >= WebSocket.CLOSING) {\n setError(\"Connection lost. Press x to return to apps.\");\n }\n return;\n }\n log(`Sending: ${JSON.stringify(message)}`);\n ws.send(JSON.stringify(message));\n };\n\n return { screen, error, connecting, sessionId, sendMessage };\n};\n","import { useMemo } from \"react\";\nimport type { TerminalActionLine, TerminalScreenPayload } from \"@blo/shared/terminal\";\nimport type { ListScrollInfo } from \"@blo/shared/screen-runtime\";\nimport { collectScreenSpecContext } from \"@blo/shared/screen-runtime\";\n\nexport const useRunnerRenderSource = (\n screen: TerminalScreenPayload | null,\n listScrollOffsets?: Record<string, number>,\n) => {\n const result = useMemo(() => {\n if (!screen?.screenSpec || !screen?.state) return { screen, listScrollInfo: undefined as Record<string, ListScrollInfo> | undefined };\n\n const ctx = collectScreenSpecContext(screen.screenSpec, {\n activeScreenId: screen.state.activeScreenId || screen.screen,\n fields: screen.state.fields || {},\n fieldErrors: screen.state.fieldErrors || {},\n data: screen.state.data || {},\n statusLine: screen.state.statusLine || screen.statusLine,\n }, { hideHotkeys: false, listScrollOffsets });\n\n const lines = ctx.lines.map((line) => line.text);\n const lineWidgetIds = ctx.lines.map((line) => line.widgetId);\n\n const fieldLineIndexById = new Map<string, number>();\n ctx.lines.forEach((line, idx) => {\n if (line.fieldId && !fieldLineIndexById.has(line.fieldId)) {\n fieldLineIndexById.set(line.fieldId, idx);\n }\n });\n\n const actionLines: TerminalActionLine[] = [];\n ctx.lines.forEach((line, idx) => {\n if (!(line.target || line.aidAlias || line.action)) return;\n actionLines.push({\n index: idx,\n selectable: line.selectable,\n target: line.target,\n aidAlias: line.aidAlias,\n action: line.action,\n fields: line.fields,\n });\n });\n\n const inputFields = ctx.inputFields.map((field) => ({\n ...field,\n lineIndex: fieldLineIndexById.get(field.id),\n }));\n\n const firstMatch = ctx.firstInput\n ? inputFields.find((f) => f.id === ctx.firstInput?.id)\n : undefined;\n const inputField = ctx.firstInput\n ? {\n id: ctx.firstInput.id,\n value: screen.state.fields?.[ctx.firstInput.id] || \"\",\n maxLength: ctx.firstInput.maxLength,\n label: firstMatch?.label,\n lineIndex: fieldLineIndexById.get(ctx.firstInput.id),\n rows: firstMatch?.rows,\n action: firstMatch?.action,\n }\n : undefined;\n\n return {\n screen: {\n ...screen,\n lines,\n actionLines,\n inputFields,\n inputField,\n shortcuts: ctx.shortcuts,\n statusLine: screen.state.statusLine || screen.statusLine,\n } satisfies TerminalScreenPayload,\n listScrollInfo: ctx.listScrollInfo,\n lineWidgetIds,\n };\n }, [screen, listScrollOffsets]);\n\n return result;\n};\n","// ===== Type Guards =====\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n\n// ===== Field Parsing Utilities =====\n\nexport const parseMaxLength = (value: unknown): number => {\n if (typeof value === \"number\" && Number.isFinite(value) && value > 0) {\n return Math.min(Math.floor(value), 512);\n }\n if (typeof value === \"string\") {\n const parsed = Number.parseInt(value, 10);\n if (Number.isFinite(parsed) && parsed > 0) {\n return Math.min(parsed, 512);\n }\n }\n return 80;\n};\n\nexport const parseRows = (value: unknown): number => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return Math.max(1, Math.floor(value));\n }\n if (typeof value === \"string\") {\n const parsed = Number.parseInt(value, 10);\n if (Number.isFinite(parsed)) {\n return Math.max(1, Math.floor(parsed));\n }\n }\n return 1;\n};\n\nexport const toFiniteNumber = (value: unknown): number | null => {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\" && value.trim().length > 0) {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) return parsed;\n }\n return null;\n};\n\n// ===== Hotkey Normalization =====\n\nexport const normalizeHotkey = (value: unknown): string | null => {\n const raw = String(value || \"\").trim().toLowerCase();\n if (!raw) return null;\n if (!/^[a-z0-9]$/.test(raw)) return null;\n return raw;\n};\n","import { isRecord } from \"../parsing/fieldParser.js\";\n\n// ===== Security Constants =====\n\n// Keys that should never be accessed or modified to prevent prototype pollution\nconst DANGEROUS_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nconst isDangerousKey = (key: string): boolean => DANGEROUS_KEYS.has(key);\n\n// ===== Path Resolution =====\n\nexport const resolvePath = (source: unknown, path: string): unknown => {\n if (!path.trim()) return undefined;\n return path.split(\".\").reduce<unknown>((acc, key) => {\n if (!isRecord(acc)) return undefined;\n if (isDangerousKey(key)) return undefined;\n return acc[key];\n }, source);\n};\n\n// ===== String Interpolation =====\n\nexport const interpolate = (template: string, context: Record<string, unknown>): string =>\n template.replace(/\\{\\{\\s*([^}]+)\\s*\\}\\}/g, (_full, exprRaw) => {\n const expr = String(exprRaw || \"\").trim();\n const defaultMatch = expr.match(\n /^([A-Za-z0-9_.]+)\\s*\\|\\s*default\\s*:\\s*(.+)$/\n );\n if (defaultMatch) {\n const path = String(defaultMatch[1] || \"\").trim();\n const fallbackRaw = String(defaultMatch[2] || \"\").trim();\n const resolved = resolvePath(context, path);\n if (resolved != null) {\n return String(resolved);\n }\n const fallback =\n fallbackRaw === \"null\"\n ? null\n : fallbackRaw === \"true\"\n ? true\n : fallbackRaw === \"false\"\n ? false\n : /^-?\\d+(\\.\\d+)?$/.test(fallbackRaw)\n ? Number(fallbackRaw)\n : fallbackRaw.replace(/^[\"']|[\"']$/g, \"\");\n return fallback == null ? \"\" : String(fallback);\n }\n\n const value = resolvePath(context, expr);\n return value == null ? \"\" : String(value);\n });\n\n// ===== Path Mutation =====\n\nexport const setPathValue = (\n target: Record<string, unknown>,\n path: string,\n value: unknown\n): void => {\n const keys = path\n .split(\".\")\n .map((part) => part.trim())\n .filter((k) => k && !isDangerousKey(k));\n if (!keys.length) return;\n let cursor: Record<string, unknown> = target;\n keys.slice(0, -1).forEach((key) => {\n const existing = cursor[key];\n if (!isRecord(existing)) {\n cursor[key] = {};\n }\n cursor = cursor[key] as Record<string, unknown>;\n });\n cursor[keys[keys.length - 1]] = value;\n};\n\n// ===== Collection Utilities =====\n\nexport const getCollectionRecords = (\n root: Record<string, unknown>,\n path: string\n): Array<Record<string, unknown>> => {\n const value = resolvePath(root, path);\n if (!Array.isArray(value)) return [];\n return value.map((item) => (isRecord(item) ? { ...item } : { value: item }));\n};\n\nexport const setCollectionRecords = (\n root: Record<string, unknown>,\n path: string,\n records: Array<Record<string, unknown>>\n) => {\n setPathValue(root, path, records);\n};\n","import { toFiniteNumber } from \"../parsing/fieldParser.js\";\n\n// ===== Action Value Building =====\n\nexport const buildActionValues = (\n actionValues: Record<string, unknown> | undefined,\n valuesFromFields: Record<string, string> | undefined,\n fields: Record<string, string>\n): Record<string, unknown> => {\n const values: Record<string, unknown> = {};\n Object.entries(actionValues || {}).forEach(([key, value]) => {\n values[key] = value;\n });\n Object.entries(valuesFromFields || {}).forEach(([key, fieldId]) => {\n values[key] = String(fields[String(fieldId) || \"\"] || \"\");\n });\n return values;\n};\n\n// ===== Sort Comparison =====\n\nexport const compareSortValues = (left: unknown, right: unknown): number => {\n const leftNum = toFiniteNumber(left);\n const rightNum = toFiniteNumber(right);\n if (leftNum != null && rightNum != null) {\n return leftNum - rightNum;\n }\n const leftText = String(left ?? \"\").toLowerCase();\n const rightText = String(right ?? \"\").toLowerCase();\n return leftText.localeCompare(rightText);\n};\n","import type { ScreenAction, ScreenFieldWidget, ScreenSelectWidget, ScreenCheckboxWidget, ScreenRadioWidget, ScreenNumberWidget, ScreenDateWidget } from \"../../screen-spec.js\";\nimport type { RuntimeState } from \"../types.js\";\nimport { resolvePath } from \"../state/pathUtils.js\";\n\n// ===== Widget Bind Keys =====\n\nexport const fieldBindKey = (widget: ScreenFieldWidget): string =>\n widget.bind.trim() || widget.id;\n\nexport const selectBindKey = (widget: Pick<ScreenSelectWidget, \"bind\" | \"id\">): string =>\n widget.bind.trim() || widget.id;\n\n// ===== Widget Labels =====\n\nexport const fieldLabel = (widget: ScreenFieldWidget): string =>\n widget.label || widget.placeholder || widget.id;\n\nexport const selectLabel = (widget: ScreenSelectWidget): string =>\n widget.label || widget.placeholder || widget.id;\n\n// ===== Widget Value Resolution =====\n\nexport const resolveFieldValue = (\n widget: ScreenFieldWidget,\n state: RuntimeState\n): string => {\n const bindKey = fieldBindKey(widget);\n const fallback = resolvePath(state.data, bindKey);\n if (state.fields[bindKey] != null) {\n return String(state.fields[bindKey] || \"\");\n }\n if (typeof fallback === \"string\" || typeof fallback === \"number\" || typeof fallback === \"boolean\") {\n return String(fallback);\n }\n return \"\";\n};\n\nexport const resolveSelectValue = (\n widget: Pick<ScreenSelectWidget, \"bind\" | \"id\">,\n state: RuntimeState\n): string => {\n const bindKey = selectBindKey(widget);\n if (state.fields[bindKey] != null) {\n return String(state.fields[bindKey] || \"\");\n }\n const fallback = resolvePath(state.data, bindKey);\n if (typeof fallback === \"string\" || typeof fallback === \"number\" || typeof fallback === \"boolean\") {\n return String(fallback);\n }\n return \"\";\n};\n\n// ===== Checkbox / Radio / Number Bind Keys =====\n\nexport const checkboxBindKey = (widget: ScreenCheckboxWidget): string =>\n widget.bind.trim() || widget.id;\n\nexport const radioBindKey = (widget: ScreenRadioWidget): string =>\n widget.bind.trim() || widget.id;\n\nexport const numberBindKey = (widget: ScreenNumberWidget): string =>\n widget.bind.trim() || widget.id;\n\n// ===== Checkbox / Number Value Resolution =====\n\nexport const resolveCheckboxValue = (\n widget: ScreenCheckboxWidget,\n state: RuntimeState\n): boolean => {\n const bindKey = checkboxBindKey(widget);\n if (state.fields[bindKey] != null) {\n const v = state.fields[bindKey];\n return v === \"true\" || v === \"1\";\n }\n const fallback = resolvePath(state.data, bindKey);\n if (typeof fallback === \"string\") {\n return fallback === \"true\" || fallback === \"1\";\n }\n return Boolean(fallback);\n};\n\nexport const resolveNumberValue = (\n widget: ScreenNumberWidget,\n state: RuntimeState\n): number => {\n const bindKey = numberBindKey(widget);\n if (state.fields[bindKey] != null) {\n const v = Number(state.fields[bindKey]);\n return Number.isFinite(v) ? v : 0;\n }\n const fallback = resolvePath(state.data, bindKey);\n if (typeof fallback === \"number\" && Number.isFinite(fallback)) return fallback;\n return 0;\n};\n\n// ===== Date Bind Key & Value Resolution =====\n\nexport const dateBindKey = (widget: ScreenDateWidget): string =>\n widget.bind.trim() || widget.id;\n\nexport const resolveDateValue = (\n widget: ScreenDateWidget,\n state: RuntimeState\n): string => {\n const bindKey = dateBindKey(widget);\n if (state.fields[bindKey] != null) {\n const v = String(state.fields[bindKey] || \"\");\n if (parseISODate(v)) return v;\n }\n const fallback = resolvePath(state.data, bindKey);\n if (typeof fallback === \"string\" && parseISODate(fallback)) return fallback;\n return todayISO();\n};\n\n// ===== Date Utilities (UTC-based, no timezone issues) =====\n\nexport const MONTH_NAMES = [\n \"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\n \"July\", \"August\", \"September\", \"October\", \"November\", \"December\",\n];\n\nconst MONTH_ABBR = [\n \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\",\n];\n\nexport const parseISODate = (str: string): { y: number; m: number; d: number } | null => {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(str);\n if (!match) return null;\n const y = Number(match[1]);\n const m = Number(match[2]);\n const d = Number(match[3]);\n if (m < 1 || m > 12 || d < 1 || d > daysInMonth(y, m)) return null;\n return { y, m, d };\n};\n\nexport const formatDisplayDate = (y: number, m: number, d: number): string =>\n `${MONTH_ABBR[m - 1]} ${d}, ${y}`;\n\nexport const daysInMonth = (y: number, m: number): number => {\n if (m === 2) return (y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0)) ? 29 : 28;\n return [0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m];\n};\n\nexport const dayOfWeek = (y: number, m: number, d: number): number => {\n // Tomohiko Sakamoto's algorithm, returns 0=Sun..6=Sat\n const t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];\n const yr = m < 3 ? y - 1 : y;\n return (yr + Math.floor(yr / 4) - Math.floor(yr / 100) + Math.floor(yr / 400) + t[m - 1] + d) % 7;\n};\n\nconst pad2 = (n: number): string => (n < 10 ? \"0\" + n : String(n));\n\nconst toISO = (y: number, m: number, d: number): string =>\n `${y}-${pad2(m)}-${pad2(d)}`;\n\nexport const shiftDay = (iso: string, delta: number): string => {\n const parsed = parseISODate(iso);\n if (!parsed) return iso;\n const ms = Date.UTC(parsed.y, parsed.m - 1, parsed.d) + delta * 86400000;\n const dt = new Date(ms);\n return toISO(dt.getUTCFullYear(), dt.getUTCMonth() + 1, dt.getUTCDate());\n};\n\nexport const shiftMonth = (iso: string, delta: number): string => {\n const parsed = parseISODate(iso);\n if (!parsed) return iso;\n let newM = parsed.m + delta;\n let newY = parsed.y;\n while (newM > 12) { newM -= 12; newY++; }\n while (newM < 1) { newM += 12; newY--; }\n const clamped = Math.min(parsed.d, daysInMonth(newY, newM));\n return toISO(newY, newM, clamped);\n};\n\nexport const buildCalendarLines = (y: number, m: number, selectedDay: number): string[] => {\n const lines: string[] = [];\n lines.push(` Su Mo Tu We Th Fr Sa`);\n const total = daysInMonth(y, m);\n const startDow = dayOfWeek(y, m, 1);\n let line = \" \".repeat(startDow * 4);\n for (let d = 1; d <= total; d++) {\n // All cells are 4 chars wide for consistent alignment\n line += d === selectedDay ? `[${pad2(d)}]` : ` ${pad2(d)}`;\n const dow = (startDow + d) % 7;\n if (dow === 0 && d < total) {\n lines.push(line.trimEnd());\n line = \"\";\n }\n }\n if (line.trim()) lines.push(line.trimEnd());\n return lines;\n};\n\nexport const todayISO = (): string => {\n const now = new Date();\n return toISO(now.getUTCFullYear(), now.getUTCMonth() + 1, now.getUTCDate());\n};\n\n// ===== Date Picker Rendering =====\n\nexport interface DatePickerState {\n bindPath: string;\n currentISO: string;\n returnScreenId: string;\n}\n\nconst CANCEL_PICKER: ScreenAction = { type: \"data.set\", path: \"__datePicker\", value: null };\nconst CONFIRM_PICKER: ScreenAction = { type: \"date.pick\" };\n\nexport interface DatePickerRenderResult {\n lines: Array<{ text: string }>;\n shortcuts: Array<{ key: string; label: string; action: ScreenAction }>;\n enterAction: ScreenAction;\n cancelAction: ScreenAction;\n}\n\nexport const isDatePickerActive = (\n data: Record<string, unknown>,\n activeScreenId: string\n): DatePickerState | null => {\n const raw = data.__datePicker;\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return null;\n const picker = raw as DatePickerState;\n if (typeof picker.bindPath !== \"string\" || typeof picker.currentISO !== \"string\") return null;\n if (picker.returnScreenId !== activeScreenId) return null;\n return picker;\n};\n\nexport const renderDatePickerLines = (picker: DatePickerState): DatePickerRenderResult => {\n const iso = picker.currentISO;\n const parsed = parseISODate(iso);\n if (!parsed) {\n return { lines: [{ text: \"Invalid date\" }], shortcuts: [], enterAction: CANCEL_PICKER, cancelAction: CANCEL_PICKER };\n }\n\n const p = \"__datePicker.currentISO\";\n const setP = (v: string): ScreenAction => ({ type: \"data.set\", path: p, value: v });\n\n return {\n lines: [\n { text: \"\" },\n { text: \" === Select Date ===\" },\n { text: \"\" },\n { text: ` ${parsed.y}` },\n { text: ` [<] ${MONTH_NAMES[parsed.m - 1]} [>]` },\n { text: \"\" },\n ...buildCalendarLines(parsed.y, parsed.m, parsed.d).map((cl) => ({ text: ` ${cl}` })),\n { text: \"\" },\n { text: ` Selected: ${formatDisplayDate(parsed.y, parsed.m, parsed.d)}` },\n { text: \"\" },\n { text: \" Arrows/H/L: Day J/K: Week\" },\n { text: \" [<] Prev Month [>] Next Month\" },\n { text: \" [[] Prev Year []] Next Year\" },\n { text: \" [T] Today\" },\n { text: \" Enter: Select Esc: Cancel\" },\n ],\n shortcuts: [\n { key: \"<\", label: \"Prev month\", action: setP(shiftMonth(iso, -1)) },\n { key: \">\", label: \"Next month\", action: setP(shiftMonth(iso, 1)) },\n { key: \"h\", label: \"Prev day\", action: setP(shiftDay(iso, -1)) },\n { key: \"l\", label: \"Next day\", action: setP(shiftDay(iso, 1)) },\n { key: \"j\", label: \"Next week\", action: setP(shiftDay(iso, 7)) },\n { key: \"k\", label: \"Prev week\", action: setP(shiftDay(iso, -7)) },\n { key: \"[\", label: \"Prev year\", action: setP(shiftMonth(iso, -12)) },\n { key: \"]\", label: \"Next year\", action: setP(shiftMonth(iso, 12)) },\n { key: \"t\", label: \"Today\", action: { type: \"date.pick\", value: todayISO() } },\n ],\n enterAction: CONFIRM_PICKER,\n cancelAction: CANCEL_PICKER,\n };\n};\n\n// ===== Validation Message Helper =====\n\nexport const toValidationMessage = (\n widget: ScreenFieldWidget | ScreenSelectWidget | ScreenRadioWidget | ScreenDateWidget,\n fallback: string\n): string => {\n const generic = String(widget.validation?.message || \"\").trim();\n return generic || fallback;\n};\n","import type { TerminalScreenSpecV2 } from \"../../screen-spec.js\";\nimport type { RuntimeState, RuntimeRenderContext, ScreenRenderOptions, ListScrollInfo } from \"../types.js\";\nimport { parseMaxLength, parseRows, normalizeHotkey } from \"../parsing/fieldParser.js\";\nimport { interpolate, resolvePath } from \"../state/pathUtils.js\";\nimport { compareSortValues } from \"../actions/actionBuilder.js\";\nimport {\n fieldBindKey,\n selectBindKey,\n checkboxBindKey,\n radioBindKey,\n numberBindKey,\n dateBindKey,\n fieldLabel,\n selectLabel,\n resolveFieldValue,\n resolveSelectValue,\n resolveCheckboxValue,\n resolveNumberValue,\n resolveDateValue,\n parseISODate,\n formatDisplayDate,\n shiftDay,\n shiftMonth,\n buildCalendarLines,\n MONTH_NAMES,\n isDatePickerActive,\n renderDatePickerLines,\n} from \"./widgetHelpers.js\";\n\n// ===== Screen Rendering =====\n\nexport const collectScreenSpecContext = (\n screenSpec: TerminalScreenSpecV2,\n state: RuntimeState,\n options: ScreenRenderOptions = {}\n): RuntimeRenderContext => {\n const ctx: RuntimeRenderContext = { lines: [], shortcuts: [], inputFields: [], actionLines: [], listScrollInfo: {} };\n const hotkeySet = new Set<string>();\n const vars: Record<string, unknown> = {\n ...state.data,\n fields: state.fields,\n };\n const picker = isDatePickerActive(state.data, state.activeScreenId);\n if (picker) {\n const result = renderDatePickerLines(picker);\n return { ...ctx, ...result };\n }\n\n const sortedWidgets = [...screenSpec.widgets].sort((a, b) => {\n const rowA = Number((a as { row?: number }).row || 0);\n const rowB = Number((b as { row?: number }).row || 0);\n if (rowA !== rowB) return rowA - rowB;\n const colA = Number((a as { col?: number }).col || 0);\n const colB = Number((b as { col?: number }).col || 0);\n return colA - colB;\n });\n\n const pushSpacerLines = (count: number) => {\n for (let i = 0; i < count; i += 1) {\n ctx.lines.push({ text: \"\" });\n }\n };\n\n sortedWidgets.forEach((widget) => {\n if (widget.kind === \"text\") {\n ctx.lines.push({\n text: interpolate(widget.text, vars),\n widgetId: widget.id,\n });\n return;\n }\n\n if (widget.kind === \"field\") {\n const bindKey = fieldBindKey(widget);\n const value = resolveFieldValue(widget, state);\n const label = fieldLabel(widget);\n const perRowLength = Math.max(1, parseMaxLength(widget.length));\n const rowCount = Math.max(1, parseRows(widget.rows));\n const lineStep = Math.max(1, Number((widget as { lineStep?: number }).lineStep) || 1);\n const maxLength = Math.min(512, perRowLength * rowCount);\n const labelPrefix = label ? `${label}: ` : \"\";\n const indent = \" \".repeat(labelPrefix.length);\n const rawLines = String(value || \"\").split(/\\r?\\n/);\n const wrappedLines: string[] = [];\n rawLines.forEach((line) => {\n if (line.length === 0) {\n wrappedLines.push(\"\");\n return;\n }\n for (let i = 0; i < line.length; i += perRowLength) {\n wrappedLines.push(line.slice(i, i + perRowLength));\n }\n });\n if (wrappedLines.length === 0) wrappedLines.push(\"\");\n const paddedLines = wrappedLines.slice(0, rowCount);\n while (paddedLines.length < rowCount) paddedLines.push(\"\");\n\n const lineIndex = ctx.lines.length;\n paddedLines.forEach((line, idx) => {\n ctx.lines.push({\n text: `${idx === 0 ? labelPrefix : indent}${line}`,\n widgetId: widget.id,\n fieldId: bindKey,\n });\n const isLast = idx === paddedLines.length - 1;\n if (lineStep > 1 && !isLast) {\n for (let gap = 1; gap < lineStep; gap += 1) {\n ctx.lines.push({\n text: indent,\n widgetId: widget.id,\n fieldId: bindKey,\n });\n }\n }\n });\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n ctx.inputFields.push({\n id: bindKey,\n value,\n maxLength,\n label,\n lineIndex,\n rows: rowCount,\n lineStep,\n });\n if (!ctx.firstInput) {\n ctx.firstInput = {\n id: bindKey,\n maxLength,\n label,\n };\n }\n return;\n }\n\n if (widget.kind === \"action\") {\n const renderedLabel = interpolate(widget.label, vars);\n const hotkey = normalizeHotkey(widget.hotkey);\n const lineLabel = options.hideHotkeys\n ? renderedLabel\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${renderedLabel}`\n : `[ ${renderedLabel} ]`;\n if (widget.action.type === \"nav.goto\") {\n ctx.lines.push({\n text: lineLabel,\n widgetId: widget.id,\n target: widget.action.target,\n });\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n target: widget.action.target,\n });\n }\n return;\n }\n ctx.lines.push({\n text: lineLabel,\n widgetId: widget.id,\n action: widget.action,\n });\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: widget.action,\n });\n }\n return;\n }\n\n if (widget.kind === \"select\") {\n const bindKey = selectBindKey(widget);\n const label = selectLabel(widget);\n const currentValue = resolveSelectValue(widget, state).trim();\n const normalizedCurrent = currentValue.toLowerCase();\n const gap = Math.max(1, Number(widget.gap ?? 2));\n const parts: string[] = [];\n const labelPrefix = label ? `${label} ` : \"\";\n\n widget.options.forEach((option) => {\n const renderedLabel = interpolate(option.label, vars);\n const hotkey = normalizeHotkey(option.hotkey);\n const normalizedOption = String(option.value || \"\").trim().toLowerCase();\n const selected =\n normalizedCurrent.length > 0 && normalizedCurrent === normalizedOption;\n const displayLabel = selected ? `${renderedLabel}*` : renderedLabel;\n const lineLabel = options.hideHotkeys\n ? displayLabel\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${displayLabel}`\n : `[ ${displayLabel} ]`;\n parts.push(lineLabel);\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: {\n type: \"data.set\",\n path: bindKey,\n value: option.value,\n },\n });\n }\n });\n\n const lineIndex = ctx.lines.length;\n ctx.lines.push({\n text: `${labelPrefix}${parts.join(\" \".repeat(gap))}`.trimEnd(),\n widgetId: widget.id,\n fieldId: bindKey,\n });\n\n ctx.inputFields.push({\n id: bindKey,\n value: currentValue,\n maxLength: 0,\n label,\n lineIndex,\n rows: 1,\n });\n\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n return;\n }\n\n if (widget.kind === \"checkbox\") {\n const bindKey = checkboxBindKey(widget);\n const checked = resolveCheckboxValue(widget, state);\n const marker = checked ? \"[X]\" : \"[ ]\";\n const renderedLabel = interpolate(widget.label, vars);\n const hotkey = normalizeHotkey(widget.hotkey);\n const lineLabel = options.hideHotkeys\n ? `${marker} ${renderedLabel}`\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${marker} ${renderedLabel}`\n : `${marker} ${renderedLabel}`;\n const lineIndex = ctx.lines.length;\n ctx.lines.push({ text: lineLabel, widgetId: widget.id, fieldId: bindKey });\n const toggleAction = widget.action ?? { type: \"data.toggleFlag\" as const, path: bindKey };\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: toggleAction,\n });\n }\n // Add to inputFields to make it navigatable\n ctx.inputFields.push({\n id: bindKey,\n value: String(checked),\n maxLength: 0,\n label: renderedLabel,\n lineIndex,\n rows: 1,\n action: toggleAction,\n });\n return;\n }\n\n if (widget.kind === \"radio\") {\n const bindKey = radioBindKey(widget);\n const currentValue = resolveSelectValue(widget, state).trim();\n const normalizedCurrent = currentValue.toLowerCase();\n const gap = Math.max(1, Number(widget.gap ?? 2));\n const parts: string[] = [];\n const label = widget.label ? `${widget.label} ` : \"\";\n\n widget.options.forEach((option) => {\n const renderedLabel = interpolate(option.label, vars);\n const hotkey = normalizeHotkey(option.hotkey);\n const normalizedOption = String(option.value || \"\").trim().toLowerCase();\n const selected =\n normalizedCurrent.length > 0 && normalizedCurrent === normalizedOption;\n const marker = selected ? \"(o)\" : \"( )\";\n const displayLabel = `${marker} ${renderedLabel}`;\n const lineLabel = options.hideHotkeys\n ? displayLabel\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${displayLabel}`\n : displayLabel;\n parts.push(lineLabel);\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: { type: \"data.set\", path: bindKey, value: option.value },\n });\n }\n });\n\n const lineIndex = ctx.lines.length;\n ctx.lines.push({\n text: `${label}${parts.join(\" \".repeat(gap))}`.trimEnd(),\n widgetId: widget.id,\n fieldId: bindKey,\n });\n\n ctx.inputFields.push({\n id: bindKey,\n value: currentValue,\n maxLength: 0,\n label: widget.label || widget.id,\n lineIndex,\n rows: 1,\n });\n\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n return;\n }\n\n if (widget.kind === \"number\") {\n const bindKey = numberBindKey(widget);\n const value = resolveNumberValue(widget, state);\n const label = widget.label || widget.id;\n const step = typeof widget.step === \"number\" && Number.isFinite(widget.step) ? widget.step : 1;\n const incAction = {\n type: \"data.increment\" as const,\n path: bindKey,\n by: step,\n ...(typeof widget.min === \"number\" ? { min: widget.min } : {}),\n ...(typeof widget.max === \"number\" ? { max: widget.max } : {}),\n };\n const decAction = {\n type: \"data.increment\" as const,\n path: bindKey,\n by: -step,\n ...(typeof widget.min === \"number\" ? { min: widget.min } : {}),\n ...(typeof widget.max === \"number\" ? { max: widget.max } : {}),\n };\n\n const lineLabel = options.hideHotkeys\n ? `${label}: [ ${value} ]`\n : `${label}: [ ${value} ] [+][-]`;\n\n const lineIndex = ctx.lines.length;\n ctx.lines.push({ text: lineLabel, widgetId: widget.id, fieldId: bindKey });\n\n if (!options.hideHotkeys) {\n if (!hotkeySet.has(\"+\")) {\n hotkeySet.add(\"+\");\n ctx.shortcuts.push({ key: \"+\", label: `${label} +`, action: incAction });\n }\n if (!hotkeySet.has(\"-\")) {\n hotkeySet.add(\"-\");\n ctx.shortcuts.push({ key: \"-\", label: `${label} -`, action: decAction });\n }\n }\n\n ctx.inputFields.push({\n id: bindKey,\n value: String(value),\n maxLength: 0,\n label,\n lineIndex,\n rows: 1,\n });\n\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n return;\n }\n\n if (widget.kind === \"date\") {\n const bindKey = dateBindKey(widget);\n const iso = resolveDateValue(widget, state);\n const parsed = parseISODate(iso);\n const label = widget.label || widget.id;\n const display = widget.display || \"inline\";\n\n const dateLineIndex = ctx.lines.length;\n\n if (display === \"calendar\" && parsed) {\n const monthLabel = `${MONTH_NAMES[parsed.m - 1]} ${parsed.y}`;\n ctx.lines.push({ text: `${label}: ${monthLabel}`, widgetId: widget.id, fieldId: bindKey });\n\n const navLine = options.hideHotkeys\n ? \"\"\n : `[<] [>]`;\n if (navLine) ctx.lines.push({ text: navLine, widgetId: widget.id });\n\n const calLines = buildCalendarLines(parsed.y, parsed.m, parsed.d);\n for (const cl of calLines) {\n ctx.lines.push({ text: cl, widgetId: widget.id });\n }\n\n if (!options.hideHotkeys) {\n if (!hotkeySet.has(\"<\")) {\n hotkeySet.add(\"<\");\n ctx.shortcuts.push({\n key: \"<\",\n label: `${label} prev month`,\n action: { type: \"data.set\", path: bindKey, value: shiftMonth(iso, -1) },\n });\n }\n if (!hotkeySet.has(\">\")) {\n hotkeySet.add(\">\");\n ctx.shortcuts.push({\n key: \">\",\n label: `${label} next month`,\n action: { type: \"data.set\", path: bindKey, value: shiftMonth(iso, 1) },\n });\n }\n }\n } else if (parsed) {\n // inline display\n const displayStr = formatDisplayDate(parsed.y, parsed.m, parsed.d);\n const lineLabel = options.hideHotkeys\n ? `${label}: ${displayStr}`\n : `${label}: [<] ${displayStr} [>]`;\n ctx.lines.push({ text: lineLabel, widgetId: widget.id, fieldId: bindKey });\n\n if (!options.hideHotkeys) {\n if (!hotkeySet.has(\"<\")) {\n hotkeySet.add(\"<\");\n ctx.shortcuts.push({\n key: \"<\",\n label: `${label} prev day`,\n action: { type: \"data.set\", path: bindKey, value: shiftDay(iso, -1) },\n });\n }\n if (!hotkeySet.has(\">\")) {\n hotkeySet.add(\">\");\n ctx.shortcuts.push({\n key: \">\",\n label: `${label} next day`,\n action: { type: \"data.set\", path: bindKey, value: shiftDay(iso, 1) },\n });\n }\n }\n }\n\n // Enter opens full-screen date picker\n if (!ctx.enterAction) {\n ctx.enterAction = {\n type: \"data.set\",\n path: \"__datePicker\",\n value: {\n bindPath: bindKey,\n currentISO: iso,\n returnScreenId: screenSpec.id,\n },\n };\n }\n\n ctx.inputFields.push({\n id: bindKey,\n value: iso,\n maxLength: 0,\n label,\n lineIndex: dateLineIndex,\n rows: 1,\n });\n\n const validationMessage = String(state.fieldErrors?.[bindKey] || \"\").trim();\n if (validationMessage) {\n ctx.lines.push({ text: `! ${validationMessage}`, widgetId: widget.id });\n }\n return;\n }\n\n if (widget.kind === \"row\") {\n const gap = Math.max(1, Number(widget.gap ?? 2));\n const parts: string[] = [];\n widget.items.forEach((item) => {\n if (item.kind === \"text\") {\n parts.push(interpolate(item.text, vars));\n return;\n }\n const renderedLabel = interpolate(item.label, vars);\n const hotkey = normalizeHotkey(item.hotkey);\n const lineLabel = options.hideHotkeys\n ? renderedLabel\n : hotkey\n ? `[${hotkey.toUpperCase()}] ${renderedLabel}`\n : `[ ${renderedLabel} ]`;\n parts.push(lineLabel);\n if (!options.hideHotkeys && hotkey && !hotkeySet.has(hotkey)) {\n hotkeySet.add(hotkey);\n ctx.shortcuts.push({\n key: hotkey,\n label: renderedLabel,\n action: item.action,\n });\n }\n });\n ctx.lines.push({\n text: parts.join(\" \".repeat(gap)),\n widgetId: widget.id,\n });\n return;\n }\n\n if (widget.kind === \"table\") {\n const padCell = (text: string, width: number, align: \"left\" | \"right\" = \"left\"): string => {\n const truncated = text.length > width ? text.slice(0, width) : text;\n return align === \"right\" ? truncated.padStart(width) : truncated.padEnd(width);\n };\n\n const marginTop = Math.max(0, Number(widget.marginTop ?? 1));\n if (marginTop) pushSpacerLines(marginTop);\n\n const listValue = resolvePath(vars, widget.bind);\n let rows = Array.isArray(listValue) ? listValue : [];\n if (widget.whereEqualsPath) {\n rows = rows.filter((item) => {\n const raw = resolvePath(item, widget.whereEqualsPath || \"\");\n return raw === widget.whereEquals;\n });\n }\n const sortByPath = String(widget.sortByPath || \"\").trim();\n if (sortByPath) {\n const direction =\n String(widget.sortDirection || \"asc\").trim().toLowerCase() === \"desc\"\n ? -1\n : 1;\n rows = [...rows].sort((left, right) => {\n const leftValue = resolvePath(left, sortByPath);\n const rightValue = resolvePath(right, sortByPath);\n const primary = compareSortValues(leftValue, rightValue) * direction;\n if (primary !== 0) return primary;\n return compareSortValues(resolvePath(left, \"id\"), resolvePath(right, \"id\"));\n });\n }\n\n const cols = widget.columns;\n const separator = \"+\" + cols.map((c) => \"-\".repeat(c.width)).join(\"+\") + \"+\";\n const headerRow = \"|\" + cols.map((c) => padCell(c.header, c.width)).join(\"|\") + \"|\";\n\n ctx.lines.push({ text: separator, widgetId: widget.id });\n ctx.lines.push({ text: headerRow, widgetId: widget.id });\n ctx.lines.push({ text: separator, widgetId: widget.id });\n\n if (!rows.length) {\n const emptyText = widget.emptyText || \"(no rows)\";\n const totalInner = cols.reduce((sum, c) => sum + c.width, 0) + cols.length - 1;\n const paddedEmpty = emptyText.length > totalInner ? emptyText.slice(0, totalInner) : emptyText.padEnd(totalInner);\n ctx.lines.push({ text: \"|\" + paddedEmpty + \"|\", widgetId: widget.id });\n ctx.lines.push({ text: separator, widgetId: widget.id });\n const marginBottom = Math.max(0, Number(widget.marginBottom ?? 1));\n if (marginBottom) pushSpacerLines(marginBottom);\n return;\n }\n\n const maxVisible = Math.max(1, Number(widget.height) || 10);\n const tableScrollable = rows.length > maxVisible;\n const tableOffset = Math.max(0, Math.min(options.listScrollOffsets?.[widget.id] ?? 0, rows.length - maxVisible));\n const visibleRows = rows.slice(tableOffset, tableOffset + maxVisible);\n\n if (tableScrollable) {\n ctx.lines.push({ text: tableOffset > 0 ? `\\u2191 ${tableOffset} more` : \"\", widgetId: widget.id });\n }\n\n visibleRows.forEach((item, sliceIndex) => {\n const index = tableOffset + sliceIndex;\n const fields: Record<string, string> = {};\n Object.entries(widget.rowActionFields || {}).forEach(([fieldId, valuePath]) => {\n const raw = resolvePath(item, String(valuePath || \"\").trim());\n fields[String(fieldId)] = raw == null ? \"\" : String(raw);\n });\n const rowActionField = String(widget.rowActionField || \"\").trim();\n if (rowActionField) {\n const valuePath = String(widget.rowActionValuePath || \"\").trim() || \"id\";\n const rawValue = resolvePath(item, valuePath);\n fields[rowActionField] = rawValue == null ? \"\" : String(rawValue);\n }\n const hasFields = Object.keys(fields).length > 0;\n const rowAction = widget.rowAction;\n\n const cellTexts = cols.map((c) => {\n const raw = resolvePath(item, c.path);\n return padCell(raw == null ? \"\" : String(raw), c.width, c.align);\n });\n\n ctx.lines.push({\n text: \"|\" + cellTexts.join(\"|\") + \"|\",\n widgetId: widget.id,\n selectable: Boolean(rowAction),\n target: rowAction?.type === \"nav.goto\" ? rowAction.target : undefined,\n action: rowAction && rowAction.type !== \"nav.goto\" ? rowAction : undefined,\n fields: hasFields ? fields : undefined,\n });\n });\n\n // Pad to stable height: always emit exactly maxVisible data-row slots\n const dataRowsEmitted = visibleRows.length;\n for (let pad = dataRowsEmitted; pad < maxVisible; pad++) {\n ctx.lines.push({ text: \"\", widgetId: widget.id });\n }\n\n if (tableScrollable) {\n const belowCount = rows.length - tableOffset - visibleRows.length;\n ctx.lines.push({ text: belowCount > 0 ? `\\u2193 ${belowCount} more` : \"\", widgetId: widget.id });\n }\n\n ctx.lines.push({ text: separator, widgetId: widget.id });\n\n if (rows.length > maxVisible) {\n ctx.listScrollInfo![widget.id] = { totalRows: rows.length, visibleRows: visibleRows.length, offset: tableOffset };\n }\n const marginBottom = Math.max(0, Number(widget.marginBottom ?? 1));\n if (marginBottom) pushSpacerLines(marginBottom);\n return;\n }\n\n if (widget.kind === \"list\") {\n const marginTop = Math.max(0, Number(widget.marginTop ?? 1));\n if (marginTop) pushSpacerLines(marginTop);\n const listValue = resolvePath(vars, widget.bind);\n let rows = Array.isArray(listValue) ? listValue : [];\n if (widget.whereEqualsPath) {\n rows = rows.filter((item) => {\n const raw = resolvePath(item, widget.whereEqualsPath || \"\");\n return raw === widget.whereEquals;\n });\n }\n const sortByPath = String(widget.sortByPath || \"\").trim();\n if (sortByPath) {\n const direction =\n String(widget.sortDirection || \"asc\").trim().toLowerCase() === \"desc\"\n ? -1\n : 1;\n rows = [...rows].sort((left, right) => {\n const leftValue = resolvePath(left, sortByPath);\n const rightValue = resolvePath(right, sortByPath);\n const primary = compareSortValues(leftValue, rightValue) * direction;\n if (primary !== 0) return primary;\n return compareSortValues(resolvePath(left, \"id\"), resolvePath(right, \"id\"));\n });\n }\n if (!rows.length) {\n ctx.lines.push({\n text: widget.emptyText || \"(no rows)\",\n widgetId: widget.id,\n });\n const marginBottom = Math.max(0, Number(widget.marginBottom ?? 1));\n if (marginBottom) pushSpacerLines(marginBottom);\n return;\n }\n const listMaxVisible = Math.max(1, Number(widget.height) || 10);\n const listScrollable = rows.length > listMaxVisible;\n const listOffset = Math.max(0, Math.min(options.listScrollOffsets?.[widget.id] ?? 0, rows.length - listMaxVisible));\n const listVisibleRows = rows.slice(listOffset, listOffset + listMaxVisible);\n\n if (listScrollable) {\n ctx.lines.push({ text: listOffset > 0 ? `\\u2191 ${listOffset} more` : \"\", widgetId: widget.id });\n }\n\n listVisibleRows.forEach((item, sliceIndex) => {\n const index = listOffset + sliceIndex;\n const fields: Record<string, string> = {};\n Object.entries(widget.rowActionFields || {}).forEach(([fieldId, valuePath]) => {\n const raw = resolvePath(item, String(valuePath || \"\").trim());\n fields[String(fieldId)] = raw == null ? \"\" : String(raw);\n });\n const rowActionField = String(widget.rowActionField || \"\").trim();\n if (rowActionField) {\n const valuePath = String(widget.rowActionValuePath || \"\").trim() || \"id\";\n const rawValue = resolvePath(item, valuePath);\n fields[rowActionField] = rawValue == null ? \"\" : String(rawValue);\n }\n const hasFields = Object.keys(fields).length > 0;\n const rowAction = widget.rowAction;\n const lineIndex = ctx.lines.length;\n ctx.lines.push({\n text: interpolate(widget.rowTemplate, {\n ...vars,\n item,\n index: index + 1,\n }),\n widgetId: widget.id,\n selectable: Boolean(rowAction),\n target: rowAction?.type === \"nav.goto\" ? rowAction.target : undefined,\n action:\n rowAction && rowAction.type !== \"nav.goto\" ? rowAction : undefined,\n fields: hasFields ? fields : undefined,\n });\n\n // Add actionLine for clickable rows\n if (rowAction) {\n ctx.actionLines.push({\n index: lineIndex,\n selectable: true,\n target: rowAction.type === \"nav.goto\" ? rowAction.target : undefined,\n action: rowAction.type !== \"nav.goto\" ? rowAction : undefined,\n fields: hasFields ? fields : undefined,\n });\n }\n });\n\n // Pad to stable height: always emit exactly listMaxVisible data-row slots\n const listDataRowsEmitted = listVisibleRows.length;\n for (let pad = listDataRowsEmitted; pad < listMaxVisible; pad++) {\n ctx.lines.push({ text: \"\", widgetId: widget.id });\n }\n\n if (listScrollable) {\n const listBelowCount = rows.length - listOffset - listVisibleRows.length;\n ctx.lines.push({ text: listBelowCount > 0 ? `\\u2193 ${listBelowCount} more` : \"\", widgetId: widget.id });\n }\n\n if (rows.length > listMaxVisible) {\n ctx.listScrollInfo![widget.id] = { totalRows: rows.length, visibleRows: listVisibleRows.length, offset: listOffset };\n }\n const marginBottom = Math.max(0, Number(widget.marginBottom ?? 1));\n if (marginBottom) pushSpacerLines(marginBottom);\n }\n });\n return ctx;\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nexport type CliConfig = {\n webOrigin: string;\n terminalUrl: string;\n firebaseProjectId: string;\n idToken?: string;\n tokenExp?: number;\n appCheckToken?: string;\n};\n\n// Production defaults — only BLO_* env vars can override (never VITE_*).\nconst defaultWebOrigin = process.env.BLO_WEB_ORIGIN || \"https://buildless.online\";\nconst defaultTerminalUrl = process.env.BLO_TERMINAL_URL || \"https://buildless.online\";\nconst defaultProjectId = process.env.BLO_FIREBASE_PROJECT_ID || \"buildless-online\";\n\nconst resolveConfigPath = (): string => {\n if (process.env.BLO_CONFIG_PATH) return process.env.BLO_CONFIG_PATH;\n const home = os.homedir();\n const configDir = process.env.XDG_CONFIG_HOME || path.join(home, \".config\");\n return path.join(configDir, \"blo\", \"cli.json\");\n};\n\nexport const loadConfig = (): { path: string; config: CliConfig } => {\n const configPath = resolveConfigPath();\n const defaults: CliConfig = {\n webOrigin: defaultWebOrigin,\n terminalUrl: defaultTerminalUrl,\n firebaseProjectId: defaultProjectId,\n };\n\n if (!fs.existsSync(configPath)) {\n return { path: configPath, config: defaults };\n }\n\n try {\n const raw = fs.readFileSync(configPath, \"utf8\");\n const parsed = JSON.parse(raw) as Partial<CliConfig>;\n return {\n path: configPath,\n config: {\n // Merge persisted values (tokens) with authoritative defaults.\n // Service URLs and project ID always come from defaults (env or\n // hardcoded prod) so a stale config file can't point the\n // published CLI at the wrong Firebase project.\n ...defaults,\n idToken: parsed.idToken,\n tokenExp: parsed.tokenExp,\n appCheckToken: parsed.appCheckToken,\n },\n };\n } catch (err) {\n process.stderr.write(`Warning: failed to parse ${configPath}, using defaults: ${err instanceof Error ? err.message : String(err)}\\n`);\n return { path: configPath, config: defaults };\n }\n};\n\nexport const saveConfig = (configPath: string, config: CliConfig): void => {\n const dir = path.dirname(configPath);\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 0o600 });\n};\n"],"mappings":"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","names":["useEffect","useState","Box","Text","URL","URL","body","useEffect","useMemo","useRef","useState","Box","Text","useInput","useState","useState","useMemo","path","marginBottom","useMemo","jsx","jsxs","useState","useRef","useEffect","useMemo","activeField","useInput","Box","Text","jsx","jsxs","useState","useEffect","Box","Text","jsx","path"]}
|