@kizenapps/cli 1.11.0-3670c77 → 1.12.0-a2af6ac
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 +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/program.ts","../src/commands/build.ts","../src/ui/BuildUI.tsx","../src/lib/runBuild.ts","../src/lib/readFiles.ts","../shared/lib/formatBytes.ts","../src/ui/AppHeader.tsx","../src/ui/Logo.tsx","../src/ui/Spinner.tsx","../src/ui/ValidationIssues.tsx","../src/lib/gitignore.ts","../src/commands/create.ts","../src/ui/CreateUI.tsx","../src/lib/createPlugin.ts","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/floatingFrames/helloFrame/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/floatingFrames/helloFrame/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/floatingFrames/helloFrame/styles.css?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/blocks/helloBlock/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/blocks/helloBlock/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/blocks/helloBlock/styles.css?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/dataAdornments/helloAdornment/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/dataAdornments/helloAdornment/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/pages/helloPage/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/pages/helloPage/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/pages/helloPage/styles.css?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/pages/helloPage/eventScripts/greet.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/toolbarItems/helloToolbarItem/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/toolbarItems/helloToolbarItem/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/objectSettingsItems/helloObjectSettingsItem/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/objectSettingsItems/helloObjectSettingsItem/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/actions/helloAction/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/actions/helloAction/script.js?raw","../src/lib/createArtifacts.ts","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/github/copilot-instructions.md?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/github/instructions/security.instructions.md?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/github/instructions/version-discipline.instructions.md?raw","../src/lib/createCopilotFiles.ts","../src/lib/createThumbnail.ts","../src/lib/createForm.ts","../src/lib/credentials.ts","../shared/lib/credentials.ts","../src/lib/createHeadless.ts","../src/commands/dev.ts","../src/ui/DevUI.tsx","../src/server/requestHandler.ts","../src/lib/proxyCache.ts","../src/lib/constants.ts","../src/lib/config.ts","../src/lib/wizardUrl.ts","../src/server/pythonExecutor.ts","../src/server/python-requirements.txt","../src/lib/pythonRuntime.ts","../shared/lib/execution.ts","../shared/lib/fileExtensions.ts","../shared/lib/proxy.ts","../src/chrome/launcher.ts","../src/hooks/useLogHistory.ts","../src/ui/CredentialSetupUI.tsx","../src/commands/encrypt.ts","../src/ui/EncryptUI.tsx","../src/lib/encryptionClient.ts","../src/lib/clipboard.ts","../src/lib/encryptHelpers.ts","../src/lib/encryptHeadless.ts","../shared/lib/validIcons.ts","../src/commands/icons.ts","../src/commands/report.ts","../src/lib/reportHelpers.ts","../src/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Command } from 'commander';\nimport { buildCommand } from './commands/build.js';\nimport { createCommand } from './commands/create.js';\nimport { devCommand } from './commands/dev.js';\nimport { encryptCommand } from './commands/encrypt.js';\nimport { iconsCommand } from './commands/icons.js';\nimport { reportCommand } from './commands/report.js';\n\nfunction readVersion(): string {\n const pkgPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as { version: string };\n\n return pkg.version;\n}\n\nexport function createProgram(): Command {\n const program = new Command();\n\n program.name('appbuilder').description('Kizen plugin app builder').version(readVersion());\n\n createCommand(program);\n\n buildCommand(program);\n\n devCommand(program);\n\n encryptCommand(program);\n\n reportCommand(program);\n\n iconsCommand(program);\n\n return program;\n}\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { BuildUI } from '../ui/BuildUI.js';\nimport { ensureGitignore } from '../lib/gitignore.js';\n\nexport function buildCommand(program: Command): void {\n program\n .command('build')\n .description('Bundle the plugin app into .kizenapp directory')\n .action(async () => {\n const pluginDir = process.cwd();\n const outputDir = `${pluginDir}/.kizenapp`;\n\n ensureGitignore(pluginDir);\n\n const { waitUntilExit } = render(createElement(BuildUI, { outputDir, pluginDir }));\n\n await waitUntilExit();\n });\n}\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { Box, Text, useApp } from 'ink';\nimport { PluginValidationError } from '@kizenapps/packager';\nimport type { ValidationIssue } from '@kizenapps/packager';\nimport { runBuild } from '../lib/runBuild.js';\nimport type { BuildStepName } from '../lib/runBuild.js';\nimport { formatBytes } from '../../shared/lib/formatBytes.js';\nimport { AppHeader } from './AppHeader.js';\nimport { Spinner } from './Spinner.js';\nimport { ValidationIssues } from './ValidationIssues.js';\n\ntype BuildStep = BuildStepName | 'done';\n\ninterface BuildUIProps {\n outputDir: string;\n pluginDir: string;\n}\n\nconst STEPS: BuildStepName[] = [\n 'creating-dir',\n 'reading-files',\n 'validating',\n 'minifying',\n 'packaging',\n 'writing-bundle',\n];\n\nconst STEP_LABELS: Record<BuildStepName, string> = {\n 'creating-dir': 'Creating .kizenapp directory',\n 'reading-files': 'Reading plugin files',\n validating: 'Validating plugin app',\n minifying: 'Minifying scripts',\n packaging: 'Packaging plugin',\n 'writing-bundle': 'Writing bundle.json',\n};\n\nexport const BuildUI: FC<BuildUIProps> = ({ outputDir, pluginDir }) => {\n const app = useApp();\n const [step, setStep] = useState<BuildStep>('creating-dir');\n const [failed, setFailed] = useState(false);\n const [issues, setIssues] = useState<ValidationIssue[] | null>(null);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [bundleSize, setBundleSize] = useState<number | null>(null);\n\n useEffect(() => {\n void runBuild(pluginDir, outputDir, setStep)\n .then(({ bundleSize: size }) => {\n setBundleSize(size);\n setStep('done');\n })\n .catch((err: unknown) => {\n if (err instanceof PluginValidationError) {\n setIssues(err.issues);\n } else {\n setErrorMessage(err instanceof Error ? err.message : String(err));\n }\n\n // Leave `step` on the step that was running so the ✗ lands on it.\n setFailed(true);\n process.exitCode = 1;\n });\n }, [outputDir, pluginDir]);\n\n // Exit only once the terminal frame has been committed and written to the\n // terminal. Calling app.exit() in the same tick as the state updates would\n // unmount ink before it paints the done/error frame, leaving the spinner as\n // the last thing on screen.\n useEffect(() => {\n if (step === 'done' || failed) {\n app.exit();\n }\n }, [step, failed, app]);\n\n const currentIndex = STEPS.indexOf(step as BuildStepName);\n const isDone = step === 'done';\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2}>\n <AppHeader marginBottom={1} />\n\n <Box flexDirection=\"column\" gap={0}>\n {STEPS.map((s, i) => {\n const isActive = step === s;\n const isStepDone = isDone || currentIndex > i;\n const isFailed = failed && i === currentIndex;\n\n return (\n <Box key={s} gap={1}>\n {isFailed ? (\n <Text color=\"red\">✗ {STEP_LABELS[s]}</Text>\n ) : isStepDone ? (\n <Text color=\"green\">✓ {STEP_LABELS[s]}</Text>\n ) : isActive ? (\n <>\n <Spinner />\n <Text>{STEP_LABELS[s]}</Text>\n </>\n ) : (\n <Text dimColor> {STEP_LABELS[s]}</Text>\n )}\n </Box>\n );\n })}\n\n {isDone && bundleSize !== null && (\n <Box marginTop={1} gap={1}>\n <Text color=\"green\">✓ bundle — {formatBytes(bundleSize)}</Text>\n </Box>\n )}\n\n {issues !== null && <ValidationIssues issues={issues} />}\n\n {errorMessage !== null && (\n <Box marginTop={1} borderStyle=\"single\" borderColor=\"red\" paddingX={1}>\n <Text color=\"red\">{errorMessage}</Text>\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n PluginValidationError,\n minifyFiles,\n packagePlugin,\n parseManifestFromFiles,\n transformDeployablePlugin,\n validatePluginApp,\n} from '@kizenapps/packager';\nimport type { DeployablePlugin } from '@kizenapps/packager';\nimport { readLocalFiles } from './readFiles.js';\n\nexport type BuildStepName =\n | 'creating-dir'\n | 'reading-files'\n | 'validating'\n | 'minifying'\n | 'packaging'\n | 'writing-bundle';\n\ninterface ReleaseNote {\n version: string;\n notes: string;\n}\n\ntype SerializableDeployablePlugin = Omit<DeployablePlugin, 'thumbnail' | 'kznFile'> & {\n thumbnail: string | null;\n kznFile: string | null;\n allReleaseNotes: ReleaseNote[];\n};\n\nconst serializePlugin = (\n plugin: DeployablePlugin,\n allReleaseNotes: ReleaseNote[],\n): SerializableDeployablePlugin => ({\n ...plugin,\n thumbnail: plugin.thumbnail ? Buffer.from(plugin.thumbnail).toString('base64') : null,\n kznFile: plugin.kznFile ? Buffer.from(plugin.kznFile).toString('base64') : null,\n allReleaseNotes,\n});\n\nexport interface BuildResult {\n bundleSize: number;\n}\n\nexport async function runBuild(\n pluginDir: string,\n outputDir: string,\n onStep?: (step: BuildStepName) => void,\n): Promise<BuildResult> {\n await mkdir(outputDir, { recursive: true });\n\n onStep?.('reading-files');\n\n const files = await readLocalFiles(pluginDir);\n\n onStep?.('validating');\n\n const issues = validatePluginApp(files);\n\n if (issues.some((issue) => issue.severity === 'error')) {\n throw new PluginValidationError(issues);\n }\n\n onStep?.('minifying');\n\n const minified = await minifyFiles(files);\n\n onStep?.('packaging');\n\n const manifests = parseManifestFromFiles(minified);\n const packaged = packagePlugin(minified, manifests);\n const deployable = Object.values(packaged).map(transformDeployablePlugin);\n\n onStep?.('writing-bundle');\n\n const bundle = deployable.map((plugin) => {\n const notesDir = plugin.release_notes_directory?.replace(/\\/$/, '');\n const allReleaseNotes: ReleaseNote[] = notesDir\n ? files\n .filter((f) => f.path.startsWith(notesDir + '/') && f.path.endsWith('.md') && f.content)\n .map((f) => ({\n version: f.path.slice(f.path.lastIndexOf('/') + 1, -3),\n notes: f.content,\n }))\n .sort((a, b) => b.version.localeCompare(a.version, undefined, { numeric: true }))\n : [];\n\n return serializePlugin(plugin, allReleaseNotes);\n });\n\n const jsonStr = JSON.stringify(bundle, null, 2);\n\n // Report the size of the plugin bundle excluding the informational release\n // notes, so \"bundle: 12KB\" reflects actual plugin code rather than long\n // markdown changelogs.\n const stripReleaseNotes = (key: string, value: unknown): unknown =>\n key === 'allReleaseNotes' ? undefined : value;\n const bundleSize = Buffer.byteLength(JSON.stringify(bundle, stripReleaseNotes, 2), 'utf-8');\n\n await writeFile(join(outputDir, 'bundle.json'), jsonStr, 'utf-8');\n\n return { bundleSize };\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { FileContent } from '@kizenapps/packager';\n\nconst IMAGE_EXTENSIONS = new Set(['.png', '.svg']);\nconst BINARY_EXTENSIONS = new Set(['.kzn']);\nconst SKIP_FILES = new Set(['.DS_Store']);\n\nexport const SKIP_DIRS = new Set([\n 'node_modules',\n '.git',\n '.kizenapp',\n '.github',\n '.claude',\n '__pycache__',\n]);\n\n// a NUL in the first 8 KB means binary\nconst BINARY_SNIFF_BYTES = 8000;\n\nfunction looksBinary(buf: Buffer): boolean {\n return buf.subarray(0, BINARY_SNIFF_BYTES).includes(0);\n}\n\nexport interface ReadLocalFilesOptions {\n detectBinaryByContent?: boolean;\n}\n\nasync function walk(dir: string, rootDir: string): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const paths: string[] = [];\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) {\n continue;\n }\n\n paths.push(...(await walk(join(dir, entry.name), rootDir)));\n } else if (entry.isFile()) {\n if (!SKIP_FILES.has(entry.name)) {\n paths.push(join(dir, entry.name));\n }\n }\n }\n\n return paths;\n}\n\nexport async function readLocalFiles(\n rootDir: string,\n { detectBinaryByContent = false }: ReadLocalFilesOptions = {},\n): Promise<FileContent[]> {\n const absolutePaths = await walk(rootDir, rootDir);\n\n return Promise.all(\n absolutePaths.map(async (absPath): Promise<FileContent> => {\n const relPath = relative(rootDir, absPath).split('\\\\').join('/');\n const dotIndex = relPath.lastIndexOf('.');\n const ext = dotIndex >= 0 ? relPath.slice(dotIndex).toLowerCase() : '';\n\n if (IMAGE_EXTENSIONS.has(ext)) {\n const buf = await readFile(absPath);\n\n return { path: relPath, content: '', base64Image: buf.toString('base64') };\n }\n\n const buf = await readFile(absPath);\n\n if (BINARY_EXTENSIONS.has(ext) || (detectBinaryByContent && looksBinary(buf))) {\n return { path: relPath, content: '', binaryData: buf };\n }\n\n return { path: relPath, content: buf.toString('utf-8') };\n }),\n );\n}\n","export function formatBytes(n: number): string {\n if (n < 1024) {\n return `${String(n)} B`;\n }\n\n if (n < 1024 * 1024) {\n return `${(n / 1024).toFixed(1)} KB`;\n }\n\n return `${(n / (1024 * 1024)).toFixed(2)} MB`;\n}\n","import type { FC } from 'react';\nimport { Box, Text } from 'ink';\nimport { Logo } from './Logo.js';\n\ninterface AppHeaderProps {\n marginBottom?: number;\n}\n\nexport const AppHeader: FC<AppHeaderProps> = ({ marginBottom = 0 }) => (\n <>\n <Logo />\n <Box flexDirection=\"column\" marginTop={1} marginBottom={marginBottom}>\n <Text bold color=\"cyan\">\n Kizen App Development Toolkit\n </Text>\n </Box>\n </>\n);\n","import type { FC } from 'react';\nimport { Box, Text } from 'ink';\n\nconst LOGO_LINES = [\n ' :::::::: ',\n ' :::::: ::::::::::: ',\n ' :::::: :::::::::: ',\n ' :::::: :::::: ::::::: ',\n ' ::::: :::::: ::::::::::::::::: ',\n ' ::::: ::::: ::::::::::::::::::: ',\n ' ::::: ::::: :::::: ::::: ',\n ':::: ::::: ::: ::::: :: ',\n '::::: :::::: :::::::::: ',\n '::::: :::::: ::::::::::: ',\n ' ::::: ::: ::::::: ',\n ' ::::::: ::: ::::: ',\n ' ::::::::::: :::::: :::::',\n ' :::::::::: :::::: :::::',\n ' :: ::::: ::: ::::: ::::',\n ' ::::: :::::: ::::: ::::: ::: ',\n ' ::::::::::::::::::: ::::: ::::: ',\n ' ::::::::::::::::: ::::: ::::: ',\n ' ::::::::: :::::: :::::: ',\n ' :::::::::: :::::: ',\n ' ::::::::::: :::::: ',\n ' :::::::: ',\n];\n\nexport const Logo: FC = () => (\n <Box flexDirection=\"column\">\n {LOGO_LINES.map((line, i) => (\n <Text key={i} color=\"cyan\">\n {line}\n </Text>\n ))}\n </Box>\n);\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { Text } from 'ink';\n\nexport const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nexport const Spinner: FC = () => {\n const [frame, setFrame] = useState(0);\n\n useEffect(() => {\n const id = setInterval(() => {\n setFrame((prev) => (prev + 1) % SPINNER_FRAMES.length);\n }, 80);\n\n return () => {\n clearInterval(id);\n };\n }, []);\n\n return <Text color=\"cyan\">{SPINNER_FRAMES[frame] ?? '⠋'}</Text>;\n};\n","import type { FC } from 'react';\nimport { Box, Text } from 'ink';\nimport type { ValidationIssue } from '@kizenapps/packager';\n\nconst groupIssuesByPath = (issues: ValidationIssue[]): Map<string, ValidationIssue[]> => {\n const groups = new Map<string, ValidationIssue[]>();\n\n for (const issue of issues) {\n const key = issue.path ?? issue.pluginApiName ?? 'general';\n const group = groups.get(key) ?? [];\n\n group.push(issue);\n groups.set(key, group);\n }\n\n return groups;\n};\n\ninterface ValidationIssuesProps {\n issues: ValidationIssue[];\n}\n\nexport const ValidationIssues: FC<ValidationIssuesProps> = ({ issues }) => {\n // The build only throws on error-severity issues, but `issues` also carries\n // any warnings; the header must count errors only, not the whole array.\n const errorCount = issues.filter((issue) => issue.severity === 'error').length;\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"red\">\n ✗ {errorCount} validation {errorCount === 1 ? 'error' : 'errors'}\n </Text>\n\n {[...groupIssuesByPath(issues)].map(([path, group]) => (\n <Box key={path} flexDirection=\"column\" marginTop={1}>\n <Text bold>{path}</Text>\n\n {group.map((issue, i) => (\n <Box key={`${issue.rule}-${String(i)}`} paddingLeft={2}>\n <Text color={issue.severity === 'error' ? 'red' : 'yellow'}>\n {issue.severity === 'error' ? '✗' : '⚠'} {issue.message}{' '}\n <Text dimColor>({issue.rule})</Text>\n </Text>\n </Box>\n ))}\n </Box>\n ))}\n </Box>\n );\n};\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport function ensureGitignore(projectDir: string): void {\n const gitignorePath = path.join(projectDir, '.gitignore');\n const entry = '.kizenapp/';\n\n let contents = '';\n\n if (fs.existsSync(gitignorePath)) {\n contents = fs.readFileSync(gitignorePath, 'utf8');\n\n const lines = contents.split('\\n').map((l) => l.trim());\n\n if (lines.includes(entry) || lines.includes('.kizenapp')) {\n return;\n }\n }\n\n const addition = contents.endsWith('\\n') ? entry + '\\n' : '\\n' + entry + '\\n';\n\n fs.writeFileSync(gitignorePath, contents + addition);\n}\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { CreateUI } from '../ui/CreateUI.js';\nimport { loadGlobalCredentials } from '../lib/credentials.js';\nimport { createPlugin, precheckTargetDir } from '../lib/createPlugin.js';\nimport { runHeadlessCreate } from '../lib/createHeadless.js';\nimport type { CreateOptions } from '../lib/createHeadless.js';\nimport { ARTIFACT_TYPES } from '../lib/createArtifacts.js';\nimport { ENVIRONMENTS } from '../../shared/lib/credentials.js';\n\nexport function createCommand(program: Command): void {\n program\n .command('create')\n .description('Scaffold a new Kizen plugin project')\n .option('-n, --name <name>', 'plugin display name (implies a non-interactive run)')\n .option('-a, --api-name <name>', 'plugin api_name (inferred from --name when omitted)')\n .option('-d, --description <text>', 'plugin description')\n .option('-l, --external-link <url>', 'external link shown on the plugin listing')\n .option('-b, --business-id <id>', 'developer business id (defaults to saved credentials)')\n .option(\n '-e, --environment <env>',\n `environment the business id belongs to: ${ENVIRONMENTS.join(', ')} (defaults to saved credentials)`,\n )\n .option(\n '--artifacts <list>',\n `comma-separated artifact types, or \"all\" / \"none\" (default: all). Types: ${ARTIFACT_TYPES.join(', ')}`,\n )\n .action(async (options: CreateOptions) => {\n const parentDir = process.cwd();\n const globalCreds = await loadGlobalCredentials();\n const defaultBusinessId = globalCreds?.businessId ?? '';\n const defaultEnvironment = globalCreds?.environment ?? 'go';\n\n const suppliedFlags = Object.values(options).some((value) => value !== undefined);\n\n const isNonInteractive = !process.stdin.isTTY || !process.stdout.isTTY || suppliedFlags;\n\n if (isNonInteractive) {\n await runHeadlessCreate(\n options,\n { businessId: defaultBusinessId, environment: defaultEnvironment },\n parentDir,\n {\n precheckTargetDir,\n createPlugin,\n writeStdout: (text) => {\n process.stdout.write(text);\n },\n writeStderr: (text) => {\n process.stderr.write(text);\n },\n setExitCode: (code) => {\n process.exitCode = code;\n },\n },\n );\n\n return;\n }\n\n const { waitUntilExit } = render(\n createElement(CreateUI, { parentDir, defaultBusinessId, defaultEnvironment }),\n { exitOnCtrlC: false },\n );\n\n await waitUntilExit();\n });\n}\n","import type { FC } from 'react';\nimport { useCallback, useState } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport { join } from 'node:path';\nimport {\n buildManifest,\n createPlugin,\n findAvailableSubDir,\n precheckTargetDir,\n} from '../lib/createPlugin.js';\nimport type { PrecheckResult } from '../lib/createPlugin.js';\nimport {\n emptyValues,\n FIELD_LABELS,\n FIELDS,\n inferApiName,\n normalizeFieldValue,\n REQUIRED_FIELDS,\n toggleArtifactSelection,\n validateField,\n} from '../lib/createForm.js';\nimport type { FieldValues } from '../lib/createForm.js';\nimport { ARTIFACT_LABELS, ARTIFACT_TYPES } from '../lib/createArtifacts.js';\nimport type { ArtifactType } from '../lib/createArtifacts.js';\nimport type { Environment } from '../../shared/lib/credentials.js';\nimport { AppHeader } from './AppHeader.js';\n\ntype Mode = 'in-place' | 'sub-dir';\n\ntype Phase =\n | { type: 'target-select'; cursor: 0 | 1 }\n | { type: 'precheck-error'; targetDir: string; reason: PrecheckResult }\n | { type: 'field-entry'; field: number; values: FieldValues; fieldError?: string }\n | {\n type: 'artifact-select';\n values: FieldValues;\n cursor: number;\n selected: readonly ArtifactType[];\n }\n | { type: 'resolving-target' }\n | { type: 'confirm'; values: FieldValues; artifacts: readonly ArtifactType[] }\n | { type: 'writing' }\n | { type: 'done'; targetDir: string }\n | { type: 'error'; message: string };\n\ninterface CreateUIProps {\n parentDir: string;\n defaultBusinessId: string;\n defaultEnvironment: Environment;\n}\n\nconst Hint: FC<{ text: string }> = ({ text }) => <Text dimColor>{text}</Text>;\n\nexport const CreateUI: FC<CreateUIProps> = ({\n parentDir,\n defaultBusinessId,\n defaultEnvironment,\n}) => {\n const app = useApp();\n const [phase, setPhase] = useState<Phase>({ type: 'target-select', cursor: 0 });\n const [mode, setMode] = useState<Mode>('in-place');\n const [values, setValues] = useState<FieldValues>(() => emptyValues(defaultBusinessId));\n const [artifacts, setArtifacts] = useState<readonly ArtifactType[]>(() => [...ARTIFACT_TYPES]);\n const [inputBuffer, setInputBuffer] = useState('');\n const [targetDir, setTargetDir] = useState<string>(parentDir);\n\n const enterFieldEntry = useCallback((nextMode: Mode, initialValues: FieldValues): void => {\n setMode(nextMode);\n\n setInputBuffer(initialValues.name);\n\n setPhase({ type: 'field-entry', field: 0, values: initialValues });\n }, []);\n\n const runPrecheck = useCallback(\n async (dir: string): Promise<void> => {\n const result = await precheckTargetDir(dir);\n\n if (result !== 'ok') {\n setPhase({ type: 'precheck-error', targetDir: dir, reason: result });\n\n return;\n }\n\n setTargetDir(dir);\n\n enterFieldEntry('in-place', values);\n },\n [values, enterFieldEntry],\n );\n\n const resolveSubDirAndConfirm = useCallback(\n async (finalValues: FieldValues, artifacts: readonly ArtifactType[]): Promise<void> => {\n try {\n const dir = await findAvailableSubDir(parentDir, finalValues.apiName);\n\n setTargetDir(dir);\n\n setPhase({ type: 'confirm', values: finalValues, artifacts });\n } catch (err) {\n setPhase({\n type: 'error',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n },\n [parentDir],\n );\n\n const runWrite = useCallback(\n async (\n finalValues: FieldValues,\n dir: string,\n artifacts: readonly ArtifactType[],\n ): Promise<void> => {\n try {\n await createPlugin({\n targetDir: dir,\n name: finalValues.name,\n apiName: finalValues.apiName,\n externalLink: finalValues.externalLink,\n description: finalValues.description,\n developerBusinessId: finalValues.developerBusinessId,\n developerEnvironment: defaultEnvironment,\n artifacts,\n });\n\n setPhase({ type: 'done', targetDir: dir });\n } catch (err) {\n setPhase({\n type: 'error',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n },\n [defaultEnvironment],\n );\n\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n app.exit();\n\n return;\n }\n\n if (phase.type === 'target-select') {\n if (key.upArrow) {\n setPhase({ type: 'target-select', cursor: 0 });\n } else if (key.downArrow) {\n setPhase({ type: 'target-select', cursor: 1 });\n } else if (key.return) {\n if (phase.cursor === 0) {\n void runPrecheck(parentDir);\n } else {\n enterFieldEntry('sub-dir', values);\n }\n } else if (key.escape) {\n app.exit();\n }\n\n return;\n }\n\n if (phase.type === 'precheck-error') {\n if (key.return || key.escape) {\n app.exit();\n }\n\n return;\n }\n\n if (phase.type === 'field-entry') {\n const { field, values: current } = phase;\n const fieldName = FIELDS[field];\n\n if (!fieldName) {\n return;\n }\n\n if (key.escape) {\n app.exit();\n\n return;\n }\n\n if (key.backspace || key.delete) {\n setInputBuffer((prev) => prev.slice(0, -1));\n\n return;\n }\n\n if (key.upArrow && field > 0) {\n const updated = { ...current, [fieldName]: inputBuffer };\n const prevField = field - 1;\n const prevName = FIELDS[prevField];\n\n setPhase({ type: 'field-entry', field: prevField, values: updated });\n\n setValues(updated);\n\n setInputBuffer(prevName ? updated[prevName] : '');\n\n return;\n }\n\n if (key.return || key.tab || key.downArrow) {\n const fieldError = validateField(fieldName, inputBuffer);\n\n if (fieldError !== undefined) {\n setPhase({ type: 'field-entry', field, values: current, fieldError });\n\n return;\n }\n\n const valueToStore = normalizeFieldValue(fieldName, inputBuffer);\n const updated = { ...current, [fieldName]: valueToStore };\n\n setValues(updated);\n\n const nextField = field + 1;\n\n if (nextField >= FIELDS.length) {\n setInputBuffer('');\n\n setPhase({\n type: 'artifact-select',\n values: updated,\n cursor: 0,\n selected: artifacts,\n });\n } else {\n const nextName = FIELDS[nextField];\n const existing = nextName ? updated[nextName] : '';\n const nextBuffer =\n nextName === 'apiName' && !existing ? inferApiName(updated.name) : existing;\n\n setPhase({ type: 'field-entry', field: nextField, values: updated });\n\n setInputBuffer(nextBuffer);\n }\n\n return;\n }\n\n if (input && !key.ctrl && !key.meta) {\n setInputBuffer((prev) => prev + input);\n }\n\n return;\n }\n\n if (phase.type === 'artifact-select') {\n const { cursor, selected, values: current } = phase;\n\n if (key.escape) {\n const lastField = FIELDS.length - 1;\n const lastName = FIELDS[lastField];\n\n setPhase({ type: 'field-entry', field: lastField, values: current });\n\n setInputBuffer(lastName ? current[lastName] : '');\n\n return;\n }\n\n if (key.upArrow) {\n setPhase({ ...phase, cursor: Math.max(0, cursor - 1) });\n\n return;\n }\n\n if (key.downArrow) {\n setPhase({ ...phase, cursor: Math.min(ARTIFACT_TYPES.length - 1, cursor + 1) });\n\n return;\n }\n\n if (input === ' ') {\n const type = ARTIFACT_TYPES[cursor];\n\n if (type) {\n const next = toggleArtifactSelection(selected, type);\n\n setArtifacts(next);\n\n setPhase({ ...phase, selected: next });\n }\n\n return;\n }\n\n if (input === 'a') {\n setArtifacts([...ARTIFACT_TYPES]);\n\n setPhase({ ...phase, selected: [...ARTIFACT_TYPES] });\n\n return;\n }\n\n if (input === 'n') {\n setArtifacts([]);\n\n setPhase({ ...phase, selected: [] });\n\n return;\n }\n\n if (key.return) {\n if (mode === 'sub-dir') {\n setPhase({ type: 'resolving-target' });\n\n void resolveSubDirAndConfirm(current, selected);\n } else {\n setPhase({ type: 'confirm', values: current, artifacts: selected });\n }\n }\n\n return;\n }\n\n if (phase.type === 'confirm') {\n if (key.escape) {\n setPhase({\n type: 'artifact-select',\n values: phase.values,\n cursor: 0,\n selected: phase.artifacts,\n });\n\n return;\n }\n\n if (key.return) {\n setPhase({ type: 'writing' });\n\n void runWrite(phase.values, targetDir, phase.artifacts);\n }\n\n return;\n }\n\n if (phase.type === 'done' || phase.type === 'error') {\n if (key.return || key.escape) {\n app.exit();\n }\n }\n });\n\n if (phase.type === 'target-select') {\n const options = [\n { label: 'Use current directory', desc: parentDir },\n { label: 'Create new sub-directory', desc: `${parentDir}/<inferred from API name>` },\n ];\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Where should the new plugin live?</Text>\n {options.map((opt, i) => {\n const selected = phase.cursor === i;\n\n return (\n <Box key={opt.label} gap={2}>\n <Text {...(selected && { color: 'cyan' as const })}>{selected ? '❯' : ' '}</Text>\n <Text bold={selected} {...(selected && { color: 'cyan' as const })}>\n {opt.label}\n </Text>\n <Text dimColor>{opt.desc}</Text>\n </Box>\n );\n })}\n </Box>\n <Hint text=\"↑↓ to move · Enter to select · Esc to cancel\" />\n </Box>\n );\n }\n\n if (phase.type === 'precheck-error') {\n const { targetDir: dir, reason } = phase;\n const conflict = reason === 'has-manifest' ? 'kizen.json' : '.kizenapp/';\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Text color=\"red\" bold>\n Cannot create plugin\n </Text>\n <Box flexDirection=\"column\" gap={0}>\n <Text>\n {dir} already contains <Text bold>{conflict}</Text>.\n </Text>\n <Text dimColor>\n Remove the conflicting file/directory or choose a different target to avoid overwriting\n an existing plugin.\n </Text>\n </Box>\n <Hint text=\"Enter or Esc to exit\" />\n </Box>\n );\n }\n\n if (phase.type === 'field-entry') {\n const { field: activeField, fieldError } = phase;\n const targetLine =\n mode === 'sub-dir'\n ? `Target: sub-directory of ${parentDir} (inferred from API name)`\n : `Target: ${targetDir}`;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Plugin details</Text>\n <Text dimColor>{targetLine}</Text>\n </Box>\n {fieldError !== undefined && <Text color=\"red\">Error: {fieldError}</Text>}\n <Box flexDirection=\"column\" gap={0}>\n {FIELDS.map((name, i) => {\n const isActive = activeField === i;\n const displayValue = isActive ? inputBuffer : values[name];\n const isRequired = REQUIRED_FIELDS.includes(name);\n const label = `${FIELD_LABELS[name]}${isRequired ? '' : ' (optional)'}`;\n\n return (\n <Box key={name} gap={2}>\n <Box width={24}>\n <Text bold={isActive} {...(isActive && { color: 'cyan' as const })}>\n {label}\n </Text>\n </Box>\n <Text {...(isActive && { color: 'cyan' as const })}>{'>'}</Text>\n <Text>{displayValue}</Text>\n {isActive && <Text color=\"cyan\">{'█'}</Text>}\n </Box>\n );\n })}\n </Box>\n <Hint text=\"Enter/Tab/↓ next · ↑ previous · Backspace delete · Esc cancel\" />\n </Box>\n );\n }\n\n if (phase.type === 'artifact-select') {\n const { cursor, selected } = phase;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Which artifacts should we scaffold?</Text>\n <Text dimColor>Each one gets a directory with a config.json and a script that runs.</Text>\n </Box>\n <Box flexDirection=\"column\" gap={0}>\n {ARTIFACT_TYPES.map((type, i) => {\n const active = cursor === i;\n const checked = selected.includes(type);\n\n return (\n <Box key={type} gap={1}>\n <Text {...(active && { color: 'cyan' as const })}>{active ? '❯' : ' '}</Text>\n <Text {...(checked && { color: 'green' as const })}>{checked ? '◉' : '◯'}</Text>\n <Text bold={active} {...(active && { color: 'cyan' as const })}>\n {ARTIFACT_LABELS[type]}\n </Text>\n </Box>\n );\n })}\n </Box>\n <Hint text=\"↑↓ move · Space toggle · a all · n none · Enter continue · Esc back\" />\n </Box>\n );\n }\n\n if (phase.type === 'confirm') {\n const manifest = buildManifest({\n targetDir,\n name: phase.values.name,\n apiName: phase.values.apiName,\n externalLink: phase.values.externalLink,\n description: phase.values.description,\n developerBusinessId: phase.values.developerBusinessId,\n developerEnvironment: defaultEnvironment,\n });\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Ready to create</Text>\n <Text dimColor>Target: {targetDir}</Text>\n </Box>\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>kizen.json preview</Text>\n <Text>{JSON.stringify(manifest, null, 2)}</Text>\n </Box>\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Artifacts</Text>\n {phase.artifacts.length === 0 ? (\n <Text dimColor>{' '}none (src/ will hold only thumbnail.png)</Text>\n ) : (\n phase.artifacts.map((type) => (\n <Text key={type} dimColor>\n {' '}\n {ARTIFACT_LABELS[type]}\n </Text>\n ))\n )}\n </Box>\n <Box flexDirection=\"column\" gap={0}>\n <Text dimColor>Also creates:</Text>\n <Text dimColor>\n {' '}\n {join(targetDir, 'src/')}\n </Text>\n <Text dimColor>\n {' '}\n {join(targetDir, 'src/thumbnail.png')} (generated placeholder)\n </Text>\n <Text dimColor>\n {' '}\n {join(targetDir, 'releaseNotes/')}\n </Text>\n <Text dimColor>\n {' '}\n {join(targetDir, '.gitignore')} (adds .kizenapp/)\n </Text>\n </Box>\n <Hint text=\"Enter to create · Esc to go back\" />\n </Box>\n );\n }\n\n if (phase.type === 'resolving-target') {\n return (\n <Box paddingY={1} paddingX={2}>\n <Text dimColor>Finding available sub-directory…</Text>\n </Box>\n );\n }\n\n if (phase.type === 'writing') {\n return (\n <Box paddingY={1} paddingX={2}>\n <Text dimColor>Creating plugin…</Text>\n </Box>\n );\n }\n\n if (phase.type === 'done') {\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Text color=\"green\" bold>\n Plugin created at {phase.targetDir}\n </Text>\n <Box flexDirection=\"column\" gap={0}>\n <Text dimColor>Next steps:</Text>\n <Text>\n {' '}cd {phase.targetDir}\n </Text>\n <Text>{' '}npx --yes @kizenapps/cli dev</Text>\n <Text dimColor>{' '}Replace src/thumbnail.png with real artwork before publishing.</Text>\n </Box>\n <Hint text=\"Enter or Esc to exit\" />\n </Box>\n );\n }\n\n // error\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Text color=\"red\" bold>\n Failed to create plugin\n </Text>\n <Text>{phase.message}</Text>\n <Hint text=\"Enter or Esc to exit\" />\n </Box>\n );\n};\n","import { access, mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { ensureGitignore } from './gitignore.js';\nimport { scaffoldArtifactFiles } from './createArtifacts.js';\nimport type { ArtifactType, ScaffoldedFile } from './createArtifacts.js';\nimport { copilotFiles } from './createCopilotFiles.js';\nimport { thumbnailBytes } from './createThumbnail.js';\nimport type { Environment } from '../../shared/lib/credentials.js';\n\nconst THUMBNAIL_PATH = 'src/thumbnail.png';\n\nconst PROD_ENVIRONMENTS: readonly Environment[] = ['go', 'fmo'];\n\nexport interface CreatePluginInput {\n targetDir: string;\n name: string;\n apiName: string;\n externalLink: string;\n description: string;\n developerBusinessId: string;\n developerEnvironment: Environment;\n artifacts?: readonly ArtifactType[];\n}\n\nexport type PrecheckResult = 'ok' | 'has-manifest' | 'has-kizenapp';\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await access(path);\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function precheckTargetDir(dir: string): Promise<PrecheckResult> {\n if (await pathExists(join(dir, 'kizen.json'))) {\n return 'has-manifest';\n }\n\n if (await pathExists(join(dir, '.kizenapp'))) {\n return 'has-kizenapp';\n }\n\n return 'ok';\n}\n\nexport async function findAvailableSubDir(parentDir: string, baseName: string): Promise<string> {\n const base = join(parentDir, baseName);\n\n if (!(await pathExists(base))) {\n return base;\n }\n\n for (let i = 1; i < 1000; i++) {\n const candidate = join(parentDir, `${baseName}-${String(i)}`);\n\n if (!(await pathExists(candidate))) {\n return candidate;\n }\n }\n\n throw new Error(`Could not find an available directory name for \"${baseName}\"`);\n}\n\nexport function buildManifest(input: CreatePluginInput): Record<string, unknown> {\n const businessId = input.developerBusinessId.trim();\n\n const targetEnvironments =\n businessId !== '' && !PROD_ENVIRONMENTS.includes(input.developerEnvironment)\n ? [input.developerEnvironment]\n : ['prod'];\n\n return {\n name: input.name,\n version: '1.0.0',\n published: true,\n api_name: input.apiName,\n external_link: input.externalLink,\n description: input.description,\n entry: 'src/',\n engine: '1.0.0',\n release_notes_directory: 'releaseNotes/',\n release_environments: targetEnvironments,\n config_template: {},\n base_config: {},\n ...(businessId ? { developer_business_id: { [input.developerEnvironment]: businessId } } : {}),\n };\n}\n\nasync function writeScaffoldedFiles(\n targetDir: string,\n scaffolded: readonly ScaffoldedFile[],\n): Promise<void> {\n const files = scaffolded.map((file) => ({\n fullPath: join(targetDir, ...file.path.split('/')),\n content: file.content,\n }));\n\n const directories = new Set(files.map((file) => dirname(file.fullPath)));\n\n await Promise.all([...directories].map((dir) => mkdir(dir, { recursive: true })));\n\n await Promise.all(files.map((file) => writeFile(file.fullPath, file.content, 'utf-8')));\n}\n\nexport async function createPlugin(input: CreatePluginInput): Promise<void> {\n await mkdir(input.targetDir, { recursive: true });\n\n const manifest = buildManifest(input);\n\n await writeFile(\n join(input.targetDir, 'kizen.json'),\n JSON.stringify(manifest, null, 2) + '\\n',\n 'utf-8',\n );\n\n await mkdir(join(input.targetDir, 'src'), { recursive: true });\n\n await mkdir(join(input.targetDir, 'releaseNotes'), { recursive: true });\n\n await Promise.all([\n writeScaffoldedFiles(input.targetDir, scaffoldArtifactFiles(input.artifacts ?? [])),\n writeScaffoldedFiles(input.targetDir, copilotFiles()),\n writeFile(join(input.targetDir, ...THUMBNAIL_PATH.split('/')), thumbnailBytes(input.apiName)),\n ]);\n\n ensureGitignore(input.targetDir);\n}\n","{\n \"name\": \"Hello Frame\",\n \"api_name\": \"hello_frame\",\n \"title\": \"Hello Frame\",\n \"default_position\": \"bottom-right\",\n \"minimized_style\": \"circle\",\n \"height\": 320,\n \"width\": 280\n}\n","this.outputUI(`\n <div class=\"hello-frame\">\n <h2 class=\"hello-frame__title\">Hello from a floating frame</h2>\n <p class=\"hello-frame__body\">Edit src/floatingFrames/helloFrame/script.js to change this.</p>\n </div>\n`);\n",".hello-frame {\n padding: 16px;\n font-family: system-ui, sans-serif;\n}\n\n.hello-frame__title {\n margin: 0 0 8px;\n font-size: 16px;\n}\n\n.hello-frame__body {\n margin: 0;\n color: #555;\n}\n","{\n \"name\": \"Hello Block\",\n \"api_name\": \"hello_block\",\n \"types\": [\"dashboards\"]\n}\n","this.outputUI(`\n <div class=\"hello-block\">\n <h2 class=\"hello-block__title\">Hello from a block</h2>\n <p class=\"hello-block__body\">Edit src/blocks/helloBlock/script.js to change this.</p>\n </div>\n`);\n",".hello-block {\n padding: 16px;\n font-family: system-ui, sans-serif;\n background: #f8fafc;\n border-radius: 6px;\n}\n\n.hello-block__title {\n margin: 0 0 8px;\n font-size: 16px;\n}\n\n.hello-block__body {\n margin: 0;\n color: #555;\n}\n","{\n \"icon\": \"phone\",\n \"color\": \"#0ea5e9\",\n \"tooltip\": \"Hello adornment\",\n \"field_type\": \"phonenumber\"\n}\n","this.showToast('Hello from a data adornment.', { variant: 'success' });\n","{\n \"name\": \"Hello Page\",\n \"api_name\": \"hello_page\"\n}\n","this.outputUI(`\n <div class=\"hello-page\">\n <p class=\"hello-page__loading\">Loading…</p>\n </div>\n`);\n\nthis.runEventScript('greet');\n",".hello-page {\n padding: 24px;\n font-family: system-ui, sans-serif;\n}\n\n.hello-page__title {\n margin: 0 0 8px;\n font-size: 20px;\n}\n\n.hello-page__body {\n margin: 0 0 16px;\n color: #555;\n}\n\n.hello-page__loading {\n margin: 0;\n color: #94a3b8;\n}\n\n.hello-page__actions {\n display: flex;\n gap: 8px;\n}\n\n.hello-page__button {\n padding: 6px 12px;\n font: inherit;\n color: #0f172a;\n background: #e2e8f0;\n border: 0;\n border-radius: 4px;\n cursor: pointer;\n}\n\n.hello-page__button:hover {\n background: #cbd5e1;\n}\n","const tone = this.args?.formData?.tone?.[0] ?? 'plain';\n\nconst greeting = tone === 'cheer' ? 'Hello, and good to see you!' : 'Hello from a routable page.';\n\nthis.outputUI(`\n <div class=\"hello-page\">\n <h1 class=\"hello-page__title\">${greeting}</h1>\n <p class=\"hello-page__body\">\n This markup came from eventScripts/greet.js. Either button re-runs it and\n repaints the page with a different greeting.\n </p>\n <div class=\"hello-page__actions\">\n <form data-script=\"greet\">\n <input type=\"hidden\" name=\"tone\" value=\"plain\" />\n <button class=\"hello-page__button\" type=\"submit\">Plain</button>\n </form>\n <form data-script=\"greet\">\n <input type=\"hidden\" name=\"tone\" value=\"cheer\" />\n <button class=\"hello-page__button\" type=\"submit\">Cheerful</button>\n </form>\n </div>\n </div>\n`);\n","{\n \"api_name\": \"hello_toolbar_item\",\n \"label\": \"Hello Toolbar Item\",\n \"icon\": \"star\",\n \"color\": \"#0ea5e9\"\n}\n","this.showToast('Hello from a toolbar item.', { variant: 'success' });\n","{\n \"api_name\": \"hello_object_settings_item\",\n \"label\": \"Hello Object Settings\"\n}\n","this.showToast('Hello from an object settings item.', { variant: 'success' });\n","{\n \"name\": \"Hello Action\",\n \"api_name\": \"hello_action\",\n \"hint_object_name\": \"client_client\"\n}\n","this.showToast('Hello from a JS action.', { variant: 'success' });\n","import helloFrameConfig from '../templates/artifacts/floatingFrames/helloFrame/config.json?raw';\nimport helloFrameScript from '../templates/artifacts/floatingFrames/helloFrame/script.js?raw';\nimport helloFrameStyles from '../templates/artifacts/floatingFrames/helloFrame/styles.css?raw';\nimport helloBlockConfig from '../templates/artifacts/blocks/helloBlock/config.json?raw';\nimport helloBlockScript from '../templates/artifacts/blocks/helloBlock/script.js?raw';\nimport helloBlockStyles from '../templates/artifacts/blocks/helloBlock/styles.css?raw';\nimport helloAdornmentConfig from '../templates/artifacts/dataAdornments/helloAdornment/config.json?raw';\nimport helloAdornmentScript from '../templates/artifacts/dataAdornments/helloAdornment/script.js?raw';\nimport helloPageConfig from '../templates/artifacts/pages/helloPage/config.json?raw';\nimport helloPageScript from '../templates/artifacts/pages/helloPage/script.js?raw';\nimport helloPageStyles from '../templates/artifacts/pages/helloPage/styles.css?raw';\nimport helloPageGreet from '../templates/artifacts/pages/helloPage/eventScripts/greet.js?raw';\nimport helloToolbarItemConfig from '../templates/artifacts/toolbarItems/helloToolbarItem/config.json?raw';\nimport helloToolbarItemScript from '../templates/artifacts/toolbarItems/helloToolbarItem/script.js?raw';\nimport helloObjectSettingsItemConfig from '../templates/artifacts/objectSettingsItems/helloObjectSettingsItem/config.json?raw';\nimport helloObjectSettingsItemScript from '../templates/artifacts/objectSettingsItems/helloObjectSettingsItem/script.js?raw';\nimport helloActionConfig from '../templates/artifacts/actions/helloAction/config.json?raw';\nimport helloActionScript from '../templates/artifacts/actions/helloAction/script.js?raw';\n\nexport const ARTIFACT_TYPES = [\n 'floatingFrame',\n 'block',\n 'dataAdornment',\n 'page',\n 'toolbarItem',\n 'objectSettingsItem',\n 'jsAction',\n] as const;\n\nexport type ArtifactType = (typeof ARTIFACT_TYPES)[number];\n\nexport const ARTIFACT_LABELS: Record<ArtifactType, string> = {\n floatingFrame: 'Floating frame',\n block: 'Block',\n dataAdornment: 'Data adornment',\n page: 'Routable page',\n toolbarItem: 'Toolbar item',\n objectSettingsItem: 'Object settings item',\n jsAction: 'JS action',\n};\n\nexport interface ScaffoldedFile {\n path: string;\n content: string;\n}\n\ninterface ArtifactTemplate {\n directory: string;\n component: string;\n files: Readonly<Record<string, string>>;\n}\n\nconst TEMPLATES: Record<ArtifactType, ArtifactTemplate> = {\n floatingFrame: {\n directory: 'floatingFrames',\n component: 'helloFrame',\n files: {\n 'config.json': helloFrameConfig,\n 'script.js': helloFrameScript,\n 'styles.css': helloFrameStyles,\n },\n },\n\n block: {\n directory: 'blocks',\n component: 'helloBlock',\n files: {\n 'config.json': helloBlockConfig,\n 'script.js': helloBlockScript,\n 'styles.css': helloBlockStyles,\n },\n },\n\n dataAdornment: {\n directory: 'dataAdornments',\n component: 'helloAdornment',\n files: {\n 'config.json': helloAdornmentConfig,\n 'script.js': helloAdornmentScript,\n },\n },\n\n page: {\n directory: 'pages',\n component: 'helloPage',\n files: {\n 'config.json': helloPageConfig,\n 'script.js': helloPageScript,\n 'styles.css': helloPageStyles,\n 'eventScripts/greet.js': helloPageGreet,\n },\n },\n\n toolbarItem: {\n directory: 'toolbarItems',\n component: 'helloToolbarItem',\n files: {\n 'config.json': helloToolbarItemConfig,\n 'script.js': helloToolbarItemScript,\n },\n },\n\n objectSettingsItem: {\n directory: 'objectSettingsItems',\n component: 'helloObjectSettingsItem',\n files: {\n 'config.json': helloObjectSettingsItemConfig,\n 'script.js': helloObjectSettingsItemScript,\n },\n },\n\n jsAction: {\n directory: 'actions',\n component: 'helloAction',\n files: {\n 'config.json': helloActionConfig,\n 'script.js': helloActionScript,\n },\n },\n};\n\nexport function artifactFiles(type: ArtifactType, entryDir = 'src'): ScaffoldedFile[] {\n const { directory, component, files } = TEMPLATES[type];\n\n return Object.entries(files).map(([relativePath, content]) => ({\n path: `${entryDir}/${directory}/${component}/${relativePath}`,\n content,\n }));\n}\n\nexport function scaffoldArtifactFiles(\n types: readonly ArtifactType[],\n entryDir = 'src',\n): ScaffoldedFile[] {\n return [...new Set(types)].flatMap((type) => artifactFiles(type, entryDir));\n}\n","# Copilot review instructions for this Kizen plugin\n\nThis repo is a Kizen plugin app: a `kizen.json` manifest plus the artifacts\nthat `@kizenapps/packager` finds by walking the directory tree under the\nmanifest's `entry` (default `src/`). No manifest key lists artifacts. The\ndirectory layout decides what gets packaged.\n\n## Component directories\n\nUnder `entry`, the packager treats these directory names as component types:\n\n- `floatingFrames`\n- `blocks`\n- `dataAdornments`\n- `pages`\n- `views`\n- `toolbarItems`\n- `objectSettingsItems`\n- `actions`\n- `routeScripts`\n- `automationSteps`\n- `calendarSources`\n\nEvery directory under a component type needs a `config.json`. `views/` is the\none exception.\n\n## `api_name` rules\n\n- An `api_name` must match `/^[a-z_][a-z0-9_]+$/`: lowercase letters, digits\n and underscores, starting with a letter or underscore, at least 2 characters.\n- Set `api_name` explicitly in each artifact's `config.json`. The fallback\n lowercases and strips the directory name (`myFrame` becomes `myframe`), and\n that result can collide with another artifact's explicit `api_name`.\n- Data adornments have no `api_name` field. Flag one that adds it as dead\n configuration.\n- Sibling components in the same directory need unique `api_name`s. `pages/`\n and `views/` go further and share one namespace, so a page and a view with\n the same `api_name` collide even though they live in different directories.\n\n## A green build does not mean a correct artifact\n\nThe packager coerces malformed artifact config instead of rejecting it: an\ninvalid `field_type` on a data adornment becomes `phonenumber`, and an invalid\n`minimized_style` on a floating frame becomes `circle`. It also says nothing\nabout a missing required field. Publishing is the real gate. The publish step\ncreates each artifact with no defaulting, so a field the packager never emitted\nis absent and the publish request 400s. Review each\n`config.json` as if the build will not catch mistakes in it, because for these\ncases it does not.\n\nPublishing an app requires these fields per artifact type. An artifact missing\none builds clean and fails to publish:\n\n| Artifact | Required fields |\n| --- | --- |\n| Floating frame | `api_name`, `name`, `title` |\n| Block | `api_name`, `name` |\n| Data adornment | `field_type` (one of `phonenumber`, `date`, `datetime`) |\n| Routable page | `api_name`, `name` |\n| Toolbar item | `api_name`, `label`, and a non-blank `script.js` |\n| Object settings item | `api_name`, `label`, and a non-blank `script.js` |\n| JS action | `api_name`, `name`, `hint_object_name` (non-blank) |\n\nA floating frame whose `default_position` ends in `-fixed` must set\n`minimized_style: \"circle\"` or omit `minimized_style`. Any other value fails\nthe build with `structure/fixed-frame-minimized-style`.\n\n## Publishing\n\nPublishing an app requires exactly one `thumbnail.png`, and it must sit inside\nthe `entry` directory (`src/thumbnail.png` by default). The packager never sees\na thumbnail at the repo root, and publishing then fails with \"Thumbnail is\nrequired for publishing\".\n\n## Scope\n\nThis file covers repo structure and general review. Two path-scoped files\ncover the rest: `.github/instructions/security.instructions.md` for\nsecurity-sensitive patterns and\n`.github/instructions/version-discipline.instructions.md` for manifest version\nbumps.\n","---\napplyTo: \"src/**/*.js,kizen.json\"\n---\n\n# Security review rules for plugin scripts\n\nThese rules mirror the `security/*` validation rules in `@kizenapps/packager`.\nFlag violations the way the packager would, and also flag the patterns listed\nhere that its static scan cannot detect.\n\n## `__dangerouslySkipProxy`\n\nThe packager lets `__dangerouslySkipProxy` through with the build WARNING\n`security/dangerously-skip-proxy`. Flag every occurrence for human review\nanyway, because the request leaves the browser directly instead of passing\nthrough the Kizen proxy.\n\n## Plaintext credentials\n\nIn `kizen.json`, a service's `auth_credentials.token`,\n`auth_credentials.password` and `auth_credentials.client_secret` must each be\none of:\n\n- an encrypted envelope (`{ \"encrypted\": true, \"value\": \"...\" }`) that\n `appbuilder encrypt` produced\n- a `{{secret.KEY}}` reference, with `KEY` declared in `base_config.secrets`\n- a reference through `auth_credentials.integration_secret_api_name`\n\nA raw literal in any of those three fields is the build ERROR\n`security/plaintext-credential`. Treat a credential that reaches a commit in\nplaintext as compromised and rotate it; deleting the line does not undo the\nexposure.\n\n`client_id` is excluded from this rule on purpose. Public client ids are not\nsensitive, so do not flag them.\n\n## Undeclared secret references\n\nA `{{secret.KEY}}` reference whose `KEY` is missing from `base_config.secrets`\nis the build ERROR `security/undeclared-secret-reference`, because nothing\nwould supply the value at install time.\n\n## Dynamic code execution\n\n`eval(...)`, `new Function(...)` or `Function(...)`, and a string argument to\n`setTimeout` or `setInterval` are the build ERROR `security/dynamic-code`.\n\nThis rule catches direct, literal usage only. The packager's scan is\nparser-based, so a call built through a computed property or a reassigned\nreference gets past it. Obfuscated dynamic code stays a human-review concern.\n\n## Secret logging and exfiltration\n\nThe packager has no static check for a secret that gets logged, sent to an\nunexpected endpoint, or otherwise exfiltrated. Review for this by hand: look\nfor credentials or decrypted secret values flowing into `console.log`, error\nmessages, analytics calls, or outbound requests to anything other than the\nservice they belong to.\n\n## Handling secrets in this repo\n\nEncrypt secrets locally with `appbuilder encrypt` before committing them. Do\nnot commit a plaintext secret value in any form; a comment, a script fixture,\nand a commit you intend to rewrite later all count.\n","---\napplyTo: \"kizen.json\"\n---\n\n# Version-bump discipline for `kizen.json`\n\n## What a wrong bump breaks\n\nA business that installs this plugin accumulates its own stored state\n(automation runs, config values, references to entities) shaped by what was\npublished at the time. Publishing is additive: it never rewrites a business's\nstored rows, and the plugin author has no way to migrate that state for them.\nA change is breaking when it invalidates an assumption the business's existing\ndata already depends on.\n\nA MINOR or PATCH republish applies at once to a business's running automations\nand installed artifacts. Only a new MAJOR version waits for the business to\nupgrade explicitly. A change that needed MAJOR but shipped as MINOR or PATCH\ntherefore breaks the business with no upgrade gate in between.\n\nTwo kinds of change get MAJOR because they fail without an error:\n\n- Renaming a config field, changing its type, or adding a required key. A\n template reference like `{{config.key}}` for a key that no longer exists\n resolves to a literal `null`, and the artifact renders wrong or does\n nothing.\n- Removing or renaming a JS action. A business's automation and UI\n associations key on the action's `api_name` as a plain string, with no\n foreign key. After a rename or removal those associations stop firing.\n\nReview every `kizen.json` diff against the table below before approving the\nversion bump in the same PR.\n\n## Bump matrix\n\n| Resource | Change | Required bump |\n| --- | --- | --- |\n| Plugin | change `api_name` | **HARD-BLOCK**: identity can never change |\n| Service | add | MINOR |\n| Service | remove | MAJOR |\n| Service | change auth type or `auth_level` | MAJOR |\n| Service | change `auth_credentials` (client id/secret, scopes, authorize/token URLs) | MAJOR |\n| Service | change base URL or other non-auth field | PATCH |\n| Service | rename `api_name` | MAJOR |\n| Secret | add | MINOR |\n| Secret | remove | MINOR |\n| Secret | rename key | MAJOR |\n| Secret | re-encrypt value only | PATCH |\n| Automation step | add | MINOR |\n| Automation step | remove entire step | MAJOR |\n| Automation step | remove an input or output | MAJOR |\n| Automation step | change input/output `data_type` | MAJOR |\n| Automation step | add required input | MAJOR |\n| Automation step | add optional input | MINOR |\n| Automation step | change python runtime | PATCH |\n| Automation step | edit script body only | PATCH |\n| Artifact (frame, block, adornment, page, route script, toolbar/object-settings item, calendar source) | add | MINOR |\n| Artifact | remove | MINOR |\n| Artifact | rename `api_name` | MINOR |\n| Artifact | edit script or behavior | PATCH |\n| JS action | add | MINOR |\n| JS action | remove | MAJOR |\n| JS action | rename `api_name` | MAJOR |\n| JS action | change `hint_object_name` or script | PATCH |\n| Config field | add optional (with default) | MINOR |\n| Config field | add required (no default) | MAJOR |\n| Config field | remove | MINOR |\n| Config field | rename | MAJOR |\n| Config field | change type | MAJOR |\n| Config field | change default or label | PATCH |\n| `required_entitlement` | add gating | MINOR |\n| `required_entitlement` | change or remove | PATCH |\n| Manifest metadata (`name`, `description`, `entry`, `release_branches`, `release_environments`, `published`, `developer_business_id`) | any change | PATCH |\n","import copilotInstructions from '../templates/github/copilot-instructions.md?raw';\nimport securityInstructions from '../templates/github/instructions/security.instructions.md?raw';\nimport versionDisciplineInstructions from '../templates/github/instructions/version-discipline.instructions.md?raw';\nimport type { ScaffoldedFile } from './createArtifacts.js';\n\nexport function copilotFiles(): ScaffoldedFile[] {\n return [\n { path: '.github/copilot-instructions.md', content: copilotInstructions },\n { path: '.github/instructions/security.instructions.md', content: securityInstructions },\n {\n path: '.github/instructions/version-discipline.instructions.md',\n content: versionDisciplineInstructions,\n },\n ];\n}\n","import { deflateSync } from 'node:zlib';\n\nexport const THUMBNAIL_SIZE = 512;\n\nconst BODY_HALF_SIZE = 150;\n\nconst BODY_CORNER_RADIUS = 26;\n\nconst KNOB_RADIUS = 46;\n\nconst KNOB_OFFSET_RATIO = 0.6;\n\nconst NECK_HALF_WIDTH = KNOB_RADIUS * 0.55;\n\nconst SATURATION = 0.55;\n\nconst LIGHTNESS = 0.47;\n\nexport interface ThumbnailStyle {\n hue: number;\n quarterTurns: 0 | 1 | 2 | 3;\n}\n\nfunction fnv1a(text: string): number {\n let hash = 0x811c9dc5;\n\n for (let i = 0; i < text.length; i += 1) {\n hash ^= text.charCodeAt(i);\n\n hash = (hash + ((hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24))) >>> 0;\n }\n\n return hash;\n}\n\nexport function thumbnailStyle(apiName: string): ThumbnailStyle {\n const hash = fnv1a(apiName);\n\n return {\n hue: hash % 360,\n quarterTurns: ((hash >>> 16) % 4) as 0 | 1 | 2 | 3,\n };\n}\n\nfunction hslToRgb(hue: number, saturation: number, lightness: number): [number, number, number] {\n const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;\n const sector = hue / 60;\n const secondary = chroma * (1 - Math.abs((sector % 2) - 1));\n const match = lightness - chroma / 2;\n\n const [r, g, b] =\n sector < 1\n ? [chroma, secondary, 0]\n : sector < 2\n ? [secondary, chroma, 0]\n : sector < 3\n ? [0, chroma, secondary]\n : sector < 4\n ? [0, secondary, chroma]\n : sector < 5\n ? [secondary, 0, chroma]\n : [chroma, 0, secondary];\n\n return [\n Math.round((r + match) * 255),\n Math.round((g + match) * 255),\n Math.round((b + match) * 255),\n ];\n}\n\nfunction roundedBoxDistance(\n x: number,\n y: number,\n halfW: number,\n halfH: number,\n radius: number,\n): number {\n const qx = Math.abs(x) - halfW + radius;\n const qy = Math.abs(y) - halfH + radius;\n\n return Math.hypot(Math.max(qx, 0), Math.max(qy, 0)) + Math.min(Math.max(qx, qy), 0) - radius;\n}\n\nfunction circleDistance(x: number, y: number, cx: number, cy: number, radius: number): number {\n return Math.hypot(x - cx, y - cy) - radius;\n}\n\nfunction puzzlePieceDistance(x: number, y: number): number {\n const s = BODY_HALF_SIZE;\n const k = KNOB_RADIUS;\n const offset = k * KNOB_OFFSET_RATIO;\n const neckHalf = NECK_HALF_WIDTH;\n\n let d = roundedBoxDistance(x, y, s, s, BODY_CORNER_RADIUS);\n\n const topKnob = Math.min(\n circleDistance(x, y, 0, -s - offset, k),\n roundedBoxDistance(x, y + s + offset / 2, neckHalf, offset / 2 + 1, 0),\n );\n\n const rightKnob = Math.min(\n circleDistance(x, y, s + offset, 0, k),\n roundedBoxDistance(x - s - offset / 2, y, offset / 2 + 1, neckHalf, 0),\n );\n\n d = Math.min(d, topKnob, rightKnob);\n\n const bottomSocket = Math.min(\n circleDistance(x, y, 0, s - offset, k),\n roundedBoxDistance(x, y - s + offset / 2, neckHalf, offset / 2 + 1, 0),\n );\n\n const leftSocket = Math.min(\n circleDistance(x, y, -s + offset, 0, k),\n roundedBoxDistance(x + s - offset / 2, y, offset / 2 + 1, neckHalf, 0),\n );\n\n return Math.max(d, -bottomSocket, -leftSocket);\n}\n\nfunction renderPixels(style: ThumbnailStyle): Uint8Array {\n const size = THUMBNAIL_SIZE;\n const pixels = new Uint8Array(size * size * 4);\n const [r, g, b] = hslToRgb(style.hue, SATURATION, LIGHTNESS);\n\n const knobExtension = KNOB_RADIUS * (1 + KNOB_OFFSET_RATIO);\n const centre = (size - 1) / 2;\n const shift = knobExtension / 2;\n\n for (let py = 0; py < size; py += 1) {\n for (let px = 0; px < size; px += 1) {\n let x = px - centre;\n let y = py - centre;\n\n for (let turn = 0; turn < style.quarterTurns; turn += 1) {\n [x, y] = [-y, x];\n }\n\n const d = puzzlePieceDistance(x + shift, y - shift);\n\n const coverage = Math.min(1, Math.max(0, 0.5 - d));\n\n if (coverage <= 0) {\n continue;\n }\n\n const i = (py * size + px) * 4;\n\n pixels[i] = r;\n pixels[i + 1] = g;\n pixels[i + 2] = b;\n pixels[i + 3] = Math.round(coverage * 255);\n }\n }\n\n return pixels;\n}\n\nconst CRC_TABLE = new Uint32Array(256).map((_, n) => {\n let c = n;\n\n for (let k = 0; k < 8; k += 1) {\n c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n }\n\n return c >>> 0;\n});\n\nfunction crc32(bytes: Uint8Array): number {\n let crc = 0xffffffff;\n\n for (const byte of bytes) {\n crc = (CRC_TABLE[(crc ^ byte) & 0xff] ?? 0) ^ (crc >>> 8);\n }\n\n return (crc ^ 0xffffffff) >>> 0;\n}\n\nfunction pngChunk(type: string, data: Uint8Array): Buffer {\n const typeBytes = Buffer.from(type, 'latin1');\n const length = Buffer.alloc(4);\n\n length.writeUInt32BE(data.length);\n\n const crc = Buffer.alloc(4);\n\n crc.writeUInt32BE(crc32(Buffer.concat([typeBytes, data])));\n\n return Buffer.concat([length, typeBytes, data, crc]);\n}\n\nconst PNG_SIGNATURE = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);\n\nexport function encodePng(width: number, height: number, rgba: Uint8Array): Buffer {\n if (rgba.length !== width * height * 4) {\n throw new Error(\n `encodePng: expected ${String(width * height * 4)} bytes of RGBA for ${String(width)}x${String(height)}, got ${String(rgba.length)}`,\n );\n }\n\n const ihdr = Buffer.alloc(13);\n\n ihdr.writeUInt32BE(width, 0);\n ihdr.writeUInt32BE(height, 4);\n ihdr[8] = 8;\n ihdr[9] = 6;\n\n const stride = width * 4;\n const raw = Buffer.alloc((stride + 1) * height);\n\n for (let y = 0; y < height; y += 1) {\n raw.set(rgba.subarray(y * stride, (y + 1) * stride), y * (stride + 1) + 1);\n }\n\n return Buffer.concat([\n PNG_SIGNATURE,\n pngChunk('IHDR', ihdr),\n pngChunk('IDAT', deflateSync(raw, { level: 9 })),\n pngChunk('IEND', new Uint8Array(0)),\n ]);\n}\n\nexport function thumbnailBytes(apiName: string): Buffer {\n return encodePng(THUMBNAIL_SIZE, THUMBNAIL_SIZE, renderPixels(thumbnailStyle(apiName)));\n}\n","import { ARTIFACT_TYPES } from './createArtifacts.js';\nimport type { ArtifactType } from './createArtifacts.js';\n\nexport const FIELDS = [\n 'name',\n 'apiName',\n 'externalLink',\n 'description',\n 'developerBusinessId',\n] as const;\n\nexport type FieldName = (typeof FIELDS)[number];\n\nexport const FIELD_LABELS: Record<FieldName, string> = {\n name: 'Name',\n apiName: 'API name',\n externalLink: 'External link',\n description: 'Description',\n developerBusinessId: 'Business ID',\n};\n\nexport const REQUIRED_FIELDS: readonly FieldName[] = ['name', 'apiName', 'description'];\n\nexport type FieldValues = Record<FieldName, string>;\n\nexport const API_NAME_PATTERN = /^[a-z_][a-z0-9_]+$/;\n\nexport const API_NAME_HINT =\n 'must start with a letter or underscore and contain only lowercase letters, numbers, or underscores (minimum 2 characters)';\n\nexport function inferApiName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '');\n}\n\nexport function emptyValues(defaultBusinessId: string): FieldValues {\n return {\n name: '',\n apiName: '',\n externalLink: '',\n description: '',\n developerBusinessId: defaultBusinessId,\n };\n}\n\nexport function validateField(fieldName: FieldName, inputBuffer: string): string | undefined {\n const value = inputBuffer.trim();\n\n if (REQUIRED_FIELDS.includes(fieldName) && !value) {\n return `${FIELD_LABELS[fieldName]} is required`;\n }\n\n if (fieldName === 'apiName' && !API_NAME_PATTERN.test(value)) {\n return `${FIELD_LABELS[fieldName]} ${API_NAME_HINT}`;\n }\n\n return undefined;\n}\n\nexport function normalizeFieldValue(fieldName: FieldName, inputBuffer: string): string {\n return fieldName === 'description' ? inputBuffer : inputBuffer.trim();\n}\n\nexport function toggleArtifactSelection(\n selected: readonly ArtifactType[],\n type: ArtifactType,\n): ArtifactType[] {\n const next = new Set(selected);\n\n if (next.has(type)) {\n next.delete(type);\n } else {\n next.add(type);\n }\n\n return ARTIFACT_TYPES.filter((candidate) => next.has(candidate));\n}\n","import { mkdir, readFile, readdir, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { ENVIRONMENTS, type Environment, type Credentials } from '../../shared/lib/credentials.js';\nexport { ENVIRONMENTS, type Environment, type Credentials } from '../../shared/lib/credentials.js';\n\nexport interface CredentialProfile {\n name: string;\n path: string;\n isDefault: boolean;\n}\n\nexport const GLOBAL_CREDENTIALS_DIR = join(homedir(), '.kizenappbuilder');\nexport const GLOBAL_CREDENTIALS_PATH = join(GLOBAL_CREDENTIALS_DIR, 'credentials.json');\nexport const DEFAULT_PROFILE_NAME = 'credentials';\n\nfunction isValidEnvironment(value: unknown): value is Environment {\n return ENVIRONMENTS.includes(value as Environment);\n}\n\nfunction parseCredentials(raw: unknown): Credentials {\n if (typeof raw !== 'object' || raw === null) {\n throw new Error('Credentials must be a JSON object');\n }\n\n const obj = raw as Record<string, unknown>;\n const env = obj.environment;\n\n return {\n apiKey: typeof obj.apiKey === 'string' ? obj.apiKey : '',\n userId: typeof obj.userId === 'string' ? obj.userId : '',\n businessId: typeof obj.businessId === 'string' ? obj.businessId : '',\n environment: isValidEnvironment(env) ? env : 'go',\n };\n}\n\nexport async function loadCredentialsFromFile(filePath: string): Promise<Credentials> {\n const content = await readFile(filePath, 'utf-8');\n\n return parseCredentials(JSON.parse(content) as unknown);\n}\n\nexport async function loadGlobalCredentials(): Promise<Credentials | null> {\n try {\n return await loadCredentialsFromFile(GLOBAL_CREDENTIALS_PATH);\n } catch {\n return null;\n }\n}\n\nexport async function saveGlobalCredentials(credentials: Credentials): Promise<void> {\n await mkdir(dirname(GLOBAL_CREDENTIALS_PATH), { recursive: true, mode: 0o700 });\n\n await writeFile(GLOBAL_CREDENTIALS_PATH, JSON.stringify(credentials, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n}\n\nexport function getProfilePath(name: string): string {\n return join(GLOBAL_CREDENTIALS_DIR, `${name}.json`);\n}\n\nexport async function listCredentialProfiles(): Promise<CredentialProfile[]> {\n const profiles: CredentialProfile[] = [\n { name: DEFAULT_PROFILE_NAME, path: GLOBAL_CREDENTIALS_PATH, isDefault: true },\n ];\n\n try {\n const entries = await readdir(GLOBAL_CREDENTIALS_DIR);\n\n for (const entry of entries) {\n if (!entry.endsWith('.json')) {\n continue;\n }\n\n const name = entry.slice(0, -5);\n\n if (name === DEFAULT_PROFILE_NAME) {\n continue;\n }\n\n profiles.push({ name, path: join(GLOBAL_CREDENTIALS_DIR, entry), isDefault: false });\n }\n } catch {\n // directory doesn't exist yet — only the default profile\n }\n\n return profiles;\n}\n\nexport async function saveCredentialProfile(name: string, credentials: Credentials): Promise<void> {\n if (name === DEFAULT_PROFILE_NAME) {\n await saveGlobalCredentials(credentials);\n\n return;\n }\n\n await mkdir(GLOBAL_CREDENTIALS_DIR, { recursive: true, mode: 0o700 });\n\n await writeFile(getProfilePath(name), JSON.stringify(credentials, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n}\n\nexport async function loadCredentialProfile(name: string): Promise<Credentials | null> {\n try {\n return await loadCredentialsFromFile(getProfilePath(name));\n } catch {\n return null;\n }\n}\n","export const ENVIRONMENTS = ['go', 'fmo', 'staging', 'integration', 'test1'] as const;\nexport type Environment = (typeof ENVIRONMENTS)[number];\n\nexport interface Credentials {\n apiKey: string;\n userId: string;\n businessId: string;\n environment: Environment;\n}\n","import { ARTIFACT_TYPES } from './createArtifacts.js';\nimport type { ArtifactType } from './createArtifacts.js';\nimport { API_NAME_HINT, API_NAME_PATTERN, inferApiName } from './createForm.js';\nimport type { CreatePluginInput, PrecheckResult } from './createPlugin.js';\nimport { ENVIRONMENTS } from '../../shared/lib/credentials.js';\nimport type { Environment } from '../../shared/lib/credentials.js';\n\nexport const PLACEHOLDER_DESCRIPTION = 'A hello-world Kizen plugin.';\n\nexport interface CreateOptions {\n name?: string;\n apiName?: string;\n description?: string;\n externalLink?: string;\n businessId?: string;\n environment?: string;\n artifacts?: string;\n}\n\nexport interface HeadlessDefaults {\n businessId: string;\n environment: Environment;\n}\n\nexport function parseArtifactSelection(raw: string | undefined): ArtifactType[] {\n if (raw === undefined || raw.trim() === '' || raw.trim() === 'all') {\n return [...ARTIFACT_TYPES];\n }\n\n if (raw.trim() === 'none') {\n return [];\n }\n\n const requested = raw\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part !== '');\n\n const unknown = requested.filter((part) => !ARTIFACT_TYPES.includes(part as ArtifactType));\n\n if (unknown.length > 0) {\n throw new Error(\n `Unknown artifact type(s): ${unknown.join(', ')}. Valid types: ${ARTIFACT_TYPES.join(', ')}, or \"all\" / \"none\".`,\n );\n }\n\n return [...new Set(requested as ArtifactType[])];\n}\n\nexport function resolveHeadlessInput(\n options: CreateOptions,\n defaults: HeadlessDefaults,\n targetDir: string,\n): CreatePluginInput {\n const name = options.name?.trim() ?? '';\n\n if (name === '') {\n throw new Error('--name is required for a non-interactive run.');\n }\n\n const apiName = (options.apiName?.trim() ?? '') || inferApiName(name);\n\n if (!API_NAME_PATTERN.test(apiName)) {\n throw new Error(`api_name \"${apiName}\" is invalid: ${API_NAME_HINT}. Pass --api-name.`);\n }\n\n const description = options.description?.trim();\n\n const developerBusinessId = options.businessId?.trim() ?? defaults.businessId;\n const developerEnvironment = resolveEnvironment(options, defaults);\n\n return {\n targetDir,\n name,\n apiName,\n externalLink: options.externalLink?.trim() ?? '',\n description:\n description === undefined || description === '' ? PLACEHOLDER_DESCRIPTION : description,\n developerBusinessId,\n developerEnvironment,\n artifacts: parseArtifactSelection(options.artifacts),\n };\n}\n\nfunction isEnvironment(value: string): value is Environment {\n return (ENVIRONMENTS as readonly string[]).includes(value);\n}\n\nfunction resolveEnvironment(options: CreateOptions, defaults: HeadlessDefaults): Environment {\n const requested = options.environment?.trim();\n\n if (requested !== undefined && requested !== '') {\n if (!isEnvironment(requested)) {\n throw new Error(\n `Unknown environment \"${requested}\". Valid environments: ${ENVIRONMENTS.join(', ')}.`,\n );\n }\n\n return requested;\n }\n\n if (options.businessId !== undefined && defaults.businessId === '') {\n throw new Error(\n '--environment is required alongside --business-id when no credentials are saved, so the id is keyed to the environment that issued it.',\n );\n }\n\n return defaults.environment;\n}\n\nexport interface HeadlessDeps {\n precheckTargetDir: (dir: string) => Promise<PrecheckResult>;\n createPlugin: (input: CreatePluginInput) => Promise<void>;\n writeStdout: (text: string) => void;\n writeStderr: (text: string) => void;\n setExitCode: (code: number) => void;\n}\n\nexport async function runHeadlessCreate(\n options: CreateOptions,\n defaults: HeadlessDefaults,\n targetDir: string,\n deps: HeadlessDeps,\n): Promise<void> {\n let input: CreatePluginInput;\n\n try {\n input = resolveHeadlessInput(options, defaults, targetDir);\n } catch (err) {\n deps.writeStderr(`Error: ${err instanceof Error ? err.message : String(err)}\\n`);\n\n deps.setExitCode(1);\n\n return;\n }\n\n const precheck = await deps.precheckTargetDir(targetDir);\n\n if (precheck !== 'ok') {\n const conflict = precheck === 'has-manifest' ? 'kizen.json' : '.kizenapp/';\n\n deps.writeStderr(\n `Error: ${targetDir} already contains ${conflict}. Refusing to overwrite an existing plugin.\\n`,\n );\n\n deps.setExitCode(1);\n\n return;\n }\n\n try {\n await deps.createPlugin(input);\n } catch (err) {\n deps.writeStderr(`Error: ${err instanceof Error ? err.message : String(err)}\\n`);\n\n deps.setExitCode(1);\n\n return;\n }\n\n const artifactSummary =\n input.artifacts && input.artifacts.length > 0 ? input.artifacts.join(', ') : 'none';\n\n deps.writeStdout(`Created plugin ${input.apiName} at ${targetDir}\\n`);\n\n deps.writeStdout(`Artifacts: ${artifactSummary}\\n`);\n\n deps.writeStdout(\n 'Thumbnail: src/thumbnail.png (generated placeholder; replace it before publishing)\\n',\n );\n\n if (input.developerBusinessId.trim() === '') {\n deps.writeStderr(\n 'Warning: no developer_business_id configured, so this plugin cannot be preview-published yet.\\n',\n );\n }\n}\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { DevUI } from '../ui/DevUI.js';\nimport { CredentialSetupUI } from '../ui/CredentialSetupUI.js';\nimport type { CredentialMode, CredentialSetupResult } from '../ui/CredentialSetupUI.js';\nimport {\n loadCredentialProfile,\n loadCredentialsFromFile,\n loadGlobalCredentials,\n} from '../lib/credentials.js';\nimport type { Credentials } from '../lib/credentials.js';\nimport { loadConfig, saveConfig } from '../lib/config.js';\nimport { ensureGitignore } from '../lib/gitignore.js';\n\nasync function runSetupUI(initialMode?: CredentialMode): Promise<CredentialSetupResult> {\n return new Promise((resolve) => {\n let unmountFn: (() => void) | null = null;\n const handleComplete = (result: CredentialSetupResult): void => {\n unmountFn?.();\n\n resolve(result);\n };\n\n const { unmount } = render(\n createElement(CredentialSetupUI, {\n ...(initialMode !== undefined && { initialMode }),\n onComplete: handleComplete,\n }),\n { exitOnCtrlC: false },\n );\n\n unmountFn = unmount;\n });\n}\n\nexport function devCommand(program: Command): void {\n program\n .command('dev')\n .description('Start the plugin viewer dev server')\n .option('-p, --port <port>', 'port to listen on', '3121')\n .option('-c, --credentials <path>', 'path to a credentials JSON file')\n .option('-d, --debug', 'Enable CDP lifecycle logs in the TUI')\n .option('-v, --verbose', 'Log every CDP event and handled error (implies --debug)')\n .option('--no-viewer', \"Don't auto-launch the viewer on startup (press [v] to launch manually)\")\n .option('--no-cache', 'Disable the network proxy cache (always fetch upstream)')\n .action(\n async (options: {\n port: string;\n credentials?: string;\n debug?: boolean;\n verbose?: boolean;\n viewer?: boolean;\n cache?: boolean;\n }) => {\n const port = parseInt(options.port, 10);\n const pluginDir = process.cwd();\n const outputDir = `${pluginDir}/.kizenapp`;\n\n ensureGitignore(pluginDir);\n\n let credentials: Credentials | null = null;\n let credentialMode: CredentialMode | undefined;\n let activeCredentialProfile: string | undefined;\n const { lastPath } = await loadConfig(outputDir);\n\n if (options.credentials) {\n credentials = await loadCredentialsFromFile(options.credentials);\n } else {\n const config = await loadConfig(outputDir);\n\n if (config.credentialMode === 'local') {\n credentialMode = 'local';\n } else if (config.credentialMode === 'global') {\n credentialMode = 'global';\n\n activeCredentialProfile = config.activeCredentialProfile;\n\n // Load silently — only show TUI if the file was deleted since last run\n if (activeCredentialProfile) {\n credentials = await loadCredentialProfile(activeCredentialProfile);\n\n if (!credentials) {\n // Named profile file missing, fall back to default\n credentials = await loadGlobalCredentials();\n\n activeCredentialProfile = undefined;\n }\n } else {\n credentials = await loadGlobalCredentials();\n }\n\n if (!credentials) {\n const result = await runSetupUI('global');\n\n credentials = result.credentials;\n\n activeCredentialProfile = result.profileName;\n }\n } else {\n // First run — show full mode selection TUI\n const result = await runSetupUI();\n\n credentials = result.credentials;\n\n credentialMode = result.mode;\n\n activeCredentialProfile = result.profileName;\n\n const profile = result.profileName;\n\n await saveConfig(outputDir, {\n credentialMode: result.mode,\n ...(profile !== undefined && { activeCredentialProfile: profile }),\n });\n }\n }\n\n const verbose = options.verbose === true;\n const debug = verbose || options.debug === true;\n const autoViewer = options.viewer !== false;\n const cacheEnabled = options.cache !== false;\n\n const { waitUntilExit } = render(\n createElement(DevUI, {\n port,\n pluginDir,\n outputDir,\n credentials,\n ...(credentialMode !== undefined && { credentialMode }),\n ...(activeCredentialProfile !== undefined && { activeCredentialProfile }),\n ...(lastPath !== undefined && { lastPath }),\n debug,\n verbose,\n autoViewer,\n cacheEnabled,\n }),\n { exitOnCtrlC: false },\n );\n\n await waitUntilExit();\n },\n );\n}\n","import type { FC } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { PluginValidationError } from '@kizenapps/packager';\nimport type { ValidationIssue } from '@kizenapps/packager';\nimport { watch } from 'node:fs';\nimport type { FSWatcher } from 'node:fs';\nimport { createServer } from 'node:http';\nimport type { Server } from 'node:http';\nimport { join } from 'node:path';\nimport { type WebSocket, WebSocketServer } from 'ws';\nimport {\n createRequestHandler,\n fileExists,\n getViewerPath,\n type ProxyLogEntry,\n proxyLogEntryToString,\n} from '../server/requestHandler.js';\nimport { launchChromeViewer, type ChromeViewerHandle } from '../chrome/launcher.js';\nimport { runBuild } from '../lib/runBuild.js';\nimport type { Credentials } from '../lib/credentials.js';\nimport { saveConfig } from '../lib/config.js';\nimport { LOG_LIMIT, LOG_DISPLAY, FILE_WATCH_DEBOUNCE_MS } from '../lib/constants.js';\nimport { formatBytes } from '../../shared/lib/formatBytes.js';\nimport { useLogHistory } from '../hooks/useLogHistory.js';\nimport { CredentialSetupUI } from './CredentialSetupUI.js';\nimport type { CredentialMode, CredentialSetupResult } from './CredentialSetupUI.js';\nimport { AppHeader } from './AppHeader.js';\nimport { Spinner } from './Spinner.js';\nimport { ValidationIssues } from './ValidationIssues.js';\n\ntype ServerStatus = 'starting' | 'running' | 'error';\ntype BuildStatus = 'pending' | 'building' | 'done' | 'error';\n\nconst SKIP_WATCH_PREFIXES = ['.kizenapp', '.git'];\n\ninterface DevUIProps {\n port: number;\n pluginDir: string;\n outputDir: string;\n credentials: Credentials | null;\n credentialMode?: CredentialMode;\n activeCredentialProfile?: string;\n lastPath?: string;\n debug?: boolean;\n verbose?: boolean;\n autoViewer?: boolean;\n cacheEnabled?: boolean;\n}\n\nexport const DevUI: FC<DevUIProps> = ({\n port,\n pluginDir,\n outputDir,\n credentials: initialCredentials,\n credentialMode: initialCredentialMode,\n activeCredentialProfile: initialActiveProfile,\n lastPath: initialLastPath,\n debug = false,\n verbose = false,\n autoViewer = true,\n cacheEnabled = true,\n}) => {\n const credentialsRef = useRef<Credentials | null>(initialCredentials);\n const activeProfileRef = useRef<string | undefined>(initialActiveProfile);\n const lastPathRef = useRef<string | undefined>(initialLastPath);\n const [credMode, setCredMode] = useState<'main' | 'editing'>('main');\n const [credentialMode, setCredentialMode] = useState<CredentialMode | undefined>(\n initialCredentialMode,\n );\n\n const [status, setStatus] = useState<ServerStatus>('starting');\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [serverLogHistory, appendServerLog] = useLogHistory(LOG_LIMIT);\n const [buildLogHistory, appendBuildLog] = useLogHistory(LOG_LIMIT);\n const [cdpLogHistory, appendCdpLog] = useLogHistory(LOG_LIMIT);\n const [proxyLogHistory, setProxyLogHistory] = useState<string[]>([]);\n const [buildStatus, setBuildStatus] = useState<BuildStatus>('pending');\n const [buildError, setBuildError] = useState<string | null>(null);\n const [buildIssues, setBuildIssues] = useState<ValidationIssue[] | null>(null);\n const [lastBuilt, setLastBuilt] = useState<Date | null>(null);\n const [lastBundleSize, setLastBundleSize] = useState<number | null>(null);\n const [wsClientCount, setWsClientCount] = useState(0);\n const [proxyCacheSize, setProxyCacheSize] = useState(0);\n const [proxyCacheHits, setProxyCacheHits] = useState(0);\n const [proxyCacheMisses, setProxyCacheMisses] = useState(0);\n\n const buildingRef = useRef(false);\n const viewerLaunchedRef = useRef(false);\n const chromeHandleRef = useRef<ChromeViewerHandle | null>(null);\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wsClientsRef = useRef<Set<WebSocket>>(new Set());\n const pendingMessagesRef = useRef<string[]>([]);\n\n const broadcast = useCallback((msg: object): void => {\n const json = JSON.stringify(msg);\n\n if (wsClientsRef.current.size === 0) {\n pendingMessagesRef.current = [...pendingMessagesRef.current, json].slice(-LOG_LIMIT);\n\n return;\n }\n\n let pruned = false;\n\n for (const client of wsClientsRef.current) {\n if (client.readyState !== 1) {\n continue;\n }\n\n try {\n client.send(json);\n } catch {\n // Socket died between readyState check and send — drop it so one\n // dead client can't break the loop and silently disconnect the rest.\n wsClientsRef.current.delete(client);\n pruned = true;\n }\n }\n\n if (pruned) {\n setWsClientCount(wsClientsRef.current.size);\n }\n }, []);\n\n const createServerLog = appendServerLog;\n\n const launchChromeViewerCb = useCallback(() => {\n chromeHandleRef.current?.kill();\n\n chromeHandleRef.current = null;\n\n void launchChromeViewer({\n port,\n userDataDir: join(outputDir, '.chrome'),\n broadcast,\n onWarn: (msg) => {\n appendServerLog(`⚠ ${msg}`);\n },\n ...(lastPathRef.current !== undefined && { path: lastPathRef.current }),\n ...(debug && { debugLog: appendCdpLog }),\n ...(verbose && { verbose: true }),\n }).then((handle) => {\n chromeHandleRef.current = handle;\n });\n }, [port, outputDir, broadcast, debug, verbose, appendCdpLog, appendServerLog]);\n\n useEffect(() => {\n const onExit = (): void => {\n chromeHandleRef.current?.kill();\n };\n\n process.on('exit', onExit);\n\n return () => {\n process.off('exit', onExit);\n };\n }, []);\n\n useInput(\n (input, key) => {\n if (input === 'q' || (key.ctrl && input === 'c')) {\n process.exit(0);\n }\n\n if (input === 'c') {\n setCredMode('editing');\n }\n\n if (input === 'v') {\n launchChromeViewerCb();\n }\n },\n { isActive: credMode === 'main' },\n );\n\n useEffect(() => {\n if (status !== 'running' || viewerLaunchedRef.current || !autoViewer) {\n return;\n }\n\n viewerLaunchedRef.current = true;\n\n launchChromeViewerCb();\n }, [status, autoViewer, launchChromeViewerCb]);\n\n const handleCredentialsDone = useCallback(\n (result: CredentialSetupResult): void => {\n credentialsRef.current = result.credentials;\n\n activeProfileRef.current = result.profileName;\n\n setCredMode('main');\n\n setCredentialMode(result.mode);\n\n const profile = result.profileName;\n\n void saveConfig(outputDir, {\n credentialMode: result.mode,\n ...(profile !== undefined && { activeCredentialProfile: profile }),\n });\n\n broadcast({ type: 'credentials-updated', credentials: result.credentials });\n },\n [outputDir, broadcast],\n );\n\n const createProxyLog = useCallback(\n (entry: ProxyLogEntry): void => {\n setProxyLogHistory((h) =>\n [...h, `${new Date().toLocaleTimeString()}: ${proxyLogEntryToString(entry)}`].slice(\n -LOG_LIMIT,\n ),\n );\n\n if (entry.kind === 'request') {\n if (entry.fromCache) {\n setProxyCacheHits((n) => n + 1);\n } else {\n setProxyCacheMisses((n) => n + 1);\n }\n }\n\n broadcast({ type: 'proxy-log', entry });\n },\n [broadcast],\n );\n\n const createBuildLog = useCallback(\n (message: string): void => {\n appendBuildLog(message);\n\n broadcast({ type: 'log', message });\n },\n [appendBuildLog, broadcast],\n );\n\n const triggerBuild = useCallback(() => {\n if (buildingRef.current) {\n return;\n }\n\n buildingRef.current = true;\n setBuildStatus('building');\n setBuildError(null);\n setBuildIssues(null);\n createBuildLog('Build started');\n\n void runBuild(pluginDir, outputDir)\n .then(({ bundleSize }) => {\n createBuildLog(`Build finished — bundle: ${formatBytes(bundleSize)}`);\n setBuildStatus('done');\n setLastBuilt(new Date());\n setLastBundleSize(bundleSize);\n createBuildLog('Notifying viewers to reload');\n broadcast({ type: 'rebuild' });\n })\n .catch((err: unknown) => {\n if (err instanceof PluginValidationError) {\n setBuildIssues(err.issues);\n setBuildError(null);\n } else {\n setBuildError(err instanceof Error ? err.message : String(err));\n setBuildIssues(null);\n }\n\n setBuildStatus('error');\n })\n .finally(() => {\n buildingRef.current = false;\n });\n }, [pluginDir, outputDir, createBuildLog, broadcast]);\n\n useEffect(() => {\n triggerBuild();\n\n const watcher: FSWatcher = watch(pluginDir, { recursive: true }, (_, filename) => {\n if (!filename) {\n return;\n }\n\n const normalized = filename.replace(/\\\\/g, '/');\n\n if (SKIP_WATCH_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {\n return;\n }\n\n createBuildLog(`File change detected: ${filename}`);\n\n if (debounceTimerRef.current !== null) {\n clearTimeout(debounceTimerRef.current);\n }\n\n debounceTimerRef.current = setTimeout(triggerBuild, FILE_WATCH_DEBOUNCE_MS);\n });\n\n // fs.watch silently dies on e.g. macOS inode-limit pressure — surface it so\n // developers know rebuilds have stopped rather than wondering why their\n // edits aren't reflected in the viewer.\n watcher.on('error', (err: Error) => {\n createBuildLog(`File watcher error — rebuilds have stopped: ${err.message}`);\n });\n\n return () => {\n watcher.close();\n\n if (debounceTimerRef.current !== null) {\n clearTimeout(debounceTimerRef.current);\n }\n };\n }, [pluginDir, triggerBuild, createBuildLog]);\n\n useEffect(() => {\n const viewerPath = getViewerPath();\n\n void fileExists(join(viewerPath, 'index.html')).then((viewerBuilt) => {\n if (!viewerBuilt) {\n setErrorMessage(\"Viewer not built. Run 'pnpm build:viewer' first.\");\n setStatus('error');\n\n return;\n }\n\n const handler = createRequestHandler(\n viewerPath,\n createServerLog,\n createProxyLog,\n credentialsRef,\n activeProfileRef,\n outputDir,\n broadcast,\n setProxyCacheSize,\n lastPathRef,\n pluginDir,\n cacheEnabled,\n );\n const server: Server = createServer(handler);\n const wss = new WebSocketServer({ server });\n\n wss.on('connection', (ws: WebSocket) => {\n for (const json of pendingMessagesRef.current) {\n if (ws.readyState === 1) {\n ws.send(json);\n }\n }\n\n pendingMessagesRef.current = [];\n createServerLog('Viewer connected for live reload');\n wsClientsRef.current.add(ws);\n setWsClientCount(wsClientsRef.current.size);\n\n ws.on('close', () => {\n wsClientsRef.current.delete(ws);\n setWsClientCount(wsClientsRef.current.size);\n });\n });\n\n server.listen(port, '127.0.0.1', () => {\n setStatus('running');\n createServerLog(`Server started on 127.0.0.1:${String(port)}`);\n });\n\n server.on('error', (err: Error) => {\n setErrorMessage(err.message);\n setStatus('error');\n });\n\n return () => {\n wss.close();\n server.close();\n };\n });\n }, [port, createServerLog, createProxyLog, broadcast, outputDir, pluginDir, cacheEnabled]);\n\n if (credMode === 'editing') {\n return (\n <CredentialSetupUI\n {...(credentialMode !== undefined && { initialMode: credentialMode })}\n showProfileManager={credentialMode === 'global'}\n onComplete={handleCredentialsDone}\n onCancel={() => {\n setCredMode('main');\n }}\n />\n );\n }\n\n const elapsedSeconds =\n lastBuilt !== null ? Math.round((Date.now() - lastBuilt.getTime()) / 1000) : null;\n\n const elapsedLabel =\n elapsedSeconds === null\n ? ''\n : elapsedSeconds < 5\n ? ' (just now)'\n : ` (${String(elapsedSeconds)}s ago)`;\n\n const buildErrorCount = buildIssues?.filter((issue) => issue.severity === 'error').length ?? 0;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2}>\n <AppHeader marginBottom={1} />\n\n {/* Build panel */}\n <Box flexDirection=\"column\">\n <Box gap={2} marginBottom={0}>\n <Text bold dimColor>\n App Build\n </Text>\n {buildStatus === 'pending' && <Text dimColor>waiting…</Text>}\n {buildStatus === 'building' && (\n <Box gap={1}>\n <Spinner />\n <Text>Building plugin package…</Text>\n </Box>\n )}\n {buildStatus === 'done' && (\n <Box gap={1}>\n <Text color=\"green\">✓ Built</Text>\n {lastBuilt !== null && (\n <Text dimColor>\n at {lastBuilt.toLocaleTimeString()}\n {elapsedLabel}\n </Text>\n )}\n {lastBundleSize !== null && (\n <Text dimColor>· bundle: {formatBytes(lastBundleSize)}</Text>\n )}\n </Box>\n )}\n {buildStatus === 'error' &&\n (buildIssues !== null ? (\n <Text color=\"red\">\n ✗ {buildErrorCount} validation {buildErrorCount === 1 ? 'error' : 'errors'}\n </Text>\n ) : (\n <Text color=\"red\">✗ {buildError ?? 'unknown error'}</Text>\n ))}\n </Box>\n {buildIssues !== null && <ValidationIssues issues={buildIssues} />}\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY + 2}\n borderStyle=\"single\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {buildLogHistory.slice(-LOG_DISPLAY).map((log, index) => (\n <Text key={index} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))}\n </Box>\n </Box>\n\n {/* Server panel */}\n <Box marginTop={1} flexDirection=\"column\">\n <Box gap={2}>\n <Text bold dimColor>\n Web Server\n </Text>\n {status === 'starting' && <Text dimColor>starting…</Text>}\n {status === 'running' && (\n <Box gap={2}>\n <Text color=\"green\">✓ Running</Text>\n <Text dimColor>\n ● {wsClientCount} viewer{wsClientCount !== 1 ? 's' : ''}\n </Text>\n </Box>\n )}\n {status === 'error' && <Text color=\"red\">✗ {errorMessage ?? 'Server error'}</Text>}\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY + 2}\n borderStyle=\"single\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {serverLogHistory.slice(-LOG_DISPLAY).map((log, index) => (\n <Text key={index} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))}\n </Box>\n </Box>\n\n {/* Proxy panel */}\n <Box marginTop={1} flexDirection=\"column\">\n <Box gap={2}>\n <Text bold dimColor>\n Network Proxy\n </Text>\n <Text color=\"green\">✓ Active</Text>\n <Text dimColor>\n {cacheEnabled\n ? `● ${String(proxyCacheSize)} key${proxyCacheSize !== 1 ? 's' : ''} in the network cache · ${String(proxyCacheHits)} hit · ${String(proxyCacheMisses)} miss`\n : `● network cache disabled · ${String(proxyCacheMisses)} request${proxyCacheMisses !== 1 ? 's' : ''}`}\n </Text>\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY + 2}\n borderStyle=\"single\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {proxyLogHistory.length === 0 ? (\n <Text dimColor> No requests yet.</Text>\n ) : (\n proxyLogHistory.slice(-LOG_DISPLAY).map((log, i) => (\n <Text key={i} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))\n )}\n </Box>\n </Box>\n\n {debug && (\n <Box marginTop={1} flexDirection=\"column\">\n <Box gap={2}>\n <Text bold dimColor>\n CDP Debug\n </Text>\n <Text dimColor>● {cdpLogHistory.length} event(s)</Text>\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY + 2}\n borderStyle=\"single\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {cdpLogHistory.length === 0 ? (\n <Text dimColor> No CDP events yet.</Text>\n ) : (\n cdpLogHistory.slice(-LOG_DISPLAY).map((log, i) => (\n <Text key={i} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))\n )}\n </Box>\n </Box>\n )}\n\n {/* Footer */}\n <Box marginTop={1} gap={1}>\n <Text dimColor>[</Text>\n <Text>q</Text>\n <Text dimColor>] quit [</Text>\n <Text>c</Text>\n <Text dimColor>] credentials [</Text>\n <Text>v</Text>\n <Text dimColor>] {wsClientCount === 0 ? 'open viewer' : 'relaunch viewer'}</Text>\n </Box>\n </Box>\n );\n};\n","import { createReadStream, realpathSync } from 'node:fs';\nimport { access, readdir, readFile, realpath, stat } from 'node:fs/promises';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { dirname, extname, join, resolve, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n createProxyCache,\n MAX_PROXY_BYTES,\n ProxyResponseTooLargeError,\n readBodyWithLimit,\n sanitizeUpstreamHeaders,\n} from '../lib/proxyCache.js';\nimport { MIME_TYPES } from '../lib/constants.js';\nimport type { Credentials } from '../lib/credentials.js';\nimport {\n listCredentialProfiles,\n loadCredentialProfile,\n loadGlobalCredentials,\n} from '../lib/credentials.js';\nimport { loadConfig, saveConfig } from '../lib/config.js';\nimport { resolveWizardBase } from '../lib/wizardUrl.js';\nimport { executePythonStep } from './pythonExecutor.js';\nimport { SKIP_DIRS } from '../lib/readFiles.js';\nimport { TEXT_EXTENSIONS } from '../../shared/lib/fileExtensions.js';\nimport { normalizeStepInputs } from '../../shared/lib/execution.js';\nimport {\n CRYPTO_ALG,\n CRYPTO_VERSION,\n deserializeEnvelope,\n encrypt,\n serializeEnvelope,\n} from '@kizenapps/packager';\n\nconst SOURCE_FILE_MAX_BYTES = 2 * 1024 * 1024;\n\nconst SKIP_FILES = new Set(['.DS_Store', '.gitignore']);\n\nfunction isLocalHost(host: string | undefined): boolean {\n if (host === undefined || host === '') {\n return false;\n }\n\n // Strip the port. This is a host header, so IPv6 would arrive as \"[::1]:port\"\n // — we don't serve ::1 (Node binds to 127.0.0.1), but the guard is permissive\n // enough to survive that even if the bind address changes later.\n const hostname = host.startsWith('[')\n ? host.slice(0, host.indexOf(']') + 1)\n : (host.split(':')[0] ?? '');\n\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]';\n}\n\nconst PROXY_ALLOWED_DOMAINS = ['kizen.com', 'kizen.dev'];\n\n/**\n * Guards the resolved encryption-API host. The wizard proxy forwards the\n * caller's Kizen credential headers, so a fat-fingered PLUGIN_WIZARD_URL* env\n * var must not be able to leak them to an arbitrary origin. Allows a\n * locally-running wizard (any localhost/loopback) plus https on a Kizen domain.\n */\nfunction isAllowedWizardTarget(target: string): boolean {\n let url: URL;\n\n try {\n url = new URL(target);\n } catch {\n return false;\n }\n\n const hostname = url.hostname.toLowerCase();\n\n // URL.hostname returns IPv6 literals bracketed, e.g. '[::1]'.\n if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]') {\n return true;\n }\n\n if (url.protocol !== 'https:') {\n return false;\n }\n\n return PROXY_ALLOWED_DOMAINS.some(\n (domain) => hostname === domain || hostname.endsWith('.' + domain),\n );\n}\n\nfunction isAllowedProxyTarget(target: string): boolean {\n let url: URL;\n\n try {\n url = new URL(target);\n } catch {\n return false;\n }\n\n if (url.protocol !== 'https:') {\n return false;\n }\n\n const hostname = url.hostname.toLowerCase();\n\n return PROXY_ALLOWED_DOMAINS.some(\n (domain) => hostname === domain || hostname.endsWith('.' + domain),\n );\n}\n\nfunction isLocalOrigin(origin: string | undefined): boolean {\n if (origin === undefined || origin === '') {\n return false;\n }\n\n try {\n const { hostname } = new URL(origin);\n\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1';\n } catch {\n return false;\n }\n}\n\nasync function resolveSafePath(realPluginDir: string, relParam: string): Promise<string | null> {\n if (relParam.includes('\\0')) {\n return null;\n }\n\n const rel = relParam.replace(/^\\/+/, '');\n const abs = resolve(realPluginDir, rel);\n\n // Syntactic .. traversal check — fails fast before touching the filesystem.\n if (abs !== realPluginDir && !abs.startsWith(realPluginDir + sep)) {\n return null;\n }\n\n // Symlink-aware check: a symlink inside the plugin dir can still escape it\n // (e.g. a link to ~/.ssh/id_rsa resolves to a path that passes the string\n // check above but reads arbitrary files). Realpath the target and re-verify.\n // If the target doesn't exist realpath throws — reject rather than guess.\n try {\n const realAbs = await realpath(abs);\n\n if (realAbs !== realPluginDir && !realAbs.startsWith(realPluginDir + sep)) {\n return null;\n }\n\n return realAbs;\n } catch {\n return null;\n }\n}\n\nfunction isInsideSkippedDir(pluginDir: string, abs: string): boolean {\n const rel = abs === pluginDir ? '' : abs.slice(pluginDir.length + 1);\n\n if (rel === '') {\n return false;\n }\n\n const segments = rel.split(sep);\n\n return segments.some((segment) => SKIP_DIRS.has(segment));\n}\n\nexport type { ProxyLogEntry } from '../../shared/lib/proxy.js';\nexport { proxyLogEntryToString } from '../../shared/lib/proxy.js';\nimport { type ProxyLogEntry } from '../../shared/lib/proxy.js';\n\nexport function getViewerPath(): string {\n const filename = fileURLToPath(import.meta.url);\n\n return join(dirname(filename), 'viewer');\n}\n\n/**\n * Calls to Kizen's `/external-integrations/proxy` endpoint wrap the third-party\n * API's status in the response body (`status_code`) and return HTTP 200 even\n * when the upstream call failed. Pull that real status out so the network log\n * can surface it instead of the misleading proxy status.\n */\nfunction extractUpstreamStatus(\n upstreamPath: string,\n headers: Record<string, string>,\n body: Buffer,\n): number | undefined {\n if (!upstreamPath.includes('/external-integrations/proxy')) {\n return undefined;\n }\n\n if (!headers['content-type']?.includes('application/json')) {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(body.toString('utf8')) as { status_code?: unknown };\n\n return typeof parsed.status_code === 'number' ? parsed.status_code : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport function createRequestHandler(\n viewerPath: string,\n createServerLog: (message: string) => void,\n createProxyLog: (entry: ProxyLogEntry) => void,\n credentialsRef: { current: Credentials | null },\n activeProfileRef: { current: string | undefined },\n outputDir: string,\n broadcast: (msg: object) => void,\n onProxyCacheChange: (size: number) => void,\n lastPathRef: { current: string | undefined },\n pluginDir: string,\n cacheEnabled: boolean,\n): (req: IncomingMessage, res: ServerResponse) => void {\n const proxyCache = createProxyCache({ onChange: onProxyCacheChange, enabled: cacheEnabled });\n // Resolve the plugin dir once so every source-path check compares against\n // the canonical path (handles macOS /var → /private/var, pnpm workspace\n // symlinks, etc.). Done synchronously at handler creation since pluginDir\n // is process.cwd() and must already exist.\n const realPluginDir = realpathSync(pluginDir);\n\n return (req, res) => {\n void (async () => {\n const url = req.url ?? '/';\n\n try {\n // Even though we bind to 127.0.0.1, a browser tab on\n // a malicious origin can point its DNS at our loopback address. The\n // Host header still carries the original hostname, so rejecting\n // anything that isn't localhost/127.0.0.1 closes the hole.\n if (!isLocalHost(req.headers.host)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Forbidden' }));\n\n return;\n }\n\n const isWrite = req.method === 'POST' || req.method === 'PATCH' || req.method === 'DELETE';\n\n if (isWrite && !isLocalOrigin(req.headers.origin)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Forbidden' }));\n\n return;\n }\n\n createServerLog(`Received request: ${url}`);\n\n if (url === '/api/credentials') {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(\n JSON.stringify({\n credentials: credentialsRef.current ?? null,\n activeProfile: activeProfileRef.current ?? null,\n }),\n );\n\n return;\n }\n\n if (url === '/api/credential-profiles' && req.method === 'GET') {\n const profiles = await listCredentialProfiles();\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(JSON.stringify({ profiles, active: activeProfileRef.current }));\n\n return;\n }\n\n if (url === '/api/credentials/switch' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n profile?: string;\n };\n const profileName = body.profile;\n const creds =\n profileName === undefined || profileName === ''\n ? await loadGlobalCredentials()\n : await loadCredentialProfile(profileName);\n\n if (creds !== null) {\n credentialsRef.current = creds;\n\n activeProfileRef.current = profileName ?? undefined;\n\n const active = activeProfileRef.current;\n const currentConfig = await loadConfig(outputDir);\n\n await saveConfig(outputDir, {\n ...currentConfig,\n credentialMode: 'global',\n ...(active !== undefined && { activeCredentialProfile: active }),\n });\n\n broadcast({\n type: 'credentials-updated',\n credentials: creds,\n activeProfile: activeProfileRef.current ?? null,\n });\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(JSON.stringify({ ok: creds !== null }));\n\n return;\n }\n\n if (url === '/api/bundle') {\n const bundlePath = join(process.cwd(), '.kizenapp', 'bundle.json');\n\n try {\n const content = await readFile(bundlePath, 'utf-8');\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(content);\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end('{}');\n }\n\n return;\n }\n\n if (url === '/api/last-path' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n path?: string;\n };\n\n if (typeof body.path === 'string') {\n lastPathRef.current = body.path;\n\n const currentConfig = await loadConfig(outputDir);\n\n await saveConfig(outputDir, { ...currentConfig, lastPath: body.path });\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end('{\"ok\":true}');\n\n return;\n }\n\n if (url === '/api/encryption-target' && req.method === 'GET') {\n const config = await loadConfig(outputDir);\n // Default to 'prod' when unset. Anything that isn't an explicit 'dev'\n // (incl. a legacy 'auto' from before the heuristic was dropped) maps to\n // 'prod', so the API only ever returns a concrete target.\n const target = config.encryptionTarget === 'dev' ? 'dev' : 'prod';\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ target }));\n\n return;\n }\n\n if (url === '/api/encryption-target' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const parsed: unknown = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}');\n const body: { target?: string } =\n parsed !== null && typeof parsed === 'object' ? (parsed as { target?: string }) : {};\n\n if (body.target !== 'dev' && body.target !== 'prod') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: \"target must be one of: 'dev', 'prod'\" }));\n\n return;\n }\n\n const currentConfig = await loadConfig(outputDir);\n\n // body.target is narrowed to 'dev' | 'prod' by the guard above.\n await saveConfig(outputDir, { ...currentConfig, encryptionTarget: body.target });\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n\n return;\n }\n\n if (url === '/api/execute-step' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n script?: string;\n scriptRuntime?: string;\n inputs?: Record<string, unknown>;\n secrets?: Record<string, string>;\n timeout?: number;\n };\n\n if (typeof body.script !== 'string') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(JSON.stringify({ error: 'Missing required field: script' }));\n\n return;\n }\n\n const stepParams: Parameters<typeof executePythonStep>[0] = {\n script: body.script,\n // Matches the production Kizen code-runner service's default runtime\n // (\"python-3-13\"). Only used when a caller omits a runtime; real\n // plugin steps send their own \"python-3-NN\" value.\n scriptRuntime: body.scriptRuntime ?? 'python-3-13',\n inputs: normalizeStepInputs(body.inputs),\n secrets: body.secrets ?? {},\n onInstallProgress: (event) => {\n if (event.kind === 'start') {\n broadcast({ type: 'venv-install-start' });\n } else if (event.kind === 'log') {\n broadcast({\n type: 'venv-install-log',\n line: event.line,\n stream: event.stream,\n });\n } else if (event.kind === 'complete') {\n broadcast({ type: 'venv-install-complete' });\n } else {\n broadcast({ type: 'venv-install-error', message: event.message });\n }\n },\n };\n\n if (typeof body.timeout === 'number' && body.timeout > 0) {\n // Cap at 5 minutes so a runaway request can't hang the Python\n // runner indefinitely. Default (30s) still applies if omitted.\n stepParams.timeout = Math.min(body.timeout, 5 * 60 * 1000);\n }\n\n const result = await executePythonStep(stepParams);\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(JSON.stringify(result));\n\n return;\n }\n\n if (url === '/api/proxy-cache/clear') {\n proxyCache.clear();\n\n createProxyLog({ kind: 'info', message: 'Proxy cache cleared' });\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end('{\"ok\":true}');\n\n return;\n }\n\n if (url === '/api/local/encrypt' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n publicKeyPem?: string;\n value?: string;\n };\n\n if (typeof body.publicKeyPem !== 'string' || typeof body.value !== 'string') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Missing required fields: publicKeyPem, value' }));\n\n return;\n }\n\n try {\n const envelope = encrypt(body.value, body.publicKeyPem);\n const serialized = serializeEnvelope(envelope);\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify(serialized));\n } catch (err) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: (err as Error).message }));\n }\n\n return;\n }\n\n if (url === '/api/local/validate' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n value?: string;\n };\n\n if (typeof body.value !== 'string') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Missing required field: value' }));\n\n return;\n }\n\n interface CheckResult {\n label: string;\n expected: string;\n actual: string;\n pass: boolean;\n }\n\n let envelope: ReturnType<typeof deserializeEnvelope> | undefined;\n let parseError: string | undefined;\n\n try {\n envelope = deserializeEnvelope(body.value);\n } catch (err) {\n parseError = (err as Error).message;\n }\n\n if (parseError !== undefined || envelope === undefined) {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ valid: false, checks: [], error: parseError }));\n\n return;\n }\n\n const bufLen = (b64: string): number => Buffer.from(b64, 'base64').length;\n\n const checks: CheckResult[] = [\n {\n label: 'Version',\n expected: String(CRYPTO_VERSION),\n actual: String(envelope.v),\n pass: (envelope.v as number) === CRYPTO_VERSION,\n },\n {\n label: 'Algorithm',\n expected: CRYPTO_ALG,\n actual: envelope.alg,\n pass: (envelope.alg as string) === CRYPTO_ALG,\n },\n {\n label: 'Wrapped key',\n expected: '384 bytes (RSA-3072)',\n actual: `${String(bufLen(envelope.k))} bytes`,\n pass: bufLen(envelope.k) === 384,\n },\n {\n label: 'IV',\n expected: '12 bytes',\n actual: `${String(bufLen(envelope.iv))} bytes`,\n pass: bufLen(envelope.iv) === 12,\n },\n {\n label: 'Auth tag',\n expected: '16 bytes',\n actual: `${String(bufLen(envelope.tag))} bytes`,\n pass: bufLen(envelope.tag) === 16,\n },\n {\n label: 'Ciphertext',\n expected: '≥ 1 byte',\n actual: `${String(bufLen(envelope.ct))} bytes`,\n pass: bufLen(envelope.ct) >= 1,\n },\n ];\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ valid: checks.every((c) => c.pass), checks }));\n\n return;\n }\n\n if (url.startsWith('/api/wizard')) {\n // The viewer sends the saved dev/prod target here; we map it to a known\n // host. A duplicated header arrives as an array — take the first value.\n // Default to 'prod' when absent/invalid: prod is the product-wide\n // default (almost every plugin ships to production), and only an\n // explicit 'dev' routes to the dev keys.\n const rawTarget = req.headers['x-encryption-target'];\n const targetHeader = Array.isArray(rawTarget) ? rawTarget[0] : rawTarget;\n const target: 'dev' | 'prod' = targetHeader === 'dev' ? 'dev' : 'prod';\n const wizardBase = resolveWizardBase(target);\n\n // The credential headers below are forwarded to wizardBase — refuse to\n // forward them anywhere but a known host.\n if (!isAllowedWizardTarget(wizardBase)) {\n res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(\n JSON.stringify({\n error: `Encryption API host is not allowed: ${wizardBase}`,\n }),\n );\n\n return;\n }\n\n const upstreamPath = url.slice('/api/wizard'.length) || '/';\n const upstreamUrl = `${wizardBase}${upstreamPath}`;\n const method = req.method ?? 'GET';\n\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n host: _wizardHost,\n // Internal control header — don't forward it upstream.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n 'x-encryption-target': _encTarget,\n ...wizardForwardHeaders\n } = req.headers;\n\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n const resolvedBody = body && body.length > 0 ? body : undefined;\n\n let upstream: Response;\n\n try {\n upstream = await fetch(upstreamUrl, {\n method,\n headers: wizardForwardHeaders as Record<string, string>,\n ...(resolvedBody !== undefined && { body: resolvedBody }),\n });\n } catch (err) {\n const message =\n (err as NodeJS.ErrnoException).code === 'ECONNREFUSED'\n ? `plugin-wizard is not running at ${wizardBase}`\n : `Failed to reach plugin-wizard: ${(err as Error).message}`;\n\n res.writeHead(503, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: message }));\n\n return;\n }\n\n const wizardResponseHeaders = sanitizeUpstreamHeaders(\n Object.fromEntries(upstream.headers),\n );\n const wizardBody = await upstream.arrayBuffer();\n\n res.writeHead(upstream.status, wizardResponseHeaders);\n res.end(Buffer.from(wizardBody));\n\n return;\n }\n\n if (url.startsWith('/api/proxy')) {\n const proxyTarget = req.headers['x-proxy-target'];\n\n if (typeof proxyTarget !== 'string') {\n res.writeHead(400);\n\n res.end('Missing x-proxy-target header');\n\n return;\n }\n\n if (!isAllowedProxyTarget(proxyTarget)) {\n res.writeHead(400);\n\n res.end('Invalid proxy target');\n\n return;\n }\n\n const upstreamPath = url.slice('/api/proxy'.length) || '/';\n const upstreamUrl = `${proxyTarget}${upstreamPath}`;\n const method = req.method ?? 'GET';\n\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { host, 'x-proxy-target': _drop, ...forwardHeaders } = req.headers;\n\n if (method === 'GET') {\n const cacheKey = `GET::${upstreamUrl}`;\n const { response: cached, fromCache } = await proxyCache.get(cacheKey, () =>\n fetch(upstreamUrl, {\n method: 'GET',\n headers: forwardHeaders as Record<string, string>,\n }),\n );\n\n createProxyLog({\n kind: 'request',\n method: 'GET',\n status: cached.status,\n upstreamStatus: extractUpstreamStatus(upstreamPath, cached.headers, cached.body),\n fromCache,\n url: upstreamPath,\n });\n\n res.writeHead(cached.status, cached.headers);\n\n res.end(cached.body);\n\n return;\n }\n\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n const resolvedBody = body && body.length > 0 ? body : undefined;\n const upstream = await fetch(upstreamUrl, {\n method,\n headers: forwardHeaders as Record<string, string>,\n ...(resolvedBody !== undefined && { body: resolvedBody }),\n });\n const responseHeaders = sanitizeUpstreamHeaders(Object.fromEntries(upstream.headers));\n const responseBody = await readBodyWithLimit(upstream, MAX_PROXY_BYTES);\n\n createProxyLog({\n kind: 'request',\n method,\n status: upstream.status,\n upstreamStatus: extractUpstreamStatus(upstreamPath, responseHeaders, responseBody),\n fromCache: false,\n url: upstreamPath,\n });\n\n res.writeHead(upstream.status, responseHeaders);\n\n res.end(responseBody);\n\n return;\n }\n\n if (url.startsWith('/api/source/tree') && req.method === 'GET') {\n const query = new URL(url, 'http://localhost').searchParams;\n const relParam = query.get('path') ?? '';\n const abs = await resolveSafePath(realPluginDir, relParam);\n\n if (abs === null) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Invalid path' }));\n\n return;\n }\n\n if (isInsideSkippedDir(realPluginDir, abs)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Path is excluded' }));\n\n return;\n }\n\n try {\n const dirEntries = await readdir(abs, { withFileTypes: true });\n const entries = await Promise.all(\n dirEntries\n .filter((entry) => {\n if (entry.isDirectory()) {\n return !SKIP_DIRS.has(entry.name);\n }\n\n if (entry.isFile()) {\n return !SKIP_FILES.has(entry.name);\n }\n\n return false;\n })\n .map(async (entry) => {\n const kind = entry.isDirectory() ? ('dir' as const) : ('file' as const);\n const result: { name: string; kind: 'dir' | 'file'; size?: number } = {\n name: entry.name,\n kind,\n };\n\n if (kind === 'file') {\n try {\n const stats = await stat(join(abs, entry.name));\n\n result.size = stats.size;\n } catch {\n // Ignore stat failures — file may have been deleted mid-scan.\n }\n }\n\n return result;\n }),\n );\n\n entries.sort((a, b) => {\n if (a.kind !== b.kind) {\n return a.kind === 'dir' ? -1 : 1;\n }\n\n return a.name.localeCompare(b.name);\n });\n\n const normalizedPath = abs === realPluginDir ? '' : abs.slice(realPluginDir.length + 1);\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ path: normalizedPath, entries }));\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n\n createServerLog(`source/tree failed (${relParam}): ${detail}`);\n\n res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Not found' }));\n }\n\n return;\n }\n\n if (url.startsWith('/api/source/file') && req.method === 'GET') {\n const query = new URL(url, 'http://localhost').searchParams;\n const relParam = query.get('path') ?? '';\n\n if (relParam === '') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Missing path' }));\n\n return;\n }\n\n const abs = await resolveSafePath(realPluginDir, relParam);\n\n if (abs === null) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Invalid path' }));\n\n return;\n }\n\n if (isInsideSkippedDir(realPluginDir, abs)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Path is excluded' }));\n\n return;\n }\n\n try {\n const stats = await stat(abs);\n\n if (!stats.isFile()) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Not a file' }));\n\n return;\n }\n\n if (stats.size > SOURCE_FILE_MAX_BYTES) {\n res.writeHead(413, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'File too large', size: stats.size }));\n\n return;\n }\n\n const ext = extname(abs).toLowerCase();\n const explicitMime = MIME_TYPES[ext];\n const isKnownText = TEXT_EXTENSIONS.has(ext);\n const contentType =\n explicitMime ??\n (isKnownText ? 'text/plain; charset=utf-8' : 'application/octet-stream');\n\n res.writeHead(200, {\n 'Content-Type': contentType,\n 'Content-Length': String(stats.size),\n });\n createReadStream(abs).pipe(res);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n\n createServerLog(`source/file failed (${relParam}): ${detail}`);\n\n res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Not found' }));\n }\n\n return;\n }\n\n const rawPath = url === '/' ? '/index.html' : url;\n const filePath = join(viewerPath, rawPath);\n const resolvedPath = (await fileExists(filePath))\n ? filePath\n : join(viewerPath, 'index.html');\n const ext = extname(resolvedPath);\n const mimeType = MIME_TYPES[ext] ?? 'application/octet-stream';\n\n res.writeHead(200, { 'Content-Type': mimeType });\n\n createReadStream(resolvedPath).pipe(res);\n } catch (err) {\n if (url.startsWith('/api/proxy')) {\n const upstreamPath = url.slice('/api/proxy'.length) || '/';\n const method = req.method ?? 'GET';\n\n if (err instanceof ProxyResponseTooLargeError) {\n createProxyLog({\n kind: 'info',\n message: `${method} ${upstreamPath} → 502 (response exceeded ${String(err.limit)} bytes)`,\n });\n } else {\n createProxyLog({\n kind: 'request',\n method,\n status: 502,\n fromCache: false,\n url: upstreamPath,\n });\n }\n } else {\n createProxyLog({\n kind: 'info',\n message: `Error handling ${url}: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n if (!res.headersSent) {\n res.writeHead(502);\n\n res.end('Bad Gateway');\n }\n }\n })();\n };\n}\n","export interface CachedResponse {\n status: number;\n headers: Record<string, string>;\n body: Buffer;\n}\n\n// Headers we refuse to pass through from upstream to the browser.\n// - set-cookie: would set Kizen cookies on the localhost origin.\n// - access-control-*: would let upstream relax CORS on our responses.\n// - strict-transport-security: shouldn't govern localhost.\n// - content-security-policy(-report-only), x-frame-options: upstream policy\n// doesn't apply to the local viewer and can conflict with our own CSP.\n// content-encoding / content-length are dropped because fetch auto-decompresses\n// the body; the original sizes/encoding no longer match what we forward.\nconst STRIPPED_RESPONSE_HEADERS = new Set([\n 'set-cookie',\n 'strict-transport-security',\n 'content-security-policy',\n 'content-security-policy-report-only',\n 'x-frame-options',\n 'content-encoding',\n 'content-length',\n]);\n\nexport function sanitizeUpstreamHeaders(headers: Record<string, string>): Record<string, string> {\n const filtered: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(headers)) {\n const lower = key.toLowerCase();\n\n if (STRIPPED_RESPONSE_HEADERS.has(lower) || lower.startsWith('access-control-')) {\n continue;\n }\n\n filtered[key] = value;\n }\n\n return filtered;\n}\n\nexport const MAX_PROXY_BYTES = 10 * 1024 * 1024;\n\n// 60s TTL keeps dev-session queries de-duplicated without masking server-side\n// changes for long. 200 entries caps worst-case memory at ~2GB if every entry\n// were maxed out, which it won't be — typical Kizen JSON responses are <100KB.\nconst CACHE_TTL_MS = 60_000;\nconst CACHE_MAX_ENTRIES = 200;\n\nexport class ProxyResponseTooLargeError extends Error {\n readonly bytesRead: number;\n readonly limit: number;\n\n constructor(bytesRead: number, limit: number) {\n super(`Upstream response exceeded ${String(limit)} bytes (read ${String(bytesRead)}).`);\n this.name = 'ProxyResponseTooLargeError';\n this.bytesRead = bytesRead;\n this.limit = limit;\n }\n}\n\nexport async function readBodyWithLimit(response: Response, limit: number): Promise<Buffer> {\n const body = response.body;\n\n if (body === null) {\n return Buffer.alloc(0);\n }\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n\n for await (const chunk of body as AsyncIterable<Uint8Array>) {\n total += chunk.length;\n\n if (total > limit) {\n throw new ProxyResponseTooLargeError(total, limit);\n }\n\n chunks.push(chunk);\n }\n\n return Buffer.concat(chunks);\n}\n\nexport interface ProxyCache {\n get(\n key: string,\n fetcher: () => Promise<Response>,\n ): Promise<{ response: CachedResponse; fromCache: boolean }>;\n clear(): void;\n}\n\nexport interface ProxyCacheOptions {\n onChange?: (size: number) => void;\n // When false, the cache becomes a pass-through: every request hits upstream\n // and nothing is stored. Used by `appbuilder dev --no-cache`.\n enabled?: boolean;\n}\n\ninterface CacheEntry {\n insertedAt: number;\n promise: Promise<CachedResponse>;\n}\n\nasync function toCachedResponse(response: Response): Promise<CachedResponse> {\n const headers = sanitizeUpstreamHeaders(Object.fromEntries(response.headers));\n const body = await readBodyWithLimit(response, MAX_PROXY_BYTES);\n\n return { status: response.status, headers, body };\n}\n\nexport function createProxyCache(options: ProxyCacheOptions = {}): ProxyCache {\n const { onChange, enabled = true } = options;\n\n if (!enabled) {\n return {\n async get(_key, fetcher) {\n const response = await toCachedResponse(await fetcher());\n\n return { response, fromCache: false };\n },\n clear() {\n // Nothing is stored, so there is nothing to clear.\n },\n };\n }\n\n const cache = new Map<string, CacheEntry>();\n const emitChange = (): void => {\n onChange?.(cache.size);\n };\n\n const evict = (key: string): void => {\n if (cache.delete(key)) {\n emitChange();\n }\n };\n\n return {\n get(\n key: string,\n fetcher: () => Promise<Response>,\n ): Promise<{ response: CachedResponse; fromCache: boolean }> {\n const existing = cache.get(key);\n\n if (existing !== undefined) {\n if (Date.now() - existing.insertedAt < CACHE_TTL_MS) {\n return existing.promise.then((response) => ({ response, fromCache: true }));\n }\n\n // Stale — drop and refetch.\n evict(key);\n }\n\n // Map iteration order is insertion order, so the first key is the oldest.\n // Evicting before insert keeps size strictly ≤ CACHE_MAX_ENTRIES.\n if (cache.size >= CACHE_MAX_ENTRIES) {\n const oldest = cache.keys().next().value;\n\n if (oldest !== undefined) {\n evict(oldest);\n }\n }\n\n const pending = fetcher()\n .then(toCachedResponse)\n .catch((error: unknown) => {\n evict(key);\n throw error;\n });\n\n cache.set(key, { insertedAt: Date.now(), promise: pending });\n\n emitChange();\n\n return pending.then((response) => {\n // Only 2xx responses stay cached; everything else is served once and\n // evicted so the next request re-fetches.\n if (response.status < 200 || response.status >= 300) {\n evict(key);\n }\n\n return { response, fromCache: false };\n });\n },\n\n clear(): void {\n cache.clear();\n\n emitChange();\n },\n };\n}\n","/** Maximum number of log entries retained per log channel. */\nexport const LOG_LIMIT = 50;\n\n/** Number of log lines visible in each TUI log panel. */\nexport const LOG_DISPLAY = 8;\n\n/** Debounce delay for file-watcher triggered rebuilds (ms). */\nexport const FILE_WATCH_DEBOUNCE_MS = 150;\n\nexport const MIME_TYPES: Readonly<Record<string, string>> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.json': 'application/json; charset=utf-8',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.map': 'application/json',\n};\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport interface AppBuilderConfig {\n credentialMode?: 'global' | 'local';\n activeCredentialProfile?: string;\n lastPath?: string;\n // Which encryption API the Secrets page fetches public keys from. Defaults to\n // 'prod' when unset; 'dev' is an explicit per-project override (KZN-16467).\n // (A legacy 'auto' value may exist in older config files; it is read as the\n // 'prod' default — see GET /api/encryption-target.)\n encryptionTarget?: 'dev' | 'prod';\n}\n\nexport async function loadConfig(outputDir: string): Promise<AppBuilderConfig> {\n try {\n const content = await readFile(join(outputDir, 'config.json'), 'utf-8');\n\n return JSON.parse(content) as AppBuilderConfig;\n } catch {\n return {};\n }\n}\n\nexport async function saveConfig(outputDir: string, config: AppBuilderConfig): Promise<void> {\n await mkdir(outputDir, { recursive: true });\n\n await writeFile(join(outputDir, 'config.json'), JSON.stringify(config, null, 2), 'utf-8');\n}\n","/**\n * Shared helper for resolving the encryption API (plugin-wizard) base URL.\n * Imported by both the dev server request handler and the `encrypt` CLI command\n * so the host defaults and env-var names live in one place. KZN-16467.\n */\n\nexport const ENCRYPTION_API_DEFAULTS = {\n prod: 'https://plugin-wizard.kizen.com', // deployed prod encryption service\n dev: 'https://plugin-wizard.kizen.dev', // deployed dev encryption service\n localDev: 'http://localhost:9823', // local plugin-wizard (APPBUILDER_LOCAL_DEV)\n} as const;\n\n/**\n * Resolves the base URL for the encryption API (plugin-wizard) public-key\n * endpoint. Precedence for the `dev` target:\n * 1. `PLUGIN_WIZARD_URL` — forces a single host for ALL targets.\n * 2. `PLUGIN_WIZARD_URL_DEV` — explicit dev URL.\n * 3. `APPBUILDER_LOCAL_DEV` — any non-empty value → localhost:9823.\n * 4. Hardcoded default — deployed dev service.\n * Prod follows the same pattern minus step 3.\n */\nexport function resolveWizardBase(target: 'dev' | 'prod'): string {\n const forced = process.env.PLUGIN_WIZARD_URL;\n\n if (forced !== undefined && forced !== '') {\n return forced;\n }\n\n if (target === 'prod') {\n // `||` (not `??`) so an empty-string env var falls back to the default,\n // matching the PLUGIN_WIZARD_URL / *_DEV branches above and below.\n return process.env.PLUGIN_WIZARD_URL_PROD || ENCRYPTION_API_DEFAULTS.prod;\n }\n\n if (process.env.PLUGIN_WIZARD_URL_DEV !== undefined && process.env.PLUGIN_WIZARD_URL_DEV !== '') {\n return process.env.PLUGIN_WIZARD_URL_DEV;\n }\n\n if (process.env.APPBUILDER_LOCAL_DEV !== undefined && process.env.APPBUILDER_LOCAL_DEV !== '') {\n return ENCRYPTION_API_DEFAULTS.localDev;\n }\n\n return ENCRYPTION_API_DEFAULTS.dev;\n}\n","import { spawn } from 'node:child_process';\nimport { writeFile, rm, mkdtemp, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport requirementsTxt from './python-requirements.txt';\nimport { parseRequirementsFile, resolvePythonBinary } from '../lib/pythonRuntime.js';\nimport {\n type ExecutionResult,\n type HttpRequests,\n type StepInputValue,\n} from '../../shared/lib/execution.js';\nexport type {\n ExecutionResult,\n HttpRequests,\n HttpRequestEntry,\n} from '../../shared/lib/execution.js';\n\nconst WRAPPER_SCRIPT = `\nimport sys, json, os, traceback\n\n# --- Inputs proxy (attribute access) ---\nclass _InputsProxy:\n def __init__(self, data):\n object.__setattr__(self, '_data', data)\n\n def __getattr__(self, name):\n if name.startswith('_'):\n raise AttributeError(name)\n return self._data.get(name)\n\n def __repr__(self):\n return repr(self._data)\n\n def __str__(self):\n return str(self._data)\n\n def __bool__(self):\n return bool(self._data)\n\ninputs = _InputsProxy(json.loads(os.environ.get('__KIZEN_INPUTS__', '{}')))\n\n# --- Secrets ---\nsecrets = json.loads(os.environ.get('__KIZEN_SECRETS__', '{}'))\n\n# --- Outputs proxy ---\nclass _OutputsProxy:\n def __init__(self):\n object.__setattr__(self, '_values', {})\n object.__setattr__(self, '_logs', [])\n\n def __setattr__(self, name, value):\n if name.startswith('_'):\n object.__setattr__(self, name, value)\n else:\n self._values[name] = value\n\n def __getattr__(self, name):\n if name.startswith('_'):\n raise AttributeError(name)\n return self._values.get(name)\n\n def log(self, message):\n self._logs.append(str(message))\n\noutputs = _OutputsProxy()\n\n# --- HTTP request capture (requests library only) ---\n_kizen_http_requests = []\n\ndef _kizen_install_http_capture():\n try:\n import requests\n except Exception:\n return\n import time, datetime\n\n _original_send = requests.Session.send\n\n def _kizen_send(self, request, **kwargs):\n submitted_at = datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d %H:%M:%S')\n start = time.time()\n error_type = None\n response = None\n try:\n response = _original_send(self, request, **kwargs)\n return response\n except Exception as exc:\n error_type = type(exc).__name__\n raise\n finally:\n body = request.body\n if isinstance(body, bytes):\n try:\n body = body.decode('utf-8')\n except Exception:\n body = '<binary>'\n elif body is None:\n body = ''\n\n status = 0\n resp_headers = {}\n resp_body = ''\n if response is not None:\n status = response.status_code\n resp_headers = dict(response.headers)\n if kwargs.get('stream'):\n resp_body = '<streamed>'\n else:\n try:\n resp_body = response.text\n except Exception:\n resp_body = '<unreadable>'\n\n _kizen_http_requests.append({\n 'method': request.method or '',\n 'url': request.url or '',\n 'headers': dict(request.headers or {}),\n 'body': body,\n 'requestSubmittedAt': submitted_at,\n 'session': True,\n 'responseStatusCode': status,\n 'responseHeaders': resp_headers,\n 'responseBody': resp_body,\n 'requestErrorType': error_type,\n 'duration': time.time() - start,\n })\n\n requests.Session.send = _kizen_send\n\n_kizen_install_http_capture()\n\ndef _kizen_http_summary():\n if not _kizen_http_requests:\n return None\n return {\n 'count': len(_kizen_http_requests),\n 'notLogged': 0,\n 'requests': _kizen_http_requests,\n }\n\n# --- Execute user script ---\ntry:\n exec(open(os.environ['__KIZEN_SCRIPT_PATH__'], encoding='utf-8').read())\n result = {\n 'success': True,\n 'outputValues': outputs._values,\n 'logs': outputs._logs,\n 'error': None,\n 'httpRequests': _kizen_http_summary(),\n }\nexcept Exception:\n # Build a clean traceback that hides the wrapper internals.\n # Keep only frames from the user script (shown as File \"<string>\")\n # and re-label them with \"script.py\" for clarity.\n exc_type, exc_value, exc_tb = sys.exc_info()\n entries = traceback.extract_tb(exc_tb)\n user_entries = [e for e in entries if e.filename != __file__]\n for e in user_entries:\n if e.filename == '<string>':\n e.filename = 'script.py'\n lines = ['Traceback (most recent call last):\\\\n']\n lines += traceback.format_list(user_entries)\n lines += traceback.format_exception_only(exc_type, exc_value)\n result = {\n 'success': False,\n 'outputValues': outputs._values,\n 'logs': outputs._logs,\n 'error': ''.join(lines),\n 'httpRequests': _kizen_http_summary(),\n }\n\n# Write results between markers so we can extract them reliably\n# even if the user script wrote to stdout\nsys.stdout.write('\\\\n__KIZEN_RESULT_START__\\\\n')\nsys.stdout.write(json.dumps(result, ensure_ascii=False))\nsys.stdout.write('\\\\n__KIZEN_RESULT_END__\\\\n')\nsys.stdout.flush()\n`.trim();\n\nconst DEFAULT_TIMEOUT = 30_000;\n\nexport type VenvInstallEvent =\n | { kind: 'start' }\n | { kind: 'log'; line: string; stream: 'stdout' | 'stderr' }\n | { kind: 'complete' }\n | { kind: 'error'; message: string };\n\nexport type VenvInstallListener = (event: VenvInstallEvent) => void;\n\nexport interface ExecuteStepParams {\n script: string;\n scriptRuntime: string;\n inputs: Record<string, StepInputValue>;\n secrets: Record<string, string>;\n timeout?: number;\n onInstallProgress?: VenvInstallListener;\n}\n\nconst VENV_DIR = join(process.cwd(), '.kizenapp', 'venv');\n\n// The production Kizen code-runner service only ships python-3-12 and\n// python-3-13 runtime images. Reject any other runtime locally so a bad or\n// unsupported \"runtime\" in a step's config.json fails fast\nconst SUPPORTED_RUNTIMES = ['python-3-12', 'python-3-13'] as const;\n\nfunction isSupportedRuntime(runtime: string): boolean {\n return (SUPPORTED_RUNTIMES as readonly string[]).includes(runtime);\n}\n\n// ./python-requirements.txt is the single source of truth for packages.\n// Keep it in sync with the Python dependency set installed by the production\n// Kizen code-runner service, so local runs match deployed ones.\nconst VENV_PACKAGES = parseRequirementsFile(requirementsTxt);\n\nif (VENV_PACKAGES.length === 0) {\n throw new Error('python-requirements.txt bundled no packages — check the build output');\n}\n\nlet venvReady: Promise<string> | null = null;\n\n// The bundled requirements (psycopg 3.3 in particular) require Python >= 3.10,\n// matching the remote code-runner which only ships 3.12 / 3.13 images. A venv\n// built on an older interpreter fails `pip install` with a cryptic\n// \"No matching distribution found for psycopg[binary]<4.0,>=3.3\".\nconst MIN_PYTHON: readonly [number, number] = [3, 10];\n\nfunction meetsMinimum([major, minor]: [number, number]): boolean {\n return major > MIN_PYTHON[0] || (major === MIN_PYTHON[0] && minor >= MIN_PYTHON[1]);\n}\n\nfunction formatVersion(version: readonly [number, number]): string {\n return `${String(version[0])}.${String(version[1])}`;\n}\n\n// Probe an interpreter for its (major, minor) version. Resolves null if the\n// binary is missing or can't run, so callers can try the next candidate.\nfunction probePython(bin: string): Promise<[number, number] | null> {\n return new Promise((resolve) => {\n const proc = spawn(bin, ['-c', \"import sys; print('%d.%d' % sys.version_info[:2])\"], {\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n\n let out = '';\n\n proc.stdout.on('data', (chunk: Buffer) => {\n out += chunk.toString('utf-8');\n });\n proc.on('error', () => {\n resolve(null);\n });\n proc.on('close', (code) => {\n const match = /(\\d+)\\.(\\d+)/.exec(out);\n\n if (code !== 0 || !match) {\n resolve(null);\n\n return;\n }\n\n resolve([Number(match[1]), Number(match[2])]);\n });\n });\n}\n\n// Pick a system interpreter new enough to install the bundled requirements.\n// Prefer the exact version the runtime asked for, then fall back to python3.\n// Throws a clear, actionable error when nothing usable is found.\nasync function findSystemPython(runtime: string): Promise<string> {\n const preferred = resolvePythonBinary(runtime);\n const candidates = preferred === 'python3' ? ['python3'] : [preferred, 'python3'];\n const tried: string[] = [];\n\n for (const bin of candidates) {\n const version = await probePython(bin);\n\n if (!version) {\n tried.push(`${bin}: not found`);\n\n continue;\n }\n\n if (meetsMinimum(version)) {\n return bin;\n }\n\n tried.push(`${bin}: ${formatVersion(version)} (too old)`);\n }\n\n throw new Error(\n `No Python >= ${formatVersion(MIN_PYTHON)} found for runtime \"${runtime}\". ` +\n `The local runner needs Python ${formatVersion(MIN_PYTHON)}+ to install the bundled ` +\n `packages (e.g. psycopg 3.3), matching the remote code-runner (3.12 / 3.13). ` +\n `Tried ${tried.join(', ')}. Install Python 3.12 or 3.13 and retry.`,\n );\n}\n\nfunction runCommand(\n bin: string,\n args: string[],\n onLine?: (line: string, stream: 'stdout' | 'stderr') => void,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const proc = spawn(bin, args, { stdio: ['ignore', 'pipe', 'pipe'] });\n\n const pipeLines = (source: NodeJS.ReadableStream, stream: 'stdout' | 'stderr'): string[] => {\n const captured: string[] = [];\n let buffer = '';\n\n source.on('data', (chunk: Buffer) => {\n buffer += chunk.toString('utf-8');\n\n let idx = buffer.indexOf('\\n');\n\n while (idx >= 0) {\n const line = buffer.slice(0, idx).replace(/\\r$/, '');\n\n buffer = buffer.slice(idx + 1);\n\n captured.push(line);\n onLine?.(line, stream);\n idx = buffer.indexOf('\\n');\n }\n });\n\n source.on('end', () => {\n if (buffer.length > 0) {\n const line = buffer.replace(/\\r$/, '');\n\n captured.push(line);\n onLine?.(line, stream);\n }\n });\n\n return captured;\n };\n\n const stderrCaptured = pipeLines(proc.stderr, 'stderr');\n\n pipeLines(proc.stdout, 'stdout');\n\n proc.on('error', reject);\n proc.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n const tail = stderrCaptured.slice(-10).join('\\n').trim();\n const detail = tail.length > 0 ? `: ${tail}` : '';\n\n reject(new Error(`${bin} exited with code ${String(code)}${detail}`));\n }\n });\n });\n}\n\n// Progress listeners for the in-flight venv build, so every caller awaiting the\n// same build receives its install output. Non-null only while a build is live,\n// so a cached-return call doesn't leak a listener that never fires.\nlet venvInstallListeners: Set<VenvInstallListener> | null = null;\n\nfunction ensureVenv(runtime: string, listener?: VenvInstallListener): Promise<string> {\n if (venvReady) {\n // Build already running or done. Attach to its progress if it's still live.\n if (listener) {\n venvInstallListeners?.add(listener);\n }\n\n return venvReady;\n }\n\n const listeners = new Set<VenvInstallListener>();\n\n if (listener) {\n listeners.add(listener);\n }\n\n venvInstallListeners = listeners;\n\n const emit = (event: VenvInstallEvent): void => {\n for (const l of listeners) {\n l(event);\n }\n };\n\n const venvPython = join(VENV_DIR, 'bin', 'python');\n\n venvReady = (async () => {\n try {\n // Reuse an existing venv only when its interpreter is new enough for the\n // bundled requirements; otherwise rebuild it. A stale venv (e.g. Python\n // 3.9) would otherwise fail `pip install` every time with a cryptic\n // \"No matching distribution\" error for psycopg 3.3.\n let reusable = false;\n\n try {\n await access(venvPython);\n\n const existing = await probePython(venvPython);\n\n reusable = existing !== null && meetsMinimum(existing);\n } catch {\n reusable = false;\n }\n\n if (!reusable) {\n // Clear any stale/half-built venv before recreating it. Best-effort:\n // rm of a missing dir is a no-op with force.\n await rm(VENV_DIR, { recursive: true, force: true }).catch(() => {\n /* ignore */\n });\n\n const systemPython = await findSystemPython(runtime);\n\n await runCommand(systemPython, ['-m', 'venv', VENV_DIR]);\n }\n\n emit({ kind: 'start' });\n\n await runCommand(\n venvPython,\n ['-m', 'pip', 'install', '--disable-pip-version-check', ...VENV_PACKAGES],\n (line, stream) => {\n emit({ kind: 'log', line, stream });\n },\n );\n\n emit({ kind: 'complete' });\n\n return venvPython;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n\n emit({ kind: 'error', message });\n\n // Reset so the next call retries rather than returning the cached\n // rejection forever. Also nuke the venv dir: a half-built venv (a failed\n // `python -m venv` or an interpreter that's too old) would confuse the\n // reuse check on the next attempt. rm is best-effort — we rebuild either\n // way.\n venvReady = null;\n\n await rm(VENV_DIR, { recursive: true, force: true }).catch(() => {\n /* ignore */\n });\n\n throw err;\n } finally {\n venvInstallListeners = null;\n }\n })();\n\n return venvReady;\n}\n\nfunction parseResult(stdout: string): {\n userStdout: string;\n result: {\n success: boolean;\n outputValues: Record<string, unknown>;\n logs: string[];\n error: string | null;\n httpRequests: HttpRequests | null;\n } | null;\n} {\n const startMarker = '__KIZEN_RESULT_START__';\n const endMarker = '__KIZEN_RESULT_END__';\n const startIdx = stdout.indexOf(startMarker);\n const endIdx = stdout.indexOf(endMarker);\n\n if (startIdx === -1 || endIdx === -1) {\n return { userStdout: stdout, result: null };\n }\n\n const userStdout = stdout.slice(0, startIdx).trimEnd();\n const jsonStr = stdout.slice(startIdx + startMarker.length, endIdx).trim();\n\n try {\n const result = JSON.parse(jsonStr) as {\n success: boolean;\n outputValues: Record<string, unknown>;\n logs: string[];\n error: string | null;\n httpRequests: HttpRequests | null;\n };\n\n return { userStdout, result };\n } catch {\n return { userStdout: stdout, result: null };\n }\n}\n\nfunction failedExecutionResult(error: string): ExecutionResult {\n return {\n success: false,\n outputValues: {},\n logs: [],\n stdout: '',\n stderr: '',\n error,\n exitCode: 1,\n durationMs: 0,\n };\n}\n\nexport async function executePythonStep(params: ExecuteStepParams): Promise<ExecutionResult> {\n const timeout = params.timeout ?? DEFAULT_TIMEOUT;\n\n // Fail fast on a runtime the remote code-runner can't run, instead of\n // silently building a venv on whatever interpreter is handy.\n if (!isSupportedRuntime(params.scriptRuntime)) {\n return failedExecutionResult(\n `Unsupported runtime \"${params.scriptRuntime}\". Supported runtimes: ` +\n `${SUPPORTED_RUNTIMES.join(', ')}. Update the step's config.json \"runtime\" field ` +\n `(e.g. \"python 3.13\").`,\n );\n }\n\n const pythonBin = await ensureVenv(params.scriptRuntime, params.onInstallProgress);\n const start = Date.now();\n\n let tmpDir: string | undefined;\n\n try {\n tmpDir = await mkdtemp(join(tmpdir(), 'kizen-step-'));\n\n const wrapperPath = join(tmpDir, 'wrapper.py');\n const scriptPath = join(tmpDir, 'script.py');\n\n await Promise.all([\n writeFile(wrapperPath, WRAPPER_SCRIPT, 'utf-8'),\n writeFile(scriptPath, params.script, 'utf-8'),\n ]);\n\n const env: Record<string, string> = {\n ...(process.env as Record<string, string>),\n __KIZEN_INPUTS__: JSON.stringify(params.inputs),\n __KIZEN_SECRETS__: JSON.stringify(params.secrets),\n __KIZEN_SCRIPT_PATH__: scriptPath,\n };\n\n const { exitCode, stdout, stderr } = await new Promise<{\n exitCode: number;\n stdout: string;\n stderr: string;\n }>((resolve) => {\n const stdoutChunks: Buffer[] = [];\n const stderrChunks: Buffer[] = [];\n let settled = false;\n\n const proc = spawn(pythonBin, [wrapperPath], {\n env,\n cwd: tmpDir,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n const timer = setTimeout(() => {\n proc.kill('SIGKILL');\n }, timeout);\n\n proc.stdout.on('data', (chunk: Buffer) => {\n stdoutChunks.push(chunk);\n });\n\n proc.stderr.on('data', (chunk: Buffer) => {\n stderrChunks.push(chunk);\n });\n\n const finish = (code: number | null): void => {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timer);\n resolve({\n exitCode: code ?? 1,\n stdout: Buffer.concat(stdoutChunks).toString('utf-8'),\n stderr: Buffer.concat(stderrChunks).toString('utf-8'),\n });\n };\n\n proc.on('close', finish);\n proc.on('error', (err) => {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timer);\n resolve({\n exitCode: 1,\n stdout: '',\n stderr: err.message,\n });\n });\n });\n\n const durationMs = Date.now() - start;\n const { userStdout, result } = parseResult(stdout);\n\n if (result) {\n const base: ExecutionResult = {\n success: result.success,\n outputValues: result.outputValues,\n logs: result.logs,\n stdout: userStdout,\n stderr,\n exitCode,\n durationMs,\n };\n\n if (result.error !== null) {\n base.error = result.error;\n }\n\n if (result.httpRequests) {\n base.httpRequests = result.httpRequests;\n }\n\n return base;\n }\n\n // If we couldn't parse the result, the wrapper itself likely failed\n const base: ExecutionResult = {\n success: false,\n outputValues: {},\n logs: [],\n stdout: userStdout,\n stderr,\n exitCode,\n durationMs,\n };\n\n if (exitCode !== 0) {\n base.error = `Process exited with code ${String(exitCode)}`;\n }\n\n return base;\n } finally {\n if (tmpDir) {\n void rm(tmpDir, { recursive: true, force: true });\n }\n }\n}\n","awslambdaric\nbcrypt\nboto3\nfpdf2\nlxml\nmsgpack\nnumpy\noracledb\nparamiko\npsycopg[binary]>=3.3,<4.0\npyjwt[crypto]\npymysql[rsa,ed25519]\npypdf[full]\npython-dateutil\npytz\nrequests\nsqlalchemy>=2.0,<2.1\ntzdata\n","export function parseRequirementsFile(content: string): string[] {\n return content\n .split('\\n')\n .map((line) => line.trim().replace(/\\s+#.*$/, ''))\n .filter((line) => line.length > 0 && !line.startsWith('#'));\n}\n\nexport function resolvePythonBinary(runtime: string): string {\n const match = /^python-(\\d+)[.-](\\d+)$/.exec(runtime);\n const major = match?.[1];\n const minor = match?.[2];\n\n if (major !== undefined && minor !== undefined) {\n return `python${major}.${minor}`;\n }\n\n return 'python3';\n}\n","export interface HttpRequestEntry {\n method: string;\n url: string;\n headers: Record<string, string>;\n body: string;\n requestSubmittedAt: string;\n session: boolean;\n responseStatusCode: number;\n responseHeaders: Record<string, string>;\n responseBody: string;\n requestErrorType: string | null;\n duration: number;\n}\n\nexport interface HttpRequests {\n count: number;\n notLogged: number;\n requests: HttpRequestEntry[];\n}\n\nexport interface ExecutionResult {\n success: boolean;\n outputValues: Record<string, unknown>;\n logs: string[];\n stdout: string;\n stderr: string;\n error?: string;\n exitCode: number;\n durationMs: number;\n httpRequests?: HttpRequests;\n}\n\nexport type StepInputValue = string | null;\n\nexport function toStepInputValue(raw: string | null | undefined): StepInputValue {\n return raw === undefined || raw === null || raw.trim() === '' ? null : raw;\n}\n\nexport function buildStepInputs(\n names: string[],\n rawValues: Record<string, string>,\n): Record<string, StepInputValue> {\n return Object.fromEntries(names.map((name) => [name, toStepInputValue(rawValues[name])]));\n}\n\nfunction coerceStepInputValue(value: unknown): StepInputValue {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'string') {\n return toStepInputValue(value);\n }\n\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {\n return String(value);\n }\n\n if (typeof value === 'function' || typeof value === 'symbol') {\n return null;\n }\n\n return JSON.stringify(value);\n}\n\nexport function normalizeStepInputs(\n inputs: Record<string, unknown> | undefined,\n): Record<string, StepInputValue> {\n if (!inputs) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(inputs).map(([name, value]) => [name, coerceStepInputValue(value)]),\n );\n}\n","export const TEXT_EXTENSIONS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.json',\n '.md',\n '.mdx',\n '.yml',\n '.yaml',\n '.toml',\n '.css',\n '.scss',\n '.html',\n '.htm',\n '.xml',\n '.svg',\n '.txt',\n '.sh',\n '.py',\n '.env',\n '.gitignore',\n '.prettierrc',\n '.eslintrc',\n]);\n","export type ProxyLogEntry =\n | {\n kind: 'request';\n method: string;\n status: number;\n // For calls to Kizen's `/external-integrations/proxy` endpoint, the\n // third-party API's status is carried in the response body (`status_code`)\n // rather than the HTTP status. `status` is the proxy status; this is the\n // upstream one. Undefined for non-proxy calls.\n upstreamStatus?: number | undefined;\n fromCache: boolean;\n url: string;\n }\n | { kind: 'info'; message: string };\n\nexport function proxyLogEntryToString(entry: ProxyLogEntry): string {\n if (entry.kind === 'info') {\n return entry.message;\n }\n\n const cache = entry.fromCache ? ' [cache]' : '';\n const upstream =\n entry.upstreamStatus !== undefined ? ` (upstream ${String(entry.upstreamStatus)})` : '';\n\n return `${entry.method} ${entry.url} → ${String(entry.status)}${upstream}${cache}`;\n}\n","import { launch } from 'chrome-launcher';\nimport type { LaunchedChrome } from 'chrome-launcher';\nimport { createRequire } from 'node:module';\nimport { mkdirSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst CDP = createRequire(import.meta.url)('chrome-remote-interface') as (opts: {\n port: number;\n}) => Promise<CDPClient>;\n\ninterface CDPHeader {\n name: string;\n value: string;\n}\n\ninterface CDPFetchPausedEvent {\n requestId: string;\n request: { url: string };\n responseHeaders?: CDPHeader[];\n responseStatusCode?: number;\n}\n\ninterface CDPClient {\n Fetch: {\n enable: (opts: { patterns: { urlPattern: string; requestStage: string }[] }) => Promise<void>;\n getResponseBody: (opts: {\n requestId: string;\n }) => Promise<{ body: string; base64Encoded: boolean }>;\n fulfillRequest: (opts: {\n requestId: string;\n responseCode: number;\n responseHeaders: CDPHeader[];\n body?: string;\n base64Encoded?: boolean;\n }) => Promise<void>;\n continueRequest: (opts: { requestId: string }) => Promise<void>;\n };\n Network: {\n getAllCookies: () => Promise<{ cookies: CDPCookie[] }>;\n setCookie: (opts: CDPCookieSet) => Promise<void>;\n };\n Target: {\n setDiscoverTargets: (opts: { discover: boolean }) => Promise<void>;\n closeTarget: (opts: { targetId: string }) => Promise<void>;\n activateTarget: (opts: { targetId: string }) => Promise<void>;\n };\n Browser: {\n setDockTile: (opts: { image?: string; label?: string }) => Promise<void>;\n };\n send: (method: string, params?: object, sessionId?: string) => Promise<unknown>;\n on: (event: string, handler: (params: unknown, sessionId?: string) => void) => void;\n close: () => Promise<void>;\n}\n\ninterface CDPTargetCreatedEvent {\n targetInfo: {\n targetId: string;\n type: string;\n url: string;\n };\n}\n\ninterface CDPCookie {\n name: string;\n value: string;\n domain?: string;\n path?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: string;\n expirationDate?: number;\n}\n\ninterface CDPCookieSet {\n url: string;\n name: string;\n value: string;\n domain?: string;\n path?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: string;\n expires?: number;\n}\n\nconst CSP_HEADERS = new Set([\n 'content-security-policy',\n 'content-security-policy-report-only',\n 'x-frame-options',\n]);\n\nconst KIZEN_DOMAINS = ['kizen.dev', 'kizen.com'];\n\nfunction isKizenUrl(url: string): boolean {\n try {\n const { hostname } = new URL(url);\n\n return KIZEN_DOMAINS.some((d) => hostname === d || hostname.endsWith('.' + d));\n } catch {\n return false;\n }\n}\n\nasync function installDockIcon(client: CDPClient): Promise<void> {\n try {\n const iconPath = join(dirname(fileURLToPath(import.meta.url)), 'viewer', 'icon.png');\n const icon = await readFile(iconPath);\n\n await client.Browser.setDockTile({ image: icon.toString('base64') });\n } catch {\n // Non-critical: silently skip if icon is missing or platform doesn't support it\n }\n}\n\nexport interface ChromeViewerOptions {\n port: number;\n userDataDir: string;\n broadcast: (msg: object) => void;\n path?: string;\n debugLog?: (msg: string) => void;\n // Always-on channel for user-visible warnings (e.g. \"CDP unavailable,\n // running without interception\"). Unlike debugLog, not gated by --debug.\n onWarn?: (msg: string) => void;\n verbose?: boolean;\n}\n\nexport interface ChromeViewerHandle {\n kill: () => void;\n}\n\nexport async function launchChromeViewer(opts: ChromeViewerOptions): Promise<ChromeViewerHandle> {\n // chrome-launcher opens log files inside userDataDir before Chrome starts\n mkdirSync(opts.userDataDir, { recursive: true });\n\n const baseUrl = `http://localhost:${String(opts.port)}`;\n\n const chrome: LaunchedChrome = await launch({\n startingUrl: baseUrl,\n chromeFlags: [\n `--app=${baseUrl}`,\n '--no-first-run',\n '--no-default-browser-check',\n '--disable-extensions',\n '--disable-features=DeviceBoundSessions',\n ],\n userDataDir: opts.userDataDir,\n handleSIGINT: false,\n logLevel: 'silent',\n });\n\n const cdpPort = chrome.port;\n\n let client: CDPClient | null = null;\n let cookieTimer: ReturnType<typeof setInterval> | null = null;\n let mainTargetId: string | null = null;\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let reconnectAttempt = 0;\n let killed = false;\n\n const dbg = (msg: string): void => {\n opts.debugLog?.(msg);\n };\n\n const vb = (msg: string): void => {\n if (opts.verbose) {\n opts.debugLog?.(msg);\n }\n };\n\n const clearCookieTimer = (): void => {\n if (cookieTimer !== null) {\n clearInterval(cookieTimer);\n cookieTimer = null;\n }\n };\n\n const isNewTabUrl = (url: string): boolean =>\n url === 'chrome://new-tab-page/' || url === 'chrome://newtab/';\n\n const setupClient = async (c: CDPClient): Promise<void> => {\n // Fresh CDP session: reset per-connection state.\n clearCookieTimer();\n mainTargetId = null;\n\n await installDockIcon(c);\n\n // ── 1. Response interception: strip CSP + fix SameSite cookies ──────────────\n await c.Fetch.enable({\n patterns: KIZEN_DOMAINS.flatMap((d) => [\n { urlPattern: `*://${d}/*`, requestStage: 'Response' },\n { urlPattern: `*://*.${d}/*`, requestStage: 'Response' },\n ]),\n });\n\n c.on('Fetch.requestPaused', (rawParams: unknown) => {\n void (async () => {\n const params = rawParams as CDPFetchPausedEvent;\n const { requestId, request, responseHeaders, responseStatusCode } = params;\n const url = request.url;\n\n vb(`Fetch ${String(responseStatusCode ?? '?')} ${url}`);\n\n const filtered: CDPHeader[] = [];\n let rewroteSetCookie = false;\n\n for (const h of responseHeaders ?? []) {\n if (CSP_HEADERS.has(h.name.toLowerCase())) {\n continue;\n }\n\n if (h.name.toLowerCase() === 'set-cookie' && isKizenUrl(url)) {\n const patched = h.value\n .split('\\n')\n .map((cookie) => {\n if (!/SameSite=/i.test(cookie)) {\n return cookie + '; SameSite=None; Secure';\n }\n\n return cookie.replace(/SameSite=\\w+/i, 'SameSite=None');\n })\n .join('\\n');\n\n filtered.push({ name: h.name, value: patched });\n rewroteSetCookie = true;\n } else {\n filtered.push(h);\n }\n }\n\n if (rewroteSetCookie) {\n vb(` rewrote Set-Cookie SameSite on ${url}`);\n }\n\n try {\n const { body, base64Encoded } = await c.Fetch.getResponseBody({ requestId });\n\n await c.Fetch.fulfillRequest({\n requestId,\n responseCode: responseStatusCode ?? 200,\n responseHeaders: filtered,\n body,\n ...(base64Encoded && { base64Encoded: true }),\n });\n } catch (e) {\n vb(` fulfillRequest failed (${(e as Error).message}), falling through`);\n\n try {\n await c.Fetch.continueRequest({ requestId });\n } catch (e2) {\n vb(` continueRequest also failed (${(e2 as Error).message})`);\n }\n }\n })();\n });\n\n // ── 2. Periodic SameSite cookie patching ────────────────────────────────────\n cookieTimer = setInterval(() => {\n void (async () => {\n try {\n const { cookies } = await c.Network.getAllCookies();\n\n let patched = 0;\n\n for (const cookie of cookies) {\n if (!isKizenUrl(`https://${cookie.domain ?? ''}`)) {\n continue;\n }\n\n if (cookie.sameSite === 'None') {\n continue;\n }\n\n const raw = cookie.domain ?? '';\n const bare = raw.startsWith('.') ? raw.slice(1) : raw;\n\n await c.Network.setCookie({\n url: `https://${bare}`,\n name: cookie.name,\n value: cookie.value,\n domain: raw,\n path: cookie.path ?? '/',\n secure: true,\n ...(cookie.httpOnly !== undefined && { httpOnly: cookie.httpOnly }),\n ...(cookie.expirationDate !== undefined && {\n expires: cookie.expirationDate,\n }),\n sameSite: 'None',\n });\n\n patched++;\n }\n\n if (patched > 0) {\n vb(`cookie-patch cycle: updated ${String(patched)} cookie(s) to SameSite=None`);\n }\n } catch (e) {\n vb(`cookie-patch cycle failed: ${(e as Error).message}`);\n }\n })();\n }, 2000);\n\n // macOS dock clicks on --app= windows open a stray new-tab-page window\n // (Chromium excludes app windows from its \"is a browser window open?\" check).\n // activate the original app window, then close the intruder. setDiscoverTargets replays\n // existing targets so mainTargetId gets recaptured after a CDP reconnect.\n await c.Target.setDiscoverTargets({ discover: true });\n\n const handleTarget = (targetInfo: { targetId: string; type: string; url: string }): void => {\n if (targetInfo.type !== 'page') {\n return;\n }\n\n if (isNewTabUrl(targetInfo.url)) {\n dbg(`closed stray new-tab-page target ${targetInfo.targetId}`);\n\n if (mainTargetId !== null) {\n void c.Target.activateTarget({ targetId: mainTargetId }).catch(() => {\n /* ignore */\n });\n }\n\n void c.Target.closeTarget({ targetId: targetInfo.targetId }).catch(() => {\n /* ignore */\n });\n\n return;\n }\n\n if (mainTargetId === null) {\n mainTargetId = targetInfo.targetId;\n dbg(`captured main target ${targetInfo.targetId} (${targetInfo.url})`);\n }\n };\n\n c.on('Target.targetCreated', (rawParams: unknown) => {\n const { targetInfo } = rawParams as CDPTargetCreatedEvent;\n\n vb(`target +${targetInfo.type} ${targetInfo.targetId} ${targetInfo.url}`);\n handleTarget(targetInfo);\n });\n\n c.on('Target.targetInfoChanged', (rawParams: unknown) => {\n const { targetInfo } = rawParams as CDPTargetCreatedEvent;\n\n vb(`target ~${targetInfo.type} ${targetInfo.targetId} ${targetInfo.url}`);\n handleTarget(targetInfo);\n });\n\n // CDP's underlying WebSocket can drop (sleep/wake, transient failure) while\n // Chrome keeps running. Without reconnect, all interception silently stops.\n c.on('disconnect', () => {\n if (killed || client !== c) {\n return;\n }\n\n dbg('CDP disconnected');\n client = null;\n clearCookieTimer();\n scheduleReconnect();\n });\n };\n\n const scheduleReconnect = (): void => {\n if (killed || reconnectTimer !== null) {\n return;\n }\n\n const delay = Math.min(1000 * 2 ** reconnectAttempt, 10_000);\n const attemptNumber = reconnectAttempt + 1;\n\n reconnectAttempt++;\n\n dbg(`CDP reconnect scheduled in ${String(delay)}ms (attempt #${String(attemptNumber)})`);\n\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n\n void (async () => {\n let c: CDPClient;\n\n try {\n c = await CDP({ port: cdpPort });\n } catch {\n dbg(`CDP reconnect attempt #${String(attemptNumber)} failed`);\n scheduleReconnect();\n\n return;\n }\n\n if (killed) {\n try {\n await c.close();\n } catch {\n /* ignore */\n }\n\n return;\n }\n\n client = c;\n\n try {\n await setupClient(c);\n dbg(`CDP reconnected after ${String(attemptNumber)} attempt(s)`);\n reconnectAttempt = 0;\n } catch {\n if (client === c) {\n client = null;\n }\n\n try {\n await c.close();\n } catch {\n /* ignore */\n }\n\n dbg(`CDP reconnect attempt #${String(attemptNumber)} failed during setup`);\n scheduleReconnect();\n }\n })();\n }, delay);\n };\n\n // Initial CDP connection — Chrome may not be ready immediately. 30 × 300ms\n // (9s total) gives cold starts, slow disks, and Rosetta-translated Chromium\n // a reasonable window before we give up and run without interception.\n const MAX_CDP_ATTEMPTS = 30;\n const CDP_ATTEMPT_DELAY_MS = 300;\n\n for (let attempt = 0; attempt < MAX_CDP_ATTEMPTS; attempt++) {\n await new Promise<void>((r) => setTimeout(r, CDP_ATTEMPT_DELAY_MS));\n\n dbg(`CDP connect attempt ${String(attempt + 1)}/${String(MAX_CDP_ATTEMPTS)}`);\n\n try {\n const c = await CDP({ port: cdpPort });\n\n client = c;\n\n if (opts.path) {\n void c.send('Page.navigate', { url: `${baseUrl}${opts.path}` });\n }\n\n try {\n await setupClient(c);\n dbg('CDP connected');\n } catch {\n if (client === c) {\n client = null;\n }\n\n try {\n await c.close();\n } catch {\n /* ignore */\n }\n\n dbg('CDP setup failed after connect');\n }\n\n break;\n } catch {\n if (attempt === MAX_CDP_ATTEMPTS - 1) {\n // CDP never came up; window still opens, just no CSP rewrite or\n // SameSite cookie patching. Surface this via onWarn so it appears in\n // the TUI even when the user didn't pass --debug.\n const warning = `CDP unavailable after ${String(MAX_CDP_ATTEMPTS)} attempts — viewer running without interception (CSP/cookie rewrites disabled)`;\n\n dbg(warning);\n opts.onWarn?.(warning);\n\n return {\n kill: () => {\n chrome.kill();\n },\n };\n }\n }\n }\n\n if (!client) {\n return {\n kill: () => {\n chrome.kill();\n },\n };\n }\n\n const kill = (): void => {\n dbg('CDP kill requested — tearing down');\n killed = true;\n\n if (reconnectTimer !== null) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n\n clearCookieTimer();\n\n if (client !== null) {\n try {\n void client.close();\n } catch {\n /* ignore */\n }\n\n client = null;\n }\n\n chrome.kill();\n };\n\n return { kill };\n}\n","import { useCallback, useState } from 'react';\n\nexport function useLogHistory(limit: number): [string[], (message: string) => void] {\n const [history, setHistory] = useState<string[]>([]);\n\n const append = useCallback(\n (message: string): void => {\n setHistory((h) => [...h, `${new Date().toLocaleTimeString()}: ${message}`].slice(-limit));\n },\n [limit],\n );\n\n return [history, append];\n}\n","import type { FC } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport {\n DEFAULT_PROFILE_NAME,\n ENVIRONMENTS,\n GLOBAL_CREDENTIALS_PATH,\n listCredentialProfiles,\n loadCredentialProfile,\n loadGlobalCredentials,\n saveCredentialProfile,\n} from '../lib/credentials.js';\nimport type { CredentialProfile, Credentials } from '../lib/credentials.js';\nimport { AppHeader } from './AppHeader.js';\n\ntype Mode = 'global' | 'local';\n\ntype Phase =\n | { type: 'mode-select'; cursor: 0 | 1 }\n | { type: 'profile-loading' }\n | { type: 'profile-select'; profiles: CredentialProfile[]; cursor: number }\n | {\n type: 'name-entry';\n nameBuffer: string;\n nameError?: string;\n existingProfiles: CredentialProfile[];\n }\n | { type: 'loading' }\n | { type: 'creds-entry'; field: number; values: Partial<Credentials>; envCursor: number }\n | { type: 'saving' }\n | { type: 'done' };\n\nconst FIELDS = ['apiKey', 'userId', 'businessId'] as const;\nconst FIELD_LABELS: Record<string, string> = {\n apiKey: 'API Key',\n userId: 'User ID',\n businessId: 'Business ID',\n};\n\nexport type CredentialMode = 'global' | 'local';\n\nexport interface CredentialSetupResult {\n mode: CredentialMode;\n credentials: Credentials | null;\n profileName?: string;\n}\n\ninterface CredentialSetupUIProps {\n initialMode?: CredentialMode;\n showProfileManager?: boolean;\n onComplete: (result: CredentialSetupResult) => void;\n onCancel?: () => void;\n}\n\nconst Hint: FC<{ text: string }> = ({ text }) => <Text dimColor>{text}</Text>;\n\nexport const CredentialSetupUI: FC<CredentialSetupUIProps> = ({\n initialMode,\n showProfileManager,\n onComplete,\n onCancel,\n}) => {\n const [phase, setPhase] = useState<Phase>(\n initialMode === 'global' && !showProfileManager\n ? { type: 'loading' }\n : initialMode === 'global' && showProfileManager\n ? { type: 'profile-loading' }\n : { type: 'mode-select', cursor: 0 },\n );\n const [inputBuffer, setInputBuffer] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [activeProfileName, setActiveProfileName] = useState<string | undefined>(undefined);\n\n const handleModeChosen = useCallback(\n (mode: Mode) => {\n if (mode === 'local') {\n onComplete({ mode: 'local', credentials: null });\n\n return;\n }\n\n setPhase({ type: 'profile-loading' });\n },\n [onComplete],\n );\n\n const handleProfileChosen = useCallback(async (profile: CredentialProfile | null) => {\n if (profile === null) {\n // \"Add new profile\" selected\n setPhase({ type: 'profile-loading' });\n\n const profiles = await listCredentialProfiles();\n\n setPhase({ type: 'name-entry', nameBuffer: '', existingProfiles: profiles });\n\n return;\n }\n\n setActiveProfileName(profile.isDefault ? undefined : profile.name);\n\n setPhase({ type: 'loading' });\n\n const existing = profile.isDefault\n ? await loadGlobalCredentials()\n : await loadCredentialProfile(profile.name);\n const envCursor = existing ? Math.max(0, ENVIRONMENTS.indexOf(existing.environment)) : 0;\n\n setPhase({ type: 'creds-entry', field: 0, values: existing ?? {}, envCursor });\n }, []);\n\n const handleSave = useCallback(\n async (values: Partial<Credentials>, envCursor: number) => {\n const environment = ENVIRONMENTS[envCursor] ?? 'go';\n const credentials: Credentials = {\n apiKey: values.apiKey ?? '',\n userId: values.userId ?? '',\n businessId: values.businessId ?? '',\n environment,\n };\n\n setPhase({ type: 'saving' });\n\n try {\n const profileName = activeProfileName ?? DEFAULT_PROFILE_NAME;\n\n await saveCredentialProfile(profileName, credentials);\n\n onComplete({\n mode: 'global',\n credentials,\n ...(activeProfileName !== undefined && { profileName: activeProfileName }),\n });\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n\n setPhase({ type: 'creds-entry', field: 0, values, envCursor });\n }\n },\n [onComplete, activeProfileName],\n );\n\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n process.exit(0);\n }\n\n if (key.escape) {\n if (phase.type === 'creds-entry' || phase.type === 'name-entry') {\n // Go back to profile select if we came from there\n if (initialMode === 'global' && showProfileManager) {\n setPhase({ type: 'profile-loading' });\n\n void loadProfileList();\n\n return;\n }\n }\n\n onCancel?.();\n\n return;\n }\n\n if (phase.type === 'mode-select') {\n if (key.upArrow) {\n setPhase({ type: 'mode-select', cursor: 0 });\n } else if (key.downArrow) {\n setPhase({ type: 'mode-select', cursor: 1 });\n } else if (key.return) {\n const mode: Mode = phase.cursor === 0 ? 'global' : 'local';\n\n handleModeChosen(mode);\n }\n\n return;\n }\n\n if (phase.type === 'profile-select') {\n const { profiles, cursor } = phase;\n const addNewIdx = profiles.length;\n const totalItems = profiles.length + 1; // +1 for \"Add new\"\n\n if (key.upArrow) {\n setPhase({ ...phase, cursor: (cursor - 1 + totalItems) % totalItems });\n } else if (key.downArrow) {\n setPhase({ ...phase, cursor: (cursor + 1) % totalItems });\n } else if (key.return) {\n if (cursor === addNewIdx) {\n setPhase({ type: 'name-entry', nameBuffer: '', existingProfiles: profiles });\n } else {\n const selected = profiles[cursor] ?? profiles[0];\n\n if (selected) {\n void handleProfileChosen(selected);\n }\n }\n }\n\n return;\n }\n\n if (phase.type === 'name-entry') {\n const { nameBuffer, existingProfiles } = phase;\n\n if (key.backspace || key.delete) {\n setPhase({ type: 'name-entry', nameBuffer: nameBuffer.slice(0, -1), existingProfiles });\n } else if (key.return) {\n const trimmed = nameBuffer.trim();\n\n if (!trimmed) {\n setPhase({ ...phase, nameError: 'Name cannot be empty' });\n\n return;\n }\n\n if (trimmed === DEFAULT_PROFILE_NAME) {\n setPhase({ ...phase, nameError: `\"${DEFAULT_PROFILE_NAME}\" is reserved` });\n\n return;\n }\n\n if (existingProfiles.some((p) => p.name === trimmed)) {\n setPhase({ ...phase, nameError: `Profile \"${trimmed}\" already exists` });\n\n return;\n }\n\n // Valid name — proceed to empty creds-entry\n setActiveProfileName(trimmed);\n\n setPhase({ type: 'creds-entry', field: 0, values: {}, envCursor: 0 });\n\n setInputBuffer('');\n } else if (input && !key.ctrl && !key.meta) {\n setPhase({ type: 'name-entry', nameBuffer: nameBuffer + input, existingProfiles });\n }\n\n return;\n }\n\n if (phase.type === 'creds-entry') {\n const { field, values, envCursor } = phase;\n const isEnvField = field === FIELDS.length;\n\n if (isEnvField) {\n if (key.leftArrow) {\n setPhase({\n ...phase,\n envCursor: (envCursor - 1 + ENVIRONMENTS.length) % ENVIRONMENTS.length,\n });\n } else if (key.rightArrow) {\n setPhase({ ...phase, envCursor: (envCursor + 1) % ENVIRONMENTS.length });\n } else if (key.upArrow) {\n setPhase({ ...phase, field: field - 1 });\n\n setInputBuffer(values[FIELDS[field - 1] as keyof typeof values] ?? '');\n } else if (key.return) {\n void handleSave(values, envCursor);\n }\n\n return;\n }\n\n const fieldName = FIELDS[field];\n\n if (!fieldName) {\n return;\n }\n\n if (key.backspace || key.delete) {\n setInputBuffer((prev) => prev.slice(0, -1));\n } else if (key.upArrow && field > 0) {\n const updatedValues = { ...values, [fieldName]: inputBuffer };\n const prevField = field - 1;\n\n setPhase({ ...phase, field: prevField, values: updatedValues });\n\n setInputBuffer(updatedValues[FIELDS[prevField] as keyof typeof updatedValues] ?? '');\n } else if (key.return || key.tab || key.downArrow) {\n const updatedValues = { ...values, [fieldName]: inputBuffer };\n const nextField = field + 1;\n\n setPhase({ ...phase, field: nextField, values: updatedValues });\n\n if (nextField < FIELDS.length) {\n setInputBuffer(updatedValues[FIELDS[nextField] as keyof typeof updatedValues] ?? '');\n } else {\n setInputBuffer('');\n }\n } else if (input && !key.ctrl && !key.meta) {\n setInputBuffer((prev) => prev + input);\n }\n }\n });\n\n const loadProfileList = useCallback(async () => {\n const profiles = await listCredentialProfiles();\n\n setPhase({ type: 'profile-select', profiles, cursor: 0 });\n }, []);\n\n // Load profile list when entering profile-loading phase\n useEffect(() => {\n if (phase.type === 'profile-loading') {\n void loadProfileList();\n }\n }, [phase.type, loadProfileList]);\n\n // Handle initial mode without profile manager (existing behavior)\n useEffect(() => {\n if (initialMode === 'global' && !showProfileManager) {\n void (async () => {\n const existing = await loadGlobalCredentials();\n const envCursor = existing ? Math.max(0, ENVIRONMENTS.indexOf(existing.environment)) : 0;\n\n setPhase({ type: 'creds-entry', field: 0, values: existing ?? {}, envCursor });\n })();\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Reset input buffer when switching to creds-entry\n useEffect(() => {\n if (phase.type === 'creds-entry' && phase.field === 0) {\n setInputBuffer(phase.values.apiKey ?? '');\n }\n }, [phase.type]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (phase.type === 'loading' || phase.type === 'saving' || phase.type === 'profile-loading') {\n const label =\n phase.type === 'saving'\n ? 'Saving credentials…'\n : phase.type === 'profile-loading'\n ? 'Loading profiles…'\n : 'Loading credentials…';\n\n return (\n <Box paddingY={1} paddingX={2}>\n <Text dimColor>{label}</Text>\n </Box>\n );\n }\n\n if (phase.type === 'done') {\n return null;\n }\n\n if (phase.type === 'mode-select') {\n const options: { label: string; desc: string; mode: Mode }[] = [\n { label: 'Global', desc: `~/.kizenappbuilder/credentials.json`, mode: 'global' },\n { label: 'Local', desc: 'Enter credentials in the browser dev tools', mode: 'local' },\n ];\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Credential mode</Text>\n {options.map((opt, i) => {\n const selected = phase.cursor === i;\n\n return (\n <Box key={opt.mode} gap={2}>\n <Text {...(selected && { color: 'cyan' as const })}>{selected ? '❯' : ' '}</Text>\n <Text bold={selected} {...(selected && { color: 'cyan' as const })}>\n {opt.label}\n </Text>\n <Text dimColor>{opt.desc}</Text>\n </Box>\n );\n })}\n </Box>\n <Hint text=\"↑↓ to move · Enter to select · Ctrl+C to quit\" />\n </Box>\n );\n }\n\n if (phase.type === 'profile-select') {\n const { profiles, cursor } = phase;\n const addNewIdx = profiles.length;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Credential profiles</Text>\n {profiles.map((profile, i) => {\n const selected = cursor === i;\n\n return (\n <Box key={profile.name} gap={2}>\n <Text {...(selected && { color: 'cyan' as const })}>{selected ? '❯' : ' '}</Text>\n <Text bold={selected} {...(selected && { color: 'cyan' as const })}>\n {profile.isDefault ? 'Default' : profile.name}\n </Text>\n <Text dimColor>{profile.path}</Text>\n </Box>\n );\n })}\n <Box gap={2}>\n <Text {...(cursor === addNewIdx && { color: 'cyan' as const })}>\n {cursor === addNewIdx ? '❯' : ' '}\n </Text>\n <Text\n bold={cursor === addNewIdx}\n {...(cursor === addNewIdx && { color: 'cyan' as const })}\n >\n + Add new profile\n </Text>\n </Box>\n </Box>\n <Hint text=\"↑↓ to move · Enter to select · Esc to cancel\" />\n </Box>\n );\n }\n\n if (phase.type === 'name-entry') {\n const { nameBuffer, nameError } = phase;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>New credential profile</Text>\n </Box>\n {nameError && <Text color=\"red\">Error: {nameError}</Text>}\n <Box gap={2}>\n <Box width={12}>\n <Text bold color=\"cyan\">\n Profile name\n </Text>\n </Box>\n <Text color=\"cyan\">{'>'}</Text>\n <Text>{nameBuffer}</Text>\n <Text color=\"cyan\">{'█'}</Text>\n </Box>\n <Hint text=\"Type a name · Enter to confirm · Esc to go back\" />\n </Box>\n );\n }\n\n // creds-entry phase\n const { field: activeField, values, envCursor } = phase;\n const isEnvField = activeField === FIELDS.length;\n const profileLabel = activeProfileName ?? DEFAULT_PROFILE_NAME;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>\n {activeProfileName !== undefined ? `Profile: ${activeProfileName}` : 'Global credentials'}\n </Text>\n <Text dimColor>\n Saved to:{' '}\n {activeProfileName !== undefined\n ? `~/.kizenappbuilder/${activeProfileName}.json`\n : GLOBAL_CREDENTIALS_PATH}\n </Text>\n </Box>\n {error && <Text color=\"red\">Error: {error}</Text>}\n <Box flexDirection=\"column\" gap={0}>\n {FIELDS.map((name, i) => {\n const isActive = activeField === i;\n const displayValue = isActive ? inputBuffer : (values[name] ?? '');\n\n return (\n <Box key={name} gap={2}>\n <Box width={12}>\n <Text bold={isActive} {...(isActive && { color: 'cyan' as const })}>\n {FIELD_LABELS[name]}\n </Text>\n </Box>\n <Text {...(isActive && { color: 'cyan' as const })}>{'>'}</Text>\n <Text>{displayValue}</Text>\n {isActive && <Text color=\"cyan\">{'█'}</Text>}\n </Box>\n );\n })}\n <Box gap={2}>\n <Box width={12}>\n <Text bold={isEnvField} {...(isEnvField && { color: 'cyan' as const })}>\n Environment\n </Text>\n </Box>\n <Text {...(isEnvField && { color: 'cyan' as const })}>{'>'}</Text>\n <Box gap={1}>\n {ENVIRONMENTS.map((env, i) => {\n const isSelected = i === envCursor;\n\n if (isEnvField) {\n return (\n <Text key={env} bold={isSelected} {...(isSelected && { color: 'cyan' as const })}>\n {isSelected ? `[${env}]` : env}\n </Text>\n );\n }\n\n return (\n <Text key={env} dimColor={!isSelected} bold={isSelected}>\n {env}\n </Text>\n );\n })}\n </Box>\n </Box>\n </Box>\n {isEnvField ? (\n <Hint text=\"←→ to select · ↑↓ to move · Enter to save · Esc to cancel\" />\n ) : (\n <Hint text=\"↑↓ to move · Backspace to delete · Esc to cancel\" />\n )}\n <Text dimColor>Profile: {profileLabel}</Text>\n </Box>\n );\n};\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { EncryptUI } from '../ui/EncryptUI.js';\nimport { encryptSecret } from '../lib/encryptionClient.js';\nimport type { EncryptionContext } from '../lib/encryptionClient.js';\nimport { loadCredentialsFromFile, loadGlobalCredentials } from '../lib/credentials.js';\nimport {\n invalidStageMessage,\n isValidStage,\n readManifestDefaults,\n readStdin,\n resolveStage,\n writeEnvelopeFile,\n type ManifestDefaults,\n} from '../lib/encryptHelpers.js';\nimport { runHeadless } from '../lib/encryptHeadless.js';\n\ninterface EncryptOptions {\n remote?: boolean;\n credentials?: string;\n apiName?: string;\n value?: string;\n stage?: string;\n out?: string;\n}\n\nexport function encryptCommand(program: Command): void {\n program\n .command('encrypt')\n .description('Encrypt a secret for a plugin against its encryption keys')\n .option('--remote', \"encrypt via the plugin-wizard's remote API instead of on-machine\")\n .option('-c, --credentials <path>', 'path to a credentials JSON file')\n .option('-a, --api-name <name>', 'plugin api_name the secret belongs to')\n .option('-v, --value <value>', 'plaintext secret value to encrypt')\n .option('-s, --stage <stage>', 'which encryption API to use: dev or prod (default: prod)')\n .option('-o, --out <path>', 'also write the encrypted envelope to a file')\n .action(async (options: EncryptOptions) => {\n if (options.stage !== undefined && !isValidStage(options.stage)) {\n console.error(invalidStageMessage(options.stage));\n process.exit(1);\n }\n\n // Read kizen.json for the api_name default. Skip the file read entirely\n // when api_name is already supplied via a flag.\n const needsDefaults = options.apiName === undefined;\n const defaults: ManifestDefaults = needsDefaults ? await readManifestDefaults() : {};\n\n // Default to prod when --stage isn't given (almost every plugin ships to\n // production); pass --stage dev to override.\n const { stage, wasDefaulted: stageWasDefaulted } = resolveStage(options.stage);\n\n const ctx: EncryptionContext = {\n isRemote: options.remote === true,\n stage,\n };\n\n // ink's interactive UI needs a TTY for raw-mode input AND a TTY stdout to\n // render into. If either is redirected/piped (CI, `> out.json`, `| jq`),\n // fall back to the headless flow so stdout gets clean compact JSON instead\n // of ANSI frames.\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n try {\n await runHeadless(ctx, options, defaults, stageWasDefaulted, {\n loadCredentialsFromFile,\n loadGlobalCredentials,\n encryptSecret,\n readStdin,\n stdinIsTTY: () => process.stdin.isTTY,\n writeStdout: (text) => {\n process.stdout.write(text);\n },\n writeStderr: (text) => {\n process.stderr.write(text);\n },\n writeEnvelopeFile,\n setExitCode: (code) => {\n process.exitCode = code;\n },\n });\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n return;\n }\n\n // The UI copies to the clipboard itself; we capture the raw value here so\n // that after ink unmounts we can write --out (ink's rendered frame\n // soft-wraps the long base64, so we never read the envelope back off it).\n let envelopeValue: string | undefined;\n\n const { waitUntilExit } = render(\n createElement(EncryptUI, {\n ctx,\n stageDefaulted: stageWasDefaulted,\n onDone: (value: string) => {\n envelopeValue = value;\n },\n ...(options.credentials !== undefined && { credentialsPath: options.credentials }),\n ...(options.apiName !== undefined && { initialApiName: options.apiName }),\n ...(defaults.apiName !== undefined && { defaultApiName: defaults.apiName }),\n ...(options.value !== undefined && { initialValue: options.value }),\n }),\n { exitOnCtrlC: false },\n );\n\n await waitUntilExit();\n\n // envelopeValue is only set on success (onDone); stays undefined on Ctrl+C\n // or error, so nothing is written in those cases.\n if (envelopeValue !== undefined && options.out !== undefined) {\n try {\n await writeEnvelopeFile(options.out, envelopeValue);\n process.stderr.write(`Wrote encrypted envelope to ${options.out}\\n`);\n } catch (err) {\n console.error(\n `Error writing ${options.out}: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exitCode = 1;\n }\n }\n });\n}\n","import type { FC, ReactNode } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport {\n listCredentialProfiles,\n loadCredentialProfile,\n loadCredentialsFromFile,\n loadGlobalCredentials,\n} from '../lib/credentials.js';\nimport type { CredentialProfile, Credentials } from '../lib/credentials.js';\nimport { encryptSecret } from '../lib/encryptionClient.js';\nimport type { EncryptionContext } from '../lib/encryptionClient.js';\nimport { copyToClipboard } from '../lib/clipboard.js';\nimport { AppHeader } from './AppHeader.js';\nimport { Spinner } from './Spinner.js';\n\ninterface EncryptUIProps {\n ctx: EncryptionContext;\n /** True when --stage was not given and the stage fell back to the prod default. */\n stageDefaulted?: boolean;\n /** Skip the profile picker and load from this file instead. */\n credentialsPath?: string;\n /** Provided via --api-name; skips the api_name prompt. */\n initialApiName?: string;\n /** Prefill for the api_name prompt (from kizen.json) — does not skip it. */\n defaultApiName?: string;\n /** Provided via --value; skips the secret prompt. */\n initialValue?: string;\n /** Called once with the base64 envelope value when encryption succeeds, so the\n * caller can write --out / emit it after ink unmounts. */\n onDone?: (envelopeValue: string) => void;\n}\n\ntype Phase =\n | { type: 'loading' }\n | { type: 'profile-select'; profiles: CredentialProfile[]; cursor: number }\n | { type: 'api-name-entry'; buffer: string; error?: string }\n | { type: 'value-entry'; buffer: string; error?: string }\n | { type: 'fetching-key' }\n | { type: 'encrypting' }\n | { type: 'done'; envelope: string; copied: boolean }\n | { type: 'error'; message: string };\n\nconst Hint: FC<{ text: string }> = ({ text }) => <Text dimColor>{text}</Text>;\n\nexport const EncryptUI: FC<EncryptUIProps> = ({\n ctx,\n stageDefaulted,\n credentialsPath,\n initialApiName,\n defaultApiName,\n initialValue,\n onDone,\n}) => {\n const app = useApp();\n const [phase, setPhase] = useState<Phase>({ type: 'loading' });\n const [credentials, setCredentials] = useState<Credentials | null>(null);\n const [apiName, setApiName] = useState<string>(initialApiName ?? '');\n const [secret, setSecret] = useState<string>(initialValue ?? '');\n\n const fail = useCallback((err: unknown) => {\n process.exitCode = 1;\n // Exit is deferred to the terminal-phase effect below so the error frame is\n // actually painted before ink unmounts.\n setPhase({ type: 'error', message: err instanceof Error ? err.message : String(err) });\n }, []);\n\n const runEncryption = useCallback(\n async (creds: Credentials, name: string, value: string) => {\n try {\n const envelopeValue = await encryptSecret(ctx, creds, name, value, (p) => {\n setPhase(p === 'fetching-key' ? { type: 'fetching-key' } : { type: 'encrypting' });\n });\n const envelope = JSON.stringify({ encrypted: true, value: envelopeValue }, null, 2);\n\n onDone?.(envelopeValue);\n\n // Copy the envelope to the clipboard so the user can paste it without the\n // terminal's soft-wrapping becoming real line breaks in the copied text.\n // The envelope is ciphertext (never the plaintext secret), so this is\n // safe; the copy is best-effort and the envelope is shown either way.\n const copied = await copyToClipboard(envelope);\n\n // Exit is deferred to the terminal-phase effect below so the done frame\n // (with the envelope) is painted before ink unmounts.\n setPhase({ type: 'done', envelope, copied });\n } catch (err) {\n fail(err);\n }\n },\n [ctx, fail, onDone],\n );\n\n // Advance to the next required input, or kick off the encryption once we have\n // everything. Args are passed explicitly so we never read stale state.\n const proceed = useCallback(\n (creds: Credentials, name: string, value: string) => {\n if (name.trim() === '') {\n setPhase({ type: 'api-name-entry', buffer: defaultApiName ?? '' });\n\n return;\n }\n\n if (value === '') {\n setPhase({ type: 'value-entry', buffer: '' });\n\n return;\n }\n\n void runEncryption(creds, name.trim(), value);\n },\n [defaultApiName, runEncryption],\n );\n\n const handleProfileChosen = useCallback(\n async (profile: CredentialProfile) => {\n try {\n setPhase({ type: 'loading' });\n\n const creds = profile.isDefault\n ? await loadGlobalCredentials()\n : await loadCredentialProfile(profile.name);\n\n if (creds === null) {\n throw new Error(`Could not load credential profile: ${profile.name}`);\n }\n\n setCredentials(creds);\n proceed(creds, apiName, secret);\n } catch (err) {\n fail(err);\n }\n },\n [apiName, secret, proceed, fail],\n );\n\n // Resolve credentials on mount, then either show the picker or move on.\n useEffect(() => {\n void (async () => {\n try {\n if (credentialsPath !== undefined) {\n // loadCredentialsFromFile throws on a missing/invalid file; wrap it so\n // the error frame shows which path failed rather than a raw ENOENT.\n let creds: Credentials;\n\n try {\n creds = await loadCredentialsFromFile(credentialsPath);\n } catch (err) {\n throw new Error(\n `Could not load credentials from ${credentialsPath}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n\n setCredentials(creds);\n proceed(creds, apiName, secret);\n\n return;\n }\n\n const profiles = await listCredentialProfiles();\n\n if (profiles.length === 0) {\n throw new Error(\n 'No credential profiles found. Create ~/.kizenappbuilder/credentials.json first.',\n );\n }\n\n const [only] = profiles;\n\n if (profiles.length === 1 && only !== undefined) {\n const creds = only.isDefault\n ? await loadGlobalCredentials()\n : await loadCredentialProfile(only.name);\n\n if (creds === null) {\n throw new Error(`Could not load credential profile: ${only.name}`);\n }\n\n setCredentials(creds);\n proceed(creds, apiName, secret);\n\n return;\n }\n\n setPhase({ type: 'profile-select', profiles, cursor: 0 });\n } catch (err) {\n fail(err);\n }\n })();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Exit only once a terminal frame has been committed and written to the\n // terminal. Calling app.exit() in the same tick as the setPhase would unmount\n // ink before it paints the done/error frame, leaving the spinner as the last\n // thing on screen.\n useEffect(() => {\n if (phase.type === 'done' || phase.type === 'error') {\n app.exit();\n }\n }, [phase, app]);\n\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n process.exitCode = 130;\n app.exit();\n\n return;\n }\n\n if (phase.type === 'profile-select') {\n const { profiles, cursor } = phase;\n\n if (key.upArrow) {\n setPhase({ ...phase, cursor: (cursor - 1 + profiles.length) % profiles.length });\n } else if (key.downArrow) {\n setPhase({ ...phase, cursor: (cursor + 1) % profiles.length });\n } else if (key.return) {\n // cursor is kept in range by the modulo above, so this is always defined.\n const selected = profiles[cursor];\n\n if (selected !== undefined) {\n void handleProfileChosen(selected);\n }\n }\n\n return;\n }\n\n if (phase.type === 'api-name-entry') {\n const { buffer } = phase;\n\n if (key.backspace || key.delete) {\n setPhase({ type: 'api-name-entry', buffer: buffer.slice(0, -1) });\n } else if (key.return) {\n const name = buffer.trim();\n\n if (name === '') {\n setPhase({ type: 'api-name-entry', buffer, error: 'api_name cannot be empty' });\n\n return;\n }\n\n setApiName(name);\n\n if (credentials) {\n proceed(credentials, name, secret);\n } else {\n fail(new Error('Internal error: credentials were not loaded'));\n }\n } else if (input && !key.ctrl && !key.meta) {\n setPhase({ type: 'api-name-entry', buffer: buffer + input });\n }\n\n return;\n }\n\n if (phase.type === 'value-entry') {\n const { buffer } = phase;\n\n if (key.backspace || key.delete) {\n setPhase({ type: 'value-entry', buffer: buffer.slice(0, -1) });\n } else if (key.return) {\n if (buffer === '') {\n setPhase({ type: 'value-entry', buffer, error: 'secret cannot be empty' });\n\n return;\n }\n\n setSecret(buffer);\n\n if (credentials) {\n proceed(credentials, apiName, buffer);\n } else {\n fail(new Error('Internal error: credentials were not loaded'));\n }\n } else if (input && !key.ctrl && !key.meta) {\n setPhase({ type: 'value-entry', buffer: buffer + input });\n }\n\n return;\n }\n });\n\n const modeLabel = ctx.isRemote ? 'remote Kizen API' : 'on-machine';\n\n const stageLabel = stageDefaulted === true ? `${ctx.stage} (default)` : ctx.stage;\n\n const frame = (children: ReactNode): ReactNode => (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Text dimColor>\n Mode: {modeLabel} Stage: {stageLabel}\n </Text>\n {children}\n </Box>\n );\n\n if (phase.type === 'loading') {\n return frame(\n <Box gap={1}>\n <Spinner />\n <Text dimColor>Loading credentials…</Text>\n </Box>,\n );\n }\n\n if (phase.type === 'profile-select') {\n const { profiles, cursor } = phase;\n\n return frame(\n <>\n <Text bold>Credential profile</Text>\n <Box flexDirection=\"column\">\n {profiles.map((profile, i) => {\n const selected = cursor === i;\n\n return (\n <Box key={profile.name} gap={2}>\n <Text {...(selected && { color: 'cyan' as const })}>{selected ? '❯' : ' '}</Text>\n <Text bold={selected} {...(selected && { color: 'cyan' as const })}>\n {profile.isDefault ? 'Default' : profile.name}\n </Text>\n <Text dimColor>{profile.path}</Text>\n </Box>\n );\n })}\n </Box>\n <Hint text=\"↑↓ to move · Enter to select · Ctrl+C to quit\" />\n </>,\n );\n }\n\n if (phase.type === 'api-name-entry') {\n return frame(\n <>\n <Text bold>Plugin api_name</Text>\n {phase.error !== undefined && <Text color=\"red\">Error: {phase.error}</Text>}\n <Box gap={1}>\n <Text color=\"cyan\">{'>'}</Text>\n <Text>{phase.buffer}</Text>\n <Text color=\"cyan\">█</Text>\n </Box>\n <Hint text=\"Type the api_name · Enter to confirm · Ctrl+C to quit\" />\n </>,\n );\n }\n\n if (phase.type === 'value-entry') {\n return frame(\n <>\n <Text bold>Secret value</Text>\n {phase.error !== undefined && <Text color=\"red\">Error: {phase.error}</Text>}\n <Box gap={1}>\n <Text color=\"cyan\">{'>'}</Text>\n <Text>{'•'.repeat(phase.buffer.length)}</Text>\n <Text color=\"cyan\">█</Text>\n </Box>\n <Hint text=\"Input hidden · Enter to encrypt · Ctrl+C to quit\" />\n </>,\n );\n }\n\n if (phase.type === 'fetching-key') {\n return frame(\n <Box gap={1}>\n <Spinner />\n <Text>\n Fetching {ctx.stage} public key for <Text bold>{apiName}</Text>…\n </Text>\n </Box>,\n );\n }\n\n if (phase.type === 'encrypting') {\n return frame(\n <Box gap={1}>\n <Spinner />\n <Text>Encrypting…</Text>\n </Box>,\n );\n }\n\n if (phase.type === 'error') {\n return frame(\n <Box gap={1}>\n <Text color=\"red\">✗</Text>\n <Text color=\"red\">{phase.message}</Text>\n </Box>,\n );\n }\n\n // phase.type === 'done'\n return frame(\n <>\n <Box gap={1}>\n <Text color=\"green\">✓</Text>\n <Text bold>Encrypted secret ready</Text>\n </Box>\n {phase.copied ? (\n <Text color=\"green\">\n ✓ Copied to clipboard — paste it into the secret value in your kizen.json.\n </Text>\n ) : (\n <Text dimColor>\n {'Paste this into the secret value in your kizen.json (re-run with --out <path> to save ' +\n 'it to a file; selecting it here may capture line wraps):'}\n </Text>\n )}\n <Text>{phase.envelope}</Text>\n </>,\n );\n};\n","/**\n * Network + crypto helpers for the `encrypt` command, shared between the ink UI\n * and any non-interactive callers. Keeping these out of the React tree means the\n * dev/prod routing and envelope handling live in one testable place. KZN-16467.\n *\n * Both modes talk to the encryption API (plugin-wizard) DIRECTLY via\n * `resolveWizardBase(stage)` — the app-builder dev server is never involved, so\n * `appbuilder encrypt` works without `appbuilder dev` running:\n * - on-machine (default): fetch the public key, then encrypt in-process.\n * - remote (`--remote`): POST the plaintext to the wizard's /encrypt endpoint\n * and let it do the crypto with the keypair it already holds.\n */\nimport { encrypt, serializeEnvelope } from '@kizenapps/packager';\nimport type { Credentials } from './credentials.js';\nimport { resolveWizardBase } from './wizardUrl.js';\n\nexport interface EncryptionContext {\n /**\n * When true, the wizard's /encrypt endpoint performs the encryption; otherwise\n * we fetch the public key and encrypt on-machine. Either way the request goes\n * straight to the wizard host — never through the app-builder dev server.\n */\n isRemote: boolean;\n /** Which encryption API to target. */\n stage: 'dev' | 'prod';\n}\n\n/** Phases reported while encrypting, so a UI can show progress. */\nexport type EncryptPhase = 'fetching-key' | 'encrypting';\n\n/**\n * Node's fetch (undici) wraps socket failures in a generic `TypeError: fetch\n * failed`, stashing the real error (with its `code`) on `.cause`. Look in both\n * places so we can surface a friendlier \"not running\" message.\n */\nfunction isConnRefused(err: unknown): boolean {\n const e = err as { code?: string; cause?: { code?: string } };\n\n return e.code === 'ECONNREFUSED' || e.cause?.code === 'ECONNREFUSED';\n}\n\nfunction authHeaders(credentials: Credentials): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n 'x-api-key': credentials.apiKey,\n 'x-user-id': credentials.userId,\n 'x-business-id': credentials.businessId,\n 'x-auth-environment': credentials.environment,\n };\n}\n\n/** Wraps a fetch to the wizard so connection failures read clearly. */\nasync function wizardFetch(wizardBase: string, path: string, init: RequestInit): Promise<Response> {\n try {\n return await fetch(`${wizardBase}${path}`, init);\n } catch (err) {\n throw new Error(\n isConnRefused(err)\n ? `Plugin-wizard is not running at ${wizardBase}`\n : `Failed to reach plugin-wizard: ${(err as Error).message}`,\n );\n }\n}\n\n/**\n * Parses a wizard JSON response without throwing on a non-JSON body. Upstream\n * errors can arrive as HTML 502 pages, plain-text 429s, or an auth 401 raised\n * before the JSON handler runs — calling res.json() on those would throw an\n * opaque SyntaxError and hide the real status. Returning {} lets callers fall\n * back to a clear HTTP-status error.\n */\nasync function readJsonSafe(res: Response): Promise<Record<string, unknown>> {\n const text = await res.text();\n\n if (text === '') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(text) as unknown;\n\n return typeof parsed === 'object' && parsed !== null ? (parsed as Record<string, unknown>) : {};\n } catch {\n return {};\n }\n}\n\n/**\n * Fetches the public key for a plugin directly from the wizard host. Used by the\n * on-machine encryption path.\n */\nexport async function fetchPublicKey(\n ctx: EncryptionContext,\n credentials: Credentials,\n apiName: string,\n): Promise<string> {\n const wizardBase = resolveWizardBase(ctx.stage);\n const res = await wizardFetch(wizardBase, '/get-public-key', {\n method: 'POST',\n headers: authHeaders(credentials),\n body: JSON.stringify({ api_name: apiName }),\n });\n\n const data = await readJsonSafe(res);\n\n if (!res.ok || typeof data.public_key !== 'string') {\n const errMsg = typeof data.error === 'string' ? data.error : `HTTP ${String(res.status)}`;\n\n throw new Error(`Failed to fetch public key: ${errMsg}`);\n }\n\n return data.public_key;\n}\n\n/** Encrypts a value in-process via @kizenapps/packager and returns the\n * serialized envelope's base64 `value`. */\nfunction encryptLocally(publicKeyPem: string, value: string): string {\n const envelope = encrypt(value, publicKeyPem);\n const serialized = serializeEnvelope(envelope) as { encrypted?: boolean; value?: unknown };\n\n if (typeof serialized.value !== 'string') {\n throw new Error('Unexpected serialized envelope shape from @kizenapps/packager');\n }\n\n return serialized.value;\n}\n\n/**\n * Asks the wizard's /encrypt endpoint to encrypt the value with the keypair it\n * holds for `apiName`, returning the serialized envelope's base64 `value`. The\n * wizard fetches its own public key, so no separate get-public-key call is made.\n */\nasync function encryptRemote(\n ctx: EncryptionContext,\n credentials: Credentials,\n apiName: string,\n value: string,\n): Promise<string> {\n const wizardBase = resolveWizardBase(ctx.stage);\n const res = await wizardFetch(wizardBase, '/encrypt', {\n method: 'POST',\n headers: authHeaders(credentials),\n body: JSON.stringify({ api_name: apiName, value }),\n });\n\n const data = await readJsonSafe(res);\n\n if (!res.ok || data.encrypted !== true || typeof data.value !== 'string') {\n const errMsg = typeof data.error === 'string' ? data.error : `HTTP ${String(res.status)}`;\n\n throw new Error(`Encryption via plugin-wizard failed: ${errMsg}`);\n }\n\n return data.value;\n}\n\nexport async function encryptSecret(\n ctx: EncryptionContext,\n credentials: Credentials,\n apiName: string,\n value: string,\n onPhase?: (phase: EncryptPhase) => void,\n): Promise<string> {\n if (ctx.isRemote) {\n onPhase?.('encrypting');\n\n return encryptRemote(ctx, credentials, apiName, value);\n }\n\n onPhase?.('fetching-key');\n\n const publicKey = await fetchPublicKey(ctx, credentials, apiName);\n\n onPhase?.('encrypting');\n\n return encryptLocally(publicKey, value);\n}\n","/**\n * Best-effort system-clipboard copy with no third-party dependency. Used by the\n * `encrypt` command so the user can paste the envelope without the terminal's\n * soft-wrapping turning into real line breaks in the copied text.\n *\n * Only the encrypted envelope (ciphertext) is ever copied — never a plaintext\n * secret — so writing it to the clipboard is safe.\n */\nimport { spawn } from 'node:child_process';\nimport { platform } from 'node:process';\n\ninterface ClipboardCommand {\n cmd: string;\n args: string[];\n}\n\n/**\n * Clipboard tools to try, in order, for the current platform. Linux/other has\n * several candidates (Wayland first, then X11) since none is guaranteed.\n */\nfunction clipboardCommands(): ClipboardCommand[] {\n if (platform === 'darwin') {\n return [{ cmd: 'pbcopy', args: [] }];\n }\n\n if (platform === 'win32') {\n return [{ cmd: 'clip', args: [] }];\n }\n\n return [\n // wl-copy (Wayland) intentionally WITHOUT --foreground: the default forks a\n // background process that keeps serving the selection after this CLI exits.\n // --foreground would instead tie the selection to our process, so the 2s\n // kill-timeout below would terminate it and wipe the clipboard.\n { cmd: 'wl-copy', args: [] },\n { cmd: 'xclip', args: ['-selection', 'clipboard'] },\n { cmd: 'xsel', args: ['--clipboard', '--input'] },\n ];\n}\n\n/** How long to wait for a clipboard tool before giving up. Encryption has\n * already succeeded by the time we copy, so a tool that hangs (some Linux\n * xclip/xsel setups can) must never freeze the CLI — it just falls back. */\nconst CLIPBOARD_TIMEOUT_MS = 2000;\n\n/** Pipes `text` into one clipboard command. Resolves false (never rejects) on\n * any failure — a missing tool (ENOENT), a non-zero exit, a broken pipe, or a\n * tool that doesn't exit within the timeout. */\nfunction runClipboardCommand(text: string, { cmd, args }: ClipboardCommand): Promise<boolean> {\n return new Promise((resolve) => {\n let child;\n\n try {\n child = spawn(cmd, args, { stdio: ['pipe', 'ignore', 'ignore'] });\n } catch {\n // Spawn threw synchronously (e.g. invalid command) — nothing to clean up.\n resolve(false);\n\n return;\n }\n\n const spawned = child;\n let settled = false;\n\n function finish(ok: boolean): void {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timer);\n resolve(ok);\n }\n\n const timer = setTimeout(() => {\n spawned.kill();\n finish(false);\n }, CLIPBOARD_TIMEOUT_MS);\n\n // Don't let a pending clipboard timer keep the process alive on its own.\n timer.unref();\n\n spawned.on('error', () => {\n finish(false);\n });\n spawned.on('close', (code) => {\n finish(code === 0);\n });\n spawned.stdin.on('error', () => {\n finish(false);\n });\n\n try {\n spawned.stdin.end(text);\n } catch {\n finish(false);\n }\n });\n}\n\n/**\n * Copies `text` to the system clipboard, returning whether it succeeded. Tries\n * each platform candidate until one works; returns false if none is available.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n for (const command of clipboardCommands()) {\n if (await runClipboardCommand(text, command)) {\n return true;\n }\n }\n\n return false;\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport type EncryptStage = 'dev' | 'prod';\n\nexport function envelopeObject(value: string): { encrypted: true; value: string } {\n return { encrypted: true, value };\n}\n\nexport function compactEnvelope(value: string): string {\n return JSON.stringify(envelopeObject(value));\n}\n\nexport async function writeEnvelopeFile(path: string, value: string): Promise<void> {\n await writeFile(path, `${JSON.stringify(envelopeObject(value), null, 2)}\\n`, 'utf-8');\n}\n\nexport interface ManifestDefaults {\n apiName?: string;\n}\n\nexport const DEFAULT_STAGE: EncryptStage = 'prod';\n\nexport function isValidStage(stage: string): stage is EncryptStage {\n return stage === 'dev' || stage === 'prod';\n}\n\nexport function invalidStageMessage(stage: string): string {\n return `Error: --stage must be \"dev\" or \"prod\" (got: \"${stage}\")`;\n}\n\nexport function resolveStage(stage: string | undefined): {\n stage: EncryptStage;\n wasDefaulted: boolean;\n} {\n return {\n stage: stage === 'dev' || stage === 'prod' ? stage : DEFAULT_STAGE,\n wasDefaulted: stage === undefined,\n };\n}\n\nexport function defaultStageNotice(stage: EncryptStage): string {\n return `No --stage given; defaulting to ${stage} encryption keys (pass --stage dev to override)\\n`;\n}\n\nexport async function readManifestDefaults(cwd: string = process.cwd()): Promise<ManifestDefaults> {\n try {\n const raw = await readFile(join(cwd, 'kizen.json'), 'utf-8');\n const parsed = JSON.parse(raw) as unknown;\n const manifest = (Array.isArray(parsed) ? parsed[0] : parsed) as Record<string, unknown>;\n\n const apiName =\n typeof manifest.api_name === 'string' && manifest.api_name !== ''\n ? manifest.api_name\n : undefined;\n\n return {\n ...(apiName !== undefined && { apiName }),\n };\n } catch {\n // Not in a plugin directory — fine, the UI will prompt with no defaults.\n }\n\n return {};\n}\n\nexport function stripTrailingNewlines(value: string): string {\n return value.replace(/[\\r\\n]+$/, '');\n}\n\nexport async function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n\n return Buffer.concat(chunks).toString('utf-8');\n}\n","import type { EncryptionContext } from './encryptionClient.js';\nimport type { Credentials } from './credentials.js';\nimport type { ManifestDefaults } from './encryptHelpers.js';\nimport { compactEnvelope, defaultStageNotice, stripTrailingNewlines } from './encryptHelpers.js';\n\nexport interface HeadlessEncryptOptions {\n credentials?: string;\n apiName?: string;\n value?: string;\n out?: string;\n}\n\nexport interface HeadlessEncryptDeps {\n loadCredentialsFromFile: (path: string) => Promise<Credentials>;\n loadGlobalCredentials: () => Promise<Credentials | null>;\n encryptSecret: (\n ctx: EncryptionContext,\n credentials: Credentials,\n apiName: string,\n value: string,\n ) => Promise<string>;\n readStdin: () => Promise<string>;\n stdinIsTTY: () => boolean;\n writeStdout: (text: string) => void;\n writeStderr: (text: string) => void;\n writeEnvelopeFile: (path: string, value: string) => Promise<void>;\n setExitCode: (code: number) => void;\n}\n\nexport async function runHeadless(\n ctx: EncryptionContext,\n options: HeadlessEncryptOptions,\n defaults: ManifestDefaults,\n stageWasDefaulted: boolean,\n deps: HeadlessEncryptDeps,\n): Promise<void> {\n const credentials =\n options.credentials !== undefined\n ? await deps.loadCredentialsFromFile(options.credentials)\n : await deps.loadGlobalCredentials();\n\n if (credentials === null) {\n throw new Error(\n 'No credentials found. Pass --credentials or create ~/.kizenappbuilder/credentials.json.',\n );\n }\n\n const apiName = options.apiName ?? defaults.apiName;\n\n if (apiName === undefined || apiName.trim() === '') {\n throw new Error(\n 'api_name is required in non-interactive mode. Pass --api-name or run inside a plugin directory.',\n );\n }\n\n if (stageWasDefaulted) {\n deps.writeStderr(defaultStageNotice(ctx.stage));\n }\n\n let value = options.value;\n\n if (value === undefined) {\n if (deps.stdinIsTTY()) {\n throw new Error(\n 'No secret provided and stdin is a terminal. Pass --value, or pipe the secret in ' +\n '(e.g. `printf %s \"$SECRET\" | npx --yes @kizenapps/cli encrypt …`).',\n );\n }\n\n deps.writeStderr('Reading secret from stdin (pass --value to skip)…\\n');\n\n value = stripTrailingNewlines(await deps.readStdin());\n }\n\n if (value === '') {\n throw new Error('A secret value is required. Pass --value or pipe it via stdin.');\n }\n\n const envelopeValue = await deps.encryptSecret(ctx, credentials, apiName.trim(), value);\n\n deps.writeStdout(`${compactEnvelope(envelopeValue)}\\n`);\n\n if (options.out !== undefined) {\n try {\n await deps.writeEnvelopeFile(options.out, envelopeValue);\n deps.writeStderr(`Wrote encrypted envelope to ${options.out}\\n`);\n } catch (err) {\n deps.writeStderr(\n `Error writing ${options.out}: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n deps.setExitCode(1);\n }\n }\n}\n","export const VALID_ICONS = new Set([\n 'phone',\n 'envelope',\n 'pen-nib',\n 'calendar-days',\n 'paperclip',\n 'file',\n 'clipboard',\n 'pen',\n 'tag',\n 'book',\n 'print',\n 'pen-to-square',\n 'folder',\n 'folder-open',\n 'thumbtack',\n 'globe',\n 'city',\n 'briefcase',\n 'compass',\n 'address-book',\n 'business-time',\n 'computer-classic',\n 'pen-fancy',\n 'badge-check',\n 'mug-saucer',\n 'landmark',\n 'chart-simple',\n 'envelopes',\n 'diagram-venn',\n 'calendar',\n 'pencil',\n 'phone-volume',\n 'copy',\n 'table',\n 'building',\n 'network-wired',\n 'address-card',\n 'tags',\n 'registered',\n 'signature',\n 'phone-office',\n 'projector',\n 'sitemap',\n 'marker',\n 'badge',\n 'wallet',\n 'copyright',\n 'bullseye',\n 'calculator',\n 'certificate',\n 'percent',\n 'eraser',\n 'file-spreadsheet',\n 'glasses',\n 'industry',\n 'vault',\n 'user-tie-hair-long',\n 'user-tie-hair',\n 'user-hair-mullet',\n 'trademark',\n 'timeline-arrow',\n 'timeline',\n 'table-tree',\n 'table-rows',\n 'table-pivot',\n 'table-layout',\n 'table-columns',\n 'stapler',\n 'square-poll-vertical',\n 'square-poll-horizontal',\n 'square-phone-flip',\n 'square-phone',\n 'square-pen',\n 'square-kanban',\n 'square-envelope',\n 'socks',\n 'slot-machine',\n 'signature-slash',\n 'signature-lock',\n 'shredder',\n 'scissors',\n 'scanner-image',\n 'scale-unbalanced-flip',\n 'scale-unbalanced',\n 'scale-balanced',\n 'router',\n 'rectangle-pro',\n 'print-slash',\n 'print-magnifying-glass',\n 'presentation-screen',\n 'podium',\n 'phone-slash',\n 'phone-intercom',\n 'phone-flip',\n 'person-chalkboard',\n 'pen-nib-slash',\n 'pen-clip',\n 'paste',\n 'paperclip-vertical',\n 'notebook',\n 'note-sticky',\n 'money-check-pen',\n 'money-check-dollar-pen',\n 'magnifying-glass-chart',\n 'magnifying-glass-arrow-right',\n 'list-tree',\n 'list-timeline',\n 'list-radio',\n 'list-dropdown',\n 'list-check',\n 'laptop-file',\n 'lamp-desk',\n 'keynote',\n 'industry-windows',\n 'inboxes',\n 'inbox-full',\n 'house-laptop',\n 'highlighter',\n 'folders',\n 'folder-xmark',\n 'folder-tree',\n 'folder-plus',\n 'folder-minus',\n 'folder-arrow-up',\n 'folder-arrow-down',\n 'floppy-disk-circle-xmark',\n 'floppy-disk-circle-arrow-right',\n 'floppy-disk',\n 'file-user',\n 'file-lines',\n 'file-circle-plus',\n 'file-circle-info',\n 'file-chart-pie',\n 'file-chart-column',\n 'fax',\n 'envelope-open',\n 'envelope-dot',\n 'envelope-circle-check',\n 'coffee-pot',\n 'cloud-word',\n 'clipboard-question',\n 'chart-user',\n 'chart-tree-map',\n 'chart-simple-horizontal',\n 'chart-pyramid',\n 'chart-pie-simple',\n 'chart-pie',\n 'chart-line-up',\n 'chart-line-down',\n 'chart-line',\n 'cake-candles',\n 'cabinet-filing',\n 'bullhorn',\n 'briefcase-blank',\n 'briefcase-arrow-right',\n 'brain-arrow-curved-right',\n 'boxes-packing',\n 'box-archive',\n 'book-section',\n 'bars-staggered',\n 'bars-progress',\n 'badge-percent',\n 'badge-dollar',\n 'arrows-to-eye',\n 'arrows-to-dot',\n 'arrows-spin',\n 'sparkles',\n 'megaphone',\n 'block-question',\n 'lightbulb-slash',\n 'comments-dollar',\n 'comments',\n 'bullseye-pointer',\n 'lightbulb',\n 'user-group-crown',\n 'user-crown',\n 'signal-stream-slash',\n 'signal-stream',\n 'rectangle-ad',\n 'ranking-star',\n 'person-rays',\n 'people-group',\n 'messages-dollar',\n 'message-dollar',\n 'magnifying-glass-location',\n 'magnifying-glass-dollar',\n 'lightbulb-on',\n 'lightbulb-exclamation',\n 'lightbulb-dollar',\n 'lightbulb-cfl-on',\n 'lightbulb-cfl',\n 'hundred-points',\n 'group-arrows-rotate',\n 'gift-card',\n 'filter-circle-dollar',\n 'envelopes-bulk',\n 'envelope-open-text',\n 'envelope-open-dollar',\n 'comment-dollar',\n 'chart-mixed',\n 'bullseye-arrow',\n 'star',\n 'heart',\n 'camera-retro',\n 'truck-fast',\n 'bell',\n 'cart-shopping',\n 'gift',\n 'barcode',\n 'bookmark',\n 'camera',\n 'thumbs-up',\n 'thumbs-down',\n 'key',\n 'truck',\n 'balloons',\n 'handshake',\n 'shop',\n 'shirt',\n 'bag-shopping',\n 'moped',\n 'cart-plus',\n 'credit-card',\n 'store',\n 'cash-register',\n 'booth-curtain',\n 'trophy',\n 'receipt',\n 'truck-container',\n 'truck-clock',\n 'truck-bolt',\n 'trophy-star',\n 'store-slash',\n 'store-lock',\n 'star-exclamation',\n 'shop-slash',\n 'shop-lock',\n 'rectangle-barcode',\n 'person-booth',\n 'nfc-trash',\n 'nfc-symbol',\n 'nfc-slash',\n 'nfc-signal',\n 'nfc-pen',\n 'nfc-magnifying-glass',\n 'nfc-lock',\n 'nfc',\n 'money-check-dollar',\n 'money-check',\n 'mobile-signal-out',\n 'mobile-signal',\n 'hexagon-vertical-nft-slanted',\n 'hexagon-vertical-nft',\n 'hexagon-image',\n 'hand-holding-box',\n 'gifts',\n 'gem',\n 'credit-card-front',\n 'credit-card-blank',\n 'cart-xmark',\n 'cart-shopping-fast',\n 'cart-minus',\n 'cart-circle-xmark',\n 'cart-circle-plus',\n 'cart-circle-exclamation',\n 'cart-circle-check',\n 'cart-circle-arrow-up',\n 'cart-circle-arrow-down',\n 'cart-arrow-up',\n 'cart-arrow-down',\n 'box-open-full',\n 'basket-shopping-simple',\n 'basket-shopping',\n 'barcode-scan',\n 'barcode-read',\n 'balloon',\n 'bags-shopping',\n 'bars',\n 'browser',\n 'chart-bar',\n 'cog',\n 'database',\n 'calendar-alt',\n 'play',\n 'kizen-k',\n 'add',\n 'book-alt',\n 'form-entity',\n 'arrows-to-circle',\n 'question-circle',\n 'chevron-down',\n 'chevron-up',\n 'window-restore',\n 'forward',\n]);\n\nexport const VALID_ICONS_LIST = [...VALID_ICONS].sort();\n\n// Icons rendered as custom Kizen-brand React components — no FontAwesome equivalent.\nexport const CUSTOM_ICON_NAMES = new Set(['kizen-k', 'form-entity']);\n\nexport const ALL_VALID_ICONS_LIST = [...VALID_ICONS_LIST, ...[...CUSTOM_ICON_NAMES].sort()];\n","import type { Command } from 'commander';\nimport { ALL_VALID_ICONS_LIST } from '../../shared/lib/validIcons.js';\n\nexport function iconsCommand(program: Command): void {\n program\n .command('icons')\n .description('List all valid icon names accepted by toolbar items, pages, and adornments')\n .action(() => {\n for (const name of ALL_VALID_ICONS_LIST) {\n console.log(name);\n }\n });\n}\n","import { mkdir, writeFile, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Command } from 'commander';\nimport { readLocalFiles } from '../lib/readFiles.js';\nimport { GLOBAL_CREDENTIALS_DIR } from '../lib/credentials.js';\nimport { generateHtml, generateMarkdown } from '../lib/reportHelpers.js';\n\nconst EXAMPLES_DIR = join(GLOBAL_CREDENTIALS_DIR, 'examples');\n\nexport function reportCommand(program: Command): void {\n program\n .command('report')\n .description('Generate a self-contained HTML report of the plugin')\n .option('-o, --output <path>', `output file path (default: ${EXAMPLES_DIR}/<api_name>.html)`)\n .action(async (options: { output?: string }) => {\n const pluginDir = process.cwd();\n\n let manifest: Record<string, unknown>;\n\n try {\n const raw = await readFile(join(pluginDir, 'kizen.json'), 'utf-8');\n const parsed = JSON.parse(raw) as unknown;\n\n manifest = (Array.isArray(parsed) ? parsed[0] : parsed) as Record<string, unknown>;\n } catch {\n console.error('Error: kizen.json not found. Run this command from a plugin directory.');\n process.exit(1);\n }\n\n const apiName = typeof manifest.api_name === 'string' ? manifest.api_name : 'plugin';\n const htmlPath = options.output ?? join(EXAMPLES_DIR, `${apiName}.html`);\n const mdPath = htmlPath.replace(/\\.html$/, '.md');\n\n const files = await readLocalFiles(pluginDir, { detectBinaryByContent: true });\n\n await mkdir(join(htmlPath, '..'), { recursive: true });\n\n await Promise.all([\n writeFile(htmlPath, generateHtml(manifest, files), 'utf-8'),\n writeFile(mdPath, generateMarkdown(manifest, files), 'utf-8'),\n ]);\n\n console.log(`Plugin report written to:\\n ${htmlPath}\\n ${mdPath}`);\n });\n}\n","import type { FileContent } from '@kizenapps/packager';\n\nconst SENSITIVE_FIELDS = new Set(['developer_business_id']);\n\nexport function redactServices(services: unknown): unknown {\n if (!Array.isArray(services)) {\n return services;\n }\n\n return services.map((svc: unknown) => {\n if (typeof svc !== 'object' || svc === null) {\n return svc;\n }\n\n const s = svc as Record<string, unknown>;\n\n if (typeof s.auth_credentials !== 'object' || s.auth_credentials === null) {\n return s;\n }\n\n const redacted = Object.fromEntries(Object.keys(s.auth_credentials).map((k) => [k, '*****']));\n\n return { ...s, auth_credentials: redacted };\n });\n}\n\nexport interface TreeNode {\n name: string;\n children: Map<string, TreeNode>;\n isFile: boolean;\n filePath: string;\n}\n\nexport function buildTree(files: FileContent[]): TreeNode {\n const root: TreeNode = { name: '', children: new Map(), isFile: false, filePath: '' };\n\n for (const file of files) {\n const parts = file.path.split('/');\n let node = root;\n\n parts.forEach((part, i) => {\n if (!node.children.has(part)) {\n node.children.set(part, {\n name: part,\n children: new Map(),\n isFile: i === parts.length - 1,\n filePath: parts.slice(0, i + 1).join('/'),\n });\n }\n\n const next = node.children.get(part);\n\n if (next) {\n node = next;\n }\n });\n }\n\n return root;\n}\n\nfunction sortTreeChildren(node: TreeNode): TreeNode[] {\n return [...node.children.values()].sort((a, b) => {\n if (a.isFile !== b.isFile) {\n return a.isFile ? 1 : -1;\n }\n\n return a.name.localeCompare(b.name);\n });\n}\n\nexport function fileId(path: string): string {\n return 'file-' + path.replace(/[^a-zA-Z0-9]/g, '-');\n}\n\nexport function esc(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\nexport function fileExt(path: string): string {\n const idx = path.lastIndexOf('.');\n\n return idx >= 0 ? path.slice(idx).toLowerCase() : '';\n}\n\nconst LANG_MAP: Record<string, string> = {\n '.ts': 'typescript',\n '.tsx': 'typescript',\n '.js': 'javascript',\n '.jsx': 'javascript',\n '.mjs': 'javascript',\n '.cjs': 'javascript',\n '.json': 'json',\n '.css': 'css',\n '.scss': 'scss',\n '.html': 'html',\n '.htm': 'html',\n '.md': 'markdown',\n '.mdx': 'markdown',\n '.py': 'python',\n '.sh': 'bash',\n '.yml': 'yaml',\n '.yaml': 'yaml',\n '.xml': 'xml',\n '.toml': 'toml',\n};\n\nexport function mdLang(path: string): string {\n return LANG_MAP[fileExt(path)] ?? '';\n}\n\n// A fenced block must be delimited by more backticks than the longest run inside\n// it, or content that is itself markdown (a README with a code sample) escapes\n// its wrapper and corrupts the rest of the document.\nexport function mdFence(content: string): string {\n const longestRun = [...content.matchAll(/`+/g)].reduce((max, m) => Math.max(max, m[0].length), 0);\n\n return '`'.repeat(Math.max(3, longestRun + 1));\n}\n\nexport function renderTextTree(node: TreeNode, prefix = ''): string {\n const sorted = sortTreeChildren(node);\n\n return sorted\n .map((child, i) => {\n const isLast = i === sorted.length - 1;\n const connector = isLast ? '└── ' : '├── ';\n const childPrefix = isLast ? ' ' : '│ ';\n\n if (child.isFile) {\n return `${prefix}${connector}${child.name}`;\n }\n\n return `${prefix}${connector}${child.name}/\\n${renderTextTree(child, prefix + childPrefix)}`;\n })\n .join('\\n');\n}\n\nconst LICENSE_FILE = /(^|\\/)licen[cs]e(\\.md|\\.txt)?$/i;\n\nexport function filterSourceFiles(files: FileContent[]): FileContent[] {\n return files.filter(\n (f) => f.path !== 'kizen.json' && f.path !== 'plugin-report.html' && !LICENSE_FILE.test(f.path),\n );\n}\n\nexport function buildFilteredConfig(manifest: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(manifest)\n .filter(([k]) => !SENSITIVE_FIELDS.has(k))\n .map(([k, v]) => [k, k === 'services' ? redactServices(v) : v]),\n );\n}\n\nconst IMAGE_MIME: Record<string, string> = {\n '.png': 'image/png',\n '.svg': 'image/svg+xml',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n};\n\nfunction renderTree(node: TreeNode): string {\n const sorted = sortTreeChildren(node);\n const items = sorted.map((child) => {\n if (child.isFile) {\n return `<li class=\"tf\"><a href=\"#${fileId(child.filePath)}\" data-id=\"${fileId(child.filePath)}\">${esc(child.name)}</a></li>`;\n }\n\n return `<li class=\"td\"><span class=\"dn\">${esc(child.name)}/</span>${renderTree(child)}</li>`;\n });\n\n return `<ul>${items.join('')}</ul>`;\n}\n\nfunction renderFileSection(file: FileContent): string {\n let body: string;\n\n if (file.base64Image !== undefined) {\n const mime = IMAGE_MIME[fileExt(file.path)] ?? 'image/png';\n\n body = `<img src=\"data:${mime};base64,${file.base64Image}\" alt=\"${esc(file.path)}\" style=\"max-width:100%\">`;\n } else if (file.binaryData !== undefined) {\n body = `<p class=\"bin\">[Binary file: ${String(file.binaryData.length)} bytes]</p>`;\n } else {\n body = `<pre><code>${esc(file.content)}</code></pre>`;\n }\n\n return `<section id=\"${fileId(file.path)}\"><h2 class=\"fp\">${esc(file.path)}</h2><div class=\"fb\">${body}</div></section>`;\n}\n\nexport function generateMarkdown(manifest: Record<string, unknown>, files: FileContent[]): string {\n const filtered = buildFilteredConfig(manifest);\n const name = typeof manifest.name === 'string' ? manifest.name : 'Plugin';\n const version = typeof manifest.version === 'string' ? manifest.version : '';\n const description = typeof manifest.description === 'string' ? manifest.description : '';\n const sourceFiles = filterSourceFiles(files);\n\n const lines: string[] = [];\n\n lines.push(`# ${name}${version ? ` v${version}` : ''}`);\n if (description) {\n lines.push('', description);\n }\n\n const configJson = JSON.stringify(filtered, null, 2);\n const configFence = mdFence(configJson);\n\n lines.push(\n '',\n '## Configuration (`kizen.json`)',\n '',\n `${configFence}json`,\n configJson,\n configFence,\n );\n\n lines.push('', '## File Tree', '', '```', renderTextTree(buildTree(sourceFiles)), '```');\n\n lines.push('', '## Files');\n\n for (const file of sourceFiles) {\n lines.push('', `### \\`${file.path}\\``, '');\n\n if (file.base64Image !== undefined) {\n lines.push(`[Image file: ${file.path}]`);\n } else if (file.binaryData !== undefined) {\n lines.push(`[Binary file: ${String(file.binaryData.length)} bytes]`);\n } else {\n const fence = mdFence(file.content);\n\n lines.push(`${fence}${mdLang(file.path)}`, file.content, fence);\n }\n }\n\n return lines.join('\\n') + '\\n';\n}\n\nexport function generateHtml(manifest: Record<string, unknown>, files: FileContent[]): string {\n const filtered = buildFilteredConfig(manifest);\n const name = typeof manifest.name === 'string' ? manifest.name : 'Plugin';\n const version = typeof manifest.version === 'string' ? manifest.version : '';\n const description = typeof manifest.description === 'string' ? manifest.description : '';\n\n const sourceFiles = filterSourceFiles(files);\n const treeHtml = renderTree(buildTree(sourceFiles));\n const fileSections = sourceFiles.map(renderFileSection).join('\\n');\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>${esc(name)} — Plugin Report</title>\n<style>\n*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}\n:root{\n --bg:#1e1e2e;--sb:#181825;--hd:#11111b;--tx:#cdd6f4;--mu:#6c7086;\n --ac:#89b4fa;--gr:#a6e3a1;--bd:#313244;--cb:#181825;--sw:280px;\n --fn:'Menlo','Consolas','Monaco',monospace;\n}\nhtml{font-size:14px}\nbody{background:var(--bg);color:var(--tx);font-family:var(--fn);display:flex;flex-direction:column;height:100vh}\nheader{background:var(--hd);border-bottom:1px solid var(--bd);padding:14px 20px;flex-shrink:0}\nheader h1{font-size:1.1rem;color:var(--ac)}\nheader p{color:var(--mu);font-size:.85rem;margin-top:3px}\n.layout{display:flex;flex:1;overflow:hidden}\nnav{width:var(--sw);background:var(--sb);border-right:1px solid var(--bd);overflow-y:auto;padding:12px 0;flex-shrink:0}\nnav a.cfg{display:block;padding:6px 16px;color:var(--gr);text-decoration:none;font-size:.85rem}\nnav a.cfg:hover,nav a.cfg.active{background:var(--bd)}\nnav ul{list-style:none;padding-left:0}\n.td>.dn{display:block;padding:4px 16px;color:var(--mu);font-size:.8rem}\n.td ul{padding-left:14px}\n.tf a{display:block;padding:3px 16px;color:var(--tx);text-decoration:none;font-size:.8rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.tf a:hover,.tf a.active{background:var(--bd);color:var(--ac)}\nmain{flex:1;overflow-y:auto;padding:0 24px 40px}\nsection{padding:32px 0;border-bottom:1px solid var(--bd)}\nh2.fp{font-size:.9rem;color:var(--ac);margin-bottom:12px;word-break:break-all}\n#config h2.fp{color:var(--gr)}\npre{background:var(--cb);border:1px solid var(--bd);border-radius:6px;padding:14px;overflow-x:auto;font-size:.78rem;line-height:1.6;white-space:pre}\ncode{font-family:var(--fn)}\nimg{border:1px solid var(--bd);border-radius:4px}\n.bin{color:var(--mu);font-style:italic;padding:12px 0}\n::-webkit-scrollbar{width:6px;height:6px}\n::-webkit-scrollbar-track{background:transparent}\n::-webkit-scrollbar-thumb{background:var(--bd);border-radius:3px}\n</style>\n</head>\n<body>\n<header>\n <h1>${esc(name)}${version ? ` <span style=\"color:var(--mu);font-size:.8em\">v${esc(version)}</span>` : ''}</h1>\n ${description ? `<p>${esc(description)}</p>` : ''}\n</header>\n<div class=\"layout\">\n<nav>\n <a href=\"#config\" class=\"cfg\" data-id=\"config\">kizen.json (config)</a>\n ${treeHtml}\n</nav>\n<main>\n<section id=\"config\"><h2 class=\"fp\">kizen.json — Plugin Configuration</h2><div class=\"fb\"><pre><code>${esc(JSON.stringify(filtered, null, 2))}</code></pre></div></section>\n${fileSections}\n</main>\n</div>\n<script>\n(function(){\n var links=document.querySelectorAll('[data-id]');\n function setActive(id){links.forEach(function(l){l.classList.toggle('active',l.getAttribute('data-id')===id);})}\n links.forEach(function(l){l.addEventListener('click',function(){setActive(this.getAttribute('data-id'));});});\n var obs=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting)setActive(e.target.id);});},{rootMargin:'-20% 0px -70% 0px'});\n document.querySelectorAll('section[id]').forEach(function(s){obs.observe(s);});\n})();\n</script>\n</body>\n</html>`;\n}\n","import { createProgram } from './program.js';\n\ncreateProgram().parse();\n"],"mappings":"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IC,GACxBC,GAAcC,GAAW,CACvB,IAAAd,EACA,eAAgBF,EAChB,OAASiB,GAAkB,CACzBL,EAAgBK,CAClB,EACA,GAAIvB,EAAQ,cAAgB,QAAa,CAAE,gBAAiBA,EAAQ,WAAY,EAChF,GAAIA,EAAQ,UAAY,QAAa,CAAE,eAAgBA,EAAQ,OAAQ,EACvE,GAAIG,EAAS,UAAY,QAAa,CAAE,eAAgBA,EAAS,OAAQ,EACzE,GAAIH,EAAQ,QAAU,QAAa,CAAE,aAAcA,EAAQ,KAAM,CACnE,CAAC,EACD,CAAE,YAAa,EAAM,CACvB,EAMA,GAJA,MAAMmB,EAAc,EAIhBD,IAAkB,QAAalB,EAAQ,MAAQ,OACjD,GAAI,CACF,MAAMe,GAAkBf,EAAQ,IAAKkB,CAAa,EAClD,QAAQ,OAAO,MAAM,+BAA+BlB,EAAQ,GAAG;AAAA,CAAI,CACrE,OAASiB,EAAK,CACZ,QAAQ,MACN,iBAAiBjB,EAAQ,GAAG,KAAKiB,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,CAAC,EACnF,EACA,QAAQ,SAAW,CACrB,CAEJ,CAAC,CACL,CM5HO,IAAMO,GAAc,IAAI,IAAI,CACjC,QACA,WACA,UACA,gBACA,YACA,OACA,YACA,MACA,MACA,OACA,QACA,gBACA,SACA,cACA,YACA,QACA,OACA,YACA,UACA,eACA,gBACA,mBACA,YACA,cACA,aACA,WACA,eACA,YACA,eACA,WACA,SACA,eACA,OACA,QACA,WACA,gBACA,eACA,OACA,aACA,YACA,eACA,YACA,UACA,SACA,QACA,SACA,YACA,WACA,aACA,cACA,UACA,SACA,mBACA,UACA,WACA,QACA,qBACA,gBACA,mBACA,YACA,iBACA,WACA,aACA,aACA,cACA,eACA,gBACA,UACA,uBACA,yBACA,oBACA,eACA,aACA,gBACA,kBACA,QACA,eACA,kBACA,iBACA,WACA,WACA,gBACA,wBACA,mBACA,iBACA,SACA,gBACA,cACA,yBACA,sBACA,SACA,cACA,iBACA,aACA,oBACA,gBACA,WACA,QACA,qBACA,WACA,cACA,kBACA,yBACA,yBACA,+BACA,YACA,gBACA,aACA,gBACA,aACA,cACA,YACA,UACA,mBACA,UACA,aACA,eACA,cACA,UACA,eACA,cACA,cACA,eACA,kBACA,oBACA,2BACA,iCACA,cACA,YACA,aACA,mBACA,mBACA,iBACA,oBACA,MACA,gBACA,eACA,wBACA,aACA,aACA,qBACA,aACA,iBACA,0BACA,gBACA,mBACA,YACA,gBACA,kBACA,aACA,eACA,iBACA,WACA,kBACA,wBACA,2BACA,gBACA,cACA,eACA,iBACA,gBACA,gBACA,eACA,gBACA,gBACA,cACA,WACA,YACA,iBACA,kBACA,kBACA,WACA,mBACA,YACA,mBACA,aACA,sBACA,gBACA,eACA,eACA,cACA,eACA,kBACA,iBACA,4BACA,0BACA,eACA,wBACA,mBACA,mBACA,gBACA,iBACA,sBACA,YACA,uBACA,iBACA,qBACA,uBACA,iBACA,cACA,iBACA,OACA,QACA,eACA,aACA,OACA,gBACA,OACA,UACA,WACA,SACA,YACA,cACA,MACA,QACA,WACA,YACA,OACA,QACA,eACA,QACA,YACA,cACA,QACA,gBACA,gBACA,SACA,UACA,kBACA,cACA,aACA,cACA,cACA,aACA,mBACA,aACA,YACA,oBACA,eACA,YACA,aACA,YACA,aACA,UACA,uBACA,WACA,MACA,qBACA,cACA,oBACA,gBACA,+BACA,uBACA,gBACA,mBACA,QACA,MACA,oBACA,oBACA,aACA,qBACA,aACA,oBACA,mBACA,0BACA,oBACA,uBACA,yBACA,gBACA,kBACA,gBACA,yBACA,kBACA,eACA,eACA,UACA,gBACA,OACA,UACA,YACA,MACA,WACA,eACA,OACA,UACA,MACA,WACA,cACA,mBACA,kBACA,eACA,aACA,iBACA,SACF,CAAC,EAEYC,GAAmB,CAAC,GAAGD,EAAW,EAAE,KAAK,EAGzCE,GAAoB,IAAI,IAAI,CAAC,UAAW,aAAa,CAAC,EAEtDC,GAAuB,CAAC,GAAGF,GAAkB,GAAG,CAAC,GAAGC,EAAiB,EAAE,KAAK,CAAC,EC3SnF,SAASE,GAAaC,EAAwB,CACnDA,EACG,QAAQ,OAAO,EACf,YAAY,4EAA4E,EACxF,OAAO,IAAM,CACZ,QAAWC,KAAQC,GACjB,QAAQ,IAAID,CAAI,CAEpB,CAAC,CACL,CCZA,OAAS,SAAAE,GAAO,aAAAC,GAAW,YAAAC,OAAgB,cAC3C,OAAS,QAAAC,OAAY,OCCrB,IAAMC,GAAmB,IAAI,IAAI,CAAC,uBAAuB,CAAC,EAEnD,SAASC,GAAeC,EAA4B,CACzD,OAAK,MAAM,QAAQA,CAAQ,EAIpBA,EAAS,IAAKC,GAAiB,CACpC,GAAI,OAAOA,GAAQ,UAAYA,IAAQ,KACrC,OAAOA,EAGT,IAAMC,EAAID,EAEV,GAAI,OAAOC,EAAE,kBAAqB,UAAYA,EAAE,mBAAqB,KACnE,OAAOA,EAGT,IAAMC,EAAW,OAAO,YAAY,OAAO,KAAKD,EAAE,gBAAgB,EAAE,IAAKE,GAAM,CAACA,EAAG,OAAO,CAAC,CAAC,EAE5F,MAAO,CAAE,GAAGF,EAAG,iBAAkBC,CAAS,CAC5C,CAAC,EAjBQH,CAkBX,CASO,SAASK,GAAUC,EAAgC,CACxD,IAAMC,EAAiB,CAAE,KAAM,GAAI,SAAU,IAAI,IAAO,OAAQ,GAAO,SAAU,EAAG,EAEpF,QAAWC,KAAQF,EAAO,CACxB,IAAMG,EAAQD,EAAK,KAAK,MAAM,GAAG,EAC7BE,EAAOH,EAEXE,EAAM,QAAQ,CAACE,EAAMC,IAAM,CACpBF,EAAK,SAAS,IAAIC,CAAI,GACzBD,EAAK,SAAS,IAAIC,EAAM,CACtB,KAAMA,EACN,SAAU,IAAI,IACd,OAAQC,IAAMH,EAAM,OAAS,EAC7B,SAAUA,EAAM,MAAM,EAAGG,EAAI,CAAC,EAAE,KAAK,GAAG,CAC1C,CAAC,EAGH,IAAMC,EAAOH,EAAK,SAAS,IAAIC,CAAI,EAE/BE,IACFH,EAAOG,EAEX,CAAC,CACH,CAEA,OAAON,CACT,CAEA,SAASO,GAAiBJ,EAA4B,CACpD,MAAO,CAAC,GAAGA,EAAK,SAAS,OAAO,CAAC,EAAE,KAAK,CAACK,EAAGC,IACtCD,EAAE,SAAWC,EAAE,OACVD,EAAE,OAAS,EAAI,GAGjBA,EAAE,KAAK,cAAcC,EAAE,IAAI,CACnC,CACH,CAEO,SAASC,GAAOC,EAAsB,CAC3C,MAAO,QAAUA,EAAK,QAAQ,gBAAiB,GAAG,CACpD,CAEO,SAASC,GAAIC,EAAqB,CACvC,OAAOA,EACJ,QAAQ,KAAM,OAAO,EACrB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,QAAQ,CAC3B,CAEO,SAASC,GAAQH,EAAsB,CAC5C,IAAMI,EAAMJ,EAAK,YAAY,GAAG,EAEhC,OAAOI,GAAO,EAAIJ,EAAK,MAAMI,CAAG,EAAE,YAAY,EAAI,EACpD,CAEA,IAAMC,GAAmC,CACvC,MAAO,aACP,OAAQ,aACR,MAAO,aACP,OAAQ,aACR,OAAQ,aACR,OAAQ,aACR,QAAS,OACT,OAAQ,MACR,QAAS,OACT,QAAS,OACT,OAAQ,OACR,MAAO,WACP,OAAQ,WACR,MAAO,SACP,MAAO,OACP,OAAQ,OACR,QAAS,OACT,OAAQ,MACR,QAAS,MACX,EAEO,SAASC,GAAON,EAAsB,CAC3C,OAAOK,GAASF,GAAQH,CAAI,CAAC,GAAK,EACpC,CAKO,SAASO,GAAQC,EAAyB,CAC/C,IAAMC,EAAa,CAAC,GAAGD,EAAQ,SAAS,KAAK,CAAC,EAAE,OAAO,CAACE,EAAKC,IAAM,KAAK,IAAID,EAAKC,EAAE,CAAC,EAAE,MAAM,EAAG,CAAC,EAEhG,MAAO,IAAI,OAAO,KAAK,IAAI,EAAGF,EAAa,CAAC,CAAC,CAC/C,CAEO,SAASG,GAAepB,EAAgBqB,EAAS,GAAY,CAClE,IAAMC,EAASlB,GAAiBJ,CAAI,EAEpC,OAAOsB,EACJ,IAAI,CAACC,EAAOrB,IAAM,CACjB,IAAMsB,EAAStB,IAAMoB,EAAO,OAAS,EAC/BG,EAAYD,EAAS,sBAAS,sBAC9BE,EAAcF,EAAS,OAAS,YAEtC,OAAID,EAAM,OACD,GAAGF,CAAM,GAAGI,CAAS,GAAGF,EAAM,IAAI,GAGpC,GAAGF,CAAM,GAAGI,CAAS,GAAGF,EAAM,IAAI;AAAA,EAAMH,GAAeG,EAAOF,EAASK,CAAW,CAAC,EAC5F,CAAC,EACA,KAAK;AAAA,CAAI,CACd,CAEA,IAAMC,GAAe,kCAEd,SAASC,GAAkBhC,EAAqC,CACrE,OAAOA,EAAM,OACViC,GAAMA,EAAE,OAAS,cAAgBA,EAAE,OAAS,sBAAwB,CAACF,GAAa,KAAKE,EAAE,IAAI,CAChG,CACF,CAEO,SAASC,GAAoBC,EAA4D,CAC9F,OAAO,OAAO,YACZ,OAAO,QAAQA,CAAQ,EACpB,OAAO,CAAC,CAACrC,CAAC,IAAM,CAACN,GAAiB,IAAIM,CAAC,CAAC,EACxC,IAAI,CAAC,CAACA,EAAGsC,CAAC,IAAM,CAACtC,EAAGA,IAAM,WAAaL,GAAe2C,CAAC,EAAIA,CAAC,CAAC,CAClE,CACF,CAEA,IAAMC,GAAqC,CACzC,OAAQ,YACR,OAAQ,gBACR,OAAQ,aACR,QAAS,aACT,OAAQ,YACR,QAAS,YACX,EAEA,SAASC,GAAWlC,EAAwB,CAU1C,MAAO,OATQI,GAAiBJ,CAAI,EACf,IAAKuB,GACpBA,EAAM,OACD,4BAA4BhB,GAAOgB,EAAM,QAAQ,CAAC,cAAchB,GAAOgB,EAAM,QAAQ,CAAC,KAAKd,GAAIc,EAAM,IAAI,CAAC,YAG5G,mCAAmCd,GAAIc,EAAM,IAAI,CAAC,WAAWW,GAAWX,CAAK,CAAC,OACtF,EAEmB,KAAK,EAAE,CAAC,OAC9B,CAEA,SAASY,GAAkBrC,EAA2B,CACpD,IAAIsC,EAEJ,OAAItC,EAAK,cAAgB,OAGvBsC,EAAO,kBAFMH,GAAWtB,GAAQb,EAAK,IAAI,CAAC,GAAK,WAElB,WAAWA,EAAK,WAAW,UAAUW,GAAIX,EAAK,IAAI,CAAC,4BACvEA,EAAK,aAAe,OAC7BsC,EAAO,gCAAgC,OAAOtC,EAAK,WAAW,MAAM,CAAC,cAErEsC,EAAO,cAAc3B,GAAIX,EAAK,OAAO,CAAC,gBAGjC,gBAAgBS,GAAOT,EAAK,IAAI,CAAC,oBAAoBW,GAAIX,EAAK,IAAI,CAAC,wBAAwBsC,CAAI,kBACxG,CAEO,SAASC,GAAiBN,EAAmCnC,EAA8B,CAChG,IAAM0C,EAAWR,GAAoBC,CAAQ,EACvCQ,EAAO,OAAOR,EAAS,MAAS,SAAWA,EAAS,KAAO,SAC3DS,EAAU,OAAOT,EAAS,SAAY,SAAWA,EAAS,QAAU,GACpEU,EAAc,OAAOV,EAAS,aAAgB,SAAWA,EAAS,YAAc,GAChFW,EAAcd,GAAkBhC,CAAK,EAErC+C,EAAkB,CAAC,EAEzBA,EAAM,KAAK,KAAKJ,CAAI,GAAGC,EAAU,KAAKA,CAAO,GAAK,EAAE,EAAE,EAClDC,GACFE,EAAM,KAAK,GAAIF,CAAW,EAG5B,IAAMG,EAAa,KAAK,UAAUN,EAAU,KAAM,CAAC,EAC7CO,EAAc9B,GAAQ6B,CAAU,EAEtCD,EAAM,KACJ,GACA,kCACA,GACA,GAAGE,CAAW,OACdD,EACAC,CACF,EAEAF,EAAM,KAAK,GAAI,eAAgB,GAAI,MAAOvB,GAAezB,GAAU+C,CAAW,CAAC,EAAG,KAAK,EAEvFC,EAAM,KAAK,GAAI,UAAU,EAEzB,QAAW7C,KAAQ4C,EAGjB,GAFAC,EAAM,KAAK,GAAI,SAAS7C,EAAK,IAAI,KAAM,EAAE,EAErCA,EAAK,cAAgB,OACvB6C,EAAM,KAAK,gBAAgB7C,EAAK,IAAI,GAAG,UAC9BA,EAAK,aAAe,OAC7B6C,EAAM,KAAK,iBAAiB,OAAO7C,EAAK,WAAW,MAAM,CAAC,SAAS,MAC9D,CACL,IAAMgD,EAAQ/B,GAAQjB,EAAK,OAAO,EAElC6C,EAAM,KAAK,GAAGG,CAAK,GAAGhC,GAAOhB,EAAK,IAAI,CAAC,GAAIA,EAAK,QAASgD,CAAK,CAChE,CAGF,OAAOH,EAAM,KAAK;AAAA,CAAI,EAAI;AAAA,CAC5B,CAEO,SAASI,GAAahB,EAAmCnC,EAA8B,CAC5F,IAAM0C,EAAWR,GAAoBC,CAAQ,EACvCQ,EAAO,OAAOR,EAAS,MAAS,SAAWA,EAAS,KAAO,SAC3DS,EAAU,OAAOT,EAAS,SAAY,SAAWA,EAAS,QAAU,GACpEU,EAAc,OAAOV,EAAS,aAAgB,SAAWA,EAAS,YAAc,GAEhFW,EAAcd,GAAkBhC,CAAK,EACrCoD,EAAWd,GAAWvC,GAAU+C,CAAW,CAAC,EAC5CO,EAAeP,EAAY,IAAIP,EAAiB,EAAE,KAAK;AAAA,CAAI,EAEjE,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA,SAKA1B,GAAI8B,CAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAqCV9B,GAAI8B,CAAI,CAAC,GAAGC,EAAU,kDAAkD/B,GAAI+B,CAAO,CAAC,UAAY,EAAE;AAAA,IACtGC,EAAc,MAAMhC,GAAIgC,CAAW,CAAC,OAAS,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,IAK/CO,CAAQ;AAAA;AAAA;AAAA,4GAG2FvC,GAAI,KAAK,UAAU6B,EAAU,KAAM,CAAC,CAAC,CAAC;AAAA,EAC3IW,CAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcd,CDxTA,IAAMC,GAAeC,GAAKC,GAAwB,UAAU,EAErD,SAASC,GAAcC,EAAwB,CACpDA,EACG,QAAQ,QAAQ,EAChB,YAAY,qDAAqD,EACjE,OAAO,sBAAuB,8BAA8BJ,EAAY,mBAAmB,EAC3F,OAAO,MAAOK,GAAiC,CAC9C,IAAMC,EAAY,QAAQ,IAAI,EAE1BC,EAEJ,GAAI,CACF,IAAMC,EAAM,MAAMC,GAASR,GAAKK,EAAW,YAAY,EAAG,OAAO,EAC3DI,EAAS,KAAK,MAAMF,CAAG,EAE7BD,EAAY,MAAM,QAAQG,CAAM,EAAIA,EAAO,CAAC,EAAIA,CAClD,MAAQ,CACN,QAAQ,MAAM,wEAAwE,EACtF,QAAQ,KAAK,CAAC,CAChB,CAEA,IAAMC,EAAU,OAAOJ,EAAS,UAAa,SAAWA,EAAS,SAAW,SACtEK,EAAWP,EAAQ,QAAUJ,GAAKD,GAAc,GAAGW,CAAO,OAAO,EACjEE,EAASD,EAAS,QAAQ,UAAW,KAAK,EAE1CE,EAAQ,MAAMC,GAAeT,EAAW,CAAE,sBAAuB,EAAK,CAAC,EAE7E,MAAMU,GAAMf,GAAKW,EAAU,IAAI,EAAG,CAAE,UAAW,EAAK,CAAC,EAErD,MAAM,QAAQ,IAAI,CAChBK,GAAUL,EAAUM,GAAaX,EAAUO,CAAK,EAAG,OAAO,EAC1DG,GAAUJ,EAAQM,GAAiBZ,EAAUO,CAAK,EAAG,OAAO,CAC9D,CAAC,EAED,QAAQ,IAAI;AAAA,IAAgCF,CAAQ;AAAA,IAAOC,CAAM,EAAE,CACrE,CAAC,CACL,ClEjCA,SAASO,IAAsB,CAC7B,IAAMC,EAAUC,GAAKC,GAAQC,GAAc,YAAY,GAAG,CAAC,EAAG,KAAM,cAAc,EAGlF,OAFY,KAAK,MAAMC,GAAaJ,EAAS,OAAO,CAAC,EAE1C,OACb,CAEO,SAASK,IAAyB,CACvC,IAAMC,EAAU,IAAIC,GAEpB,OAAAD,EAAQ,KAAK,YAAY,EAAE,YAAY,0BAA0B,EAAE,QAAQP,GAAY,CAAC,EAExFS,GAAcF,CAAO,EAErBG,GAAaH,CAAO,EAEpBI,GAAWJ,CAAO,EAElBK,GAAeL,CAAO,EAEtBM,GAAcN,CAAO,EAErBO,GAAaP,CAAO,EAEbA,CACT,CoElCAQ,GAAc,EAAE,MAAM","names":["readFileSync","dirname","join","fileURLToPath","Command","createElement","render","useEffect","useState","Box","Text","useApp","PluginValidationError","mkdir","writeFile","join","PluginValidationError","minifyFiles","packagePlugin","parseManifestFromFiles","transformDeployablePlugin","validatePluginApp","readdir","readFile","join","relative","IMAGE_EXTENSIONS","BINARY_EXTENSIONS","SKIP_FILES","SKIP_DIRS","BINARY_SNIFF_BYTES","looksBinary","buf","walk","dir","rootDir","entries","paths","entry","readLocalFiles","detectBinaryByContent","absolutePaths","absPath","relPath","dotIndex","ext","serializePlugin","plugin","allReleaseNotes","runBuild","pluginDir","outputDir","onStep","mkdir","files","readLocalFiles","issues","validatePluginApp","issue","PluginValidationError","minified","minifyFiles","manifests","parseManifestFromFiles","packaged","packagePlugin","deployable","transformDeployablePlugin","bundle","notesDir","f","a","b","jsonStr","stripReleaseNotes","key","value","bundleSize","writeFile","join","formatBytes","n","Box","Text","Box","Text","jsx","LOGO_LINES","Logo","line","i","Fragment","jsx","jsxs","AppHeader","marginBottom","Logo","Box","Text","useEffect","useState","Text","jsx","SPINNER_FRAMES","Spinner","frame","setFrame","id","prev","Box","Text","jsx","jsxs","groupIssuesByPath","issues","groups","issue","key","group","ValidationIssues","errorCount","path","Fragment","jsx","jsxs","STEPS","STEP_LABELS","BuildUI","outputDir","pluginDir","app","useApp","step","setStep","useState","failed","setFailed","issues","setIssues","errorMessage","setErrorMessage","bundleSize","setBundleSize","useEffect","runBuild","size","err","PluginValidationError","currentIndex","isDone","Box","AppHeader","s","i","isActive","isStepDone","Text","Spinner","formatBytes","ValidationIssues","fs","path","ensureGitignore","projectDir","gitignorePath","entry","contents","lines","l","addition","buildCommand","program","pluginDir","outputDir","ensureGitignore","waitUntilExit","render","createElement","BuildUI","createElement","render","useCallback","useState","Box","Text","useApp","useInput","join","access","mkdir","writeFile","dirname","join","config_default","script_default","styles_default","config_default","script_default","styles_default","config_default","script_default","config_default","script_default","styles_default","greet_default","config_default","script_default","config_default","script_default","config_default","script_default","ARTIFACT_TYPES","ARTIFACT_LABELS","TEMPLATES","config_default","script_default","styles_default","greet_default","artifactFiles","type","entryDir","directory","component","files","relativePath","content","scaffoldArtifactFiles","types","copilot_instructions_default","security_instructions_default","version_discipline_instructions_default","copilotFiles","copilot_instructions_default","security_instructions_default","version_discipline_instructions_default","deflateSync","THUMBNAIL_SIZE","BODY_HALF_SIZE","BODY_CORNER_RADIUS","KNOB_RADIUS","KNOB_OFFSET_RATIO","NECK_HALF_WIDTH","SATURATION","LIGHTNESS","fnv1a","text","hash","i","thumbnailStyle","apiName","hslToRgb","hue","saturation","lightness","chroma","sector","secondary","match","r","b","roundedBoxDistance","x","y","halfW","halfH","radius","qx","qy","circleDistance","cx","cy","puzzlePieceDistance","s","k","offset","neckHalf","topKnob","rightKnob","bottomSocket","leftSocket","renderPixels","style","size","pixels","g","knobExtension","centre","shift","py","px","turn","d","coverage","CRC_TABLE","_","n","c","crc32","bytes","crc","byte","pngChunk","type","data","typeBytes","length","PNG_SIGNATURE","encodePng","width","height","rgba","ihdr","stride","raw","thumbnailBytes","THUMBNAIL_PATH","PROD_ENVIRONMENTS","pathExists","path","access","precheckTargetDir","dir","join","findAvailableSubDir","parentDir","baseName","base","i","candidate","buildManifest","input","businessId","targetEnvironments","writeScaffoldedFiles","targetDir","scaffolded","files","file","directories","dirname","mkdir","writeFile","createPlugin","manifest","scaffoldArtifactFiles","copilotFiles","thumbnailBytes","ensureGitignore","FIELDS","FIELD_LABELS","REQUIRED_FIELDS","API_NAME_PATTERN","API_NAME_HINT","inferApiName","name","emptyValues","defaultBusinessId","validateField","fieldName","inputBuffer","value","normalizeFieldValue","toggleArtifactSelection","selected","type","next","ARTIFACT_TYPES","candidate","jsx","jsxs","Hint","text","Text","CreateUI","parentDir","defaultBusinessId","defaultEnvironment","app","useApp","phase","setPhase","useState","mode","setMode","values","setValues","emptyValues","artifacts","setArtifacts","ARTIFACT_TYPES","inputBuffer","setInputBuffer","targetDir","setTargetDir","enterFieldEntry","useCallback","nextMode","initialValues","runPrecheck","dir","result","precheckTargetDir","resolveSubDirAndConfirm","finalValues","findAvailableSubDir","err","runWrite","createPlugin","useInput","input","key","field","current","fieldName","FIELDS","prev","updated","prevField","prevName","fieldError","validateField","valueToStore","normalizeFieldValue","nextField","nextName","existing","nextBuffer","inferApiName","cursor","selected","lastField","lastName","type","next","toggleArtifactSelection","options","Box","AppHeader","opt","i","reason","activeField","targetLine","name","isActive","displayValue","isRequired","REQUIRED_FIELDS","label","FIELD_LABELS","active","checked","ARTIFACT_LABELS","manifest","buildManifest","join","mkdir","readFile","readdir","writeFile","homedir","dirname","join","ENVIRONMENTS","GLOBAL_CREDENTIALS_DIR","join","homedir","GLOBAL_CREDENTIALS_PATH","DEFAULT_PROFILE_NAME","isValidEnvironment","value","ENVIRONMENTS","parseCredentials","raw","obj","env","loadCredentialsFromFile","filePath","content","readFile","loadGlobalCredentials","saveGlobalCredentials","credentials","mkdir","dirname","writeFile","getProfilePath","name","listCredentialProfiles","profiles","entries","readdir","entry","saveCredentialProfile","loadCredentialProfile","PLACEHOLDER_DESCRIPTION","parseArtifactSelection","raw","ARTIFACT_TYPES","requested","part","unknown","resolveHeadlessInput","options","defaults","targetDir","name","apiName","inferApiName","API_NAME_PATTERN","API_NAME_HINT","description","developerBusinessId","developerEnvironment","resolveEnvironment","isEnvironment","value","ENVIRONMENTS","runHeadlessCreate","deps","input","err","precheck","conflict","artifactSummary","createCommand","program","ENVIRONMENTS","ARTIFACT_TYPES","options","parentDir","globalCreds","loadGlobalCredentials","defaultBusinessId","defaultEnvironment","suppliedFlags","value","runHeadlessCreate","precheckTargetDir","createPlugin","text","code","waitUntilExit","render","createElement","CreateUI","createElement","render","useCallback","useEffect","useRef","useState","Box","Text","useInput","PluginValidationError","watch","createServer","join","WebSocketServer","createReadStream","realpathSync","access","readdir","readFile","realpath","stat","dirname","extname","join","resolve","sep","fileURLToPath","STRIPPED_RESPONSE_HEADERS","sanitizeUpstreamHeaders","headers","filtered","key","value","lower","MAX_PROXY_BYTES","CACHE_TTL_MS","CACHE_MAX_ENTRIES","ProxyResponseTooLargeError","bytesRead","limit","readBodyWithLimit","response","body","chunks","total","chunk","toCachedResponse","createProxyCache","options","onChange","enabled","_key","fetcher","cache","emitChange","evict","existing","oldest","pending","error","MIME_TYPES","mkdir","readFile","writeFile","join","loadConfig","outputDir","content","saveConfig","config","ENCRYPTION_API_DEFAULTS","resolveWizardBase","target","forced","spawn","writeFile","rm","mkdtemp","access","join","tmpdir","python_requirements_default","parseRequirementsFile","content","line","resolvePythonBinary","runtime","match","major","minor","toStepInputValue","raw","coerceStepInputValue","value","toStepInputValue","normalizeStepInputs","inputs","name","WRAPPER_SCRIPT","DEFAULT_TIMEOUT","VENV_DIR","join","SUPPORTED_RUNTIMES","isSupportedRuntime","runtime","VENV_PACKAGES","parseRequirementsFile","python_requirements_default","venvReady","MIN_PYTHON","meetsMinimum","major","minor","formatVersion","version","probePython","bin","resolve","proc","spawn","out","chunk","code","match","findSystemPython","preferred","resolvePythonBinary","candidates","tried","runCommand","args","onLine","reject","pipeLines","source","stream","captured","buffer","idx","line","stderrCaptured","tail","detail","venvInstallListeners","ensureVenv","listener","listeners","emit","event","l","venvPython","reusable","access","existing","rm","systemPython","err","message","parseResult","stdout","startMarker","endMarker","startIdx","endIdx","userStdout","jsonStr","result","failedExecutionResult","error","executePythonStep","params","timeout","pythonBin","start","tmpDir","mkdtemp","tmpdir","wrapperPath","scriptPath","writeFile","env","exitCode","stderr","stdoutChunks","stderrChunks","settled","timer","finish","durationMs","base","TEXT_EXTENSIONS","CRYPTO_ALG","CRYPTO_VERSION","deserializeEnvelope","encrypt","serializeEnvelope","proxyLogEntryToString","entry","cache","upstream","SOURCE_FILE_MAX_BYTES","SKIP_FILES","isLocalHost","host","hostname","PROXY_ALLOWED_DOMAINS","isAllowedWizardTarget","target","url","domain","isAllowedProxyTarget","isLocalOrigin","origin","resolveSafePath","realPluginDir","relParam","rel","abs","resolve","sep","realAbs","realpath","isInsideSkippedDir","pluginDir","segment","SKIP_DIRS","getViewerPath","filename","fileURLToPath","join","dirname","extractUpstreamStatus","upstreamPath","headers","body","parsed","fileExists","filePath","access","createRequestHandler","viewerPath","createServerLog","createProxyLog","credentialsRef","activeProfileRef","outputDir","broadcast","onProxyCacheChange","lastPathRef","cacheEnabled","proxyCache","createProxyCache","realpathSync","req","res","profiles","listCredentialProfiles","chunks","chunk","profileName","creds","loadGlobalCredentials","loadCredentialProfile","active","currentConfig","loadConfig","saveConfig","bundlePath","content","readFile","stepParams","normalizeStepInputs","event","result","executePythonStep","envelope","encrypt","serialized","serializeEnvelope","err","parseError","deserializeEnvelope","bufLen","b64","checks","CRYPTO_VERSION","CRYPTO_ALG","c","rawTarget","wizardBase","resolveWizardBase","upstreamUrl","method","_wizardHost","_encTarget","wizardForwardHeaders","resolvedBody","upstream","message","wizardResponseHeaders","sanitizeUpstreamHeaders","wizardBody","proxyTarget","_drop","forwardHeaders","cacheKey","cached","fromCache","responseHeaders","responseBody","readBodyWithLimit","MAX_PROXY_BYTES","dirEntries","readdir","entries","entry","kind","stats","stat","a","b","normalizedPath","detail","ext","extname","explicitMime","MIME_TYPES","isKnownText","TEXT_EXTENSIONS","contentType","createReadStream","resolvedPath","mimeType","ProxyResponseTooLargeError","launch","createRequire","mkdirSync","readFile","dirname","join","fileURLToPath","CDP","CSP_HEADERS","KIZEN_DOMAINS","isKizenUrl","url","hostname","d","installDockIcon","client","iconPath","icon","launchChromeViewer","opts","baseUrl","chrome","cdpPort","cookieTimer","mainTargetId","reconnectTimer","reconnectAttempt","killed","dbg","msg","vb","clearCookieTimer","isNewTabUrl","setupClient","c","rawParams","params","requestId","request","responseHeaders","responseStatusCode","filtered","rewroteSetCookie","h","patched","cookie","body","base64Encoded","e","e2","cookies","raw","bare","handleTarget","targetInfo","scheduleReconnect","delay","attemptNumber","MAX_CDP_ATTEMPTS","CDP_ATTEMPT_DELAY_MS","attempt","r","warning","useCallback","useState","useLogHistory","limit","history","setHistory","append","message","h","useCallback","useEffect","useState","Box","Text","useInput","jsx","jsxs","FIELDS","FIELD_LABELS","Hint","text","Text","CredentialSetupUI","initialMode","showProfileManager","onComplete","onCancel","phase","setPhase","useState","inputBuffer","setInputBuffer","error","setError","activeProfileName","setActiveProfileName","handleModeChosen","useCallback","mode","handleProfileChosen","profile","profiles","listCredentialProfiles","existing","loadGlobalCredentials","loadCredentialProfile","envCursor","ENVIRONMENTS","handleSave","values","environment","credentials","saveCredentialProfile","DEFAULT_PROFILE_NAME","err","useInput","input","key","loadProfileList","cursor","addNewIdx","totalItems","selected","nameBuffer","existingProfiles","trimmed","p","field","fieldName","prev","updatedValues","prevField","nextField","useEffect","label","Box","AppHeader","opt","i","nameError","activeField","isEnvField","profileLabel","GLOBAL_CREDENTIALS_PATH","name","isActive","displayValue","env","isSelected","jsx","jsxs","SKIP_WATCH_PREFIXES","DevUI","port","pluginDir","outputDir","initialCredentials","initialCredentialMode","initialActiveProfile","initialLastPath","debug","verbose","autoViewer","cacheEnabled","credentialsRef","useRef","activeProfileRef","lastPathRef","credMode","setCredMode","useState","credentialMode","setCredentialMode","status","setStatus","errorMessage","setErrorMessage","serverLogHistory","appendServerLog","useLogHistory","buildLogHistory","appendBuildLog","cdpLogHistory","appendCdpLog","proxyLogHistory","setProxyLogHistory","buildStatus","setBuildStatus","buildError","setBuildError","buildIssues","setBuildIssues","lastBuilt","setLastBuilt","lastBundleSize","setLastBundleSize","wsClientCount","setWsClientCount","proxyCacheSize","setProxyCacheSize","proxyCacheHits","setProxyCacheHits","proxyCacheMisses","setProxyCacheMisses","buildingRef","viewerLaunchedRef","chromeHandleRef","debounceTimerRef","wsClientsRef","pendingMessagesRef","broadcast","useCallback","msg","json","pruned","client","createServerLog","launchChromeViewerCb","launchChromeViewer","join","handle","useEffect","onExit","useInput","input","key","handleCredentialsDone","result","profile","saveConfig","createProxyLog","entry","h","proxyLogEntryToString","n","createBuildLog","message","triggerBuild","runBuild","bundleSize","formatBytes","err","PluginValidationError","watcher","watch","_","filename","normalized","prefix","viewerPath","getViewerPath","fileExists","viewerBuilt","handler","createRequestHandler","server","createServer","wss","WebSocketServer","ws","CredentialSetupUI","elapsedSeconds","elapsedLabel","buildErrorCount","issue","Box","AppHeader","Text","Spinner","ValidationIssues","log","index","i","runSetupUI","initialMode","resolve","unmountFn","handleComplete","result","unmount","render","createElement","CredentialSetupUI","devCommand","program","options","port","pluginDir","outputDir","ensureGitignore","credentials","credentialMode","activeCredentialProfile","lastPath","loadConfig","loadCredentialsFromFile","config","loadCredentialProfile","loadGlobalCredentials","profile","saveConfig","verbose","debug","autoViewer","cacheEnabled","waitUntilExit","DevUI","createElement","render","useCallback","useEffect","useState","Box","Text","useApp","useInput","encrypt","serializeEnvelope","isConnRefused","err","e","authHeaders","credentials","wizardFetch","wizardBase","path","init","readJsonSafe","res","text","parsed","fetchPublicKey","ctx","apiName","resolveWizardBase","data","errMsg","encryptLocally","publicKeyPem","value","envelope","encrypt","serialized","serializeEnvelope","encryptRemote","encryptSecret","onPhase","publicKey","spawn","platform","clipboardCommands","CLIPBOARD_TIMEOUT_MS","runClipboardCommand","text","cmd","args","resolve","child","spawned","settled","finish","ok","timer","code","copyToClipboard","command","Fragment","jsx","jsxs","Hint","text","Text","EncryptUI","ctx","stageDefaulted","credentialsPath","initialApiName","defaultApiName","initialValue","onDone","app","useApp","phase","setPhase","useState","credentials","setCredentials","apiName","setApiName","secret","setSecret","fail","useCallback","err","runEncryption","creds","name","value","envelopeValue","encryptSecret","p","envelope","copied","copyToClipboard","proceed","handleProfileChosen","profile","loadGlobalCredentials","loadCredentialProfile","useEffect","loadCredentialsFromFile","profiles","listCredentialProfiles","only","useInput","input","key","cursor","selected","buffer","modeLabel","stageLabel","frame","children","Box","AppHeader","Spinner","i","readFile","writeFile","join","envelopeObject","value","compactEnvelope","writeEnvelopeFile","path","DEFAULT_STAGE","isValidStage","stage","invalidStageMessage","resolveStage","defaultStageNotice","readManifestDefaults","cwd","raw","parsed","manifest","apiName","stripTrailingNewlines","readStdin","chunks","chunk","runHeadless","ctx","options","defaults","stageWasDefaulted","deps","credentials","apiName","defaultStageNotice","value","stripTrailingNewlines","envelopeValue","compactEnvelope","err","encryptCommand","program","options","isValidStage","invalidStageMessage","defaults","readManifestDefaults","stage","stageWasDefaulted","resolveStage","ctx","runHeadless","loadCredentialsFromFile","loadGlobalCredentials","encryptSecret","readStdin","text","writeEnvelopeFile","code","err","envelopeValue","waitUntilExit","render","createElement","EncryptUI","value","VALID_ICONS","VALID_ICONS_LIST","CUSTOM_ICON_NAMES","ALL_VALID_ICONS_LIST","iconsCommand","program","name","ALL_VALID_ICONS_LIST","mkdir","writeFile","readFile","join","SENSITIVE_FIELDS","redactServices","services","svc","s","redacted","k","buildTree","files","root","file","parts","node","part","i","next","sortTreeChildren","a","b","fileId","path","esc","str","fileExt","idx","LANG_MAP","mdLang","mdFence","content","longestRun","max","m","renderTextTree","prefix","sorted","child","isLast","connector","childPrefix","LICENSE_FILE","filterSourceFiles","f","buildFilteredConfig","manifest","v","IMAGE_MIME","renderTree","renderFileSection","body","generateMarkdown","filtered","name","version","description","sourceFiles","lines","configJson","configFence","fence","generateHtml","treeHtml","fileSections","EXAMPLES_DIR","join","GLOBAL_CREDENTIALS_DIR","reportCommand","program","options","pluginDir","manifest","raw","readFile","parsed","apiName","htmlPath","mdPath","files","readLocalFiles","mkdir","writeFile","generateHtml","generateMarkdown","readVersion","pkgPath","join","dirname","fileURLToPath","readFileSync","createProgram","program","Command","createCommand","buildCommand","devCommand","encryptCommand","reportCommand","iconsCommand","createProgram"]}
|
|
1
|
+
{"version":3,"sources":["../src/program.ts","../src/commands/build.ts","../src/ui/BuildUI.tsx","../src/lib/runBuild.ts","../src/lib/readFiles.ts","../shared/lib/formatBytes.ts","../src/ui/AppHeader.tsx","../src/ui/Logo.tsx","../src/ui/Spinner.tsx","../src/ui/ValidationIssues.tsx","../src/lib/gitignore.ts","../src/commands/create.ts","../src/ui/CreateUI.tsx","../src/lib/createPlugin.ts","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/floatingFrames/helloFrame/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/floatingFrames/helloFrame/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/floatingFrames/helloFrame/styles.css?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/blocks/helloBlock/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/blocks/helloBlock/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/blocks/helloBlock/styles.css?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/dataAdornments/helloAdornment/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/dataAdornments/helloAdornment/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/pages/helloPage/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/pages/helloPage/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/pages/helloPage/styles.css?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/pages/helloPage/eventScripts/greet.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/toolbarItems/helloToolbarItem/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/toolbarItems/helloToolbarItem/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/objectSettingsItems/helloObjectSettingsItem/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/objectSettingsItems/helloObjectSettingsItem/script.js?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/actions/helloAction/config.json?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/artifacts/actions/helloAction/script.js?raw","../src/lib/createArtifacts.ts","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/github/copilot-instructions.md?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/github/instructions/security.instructions.md?raw","raw:/home/runner/work/app-builder-cli/app-builder-cli/src/templates/github/instructions/version-discipline.instructions.md?raw","../src/lib/createCopilotFiles.ts","../src/lib/createThumbnail.ts","../src/lib/createForm.ts","../src/lib/credentials.ts","../shared/lib/credentials.ts","../src/lib/createHeadless.ts","../src/commands/dev.ts","../src/ui/DevUI.tsx","../src/server/requestHandler.ts","../src/lib/proxyCache.ts","../src/lib/constants.ts","../src/lib/config.ts","../src/lib/wizardUrl.ts","../src/server/pythonExecutor.ts","../src/server/python-requirements.txt","../src/lib/pythonRuntime.ts","../shared/lib/execution.ts","../shared/lib/fileExtensions.ts","../shared/lib/proxy.ts","../src/chrome/launcher.ts","../src/hooks/useLogHistory.ts","../src/ui/CredentialSetupUI.tsx","../src/commands/encrypt.ts","../src/ui/EncryptUI.tsx","../src/lib/encryptionClient.ts","../src/lib/clipboard.ts","../src/lib/encryptHelpers.ts","../src/lib/encryptHeadless.ts","../shared/lib/validIcons.ts","../src/commands/icons.ts","../src/commands/report.ts","../src/lib/reportHelpers.ts","../src/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Command } from 'commander';\nimport { buildCommand } from './commands/build.js';\nimport { createCommand } from './commands/create.js';\nimport { devCommand } from './commands/dev.js';\nimport { encryptCommand } from './commands/encrypt.js';\nimport { iconsCommand } from './commands/icons.js';\nimport { reportCommand } from './commands/report.js';\n\nfunction readVersion(): string {\n const pkgPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as { version: string };\n\n return pkg.version;\n}\n\nexport function createProgram(): Command {\n const program = new Command();\n\n program.name('appbuilder').description('Kizen plugin app builder').version(readVersion());\n\n createCommand(program);\n\n buildCommand(program);\n\n devCommand(program);\n\n encryptCommand(program);\n\n reportCommand(program);\n\n iconsCommand(program);\n\n return program;\n}\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { BuildUI } from '../ui/BuildUI.js';\nimport { ensureGitignore } from '../lib/gitignore.js';\n\nexport function buildCommand(program: Command): void {\n program\n .command('build')\n .description('Bundle the plugin app into .kizenapp directory')\n .action(async () => {\n const pluginDir = process.cwd();\n const outputDir = `${pluginDir}/.kizenapp`;\n\n ensureGitignore(pluginDir);\n\n const { waitUntilExit } = render(createElement(BuildUI, { outputDir, pluginDir }));\n\n await waitUntilExit();\n });\n}\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { Box, Text, useApp } from 'ink';\nimport { PluginValidationError } from '@kizenapps/packager';\nimport type { ValidationIssue } from '@kizenapps/packager';\nimport { runBuild } from '../lib/runBuild.js';\nimport type { BuildStepName } from '../lib/runBuild.js';\nimport { formatBytes } from '../../shared/lib/formatBytes.js';\nimport { AppHeader } from './AppHeader.js';\nimport { Spinner } from './Spinner.js';\nimport { ValidationIssues } from './ValidationIssues.js';\n\ntype BuildStep = BuildStepName | 'done';\n\ninterface BuildUIProps {\n outputDir: string;\n pluginDir: string;\n}\n\nconst STEPS: BuildStepName[] = [\n 'creating-dir',\n 'reading-files',\n 'validating',\n 'minifying',\n 'packaging',\n 'writing-bundle',\n];\n\nconst STEP_LABELS: Record<BuildStepName, string> = {\n 'creating-dir': 'Creating .kizenapp directory',\n 'reading-files': 'Reading plugin files',\n validating: 'Validating plugin app',\n minifying: 'Minifying scripts',\n packaging: 'Packaging plugin',\n 'writing-bundle': 'Writing bundle.json',\n};\n\nexport const BuildUI: FC<BuildUIProps> = ({ outputDir, pluginDir }) => {\n const app = useApp();\n const [step, setStep] = useState<BuildStep>('creating-dir');\n const [failed, setFailed] = useState(false);\n const [issues, setIssues] = useState<ValidationIssue[] | null>(null);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [bundleSize, setBundleSize] = useState<number | null>(null);\n\n useEffect(() => {\n void runBuild(pluginDir, outputDir, setStep)\n .then(({ bundleSize: size }) => {\n setBundleSize(size);\n setStep('done');\n })\n .catch((err: unknown) => {\n if (err instanceof PluginValidationError) {\n setIssues(err.issues);\n } else {\n setErrorMessage(err instanceof Error ? err.message : String(err));\n }\n\n // Leave `step` on the step that was running so the ✗ lands on it.\n setFailed(true);\n process.exitCode = 1;\n });\n }, [outputDir, pluginDir]);\n\n // Exit only once the terminal frame has been committed and written to the\n // terminal. Calling app.exit() in the same tick as the state updates would\n // unmount ink before it paints the done/error frame, leaving the spinner as\n // the last thing on screen.\n useEffect(() => {\n if (step === 'done' || failed) {\n app.exit();\n }\n }, [step, failed, app]);\n\n const currentIndex = STEPS.indexOf(step as BuildStepName);\n const isDone = step === 'done';\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2}>\n <AppHeader marginBottom={1} />\n\n <Box flexDirection=\"column\" gap={0}>\n {STEPS.map((s, i) => {\n const isActive = step === s;\n const isStepDone = isDone || currentIndex > i;\n const isFailed = failed && i === currentIndex;\n\n return (\n <Box key={s} gap={1}>\n {isFailed ? (\n <Text color=\"red\">✗ {STEP_LABELS[s]}</Text>\n ) : isStepDone ? (\n <Text color=\"green\">✓ {STEP_LABELS[s]}</Text>\n ) : isActive ? (\n <>\n <Spinner />\n <Text>{STEP_LABELS[s]}</Text>\n </>\n ) : (\n <Text dimColor> {STEP_LABELS[s]}</Text>\n )}\n </Box>\n );\n })}\n\n {isDone && bundleSize !== null && (\n <Box marginTop={1} gap={1}>\n <Text color=\"green\">✓ bundle — {formatBytes(bundleSize)}</Text>\n </Box>\n )}\n\n {issues !== null && <ValidationIssues issues={issues} />}\n\n {errorMessage !== null && (\n <Box marginTop={1} borderStyle=\"single\" borderColor=\"red\" paddingX={1}>\n <Text color=\"red\">{errorMessage}</Text>\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n PluginValidationError,\n packagePlugin,\n parseManifestFromFiles,\n transformDeployablePlugin,\n transformFiles,\n validatePluginApp,\n} from '@kizenapps/packager';\nimport type { DeployablePlugin } from '@kizenapps/packager';\nimport { readLocalFiles } from './readFiles.js';\n\nexport type BuildStepName =\n | 'creating-dir'\n | 'reading-files'\n | 'validating'\n | 'minifying'\n | 'packaging'\n | 'writing-bundle';\n\ninterface ReleaseNote {\n version: string;\n notes: string;\n}\n\ntype SerializableDeployablePlugin = Omit<DeployablePlugin, 'thumbnail' | 'kznFile'> & {\n thumbnail: string | null;\n kznFile: string | null;\n allReleaseNotes: ReleaseNote[];\n};\n\nconst serializePlugin = (\n plugin: DeployablePlugin,\n allReleaseNotes: ReleaseNote[],\n): SerializableDeployablePlugin => ({\n ...plugin,\n thumbnail: plugin.thumbnail ? Buffer.from(plugin.thumbnail).toString('base64') : null,\n kznFile: plugin.kznFile ? Buffer.from(plugin.kznFile).toString('base64') : null,\n allReleaseNotes,\n});\n\nexport interface BuildResult {\n bundleSize: number;\n}\n\nexport async function runBuild(\n pluginDir: string,\n outputDir: string,\n onStep?: (step: BuildStepName) => void,\n): Promise<BuildResult> {\n await mkdir(outputDir, { recursive: true });\n\n onStep?.('reading-files');\n\n const files = await readLocalFiles(pluginDir);\n\n onStep?.('validating');\n\n const issues = validatePluginApp(files);\n\n if (issues.some((issue) => issue.severity === 'error')) {\n throw new PluginValidationError(issues);\n }\n\n onStep?.('minifying');\n\n const minified = await transformFiles(files);\n\n onStep?.('packaging');\n\n const manifests = parseManifestFromFiles(minified);\n const packaged = packagePlugin(minified, manifests);\n const deployable = Object.values(packaged).map(transformDeployablePlugin);\n\n onStep?.('writing-bundle');\n\n const bundle = deployable.map((plugin) => {\n const notesDir = plugin.release_notes_directory?.replace(/\\/$/, '');\n const allReleaseNotes: ReleaseNote[] = notesDir\n ? files\n .filter((f) => f.path.startsWith(notesDir + '/') && f.path.endsWith('.md') && f.content)\n .map((f) => ({\n version: f.path.slice(f.path.lastIndexOf('/') + 1, -3),\n notes: f.content,\n }))\n .sort((a, b) => b.version.localeCompare(a.version, undefined, { numeric: true }))\n : [];\n\n return serializePlugin(plugin, allReleaseNotes);\n });\n\n const jsonStr = JSON.stringify(bundle, null, 2);\n\n // Report the size of the plugin bundle excluding the informational release\n // notes, so \"bundle: 12KB\" reflects actual plugin code rather than long\n // markdown changelogs.\n const stripReleaseNotes = (key: string, value: unknown): unknown =>\n key === 'allReleaseNotes' ? undefined : value;\n const bundleSize = Buffer.byteLength(JSON.stringify(bundle, stripReleaseNotes, 2), 'utf-8');\n\n await writeFile(join(outputDir, 'bundle.json'), jsonStr, 'utf-8');\n\n return { bundleSize };\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { FileContent } from '@kizenapps/packager';\n\nconst IMAGE_EXTENSIONS = new Set(['.png', '.svg']);\nconst BINARY_EXTENSIONS = new Set(['.kzn']);\nconst SKIP_FILES = new Set(['.DS_Store']);\n\nexport const SKIP_DIRS = new Set([\n 'node_modules',\n '.git',\n '.kizenapp',\n '.github',\n '.claude',\n '__pycache__',\n]);\n\n// a NUL in the first 8 KB means binary\nconst BINARY_SNIFF_BYTES = 8000;\n\nfunction looksBinary(buf: Buffer): boolean {\n return buf.subarray(0, BINARY_SNIFF_BYTES).includes(0);\n}\n\nexport interface ReadLocalFilesOptions {\n detectBinaryByContent?: boolean;\n}\n\nasync function walk(dir: string, rootDir: string): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const paths: string[] = [];\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) {\n continue;\n }\n\n paths.push(...(await walk(join(dir, entry.name), rootDir)));\n } else if (entry.isFile()) {\n if (!SKIP_FILES.has(entry.name)) {\n paths.push(join(dir, entry.name));\n }\n }\n }\n\n return paths;\n}\n\nexport async function readLocalFiles(\n rootDir: string,\n { detectBinaryByContent = false }: ReadLocalFilesOptions = {},\n): Promise<FileContent[]> {\n const absolutePaths = await walk(rootDir, rootDir);\n\n return Promise.all(\n absolutePaths.map(async (absPath): Promise<FileContent> => {\n const relPath = relative(rootDir, absPath).split('\\\\').join('/');\n const dotIndex = relPath.lastIndexOf('.');\n const ext = dotIndex >= 0 ? relPath.slice(dotIndex).toLowerCase() : '';\n\n if (IMAGE_EXTENSIONS.has(ext)) {\n const buf = await readFile(absPath);\n\n return { path: relPath, content: '', base64Image: buf.toString('base64') };\n }\n\n const buf = await readFile(absPath);\n\n if (BINARY_EXTENSIONS.has(ext) || (detectBinaryByContent && looksBinary(buf))) {\n return { path: relPath, content: '', binaryData: buf };\n }\n\n return { path: relPath, content: buf.toString('utf-8') };\n }),\n );\n}\n","export function formatBytes(n: number): string {\n if (n < 1024) {\n return `${String(n)} B`;\n }\n\n if (n < 1024 * 1024) {\n return `${(n / 1024).toFixed(1)} KB`;\n }\n\n return `${(n / (1024 * 1024)).toFixed(2)} MB`;\n}\n","import type { FC } from 'react';\nimport { Box, Text } from 'ink';\nimport { Logo } from './Logo.js';\n\ninterface AppHeaderProps {\n marginBottom?: number;\n}\n\nexport const AppHeader: FC<AppHeaderProps> = ({ marginBottom = 0 }) => (\n <>\n <Logo />\n <Box flexDirection=\"column\" marginTop={1} marginBottom={marginBottom}>\n <Text bold color=\"cyan\">\n Kizen App Development Toolkit\n </Text>\n </Box>\n </>\n);\n","import type { FC } from 'react';\nimport { Box, Text } from 'ink';\n\nconst LOGO_LINES = [\n ' :::::::: ',\n ' :::::: ::::::::::: ',\n ' :::::: :::::::::: ',\n ' :::::: :::::: ::::::: ',\n ' ::::: :::::: ::::::::::::::::: ',\n ' ::::: ::::: ::::::::::::::::::: ',\n ' ::::: ::::: :::::: ::::: ',\n ':::: ::::: ::: ::::: :: ',\n '::::: :::::: :::::::::: ',\n '::::: :::::: ::::::::::: ',\n ' ::::: ::: ::::::: ',\n ' ::::::: ::: ::::: ',\n ' ::::::::::: :::::: :::::',\n ' :::::::::: :::::: :::::',\n ' :: ::::: ::: ::::: ::::',\n ' ::::: :::::: ::::: ::::: ::: ',\n ' ::::::::::::::::::: ::::: ::::: ',\n ' ::::::::::::::::: ::::: ::::: ',\n ' ::::::::: :::::: :::::: ',\n ' :::::::::: :::::: ',\n ' ::::::::::: :::::: ',\n ' :::::::: ',\n];\n\nexport const Logo: FC = () => (\n <Box flexDirection=\"column\">\n {LOGO_LINES.map((line, i) => (\n <Text key={i} color=\"cyan\">\n {line}\n </Text>\n ))}\n </Box>\n);\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { Text } from 'ink';\n\nexport const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nexport const Spinner: FC = () => {\n const [frame, setFrame] = useState(0);\n\n useEffect(() => {\n const id = setInterval(() => {\n setFrame((prev) => (prev + 1) % SPINNER_FRAMES.length);\n }, 80);\n\n return () => {\n clearInterval(id);\n };\n }, []);\n\n return <Text color=\"cyan\">{SPINNER_FRAMES[frame] ?? '⠋'}</Text>;\n};\n","import type { FC } from 'react';\nimport { Box, Text } from 'ink';\nimport type { ValidationIssue } from '@kizenapps/packager';\n\nconst groupIssuesByPath = (issues: ValidationIssue[]): Map<string, ValidationIssue[]> => {\n const groups = new Map<string, ValidationIssue[]>();\n\n for (const issue of issues) {\n const key = issue.path ?? issue.pluginApiName ?? 'general';\n const group = groups.get(key) ?? [];\n\n group.push(issue);\n groups.set(key, group);\n }\n\n return groups;\n};\n\ninterface ValidationIssuesProps {\n issues: ValidationIssue[];\n}\n\nexport const ValidationIssues: FC<ValidationIssuesProps> = ({ issues }) => {\n // The build only throws on error-severity issues, but `issues` also carries\n // any warnings; the header must count errors only, not the whole array.\n const errorCount = issues.filter((issue) => issue.severity === 'error').length;\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"red\">\n ✗ {errorCount} validation {errorCount === 1 ? 'error' : 'errors'}\n </Text>\n\n {[...groupIssuesByPath(issues)].map(([path, group]) => (\n <Box key={path} flexDirection=\"column\" marginTop={1}>\n <Text bold>{path}</Text>\n\n {group.map((issue, i) => (\n <Box key={`${issue.rule}-${String(i)}`} paddingLeft={2}>\n <Text color={issue.severity === 'error' ? 'red' : 'yellow'}>\n {issue.severity === 'error' ? '✗' : '⚠'} {issue.message}{' '}\n <Text dimColor>({issue.rule})</Text>\n </Text>\n </Box>\n ))}\n </Box>\n ))}\n </Box>\n );\n};\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport function ensureGitignore(projectDir: string): void {\n const gitignorePath = path.join(projectDir, '.gitignore');\n const entry = '.kizenapp/';\n\n let contents = '';\n\n if (fs.existsSync(gitignorePath)) {\n contents = fs.readFileSync(gitignorePath, 'utf8');\n\n const lines = contents.split('\\n').map((l) => l.trim());\n\n if (lines.includes(entry) || lines.includes('.kizenapp')) {\n return;\n }\n }\n\n const addition = contents.endsWith('\\n') ? entry + '\\n' : '\\n' + entry + '\\n';\n\n fs.writeFileSync(gitignorePath, contents + addition);\n}\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { CreateUI } from '../ui/CreateUI.js';\nimport { loadGlobalCredentials } from '../lib/credentials.js';\nimport { createPlugin, precheckTargetDir } from '../lib/createPlugin.js';\nimport { runHeadlessCreate } from '../lib/createHeadless.js';\nimport type { CreateOptions } from '../lib/createHeadless.js';\nimport { ARTIFACT_TYPES } from '../lib/createArtifacts.js';\nimport { ENVIRONMENTS } from '../../shared/lib/credentials.js';\n\nexport function createCommand(program: Command): void {\n program\n .command('create')\n .description('Scaffold a new Kizen plugin project')\n .option('-n, --name <name>', 'plugin display name (implies a non-interactive run)')\n .option('-a, --api-name <name>', 'plugin api_name (inferred from --name when omitted)')\n .option('-d, --description <text>', 'plugin description')\n .option('-l, --external-link <url>', 'external link shown on the plugin listing')\n .option('-b, --business-id <id>', 'developer business id (defaults to saved credentials)')\n .option(\n '-e, --environment <env>',\n `environment the business id belongs to: ${ENVIRONMENTS.join(', ')} (defaults to saved credentials)`,\n )\n .option(\n '--artifacts <list>',\n `comma-separated artifact types, or \"all\" / \"none\" (default: all). Types: ${ARTIFACT_TYPES.join(', ')}`,\n )\n .action(async (options: CreateOptions) => {\n const parentDir = process.cwd();\n const globalCreds = await loadGlobalCredentials();\n const defaultBusinessId = globalCreds?.businessId ?? '';\n const defaultEnvironment = globalCreds?.environment ?? 'go';\n\n const suppliedFlags = Object.values(options).some((value) => value !== undefined);\n\n const isNonInteractive = !process.stdin.isTTY || !process.stdout.isTTY || suppliedFlags;\n\n if (isNonInteractive) {\n await runHeadlessCreate(\n options,\n { businessId: defaultBusinessId, environment: defaultEnvironment },\n parentDir,\n {\n precheckTargetDir,\n createPlugin,\n writeStdout: (text) => {\n process.stdout.write(text);\n },\n writeStderr: (text) => {\n process.stderr.write(text);\n },\n setExitCode: (code) => {\n process.exitCode = code;\n },\n },\n );\n\n return;\n }\n\n const { waitUntilExit } = render(\n createElement(CreateUI, { parentDir, defaultBusinessId, defaultEnvironment }),\n { exitOnCtrlC: false },\n );\n\n await waitUntilExit();\n });\n}\n","import type { FC } from 'react';\nimport { useCallback, useState } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport { join } from 'node:path';\nimport {\n buildManifest,\n createPlugin,\n findAvailableSubDir,\n precheckTargetDir,\n} from '../lib/createPlugin.js';\nimport type { PrecheckResult } from '../lib/createPlugin.js';\nimport {\n emptyValues,\n FIELD_LABELS,\n FIELDS,\n inferApiName,\n normalizeFieldValue,\n REQUIRED_FIELDS,\n toggleArtifactSelection,\n validateField,\n} from '../lib/createForm.js';\nimport type { FieldValues } from '../lib/createForm.js';\nimport { ARTIFACT_LABELS, ARTIFACT_TYPES } from '../lib/createArtifacts.js';\nimport type { ArtifactType } from '../lib/createArtifacts.js';\nimport type { Environment } from '../../shared/lib/credentials.js';\nimport { AppHeader } from './AppHeader.js';\n\ntype Mode = 'in-place' | 'sub-dir';\n\ntype Phase =\n | { type: 'target-select'; cursor: 0 | 1 }\n | { type: 'precheck-error'; targetDir: string; reason: PrecheckResult }\n | { type: 'field-entry'; field: number; values: FieldValues; fieldError?: string }\n | {\n type: 'artifact-select';\n values: FieldValues;\n cursor: number;\n selected: readonly ArtifactType[];\n }\n | { type: 'resolving-target' }\n | { type: 'confirm'; values: FieldValues; artifacts: readonly ArtifactType[] }\n | { type: 'writing' }\n | { type: 'done'; targetDir: string }\n | { type: 'error'; message: string };\n\ninterface CreateUIProps {\n parentDir: string;\n defaultBusinessId: string;\n defaultEnvironment: Environment;\n}\n\nconst Hint: FC<{ text: string }> = ({ text }) => <Text dimColor>{text}</Text>;\n\nexport const CreateUI: FC<CreateUIProps> = ({\n parentDir,\n defaultBusinessId,\n defaultEnvironment,\n}) => {\n const app = useApp();\n const [phase, setPhase] = useState<Phase>({ type: 'target-select', cursor: 0 });\n const [mode, setMode] = useState<Mode>('in-place');\n const [values, setValues] = useState<FieldValues>(() => emptyValues(defaultBusinessId));\n const [artifacts, setArtifacts] = useState<readonly ArtifactType[]>(() => [...ARTIFACT_TYPES]);\n const [inputBuffer, setInputBuffer] = useState('');\n const [targetDir, setTargetDir] = useState<string>(parentDir);\n\n const enterFieldEntry = useCallback((nextMode: Mode, initialValues: FieldValues): void => {\n setMode(nextMode);\n\n setInputBuffer(initialValues.name);\n\n setPhase({ type: 'field-entry', field: 0, values: initialValues });\n }, []);\n\n const runPrecheck = useCallback(\n async (dir: string): Promise<void> => {\n const result = await precheckTargetDir(dir);\n\n if (result !== 'ok') {\n setPhase({ type: 'precheck-error', targetDir: dir, reason: result });\n\n return;\n }\n\n setTargetDir(dir);\n\n enterFieldEntry('in-place', values);\n },\n [values, enterFieldEntry],\n );\n\n const resolveSubDirAndConfirm = useCallback(\n async (finalValues: FieldValues, artifacts: readonly ArtifactType[]): Promise<void> => {\n try {\n const dir = await findAvailableSubDir(parentDir, finalValues.apiName);\n\n setTargetDir(dir);\n\n setPhase({ type: 'confirm', values: finalValues, artifacts });\n } catch (err) {\n setPhase({\n type: 'error',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n },\n [parentDir],\n );\n\n const runWrite = useCallback(\n async (\n finalValues: FieldValues,\n dir: string,\n artifacts: readonly ArtifactType[],\n ): Promise<void> => {\n try {\n await createPlugin({\n targetDir: dir,\n name: finalValues.name,\n apiName: finalValues.apiName,\n externalLink: finalValues.externalLink,\n description: finalValues.description,\n developerBusinessId: finalValues.developerBusinessId,\n developerEnvironment: defaultEnvironment,\n artifacts,\n });\n\n setPhase({ type: 'done', targetDir: dir });\n } catch (err) {\n setPhase({\n type: 'error',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n },\n [defaultEnvironment],\n );\n\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n app.exit();\n\n return;\n }\n\n if (phase.type === 'target-select') {\n if (key.upArrow) {\n setPhase({ type: 'target-select', cursor: 0 });\n } else if (key.downArrow) {\n setPhase({ type: 'target-select', cursor: 1 });\n } else if (key.return) {\n if (phase.cursor === 0) {\n void runPrecheck(parentDir);\n } else {\n enterFieldEntry('sub-dir', values);\n }\n } else if (key.escape) {\n app.exit();\n }\n\n return;\n }\n\n if (phase.type === 'precheck-error') {\n if (key.return || key.escape) {\n app.exit();\n }\n\n return;\n }\n\n if (phase.type === 'field-entry') {\n const { field, values: current } = phase;\n const fieldName = FIELDS[field];\n\n if (!fieldName) {\n return;\n }\n\n if (key.escape) {\n app.exit();\n\n return;\n }\n\n if (key.backspace || key.delete) {\n setInputBuffer((prev) => prev.slice(0, -1));\n\n return;\n }\n\n if (key.upArrow && field > 0) {\n const updated = { ...current, [fieldName]: inputBuffer };\n const prevField = field - 1;\n const prevName = FIELDS[prevField];\n\n setPhase({ type: 'field-entry', field: prevField, values: updated });\n\n setValues(updated);\n\n setInputBuffer(prevName ? updated[prevName] : '');\n\n return;\n }\n\n if (key.return || key.tab || key.downArrow) {\n const fieldError = validateField(fieldName, inputBuffer);\n\n if (fieldError !== undefined) {\n setPhase({ type: 'field-entry', field, values: current, fieldError });\n\n return;\n }\n\n const valueToStore = normalizeFieldValue(fieldName, inputBuffer);\n const updated = { ...current, [fieldName]: valueToStore };\n\n setValues(updated);\n\n const nextField = field + 1;\n\n if (nextField >= FIELDS.length) {\n setInputBuffer('');\n\n setPhase({\n type: 'artifact-select',\n values: updated,\n cursor: 0,\n selected: artifacts,\n });\n } else {\n const nextName = FIELDS[nextField];\n const existing = nextName ? updated[nextName] : '';\n const nextBuffer =\n nextName === 'apiName' && !existing ? inferApiName(updated.name) : existing;\n\n setPhase({ type: 'field-entry', field: nextField, values: updated });\n\n setInputBuffer(nextBuffer);\n }\n\n return;\n }\n\n if (input && !key.ctrl && !key.meta) {\n setInputBuffer((prev) => prev + input);\n }\n\n return;\n }\n\n if (phase.type === 'artifact-select') {\n const { cursor, selected, values: current } = phase;\n\n if (key.escape) {\n const lastField = FIELDS.length - 1;\n const lastName = FIELDS[lastField];\n\n setPhase({ type: 'field-entry', field: lastField, values: current });\n\n setInputBuffer(lastName ? current[lastName] : '');\n\n return;\n }\n\n if (key.upArrow) {\n setPhase({ ...phase, cursor: Math.max(0, cursor - 1) });\n\n return;\n }\n\n if (key.downArrow) {\n setPhase({ ...phase, cursor: Math.min(ARTIFACT_TYPES.length - 1, cursor + 1) });\n\n return;\n }\n\n if (input === ' ') {\n const type = ARTIFACT_TYPES[cursor];\n\n if (type) {\n const next = toggleArtifactSelection(selected, type);\n\n setArtifacts(next);\n\n setPhase({ ...phase, selected: next });\n }\n\n return;\n }\n\n if (input === 'a') {\n setArtifacts([...ARTIFACT_TYPES]);\n\n setPhase({ ...phase, selected: [...ARTIFACT_TYPES] });\n\n return;\n }\n\n if (input === 'n') {\n setArtifacts([]);\n\n setPhase({ ...phase, selected: [] });\n\n return;\n }\n\n if (key.return) {\n if (mode === 'sub-dir') {\n setPhase({ type: 'resolving-target' });\n\n void resolveSubDirAndConfirm(current, selected);\n } else {\n setPhase({ type: 'confirm', values: current, artifacts: selected });\n }\n }\n\n return;\n }\n\n if (phase.type === 'confirm') {\n if (key.escape) {\n setPhase({\n type: 'artifact-select',\n values: phase.values,\n cursor: 0,\n selected: phase.artifacts,\n });\n\n return;\n }\n\n if (key.return) {\n setPhase({ type: 'writing' });\n\n void runWrite(phase.values, targetDir, phase.artifacts);\n }\n\n return;\n }\n\n if (phase.type === 'done' || phase.type === 'error') {\n if (key.return || key.escape) {\n app.exit();\n }\n }\n });\n\n if (phase.type === 'target-select') {\n const options = [\n { label: 'Use current directory', desc: parentDir },\n { label: 'Create new sub-directory', desc: `${parentDir}/<inferred from API name>` },\n ];\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Where should the new plugin live?</Text>\n {options.map((opt, i) => {\n const selected = phase.cursor === i;\n\n return (\n <Box key={opt.label} gap={2}>\n <Text {...(selected && { color: 'cyan' as const })}>{selected ? '❯' : ' '}</Text>\n <Text bold={selected} {...(selected && { color: 'cyan' as const })}>\n {opt.label}\n </Text>\n <Text dimColor>{opt.desc}</Text>\n </Box>\n );\n })}\n </Box>\n <Hint text=\"↑↓ to move · Enter to select · Esc to cancel\" />\n </Box>\n );\n }\n\n if (phase.type === 'precheck-error') {\n const { targetDir: dir, reason } = phase;\n const conflict = reason === 'has-manifest' ? 'kizen.json' : '.kizenapp/';\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Text color=\"red\" bold>\n Cannot create plugin\n </Text>\n <Box flexDirection=\"column\" gap={0}>\n <Text>\n {dir} already contains <Text bold>{conflict}</Text>.\n </Text>\n <Text dimColor>\n Remove the conflicting file/directory or choose a different target to avoid overwriting\n an existing plugin.\n </Text>\n </Box>\n <Hint text=\"Enter or Esc to exit\" />\n </Box>\n );\n }\n\n if (phase.type === 'field-entry') {\n const { field: activeField, fieldError } = phase;\n const targetLine =\n mode === 'sub-dir'\n ? `Target: sub-directory of ${parentDir} (inferred from API name)`\n : `Target: ${targetDir}`;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Plugin details</Text>\n <Text dimColor>{targetLine}</Text>\n </Box>\n {fieldError !== undefined && <Text color=\"red\">Error: {fieldError}</Text>}\n <Box flexDirection=\"column\" gap={0}>\n {FIELDS.map((name, i) => {\n const isActive = activeField === i;\n const displayValue = isActive ? inputBuffer : values[name];\n const isRequired = REQUIRED_FIELDS.includes(name);\n const label = `${FIELD_LABELS[name]}${isRequired ? '' : ' (optional)'}`;\n\n return (\n <Box key={name} gap={2}>\n <Box width={24}>\n <Text bold={isActive} {...(isActive && { color: 'cyan' as const })}>\n {label}\n </Text>\n </Box>\n <Text {...(isActive && { color: 'cyan' as const })}>{'>'}</Text>\n <Text>{displayValue}</Text>\n {isActive && <Text color=\"cyan\">{'█'}</Text>}\n </Box>\n );\n })}\n </Box>\n <Hint text=\"Enter/Tab/↓ next · ↑ previous · Backspace delete · Esc cancel\" />\n </Box>\n );\n }\n\n if (phase.type === 'artifact-select') {\n const { cursor, selected } = phase;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Which artifacts should we scaffold?</Text>\n <Text dimColor>Each one gets a directory with a config.json and a script that runs.</Text>\n </Box>\n <Box flexDirection=\"column\" gap={0}>\n {ARTIFACT_TYPES.map((type, i) => {\n const active = cursor === i;\n const checked = selected.includes(type);\n\n return (\n <Box key={type} gap={1}>\n <Text {...(active && { color: 'cyan' as const })}>{active ? '❯' : ' '}</Text>\n <Text {...(checked && { color: 'green' as const })}>{checked ? '◉' : '◯'}</Text>\n <Text bold={active} {...(active && { color: 'cyan' as const })}>\n {ARTIFACT_LABELS[type]}\n </Text>\n </Box>\n );\n })}\n </Box>\n <Hint text=\"↑↓ move · Space toggle · a all · n none · Enter continue · Esc back\" />\n </Box>\n );\n }\n\n if (phase.type === 'confirm') {\n const manifest = buildManifest({\n targetDir,\n name: phase.values.name,\n apiName: phase.values.apiName,\n externalLink: phase.values.externalLink,\n description: phase.values.description,\n developerBusinessId: phase.values.developerBusinessId,\n developerEnvironment: defaultEnvironment,\n });\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Ready to create</Text>\n <Text dimColor>Target: {targetDir}</Text>\n </Box>\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>kizen.json preview</Text>\n <Text>{JSON.stringify(manifest, null, 2)}</Text>\n </Box>\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Artifacts</Text>\n {phase.artifacts.length === 0 ? (\n <Text dimColor>{' '}none (src/ will hold only thumbnail.png)</Text>\n ) : (\n phase.artifacts.map((type) => (\n <Text key={type} dimColor>\n {' '}\n {ARTIFACT_LABELS[type]}\n </Text>\n ))\n )}\n </Box>\n <Box flexDirection=\"column\" gap={0}>\n <Text dimColor>Also creates:</Text>\n <Text dimColor>\n {' '}\n {join(targetDir, 'src/')}\n </Text>\n <Text dimColor>\n {' '}\n {join(targetDir, 'src/thumbnail.png')} (generated placeholder)\n </Text>\n <Text dimColor>\n {' '}\n {join(targetDir, 'releaseNotes/')}\n </Text>\n <Text dimColor>\n {' '}\n {join(targetDir, '.gitignore')} (adds .kizenapp/)\n </Text>\n </Box>\n <Hint text=\"Enter to create · Esc to go back\" />\n </Box>\n );\n }\n\n if (phase.type === 'resolving-target') {\n return (\n <Box paddingY={1} paddingX={2}>\n <Text dimColor>Finding available sub-directory…</Text>\n </Box>\n );\n }\n\n if (phase.type === 'writing') {\n return (\n <Box paddingY={1} paddingX={2}>\n <Text dimColor>Creating plugin…</Text>\n </Box>\n );\n }\n\n if (phase.type === 'done') {\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Text color=\"green\" bold>\n Plugin created at {phase.targetDir}\n </Text>\n <Box flexDirection=\"column\" gap={0}>\n <Text dimColor>Next steps:</Text>\n <Text>\n {' '}cd {phase.targetDir}\n </Text>\n <Text>{' '}npx --yes @kizenapps/cli dev</Text>\n <Text dimColor>{' '}Replace src/thumbnail.png with real artwork before publishing.</Text>\n </Box>\n <Hint text=\"Enter or Esc to exit\" />\n </Box>\n );\n }\n\n // error\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Text color=\"red\" bold>\n Failed to create plugin\n </Text>\n <Text>{phase.message}</Text>\n <Hint text=\"Enter or Esc to exit\" />\n </Box>\n );\n};\n","import { access, mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { ensureGitignore } from './gitignore.js';\nimport { scaffoldArtifactFiles } from './createArtifacts.js';\nimport type { ArtifactType, ScaffoldedFile } from './createArtifacts.js';\nimport { copilotFiles } from './createCopilotFiles.js';\nimport { thumbnailBytes } from './createThumbnail.js';\nimport type { Environment } from '../../shared/lib/credentials.js';\n\nconst THUMBNAIL_PATH = 'src/thumbnail.png';\n\nconst PROD_ENVIRONMENTS: readonly Environment[] = ['go', 'fmo'];\n\nexport interface CreatePluginInput {\n targetDir: string;\n name: string;\n apiName: string;\n externalLink: string;\n description: string;\n developerBusinessId: string;\n developerEnvironment: Environment;\n artifacts?: readonly ArtifactType[];\n}\n\nexport type PrecheckResult = 'ok' | 'has-manifest' | 'has-kizenapp';\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await access(path);\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function precheckTargetDir(dir: string): Promise<PrecheckResult> {\n if (await pathExists(join(dir, 'kizen.json'))) {\n return 'has-manifest';\n }\n\n if (await pathExists(join(dir, '.kizenapp'))) {\n return 'has-kizenapp';\n }\n\n return 'ok';\n}\n\nexport async function findAvailableSubDir(parentDir: string, baseName: string): Promise<string> {\n const base = join(parentDir, baseName);\n\n if (!(await pathExists(base))) {\n return base;\n }\n\n for (let i = 1; i < 1000; i++) {\n const candidate = join(parentDir, `${baseName}-${String(i)}`);\n\n if (!(await pathExists(candidate))) {\n return candidate;\n }\n }\n\n throw new Error(`Could not find an available directory name for \"${baseName}\"`);\n}\n\nexport function buildManifest(input: CreatePluginInput): Record<string, unknown> {\n const businessId = input.developerBusinessId.trim();\n\n const targetEnvironments =\n businessId !== '' && !PROD_ENVIRONMENTS.includes(input.developerEnvironment)\n ? [input.developerEnvironment]\n : ['prod'];\n\n return {\n name: input.name,\n version: '1.0.0',\n published: true,\n api_name: input.apiName,\n external_link: input.externalLink,\n description: input.description,\n entry: 'src/',\n engine: '1.0.0',\n release_notes_directory: 'releaseNotes/',\n release_environments: targetEnvironments,\n config_template: {},\n base_config: {},\n ...(businessId ? { developer_business_id: { [input.developerEnvironment]: businessId } } : {}),\n };\n}\n\nasync function writeScaffoldedFiles(\n targetDir: string,\n scaffolded: readonly ScaffoldedFile[],\n): Promise<void> {\n const files = scaffolded.map((file) => ({\n fullPath: join(targetDir, ...file.path.split('/')),\n content: file.content,\n }));\n\n const directories = new Set(files.map((file) => dirname(file.fullPath)));\n\n await Promise.all([...directories].map((dir) => mkdir(dir, { recursive: true })));\n\n await Promise.all(files.map((file) => writeFile(file.fullPath, file.content, 'utf-8')));\n}\n\nexport async function createPlugin(input: CreatePluginInput): Promise<void> {\n await mkdir(input.targetDir, { recursive: true });\n\n const manifest = buildManifest(input);\n\n await writeFile(\n join(input.targetDir, 'kizen.json'),\n JSON.stringify(manifest, null, 2) + '\\n',\n 'utf-8',\n );\n\n await mkdir(join(input.targetDir, 'src'), { recursive: true });\n\n await mkdir(join(input.targetDir, 'releaseNotes'), { recursive: true });\n\n await Promise.all([\n writeScaffoldedFiles(input.targetDir, scaffoldArtifactFiles(input.artifacts ?? [])),\n writeScaffoldedFiles(input.targetDir, copilotFiles()),\n writeFile(join(input.targetDir, ...THUMBNAIL_PATH.split('/')), thumbnailBytes(input.apiName)),\n ]);\n\n ensureGitignore(input.targetDir);\n}\n","{\n \"name\": \"Hello Frame\",\n \"api_name\": \"hello_frame\",\n \"title\": \"Hello Frame\",\n \"default_position\": \"bottom-right\",\n \"minimized_style\": \"circle\",\n \"height\": 320,\n \"width\": 280\n}\n","this.outputUI(`\n <div class=\"hello-frame\">\n <h2 class=\"hello-frame__title\">Hello from a floating frame</h2>\n <p class=\"hello-frame__body\">Edit src/floatingFrames/helloFrame/script.js to change this.</p>\n </div>\n`);\n",".hello-frame {\n padding: 16px;\n font-family: system-ui, sans-serif;\n}\n\n.hello-frame__title {\n margin: 0 0 8px;\n font-size: 16px;\n}\n\n.hello-frame__body {\n margin: 0;\n color: #555;\n}\n","{\n \"name\": \"Hello Block\",\n \"api_name\": \"hello_block\",\n \"types\": [\"dashboards\"]\n}\n","this.outputUI(`\n <div class=\"hello-block\">\n <h2 class=\"hello-block__title\">Hello from a block</h2>\n <p class=\"hello-block__body\">Edit src/blocks/helloBlock/script.js to change this.</p>\n </div>\n`);\n",".hello-block {\n padding: 16px;\n font-family: system-ui, sans-serif;\n background: #f8fafc;\n border-radius: 6px;\n}\n\n.hello-block__title {\n margin: 0 0 8px;\n font-size: 16px;\n}\n\n.hello-block__body {\n margin: 0;\n color: #555;\n}\n","{\n \"icon\": \"phone\",\n \"color\": \"#0ea5e9\",\n \"tooltip\": \"Hello adornment\",\n \"field_type\": \"phonenumber\"\n}\n","this.showToast('Hello from a data adornment.', { variant: 'success' });\n","{\n \"name\": \"Hello Page\",\n \"api_name\": \"hello_page\"\n}\n","this.outputUI(`\n <div class=\"hello-page\">\n <p class=\"hello-page__loading\">Loading…</p>\n </div>\n`);\n\nthis.runEventScript('greet');\n",".hello-page {\n padding: 24px;\n font-family: system-ui, sans-serif;\n}\n\n.hello-page__title {\n margin: 0 0 8px;\n font-size: 20px;\n}\n\n.hello-page__body {\n margin: 0 0 16px;\n color: #555;\n}\n\n.hello-page__loading {\n margin: 0;\n color: #94a3b8;\n}\n\n.hello-page__actions {\n display: flex;\n gap: 8px;\n}\n\n.hello-page__button {\n padding: 6px 12px;\n font: inherit;\n color: #0f172a;\n background: #e2e8f0;\n border: 0;\n border-radius: 4px;\n cursor: pointer;\n}\n\n.hello-page__button:hover {\n background: #cbd5e1;\n}\n","const tone = this.args?.formData?.tone?.[0] ?? 'plain';\n\nconst greeting = tone === 'cheer' ? 'Hello, and good to see you!' : 'Hello from a routable page.';\n\nthis.outputUI(`\n <div class=\"hello-page\">\n <h1 class=\"hello-page__title\">${greeting}</h1>\n <p class=\"hello-page__body\">\n This markup came from eventScripts/greet.js. Either button re-runs it and\n repaints the page with a different greeting.\n </p>\n <div class=\"hello-page__actions\">\n <form data-script=\"greet\">\n <input type=\"hidden\" name=\"tone\" value=\"plain\" />\n <button class=\"hello-page__button\" type=\"submit\">Plain</button>\n </form>\n <form data-script=\"greet\">\n <input type=\"hidden\" name=\"tone\" value=\"cheer\" />\n <button class=\"hello-page__button\" type=\"submit\">Cheerful</button>\n </form>\n </div>\n </div>\n`);\n","{\n \"api_name\": \"hello_toolbar_item\",\n \"label\": \"Hello Toolbar Item\",\n \"icon\": \"star\",\n \"color\": \"#0ea5e9\"\n}\n","this.showToast('Hello from a toolbar item.', { variant: 'success' });\n","{\n \"api_name\": \"hello_object_settings_item\",\n \"label\": \"Hello Object Settings\"\n}\n","this.showToast('Hello from an object settings item.', { variant: 'success' });\n","{\n \"name\": \"Hello Action\",\n \"api_name\": \"hello_action\",\n \"hint_object_name\": \"client_client\"\n}\n","this.showToast('Hello from a JS action.', { variant: 'success' });\n","import helloFrameConfig from '../templates/artifacts/floatingFrames/helloFrame/config.json?raw';\nimport helloFrameScript from '../templates/artifacts/floatingFrames/helloFrame/script.js?raw';\nimport helloFrameStyles from '../templates/artifacts/floatingFrames/helloFrame/styles.css?raw';\nimport helloBlockConfig from '../templates/artifacts/blocks/helloBlock/config.json?raw';\nimport helloBlockScript from '../templates/artifacts/blocks/helloBlock/script.js?raw';\nimport helloBlockStyles from '../templates/artifacts/blocks/helloBlock/styles.css?raw';\nimport helloAdornmentConfig from '../templates/artifacts/dataAdornments/helloAdornment/config.json?raw';\nimport helloAdornmentScript from '../templates/artifacts/dataAdornments/helloAdornment/script.js?raw';\nimport helloPageConfig from '../templates/artifacts/pages/helloPage/config.json?raw';\nimport helloPageScript from '../templates/artifacts/pages/helloPage/script.js?raw';\nimport helloPageStyles from '../templates/artifacts/pages/helloPage/styles.css?raw';\nimport helloPageGreet from '../templates/artifacts/pages/helloPage/eventScripts/greet.js?raw';\nimport helloToolbarItemConfig from '../templates/artifacts/toolbarItems/helloToolbarItem/config.json?raw';\nimport helloToolbarItemScript from '../templates/artifacts/toolbarItems/helloToolbarItem/script.js?raw';\nimport helloObjectSettingsItemConfig from '../templates/artifacts/objectSettingsItems/helloObjectSettingsItem/config.json?raw';\nimport helloObjectSettingsItemScript from '../templates/artifacts/objectSettingsItems/helloObjectSettingsItem/script.js?raw';\nimport helloActionConfig from '../templates/artifacts/actions/helloAction/config.json?raw';\nimport helloActionScript from '../templates/artifacts/actions/helloAction/script.js?raw';\n\nexport const ARTIFACT_TYPES = [\n 'floatingFrame',\n 'block',\n 'dataAdornment',\n 'page',\n 'toolbarItem',\n 'objectSettingsItem',\n 'jsAction',\n] as const;\n\nexport type ArtifactType = (typeof ARTIFACT_TYPES)[number];\n\nexport const ARTIFACT_LABELS: Record<ArtifactType, string> = {\n floatingFrame: 'Floating frame',\n block: 'Block',\n dataAdornment: 'Data adornment',\n page: 'Routable page',\n toolbarItem: 'Toolbar item',\n objectSettingsItem: 'Object settings item',\n jsAction: 'JS action',\n};\n\nexport interface ScaffoldedFile {\n path: string;\n content: string;\n}\n\ninterface ArtifactTemplate {\n directory: string;\n component: string;\n files: Readonly<Record<string, string>>;\n}\n\nconst TEMPLATES: Record<ArtifactType, ArtifactTemplate> = {\n floatingFrame: {\n directory: 'floatingFrames',\n component: 'helloFrame',\n files: {\n 'config.json': helloFrameConfig,\n 'script.js': helloFrameScript,\n 'styles.css': helloFrameStyles,\n },\n },\n\n block: {\n directory: 'blocks',\n component: 'helloBlock',\n files: {\n 'config.json': helloBlockConfig,\n 'script.js': helloBlockScript,\n 'styles.css': helloBlockStyles,\n },\n },\n\n dataAdornment: {\n directory: 'dataAdornments',\n component: 'helloAdornment',\n files: {\n 'config.json': helloAdornmentConfig,\n 'script.js': helloAdornmentScript,\n },\n },\n\n page: {\n directory: 'pages',\n component: 'helloPage',\n files: {\n 'config.json': helloPageConfig,\n 'script.js': helloPageScript,\n 'styles.css': helloPageStyles,\n 'eventScripts/greet.js': helloPageGreet,\n },\n },\n\n toolbarItem: {\n directory: 'toolbarItems',\n component: 'helloToolbarItem',\n files: {\n 'config.json': helloToolbarItemConfig,\n 'script.js': helloToolbarItemScript,\n },\n },\n\n objectSettingsItem: {\n directory: 'objectSettingsItems',\n component: 'helloObjectSettingsItem',\n files: {\n 'config.json': helloObjectSettingsItemConfig,\n 'script.js': helloObjectSettingsItemScript,\n },\n },\n\n jsAction: {\n directory: 'actions',\n component: 'helloAction',\n files: {\n 'config.json': helloActionConfig,\n 'script.js': helloActionScript,\n },\n },\n};\n\nexport function artifactFiles(type: ArtifactType, entryDir = 'src'): ScaffoldedFile[] {\n const { directory, component, files } = TEMPLATES[type];\n\n return Object.entries(files).map(([relativePath, content]) => ({\n path: `${entryDir}/${directory}/${component}/${relativePath}`,\n content,\n }));\n}\n\nexport function scaffoldArtifactFiles(\n types: readonly ArtifactType[],\n entryDir = 'src',\n): ScaffoldedFile[] {\n return [...new Set(types)].flatMap((type) => artifactFiles(type, entryDir));\n}\n","# Copilot review instructions for this Kizen plugin\n\nThis repo is a Kizen plugin app: a `kizen.json` manifest plus the artifacts\nthat `@kizenapps/packager` finds by walking the directory tree under the\nmanifest's `entry` (default `src/`). No manifest key lists artifacts. The\ndirectory layout decides what gets packaged.\n\n## Component directories\n\nUnder `entry`, the packager treats these directory names as component types:\n\n- `floatingFrames`\n- `blocks`\n- `dataAdornments`\n- `pages`\n- `views`\n- `toolbarItems`\n- `objectSettingsItems`\n- `actions`\n- `routeScripts`\n- `automationSteps`\n- `calendarSources`\n\nEvery directory under a component type needs a `config.json`. `views/` is the\none exception.\n\n## `api_name` rules\n\n- An `api_name` must match `/^[a-z_][a-z0-9_]+$/`: lowercase letters, digits\n and underscores, starting with a letter or underscore, at least 2 characters.\n- Set `api_name` explicitly in each artifact's `config.json`. The fallback\n lowercases and strips the directory name (`myFrame` becomes `myframe`), and\n that result can collide with another artifact's explicit `api_name`.\n- Data adornments have no `api_name` field. Flag one that adds it as dead\n configuration.\n- Sibling components in the same directory need unique `api_name`s. `pages/`\n and `views/` go further and share one namespace, so a page and a view with\n the same `api_name` collide even though they live in different directories.\n\n## A green build does not mean a correct artifact\n\nThe packager coerces malformed artifact config instead of rejecting it: an\ninvalid `field_type` on a data adornment becomes `phonenumber`, and an invalid\n`minimized_style` on a floating frame becomes `circle`. It also says nothing\nabout a missing required field. Publishing is the real gate. The publish step\ncreates each artifact with no defaulting, so a field the packager never emitted\nis absent and the publish request 400s. Review each\n`config.json` as if the build will not catch mistakes in it, because for these\ncases it does not.\n\nPublishing an app requires these fields per artifact type. An artifact missing\none builds clean and fails to publish:\n\n| Artifact | Required fields |\n| --- | --- |\n| Floating frame | `api_name`, `name`, `title` |\n| Block | `api_name`, `name` |\n| Data adornment | `field_type` (one of `phonenumber`, `date`, `datetime`) |\n| Routable page | `api_name`, `name` |\n| Toolbar item | `api_name`, `label`, and a non-blank `script.js` |\n| Object settings item | `api_name`, `label`, and a non-blank `script.js` |\n| JS action | `api_name`, `name`, `hint_object_name` (non-blank) |\n\nA floating frame whose `default_position` ends in `-fixed` must set\n`minimized_style: \"circle\"` or omit `minimized_style`. Any other value fails\nthe build with `structure/fixed-frame-minimized-style`.\n\n## Publishing\n\nPublishing an app requires exactly one `thumbnail.png`, and it must sit inside\nthe `entry` directory (`src/thumbnail.png` by default). The packager never sees\na thumbnail at the repo root, and publishing then fails with \"Thumbnail is\nrequired for publishing\".\n\n## Scope\n\nThis file covers repo structure and general review. Two path-scoped files\ncover the rest: `.github/instructions/security.instructions.md` for\nsecurity-sensitive patterns and\n`.github/instructions/version-discipline.instructions.md` for manifest version\nbumps.\n","---\napplyTo: \"src/**/*.js,kizen.json\"\n---\n\n# Security review rules for plugin scripts\n\nThese rules mirror the `security/*` validation rules in `@kizenapps/packager`.\nFlag violations the way the packager would, and also flag the patterns listed\nhere that its static scan cannot detect.\n\n## `__dangerouslySkipProxy`\n\nThe packager lets `__dangerouslySkipProxy` through with the build WARNING\n`security/dangerously-skip-proxy`. Flag every occurrence for human review\nanyway, because the request leaves the browser directly instead of passing\nthrough the Kizen proxy.\n\n## Plaintext credentials\n\nIn `kizen.json`, a service's `auth_credentials.token`,\n`auth_credentials.password` and `auth_credentials.client_secret` must each be\none of:\n\n- an encrypted envelope (`{ \"encrypted\": true, \"value\": \"...\" }`) that\n `appbuilder encrypt` produced\n- a `{{secret.KEY}}` reference, with `KEY` declared in `base_config.secrets`\n- a reference through `auth_credentials.integration_secret_api_name`\n\nA raw literal in any of those three fields is the build ERROR\n`security/plaintext-credential`. Treat a credential that reaches a commit in\nplaintext as compromised and rotate it; deleting the line does not undo the\nexposure.\n\n`client_id` is excluded from this rule on purpose. Public client ids are not\nsensitive, so do not flag them.\n\n## Undeclared secret references\n\nA `{{secret.KEY}}` reference whose `KEY` is missing from `base_config.secrets`\nis the build ERROR `security/undeclared-secret-reference`, because nothing\nwould supply the value at install time.\n\n## Dynamic code execution\n\n`eval(...)`, `new Function(...)` or `Function(...)`, and a string argument to\n`setTimeout` or `setInterval` are the build ERROR `security/dynamic-code`.\n\nThis rule catches direct, literal usage only. The packager's scan is\nparser-based, so a call built through a computed property or a reassigned\nreference gets past it. Obfuscated dynamic code stays a human-review concern.\n\n## Secret logging and exfiltration\n\nThe packager has no static check for a secret that gets logged, sent to an\nunexpected endpoint, or otherwise exfiltrated. Review for this by hand: look\nfor credentials or decrypted secret values flowing into `console.log`, error\nmessages, analytics calls, or outbound requests to anything other than the\nservice they belong to.\n\n## Handling secrets in this repo\n\nEncrypt secrets locally with `appbuilder encrypt` before committing them. Do\nnot commit a plaintext secret value in any form; a comment, a script fixture,\nand a commit you intend to rewrite later all count.\n","---\napplyTo: \"kizen.json\"\n---\n\n# Version-bump discipline for `kizen.json`\n\n## What a wrong bump breaks\n\nA business that installs this plugin accumulates its own stored state\n(automation runs, config values, references to entities) shaped by what was\npublished at the time. Publishing is additive: it never rewrites a business's\nstored rows, and the plugin author has no way to migrate that state for them.\nA change is breaking when it invalidates an assumption the business's existing\ndata already depends on.\n\nA MINOR or PATCH republish applies at once to a business's running automations\nand installed artifacts. Only a new MAJOR version waits for the business to\nupgrade explicitly. A change that needed MAJOR but shipped as MINOR or PATCH\ntherefore breaks the business with no upgrade gate in between.\n\nTwo kinds of change get MAJOR because they fail without an error:\n\n- Renaming a config field, changing its type, or adding a required key. A\n template reference like `{{config.key}}` for a key that no longer exists\n resolves to a literal `null`, and the artifact renders wrong or does\n nothing.\n- Removing or renaming a JS action. A business's automation and UI\n associations key on the action's `api_name` as a plain string, with no\n foreign key. After a rename or removal those associations stop firing.\n\nReview every `kizen.json` diff against the table below before approving the\nversion bump in the same PR.\n\n## Bump matrix\n\n| Resource | Change | Required bump |\n| --- | --- | --- |\n| Plugin | change `api_name` | **HARD-BLOCK**: identity can never change |\n| Service | add | MINOR |\n| Service | remove | MAJOR |\n| Service | change auth type or `auth_level` | MAJOR |\n| Service | change `auth_credentials` (client id/secret, scopes, authorize/token URLs) | MAJOR |\n| Service | change base URL or other non-auth field | PATCH |\n| Service | rename `api_name` | MAJOR |\n| Secret | add | MINOR |\n| Secret | remove | MINOR |\n| Secret | rename key | MAJOR |\n| Secret | re-encrypt value only | PATCH |\n| Automation step | add | MINOR |\n| Automation step | remove entire step | MAJOR |\n| Automation step | remove an input or output | MAJOR |\n| Automation step | change input/output `data_type` | MAJOR |\n| Automation step | add required input | MAJOR |\n| Automation step | add optional input | MINOR |\n| Automation step | change python runtime | PATCH |\n| Automation step | edit script body only | PATCH |\n| Artifact (frame, block, adornment, page, route script, toolbar/object-settings item, calendar source) | add | MINOR |\n| Artifact | remove | MINOR |\n| Artifact | rename `api_name` | MINOR |\n| Artifact | edit script or behavior | PATCH |\n| JS action | add | MINOR |\n| JS action | remove | MAJOR |\n| JS action | rename `api_name` | MAJOR |\n| JS action | change `hint_object_name` or script | PATCH |\n| Config field | add optional (with default) | MINOR |\n| Config field | add required (no default) | MAJOR |\n| Config field | remove | MINOR |\n| Config field | rename | MAJOR |\n| Config field | change type | MAJOR |\n| Config field | change default or label | PATCH |\n| `required_entitlement` | add gating | MINOR |\n| `required_entitlement` | change or remove | PATCH |\n| Manifest metadata (`name`, `description`, `entry`, `release_branches`, `release_environments`, `published`, `developer_business_id`) | any change | PATCH |\n","import copilotInstructions from '../templates/github/copilot-instructions.md?raw';\nimport securityInstructions from '../templates/github/instructions/security.instructions.md?raw';\nimport versionDisciplineInstructions from '../templates/github/instructions/version-discipline.instructions.md?raw';\nimport type { ScaffoldedFile } from './createArtifacts.js';\n\nexport function copilotFiles(): ScaffoldedFile[] {\n return [\n { path: '.github/copilot-instructions.md', content: copilotInstructions },\n { path: '.github/instructions/security.instructions.md', content: securityInstructions },\n {\n path: '.github/instructions/version-discipline.instructions.md',\n content: versionDisciplineInstructions,\n },\n ];\n}\n","import { deflateSync } from 'node:zlib';\n\nexport const THUMBNAIL_SIZE = 512;\n\nconst BODY_HALF_SIZE = 150;\n\nconst BODY_CORNER_RADIUS = 26;\n\nconst KNOB_RADIUS = 46;\n\nconst KNOB_OFFSET_RATIO = 0.6;\n\nconst NECK_HALF_WIDTH = KNOB_RADIUS * 0.55;\n\nconst SATURATION = 0.55;\n\nconst LIGHTNESS = 0.47;\n\nexport interface ThumbnailStyle {\n hue: number;\n quarterTurns: 0 | 1 | 2 | 3;\n}\n\nfunction fnv1a(text: string): number {\n let hash = 0x811c9dc5;\n\n for (let i = 0; i < text.length; i += 1) {\n hash ^= text.charCodeAt(i);\n\n hash = (hash + ((hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24))) >>> 0;\n }\n\n return hash;\n}\n\nexport function thumbnailStyle(apiName: string): ThumbnailStyle {\n const hash = fnv1a(apiName);\n\n return {\n hue: hash % 360,\n quarterTurns: ((hash >>> 16) % 4) as 0 | 1 | 2 | 3,\n };\n}\n\nfunction hslToRgb(hue: number, saturation: number, lightness: number): [number, number, number] {\n const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;\n const sector = hue / 60;\n const secondary = chroma * (1 - Math.abs((sector % 2) - 1));\n const match = lightness - chroma / 2;\n\n const [r, g, b] =\n sector < 1\n ? [chroma, secondary, 0]\n : sector < 2\n ? [secondary, chroma, 0]\n : sector < 3\n ? [0, chroma, secondary]\n : sector < 4\n ? [0, secondary, chroma]\n : sector < 5\n ? [secondary, 0, chroma]\n : [chroma, 0, secondary];\n\n return [\n Math.round((r + match) * 255),\n Math.round((g + match) * 255),\n Math.round((b + match) * 255),\n ];\n}\n\nfunction roundedBoxDistance(\n x: number,\n y: number,\n halfW: number,\n halfH: number,\n radius: number,\n): number {\n const qx = Math.abs(x) - halfW + radius;\n const qy = Math.abs(y) - halfH + radius;\n\n return Math.hypot(Math.max(qx, 0), Math.max(qy, 0)) + Math.min(Math.max(qx, qy), 0) - radius;\n}\n\nfunction circleDistance(x: number, y: number, cx: number, cy: number, radius: number): number {\n return Math.hypot(x - cx, y - cy) - radius;\n}\n\nfunction puzzlePieceDistance(x: number, y: number): number {\n const s = BODY_HALF_SIZE;\n const k = KNOB_RADIUS;\n const offset = k * KNOB_OFFSET_RATIO;\n const neckHalf = NECK_HALF_WIDTH;\n\n let d = roundedBoxDistance(x, y, s, s, BODY_CORNER_RADIUS);\n\n const topKnob = Math.min(\n circleDistance(x, y, 0, -s - offset, k),\n roundedBoxDistance(x, y + s + offset / 2, neckHalf, offset / 2 + 1, 0),\n );\n\n const rightKnob = Math.min(\n circleDistance(x, y, s + offset, 0, k),\n roundedBoxDistance(x - s - offset / 2, y, offset / 2 + 1, neckHalf, 0),\n );\n\n d = Math.min(d, topKnob, rightKnob);\n\n const bottomSocket = Math.min(\n circleDistance(x, y, 0, s - offset, k),\n roundedBoxDistance(x, y - s + offset / 2, neckHalf, offset / 2 + 1, 0),\n );\n\n const leftSocket = Math.min(\n circleDistance(x, y, -s + offset, 0, k),\n roundedBoxDistance(x + s - offset / 2, y, offset / 2 + 1, neckHalf, 0),\n );\n\n return Math.max(d, -bottomSocket, -leftSocket);\n}\n\nfunction renderPixels(style: ThumbnailStyle): Uint8Array {\n const size = THUMBNAIL_SIZE;\n const pixels = new Uint8Array(size * size * 4);\n const [r, g, b] = hslToRgb(style.hue, SATURATION, LIGHTNESS);\n\n const knobExtension = KNOB_RADIUS * (1 + KNOB_OFFSET_RATIO);\n const centre = (size - 1) / 2;\n const shift = knobExtension / 2;\n\n for (let py = 0; py < size; py += 1) {\n for (let px = 0; px < size; px += 1) {\n let x = px - centre;\n let y = py - centre;\n\n for (let turn = 0; turn < style.quarterTurns; turn += 1) {\n [x, y] = [-y, x];\n }\n\n const d = puzzlePieceDistance(x + shift, y - shift);\n\n const coverage = Math.min(1, Math.max(0, 0.5 - d));\n\n if (coverage <= 0) {\n continue;\n }\n\n const i = (py * size + px) * 4;\n\n pixels[i] = r;\n pixels[i + 1] = g;\n pixels[i + 2] = b;\n pixels[i + 3] = Math.round(coverage * 255);\n }\n }\n\n return pixels;\n}\n\nconst CRC_TABLE = new Uint32Array(256).map((_, n) => {\n let c = n;\n\n for (let k = 0; k < 8; k += 1) {\n c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n }\n\n return c >>> 0;\n});\n\nfunction crc32(bytes: Uint8Array): number {\n let crc = 0xffffffff;\n\n for (const byte of bytes) {\n crc = (CRC_TABLE[(crc ^ byte) & 0xff] ?? 0) ^ (crc >>> 8);\n }\n\n return (crc ^ 0xffffffff) >>> 0;\n}\n\nfunction pngChunk(type: string, data: Uint8Array): Buffer {\n const typeBytes = Buffer.from(type, 'latin1');\n const length = Buffer.alloc(4);\n\n length.writeUInt32BE(data.length);\n\n const crc = Buffer.alloc(4);\n\n crc.writeUInt32BE(crc32(Buffer.concat([typeBytes, data])));\n\n return Buffer.concat([length, typeBytes, data, crc]);\n}\n\nconst PNG_SIGNATURE = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);\n\nexport function encodePng(width: number, height: number, rgba: Uint8Array): Buffer {\n if (rgba.length !== width * height * 4) {\n throw new Error(\n `encodePng: expected ${String(width * height * 4)} bytes of RGBA for ${String(width)}x${String(height)}, got ${String(rgba.length)}`,\n );\n }\n\n const ihdr = Buffer.alloc(13);\n\n ihdr.writeUInt32BE(width, 0);\n ihdr.writeUInt32BE(height, 4);\n ihdr[8] = 8;\n ihdr[9] = 6;\n\n const stride = width * 4;\n const raw = Buffer.alloc((stride + 1) * height);\n\n for (let y = 0; y < height; y += 1) {\n raw.set(rgba.subarray(y * stride, (y + 1) * stride), y * (stride + 1) + 1);\n }\n\n return Buffer.concat([\n PNG_SIGNATURE,\n pngChunk('IHDR', ihdr),\n pngChunk('IDAT', deflateSync(raw, { level: 9 })),\n pngChunk('IEND', new Uint8Array(0)),\n ]);\n}\n\nexport function thumbnailBytes(apiName: string): Buffer {\n return encodePng(THUMBNAIL_SIZE, THUMBNAIL_SIZE, renderPixels(thumbnailStyle(apiName)));\n}\n","import { ARTIFACT_TYPES } from './createArtifacts.js';\nimport type { ArtifactType } from './createArtifacts.js';\n\nexport const FIELDS = [\n 'name',\n 'apiName',\n 'externalLink',\n 'description',\n 'developerBusinessId',\n] as const;\n\nexport type FieldName = (typeof FIELDS)[number];\n\nexport const FIELD_LABELS: Record<FieldName, string> = {\n name: 'Name',\n apiName: 'API name',\n externalLink: 'External link',\n description: 'Description',\n developerBusinessId: 'Business ID',\n};\n\nexport const REQUIRED_FIELDS: readonly FieldName[] = ['name', 'apiName', 'description'];\n\nexport type FieldValues = Record<FieldName, string>;\n\nexport const API_NAME_PATTERN = /^[a-z_][a-z0-9_]+$/;\n\nexport const API_NAME_HINT =\n 'must start with a letter or underscore and contain only lowercase letters, numbers, or underscores (minimum 2 characters)';\n\nexport function inferApiName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '');\n}\n\nexport function emptyValues(defaultBusinessId: string): FieldValues {\n return {\n name: '',\n apiName: '',\n externalLink: '',\n description: '',\n developerBusinessId: defaultBusinessId,\n };\n}\n\nexport function validateField(fieldName: FieldName, inputBuffer: string): string | undefined {\n const value = inputBuffer.trim();\n\n if (REQUIRED_FIELDS.includes(fieldName) && !value) {\n return `${FIELD_LABELS[fieldName]} is required`;\n }\n\n if (fieldName === 'apiName' && !API_NAME_PATTERN.test(value)) {\n return `${FIELD_LABELS[fieldName]} ${API_NAME_HINT}`;\n }\n\n return undefined;\n}\n\nexport function normalizeFieldValue(fieldName: FieldName, inputBuffer: string): string {\n return fieldName === 'description' ? inputBuffer : inputBuffer.trim();\n}\n\nexport function toggleArtifactSelection(\n selected: readonly ArtifactType[],\n type: ArtifactType,\n): ArtifactType[] {\n const next = new Set(selected);\n\n if (next.has(type)) {\n next.delete(type);\n } else {\n next.add(type);\n }\n\n return ARTIFACT_TYPES.filter((candidate) => next.has(candidate));\n}\n","import { mkdir, readFile, readdir, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { ENVIRONMENTS, type Environment, type Credentials } from '../../shared/lib/credentials.js';\nexport { ENVIRONMENTS, type Environment, type Credentials } from '../../shared/lib/credentials.js';\n\nexport interface CredentialProfile {\n name: string;\n path: string;\n isDefault: boolean;\n}\n\nexport const GLOBAL_CREDENTIALS_DIR = join(homedir(), '.kizenappbuilder');\nexport const GLOBAL_CREDENTIALS_PATH = join(GLOBAL_CREDENTIALS_DIR, 'credentials.json');\nexport const DEFAULT_PROFILE_NAME = 'credentials';\n\nfunction isValidEnvironment(value: unknown): value is Environment {\n return ENVIRONMENTS.includes(value as Environment);\n}\n\nfunction parseCredentials(raw: unknown): Credentials {\n if (typeof raw !== 'object' || raw === null) {\n throw new Error('Credentials must be a JSON object');\n }\n\n const obj = raw as Record<string, unknown>;\n const env = obj.environment;\n\n return {\n apiKey: typeof obj.apiKey === 'string' ? obj.apiKey : '',\n userId: typeof obj.userId === 'string' ? obj.userId : '',\n businessId: typeof obj.businessId === 'string' ? obj.businessId : '',\n environment: isValidEnvironment(env) ? env : 'go',\n };\n}\n\nexport async function loadCredentialsFromFile(filePath: string): Promise<Credentials> {\n const content = await readFile(filePath, 'utf-8');\n\n return parseCredentials(JSON.parse(content) as unknown);\n}\n\nexport async function loadGlobalCredentials(): Promise<Credentials | null> {\n try {\n return await loadCredentialsFromFile(GLOBAL_CREDENTIALS_PATH);\n } catch {\n return null;\n }\n}\n\nexport async function saveGlobalCredentials(credentials: Credentials): Promise<void> {\n await mkdir(dirname(GLOBAL_CREDENTIALS_PATH), { recursive: true, mode: 0o700 });\n\n await writeFile(GLOBAL_CREDENTIALS_PATH, JSON.stringify(credentials, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n}\n\nexport function getProfilePath(name: string): string {\n return join(GLOBAL_CREDENTIALS_DIR, `${name}.json`);\n}\n\nexport async function listCredentialProfiles(): Promise<CredentialProfile[]> {\n const profiles: CredentialProfile[] = [\n { name: DEFAULT_PROFILE_NAME, path: GLOBAL_CREDENTIALS_PATH, isDefault: true },\n ];\n\n try {\n const entries = await readdir(GLOBAL_CREDENTIALS_DIR);\n\n for (const entry of entries) {\n if (!entry.endsWith('.json')) {\n continue;\n }\n\n const name = entry.slice(0, -5);\n\n if (name === DEFAULT_PROFILE_NAME) {\n continue;\n }\n\n profiles.push({ name, path: join(GLOBAL_CREDENTIALS_DIR, entry), isDefault: false });\n }\n } catch {\n // directory doesn't exist yet — only the default profile\n }\n\n return profiles;\n}\n\nexport async function saveCredentialProfile(name: string, credentials: Credentials): Promise<void> {\n if (name === DEFAULT_PROFILE_NAME) {\n await saveGlobalCredentials(credentials);\n\n return;\n }\n\n await mkdir(GLOBAL_CREDENTIALS_DIR, { recursive: true, mode: 0o700 });\n\n await writeFile(getProfilePath(name), JSON.stringify(credentials, null, 2), {\n encoding: 'utf-8',\n mode: 0o600,\n });\n}\n\nexport async function loadCredentialProfile(name: string): Promise<Credentials | null> {\n try {\n return await loadCredentialsFromFile(getProfilePath(name));\n } catch {\n return null;\n }\n}\n","export const ENVIRONMENTS = ['go', 'fmo', 'staging', 'integration', 'test1'] as const;\nexport type Environment = (typeof ENVIRONMENTS)[number];\n\nexport interface Credentials {\n apiKey: string;\n userId: string;\n businessId: string;\n environment: Environment;\n}\n","import { ARTIFACT_TYPES } from './createArtifacts.js';\nimport type { ArtifactType } from './createArtifacts.js';\nimport { API_NAME_HINT, API_NAME_PATTERN, inferApiName } from './createForm.js';\nimport type { CreatePluginInput, PrecheckResult } from './createPlugin.js';\nimport { ENVIRONMENTS } from '../../shared/lib/credentials.js';\nimport type { Environment } from '../../shared/lib/credentials.js';\n\nexport const PLACEHOLDER_DESCRIPTION = 'A hello-world Kizen plugin.';\n\nexport interface CreateOptions {\n name?: string;\n apiName?: string;\n description?: string;\n externalLink?: string;\n businessId?: string;\n environment?: string;\n artifacts?: string;\n}\n\nexport interface HeadlessDefaults {\n businessId: string;\n environment: Environment;\n}\n\nexport function parseArtifactSelection(raw: string | undefined): ArtifactType[] {\n if (raw === undefined || raw.trim() === '' || raw.trim() === 'all') {\n return [...ARTIFACT_TYPES];\n }\n\n if (raw.trim() === 'none') {\n return [];\n }\n\n const requested = raw\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part !== '');\n\n const unknown = requested.filter((part) => !ARTIFACT_TYPES.includes(part as ArtifactType));\n\n if (unknown.length > 0) {\n throw new Error(\n `Unknown artifact type(s): ${unknown.join(', ')}. Valid types: ${ARTIFACT_TYPES.join(', ')}, or \"all\" / \"none\".`,\n );\n }\n\n return [...new Set(requested as ArtifactType[])];\n}\n\nexport function resolveHeadlessInput(\n options: CreateOptions,\n defaults: HeadlessDefaults,\n targetDir: string,\n): CreatePluginInput {\n const name = options.name?.trim() ?? '';\n\n if (name === '') {\n throw new Error('--name is required for a non-interactive run.');\n }\n\n const apiName = (options.apiName?.trim() ?? '') || inferApiName(name);\n\n if (!API_NAME_PATTERN.test(apiName)) {\n throw new Error(`api_name \"${apiName}\" is invalid: ${API_NAME_HINT}. Pass --api-name.`);\n }\n\n const description = options.description?.trim();\n\n const developerBusinessId = options.businessId?.trim() ?? defaults.businessId;\n const developerEnvironment = resolveEnvironment(options, defaults);\n\n return {\n targetDir,\n name,\n apiName,\n externalLink: options.externalLink?.trim() ?? '',\n description:\n description === undefined || description === '' ? PLACEHOLDER_DESCRIPTION : description,\n developerBusinessId,\n developerEnvironment,\n artifacts: parseArtifactSelection(options.artifacts),\n };\n}\n\nfunction isEnvironment(value: string): value is Environment {\n return (ENVIRONMENTS as readonly string[]).includes(value);\n}\n\nfunction resolveEnvironment(options: CreateOptions, defaults: HeadlessDefaults): Environment {\n const requested = options.environment?.trim();\n\n if (requested !== undefined && requested !== '') {\n if (!isEnvironment(requested)) {\n throw new Error(\n `Unknown environment \"${requested}\". Valid environments: ${ENVIRONMENTS.join(', ')}.`,\n );\n }\n\n return requested;\n }\n\n if (options.businessId !== undefined && defaults.businessId === '') {\n throw new Error(\n '--environment is required alongside --business-id when no credentials are saved, so the id is keyed to the environment that issued it.',\n );\n }\n\n return defaults.environment;\n}\n\nexport interface HeadlessDeps {\n precheckTargetDir: (dir: string) => Promise<PrecheckResult>;\n createPlugin: (input: CreatePluginInput) => Promise<void>;\n writeStdout: (text: string) => void;\n writeStderr: (text: string) => void;\n setExitCode: (code: number) => void;\n}\n\nexport async function runHeadlessCreate(\n options: CreateOptions,\n defaults: HeadlessDefaults,\n targetDir: string,\n deps: HeadlessDeps,\n): Promise<void> {\n let input: CreatePluginInput;\n\n try {\n input = resolveHeadlessInput(options, defaults, targetDir);\n } catch (err) {\n deps.writeStderr(`Error: ${err instanceof Error ? err.message : String(err)}\\n`);\n\n deps.setExitCode(1);\n\n return;\n }\n\n const precheck = await deps.precheckTargetDir(targetDir);\n\n if (precheck !== 'ok') {\n const conflict = precheck === 'has-manifest' ? 'kizen.json' : '.kizenapp/';\n\n deps.writeStderr(\n `Error: ${targetDir} already contains ${conflict}. Refusing to overwrite an existing plugin.\\n`,\n );\n\n deps.setExitCode(1);\n\n return;\n }\n\n try {\n await deps.createPlugin(input);\n } catch (err) {\n deps.writeStderr(`Error: ${err instanceof Error ? err.message : String(err)}\\n`);\n\n deps.setExitCode(1);\n\n return;\n }\n\n const artifactSummary =\n input.artifacts && input.artifacts.length > 0 ? input.artifacts.join(', ') : 'none';\n\n deps.writeStdout(`Created plugin ${input.apiName} at ${targetDir}\\n`);\n\n deps.writeStdout(`Artifacts: ${artifactSummary}\\n`);\n\n deps.writeStdout(\n 'Thumbnail: src/thumbnail.png (generated placeholder; replace it before publishing)\\n',\n );\n\n if (input.developerBusinessId.trim() === '') {\n deps.writeStderr(\n 'Warning: no developer_business_id configured, so this plugin cannot be preview-published yet.\\n',\n );\n }\n}\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { DevUI } from '../ui/DevUI.js';\nimport { CredentialSetupUI } from '../ui/CredentialSetupUI.js';\nimport type { CredentialMode, CredentialSetupResult } from '../ui/CredentialSetupUI.js';\nimport {\n loadCredentialProfile,\n loadCredentialsFromFile,\n loadGlobalCredentials,\n} from '../lib/credentials.js';\nimport type { Credentials } from '../lib/credentials.js';\nimport { loadConfig, saveConfig } from '../lib/config.js';\nimport { ensureGitignore } from '../lib/gitignore.js';\n\nasync function runSetupUI(initialMode?: CredentialMode): Promise<CredentialSetupResult> {\n return new Promise((resolve) => {\n let unmountFn: (() => void) | null = null;\n const handleComplete = (result: CredentialSetupResult): void => {\n unmountFn?.();\n\n resolve(result);\n };\n\n const { unmount } = render(\n createElement(CredentialSetupUI, {\n ...(initialMode !== undefined && { initialMode }),\n onComplete: handleComplete,\n }),\n { exitOnCtrlC: false },\n );\n\n unmountFn = unmount;\n });\n}\n\nexport function devCommand(program: Command): void {\n program\n .command('dev')\n .description('Start the plugin viewer dev server')\n .option('-p, --port <port>', 'port to listen on', '3121')\n .option('-c, --credentials <path>', 'path to a credentials JSON file')\n .option('-d, --debug', 'Enable CDP lifecycle logs in the TUI')\n .option('-v, --verbose', 'Log every CDP event and handled error (implies --debug)')\n .option('--no-viewer', \"Don't auto-launch the viewer on startup (press [v] to launch manually)\")\n .option('--no-cache', 'Disable the network proxy cache (always fetch upstream)')\n .action(\n async (options: {\n port: string;\n credentials?: string;\n debug?: boolean;\n verbose?: boolean;\n viewer?: boolean;\n cache?: boolean;\n }) => {\n const port = parseInt(options.port, 10);\n const pluginDir = process.cwd();\n const outputDir = `${pluginDir}/.kizenapp`;\n\n ensureGitignore(pluginDir);\n\n let credentials: Credentials | null = null;\n let credentialMode: CredentialMode | undefined;\n let activeCredentialProfile: string | undefined;\n const { lastPath } = await loadConfig(outputDir);\n\n if (options.credentials) {\n credentials = await loadCredentialsFromFile(options.credentials);\n } else {\n const config = await loadConfig(outputDir);\n\n if (config.credentialMode === 'local') {\n credentialMode = 'local';\n } else if (config.credentialMode === 'global') {\n credentialMode = 'global';\n\n activeCredentialProfile = config.activeCredentialProfile;\n\n // Load silently — only show TUI if the file was deleted since last run\n if (activeCredentialProfile) {\n credentials = await loadCredentialProfile(activeCredentialProfile);\n\n if (!credentials) {\n // Named profile file missing, fall back to default\n credentials = await loadGlobalCredentials();\n\n activeCredentialProfile = undefined;\n }\n } else {\n credentials = await loadGlobalCredentials();\n }\n\n if (!credentials) {\n const result = await runSetupUI('global');\n\n credentials = result.credentials;\n\n activeCredentialProfile = result.profileName;\n }\n } else {\n // First run — show full mode selection TUI\n const result = await runSetupUI();\n\n credentials = result.credentials;\n\n credentialMode = result.mode;\n\n activeCredentialProfile = result.profileName;\n\n const profile = result.profileName;\n\n await saveConfig(outputDir, {\n credentialMode: result.mode,\n ...(profile !== undefined && { activeCredentialProfile: profile }),\n });\n }\n }\n\n const verbose = options.verbose === true;\n const debug = verbose || options.debug === true;\n const autoViewer = options.viewer !== false;\n const cacheEnabled = options.cache !== false;\n\n const { waitUntilExit } = render(\n createElement(DevUI, {\n port,\n pluginDir,\n outputDir,\n credentials,\n ...(credentialMode !== undefined && { credentialMode }),\n ...(activeCredentialProfile !== undefined && { activeCredentialProfile }),\n ...(lastPath !== undefined && { lastPath }),\n debug,\n verbose,\n autoViewer,\n cacheEnabled,\n }),\n { exitOnCtrlC: false },\n );\n\n await waitUntilExit();\n },\n );\n}\n","import type { FC } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { PluginValidationError } from '@kizenapps/packager';\nimport type { ValidationIssue } from '@kizenapps/packager';\nimport { watch } from 'node:fs';\nimport type { FSWatcher } from 'node:fs';\nimport { createServer } from 'node:http';\nimport type { Server } from 'node:http';\nimport { join } from 'node:path';\nimport { type WebSocket, WebSocketServer } from 'ws';\nimport {\n createRequestHandler,\n fileExists,\n getViewerPath,\n type ProxyLogEntry,\n proxyLogEntryToString,\n} from '../server/requestHandler.js';\nimport { launchChromeViewer, type ChromeViewerHandle } from '../chrome/launcher.js';\nimport { runBuild } from '../lib/runBuild.js';\nimport type { Credentials } from '../lib/credentials.js';\nimport { saveConfig } from '../lib/config.js';\nimport { LOG_LIMIT, LOG_DISPLAY, FILE_WATCH_DEBOUNCE_MS } from '../lib/constants.js';\nimport { formatBytes } from '../../shared/lib/formatBytes.js';\nimport { useLogHistory } from '../hooks/useLogHistory.js';\nimport { CredentialSetupUI } from './CredentialSetupUI.js';\nimport type { CredentialMode, CredentialSetupResult } from './CredentialSetupUI.js';\nimport { AppHeader } from './AppHeader.js';\nimport { Spinner } from './Spinner.js';\nimport { ValidationIssues } from './ValidationIssues.js';\n\ntype ServerStatus = 'starting' | 'running' | 'error';\ntype BuildStatus = 'pending' | 'building' | 'done' | 'error';\n\nconst SKIP_WATCH_PREFIXES = ['.kizenapp', '.git'];\n\ninterface DevUIProps {\n port: number;\n pluginDir: string;\n outputDir: string;\n credentials: Credentials | null;\n credentialMode?: CredentialMode;\n activeCredentialProfile?: string;\n lastPath?: string;\n debug?: boolean;\n verbose?: boolean;\n autoViewer?: boolean;\n cacheEnabled?: boolean;\n}\n\nexport const DevUI: FC<DevUIProps> = ({\n port,\n pluginDir,\n outputDir,\n credentials: initialCredentials,\n credentialMode: initialCredentialMode,\n activeCredentialProfile: initialActiveProfile,\n lastPath: initialLastPath,\n debug = false,\n verbose = false,\n autoViewer = true,\n cacheEnabled = true,\n}) => {\n const credentialsRef = useRef<Credentials | null>(initialCredentials);\n const activeProfileRef = useRef<string | undefined>(initialActiveProfile);\n const lastPathRef = useRef<string | undefined>(initialLastPath);\n const [credMode, setCredMode] = useState<'main' | 'editing'>('main');\n const [credentialMode, setCredentialMode] = useState<CredentialMode | undefined>(\n initialCredentialMode,\n );\n\n const [status, setStatus] = useState<ServerStatus>('starting');\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [serverLogHistory, appendServerLog] = useLogHistory(LOG_LIMIT);\n const [buildLogHistory, appendBuildLog] = useLogHistory(LOG_LIMIT);\n const [cdpLogHistory, appendCdpLog] = useLogHistory(LOG_LIMIT);\n const [proxyLogHistory, setProxyLogHistory] = useState<string[]>([]);\n const [buildStatus, setBuildStatus] = useState<BuildStatus>('pending');\n const [buildError, setBuildError] = useState<string | null>(null);\n const [buildIssues, setBuildIssues] = useState<ValidationIssue[] | null>(null);\n const [lastBuilt, setLastBuilt] = useState<Date | null>(null);\n const [lastBundleSize, setLastBundleSize] = useState<number | null>(null);\n const [wsClientCount, setWsClientCount] = useState(0);\n const [proxyCacheSize, setProxyCacheSize] = useState(0);\n const [proxyCacheHits, setProxyCacheHits] = useState(0);\n const [proxyCacheMisses, setProxyCacheMisses] = useState(0);\n\n const buildingRef = useRef(false);\n const viewerLaunchedRef = useRef(false);\n const chromeHandleRef = useRef<ChromeViewerHandle | null>(null);\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wsClientsRef = useRef<Set<WebSocket>>(new Set());\n const pendingMessagesRef = useRef<string[]>([]);\n\n const broadcast = useCallback((msg: object): void => {\n const json = JSON.stringify(msg);\n\n if (wsClientsRef.current.size === 0) {\n pendingMessagesRef.current = [...pendingMessagesRef.current, json].slice(-LOG_LIMIT);\n\n return;\n }\n\n let pruned = false;\n\n for (const client of wsClientsRef.current) {\n if (client.readyState !== 1) {\n continue;\n }\n\n try {\n client.send(json);\n } catch {\n // Socket died between readyState check and send — drop it so one\n // dead client can't break the loop and silently disconnect the rest.\n wsClientsRef.current.delete(client);\n pruned = true;\n }\n }\n\n if (pruned) {\n setWsClientCount(wsClientsRef.current.size);\n }\n }, []);\n\n const createServerLog = appendServerLog;\n\n const launchChromeViewerCb = useCallback(() => {\n chromeHandleRef.current?.kill();\n\n chromeHandleRef.current = null;\n\n void launchChromeViewer({\n port,\n userDataDir: join(outputDir, '.chrome'),\n broadcast,\n onWarn: (msg) => {\n appendServerLog(`⚠ ${msg}`);\n },\n ...(lastPathRef.current !== undefined && { path: lastPathRef.current }),\n ...(debug && { debugLog: appendCdpLog }),\n ...(verbose && { verbose: true }),\n }).then((handle) => {\n chromeHandleRef.current = handle;\n });\n }, [port, outputDir, broadcast, debug, verbose, appendCdpLog, appendServerLog]);\n\n useEffect(() => {\n const onExit = (): void => {\n chromeHandleRef.current?.kill();\n };\n\n process.on('exit', onExit);\n\n return () => {\n process.off('exit', onExit);\n };\n }, []);\n\n useInput(\n (input, key) => {\n if (input === 'q' || (key.ctrl && input === 'c')) {\n process.exit(0);\n }\n\n if (input === 'c') {\n setCredMode('editing');\n }\n\n if (input === 'v') {\n launchChromeViewerCb();\n }\n },\n { isActive: credMode === 'main' },\n );\n\n useEffect(() => {\n if (status !== 'running' || viewerLaunchedRef.current || !autoViewer) {\n return;\n }\n\n viewerLaunchedRef.current = true;\n\n launchChromeViewerCb();\n }, [status, autoViewer, launchChromeViewerCb]);\n\n const handleCredentialsDone = useCallback(\n (result: CredentialSetupResult): void => {\n credentialsRef.current = result.credentials;\n\n activeProfileRef.current = result.profileName;\n\n setCredMode('main');\n\n setCredentialMode(result.mode);\n\n const profile = result.profileName;\n\n void saveConfig(outputDir, {\n credentialMode: result.mode,\n ...(profile !== undefined && { activeCredentialProfile: profile }),\n });\n\n broadcast({ type: 'credentials-updated', credentials: result.credentials });\n },\n [outputDir, broadcast],\n );\n\n const createProxyLog = useCallback(\n (entry: ProxyLogEntry): void => {\n setProxyLogHistory((h) =>\n [...h, `${new Date().toLocaleTimeString()}: ${proxyLogEntryToString(entry)}`].slice(\n -LOG_LIMIT,\n ),\n );\n\n if (entry.kind === 'request') {\n if (entry.fromCache) {\n setProxyCacheHits((n) => n + 1);\n } else {\n setProxyCacheMisses((n) => n + 1);\n }\n }\n\n broadcast({ type: 'proxy-log', entry });\n },\n [broadcast],\n );\n\n const createBuildLog = useCallback(\n (message: string): void => {\n appendBuildLog(message);\n\n broadcast({ type: 'log', message });\n },\n [appendBuildLog, broadcast],\n );\n\n const triggerBuild = useCallback(() => {\n if (buildingRef.current) {\n return;\n }\n\n buildingRef.current = true;\n setBuildStatus('building');\n setBuildError(null);\n setBuildIssues(null);\n createBuildLog('Build started');\n\n void runBuild(pluginDir, outputDir)\n .then(({ bundleSize }) => {\n createBuildLog(`Build finished — bundle: ${formatBytes(bundleSize)}`);\n setBuildStatus('done');\n setLastBuilt(new Date());\n setLastBundleSize(bundleSize);\n createBuildLog('Notifying viewers to reload');\n broadcast({ type: 'rebuild' });\n })\n .catch((err: unknown) => {\n if (err instanceof PluginValidationError) {\n setBuildIssues(err.issues);\n setBuildError(null);\n } else {\n setBuildError(err instanceof Error ? err.message : String(err));\n setBuildIssues(null);\n }\n\n setBuildStatus('error');\n })\n .finally(() => {\n buildingRef.current = false;\n });\n }, [pluginDir, outputDir, createBuildLog, broadcast]);\n\n useEffect(() => {\n triggerBuild();\n\n const watcher: FSWatcher = watch(pluginDir, { recursive: true }, (_, filename) => {\n if (!filename) {\n return;\n }\n\n const normalized = filename.replace(/\\\\/g, '/');\n\n if (SKIP_WATCH_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {\n return;\n }\n\n createBuildLog(`File change detected: ${filename}`);\n\n if (debounceTimerRef.current !== null) {\n clearTimeout(debounceTimerRef.current);\n }\n\n debounceTimerRef.current = setTimeout(triggerBuild, FILE_WATCH_DEBOUNCE_MS);\n });\n\n // fs.watch silently dies on e.g. macOS inode-limit pressure — surface it so\n // developers know rebuilds have stopped rather than wondering why their\n // edits aren't reflected in the viewer.\n watcher.on('error', (err: Error) => {\n createBuildLog(`File watcher error — rebuilds have stopped: ${err.message}`);\n });\n\n return () => {\n watcher.close();\n\n if (debounceTimerRef.current !== null) {\n clearTimeout(debounceTimerRef.current);\n }\n };\n }, [pluginDir, triggerBuild, createBuildLog]);\n\n useEffect(() => {\n const viewerPath = getViewerPath();\n\n void fileExists(join(viewerPath, 'index.html')).then((viewerBuilt) => {\n if (!viewerBuilt) {\n setErrorMessage(\"Viewer not built. Run 'pnpm build:viewer' first.\");\n setStatus('error');\n\n return;\n }\n\n const handler = createRequestHandler(\n viewerPath,\n createServerLog,\n createProxyLog,\n credentialsRef,\n activeProfileRef,\n outputDir,\n broadcast,\n setProxyCacheSize,\n lastPathRef,\n pluginDir,\n cacheEnabled,\n );\n const server: Server = createServer(handler);\n const wss = new WebSocketServer({ server });\n\n wss.on('connection', (ws: WebSocket) => {\n for (const json of pendingMessagesRef.current) {\n if (ws.readyState === 1) {\n ws.send(json);\n }\n }\n\n pendingMessagesRef.current = [];\n createServerLog('Viewer connected for live reload');\n wsClientsRef.current.add(ws);\n setWsClientCount(wsClientsRef.current.size);\n\n ws.on('close', () => {\n wsClientsRef.current.delete(ws);\n setWsClientCount(wsClientsRef.current.size);\n });\n });\n\n server.listen(port, '127.0.0.1', () => {\n setStatus('running');\n createServerLog(`Server started on 127.0.0.1:${String(port)}`);\n });\n\n server.on('error', (err: Error) => {\n setErrorMessage(err.message);\n setStatus('error');\n });\n\n return () => {\n wss.close();\n server.close();\n };\n });\n }, [port, createServerLog, createProxyLog, broadcast, outputDir, pluginDir, cacheEnabled]);\n\n if (credMode === 'editing') {\n return (\n <CredentialSetupUI\n {...(credentialMode !== undefined && { initialMode: credentialMode })}\n showProfileManager={credentialMode === 'global'}\n onComplete={handleCredentialsDone}\n onCancel={() => {\n setCredMode('main');\n }}\n />\n );\n }\n\n const elapsedSeconds =\n lastBuilt !== null ? Math.round((Date.now() - lastBuilt.getTime()) / 1000) : null;\n\n const elapsedLabel =\n elapsedSeconds === null\n ? ''\n : elapsedSeconds < 5\n ? ' (just now)'\n : ` (${String(elapsedSeconds)}s ago)`;\n\n const buildErrorCount = buildIssues?.filter((issue) => issue.severity === 'error').length ?? 0;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2}>\n <AppHeader marginBottom={1} />\n\n {/* Build panel */}\n <Box flexDirection=\"column\">\n <Box gap={2} marginBottom={0}>\n <Text bold dimColor>\n App Build\n </Text>\n {buildStatus === 'pending' && <Text dimColor>waiting…</Text>}\n {buildStatus === 'building' && (\n <Box gap={1}>\n <Spinner />\n <Text>Building plugin package…</Text>\n </Box>\n )}\n {buildStatus === 'done' && (\n <Box gap={1}>\n <Text color=\"green\">✓ Built</Text>\n {lastBuilt !== null && (\n <Text dimColor>\n at {lastBuilt.toLocaleTimeString()}\n {elapsedLabel}\n </Text>\n )}\n {lastBundleSize !== null && (\n <Text dimColor>· bundle: {formatBytes(lastBundleSize)}</Text>\n )}\n </Box>\n )}\n {buildStatus === 'error' &&\n (buildIssues !== null ? (\n <Text color=\"red\">\n ✗ {buildErrorCount} validation {buildErrorCount === 1 ? 'error' : 'errors'}\n </Text>\n ) : (\n <Text color=\"red\">✗ {buildError ?? 'unknown error'}</Text>\n ))}\n </Box>\n {buildIssues !== null && <ValidationIssues issues={buildIssues} />}\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY + 2}\n borderStyle=\"single\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {buildLogHistory.slice(-LOG_DISPLAY).map((log, index) => (\n <Text key={index} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))}\n </Box>\n </Box>\n\n {/* Server panel */}\n <Box marginTop={1} flexDirection=\"column\">\n <Box gap={2}>\n <Text bold dimColor>\n Web Server\n </Text>\n {status === 'starting' && <Text dimColor>starting…</Text>}\n {status === 'running' && (\n <Box gap={2}>\n <Text color=\"green\">✓ Running</Text>\n <Text dimColor>\n ● {wsClientCount} viewer{wsClientCount !== 1 ? 's' : ''}\n </Text>\n </Box>\n )}\n {status === 'error' && <Text color=\"red\">✗ {errorMessage ?? 'Server error'}</Text>}\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY + 2}\n borderStyle=\"single\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {serverLogHistory.slice(-LOG_DISPLAY).map((log, index) => (\n <Text key={index} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))}\n </Box>\n </Box>\n\n {/* Proxy panel */}\n <Box marginTop={1} flexDirection=\"column\">\n <Box gap={2}>\n <Text bold dimColor>\n Network Proxy\n </Text>\n <Text color=\"green\">✓ Active</Text>\n <Text dimColor>\n {cacheEnabled\n ? `● ${String(proxyCacheSize)} key${proxyCacheSize !== 1 ? 's' : ''} in the network cache · ${String(proxyCacheHits)} hit · ${String(proxyCacheMisses)} miss`\n : `● network cache disabled · ${String(proxyCacheMisses)} request${proxyCacheMisses !== 1 ? 's' : ''}`}\n </Text>\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY + 2}\n borderStyle=\"single\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {proxyLogHistory.length === 0 ? (\n <Text dimColor> No requests yet.</Text>\n ) : (\n proxyLogHistory.slice(-LOG_DISPLAY).map((log, i) => (\n <Text key={i} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))\n )}\n </Box>\n </Box>\n\n {debug && (\n <Box marginTop={1} flexDirection=\"column\">\n <Box gap={2}>\n <Text bold dimColor>\n CDP Debug\n </Text>\n <Text dimColor>● {cdpLogHistory.length} event(s)</Text>\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY + 2}\n borderStyle=\"single\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {cdpLogHistory.length === 0 ? (\n <Text dimColor> No CDP events yet.</Text>\n ) : (\n cdpLogHistory.slice(-LOG_DISPLAY).map((log, i) => (\n <Text key={i} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))\n )}\n </Box>\n </Box>\n )}\n\n {/* Footer */}\n <Box marginTop={1} gap={1}>\n <Text dimColor>[</Text>\n <Text>q</Text>\n <Text dimColor>] quit [</Text>\n <Text>c</Text>\n <Text dimColor>] credentials [</Text>\n <Text>v</Text>\n <Text dimColor>] {wsClientCount === 0 ? 'open viewer' : 'relaunch viewer'}</Text>\n </Box>\n </Box>\n );\n};\n","import { createReadStream, realpathSync } from 'node:fs';\nimport { access, readdir, readFile, realpath, stat } from 'node:fs/promises';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { dirname, extname, join, resolve, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n createProxyCache,\n MAX_PROXY_BYTES,\n ProxyResponseTooLargeError,\n readBodyWithLimit,\n sanitizeUpstreamHeaders,\n} from '../lib/proxyCache.js';\nimport { MIME_TYPES } from '../lib/constants.js';\nimport type { Credentials } from '../lib/credentials.js';\nimport {\n listCredentialProfiles,\n loadCredentialProfile,\n loadGlobalCredentials,\n} from '../lib/credentials.js';\nimport { loadConfig, saveConfig } from '../lib/config.js';\nimport { resolveWizardBase } from '../lib/wizardUrl.js';\nimport { executePythonStep } from './pythonExecutor.js';\nimport { SKIP_DIRS } from '../lib/readFiles.js';\nimport { TEXT_EXTENSIONS } from '../../shared/lib/fileExtensions.js';\nimport { normalizeStepInputs } from '../../shared/lib/execution.js';\nimport {\n CRYPTO_ALG,\n CRYPTO_VERSION,\n deserializeEnvelope,\n encrypt,\n serializeEnvelope,\n} from '@kizenapps/packager';\n\nconst SOURCE_FILE_MAX_BYTES = 2 * 1024 * 1024;\n\nconst SKIP_FILES = new Set(['.DS_Store', '.gitignore']);\n\nfunction isLocalHost(host: string | undefined): boolean {\n if (host === undefined || host === '') {\n return false;\n }\n\n // Strip the port. This is a host header, so IPv6 would arrive as \"[::1]:port\"\n // — we don't serve ::1 (Node binds to 127.0.0.1), but the guard is permissive\n // enough to survive that even if the bind address changes later.\n const hostname = host.startsWith('[')\n ? host.slice(0, host.indexOf(']') + 1)\n : (host.split(':')[0] ?? '');\n\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]';\n}\n\nconst PROXY_ALLOWED_DOMAINS = ['kizen.com', 'kizen.dev'];\n\n/**\n * Guards the resolved encryption-API host. The wizard proxy forwards the\n * caller's Kizen credential headers, so a fat-fingered PLUGIN_WIZARD_URL* env\n * var must not be able to leak them to an arbitrary origin. Allows a\n * locally-running wizard (any localhost/loopback) plus https on a Kizen domain.\n */\nfunction isAllowedWizardTarget(target: string): boolean {\n let url: URL;\n\n try {\n url = new URL(target);\n } catch {\n return false;\n }\n\n const hostname = url.hostname.toLowerCase();\n\n // URL.hostname returns IPv6 literals bracketed, e.g. '[::1]'.\n if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]') {\n return true;\n }\n\n if (url.protocol !== 'https:') {\n return false;\n }\n\n return PROXY_ALLOWED_DOMAINS.some(\n (domain) => hostname === domain || hostname.endsWith('.' + domain),\n );\n}\n\nfunction isAllowedProxyTarget(target: string): boolean {\n let url: URL;\n\n try {\n url = new URL(target);\n } catch {\n return false;\n }\n\n if (url.protocol !== 'https:') {\n return false;\n }\n\n const hostname = url.hostname.toLowerCase();\n\n return PROXY_ALLOWED_DOMAINS.some(\n (domain) => hostname === domain || hostname.endsWith('.' + domain),\n );\n}\n\nfunction isLocalOrigin(origin: string | undefined): boolean {\n if (origin === undefined || origin === '') {\n return false;\n }\n\n try {\n const { hostname } = new URL(origin);\n\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1';\n } catch {\n return false;\n }\n}\n\nasync function resolveSafePath(realPluginDir: string, relParam: string): Promise<string | null> {\n if (relParam.includes('\\0')) {\n return null;\n }\n\n const rel = relParam.replace(/^\\/+/, '');\n const abs = resolve(realPluginDir, rel);\n\n // Syntactic .. traversal check — fails fast before touching the filesystem.\n if (abs !== realPluginDir && !abs.startsWith(realPluginDir + sep)) {\n return null;\n }\n\n // Symlink-aware check: a symlink inside the plugin dir can still escape it\n // (e.g. a link to ~/.ssh/id_rsa resolves to a path that passes the string\n // check above but reads arbitrary files). Realpath the target and re-verify.\n // If the target doesn't exist realpath throws — reject rather than guess.\n try {\n const realAbs = await realpath(abs);\n\n if (realAbs !== realPluginDir && !realAbs.startsWith(realPluginDir + sep)) {\n return null;\n }\n\n return realAbs;\n } catch {\n return null;\n }\n}\n\nfunction isInsideSkippedDir(pluginDir: string, abs: string): boolean {\n const rel = abs === pluginDir ? '' : abs.slice(pluginDir.length + 1);\n\n if (rel === '') {\n return false;\n }\n\n const segments = rel.split(sep);\n\n return segments.some((segment) => SKIP_DIRS.has(segment));\n}\n\nexport type { ProxyLogEntry } from '../../shared/lib/proxy.js';\nexport { proxyLogEntryToString } from '../../shared/lib/proxy.js';\nimport { type ProxyLogEntry } from '../../shared/lib/proxy.js';\n\nexport function getViewerPath(): string {\n const filename = fileURLToPath(import.meta.url);\n\n return join(dirname(filename), 'viewer');\n}\n\n/**\n * Calls to Kizen's `/external-integrations/proxy` endpoint wrap the third-party\n * API's status in the response body (`status_code`) and return HTTP 200 even\n * when the upstream call failed. Pull that real status out so the network log\n * can surface it instead of the misleading proxy status.\n */\nfunction extractUpstreamStatus(\n upstreamPath: string,\n headers: Record<string, string>,\n body: Buffer,\n): number | undefined {\n if (!upstreamPath.includes('/external-integrations/proxy')) {\n return undefined;\n }\n\n if (!headers['content-type']?.includes('application/json')) {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(body.toString('utf8')) as { status_code?: unknown };\n\n return typeof parsed.status_code === 'number' ? parsed.status_code : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport function createRequestHandler(\n viewerPath: string,\n createServerLog: (message: string) => void,\n createProxyLog: (entry: ProxyLogEntry) => void,\n credentialsRef: { current: Credentials | null },\n activeProfileRef: { current: string | undefined },\n outputDir: string,\n broadcast: (msg: object) => void,\n onProxyCacheChange: (size: number) => void,\n lastPathRef: { current: string | undefined },\n pluginDir: string,\n cacheEnabled: boolean,\n): (req: IncomingMessage, res: ServerResponse) => void {\n const proxyCache = createProxyCache({ onChange: onProxyCacheChange, enabled: cacheEnabled });\n // Resolve the plugin dir once so every source-path check compares against\n // the canonical path (handles macOS /var → /private/var, pnpm workspace\n // symlinks, etc.). Done synchronously at handler creation since pluginDir\n // is process.cwd() and must already exist.\n const realPluginDir = realpathSync(pluginDir);\n\n return (req, res) => {\n void (async () => {\n const url = req.url ?? '/';\n\n try {\n // Even though we bind to 127.0.0.1, a browser tab on\n // a malicious origin can point its DNS at our loopback address. The\n // Host header still carries the original hostname, so rejecting\n // anything that isn't localhost/127.0.0.1 closes the hole.\n if (!isLocalHost(req.headers.host)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Forbidden' }));\n\n return;\n }\n\n const isWrite = req.method === 'POST' || req.method === 'PATCH' || req.method === 'DELETE';\n\n if (isWrite && !isLocalOrigin(req.headers.origin)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Forbidden' }));\n\n return;\n }\n\n createServerLog(`Received request: ${url}`);\n\n if (url === '/api/credentials') {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(\n JSON.stringify({\n credentials: credentialsRef.current ?? null,\n activeProfile: activeProfileRef.current ?? null,\n }),\n );\n\n return;\n }\n\n if (url === '/api/credential-profiles' && req.method === 'GET') {\n const profiles = await listCredentialProfiles();\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(JSON.stringify({ profiles, active: activeProfileRef.current }));\n\n return;\n }\n\n if (url === '/api/credentials/switch' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n profile?: string;\n };\n const profileName = body.profile;\n const creds =\n profileName === undefined || profileName === ''\n ? await loadGlobalCredentials()\n : await loadCredentialProfile(profileName);\n\n if (creds !== null) {\n credentialsRef.current = creds;\n\n activeProfileRef.current = profileName ?? undefined;\n\n const active = activeProfileRef.current;\n const currentConfig = await loadConfig(outputDir);\n\n await saveConfig(outputDir, {\n ...currentConfig,\n credentialMode: 'global',\n ...(active !== undefined && { activeCredentialProfile: active }),\n });\n\n broadcast({\n type: 'credentials-updated',\n credentials: creds,\n activeProfile: activeProfileRef.current ?? null,\n });\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(JSON.stringify({ ok: creds !== null }));\n\n return;\n }\n\n if (url === '/api/bundle') {\n const bundlePath = join(process.cwd(), '.kizenapp', 'bundle.json');\n\n try {\n const content = await readFile(bundlePath, 'utf-8');\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(content);\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end('{}');\n }\n\n return;\n }\n\n if (url === '/api/last-path' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n path?: string;\n };\n\n if (typeof body.path === 'string') {\n lastPathRef.current = body.path;\n\n const currentConfig = await loadConfig(outputDir);\n\n await saveConfig(outputDir, { ...currentConfig, lastPath: body.path });\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end('{\"ok\":true}');\n\n return;\n }\n\n if (url === '/api/encryption-target' && req.method === 'GET') {\n const config = await loadConfig(outputDir);\n // Default to 'prod' when unset. Anything that isn't an explicit 'dev'\n // (incl. a legacy 'auto' from before the heuristic was dropped) maps to\n // 'prod', so the API only ever returns a concrete target.\n const target = config.encryptionTarget === 'dev' ? 'dev' : 'prod';\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ target }));\n\n return;\n }\n\n if (url === '/api/encryption-target' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const parsed: unknown = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}');\n const body: { target?: string } =\n parsed !== null && typeof parsed === 'object' ? (parsed as { target?: string }) : {};\n\n if (body.target !== 'dev' && body.target !== 'prod') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: \"target must be one of: 'dev', 'prod'\" }));\n\n return;\n }\n\n const currentConfig = await loadConfig(outputDir);\n\n // body.target is narrowed to 'dev' | 'prod' by the guard above.\n await saveConfig(outputDir, { ...currentConfig, encryptionTarget: body.target });\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n\n return;\n }\n\n if (url === '/api/execute-step' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n script?: string;\n scriptRuntime?: string;\n inputs?: Record<string, unknown>;\n secrets?: Record<string, string>;\n timeout?: number;\n };\n\n if (typeof body.script !== 'string') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(JSON.stringify({ error: 'Missing required field: script' }));\n\n return;\n }\n\n const stepParams: Parameters<typeof executePythonStep>[0] = {\n script: body.script,\n // Matches the production Kizen code-runner service's default runtime\n // (\"python-3-13\"). Only used when a caller omits a runtime; real\n // plugin steps send their own \"python-3-NN\" value.\n scriptRuntime: body.scriptRuntime ?? 'python-3-13',\n inputs: normalizeStepInputs(body.inputs),\n secrets: body.secrets ?? {},\n onInstallProgress: (event) => {\n if (event.kind === 'start') {\n broadcast({ type: 'venv-install-start' });\n } else if (event.kind === 'log') {\n broadcast({\n type: 'venv-install-log',\n line: event.line,\n stream: event.stream,\n });\n } else if (event.kind === 'complete') {\n broadcast({ type: 'venv-install-complete' });\n } else {\n broadcast({ type: 'venv-install-error', message: event.message });\n }\n },\n };\n\n if (typeof body.timeout === 'number' && body.timeout > 0) {\n // Cap at 5 minutes so a runaway request can't hang the Python\n // runner indefinitely. Default (30s) still applies if omitted.\n stepParams.timeout = Math.min(body.timeout, 5 * 60 * 1000);\n }\n\n const result = await executePythonStep(stepParams);\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end(JSON.stringify(result));\n\n return;\n }\n\n if (url === '/api/proxy-cache/clear') {\n proxyCache.clear();\n\n createProxyLog({ kind: 'info', message: 'Proxy cache cleared' });\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n\n res.end('{\"ok\":true}');\n\n return;\n }\n\n if (url === '/api/local/encrypt' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n publicKeyPem?: string;\n value?: string;\n };\n\n if (typeof body.publicKeyPem !== 'string' || typeof body.value !== 'string') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Missing required fields: publicKeyPem, value' }));\n\n return;\n }\n\n try {\n const envelope = encrypt(body.value, body.publicKeyPem);\n const serialized = serializeEnvelope(envelope);\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify(serialized));\n } catch (err) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: (err as Error).message }));\n }\n\n return;\n }\n\n if (url === '/api/local/validate' && req.method === 'POST') {\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = JSON.parse(Buffer.concat(chunks).toString('utf-8') || '{}') as {\n value?: string;\n };\n\n if (typeof body.value !== 'string') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Missing required field: value' }));\n\n return;\n }\n\n interface CheckResult {\n label: string;\n expected: string;\n actual: string;\n pass: boolean;\n }\n\n let envelope: ReturnType<typeof deserializeEnvelope> | undefined;\n let parseError: string | undefined;\n\n try {\n envelope = deserializeEnvelope(body.value);\n } catch (err) {\n parseError = (err as Error).message;\n }\n\n if (parseError !== undefined || envelope === undefined) {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ valid: false, checks: [], error: parseError }));\n\n return;\n }\n\n const bufLen = (b64: string): number => Buffer.from(b64, 'base64').length;\n\n const checks: CheckResult[] = [\n {\n label: 'Version',\n expected: String(CRYPTO_VERSION),\n actual: String(envelope.v),\n pass: (envelope.v as number) === CRYPTO_VERSION,\n },\n {\n label: 'Algorithm',\n expected: CRYPTO_ALG,\n actual: envelope.alg,\n pass: (envelope.alg as string) === CRYPTO_ALG,\n },\n {\n label: 'Wrapped key',\n expected: '384 bytes (RSA-3072)',\n actual: `${String(bufLen(envelope.k))} bytes`,\n pass: bufLen(envelope.k) === 384,\n },\n {\n label: 'IV',\n expected: '12 bytes',\n actual: `${String(bufLen(envelope.iv))} bytes`,\n pass: bufLen(envelope.iv) === 12,\n },\n {\n label: 'Auth tag',\n expected: '16 bytes',\n actual: `${String(bufLen(envelope.tag))} bytes`,\n pass: bufLen(envelope.tag) === 16,\n },\n {\n label: 'Ciphertext',\n expected: '≥ 1 byte',\n actual: `${String(bufLen(envelope.ct))} bytes`,\n pass: bufLen(envelope.ct) >= 1,\n },\n ];\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ valid: checks.every((c) => c.pass), checks }));\n\n return;\n }\n\n if (url.startsWith('/api/wizard')) {\n // The viewer sends the saved dev/prod target here; we map it to a known\n // host. A duplicated header arrives as an array — take the first value.\n // Default to 'prod' when absent/invalid: prod is the product-wide\n // default (almost every plugin ships to production), and only an\n // explicit 'dev' routes to the dev keys.\n const rawTarget = req.headers['x-encryption-target'];\n const targetHeader = Array.isArray(rawTarget) ? rawTarget[0] : rawTarget;\n const target: 'dev' | 'prod' = targetHeader === 'dev' ? 'dev' : 'prod';\n const wizardBase = resolveWizardBase(target);\n\n // The credential headers below are forwarded to wizardBase — refuse to\n // forward them anywhere but a known host.\n if (!isAllowedWizardTarget(wizardBase)) {\n res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(\n JSON.stringify({\n error: `Encryption API host is not allowed: ${wizardBase}`,\n }),\n );\n\n return;\n }\n\n const upstreamPath = url.slice('/api/wizard'.length) || '/';\n const upstreamUrl = `${wizardBase}${upstreamPath}`;\n const method = req.method ?? 'GET';\n\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n host: _wizardHost,\n // Internal control header — don't forward it upstream.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n 'x-encryption-target': _encTarget,\n ...wizardForwardHeaders\n } = req.headers;\n\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n const resolvedBody = body && body.length > 0 ? body : undefined;\n\n let upstream: Response;\n\n try {\n upstream = await fetch(upstreamUrl, {\n method,\n headers: wizardForwardHeaders as Record<string, string>,\n ...(resolvedBody !== undefined && { body: resolvedBody }),\n });\n } catch (err) {\n const message =\n (err as NodeJS.ErrnoException).code === 'ECONNREFUSED'\n ? `plugin-wizard is not running at ${wizardBase}`\n : `Failed to reach plugin-wizard: ${(err as Error).message}`;\n\n res.writeHead(503, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: message }));\n\n return;\n }\n\n const wizardResponseHeaders = sanitizeUpstreamHeaders(\n Object.fromEntries(upstream.headers),\n );\n const wizardBody = await upstream.arrayBuffer();\n\n res.writeHead(upstream.status, wizardResponseHeaders);\n res.end(Buffer.from(wizardBody));\n\n return;\n }\n\n if (url.startsWith('/api/proxy')) {\n const proxyTarget = req.headers['x-proxy-target'];\n\n if (typeof proxyTarget !== 'string') {\n res.writeHead(400);\n\n res.end('Missing x-proxy-target header');\n\n return;\n }\n\n if (!isAllowedProxyTarget(proxyTarget)) {\n res.writeHead(400);\n\n res.end('Invalid proxy target');\n\n return;\n }\n\n const upstreamPath = url.slice('/api/proxy'.length) || '/';\n const upstreamUrl = `${proxyTarget}${upstreamPath}`;\n const method = req.method ?? 'GET';\n\n const chunks: Buffer[] = [];\n\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { host, 'x-proxy-target': _drop, ...forwardHeaders } = req.headers;\n\n if (method === 'GET') {\n const cacheKey = `GET::${upstreamUrl}`;\n const { response: cached, fromCache } = await proxyCache.get(cacheKey, () =>\n fetch(upstreamUrl, {\n method: 'GET',\n headers: forwardHeaders as Record<string, string>,\n }),\n );\n\n createProxyLog({\n kind: 'request',\n method: 'GET',\n status: cached.status,\n upstreamStatus: extractUpstreamStatus(upstreamPath, cached.headers, cached.body),\n fromCache,\n url: upstreamPath,\n });\n\n res.writeHead(cached.status, cached.headers);\n\n res.end(cached.body);\n\n return;\n }\n\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n const resolvedBody = body && body.length > 0 ? body : undefined;\n const upstream = await fetch(upstreamUrl, {\n method,\n headers: forwardHeaders as Record<string, string>,\n ...(resolvedBody !== undefined && { body: resolvedBody }),\n });\n const responseHeaders = sanitizeUpstreamHeaders(Object.fromEntries(upstream.headers));\n const responseBody = await readBodyWithLimit(upstream, MAX_PROXY_BYTES);\n\n createProxyLog({\n kind: 'request',\n method,\n status: upstream.status,\n upstreamStatus: extractUpstreamStatus(upstreamPath, responseHeaders, responseBody),\n fromCache: false,\n url: upstreamPath,\n });\n\n res.writeHead(upstream.status, responseHeaders);\n\n res.end(responseBody);\n\n return;\n }\n\n if (url.startsWith('/api/source/tree') && req.method === 'GET') {\n const query = new URL(url, 'http://localhost').searchParams;\n const relParam = query.get('path') ?? '';\n const abs = await resolveSafePath(realPluginDir, relParam);\n\n if (abs === null) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Invalid path' }));\n\n return;\n }\n\n if (isInsideSkippedDir(realPluginDir, abs)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Path is excluded' }));\n\n return;\n }\n\n try {\n const dirEntries = await readdir(abs, { withFileTypes: true });\n const entries = await Promise.all(\n dirEntries\n .filter((entry) => {\n if (entry.isDirectory()) {\n return !SKIP_DIRS.has(entry.name);\n }\n\n if (entry.isFile()) {\n return !SKIP_FILES.has(entry.name);\n }\n\n return false;\n })\n .map(async (entry) => {\n const kind = entry.isDirectory() ? ('dir' as const) : ('file' as const);\n const result: { name: string; kind: 'dir' | 'file'; size?: number } = {\n name: entry.name,\n kind,\n };\n\n if (kind === 'file') {\n try {\n const stats = await stat(join(abs, entry.name));\n\n result.size = stats.size;\n } catch {\n // Ignore stat failures — file may have been deleted mid-scan.\n }\n }\n\n return result;\n }),\n );\n\n entries.sort((a, b) => {\n if (a.kind !== b.kind) {\n return a.kind === 'dir' ? -1 : 1;\n }\n\n return a.name.localeCompare(b.name);\n });\n\n const normalizedPath = abs === realPluginDir ? '' : abs.slice(realPluginDir.length + 1);\n\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ path: normalizedPath, entries }));\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n\n createServerLog(`source/tree failed (${relParam}): ${detail}`);\n\n res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Not found' }));\n }\n\n return;\n }\n\n if (url.startsWith('/api/source/file') && req.method === 'GET') {\n const query = new URL(url, 'http://localhost').searchParams;\n const relParam = query.get('path') ?? '';\n\n if (relParam === '') {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Missing path' }));\n\n return;\n }\n\n const abs = await resolveSafePath(realPluginDir, relParam);\n\n if (abs === null) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Invalid path' }));\n\n return;\n }\n\n if (isInsideSkippedDir(realPluginDir, abs)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Path is excluded' }));\n\n return;\n }\n\n try {\n const stats = await stat(abs);\n\n if (!stats.isFile()) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Not a file' }));\n\n return;\n }\n\n if (stats.size > SOURCE_FILE_MAX_BYTES) {\n res.writeHead(413, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'File too large', size: stats.size }));\n\n return;\n }\n\n const ext = extname(abs).toLowerCase();\n const explicitMime = MIME_TYPES[ext];\n const isKnownText = TEXT_EXTENSIONS.has(ext);\n const contentType =\n explicitMime ??\n (isKnownText ? 'text/plain; charset=utf-8' : 'application/octet-stream');\n\n res.writeHead(200, {\n 'Content-Type': contentType,\n 'Content-Length': String(stats.size),\n });\n createReadStream(abs).pipe(res);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n\n createServerLog(`source/file failed (${relParam}): ${detail}`);\n\n res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: 'Not found' }));\n }\n\n return;\n }\n\n const rawPath = url === '/' ? '/index.html' : url;\n const filePath = join(viewerPath, rawPath);\n const resolvedPath = (await fileExists(filePath))\n ? filePath\n : join(viewerPath, 'index.html');\n const ext = extname(resolvedPath);\n const mimeType = MIME_TYPES[ext] ?? 'application/octet-stream';\n\n res.writeHead(200, { 'Content-Type': mimeType });\n\n createReadStream(resolvedPath).pipe(res);\n } catch (err) {\n if (url.startsWith('/api/proxy')) {\n const upstreamPath = url.slice('/api/proxy'.length) || '/';\n const method = req.method ?? 'GET';\n\n if (err instanceof ProxyResponseTooLargeError) {\n createProxyLog({\n kind: 'info',\n message: `${method} ${upstreamPath} → 502 (response exceeded ${String(err.limit)} bytes)`,\n });\n } else {\n createProxyLog({\n kind: 'request',\n method,\n status: 502,\n fromCache: false,\n url: upstreamPath,\n });\n }\n } else {\n createProxyLog({\n kind: 'info',\n message: `Error handling ${url}: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n if (!res.headersSent) {\n res.writeHead(502);\n\n res.end('Bad Gateway');\n }\n }\n })();\n };\n}\n","export interface CachedResponse {\n status: number;\n headers: Record<string, string>;\n body: Buffer;\n}\n\n// Headers we refuse to pass through from upstream to the browser.\n// - set-cookie: would set Kizen cookies on the localhost origin.\n// - access-control-*: would let upstream relax CORS on our responses.\n// - strict-transport-security: shouldn't govern localhost.\n// - content-security-policy(-report-only), x-frame-options: upstream policy\n// doesn't apply to the local viewer and can conflict with our own CSP.\n// content-encoding / content-length are dropped because fetch auto-decompresses\n// the body; the original sizes/encoding no longer match what we forward.\nconst STRIPPED_RESPONSE_HEADERS = new Set([\n 'set-cookie',\n 'strict-transport-security',\n 'content-security-policy',\n 'content-security-policy-report-only',\n 'x-frame-options',\n 'content-encoding',\n 'content-length',\n]);\n\nexport function sanitizeUpstreamHeaders(headers: Record<string, string>): Record<string, string> {\n const filtered: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(headers)) {\n const lower = key.toLowerCase();\n\n if (STRIPPED_RESPONSE_HEADERS.has(lower) || lower.startsWith('access-control-')) {\n continue;\n }\n\n filtered[key] = value;\n }\n\n return filtered;\n}\n\nexport const MAX_PROXY_BYTES = 10 * 1024 * 1024;\n\n// 60s TTL keeps dev-session queries de-duplicated without masking server-side\n// changes for long. 200 entries caps worst-case memory at ~2GB if every entry\n// were maxed out, which it won't be — typical Kizen JSON responses are <100KB.\nconst CACHE_TTL_MS = 60_000;\nconst CACHE_MAX_ENTRIES = 200;\n\nexport class ProxyResponseTooLargeError extends Error {\n readonly bytesRead: number;\n readonly limit: number;\n\n constructor(bytesRead: number, limit: number) {\n super(`Upstream response exceeded ${String(limit)} bytes (read ${String(bytesRead)}).`);\n this.name = 'ProxyResponseTooLargeError';\n this.bytesRead = bytesRead;\n this.limit = limit;\n }\n}\n\nexport async function readBodyWithLimit(response: Response, limit: number): Promise<Buffer> {\n const body = response.body;\n\n if (body === null) {\n return Buffer.alloc(0);\n }\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n\n for await (const chunk of body as AsyncIterable<Uint8Array>) {\n total += chunk.length;\n\n if (total > limit) {\n throw new ProxyResponseTooLargeError(total, limit);\n }\n\n chunks.push(chunk);\n }\n\n return Buffer.concat(chunks);\n}\n\nexport interface ProxyCache {\n get(\n key: string,\n fetcher: () => Promise<Response>,\n ): Promise<{ response: CachedResponse; fromCache: boolean }>;\n clear(): void;\n}\n\nexport interface ProxyCacheOptions {\n onChange?: (size: number) => void;\n // When false, the cache becomes a pass-through: every request hits upstream\n // and nothing is stored. Used by `appbuilder dev --no-cache`.\n enabled?: boolean;\n}\n\ninterface CacheEntry {\n insertedAt: number;\n promise: Promise<CachedResponse>;\n}\n\nasync function toCachedResponse(response: Response): Promise<CachedResponse> {\n const headers = sanitizeUpstreamHeaders(Object.fromEntries(response.headers));\n const body = await readBodyWithLimit(response, MAX_PROXY_BYTES);\n\n return { status: response.status, headers, body };\n}\n\nexport function createProxyCache(options: ProxyCacheOptions = {}): ProxyCache {\n const { onChange, enabled = true } = options;\n\n if (!enabled) {\n return {\n async get(_key, fetcher) {\n const response = await toCachedResponse(await fetcher());\n\n return { response, fromCache: false };\n },\n clear() {\n // Nothing is stored, so there is nothing to clear.\n },\n };\n }\n\n const cache = new Map<string, CacheEntry>();\n const emitChange = (): void => {\n onChange?.(cache.size);\n };\n\n const evict = (key: string): void => {\n if (cache.delete(key)) {\n emitChange();\n }\n };\n\n return {\n get(\n key: string,\n fetcher: () => Promise<Response>,\n ): Promise<{ response: CachedResponse; fromCache: boolean }> {\n const existing = cache.get(key);\n\n if (existing !== undefined) {\n if (Date.now() - existing.insertedAt < CACHE_TTL_MS) {\n return existing.promise.then((response) => ({ response, fromCache: true }));\n }\n\n // Stale — drop and refetch.\n evict(key);\n }\n\n // Map iteration order is insertion order, so the first key is the oldest.\n // Evicting before insert keeps size strictly ≤ CACHE_MAX_ENTRIES.\n if (cache.size >= CACHE_MAX_ENTRIES) {\n const oldest = cache.keys().next().value;\n\n if (oldest !== undefined) {\n evict(oldest);\n }\n }\n\n const pending = fetcher()\n .then(toCachedResponse)\n .catch((error: unknown) => {\n evict(key);\n throw error;\n });\n\n cache.set(key, { insertedAt: Date.now(), promise: pending });\n\n emitChange();\n\n return pending.then((response) => {\n // Only 2xx responses stay cached; everything else is served once and\n // evicted so the next request re-fetches.\n if (response.status < 200 || response.status >= 300) {\n evict(key);\n }\n\n return { response, fromCache: false };\n });\n },\n\n clear(): void {\n cache.clear();\n\n emitChange();\n },\n };\n}\n","/** Maximum number of log entries retained per log channel. */\nexport const LOG_LIMIT = 50;\n\n/** Number of log lines visible in each TUI log panel. */\nexport const LOG_DISPLAY = 8;\n\n/** Debounce delay for file-watcher triggered rebuilds (ms). */\nexport const FILE_WATCH_DEBOUNCE_MS = 150;\n\nexport const MIME_TYPES: Readonly<Record<string, string>> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.json': 'application/json; charset=utf-8',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.map': 'application/json',\n};\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport interface AppBuilderConfig {\n credentialMode?: 'global' | 'local';\n activeCredentialProfile?: string;\n lastPath?: string;\n // Which encryption API the Secrets page fetches public keys from. Defaults to\n // 'prod' when unset; 'dev' is an explicit per-project override (KZN-16467).\n // (A legacy 'auto' value may exist in older config files; it is read as the\n // 'prod' default — see GET /api/encryption-target.)\n encryptionTarget?: 'dev' | 'prod';\n}\n\nexport async function loadConfig(outputDir: string): Promise<AppBuilderConfig> {\n try {\n const content = await readFile(join(outputDir, 'config.json'), 'utf-8');\n\n return JSON.parse(content) as AppBuilderConfig;\n } catch {\n return {};\n }\n}\n\nexport async function saveConfig(outputDir: string, config: AppBuilderConfig): Promise<void> {\n await mkdir(outputDir, { recursive: true });\n\n await writeFile(join(outputDir, 'config.json'), JSON.stringify(config, null, 2), 'utf-8');\n}\n","/**\n * Shared helper for resolving the encryption API (plugin-wizard) base URL.\n * Imported by both the dev server request handler and the `encrypt` CLI command\n * so the host defaults and env-var names live in one place. KZN-16467.\n */\n\nexport const ENCRYPTION_API_DEFAULTS = {\n prod: 'https://plugin-wizard.kizen.com', // deployed prod encryption service\n dev: 'https://plugin-wizard.kizen.dev', // deployed dev encryption service\n localDev: 'http://localhost:9823', // local plugin-wizard (APPBUILDER_LOCAL_DEV)\n} as const;\n\n/**\n * Resolves the base URL for the encryption API (plugin-wizard) public-key\n * endpoint. Precedence for the `dev` target:\n * 1. `PLUGIN_WIZARD_URL` — forces a single host for ALL targets.\n * 2. `PLUGIN_WIZARD_URL_DEV` — explicit dev URL.\n * 3. `APPBUILDER_LOCAL_DEV` — any non-empty value → localhost:9823.\n * 4. Hardcoded default — deployed dev service.\n * Prod follows the same pattern minus step 3.\n */\nexport function resolveWizardBase(target: 'dev' | 'prod'): string {\n const forced = process.env.PLUGIN_WIZARD_URL;\n\n if (forced !== undefined && forced !== '') {\n return forced;\n }\n\n if (target === 'prod') {\n // `||` (not `??`) so an empty-string env var falls back to the default,\n // matching the PLUGIN_WIZARD_URL / *_DEV branches above and below.\n return process.env.PLUGIN_WIZARD_URL_PROD || ENCRYPTION_API_DEFAULTS.prod;\n }\n\n if (process.env.PLUGIN_WIZARD_URL_DEV !== undefined && process.env.PLUGIN_WIZARD_URL_DEV !== '') {\n return process.env.PLUGIN_WIZARD_URL_DEV;\n }\n\n if (process.env.APPBUILDER_LOCAL_DEV !== undefined && process.env.APPBUILDER_LOCAL_DEV !== '') {\n return ENCRYPTION_API_DEFAULTS.localDev;\n }\n\n return ENCRYPTION_API_DEFAULTS.dev;\n}\n","import { spawn } from 'node:child_process';\nimport { writeFile, rm, mkdtemp, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport requirementsTxt from './python-requirements.txt';\nimport { parseRequirementsFile, resolvePythonBinary } from '../lib/pythonRuntime.js';\nimport {\n type ExecutionResult,\n type HttpRequests,\n type StepInputValue,\n} from '../../shared/lib/execution.js';\nexport type {\n ExecutionResult,\n HttpRequests,\n HttpRequestEntry,\n} from '../../shared/lib/execution.js';\n\nconst WRAPPER_SCRIPT = `\nimport sys, json, os, traceback\n\n# --- Inputs proxy (attribute access) ---\nclass _InputsProxy:\n def __init__(self, data):\n object.__setattr__(self, '_data', data)\n\n def __getattr__(self, name):\n if name.startswith('_'):\n raise AttributeError(name)\n return self._data.get(name)\n\n def __repr__(self):\n return repr(self._data)\n\n def __str__(self):\n return str(self._data)\n\n def __bool__(self):\n return bool(self._data)\n\ninputs = _InputsProxy(json.loads(os.environ.get('__KIZEN_INPUTS__', '{}')))\n\n# --- Secrets ---\nsecrets = json.loads(os.environ.get('__KIZEN_SECRETS__', '{}'))\n\n# --- Outputs proxy ---\nclass _OutputsProxy:\n def __init__(self):\n object.__setattr__(self, '_values', {})\n object.__setattr__(self, '_logs', [])\n\n def __setattr__(self, name, value):\n if name.startswith('_'):\n object.__setattr__(self, name, value)\n else:\n self._values[name] = value\n\n def __getattr__(self, name):\n if name.startswith('_'):\n raise AttributeError(name)\n return self._values.get(name)\n\n def log(self, message):\n self._logs.append(str(message))\n\noutputs = _OutputsProxy()\n\n# --- HTTP request capture (requests library only) ---\n_kizen_http_requests = []\n\ndef _kizen_install_http_capture():\n try:\n import requests\n except Exception:\n return\n import time, datetime\n\n _original_send = requests.Session.send\n\n def _kizen_send(self, request, **kwargs):\n submitted_at = datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d %H:%M:%S')\n start = time.time()\n error_type = None\n response = None\n try:\n response = _original_send(self, request, **kwargs)\n return response\n except Exception as exc:\n error_type = type(exc).__name__\n raise\n finally:\n body = request.body\n if isinstance(body, bytes):\n try:\n body = body.decode('utf-8')\n except Exception:\n body = '<binary>'\n elif body is None:\n body = ''\n\n status = 0\n resp_headers = {}\n resp_body = ''\n if response is not None:\n status = response.status_code\n resp_headers = dict(response.headers)\n if kwargs.get('stream'):\n resp_body = '<streamed>'\n else:\n try:\n resp_body = response.text\n except Exception:\n resp_body = '<unreadable>'\n\n _kizen_http_requests.append({\n 'method': request.method or '',\n 'url': request.url or '',\n 'headers': dict(request.headers or {}),\n 'body': body,\n 'requestSubmittedAt': submitted_at,\n 'session': True,\n 'responseStatusCode': status,\n 'responseHeaders': resp_headers,\n 'responseBody': resp_body,\n 'requestErrorType': error_type,\n 'duration': time.time() - start,\n })\n\n requests.Session.send = _kizen_send\n\n_kizen_install_http_capture()\n\ndef _kizen_http_summary():\n if not _kizen_http_requests:\n return None\n return {\n 'count': len(_kizen_http_requests),\n 'notLogged': 0,\n 'requests': _kizen_http_requests,\n }\n\n# --- Execute user script ---\ntry:\n exec(open(os.environ['__KIZEN_SCRIPT_PATH__'], encoding='utf-8').read())\n result = {\n 'success': True,\n 'outputValues': outputs._values,\n 'logs': outputs._logs,\n 'error': None,\n 'httpRequests': _kizen_http_summary(),\n }\nexcept Exception:\n # Build a clean traceback that hides the wrapper internals.\n # Keep only frames from the user script (shown as File \"<string>\")\n # and re-label them with \"script.py\" for clarity.\n exc_type, exc_value, exc_tb = sys.exc_info()\n entries = traceback.extract_tb(exc_tb)\n user_entries = [e for e in entries if e.filename != __file__]\n for e in user_entries:\n if e.filename == '<string>':\n e.filename = 'script.py'\n lines = ['Traceback (most recent call last):\\\\n']\n lines += traceback.format_list(user_entries)\n lines += traceback.format_exception_only(exc_type, exc_value)\n result = {\n 'success': False,\n 'outputValues': outputs._values,\n 'logs': outputs._logs,\n 'error': ''.join(lines),\n 'httpRequests': _kizen_http_summary(),\n }\n\n# Write results between markers so we can extract them reliably\n# even if the user script wrote to stdout\nsys.stdout.write('\\\\n__KIZEN_RESULT_START__\\\\n')\nsys.stdout.write(json.dumps(result, ensure_ascii=False))\nsys.stdout.write('\\\\n__KIZEN_RESULT_END__\\\\n')\nsys.stdout.flush()\n`.trim();\n\nconst DEFAULT_TIMEOUT = 30_000;\n\nexport type VenvInstallEvent =\n | { kind: 'start' }\n | { kind: 'log'; line: string; stream: 'stdout' | 'stderr' }\n | { kind: 'complete' }\n | { kind: 'error'; message: string };\n\nexport type VenvInstallListener = (event: VenvInstallEvent) => void;\n\nexport interface ExecuteStepParams {\n script: string;\n scriptRuntime: string;\n inputs: Record<string, StepInputValue>;\n secrets: Record<string, string>;\n timeout?: number;\n onInstallProgress?: VenvInstallListener;\n}\n\nconst VENV_DIR = join(process.cwd(), '.kizenapp', 'venv');\n\n// The production Kizen code-runner service only ships python-3-12 and\n// python-3-13 runtime images. Reject any other runtime locally so a bad or\n// unsupported \"runtime\" in a step's config.json fails fast\nconst SUPPORTED_RUNTIMES = ['python-3-12', 'python-3-13'] as const;\n\nfunction isSupportedRuntime(runtime: string): boolean {\n return (SUPPORTED_RUNTIMES as readonly string[]).includes(runtime);\n}\n\n// ./python-requirements.txt is the single source of truth for packages.\n// Keep it in sync with the Python dependency set installed by the production\n// Kizen code-runner service, so local runs match deployed ones.\nconst VENV_PACKAGES = parseRequirementsFile(requirementsTxt);\n\nif (VENV_PACKAGES.length === 0) {\n throw new Error('python-requirements.txt bundled no packages — check the build output');\n}\n\nlet venvReady: Promise<string> | null = null;\n\n// The bundled requirements (psycopg 3.3 in particular) require Python >= 3.10,\n// matching the remote code-runner which only ships 3.12 / 3.13 images. A venv\n// built on an older interpreter fails `pip install` with a cryptic\n// \"No matching distribution found for psycopg[binary]<4.0,>=3.3\".\nconst MIN_PYTHON: readonly [number, number] = [3, 10];\n\nfunction meetsMinimum([major, minor]: [number, number]): boolean {\n return major > MIN_PYTHON[0] || (major === MIN_PYTHON[0] && minor >= MIN_PYTHON[1]);\n}\n\nfunction formatVersion(version: readonly [number, number]): string {\n return `${String(version[0])}.${String(version[1])}`;\n}\n\n// Probe an interpreter for its (major, minor) version. Resolves null if the\n// binary is missing or can't run, so callers can try the next candidate.\nfunction probePython(bin: string): Promise<[number, number] | null> {\n return new Promise((resolve) => {\n const proc = spawn(bin, ['-c', \"import sys; print('%d.%d' % sys.version_info[:2])\"], {\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n\n let out = '';\n\n proc.stdout.on('data', (chunk: Buffer) => {\n out += chunk.toString('utf-8');\n });\n proc.on('error', () => {\n resolve(null);\n });\n proc.on('close', (code) => {\n const match = /(\\d+)\\.(\\d+)/.exec(out);\n\n if (code !== 0 || !match) {\n resolve(null);\n\n return;\n }\n\n resolve([Number(match[1]), Number(match[2])]);\n });\n });\n}\n\n// Pick a system interpreter new enough to install the bundled requirements.\n// Prefer the exact version the runtime asked for, then fall back to python3.\n// Throws a clear, actionable error when nothing usable is found.\nasync function findSystemPython(runtime: string): Promise<string> {\n const preferred = resolvePythonBinary(runtime);\n const candidates = preferred === 'python3' ? ['python3'] : [preferred, 'python3'];\n const tried: string[] = [];\n\n for (const bin of candidates) {\n const version = await probePython(bin);\n\n if (!version) {\n tried.push(`${bin}: not found`);\n\n continue;\n }\n\n if (meetsMinimum(version)) {\n return bin;\n }\n\n tried.push(`${bin}: ${formatVersion(version)} (too old)`);\n }\n\n throw new Error(\n `No Python >= ${formatVersion(MIN_PYTHON)} found for runtime \"${runtime}\". ` +\n `The local runner needs Python ${formatVersion(MIN_PYTHON)}+ to install the bundled ` +\n `packages (e.g. psycopg 3.3), matching the remote code-runner (3.12 / 3.13). ` +\n `Tried ${tried.join(', ')}. Install Python 3.12 or 3.13 and retry.`,\n );\n}\n\nfunction runCommand(\n bin: string,\n args: string[],\n onLine?: (line: string, stream: 'stdout' | 'stderr') => void,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const proc = spawn(bin, args, { stdio: ['ignore', 'pipe', 'pipe'] });\n\n const pipeLines = (source: NodeJS.ReadableStream, stream: 'stdout' | 'stderr'): string[] => {\n const captured: string[] = [];\n let buffer = '';\n\n source.on('data', (chunk: Buffer) => {\n buffer += chunk.toString('utf-8');\n\n let idx = buffer.indexOf('\\n');\n\n while (idx >= 0) {\n const line = buffer.slice(0, idx).replace(/\\r$/, '');\n\n buffer = buffer.slice(idx + 1);\n\n captured.push(line);\n onLine?.(line, stream);\n idx = buffer.indexOf('\\n');\n }\n });\n\n source.on('end', () => {\n if (buffer.length > 0) {\n const line = buffer.replace(/\\r$/, '');\n\n captured.push(line);\n onLine?.(line, stream);\n }\n });\n\n return captured;\n };\n\n const stderrCaptured = pipeLines(proc.stderr, 'stderr');\n\n pipeLines(proc.stdout, 'stdout');\n\n proc.on('error', reject);\n proc.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n const tail = stderrCaptured.slice(-10).join('\\n').trim();\n const detail = tail.length > 0 ? `: ${tail}` : '';\n\n reject(new Error(`${bin} exited with code ${String(code)}${detail}`));\n }\n });\n });\n}\n\n// Progress listeners for the in-flight venv build, so every caller awaiting the\n// same build receives its install output. Non-null only while a build is live,\n// so a cached-return call doesn't leak a listener that never fires.\nlet venvInstallListeners: Set<VenvInstallListener> | null = null;\n\nfunction ensureVenv(runtime: string, listener?: VenvInstallListener): Promise<string> {\n if (venvReady) {\n // Build already running or done. Attach to its progress if it's still live.\n if (listener) {\n venvInstallListeners?.add(listener);\n }\n\n return venvReady;\n }\n\n const listeners = new Set<VenvInstallListener>();\n\n if (listener) {\n listeners.add(listener);\n }\n\n venvInstallListeners = listeners;\n\n const emit = (event: VenvInstallEvent): void => {\n for (const l of listeners) {\n l(event);\n }\n };\n\n const venvPython = join(VENV_DIR, 'bin', 'python');\n\n venvReady = (async () => {\n try {\n // Reuse an existing venv only when its interpreter is new enough for the\n // bundled requirements; otherwise rebuild it. A stale venv (e.g. Python\n // 3.9) would otherwise fail `pip install` every time with a cryptic\n // \"No matching distribution\" error for psycopg 3.3.\n let reusable = false;\n\n try {\n await access(venvPython);\n\n const existing = await probePython(venvPython);\n\n reusable = existing !== null && meetsMinimum(existing);\n } catch {\n reusable = false;\n }\n\n if (!reusable) {\n // Clear any stale/half-built venv before recreating it. Best-effort:\n // rm of a missing dir is a no-op with force.\n await rm(VENV_DIR, { recursive: true, force: true }).catch(() => {\n /* ignore */\n });\n\n const systemPython = await findSystemPython(runtime);\n\n await runCommand(systemPython, ['-m', 'venv', VENV_DIR]);\n }\n\n emit({ kind: 'start' });\n\n await runCommand(\n venvPython,\n ['-m', 'pip', 'install', '--disable-pip-version-check', ...VENV_PACKAGES],\n (line, stream) => {\n emit({ kind: 'log', line, stream });\n },\n );\n\n emit({ kind: 'complete' });\n\n return venvPython;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n\n emit({ kind: 'error', message });\n\n // Reset so the next call retries rather than returning the cached\n // rejection forever. Also nuke the venv dir: a half-built venv (a failed\n // `python -m venv` or an interpreter that's too old) would confuse the\n // reuse check on the next attempt. rm is best-effort — we rebuild either\n // way.\n venvReady = null;\n\n await rm(VENV_DIR, { recursive: true, force: true }).catch(() => {\n /* ignore */\n });\n\n throw err;\n } finally {\n venvInstallListeners = null;\n }\n })();\n\n return venvReady;\n}\n\nfunction parseResult(stdout: string): {\n userStdout: string;\n result: {\n success: boolean;\n outputValues: Record<string, unknown>;\n logs: string[];\n error: string | null;\n httpRequests: HttpRequests | null;\n } | null;\n} {\n const startMarker = '__KIZEN_RESULT_START__';\n const endMarker = '__KIZEN_RESULT_END__';\n const startIdx = stdout.indexOf(startMarker);\n const endIdx = stdout.indexOf(endMarker);\n\n if (startIdx === -1 || endIdx === -1) {\n return { userStdout: stdout, result: null };\n }\n\n const userStdout = stdout.slice(0, startIdx).trimEnd();\n const jsonStr = stdout.slice(startIdx + startMarker.length, endIdx).trim();\n\n try {\n const result = JSON.parse(jsonStr) as {\n success: boolean;\n outputValues: Record<string, unknown>;\n logs: string[];\n error: string | null;\n httpRequests: HttpRequests | null;\n };\n\n return { userStdout, result };\n } catch {\n return { userStdout: stdout, result: null };\n }\n}\n\nfunction failedExecutionResult(error: string): ExecutionResult {\n return {\n success: false,\n outputValues: {},\n logs: [],\n stdout: '',\n stderr: '',\n error,\n exitCode: 1,\n durationMs: 0,\n };\n}\n\nexport async function executePythonStep(params: ExecuteStepParams): Promise<ExecutionResult> {\n const timeout = params.timeout ?? DEFAULT_TIMEOUT;\n\n // Fail fast on a runtime the remote code-runner can't run, instead of\n // silently building a venv on whatever interpreter is handy.\n if (!isSupportedRuntime(params.scriptRuntime)) {\n return failedExecutionResult(\n `Unsupported runtime \"${params.scriptRuntime}\". Supported runtimes: ` +\n `${SUPPORTED_RUNTIMES.join(', ')}. Update the step's config.json \"runtime\" field ` +\n `(e.g. \"python 3.13\").`,\n );\n }\n\n const pythonBin = await ensureVenv(params.scriptRuntime, params.onInstallProgress);\n const start = Date.now();\n\n let tmpDir: string | undefined;\n\n try {\n tmpDir = await mkdtemp(join(tmpdir(), 'kizen-step-'));\n\n const wrapperPath = join(tmpDir, 'wrapper.py');\n const scriptPath = join(tmpDir, 'script.py');\n\n await Promise.all([\n writeFile(wrapperPath, WRAPPER_SCRIPT, 'utf-8'),\n writeFile(scriptPath, params.script, 'utf-8'),\n ]);\n\n const env: Record<string, string> = {\n ...(process.env as Record<string, string>),\n __KIZEN_INPUTS__: JSON.stringify(params.inputs),\n __KIZEN_SECRETS__: JSON.stringify(params.secrets),\n __KIZEN_SCRIPT_PATH__: scriptPath,\n };\n\n const { exitCode, stdout, stderr } = await new Promise<{\n exitCode: number;\n stdout: string;\n stderr: string;\n }>((resolve) => {\n const stdoutChunks: Buffer[] = [];\n const stderrChunks: Buffer[] = [];\n let settled = false;\n\n const proc = spawn(pythonBin, [wrapperPath], {\n env,\n cwd: tmpDir,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n const timer = setTimeout(() => {\n proc.kill('SIGKILL');\n }, timeout);\n\n proc.stdout.on('data', (chunk: Buffer) => {\n stdoutChunks.push(chunk);\n });\n\n proc.stderr.on('data', (chunk: Buffer) => {\n stderrChunks.push(chunk);\n });\n\n const finish = (code: number | null): void => {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timer);\n resolve({\n exitCode: code ?? 1,\n stdout: Buffer.concat(stdoutChunks).toString('utf-8'),\n stderr: Buffer.concat(stderrChunks).toString('utf-8'),\n });\n };\n\n proc.on('close', finish);\n proc.on('error', (err) => {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timer);\n resolve({\n exitCode: 1,\n stdout: '',\n stderr: err.message,\n });\n });\n });\n\n const durationMs = Date.now() - start;\n const { userStdout, result } = parseResult(stdout);\n\n if (result) {\n const base: ExecutionResult = {\n success: result.success,\n outputValues: result.outputValues,\n logs: result.logs,\n stdout: userStdout,\n stderr,\n exitCode,\n durationMs,\n };\n\n if (result.error !== null) {\n base.error = result.error;\n }\n\n if (result.httpRequests) {\n base.httpRequests = result.httpRequests;\n }\n\n return base;\n }\n\n // If we couldn't parse the result, the wrapper itself likely failed\n const base: ExecutionResult = {\n success: false,\n outputValues: {},\n logs: [],\n stdout: userStdout,\n stderr,\n exitCode,\n durationMs,\n };\n\n if (exitCode !== 0) {\n base.error = `Process exited with code ${String(exitCode)}`;\n }\n\n return base;\n } finally {\n if (tmpDir) {\n void rm(tmpDir, { recursive: true, force: true });\n }\n }\n}\n","awslambdaric\nbcrypt\nboto3\nfpdf2\nlxml\nmsgpack\nnumpy\noracledb\nparamiko\npsycopg[binary]>=3.3,<4.0\npyjwt[crypto]\npymysql[rsa,ed25519]\npypdf[full]\npython-dateutil\npytz\nrequests\nsqlalchemy>=2.0,<2.1\ntzdata\n","export function parseRequirementsFile(content: string): string[] {\n return content\n .split('\\n')\n .map((line) => line.trim().replace(/\\s+#.*$/, ''))\n .filter((line) => line.length > 0 && !line.startsWith('#'));\n}\n\nexport function resolvePythonBinary(runtime: string): string {\n const match = /^python-(\\d+)[.-](\\d+)$/.exec(runtime);\n const major = match?.[1];\n const minor = match?.[2];\n\n if (major !== undefined && minor !== undefined) {\n return `python${major}.${minor}`;\n }\n\n return 'python3';\n}\n","export interface HttpRequestEntry {\n method: string;\n url: string;\n headers: Record<string, string>;\n body: string;\n requestSubmittedAt: string;\n session: boolean;\n responseStatusCode: number;\n responseHeaders: Record<string, string>;\n responseBody: string;\n requestErrorType: string | null;\n duration: number;\n}\n\nexport interface HttpRequests {\n count: number;\n notLogged: number;\n requests: HttpRequestEntry[];\n}\n\nexport interface ExecutionResult {\n success: boolean;\n outputValues: Record<string, unknown>;\n logs: string[];\n stdout: string;\n stderr: string;\n error?: string;\n exitCode: number;\n durationMs: number;\n httpRequests?: HttpRequests;\n}\n\nexport type StepInputValue = string | null;\n\nexport function toStepInputValue(raw: string | null | undefined): StepInputValue {\n return raw === undefined || raw === null || raw.trim() === '' ? null : raw;\n}\n\nexport function buildStepInputs(\n names: string[],\n rawValues: Record<string, string>,\n): Record<string, StepInputValue> {\n return Object.fromEntries(names.map((name) => [name, toStepInputValue(rawValues[name])]));\n}\n\nfunction coerceStepInputValue(value: unknown): StepInputValue {\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'string') {\n return toStepInputValue(value);\n }\n\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {\n return String(value);\n }\n\n if (typeof value === 'function' || typeof value === 'symbol') {\n return null;\n }\n\n return JSON.stringify(value);\n}\n\nexport function normalizeStepInputs(\n inputs: Record<string, unknown> | undefined,\n): Record<string, StepInputValue> {\n if (!inputs) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(inputs).map(([name, value]) => [name, coerceStepInputValue(value)]),\n );\n}\n","export const TEXT_EXTENSIONS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.json',\n '.md',\n '.mdx',\n '.yml',\n '.yaml',\n '.toml',\n '.css',\n '.scss',\n '.html',\n '.htm',\n '.xml',\n '.svg',\n '.txt',\n '.sh',\n '.py',\n '.env',\n '.gitignore',\n '.prettierrc',\n '.eslintrc',\n]);\n","export type ProxyLogEntry =\n | {\n kind: 'request';\n method: string;\n status: number;\n // For calls to Kizen's `/external-integrations/proxy` endpoint, the\n // third-party API's status is carried in the response body (`status_code`)\n // rather than the HTTP status. `status` is the proxy status; this is the\n // upstream one. Undefined for non-proxy calls.\n upstreamStatus?: number | undefined;\n fromCache: boolean;\n url: string;\n }\n | { kind: 'info'; message: string };\n\nexport function proxyLogEntryToString(entry: ProxyLogEntry): string {\n if (entry.kind === 'info') {\n return entry.message;\n }\n\n const cache = entry.fromCache ? ' [cache]' : '';\n const upstream =\n entry.upstreamStatus !== undefined ? ` (upstream ${String(entry.upstreamStatus)})` : '';\n\n return `${entry.method} ${entry.url} → ${String(entry.status)}${upstream}${cache}`;\n}\n","import { launch } from 'chrome-launcher';\nimport type { LaunchedChrome } from 'chrome-launcher';\nimport { createRequire } from 'node:module';\nimport { mkdirSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst CDP = createRequire(import.meta.url)('chrome-remote-interface') as (opts: {\n port: number;\n}) => Promise<CDPClient>;\n\ninterface CDPHeader {\n name: string;\n value: string;\n}\n\ninterface CDPFetchPausedEvent {\n requestId: string;\n request: { url: string };\n responseHeaders?: CDPHeader[];\n responseStatusCode?: number;\n}\n\ninterface CDPClient {\n Fetch: {\n enable: (opts: { patterns: { urlPattern: string; requestStage: string }[] }) => Promise<void>;\n getResponseBody: (opts: {\n requestId: string;\n }) => Promise<{ body: string; base64Encoded: boolean }>;\n fulfillRequest: (opts: {\n requestId: string;\n responseCode: number;\n responseHeaders: CDPHeader[];\n body?: string;\n base64Encoded?: boolean;\n }) => Promise<void>;\n continueRequest: (opts: { requestId: string }) => Promise<void>;\n };\n Network: {\n getAllCookies: () => Promise<{ cookies: CDPCookie[] }>;\n setCookie: (opts: CDPCookieSet) => Promise<void>;\n };\n Target: {\n setDiscoverTargets: (opts: { discover: boolean }) => Promise<void>;\n closeTarget: (opts: { targetId: string }) => Promise<void>;\n activateTarget: (opts: { targetId: string }) => Promise<void>;\n };\n Browser: {\n setDockTile: (opts: { image?: string; label?: string }) => Promise<void>;\n };\n send: (method: string, params?: object, sessionId?: string) => Promise<unknown>;\n on: (event: string, handler: (params: unknown, sessionId?: string) => void) => void;\n close: () => Promise<void>;\n}\n\ninterface CDPTargetCreatedEvent {\n targetInfo: {\n targetId: string;\n type: string;\n url: string;\n };\n}\n\ninterface CDPCookie {\n name: string;\n value: string;\n domain?: string;\n path?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: string;\n expirationDate?: number;\n}\n\ninterface CDPCookieSet {\n url: string;\n name: string;\n value: string;\n domain?: string;\n path?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: string;\n expires?: number;\n}\n\nconst CSP_HEADERS = new Set([\n 'content-security-policy',\n 'content-security-policy-report-only',\n 'x-frame-options',\n]);\n\nconst KIZEN_DOMAINS = ['kizen.dev', 'kizen.com'];\n\nfunction isKizenUrl(url: string): boolean {\n try {\n const { hostname } = new URL(url);\n\n return KIZEN_DOMAINS.some((d) => hostname === d || hostname.endsWith('.' + d));\n } catch {\n return false;\n }\n}\n\nasync function installDockIcon(client: CDPClient): Promise<void> {\n try {\n const iconPath = join(dirname(fileURLToPath(import.meta.url)), 'viewer', 'icon.png');\n const icon = await readFile(iconPath);\n\n await client.Browser.setDockTile({ image: icon.toString('base64') });\n } catch {\n // Non-critical: silently skip if icon is missing or platform doesn't support it\n }\n}\n\nexport interface ChromeViewerOptions {\n port: number;\n userDataDir: string;\n broadcast: (msg: object) => void;\n path?: string;\n debugLog?: (msg: string) => void;\n // Always-on channel for user-visible warnings (e.g. \"CDP unavailable,\n // running without interception\"). Unlike debugLog, not gated by --debug.\n onWarn?: (msg: string) => void;\n verbose?: boolean;\n}\n\nexport interface ChromeViewerHandle {\n kill: () => void;\n}\n\nexport async function launchChromeViewer(opts: ChromeViewerOptions): Promise<ChromeViewerHandle> {\n // chrome-launcher opens log files inside userDataDir before Chrome starts\n mkdirSync(opts.userDataDir, { recursive: true });\n\n const baseUrl = `http://localhost:${String(opts.port)}`;\n\n const chrome: LaunchedChrome = await launch({\n startingUrl: baseUrl,\n chromeFlags: [\n `--app=${baseUrl}`,\n '--no-first-run',\n '--no-default-browser-check',\n '--disable-extensions',\n '--disable-features=DeviceBoundSessions',\n ],\n userDataDir: opts.userDataDir,\n handleSIGINT: false,\n logLevel: 'silent',\n });\n\n const cdpPort = chrome.port;\n\n let client: CDPClient | null = null;\n let cookieTimer: ReturnType<typeof setInterval> | null = null;\n let mainTargetId: string | null = null;\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let reconnectAttempt = 0;\n let killed = false;\n\n const dbg = (msg: string): void => {\n opts.debugLog?.(msg);\n };\n\n const vb = (msg: string): void => {\n if (opts.verbose) {\n opts.debugLog?.(msg);\n }\n };\n\n const clearCookieTimer = (): void => {\n if (cookieTimer !== null) {\n clearInterval(cookieTimer);\n cookieTimer = null;\n }\n };\n\n const isNewTabUrl = (url: string): boolean =>\n url === 'chrome://new-tab-page/' || url === 'chrome://newtab/';\n\n const setupClient = async (c: CDPClient): Promise<void> => {\n // Fresh CDP session: reset per-connection state.\n clearCookieTimer();\n mainTargetId = null;\n\n await installDockIcon(c);\n\n // ── 1. Response interception: strip CSP + fix SameSite cookies ──────────────\n await c.Fetch.enable({\n patterns: KIZEN_DOMAINS.flatMap((d) => [\n { urlPattern: `*://${d}/*`, requestStage: 'Response' },\n { urlPattern: `*://*.${d}/*`, requestStage: 'Response' },\n ]),\n });\n\n c.on('Fetch.requestPaused', (rawParams: unknown) => {\n void (async () => {\n const params = rawParams as CDPFetchPausedEvent;\n const { requestId, request, responseHeaders, responseStatusCode } = params;\n const url = request.url;\n\n vb(`Fetch ${String(responseStatusCode ?? '?')} ${url}`);\n\n const filtered: CDPHeader[] = [];\n let rewroteSetCookie = false;\n\n for (const h of responseHeaders ?? []) {\n if (CSP_HEADERS.has(h.name.toLowerCase())) {\n continue;\n }\n\n if (h.name.toLowerCase() === 'set-cookie' && isKizenUrl(url)) {\n const patched = h.value\n .split('\\n')\n .map((cookie) => {\n if (!/SameSite=/i.test(cookie)) {\n return cookie + '; SameSite=None; Secure';\n }\n\n return cookie.replace(/SameSite=\\w+/i, 'SameSite=None');\n })\n .join('\\n');\n\n filtered.push({ name: h.name, value: patched });\n rewroteSetCookie = true;\n } else {\n filtered.push(h);\n }\n }\n\n if (rewroteSetCookie) {\n vb(` rewrote Set-Cookie SameSite on ${url}`);\n }\n\n try {\n const { body, base64Encoded } = await c.Fetch.getResponseBody({ requestId });\n\n await c.Fetch.fulfillRequest({\n requestId,\n responseCode: responseStatusCode ?? 200,\n responseHeaders: filtered,\n body,\n ...(base64Encoded && { base64Encoded: true }),\n });\n } catch (e) {\n vb(` fulfillRequest failed (${(e as Error).message}), falling through`);\n\n try {\n await c.Fetch.continueRequest({ requestId });\n } catch (e2) {\n vb(` continueRequest also failed (${(e2 as Error).message})`);\n }\n }\n })();\n });\n\n // ── 2. Periodic SameSite cookie patching ────────────────────────────────────\n cookieTimer = setInterval(() => {\n void (async () => {\n try {\n const { cookies } = await c.Network.getAllCookies();\n\n let patched = 0;\n\n for (const cookie of cookies) {\n if (!isKizenUrl(`https://${cookie.domain ?? ''}`)) {\n continue;\n }\n\n if (cookie.sameSite === 'None') {\n continue;\n }\n\n const raw = cookie.domain ?? '';\n const bare = raw.startsWith('.') ? raw.slice(1) : raw;\n\n await c.Network.setCookie({\n url: `https://${bare}`,\n name: cookie.name,\n value: cookie.value,\n domain: raw,\n path: cookie.path ?? '/',\n secure: true,\n ...(cookie.httpOnly !== undefined && { httpOnly: cookie.httpOnly }),\n ...(cookie.expirationDate !== undefined && {\n expires: cookie.expirationDate,\n }),\n sameSite: 'None',\n });\n\n patched++;\n }\n\n if (patched > 0) {\n vb(`cookie-patch cycle: updated ${String(patched)} cookie(s) to SameSite=None`);\n }\n } catch (e) {\n vb(`cookie-patch cycle failed: ${(e as Error).message}`);\n }\n })();\n }, 2000);\n\n // macOS dock clicks on --app= windows open a stray new-tab-page window\n // (Chromium excludes app windows from its \"is a browser window open?\" check).\n // activate the original app window, then close the intruder. setDiscoverTargets replays\n // existing targets so mainTargetId gets recaptured after a CDP reconnect.\n await c.Target.setDiscoverTargets({ discover: true });\n\n const handleTarget = (targetInfo: { targetId: string; type: string; url: string }): void => {\n if (targetInfo.type !== 'page') {\n return;\n }\n\n if (isNewTabUrl(targetInfo.url)) {\n dbg(`closed stray new-tab-page target ${targetInfo.targetId}`);\n\n if (mainTargetId !== null) {\n void c.Target.activateTarget({ targetId: mainTargetId }).catch(() => {\n /* ignore */\n });\n }\n\n void c.Target.closeTarget({ targetId: targetInfo.targetId }).catch(() => {\n /* ignore */\n });\n\n return;\n }\n\n if (mainTargetId === null) {\n mainTargetId = targetInfo.targetId;\n dbg(`captured main target ${targetInfo.targetId} (${targetInfo.url})`);\n }\n };\n\n c.on('Target.targetCreated', (rawParams: unknown) => {\n const { targetInfo } = rawParams as CDPTargetCreatedEvent;\n\n vb(`target +${targetInfo.type} ${targetInfo.targetId} ${targetInfo.url}`);\n handleTarget(targetInfo);\n });\n\n c.on('Target.targetInfoChanged', (rawParams: unknown) => {\n const { targetInfo } = rawParams as CDPTargetCreatedEvent;\n\n vb(`target ~${targetInfo.type} ${targetInfo.targetId} ${targetInfo.url}`);\n handleTarget(targetInfo);\n });\n\n // CDP's underlying WebSocket can drop (sleep/wake, transient failure) while\n // Chrome keeps running. Without reconnect, all interception silently stops.\n c.on('disconnect', () => {\n if (killed || client !== c) {\n return;\n }\n\n dbg('CDP disconnected');\n client = null;\n clearCookieTimer();\n scheduleReconnect();\n });\n };\n\n const scheduleReconnect = (): void => {\n if (killed || reconnectTimer !== null) {\n return;\n }\n\n const delay = Math.min(1000 * 2 ** reconnectAttempt, 10_000);\n const attemptNumber = reconnectAttempt + 1;\n\n reconnectAttempt++;\n\n dbg(`CDP reconnect scheduled in ${String(delay)}ms (attempt #${String(attemptNumber)})`);\n\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n\n void (async () => {\n let c: CDPClient;\n\n try {\n c = await CDP({ port: cdpPort });\n } catch {\n dbg(`CDP reconnect attempt #${String(attemptNumber)} failed`);\n scheduleReconnect();\n\n return;\n }\n\n if (killed) {\n try {\n await c.close();\n } catch {\n /* ignore */\n }\n\n return;\n }\n\n client = c;\n\n try {\n await setupClient(c);\n dbg(`CDP reconnected after ${String(attemptNumber)} attempt(s)`);\n reconnectAttempt = 0;\n } catch {\n if (client === c) {\n client = null;\n }\n\n try {\n await c.close();\n } catch {\n /* ignore */\n }\n\n dbg(`CDP reconnect attempt #${String(attemptNumber)} failed during setup`);\n scheduleReconnect();\n }\n })();\n }, delay);\n };\n\n // Initial CDP connection — Chrome may not be ready immediately. 30 × 300ms\n // (9s total) gives cold starts, slow disks, and Rosetta-translated Chromium\n // a reasonable window before we give up and run without interception.\n const MAX_CDP_ATTEMPTS = 30;\n const CDP_ATTEMPT_DELAY_MS = 300;\n\n for (let attempt = 0; attempt < MAX_CDP_ATTEMPTS; attempt++) {\n await new Promise<void>((r) => setTimeout(r, CDP_ATTEMPT_DELAY_MS));\n\n dbg(`CDP connect attempt ${String(attempt + 1)}/${String(MAX_CDP_ATTEMPTS)}`);\n\n try {\n const c = await CDP({ port: cdpPort });\n\n client = c;\n\n if (opts.path) {\n void c.send('Page.navigate', { url: `${baseUrl}${opts.path}` });\n }\n\n try {\n await setupClient(c);\n dbg('CDP connected');\n } catch {\n if (client === c) {\n client = null;\n }\n\n try {\n await c.close();\n } catch {\n /* ignore */\n }\n\n dbg('CDP setup failed after connect');\n }\n\n break;\n } catch {\n if (attempt === MAX_CDP_ATTEMPTS - 1) {\n // CDP never came up; window still opens, just no CSP rewrite or\n // SameSite cookie patching. Surface this via onWarn so it appears in\n // the TUI even when the user didn't pass --debug.\n const warning = `CDP unavailable after ${String(MAX_CDP_ATTEMPTS)} attempts — viewer running without interception (CSP/cookie rewrites disabled)`;\n\n dbg(warning);\n opts.onWarn?.(warning);\n\n return {\n kill: () => {\n chrome.kill();\n },\n };\n }\n }\n }\n\n if (!client) {\n return {\n kill: () => {\n chrome.kill();\n },\n };\n }\n\n const kill = (): void => {\n dbg('CDP kill requested — tearing down');\n killed = true;\n\n if (reconnectTimer !== null) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n\n clearCookieTimer();\n\n if (client !== null) {\n try {\n void client.close();\n } catch {\n /* ignore */\n }\n\n client = null;\n }\n\n chrome.kill();\n };\n\n return { kill };\n}\n","import { useCallback, useState } from 'react';\n\nexport function useLogHistory(limit: number): [string[], (message: string) => void] {\n const [history, setHistory] = useState<string[]>([]);\n\n const append = useCallback(\n (message: string): void => {\n setHistory((h) => [...h, `${new Date().toLocaleTimeString()}: ${message}`].slice(-limit));\n },\n [limit],\n );\n\n return [history, append];\n}\n","import type { FC } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport {\n DEFAULT_PROFILE_NAME,\n ENVIRONMENTS,\n GLOBAL_CREDENTIALS_PATH,\n listCredentialProfiles,\n loadCredentialProfile,\n loadGlobalCredentials,\n saveCredentialProfile,\n} from '../lib/credentials.js';\nimport type { CredentialProfile, Credentials } from '../lib/credentials.js';\nimport { AppHeader } from './AppHeader.js';\n\ntype Mode = 'global' | 'local';\n\ntype Phase =\n | { type: 'mode-select'; cursor: 0 | 1 }\n | { type: 'profile-loading' }\n | { type: 'profile-select'; profiles: CredentialProfile[]; cursor: number }\n | {\n type: 'name-entry';\n nameBuffer: string;\n nameError?: string;\n existingProfiles: CredentialProfile[];\n }\n | { type: 'loading' }\n | { type: 'creds-entry'; field: number; values: Partial<Credentials>; envCursor: number }\n | { type: 'saving' }\n | { type: 'done' };\n\nconst FIELDS = ['apiKey', 'userId', 'businessId'] as const;\nconst FIELD_LABELS: Record<string, string> = {\n apiKey: 'API Key',\n userId: 'User ID',\n businessId: 'Business ID',\n};\n\nexport type CredentialMode = 'global' | 'local';\n\nexport interface CredentialSetupResult {\n mode: CredentialMode;\n credentials: Credentials | null;\n profileName?: string;\n}\n\ninterface CredentialSetupUIProps {\n initialMode?: CredentialMode;\n showProfileManager?: boolean;\n onComplete: (result: CredentialSetupResult) => void;\n onCancel?: () => void;\n}\n\nconst Hint: FC<{ text: string }> = ({ text }) => <Text dimColor>{text}</Text>;\n\nexport const CredentialSetupUI: FC<CredentialSetupUIProps> = ({\n initialMode,\n showProfileManager,\n onComplete,\n onCancel,\n}) => {\n const [phase, setPhase] = useState<Phase>(\n initialMode === 'global' && !showProfileManager\n ? { type: 'loading' }\n : initialMode === 'global' && showProfileManager\n ? { type: 'profile-loading' }\n : { type: 'mode-select', cursor: 0 },\n );\n const [inputBuffer, setInputBuffer] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [activeProfileName, setActiveProfileName] = useState<string | undefined>(undefined);\n\n const handleModeChosen = useCallback(\n (mode: Mode) => {\n if (mode === 'local') {\n onComplete({ mode: 'local', credentials: null });\n\n return;\n }\n\n setPhase({ type: 'profile-loading' });\n },\n [onComplete],\n );\n\n const handleProfileChosen = useCallback(async (profile: CredentialProfile | null) => {\n if (profile === null) {\n // \"Add new profile\" selected\n setPhase({ type: 'profile-loading' });\n\n const profiles = await listCredentialProfiles();\n\n setPhase({ type: 'name-entry', nameBuffer: '', existingProfiles: profiles });\n\n return;\n }\n\n setActiveProfileName(profile.isDefault ? undefined : profile.name);\n\n setPhase({ type: 'loading' });\n\n const existing = profile.isDefault\n ? await loadGlobalCredentials()\n : await loadCredentialProfile(profile.name);\n const envCursor = existing ? Math.max(0, ENVIRONMENTS.indexOf(existing.environment)) : 0;\n\n setPhase({ type: 'creds-entry', field: 0, values: existing ?? {}, envCursor });\n }, []);\n\n const handleSave = useCallback(\n async (values: Partial<Credentials>, envCursor: number) => {\n const environment = ENVIRONMENTS[envCursor] ?? 'go';\n const credentials: Credentials = {\n apiKey: values.apiKey ?? '',\n userId: values.userId ?? '',\n businessId: values.businessId ?? '',\n environment,\n };\n\n setPhase({ type: 'saving' });\n\n try {\n const profileName = activeProfileName ?? DEFAULT_PROFILE_NAME;\n\n await saveCredentialProfile(profileName, credentials);\n\n onComplete({\n mode: 'global',\n credentials,\n ...(activeProfileName !== undefined && { profileName: activeProfileName }),\n });\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n\n setPhase({ type: 'creds-entry', field: 0, values, envCursor });\n }\n },\n [onComplete, activeProfileName],\n );\n\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n process.exit(0);\n }\n\n if (key.escape) {\n if (phase.type === 'creds-entry' || phase.type === 'name-entry') {\n // Go back to profile select if we came from there\n if (initialMode === 'global' && showProfileManager) {\n setPhase({ type: 'profile-loading' });\n\n void loadProfileList();\n\n return;\n }\n }\n\n onCancel?.();\n\n return;\n }\n\n if (phase.type === 'mode-select') {\n if (key.upArrow) {\n setPhase({ type: 'mode-select', cursor: 0 });\n } else if (key.downArrow) {\n setPhase({ type: 'mode-select', cursor: 1 });\n } else if (key.return) {\n const mode: Mode = phase.cursor === 0 ? 'global' : 'local';\n\n handleModeChosen(mode);\n }\n\n return;\n }\n\n if (phase.type === 'profile-select') {\n const { profiles, cursor } = phase;\n const addNewIdx = profiles.length;\n const totalItems = profiles.length + 1; // +1 for \"Add new\"\n\n if (key.upArrow) {\n setPhase({ ...phase, cursor: (cursor - 1 + totalItems) % totalItems });\n } else if (key.downArrow) {\n setPhase({ ...phase, cursor: (cursor + 1) % totalItems });\n } else if (key.return) {\n if (cursor === addNewIdx) {\n setPhase({ type: 'name-entry', nameBuffer: '', existingProfiles: profiles });\n } else {\n const selected = profiles[cursor] ?? profiles[0];\n\n if (selected) {\n void handleProfileChosen(selected);\n }\n }\n }\n\n return;\n }\n\n if (phase.type === 'name-entry') {\n const { nameBuffer, existingProfiles } = phase;\n\n if (key.backspace || key.delete) {\n setPhase({ type: 'name-entry', nameBuffer: nameBuffer.slice(0, -1), existingProfiles });\n } else if (key.return) {\n const trimmed = nameBuffer.trim();\n\n if (!trimmed) {\n setPhase({ ...phase, nameError: 'Name cannot be empty' });\n\n return;\n }\n\n if (trimmed === DEFAULT_PROFILE_NAME) {\n setPhase({ ...phase, nameError: `\"${DEFAULT_PROFILE_NAME}\" is reserved` });\n\n return;\n }\n\n if (existingProfiles.some((p) => p.name === trimmed)) {\n setPhase({ ...phase, nameError: `Profile \"${trimmed}\" already exists` });\n\n return;\n }\n\n // Valid name — proceed to empty creds-entry\n setActiveProfileName(trimmed);\n\n setPhase({ type: 'creds-entry', field: 0, values: {}, envCursor: 0 });\n\n setInputBuffer('');\n } else if (input && !key.ctrl && !key.meta) {\n setPhase({ type: 'name-entry', nameBuffer: nameBuffer + input, existingProfiles });\n }\n\n return;\n }\n\n if (phase.type === 'creds-entry') {\n const { field, values, envCursor } = phase;\n const isEnvField = field === FIELDS.length;\n\n if (isEnvField) {\n if (key.leftArrow) {\n setPhase({\n ...phase,\n envCursor: (envCursor - 1 + ENVIRONMENTS.length) % ENVIRONMENTS.length,\n });\n } else if (key.rightArrow) {\n setPhase({ ...phase, envCursor: (envCursor + 1) % ENVIRONMENTS.length });\n } else if (key.upArrow) {\n setPhase({ ...phase, field: field - 1 });\n\n setInputBuffer(values[FIELDS[field - 1] as keyof typeof values] ?? '');\n } else if (key.return) {\n void handleSave(values, envCursor);\n }\n\n return;\n }\n\n const fieldName = FIELDS[field];\n\n if (!fieldName) {\n return;\n }\n\n if (key.backspace || key.delete) {\n setInputBuffer((prev) => prev.slice(0, -1));\n } else if (key.upArrow && field > 0) {\n const updatedValues = { ...values, [fieldName]: inputBuffer };\n const prevField = field - 1;\n\n setPhase({ ...phase, field: prevField, values: updatedValues });\n\n setInputBuffer(updatedValues[FIELDS[prevField] as keyof typeof updatedValues] ?? '');\n } else if (key.return || key.tab || key.downArrow) {\n const updatedValues = { ...values, [fieldName]: inputBuffer };\n const nextField = field + 1;\n\n setPhase({ ...phase, field: nextField, values: updatedValues });\n\n if (nextField < FIELDS.length) {\n setInputBuffer(updatedValues[FIELDS[nextField] as keyof typeof updatedValues] ?? '');\n } else {\n setInputBuffer('');\n }\n } else if (input && !key.ctrl && !key.meta) {\n setInputBuffer((prev) => prev + input);\n }\n }\n });\n\n const loadProfileList = useCallback(async () => {\n const profiles = await listCredentialProfiles();\n\n setPhase({ type: 'profile-select', profiles, cursor: 0 });\n }, []);\n\n // Load profile list when entering profile-loading phase\n useEffect(() => {\n if (phase.type === 'profile-loading') {\n void loadProfileList();\n }\n }, [phase.type, loadProfileList]);\n\n // Handle initial mode without profile manager (existing behavior)\n useEffect(() => {\n if (initialMode === 'global' && !showProfileManager) {\n void (async () => {\n const existing = await loadGlobalCredentials();\n const envCursor = existing ? Math.max(0, ENVIRONMENTS.indexOf(existing.environment)) : 0;\n\n setPhase({ type: 'creds-entry', field: 0, values: existing ?? {}, envCursor });\n })();\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Reset input buffer when switching to creds-entry\n useEffect(() => {\n if (phase.type === 'creds-entry' && phase.field === 0) {\n setInputBuffer(phase.values.apiKey ?? '');\n }\n }, [phase.type]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (phase.type === 'loading' || phase.type === 'saving' || phase.type === 'profile-loading') {\n const label =\n phase.type === 'saving'\n ? 'Saving credentials…'\n : phase.type === 'profile-loading'\n ? 'Loading profiles…'\n : 'Loading credentials…';\n\n return (\n <Box paddingY={1} paddingX={2}>\n <Text dimColor>{label}</Text>\n </Box>\n );\n }\n\n if (phase.type === 'done') {\n return null;\n }\n\n if (phase.type === 'mode-select') {\n const options: { label: string; desc: string; mode: Mode }[] = [\n { label: 'Global', desc: `~/.kizenappbuilder/credentials.json`, mode: 'global' },\n { label: 'Local', desc: 'Enter credentials in the browser dev tools', mode: 'local' },\n ];\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Credential mode</Text>\n {options.map((opt, i) => {\n const selected = phase.cursor === i;\n\n return (\n <Box key={opt.mode} gap={2}>\n <Text {...(selected && { color: 'cyan' as const })}>{selected ? '❯' : ' '}</Text>\n <Text bold={selected} {...(selected && { color: 'cyan' as const })}>\n {opt.label}\n </Text>\n <Text dimColor>{opt.desc}</Text>\n </Box>\n );\n })}\n </Box>\n <Hint text=\"↑↓ to move · Enter to select · Ctrl+C to quit\" />\n </Box>\n );\n }\n\n if (phase.type === 'profile-select') {\n const { profiles, cursor } = phase;\n const addNewIdx = profiles.length;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>Credential profiles</Text>\n {profiles.map((profile, i) => {\n const selected = cursor === i;\n\n return (\n <Box key={profile.name} gap={2}>\n <Text {...(selected && { color: 'cyan' as const })}>{selected ? '❯' : ' '}</Text>\n <Text bold={selected} {...(selected && { color: 'cyan' as const })}>\n {profile.isDefault ? 'Default' : profile.name}\n </Text>\n <Text dimColor>{profile.path}</Text>\n </Box>\n );\n })}\n <Box gap={2}>\n <Text {...(cursor === addNewIdx && { color: 'cyan' as const })}>\n {cursor === addNewIdx ? '❯' : ' '}\n </Text>\n <Text\n bold={cursor === addNewIdx}\n {...(cursor === addNewIdx && { color: 'cyan' as const })}\n >\n + Add new profile\n </Text>\n </Box>\n </Box>\n <Hint text=\"↑↓ to move · Enter to select · Esc to cancel\" />\n </Box>\n );\n }\n\n if (phase.type === 'name-entry') {\n const { nameBuffer, nameError } = phase;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>New credential profile</Text>\n </Box>\n {nameError && <Text color=\"red\">Error: {nameError}</Text>}\n <Box gap={2}>\n <Box width={12}>\n <Text bold color=\"cyan\">\n Profile name\n </Text>\n </Box>\n <Text color=\"cyan\">{'>'}</Text>\n <Text>{nameBuffer}</Text>\n <Text color=\"cyan\">{'█'}</Text>\n </Box>\n <Hint text=\"Type a name · Enter to confirm · Esc to go back\" />\n </Box>\n );\n }\n\n // creds-entry phase\n const { field: activeField, values, envCursor } = phase;\n const isEnvField = activeField === FIELDS.length;\n const profileLabel = activeProfileName ?? DEFAULT_PROFILE_NAME;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Box flexDirection=\"column\" gap={0}>\n <Text bold>\n {activeProfileName !== undefined ? `Profile: ${activeProfileName}` : 'Global credentials'}\n </Text>\n <Text dimColor>\n Saved to:{' '}\n {activeProfileName !== undefined\n ? `~/.kizenappbuilder/${activeProfileName}.json`\n : GLOBAL_CREDENTIALS_PATH}\n </Text>\n </Box>\n {error && <Text color=\"red\">Error: {error}</Text>}\n <Box flexDirection=\"column\" gap={0}>\n {FIELDS.map((name, i) => {\n const isActive = activeField === i;\n const displayValue = isActive ? inputBuffer : (values[name] ?? '');\n\n return (\n <Box key={name} gap={2}>\n <Box width={12}>\n <Text bold={isActive} {...(isActive && { color: 'cyan' as const })}>\n {FIELD_LABELS[name]}\n </Text>\n </Box>\n <Text {...(isActive && { color: 'cyan' as const })}>{'>'}</Text>\n <Text>{displayValue}</Text>\n {isActive && <Text color=\"cyan\">{'█'}</Text>}\n </Box>\n );\n })}\n <Box gap={2}>\n <Box width={12}>\n <Text bold={isEnvField} {...(isEnvField && { color: 'cyan' as const })}>\n Environment\n </Text>\n </Box>\n <Text {...(isEnvField && { color: 'cyan' as const })}>{'>'}</Text>\n <Box gap={1}>\n {ENVIRONMENTS.map((env, i) => {\n const isSelected = i === envCursor;\n\n if (isEnvField) {\n return (\n <Text key={env} bold={isSelected} {...(isSelected && { color: 'cyan' as const })}>\n {isSelected ? `[${env}]` : env}\n </Text>\n );\n }\n\n return (\n <Text key={env} dimColor={!isSelected} bold={isSelected}>\n {env}\n </Text>\n );\n })}\n </Box>\n </Box>\n </Box>\n {isEnvField ? (\n <Hint text=\"←→ to select · ↑↓ to move · Enter to save · Esc to cancel\" />\n ) : (\n <Hint text=\"↑↓ to move · Backspace to delete · Esc to cancel\" />\n )}\n <Text dimColor>Profile: {profileLabel}</Text>\n </Box>\n );\n};\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { EncryptUI } from '../ui/EncryptUI.js';\nimport { encryptSecret } from '../lib/encryptionClient.js';\nimport type { EncryptionContext } from '../lib/encryptionClient.js';\nimport { loadCredentialsFromFile, loadGlobalCredentials } from '../lib/credentials.js';\nimport {\n invalidStageMessage,\n isValidStage,\n readManifestDefaults,\n readStdin,\n resolveStage,\n writeEnvelopeFile,\n type ManifestDefaults,\n} from '../lib/encryptHelpers.js';\nimport { runHeadless } from '../lib/encryptHeadless.js';\n\ninterface EncryptOptions {\n remote?: boolean;\n credentials?: string;\n apiName?: string;\n value?: string;\n stage?: string;\n out?: string;\n}\n\nexport function encryptCommand(program: Command): void {\n program\n .command('encrypt')\n .description('Encrypt a secret for a plugin against its encryption keys')\n .option('--remote', \"encrypt via the plugin-wizard's remote API instead of on-machine\")\n .option('-c, --credentials <path>', 'path to a credentials JSON file')\n .option('-a, --api-name <name>', 'plugin api_name the secret belongs to')\n .option('-v, --value <value>', 'plaintext secret value to encrypt')\n .option('-s, --stage <stage>', 'which encryption API to use: dev or prod (default: prod)')\n .option('-o, --out <path>', 'also write the encrypted envelope to a file')\n .action(async (options: EncryptOptions) => {\n if (options.stage !== undefined && !isValidStage(options.stage)) {\n console.error(invalidStageMessage(options.stage));\n process.exit(1);\n }\n\n // Read kizen.json for the api_name default. Skip the file read entirely\n // when api_name is already supplied via a flag.\n const needsDefaults = options.apiName === undefined;\n const defaults: ManifestDefaults = needsDefaults ? await readManifestDefaults() : {};\n\n // Default to prod when --stage isn't given (almost every plugin ships to\n // production); pass --stage dev to override.\n const { stage, wasDefaulted: stageWasDefaulted } = resolveStage(options.stage);\n\n const ctx: EncryptionContext = {\n isRemote: options.remote === true,\n stage,\n };\n\n // ink's interactive UI needs a TTY for raw-mode input AND a TTY stdout to\n // render into. If either is redirected/piped (CI, `> out.json`, `| jq`),\n // fall back to the headless flow so stdout gets clean compact JSON instead\n // of ANSI frames.\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n try {\n await runHeadless(ctx, options, defaults, stageWasDefaulted, {\n loadCredentialsFromFile,\n loadGlobalCredentials,\n encryptSecret,\n readStdin,\n stdinIsTTY: () => process.stdin.isTTY,\n writeStdout: (text) => {\n process.stdout.write(text);\n },\n writeStderr: (text) => {\n process.stderr.write(text);\n },\n writeEnvelopeFile,\n setExitCode: (code) => {\n process.exitCode = code;\n },\n });\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n return;\n }\n\n // The UI copies to the clipboard itself; we capture the raw value here so\n // that after ink unmounts we can write --out (ink's rendered frame\n // soft-wraps the long base64, so we never read the envelope back off it).\n let envelopeValue: string | undefined;\n\n const { waitUntilExit } = render(\n createElement(EncryptUI, {\n ctx,\n stageDefaulted: stageWasDefaulted,\n onDone: (value: string) => {\n envelopeValue = value;\n },\n ...(options.credentials !== undefined && { credentialsPath: options.credentials }),\n ...(options.apiName !== undefined && { initialApiName: options.apiName }),\n ...(defaults.apiName !== undefined && { defaultApiName: defaults.apiName }),\n ...(options.value !== undefined && { initialValue: options.value }),\n }),\n { exitOnCtrlC: false },\n );\n\n await waitUntilExit();\n\n // envelopeValue is only set on success (onDone); stays undefined on Ctrl+C\n // or error, so nothing is written in those cases.\n if (envelopeValue !== undefined && options.out !== undefined) {\n try {\n await writeEnvelopeFile(options.out, envelopeValue);\n process.stderr.write(`Wrote encrypted envelope to ${options.out}\\n`);\n } catch (err) {\n console.error(\n `Error writing ${options.out}: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exitCode = 1;\n }\n }\n });\n}\n","import type { FC, ReactNode } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport {\n listCredentialProfiles,\n loadCredentialProfile,\n loadCredentialsFromFile,\n loadGlobalCredentials,\n} from '../lib/credentials.js';\nimport type { CredentialProfile, Credentials } from '../lib/credentials.js';\nimport { encryptSecret } from '../lib/encryptionClient.js';\nimport type { EncryptionContext } from '../lib/encryptionClient.js';\nimport { copyToClipboard } from '../lib/clipboard.js';\nimport { AppHeader } from './AppHeader.js';\nimport { Spinner } from './Spinner.js';\n\ninterface EncryptUIProps {\n ctx: EncryptionContext;\n /** True when --stage was not given and the stage fell back to the prod default. */\n stageDefaulted?: boolean;\n /** Skip the profile picker and load from this file instead. */\n credentialsPath?: string;\n /** Provided via --api-name; skips the api_name prompt. */\n initialApiName?: string;\n /** Prefill for the api_name prompt (from kizen.json) — does not skip it. */\n defaultApiName?: string;\n /** Provided via --value; skips the secret prompt. */\n initialValue?: string;\n /** Called once with the base64 envelope value when encryption succeeds, so the\n * caller can write --out / emit it after ink unmounts. */\n onDone?: (envelopeValue: string) => void;\n}\n\ntype Phase =\n | { type: 'loading' }\n | { type: 'profile-select'; profiles: CredentialProfile[]; cursor: number }\n | { type: 'api-name-entry'; buffer: string; error?: string }\n | { type: 'value-entry'; buffer: string; error?: string }\n | { type: 'fetching-key' }\n | { type: 'encrypting' }\n | { type: 'done'; envelope: string; copied: boolean }\n | { type: 'error'; message: string };\n\nconst Hint: FC<{ text: string }> = ({ text }) => <Text dimColor>{text}</Text>;\n\nexport const EncryptUI: FC<EncryptUIProps> = ({\n ctx,\n stageDefaulted,\n credentialsPath,\n initialApiName,\n defaultApiName,\n initialValue,\n onDone,\n}) => {\n const app = useApp();\n const [phase, setPhase] = useState<Phase>({ type: 'loading' });\n const [credentials, setCredentials] = useState<Credentials | null>(null);\n const [apiName, setApiName] = useState<string>(initialApiName ?? '');\n const [secret, setSecret] = useState<string>(initialValue ?? '');\n\n const fail = useCallback((err: unknown) => {\n process.exitCode = 1;\n // Exit is deferred to the terminal-phase effect below so the error frame is\n // actually painted before ink unmounts.\n setPhase({ type: 'error', message: err instanceof Error ? err.message : String(err) });\n }, []);\n\n const runEncryption = useCallback(\n async (creds: Credentials, name: string, value: string) => {\n try {\n const envelopeValue = await encryptSecret(ctx, creds, name, value, (p) => {\n setPhase(p === 'fetching-key' ? { type: 'fetching-key' } : { type: 'encrypting' });\n });\n const envelope = JSON.stringify({ encrypted: true, value: envelopeValue }, null, 2);\n\n onDone?.(envelopeValue);\n\n // Copy the envelope to the clipboard so the user can paste it without the\n // terminal's soft-wrapping becoming real line breaks in the copied text.\n // The envelope is ciphertext (never the plaintext secret), so this is\n // safe; the copy is best-effort and the envelope is shown either way.\n const copied = await copyToClipboard(envelope);\n\n // Exit is deferred to the terminal-phase effect below so the done frame\n // (with the envelope) is painted before ink unmounts.\n setPhase({ type: 'done', envelope, copied });\n } catch (err) {\n fail(err);\n }\n },\n [ctx, fail, onDone],\n );\n\n // Advance to the next required input, or kick off the encryption once we have\n // everything. Args are passed explicitly so we never read stale state.\n const proceed = useCallback(\n (creds: Credentials, name: string, value: string) => {\n if (name.trim() === '') {\n setPhase({ type: 'api-name-entry', buffer: defaultApiName ?? '' });\n\n return;\n }\n\n if (value === '') {\n setPhase({ type: 'value-entry', buffer: '' });\n\n return;\n }\n\n void runEncryption(creds, name.trim(), value);\n },\n [defaultApiName, runEncryption],\n );\n\n const handleProfileChosen = useCallback(\n async (profile: CredentialProfile) => {\n try {\n setPhase({ type: 'loading' });\n\n const creds = profile.isDefault\n ? await loadGlobalCredentials()\n : await loadCredentialProfile(profile.name);\n\n if (creds === null) {\n throw new Error(`Could not load credential profile: ${profile.name}`);\n }\n\n setCredentials(creds);\n proceed(creds, apiName, secret);\n } catch (err) {\n fail(err);\n }\n },\n [apiName, secret, proceed, fail],\n );\n\n // Resolve credentials on mount, then either show the picker or move on.\n useEffect(() => {\n void (async () => {\n try {\n if (credentialsPath !== undefined) {\n // loadCredentialsFromFile throws on a missing/invalid file; wrap it so\n // the error frame shows which path failed rather than a raw ENOENT.\n let creds: Credentials;\n\n try {\n creds = await loadCredentialsFromFile(credentialsPath);\n } catch (err) {\n throw new Error(\n `Could not load credentials from ${credentialsPath}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n\n setCredentials(creds);\n proceed(creds, apiName, secret);\n\n return;\n }\n\n const profiles = await listCredentialProfiles();\n\n if (profiles.length === 0) {\n throw new Error(\n 'No credential profiles found. Create ~/.kizenappbuilder/credentials.json first.',\n );\n }\n\n const [only] = profiles;\n\n if (profiles.length === 1 && only !== undefined) {\n const creds = only.isDefault\n ? await loadGlobalCredentials()\n : await loadCredentialProfile(only.name);\n\n if (creds === null) {\n throw new Error(`Could not load credential profile: ${only.name}`);\n }\n\n setCredentials(creds);\n proceed(creds, apiName, secret);\n\n return;\n }\n\n setPhase({ type: 'profile-select', profiles, cursor: 0 });\n } catch (err) {\n fail(err);\n }\n })();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Exit only once a terminal frame has been committed and written to the\n // terminal. Calling app.exit() in the same tick as the setPhase would unmount\n // ink before it paints the done/error frame, leaving the spinner as the last\n // thing on screen.\n useEffect(() => {\n if (phase.type === 'done' || phase.type === 'error') {\n app.exit();\n }\n }, [phase, app]);\n\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n process.exitCode = 130;\n app.exit();\n\n return;\n }\n\n if (phase.type === 'profile-select') {\n const { profiles, cursor } = phase;\n\n if (key.upArrow) {\n setPhase({ ...phase, cursor: (cursor - 1 + profiles.length) % profiles.length });\n } else if (key.downArrow) {\n setPhase({ ...phase, cursor: (cursor + 1) % profiles.length });\n } else if (key.return) {\n // cursor is kept in range by the modulo above, so this is always defined.\n const selected = profiles[cursor];\n\n if (selected !== undefined) {\n void handleProfileChosen(selected);\n }\n }\n\n return;\n }\n\n if (phase.type === 'api-name-entry') {\n const { buffer } = phase;\n\n if (key.backspace || key.delete) {\n setPhase({ type: 'api-name-entry', buffer: buffer.slice(0, -1) });\n } else if (key.return) {\n const name = buffer.trim();\n\n if (name === '') {\n setPhase({ type: 'api-name-entry', buffer, error: 'api_name cannot be empty' });\n\n return;\n }\n\n setApiName(name);\n\n if (credentials) {\n proceed(credentials, name, secret);\n } else {\n fail(new Error('Internal error: credentials were not loaded'));\n }\n } else if (input && !key.ctrl && !key.meta) {\n setPhase({ type: 'api-name-entry', buffer: buffer + input });\n }\n\n return;\n }\n\n if (phase.type === 'value-entry') {\n const { buffer } = phase;\n\n if (key.backspace || key.delete) {\n setPhase({ type: 'value-entry', buffer: buffer.slice(0, -1) });\n } else if (key.return) {\n if (buffer === '') {\n setPhase({ type: 'value-entry', buffer, error: 'secret cannot be empty' });\n\n return;\n }\n\n setSecret(buffer);\n\n if (credentials) {\n proceed(credentials, apiName, buffer);\n } else {\n fail(new Error('Internal error: credentials were not loaded'));\n }\n } else if (input && !key.ctrl && !key.meta) {\n setPhase({ type: 'value-entry', buffer: buffer + input });\n }\n\n return;\n }\n });\n\n const modeLabel = ctx.isRemote ? 'remote Kizen API' : 'on-machine';\n\n const stageLabel = stageDefaulted === true ? `${ctx.stage} (default)` : ctx.stage;\n\n const frame = (children: ReactNode): ReactNode => (\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n <AppHeader />\n <Text dimColor>\n Mode: {modeLabel} Stage: {stageLabel}\n </Text>\n {children}\n </Box>\n );\n\n if (phase.type === 'loading') {\n return frame(\n <Box gap={1}>\n <Spinner />\n <Text dimColor>Loading credentials…</Text>\n </Box>,\n );\n }\n\n if (phase.type === 'profile-select') {\n const { profiles, cursor } = phase;\n\n return frame(\n <>\n <Text bold>Credential profile</Text>\n <Box flexDirection=\"column\">\n {profiles.map((profile, i) => {\n const selected = cursor === i;\n\n return (\n <Box key={profile.name} gap={2}>\n <Text {...(selected && { color: 'cyan' as const })}>{selected ? '❯' : ' '}</Text>\n <Text bold={selected} {...(selected && { color: 'cyan' as const })}>\n {profile.isDefault ? 'Default' : profile.name}\n </Text>\n <Text dimColor>{profile.path}</Text>\n </Box>\n );\n })}\n </Box>\n <Hint text=\"↑↓ to move · Enter to select · Ctrl+C to quit\" />\n </>,\n );\n }\n\n if (phase.type === 'api-name-entry') {\n return frame(\n <>\n <Text bold>Plugin api_name</Text>\n {phase.error !== undefined && <Text color=\"red\">Error: {phase.error}</Text>}\n <Box gap={1}>\n <Text color=\"cyan\">{'>'}</Text>\n <Text>{phase.buffer}</Text>\n <Text color=\"cyan\">█</Text>\n </Box>\n <Hint text=\"Type the api_name · Enter to confirm · Ctrl+C to quit\" />\n </>,\n );\n }\n\n if (phase.type === 'value-entry') {\n return frame(\n <>\n <Text bold>Secret value</Text>\n {phase.error !== undefined && <Text color=\"red\">Error: {phase.error}</Text>}\n <Box gap={1}>\n <Text color=\"cyan\">{'>'}</Text>\n <Text>{'•'.repeat(phase.buffer.length)}</Text>\n <Text color=\"cyan\">█</Text>\n </Box>\n <Hint text=\"Input hidden · Enter to encrypt · Ctrl+C to quit\" />\n </>,\n );\n }\n\n if (phase.type === 'fetching-key') {\n return frame(\n <Box gap={1}>\n <Spinner />\n <Text>\n Fetching {ctx.stage} public key for <Text bold>{apiName}</Text>…\n </Text>\n </Box>,\n );\n }\n\n if (phase.type === 'encrypting') {\n return frame(\n <Box gap={1}>\n <Spinner />\n <Text>Encrypting…</Text>\n </Box>,\n );\n }\n\n if (phase.type === 'error') {\n return frame(\n <Box gap={1}>\n <Text color=\"red\">✗</Text>\n <Text color=\"red\">{phase.message}</Text>\n </Box>,\n );\n }\n\n // phase.type === 'done'\n return frame(\n <>\n <Box gap={1}>\n <Text color=\"green\">✓</Text>\n <Text bold>Encrypted secret ready</Text>\n </Box>\n {phase.copied ? (\n <Text color=\"green\">\n ✓ Copied to clipboard — paste it into the secret value in your kizen.json.\n </Text>\n ) : (\n <Text dimColor>\n {'Paste this into the secret value in your kizen.json (re-run with --out <path> to save ' +\n 'it to a file; selecting it here may capture line wraps):'}\n </Text>\n )}\n <Text>{phase.envelope}</Text>\n </>,\n );\n};\n","/**\n * Network + crypto helpers for the `encrypt` command, shared between the ink UI\n * and any non-interactive callers. Keeping these out of the React tree means the\n * dev/prod routing and envelope handling live in one testable place. KZN-16467.\n *\n * Both modes talk to the encryption API (plugin-wizard) DIRECTLY via\n * `resolveWizardBase(stage)` — the app-builder dev server is never involved, so\n * `appbuilder encrypt` works without `appbuilder dev` running:\n * - on-machine (default): fetch the public key, then encrypt in-process.\n * - remote (`--remote`): POST the plaintext to the wizard's /encrypt endpoint\n * and let it do the crypto with the keypair it already holds.\n */\nimport { encrypt, serializeEnvelope } from '@kizenapps/packager';\nimport type { Credentials } from './credentials.js';\nimport { resolveWizardBase } from './wizardUrl.js';\n\nexport interface EncryptionContext {\n /**\n * When true, the wizard's /encrypt endpoint performs the encryption; otherwise\n * we fetch the public key and encrypt on-machine. Either way the request goes\n * straight to the wizard host — never through the app-builder dev server.\n */\n isRemote: boolean;\n /** Which encryption API to target. */\n stage: 'dev' | 'prod';\n}\n\n/** Phases reported while encrypting, so a UI can show progress. */\nexport type EncryptPhase = 'fetching-key' | 'encrypting';\n\n/**\n * Node's fetch (undici) wraps socket failures in a generic `TypeError: fetch\n * failed`, stashing the real error (with its `code`) on `.cause`. Look in both\n * places so we can surface a friendlier \"not running\" message.\n */\nfunction isConnRefused(err: unknown): boolean {\n const e = err as { code?: string; cause?: { code?: string } };\n\n return e.code === 'ECONNREFUSED' || e.cause?.code === 'ECONNREFUSED';\n}\n\nfunction authHeaders(credentials: Credentials): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n 'x-api-key': credentials.apiKey,\n 'x-user-id': credentials.userId,\n 'x-business-id': credentials.businessId,\n 'x-auth-environment': credentials.environment,\n };\n}\n\n/** Wraps a fetch to the wizard so connection failures read clearly. */\nasync function wizardFetch(wizardBase: string, path: string, init: RequestInit): Promise<Response> {\n try {\n return await fetch(`${wizardBase}${path}`, init);\n } catch (err) {\n throw new Error(\n isConnRefused(err)\n ? `Plugin-wizard is not running at ${wizardBase}`\n : `Failed to reach plugin-wizard: ${(err as Error).message}`,\n );\n }\n}\n\n/**\n * Parses a wizard JSON response without throwing on a non-JSON body. Upstream\n * errors can arrive as HTML 502 pages, plain-text 429s, or an auth 401 raised\n * before the JSON handler runs — calling res.json() on those would throw an\n * opaque SyntaxError and hide the real status. Returning {} lets callers fall\n * back to a clear HTTP-status error.\n */\nasync function readJsonSafe(res: Response): Promise<Record<string, unknown>> {\n const text = await res.text();\n\n if (text === '') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(text) as unknown;\n\n return typeof parsed === 'object' && parsed !== null ? (parsed as Record<string, unknown>) : {};\n } catch {\n return {};\n }\n}\n\n/**\n * Fetches the public key for a plugin directly from the wizard host. Used by the\n * on-machine encryption path.\n */\nexport async function fetchPublicKey(\n ctx: EncryptionContext,\n credentials: Credentials,\n apiName: string,\n): Promise<string> {\n const wizardBase = resolveWizardBase(ctx.stage);\n const res = await wizardFetch(wizardBase, '/get-public-key', {\n method: 'POST',\n headers: authHeaders(credentials),\n body: JSON.stringify({ api_name: apiName }),\n });\n\n const data = await readJsonSafe(res);\n\n if (!res.ok || typeof data.public_key !== 'string') {\n const errMsg = typeof data.error === 'string' ? data.error : `HTTP ${String(res.status)}`;\n\n throw new Error(`Failed to fetch public key: ${errMsg}`);\n }\n\n return data.public_key;\n}\n\n/** Encrypts a value in-process via @kizenapps/packager and returns the\n * serialized envelope's base64 `value`. */\nfunction encryptLocally(publicKeyPem: string, value: string): string {\n const envelope = encrypt(value, publicKeyPem);\n const serialized = serializeEnvelope(envelope) as { encrypted?: boolean; value?: unknown };\n\n if (typeof serialized.value !== 'string') {\n throw new Error('Unexpected serialized envelope shape from @kizenapps/packager');\n }\n\n return serialized.value;\n}\n\n/**\n * Asks the wizard's /encrypt endpoint to encrypt the value with the keypair it\n * holds for `apiName`, returning the serialized envelope's base64 `value`. The\n * wizard fetches its own public key, so no separate get-public-key call is made.\n */\nasync function encryptRemote(\n ctx: EncryptionContext,\n credentials: Credentials,\n apiName: string,\n value: string,\n): Promise<string> {\n const wizardBase = resolveWizardBase(ctx.stage);\n const res = await wizardFetch(wizardBase, '/encrypt', {\n method: 'POST',\n headers: authHeaders(credentials),\n body: JSON.stringify({ api_name: apiName, value }),\n });\n\n const data = await readJsonSafe(res);\n\n if (!res.ok || data.encrypted !== true || typeof data.value !== 'string') {\n const errMsg = typeof data.error === 'string' ? data.error : `HTTP ${String(res.status)}`;\n\n throw new Error(`Encryption via plugin-wizard failed: ${errMsg}`);\n }\n\n return data.value;\n}\n\nexport async function encryptSecret(\n ctx: EncryptionContext,\n credentials: Credentials,\n apiName: string,\n value: string,\n onPhase?: (phase: EncryptPhase) => void,\n): Promise<string> {\n if (ctx.isRemote) {\n onPhase?.('encrypting');\n\n return encryptRemote(ctx, credentials, apiName, value);\n }\n\n onPhase?.('fetching-key');\n\n const publicKey = await fetchPublicKey(ctx, credentials, apiName);\n\n onPhase?.('encrypting');\n\n return encryptLocally(publicKey, value);\n}\n","/**\n * Best-effort system-clipboard copy with no third-party dependency. Used by the\n * `encrypt` command so the user can paste the envelope without the terminal's\n * soft-wrapping turning into real line breaks in the copied text.\n *\n * Only the encrypted envelope (ciphertext) is ever copied — never a plaintext\n * secret — so writing it to the clipboard is safe.\n */\nimport { spawn } from 'node:child_process';\nimport { platform } from 'node:process';\n\ninterface ClipboardCommand {\n cmd: string;\n args: string[];\n}\n\n/**\n * Clipboard tools to try, in order, for the current platform. Linux/other has\n * several candidates (Wayland first, then X11) since none is guaranteed.\n */\nfunction clipboardCommands(): ClipboardCommand[] {\n if (platform === 'darwin') {\n return [{ cmd: 'pbcopy', args: [] }];\n }\n\n if (platform === 'win32') {\n return [{ cmd: 'clip', args: [] }];\n }\n\n return [\n // wl-copy (Wayland) intentionally WITHOUT --foreground: the default forks a\n // background process that keeps serving the selection after this CLI exits.\n // --foreground would instead tie the selection to our process, so the 2s\n // kill-timeout below would terminate it and wipe the clipboard.\n { cmd: 'wl-copy', args: [] },\n { cmd: 'xclip', args: ['-selection', 'clipboard'] },\n { cmd: 'xsel', args: ['--clipboard', '--input'] },\n ];\n}\n\n/** How long to wait for a clipboard tool before giving up. Encryption has\n * already succeeded by the time we copy, so a tool that hangs (some Linux\n * xclip/xsel setups can) must never freeze the CLI — it just falls back. */\nconst CLIPBOARD_TIMEOUT_MS = 2000;\n\n/** Pipes `text` into one clipboard command. Resolves false (never rejects) on\n * any failure — a missing tool (ENOENT), a non-zero exit, a broken pipe, or a\n * tool that doesn't exit within the timeout. */\nfunction runClipboardCommand(text: string, { cmd, args }: ClipboardCommand): Promise<boolean> {\n return new Promise((resolve) => {\n let child;\n\n try {\n child = spawn(cmd, args, { stdio: ['pipe', 'ignore', 'ignore'] });\n } catch {\n // Spawn threw synchronously (e.g. invalid command) — nothing to clean up.\n resolve(false);\n\n return;\n }\n\n const spawned = child;\n let settled = false;\n\n function finish(ok: boolean): void {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timer);\n resolve(ok);\n }\n\n const timer = setTimeout(() => {\n spawned.kill();\n finish(false);\n }, CLIPBOARD_TIMEOUT_MS);\n\n // Don't let a pending clipboard timer keep the process alive on its own.\n timer.unref();\n\n spawned.on('error', () => {\n finish(false);\n });\n spawned.on('close', (code) => {\n finish(code === 0);\n });\n spawned.stdin.on('error', () => {\n finish(false);\n });\n\n try {\n spawned.stdin.end(text);\n } catch {\n finish(false);\n }\n });\n}\n\n/**\n * Copies `text` to the system clipboard, returning whether it succeeded. Tries\n * each platform candidate until one works; returns false if none is available.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n for (const command of clipboardCommands()) {\n if (await runClipboardCommand(text, command)) {\n return true;\n }\n }\n\n return false;\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport type EncryptStage = 'dev' | 'prod';\n\nexport function envelopeObject(value: string): { encrypted: true; value: string } {\n return { encrypted: true, value };\n}\n\nexport function compactEnvelope(value: string): string {\n return JSON.stringify(envelopeObject(value));\n}\n\nexport async function writeEnvelopeFile(path: string, value: string): Promise<void> {\n await writeFile(path, `${JSON.stringify(envelopeObject(value), null, 2)}\\n`, 'utf-8');\n}\n\nexport interface ManifestDefaults {\n apiName?: string;\n}\n\nexport const DEFAULT_STAGE: EncryptStage = 'prod';\n\nexport function isValidStage(stage: string): stage is EncryptStage {\n return stage === 'dev' || stage === 'prod';\n}\n\nexport function invalidStageMessage(stage: string): string {\n return `Error: --stage must be \"dev\" or \"prod\" (got: \"${stage}\")`;\n}\n\nexport function resolveStage(stage: string | undefined): {\n stage: EncryptStage;\n wasDefaulted: boolean;\n} {\n return {\n stage: stage === 'dev' || stage === 'prod' ? stage : DEFAULT_STAGE,\n wasDefaulted: stage === undefined,\n };\n}\n\nexport function defaultStageNotice(stage: EncryptStage): string {\n return `No --stage given; defaulting to ${stage} encryption keys (pass --stage dev to override)\\n`;\n}\n\nexport async function readManifestDefaults(cwd: string = process.cwd()): Promise<ManifestDefaults> {\n try {\n const raw = await readFile(join(cwd, 'kizen.json'), 'utf-8');\n const parsed = JSON.parse(raw) as unknown;\n const manifest = (Array.isArray(parsed) ? parsed[0] : parsed) as Record<string, unknown>;\n\n const apiName =\n typeof manifest.api_name === 'string' && manifest.api_name !== ''\n ? manifest.api_name\n : undefined;\n\n return {\n ...(apiName !== undefined && { apiName }),\n };\n } catch {\n // Not in a plugin directory — fine, the UI will prompt with no defaults.\n }\n\n return {};\n}\n\nexport function stripTrailingNewlines(value: string): string {\n return value.replace(/[\\r\\n]+$/, '');\n}\n\nexport async function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n\n return Buffer.concat(chunks).toString('utf-8');\n}\n","import type { EncryptionContext } from './encryptionClient.js';\nimport type { Credentials } from './credentials.js';\nimport type { ManifestDefaults } from './encryptHelpers.js';\nimport { compactEnvelope, defaultStageNotice, stripTrailingNewlines } from './encryptHelpers.js';\n\nexport interface HeadlessEncryptOptions {\n credentials?: string;\n apiName?: string;\n value?: string;\n out?: string;\n}\n\nexport interface HeadlessEncryptDeps {\n loadCredentialsFromFile: (path: string) => Promise<Credentials>;\n loadGlobalCredentials: () => Promise<Credentials | null>;\n encryptSecret: (\n ctx: EncryptionContext,\n credentials: Credentials,\n apiName: string,\n value: string,\n ) => Promise<string>;\n readStdin: () => Promise<string>;\n stdinIsTTY: () => boolean;\n writeStdout: (text: string) => void;\n writeStderr: (text: string) => void;\n writeEnvelopeFile: (path: string, value: string) => Promise<void>;\n setExitCode: (code: number) => void;\n}\n\nexport async function runHeadless(\n ctx: EncryptionContext,\n options: HeadlessEncryptOptions,\n defaults: ManifestDefaults,\n stageWasDefaulted: boolean,\n deps: HeadlessEncryptDeps,\n): Promise<void> {\n const credentials =\n options.credentials !== undefined\n ? await deps.loadCredentialsFromFile(options.credentials)\n : await deps.loadGlobalCredentials();\n\n if (credentials === null) {\n throw new Error(\n 'No credentials found. Pass --credentials or create ~/.kizenappbuilder/credentials.json.',\n );\n }\n\n const apiName = options.apiName ?? defaults.apiName;\n\n if (apiName === undefined || apiName.trim() === '') {\n throw new Error(\n 'api_name is required in non-interactive mode. Pass --api-name or run inside a plugin directory.',\n );\n }\n\n if (stageWasDefaulted) {\n deps.writeStderr(defaultStageNotice(ctx.stage));\n }\n\n let value = options.value;\n\n if (value === undefined) {\n if (deps.stdinIsTTY()) {\n throw new Error(\n 'No secret provided and stdin is a terminal. Pass --value, or pipe the secret in ' +\n '(e.g. `printf %s \"$SECRET\" | npx --yes @kizenapps/cli encrypt …`).',\n );\n }\n\n deps.writeStderr('Reading secret from stdin (pass --value to skip)…\\n');\n\n value = stripTrailingNewlines(await deps.readStdin());\n }\n\n if (value === '') {\n throw new Error('A secret value is required. Pass --value or pipe it via stdin.');\n }\n\n const envelopeValue = await deps.encryptSecret(ctx, credentials, apiName.trim(), value);\n\n deps.writeStdout(`${compactEnvelope(envelopeValue)}\\n`);\n\n if (options.out !== undefined) {\n try {\n await deps.writeEnvelopeFile(options.out, envelopeValue);\n deps.writeStderr(`Wrote encrypted envelope to ${options.out}\\n`);\n } catch (err) {\n deps.writeStderr(\n `Error writing ${options.out}: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n deps.setExitCode(1);\n }\n }\n}\n","export const VALID_ICONS = new Set([\n 'phone',\n 'envelope',\n 'pen-nib',\n 'calendar-days',\n 'paperclip',\n 'file',\n 'clipboard',\n 'pen',\n 'tag',\n 'book',\n 'print',\n 'pen-to-square',\n 'folder',\n 'folder-open',\n 'thumbtack',\n 'globe',\n 'city',\n 'briefcase',\n 'compass',\n 'address-book',\n 'business-time',\n 'computer-classic',\n 'pen-fancy',\n 'badge-check',\n 'mug-saucer',\n 'landmark',\n 'chart-simple',\n 'envelopes',\n 'diagram-venn',\n 'calendar',\n 'pencil',\n 'phone-volume',\n 'copy',\n 'table',\n 'building',\n 'network-wired',\n 'address-card',\n 'tags',\n 'registered',\n 'signature',\n 'phone-office',\n 'projector',\n 'sitemap',\n 'marker',\n 'badge',\n 'wallet',\n 'copyright',\n 'bullseye',\n 'calculator',\n 'certificate',\n 'percent',\n 'eraser',\n 'file-spreadsheet',\n 'glasses',\n 'industry',\n 'vault',\n 'user-tie-hair-long',\n 'user-tie-hair',\n 'user-hair-mullet',\n 'trademark',\n 'timeline-arrow',\n 'timeline',\n 'table-tree',\n 'table-rows',\n 'table-pivot',\n 'table-layout',\n 'table-columns',\n 'stapler',\n 'square-poll-vertical',\n 'square-poll-horizontal',\n 'square-phone-flip',\n 'square-phone',\n 'square-pen',\n 'square-kanban',\n 'square-envelope',\n 'socks',\n 'slot-machine',\n 'signature-slash',\n 'signature-lock',\n 'shredder',\n 'scissors',\n 'scanner-image',\n 'scale-unbalanced-flip',\n 'scale-unbalanced',\n 'scale-balanced',\n 'router',\n 'rectangle-pro',\n 'print-slash',\n 'print-magnifying-glass',\n 'presentation-screen',\n 'podium',\n 'phone-slash',\n 'phone-intercom',\n 'phone-flip',\n 'person-chalkboard',\n 'pen-nib-slash',\n 'pen-clip',\n 'paste',\n 'paperclip-vertical',\n 'notebook',\n 'note-sticky',\n 'money-check-pen',\n 'money-check-dollar-pen',\n 'magnifying-glass-chart',\n 'magnifying-glass-arrow-right',\n 'list-tree',\n 'list-timeline',\n 'list-radio',\n 'list-dropdown',\n 'list-check',\n 'laptop-file',\n 'lamp-desk',\n 'keynote',\n 'industry-windows',\n 'inboxes',\n 'inbox-full',\n 'house-laptop',\n 'highlighter',\n 'folders',\n 'folder-xmark',\n 'folder-tree',\n 'folder-plus',\n 'folder-minus',\n 'folder-arrow-up',\n 'folder-arrow-down',\n 'floppy-disk-circle-xmark',\n 'floppy-disk-circle-arrow-right',\n 'floppy-disk',\n 'file-user',\n 'file-lines',\n 'file-circle-plus',\n 'file-circle-info',\n 'file-chart-pie',\n 'file-chart-column',\n 'fax',\n 'envelope-open',\n 'envelope-dot',\n 'envelope-circle-check',\n 'coffee-pot',\n 'cloud-word',\n 'clipboard-question',\n 'chart-user',\n 'chart-tree-map',\n 'chart-simple-horizontal',\n 'chart-pyramid',\n 'chart-pie-simple',\n 'chart-pie',\n 'chart-line-up',\n 'chart-line-down',\n 'chart-line',\n 'cake-candles',\n 'cabinet-filing',\n 'bullhorn',\n 'briefcase-blank',\n 'briefcase-arrow-right',\n 'brain-arrow-curved-right',\n 'boxes-packing',\n 'box-archive',\n 'book-section',\n 'bars-staggered',\n 'bars-progress',\n 'badge-percent',\n 'badge-dollar',\n 'arrows-to-eye',\n 'arrows-to-dot',\n 'arrows-spin',\n 'sparkles',\n 'megaphone',\n 'block-question',\n 'lightbulb-slash',\n 'comments-dollar',\n 'comments',\n 'bullseye-pointer',\n 'lightbulb',\n 'user-group-crown',\n 'user-crown',\n 'signal-stream-slash',\n 'signal-stream',\n 'rectangle-ad',\n 'ranking-star',\n 'person-rays',\n 'people-group',\n 'messages-dollar',\n 'message-dollar',\n 'magnifying-glass-location',\n 'magnifying-glass-dollar',\n 'lightbulb-on',\n 'lightbulb-exclamation',\n 'lightbulb-dollar',\n 'lightbulb-cfl-on',\n 'lightbulb-cfl',\n 'hundred-points',\n 'group-arrows-rotate',\n 'gift-card',\n 'filter-circle-dollar',\n 'envelopes-bulk',\n 'envelope-open-text',\n 'envelope-open-dollar',\n 'comment-dollar',\n 'chart-mixed',\n 'bullseye-arrow',\n 'star',\n 'heart',\n 'camera-retro',\n 'truck-fast',\n 'bell',\n 'cart-shopping',\n 'gift',\n 'barcode',\n 'bookmark',\n 'camera',\n 'thumbs-up',\n 'thumbs-down',\n 'key',\n 'truck',\n 'balloons',\n 'handshake',\n 'shop',\n 'shirt',\n 'bag-shopping',\n 'moped',\n 'cart-plus',\n 'credit-card',\n 'store',\n 'cash-register',\n 'booth-curtain',\n 'trophy',\n 'receipt',\n 'truck-container',\n 'truck-clock',\n 'truck-bolt',\n 'trophy-star',\n 'store-slash',\n 'store-lock',\n 'star-exclamation',\n 'shop-slash',\n 'shop-lock',\n 'rectangle-barcode',\n 'person-booth',\n 'nfc-trash',\n 'nfc-symbol',\n 'nfc-slash',\n 'nfc-signal',\n 'nfc-pen',\n 'nfc-magnifying-glass',\n 'nfc-lock',\n 'nfc',\n 'money-check-dollar',\n 'money-check',\n 'mobile-signal-out',\n 'mobile-signal',\n 'hexagon-vertical-nft-slanted',\n 'hexagon-vertical-nft',\n 'hexagon-image',\n 'hand-holding-box',\n 'gifts',\n 'gem',\n 'credit-card-front',\n 'credit-card-blank',\n 'cart-xmark',\n 'cart-shopping-fast',\n 'cart-minus',\n 'cart-circle-xmark',\n 'cart-circle-plus',\n 'cart-circle-exclamation',\n 'cart-circle-check',\n 'cart-circle-arrow-up',\n 'cart-circle-arrow-down',\n 'cart-arrow-up',\n 'cart-arrow-down',\n 'box-open-full',\n 'basket-shopping-simple',\n 'basket-shopping',\n 'barcode-scan',\n 'barcode-read',\n 'balloon',\n 'bags-shopping',\n 'bars',\n 'browser',\n 'chart-bar',\n 'cog',\n 'database',\n 'calendar-alt',\n 'play',\n 'kizen-k',\n 'add',\n 'book-alt',\n 'form-entity',\n 'arrows-to-circle',\n 'question-circle',\n 'chevron-down',\n 'chevron-up',\n 'window-restore',\n 'forward',\n]);\n\nexport const VALID_ICONS_LIST = [...VALID_ICONS].sort();\n\n// Icons rendered as custom Kizen-brand React components — no FontAwesome equivalent.\nexport const CUSTOM_ICON_NAMES = new Set(['kizen-k', 'form-entity']);\n\nexport const ALL_VALID_ICONS_LIST = [...VALID_ICONS_LIST, ...[...CUSTOM_ICON_NAMES].sort()];\n","import type { Command } from 'commander';\nimport { ALL_VALID_ICONS_LIST } from '../../shared/lib/validIcons.js';\n\nexport function iconsCommand(program: Command): void {\n program\n .command('icons')\n .description('List all valid icon names accepted by toolbar items, pages, and adornments')\n .action(() => {\n for (const name of ALL_VALID_ICONS_LIST) {\n console.log(name);\n }\n });\n}\n","import { mkdir, writeFile, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Command } from 'commander';\nimport { readLocalFiles } from '../lib/readFiles.js';\nimport { GLOBAL_CREDENTIALS_DIR } from '../lib/credentials.js';\nimport { generateHtml, generateMarkdown } from '../lib/reportHelpers.js';\n\nconst EXAMPLES_DIR = join(GLOBAL_CREDENTIALS_DIR, 'examples');\n\nexport function reportCommand(program: Command): void {\n program\n .command('report')\n .description('Generate a self-contained HTML report of the plugin')\n .option('-o, --output <path>', `output file path (default: ${EXAMPLES_DIR}/<api_name>.html)`)\n .action(async (options: { output?: string }) => {\n const pluginDir = process.cwd();\n\n let manifest: Record<string, unknown>;\n\n try {\n const raw = await readFile(join(pluginDir, 'kizen.json'), 'utf-8');\n const parsed = JSON.parse(raw) as unknown;\n\n manifest = (Array.isArray(parsed) ? parsed[0] : parsed) as Record<string, unknown>;\n } catch {\n console.error('Error: kizen.json not found. Run this command from a plugin directory.');\n process.exit(1);\n }\n\n const apiName = typeof manifest.api_name === 'string' ? manifest.api_name : 'plugin';\n const htmlPath = options.output ?? join(EXAMPLES_DIR, `${apiName}.html`);\n const mdPath = htmlPath.replace(/\\.html$/, '.md');\n\n const files = await readLocalFiles(pluginDir, { detectBinaryByContent: true });\n\n await mkdir(join(htmlPath, '..'), { recursive: true });\n\n await Promise.all([\n writeFile(htmlPath, generateHtml(manifest, files), 'utf-8'),\n writeFile(mdPath, generateMarkdown(manifest, files), 'utf-8'),\n ]);\n\n console.log(`Plugin report written to:\\n ${htmlPath}\\n ${mdPath}`);\n });\n}\n","import type { FileContent } from '@kizenapps/packager';\n\nconst SENSITIVE_FIELDS = new Set(['developer_business_id']);\n\nexport function redactServices(services: unknown): unknown {\n if (!Array.isArray(services)) {\n return services;\n }\n\n return services.map((svc: unknown) => {\n if (typeof svc !== 'object' || svc === null) {\n return svc;\n }\n\n const s = svc as Record<string, unknown>;\n\n if (typeof s.auth_credentials !== 'object' || s.auth_credentials === null) {\n return s;\n }\n\n const redacted = Object.fromEntries(Object.keys(s.auth_credentials).map((k) => [k, '*****']));\n\n return { ...s, auth_credentials: redacted };\n });\n}\n\nexport interface TreeNode {\n name: string;\n children: Map<string, TreeNode>;\n isFile: boolean;\n filePath: string;\n}\n\nexport function buildTree(files: FileContent[]): TreeNode {\n const root: TreeNode = { name: '', children: new Map(), isFile: false, filePath: '' };\n\n for (const file of files) {\n const parts = file.path.split('/');\n let node = root;\n\n parts.forEach((part, i) => {\n if (!node.children.has(part)) {\n node.children.set(part, {\n name: part,\n children: new Map(),\n isFile: i === parts.length - 1,\n filePath: parts.slice(0, i + 1).join('/'),\n });\n }\n\n const next = node.children.get(part);\n\n if (next) {\n node = next;\n }\n });\n }\n\n return root;\n}\n\nfunction sortTreeChildren(node: TreeNode): TreeNode[] {\n return [...node.children.values()].sort((a, b) => {\n if (a.isFile !== b.isFile) {\n return a.isFile ? 1 : -1;\n }\n\n return a.name.localeCompare(b.name);\n });\n}\n\nexport function fileId(path: string): string {\n return 'file-' + path.replace(/[^a-zA-Z0-9]/g, '-');\n}\n\nexport function esc(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\nexport function fileExt(path: string): string {\n const idx = path.lastIndexOf('.');\n\n return idx >= 0 ? path.slice(idx).toLowerCase() : '';\n}\n\nconst LANG_MAP: Record<string, string> = {\n '.ts': 'typescript',\n '.tsx': 'typescript',\n '.js': 'javascript',\n '.jsx': 'javascript',\n '.mjs': 'javascript',\n '.cjs': 'javascript',\n '.json': 'json',\n '.css': 'css',\n '.scss': 'scss',\n '.html': 'html',\n '.htm': 'html',\n '.md': 'markdown',\n '.mdx': 'markdown',\n '.py': 'python',\n '.sh': 'bash',\n '.yml': 'yaml',\n '.yaml': 'yaml',\n '.xml': 'xml',\n '.toml': 'toml',\n};\n\nexport function mdLang(path: string): string {\n return LANG_MAP[fileExt(path)] ?? '';\n}\n\n// A fenced block must be delimited by more backticks than the longest run inside\n// it, or content that is itself markdown (a README with a code sample) escapes\n// its wrapper and corrupts the rest of the document.\nexport function mdFence(content: string): string {\n const longestRun = [...content.matchAll(/`+/g)].reduce((max, m) => Math.max(max, m[0].length), 0);\n\n return '`'.repeat(Math.max(3, longestRun + 1));\n}\n\nexport function renderTextTree(node: TreeNode, prefix = ''): string {\n const sorted = sortTreeChildren(node);\n\n return sorted\n .map((child, i) => {\n const isLast = i === sorted.length - 1;\n const connector = isLast ? '└── ' : '├── ';\n const childPrefix = isLast ? ' ' : '│ ';\n\n if (child.isFile) {\n return `${prefix}${connector}${child.name}`;\n }\n\n return `${prefix}${connector}${child.name}/\\n${renderTextTree(child, prefix + childPrefix)}`;\n })\n .join('\\n');\n}\n\nconst LICENSE_FILE = /(^|\\/)licen[cs]e(\\.md|\\.txt)?$/i;\n\nexport function filterSourceFiles(files: FileContent[]): FileContent[] {\n return files.filter(\n (f) => f.path !== 'kizen.json' && f.path !== 'plugin-report.html' && !LICENSE_FILE.test(f.path),\n );\n}\n\nexport function buildFilteredConfig(manifest: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(manifest)\n .filter(([k]) => !SENSITIVE_FIELDS.has(k))\n .map(([k, v]) => [k, k === 'services' ? redactServices(v) : v]),\n );\n}\n\nconst IMAGE_MIME: Record<string, string> = {\n '.png': 'image/png',\n '.svg': 'image/svg+xml',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n};\n\nfunction renderTree(node: TreeNode): string {\n const sorted = sortTreeChildren(node);\n const items = sorted.map((child) => {\n if (child.isFile) {\n return `<li class=\"tf\"><a href=\"#${fileId(child.filePath)}\" data-id=\"${fileId(child.filePath)}\">${esc(child.name)}</a></li>`;\n }\n\n return `<li class=\"td\"><span class=\"dn\">${esc(child.name)}/</span>${renderTree(child)}</li>`;\n });\n\n return `<ul>${items.join('')}</ul>`;\n}\n\nfunction renderFileSection(file: FileContent): string {\n let body: string;\n\n if (file.base64Image !== undefined) {\n const mime = IMAGE_MIME[fileExt(file.path)] ?? 'image/png';\n\n body = `<img src=\"data:${mime};base64,${file.base64Image}\" alt=\"${esc(file.path)}\" style=\"max-width:100%\">`;\n } else if (file.binaryData !== undefined) {\n body = `<p class=\"bin\">[Binary file: ${String(file.binaryData.length)} bytes]</p>`;\n } else {\n body = `<pre><code>${esc(file.content)}</code></pre>`;\n }\n\n return `<section id=\"${fileId(file.path)}\"><h2 class=\"fp\">${esc(file.path)}</h2><div class=\"fb\">${body}</div></section>`;\n}\n\nexport function generateMarkdown(manifest: Record<string, unknown>, files: FileContent[]): string {\n const filtered = buildFilteredConfig(manifest);\n const name = typeof manifest.name === 'string' ? manifest.name : 'Plugin';\n const version = typeof manifest.version === 'string' ? manifest.version : '';\n const description = typeof manifest.description === 'string' ? manifest.description : '';\n const sourceFiles = filterSourceFiles(files);\n\n const lines: string[] = [];\n\n lines.push(`# ${name}${version ? ` v${version}` : ''}`);\n if (description) {\n lines.push('', description);\n }\n\n const configJson = JSON.stringify(filtered, null, 2);\n const configFence = mdFence(configJson);\n\n lines.push(\n '',\n '## Configuration (`kizen.json`)',\n '',\n `${configFence}json`,\n configJson,\n configFence,\n );\n\n lines.push('', '## File Tree', '', '```', renderTextTree(buildTree(sourceFiles)), '```');\n\n lines.push('', '## Files');\n\n for (const file of sourceFiles) {\n lines.push('', `### \\`${file.path}\\``, '');\n\n if (file.base64Image !== undefined) {\n lines.push(`[Image file: ${file.path}]`);\n } else if (file.binaryData !== undefined) {\n lines.push(`[Binary file: ${String(file.binaryData.length)} bytes]`);\n } else {\n const fence = mdFence(file.content);\n\n lines.push(`${fence}${mdLang(file.path)}`, file.content, fence);\n }\n }\n\n return lines.join('\\n') + '\\n';\n}\n\nexport function generateHtml(manifest: Record<string, unknown>, files: FileContent[]): string {\n const filtered = buildFilteredConfig(manifest);\n const name = typeof manifest.name === 'string' ? manifest.name : 'Plugin';\n const version = typeof manifest.version === 'string' ? manifest.version : '';\n const description = typeof manifest.description === 'string' ? manifest.description : '';\n\n const sourceFiles = filterSourceFiles(files);\n const treeHtml = renderTree(buildTree(sourceFiles));\n const fileSections = sourceFiles.map(renderFileSection).join('\\n');\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>${esc(name)} — Plugin Report</title>\n<style>\n*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}\n:root{\n --bg:#1e1e2e;--sb:#181825;--hd:#11111b;--tx:#cdd6f4;--mu:#6c7086;\n --ac:#89b4fa;--gr:#a6e3a1;--bd:#313244;--cb:#181825;--sw:280px;\n --fn:'Menlo','Consolas','Monaco',monospace;\n}\nhtml{font-size:14px}\nbody{background:var(--bg);color:var(--tx);font-family:var(--fn);display:flex;flex-direction:column;height:100vh}\nheader{background:var(--hd);border-bottom:1px solid var(--bd);padding:14px 20px;flex-shrink:0}\nheader h1{font-size:1.1rem;color:var(--ac)}\nheader p{color:var(--mu);font-size:.85rem;margin-top:3px}\n.layout{display:flex;flex:1;overflow:hidden}\nnav{width:var(--sw);background:var(--sb);border-right:1px solid var(--bd);overflow-y:auto;padding:12px 0;flex-shrink:0}\nnav a.cfg{display:block;padding:6px 16px;color:var(--gr);text-decoration:none;font-size:.85rem}\nnav a.cfg:hover,nav a.cfg.active{background:var(--bd)}\nnav ul{list-style:none;padding-left:0}\n.td>.dn{display:block;padding:4px 16px;color:var(--mu);font-size:.8rem}\n.td ul{padding-left:14px}\n.tf a{display:block;padding:3px 16px;color:var(--tx);text-decoration:none;font-size:.8rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.tf a:hover,.tf a.active{background:var(--bd);color:var(--ac)}\nmain{flex:1;overflow-y:auto;padding:0 24px 40px}\nsection{padding:32px 0;border-bottom:1px solid var(--bd)}\nh2.fp{font-size:.9rem;color:var(--ac);margin-bottom:12px;word-break:break-all}\n#config h2.fp{color:var(--gr)}\npre{background:var(--cb);border:1px solid var(--bd);border-radius:6px;padding:14px;overflow-x:auto;font-size:.78rem;line-height:1.6;white-space:pre}\ncode{font-family:var(--fn)}\nimg{border:1px solid var(--bd);border-radius:4px}\n.bin{color:var(--mu);font-style:italic;padding:12px 0}\n::-webkit-scrollbar{width:6px;height:6px}\n::-webkit-scrollbar-track{background:transparent}\n::-webkit-scrollbar-thumb{background:var(--bd);border-radius:3px}\n</style>\n</head>\n<body>\n<header>\n <h1>${esc(name)}${version ? ` <span style=\"color:var(--mu);font-size:.8em\">v${esc(version)}</span>` : ''}</h1>\n ${description ? `<p>${esc(description)}</p>` : ''}\n</header>\n<div class=\"layout\">\n<nav>\n <a href=\"#config\" class=\"cfg\" data-id=\"config\">kizen.json (config)</a>\n ${treeHtml}\n</nav>\n<main>\n<section id=\"config\"><h2 class=\"fp\">kizen.json — Plugin Configuration</h2><div class=\"fb\"><pre><code>${esc(JSON.stringify(filtered, null, 2))}</code></pre></div></section>\n${fileSections}\n</main>\n</div>\n<script>\n(function(){\n var links=document.querySelectorAll('[data-id]');\n function setActive(id){links.forEach(function(l){l.classList.toggle('active',l.getAttribute('data-id')===id);})}\n links.forEach(function(l){l.addEventListener('click',function(){setActive(this.getAttribute('data-id'));});});\n var obs=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting)setActive(e.target.id);});},{rootMargin:'-20% 0px -70% 0px'});\n document.querySelectorAll('section[id]').forEach(function(s){obs.observe(s);});\n})();\n</script>\n</body>\n</html>`;\n}\n","import { createProgram } from './program.js';\n\ncreateProgram().parse();\n"],"mappings":"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AIC,GACxBC,GAAcC,GAAW,CACvB,IAAAd,EACA,eAAgBF,EAChB,OAASiB,GAAkB,CACzBL,EAAgBK,CAClB,EACA,GAAIvB,EAAQ,cAAgB,QAAa,CAAE,gBAAiBA,EAAQ,WAAY,EAChF,GAAIA,EAAQ,UAAY,QAAa,CAAE,eAAgBA,EAAQ,OAAQ,EACvE,GAAIG,EAAS,UAAY,QAAa,CAAE,eAAgBA,EAAS,OAAQ,EACzE,GAAIH,EAAQ,QAAU,QAAa,CAAE,aAAcA,EAAQ,KAAM,CACnE,CAAC,EACD,CAAE,YAAa,EAAM,CACvB,EAMA,GAJA,MAAMmB,EAAc,EAIhBD,IAAkB,QAAalB,EAAQ,MAAQ,OACjD,GAAI,CACF,MAAMe,GAAkBf,EAAQ,IAAKkB,CAAa,EAClD,QAAQ,OAAO,MAAM,+BAA+BlB,EAAQ,GAAG;AAAA,CAAI,CACrE,OAASiB,EAAK,CACZ,QAAQ,MACN,iBAAiBjB,EAAQ,GAAG,KAAKiB,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,CAAC,EACnF,EACA,QAAQ,SAAW,CACrB,CAEJ,CAAC,CACL,CM5HO,IAAMO,GAAc,IAAI,IAAI,CACjC,QACA,WACA,UACA,gBACA,YACA,OACA,YACA,MACA,MACA,OACA,QACA,gBACA,SACA,cACA,YACA,QACA,OACA,YACA,UACA,eACA,gBACA,mBACA,YACA,cACA,aACA,WACA,eACA,YACA,eACA,WACA,SACA,eACA,OACA,QACA,WACA,gBACA,eACA,OACA,aACA,YACA,eACA,YACA,UACA,SACA,QACA,SACA,YACA,WACA,aACA,cACA,UACA,SACA,mBACA,UACA,WACA,QACA,qBACA,gBACA,mBACA,YACA,iBACA,WACA,aACA,aACA,cACA,eACA,gBACA,UACA,uBACA,yBACA,oBACA,eACA,aACA,gBACA,kBACA,QACA,eACA,kBACA,iBACA,WACA,WACA,gBACA,wBACA,mBACA,iBACA,SACA,gBACA,cACA,yBACA,sBACA,SACA,cACA,iBACA,aACA,oBACA,gBACA,WACA,QACA,qBACA,WACA,cACA,kBACA,yBACA,yBACA,+BACA,YACA,gBACA,aACA,gBACA,aACA,cACA,YACA,UACA,mBACA,UACA,aACA,eACA,cACA,UACA,eACA,cACA,cACA,eACA,kBACA,oBACA,2BACA,iCACA,cACA,YACA,aACA,mBACA,mBACA,iBACA,oBACA,MACA,gBACA,eACA,wBACA,aACA,aACA,qBACA,aACA,iBACA,0BACA,gBACA,mBACA,YACA,gBACA,kBACA,aACA,eACA,iBACA,WACA,kBACA,wBACA,2BACA,gBACA,cACA,eACA,iBACA,gBACA,gBACA,eACA,gBACA,gBACA,cACA,WACA,YACA,iBACA,kBACA,kBACA,WACA,mBACA,YACA,mBACA,aACA,sBACA,gBACA,eACA,eACA,cACA,eACA,kBACA,iBACA,4BACA,0BACA,eACA,wBACA,mBACA,mBACA,gBACA,iBACA,sBACA,YACA,uBACA,iBACA,qBACA,uBACA,iBACA,cACA,iBACA,OACA,QACA,eACA,aACA,OACA,gBACA,OACA,UACA,WACA,SACA,YACA,cACA,MACA,QACA,WACA,YACA,OACA,QACA,eACA,QACA,YACA,cACA,QACA,gBACA,gBACA,SACA,UACA,kBACA,cACA,aACA,cACA,cACA,aACA,mBACA,aACA,YACA,oBACA,eACA,YACA,aACA,YACA,aACA,UACA,uBACA,WACA,MACA,qBACA,cACA,oBACA,gBACA,+BACA,uBACA,gBACA,mBACA,QACA,MACA,oBACA,oBACA,aACA,qBACA,aACA,oBACA,mBACA,0BACA,oBACA,uBACA,yBACA,gBACA,kBACA,gBACA,yBACA,kBACA,eACA,eACA,UACA,gBACA,OACA,UACA,YACA,MACA,WACA,eACA,OACA,UACA,MACA,WACA,cACA,mBACA,kBACA,eACA,aACA,iBACA,SACF,CAAC,EAEYC,GAAmB,CAAC,GAAGD,EAAW,EAAE,KAAK,EAGzCE,GAAoB,IAAI,IAAI,CAAC,UAAW,aAAa,CAAC,EAEtDC,GAAuB,CAAC,GAAGF,GAAkB,GAAG,CAAC,GAAGC,EAAiB,EAAE,KAAK,CAAC,EC3SnF,SAASE,GAAaC,EA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","names":["readFileSync","dirname","join","fileURLToPath","Command","createElement","render","useEffect","useState","Box","Text","useApp","PluginValidationError","mkdir","writeFile","join","PluginValidationError","packagePlugin","parseManifestFromFiles","transformDeployablePlugin","transformFiles","validatePluginApp","readdir","readFile","join","relative","IMAGE_EXTENSIONS","BINARY_EXTENSIONS","SKIP_FILES","SKIP_DIRS","BINARY_SNIFF_BYTES","looksBinary","buf","walk","dir","rootDir","entries","paths","entry","readLocalFiles","detectBinaryByContent","absolutePaths","absPath","relPath","dotIndex","ext","serializePlugin","plugin","allReleaseNotes","runBuild","pluginDir","outputDir","onStep","mkdir","files","readLocalFiles","issues","validatePluginApp","issue","PluginValidationError","minified","transformFiles","manifests","parseManifestFromFiles","packaged","packagePlugin","deployable","transformDeployablePlugin","bundle","notesDir","f","a","b","jsonStr","stripReleaseNotes","key","value","bundleSize","writeFile","join","formatBytes","n","Box","Text","Box","Text","jsx","LOGO_LINES","Logo","line","i","Fragment","jsx","jsxs","AppHeader","marginBottom","Logo","Box","Text","useEffect","useState","Text","jsx","SPINNER_FRAMES","Spinner","frame","setFrame","id","prev","Box","Text","jsx","jsxs","groupIssuesByPath","issues","groups","issue","key","group","ValidationIssues","errorCount","path","Fragment","jsx","jsxs","STEPS","STEP_LABELS","BuildUI","outputDir","pluginDir","app","useApp","step","setStep","useState","failed","setFailed","issues","setIssues","errorMessage","setErrorMessage","bundleSize","setBundleSize","useEffect","runBuild","size","err","PluginValidationError","currentIndex","isDone","Box","AppHeader","s","i","isActive","isStepDone","Text","Spinner","formatBytes","ValidationIssues","fs","path","ensureGitignore","projectDir","gitignorePath","entry","contents","lines","l","addition","buildCommand","program","pluginDir","outputDir","ensureGitignore","waitUntilExit","render","createElement","BuildUI","createElement","render","useCallback","useState","Box","Text","useApp","useInput","join","access","mkdir","writeFile","dirname","join","config_default","script_default","styles_default","config_default","script_default","styles_default","config_default","script_default","config_default","script_default","styles_default","greet_default","config_default","script_default","config_default","script_default","config_default","script_default","ARTIFACT_TYPES","ARTIFACT_LABELS","TEMPLATES","config_default","script_default","styles_default","greet_default","artifactFiles","type","entryDir","directory","component","files","relativePath","content","scaffoldArtifactFiles","types","copilot_instructions_default","security_instructions_default","version_discipline_instructions_default","copilotFiles","copilot_instructions_default","security_instructions_default","version_discipline_instructions_default","deflateSync","THUMBNAIL_SIZE","BODY_HALF_SIZE","BODY_CORNER_RADIUS","KNOB_RADIUS","KNOB_OFFSET_RATIO","NECK_HALF_WIDTH","SATURATION","LIGHTNESS","fnv1a","text","hash","i","thumbnailStyle","apiName","hslToRgb","hue","saturation","lightness","chroma","sector","secondary","match","r","b","roundedBoxDistance","x","y","halfW","halfH","radius","qx","qy","circleDistance","cx","cy","puzzlePieceDistance","s","k","offset","neckHalf","topKnob","rightKnob","bottomSocket","leftSocket","renderPixels","style","size","pixels","g","knobExtension","centre","shift","py","px","turn","d","coverage","CRC_TABLE","_","n","c","crc32","bytes","crc","byte","pngChunk","type","data","typeBytes","length","PNG_SIGNATURE","encodePng","width","height","rgba","ihdr","stride","raw","thumbnailBytes","THUMBNAIL_PATH","PROD_ENVIRONMENTS","pathExists","path","access","precheckTargetDir","dir","join","findAvailableSubDir","parentDir","baseName","base","i","candidate","buildManifest","input","businessId","targetEnvironments","writeScaffoldedFiles","targetDir","scaffolded","files","file","directories","dirname","mkdir","writeFile","createPlugin","manifest","scaffoldArtifactFiles","copilotFiles","thumbnailBytes","ensureGitignore","FIELDS","FIELD_LABELS","REQUIRED_FIELDS","API_NAME_PATTERN","API_NAME_HINT","inferApiName","name","emptyValues","defaultBusinessId","validateField","fieldName","inputBuffer","value","normalizeFieldValue","toggleArtifactSelection","selected","type","next","ARTIFACT_TYPES","candidate","jsx","jsxs","Hint","text","Text","CreateUI","parentDir","defaultBusinessId","defaultEnvironment","app","useApp","phase","setPhase","useState","mode","setMode","values","setValues","emptyValues","artifacts","setArtifacts","ARTIFACT_TYPES","inputBuffer","setInputBuffer","targetDir","setTargetDir","enterFieldEntry","useCallback","nextMode","initialValues","runPrecheck","dir","result","precheckTargetDir","resolveSubDirAndConfirm","finalValues","findAvailableSubDir","err","runWrite","createPlugin","useInput","input","key","field","current","fieldName","FIELDS","prev","updated","prevField","prevName","fieldError","validateField","valueToStore","normalizeFieldValue","nextField","nextName","existing","nextBuffer","inferApiName","cursor","selected","lastField","lastName","type","next","toggleArtifactSelection","options","Box","AppHeader","opt","i","reason","activeField","targetLine","name","isActive","displayValue","isRequired","REQUIRED_FIELDS","label","FIELD_LABELS","active","checked","ARTIFACT_LABELS","manifest","buildManifest","join","mkdir","readFile","readdir","writeFile","homedir","dirname","join","ENVIRONMENTS","GLOBAL_CREDENTIALS_DIR","join","homedir","GLOBAL_CREDENTIALS_PATH","DEFAULT_PROFILE_NAME","isValidEnvironment","value","ENVIRONMENTS","parseCredentials","raw","obj","env","loadCredentialsFromFile","filePath","content","readFile","loadGlobalCredentials","saveGlobalCredentials","credentials","mkdir","dirname","writeFile","getProfilePath","name","listCredentialProfiles","profiles","entries","readdir","entry","saveCredentialProfile","loadCredentialProfile","PLACEHOLDER_DESCRIPTION","parseArtifactSelection","raw","ARTIFACT_TYPES","requested","part","unknown","resolveHeadlessInput","options","defaults","targetDir","name","apiName","inferApiName","API_NAME_PATTERN","API_NAME_HINT","description","developerBusinessId","developerEnvironment","resolveEnvironment","isEnvironment","value","ENVIRONMENTS","runHeadlessCreate","deps","input","err","precheck","conflict","artifactSummary","createCommand","program","ENVIRONMENTS","ARTIFACT_TYPES","options","parentDir","globalCreds","loadGlobalCredentials","defaultBusinessId","defaultEnvironment","suppliedFlags","value","runHeadlessCreate","precheckTargetDir","createPlugin","text","code","waitUntilExit","render","createElement","CreateUI","createElement","render","useCallback","useEffect","useRef","useState","Box","Text","useInput","PluginValidationError","watch","createServer","join","WebSocketServer","createReadStream","realpathSync","access","readdir","readFile","realpath","stat","dirname","extname","join","resolve","sep","fileURLToPath","STRIPPED_RESPONSE_HEADERS","sanitizeUpstreamHeaders","headers","filtered","key","value","lower","MAX_PROXY_BYTES","CACHE_TTL_MS","CACHE_MAX_ENTRIES","ProxyResponseTooLargeError","bytesRead","limit","readBodyWithLimit","response","body","chunks","total","chunk","toCachedResponse","createProxyCache","options","onChange","enabled","_key","fetcher","cache","emitChange","evict","existing","oldest","pending","error","MIME_TYPES","mkdir","readFile","writeFile","join","loadConfig","outputDir","content","saveConfig","config","ENCRYPTION_API_DEFAULTS","resolveWizardBase","target","forced","spawn","writeFile","rm","mkdtemp","access","join","tmpdir","python_requirements_default","parseRequirementsFile","content","line","resolvePythonBinary","runtime","match","major","minor","toStepInputValue","raw","coerceStepInputValue","value","toStepInputValue","normalizeStepInputs","inputs","name","WRAPPER_SCRIPT","DEFAULT_TIMEOUT","VENV_DIR","join","SUPPORTED_RUNTIMES","isSupportedRuntime","runtime","VENV_PACKAGES","parseRequirementsFile","python_requirements_default","venvReady","MIN_PYTHON","meetsMinimum","major","minor","formatVersion","version","probePython","bin","resolve","proc","spawn","out","chunk","code","match","findSystemPython","preferred","resolvePythonBinary","candidates","tried","runCommand","args","onLine","reject","pipeLines","source","stream","captured","buffer","idx","line","stderrCaptured","tail","detail","venvInstallListeners","ensureVenv","listener","listeners","emit","event","l","venvPython","reusable","access","existing","rm","systemPython","err","message","parseResult","stdout","startMarker","endMarker","startIdx","endIdx","userStdout","jsonStr","result","failedExecutionResult","error","executePythonStep","params","timeout","pythonBin","start","tmpDir","mkdtemp","tmpdir","wrapperPath","scriptPath","writeFile","env","exitCode","stderr","stdoutChunks","stderrChunks","settled","timer","finish","durationMs","base","TEXT_EXTENSIONS","CRYPTO_ALG","CRYPTO_VERSION","deserializeEnvelope","encrypt","serializeEnvelope","proxyLogEntryToString","entry","cache","upstream","SOURCE_FILE_MAX_BYTES","SKIP_FILES","isLocalHost","host","hostname","PROXY_ALLOWED_DOMAINS","isAllowedWizardTarget","target","url","domain","isAllowedProxyTarget","isLocalOrigin","origin","resolveSafePath","realPluginDir","relParam","rel","abs","resolve","sep","realAbs","realpath","isInsideSkippedDir","pluginDir","segment","SKIP_DIRS","getViewerPath","filename","fileURLToPath","join","dirname","extractUpstreamStatus","upstreamPath","headers","body","parsed","fileExists","filePath","access","createRequestHandler","viewerPath","createServerLog","createProxyLog","credentialsRef","activeProfileRef","outputDir","broadcast","onProxyCacheChange","lastPathRef","cacheEnabled","proxyCache","createProxyCache","realpathSync","req","res","profiles","listCredentialProfiles","chunks","chunk","profileName","creds","loadGlobalCredentials","loadCredentialProfile","active","currentConfig","loadConfig","saveConfig","bundlePath","content","readFile","stepParams","normalizeStepInputs","event","result","executePythonStep","envelope","encrypt","serialized","serializeEnvelope","err","parseError","deserializeEnvelope","bufLen","b64","checks","CRYPTO_VERSION","CRYPTO_ALG","c","rawTarget","wizardBase","resolveWizardBase","upstreamUrl","method","_wizardHost","_encTarget","wizardForwardHeaders","resolvedBody","upstream","message","wizardResponseHeaders","sanitizeUpstreamHeaders","wizardBody","proxyTarget","_drop","forwardHeaders","cacheKey","cached","fromCache","responseHeaders","responseBody","readBodyWithLimit","MAX_PROXY_BYTES","dirEntries","readdir","entries","entry","kind","stats","stat","a","b","normalizedPath","detail","ext","extname","explicitMime","MIME_TYPES","isKnownText","TEXT_EXTENSIONS","contentType","createReadStream","resolvedPath","mimeType","ProxyResponseTooLargeError","launch","createRequire","mkdirSync","readFile","dirname","join","fileURLToPath","CDP","CSP_HEADERS","KIZEN_DOMAINS","isKizenUrl","url","hostname","d","installDockIcon","client","iconPath","icon","launchChromeViewer","opts","baseUrl","chrome","cdpPort","cookieTimer","mainTargetId","reconnectTimer","reconnectAttempt","killed","dbg","msg","vb","clearCookieTimer","isNewTabUrl","setupClient","c","rawParams","params","requestId","request","responseHeaders","responseStatusCode","filtered","rewroteSetCookie","h","patched","cookie","body","base64Encoded","e","e2","cookies","raw","bare","handleTarget","targetInfo","scheduleReconnect","delay","attemptNumber","MAX_CDP_ATTEMPTS","CDP_ATTEMPT_DELAY_MS","attempt","r","warning","useCallback","useState","useLogHistory","limit","history","setHistory","append","message","h","useCallback","useEffect","useState","Box","Text","useInput","jsx","jsxs","FIELDS","FIELD_LABELS","Hint","text","Text","CredentialSetupUI","initialMode","showProfileManager","onComplete","onCancel","phase","setPhase","useState","inputBuffer","setInputBuffer","error","setError","activeProfileName","setActiveProfileName","handleModeChosen","useCallback","mode","handleProfileChosen","profile","profiles","listCredentialProfiles","existing","loadGlobalCredentials","loadCredentialProfile","envCursor","ENVIRONMENTS","handleSave","values","environment","credentials","saveCredentialProfile","DEFAULT_PROFILE_NAME","err","useInput","input","key","loadProfileList","cursor","addNewIdx","totalItems","selected","nameBuffer","existingProfiles","trimmed","p","field","fieldName","prev","updatedValues","prevField","nextField","useEffect","label","Box","AppHeader","opt","i","nameError","activeField","isEnvField","profileLabel","GLOBAL_CREDENTIALS_PATH","name","isActive","displayValue","env","isSelected","jsx","jsxs","SKIP_WATCH_PREFIXES","DevUI","port","pluginDir","outputDir","initialCredentials","initialCredentialMode","initialActiveProfile","initialLastPath","debug","verbose","autoViewer","cacheEnabled","credentialsRef","useRef","activeProfileRef","lastPathRef","credMode","setCredMode","useState","credentialMode","setCredentialMode","status","setStatus","errorMessage","setErrorMessage","serverLogHistory","appendServerLog","useLogHistory","buildLogHistory","appendBuildLog","cdpLogHistory","appendCdpLog","proxyLogHistory","setProxyLogHistory","buildStatus","setBuildStatus","buildError","setBuildError","buildIssues","setBuildIssues","lastBuilt","setLastBuilt","lastBundleSize","setLastBundleSize","wsClientCount","setWsClientCount","proxyCacheSize","setProxyCacheSize","proxyCacheHits","setProxyCacheHits","proxyCacheMisses","setProxyCacheMisses","buildingRef","viewerLaunchedRef","chromeHandleRef","debounceTimerRef","wsClientsRef","pendingMessagesRef","broadcast","useCallback","msg","json","pruned","client","createServerLog","launchChromeViewerCb","launchChromeViewer","join","handle","useEffect","onExit","useInput","input","key","handleCredentialsDone","result","profile","saveConfig","createProxyLog","entry","h","proxyLogEntryToString","n","createBuildLog","message","triggerBuild","runBuild","bundleSize","formatBytes","err","PluginValidationError","watcher","watch","_","filename","normalized","prefix","viewerPath","getViewerPath","fileExists","viewerBuilt","handler","createRequestHandler","server","createServer","wss","WebSocketServer","ws","CredentialSetupUI","elapsedSeconds","elapsedLabel","buildErrorCount","issue","Box","AppHeader","Text","Spinner","ValidationIssues","log","index","i","runSetupUI","initialMode","resolve","unmountFn","handleComplete","result","unmount","render","createElement","CredentialSetupUI","devCommand","program","options","port","pluginDir","outputDir","ensureGitignore","credentials","credentialMode","activeCredentialProfile","lastPath","loadConfig","loadCredentialsFromFile","config","loadCredentialProfile","loadGlobalCredentials","profile","saveConfig","verbose","debug","autoViewer","cacheEnabled","waitUntilExit","DevUI","createElement","render","useCallback","useEffect","useState","Box","Text","useApp","useInput","encrypt","serializeEnvelope","isConnRefused","err","e","authHeaders","credentials","wizardFetch","wizardBase","path","init","readJsonSafe","res","text","parsed","fetchPublicKey","ctx","apiName","resolveWizardBase","data","errMsg","encryptLocally","publicKeyPem","value","envelope","encrypt","serialized","serializeEnvelope","encryptRemote","encryptSecret","onPhase","publicKey","spawn","platform","clipboardCommands","CLIPBOARD_TIMEOUT_MS","runClipboardCommand","text","cmd","args","resolve","child","spawned","settled","finish","ok","timer","code","copyToClipboard","command","Fragment","jsx","jsxs","Hint","text","Text","EncryptUI","ctx","stageDefaulted","credentialsPath","initialApiName","defaultApiName","initialValue","onDone","app","useApp","phase","setPhase","useState","credentials","setCredentials","apiName","setApiName","secret","setSecret","fail","useCallback","err","runEncryption","creds","name","value","envelopeValue","encryptSecret","p","envelope","copied","copyToClipboard","proceed","handleProfileChosen","profile","loadGlobalCredentials","loadCredentialProfile","useEffect","loadCredentialsFromFile","profiles","listCredentialProfiles","only","useInput","input","key","cursor","selected","buffer","modeLabel","stageLabel","frame","children","Box","AppHeader","Spinner","i","readFile","writeFile","join","envelopeObject","value","compactEnvelope","writeEnvelopeFile","path","DEFAULT_STAGE","isValidStage","stage","invalidStageMessage","resolveStage","defaultStageNotice","readManifestDefaults","cwd","raw","parsed","manifest","apiName","stripTrailingNewlines","readStdin","chunks","chunk","runHeadless","ctx","options","defaults","stageWasDefaulted","deps","credentials","apiName","defaultStageNotice","value","stripTrailingNewlines","envelopeValue","compactEnvelope","err","encryptCommand","program","options","isValidStage","invalidStageMessage","defaults","readManifestDefaults","stage","stageWasDefaulted","resolveStage","ctx","runHeadless","loadCredentialsFromFile","loadGlobalCredentials","encryptSecret","readStdin","text","writeEnvelopeFile","code","err","envelopeValue","waitUntilExit","render","createElement","EncryptUI","value","VALID_ICONS","VALID_ICONS_LIST","CUSTOM_ICON_NAMES","ALL_VALID_ICONS_LIST","iconsCommand","program","name","ALL_VALID_ICONS_LIST","mkdir","writeFile","readFile","join","SENSITIVE_FIELDS","redactServices","services","svc","s","redacted","k","buildTree","files","root","file","parts","node","part","i","next","sortTreeChildren","a","b","fileId","path","esc","str","fileExt","idx","LANG_MAP","mdLang","mdFence","content","longestRun","max","m","renderTextTree","prefix","sorted","child","isLast","connector","childPrefix","LICENSE_FILE","filterSourceFiles","f","buildFilteredConfig","manifest","v","IMAGE_MIME","renderTree","renderFileSection","body","generateMarkdown","filtered","name","version","description","sourceFiles","lines","configJson","configFence","fence","generateHtml","treeHtml","fileSections","EXAMPLES_DIR","join","GLOBAL_CREDENTIALS_DIR","reportCommand","program","options","pluginDir","manifest","raw","readFile","parsed","apiName","htmlPath","mdPath","files","readLocalFiles","mkdir","writeFile","generateHtml","generateMarkdown","readVersion","pkgPath","join","dirname","fileURLToPath","readFileSync","createProgram","program","Command","createCommand","buildCommand","devCommand","encryptCommand","reportCommand","iconsCommand","createProgram"]}
|