@runeya/runeya 2.0.136 → 2.0.138
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/agent/index.js +29 -7
- package/agent/index.js.map +1 -1
- package/{agent-manager-TUFAFC6U.js → agent-manager-2AZVCQRI.js} +3 -3
- package/{chat-UBUGGGBZ.js → chat-SWYI4ENT.js} +5 -5
- package/{chunk-7JAJSV4L.js → chunk-ALWA4K5L.js} +2 -2
- package/{chunk-5JUONZ3G.js → chunk-C6LIGJFX.js} +4 -4
- package/{chunk-G4CR7O3L.js → chunk-GUIONCNA.js} +6 -6
- package/{chunk-4RMM2OUU.js → chunk-OZBSOSAS.js} +31 -8
- package/chunk-OZBSOSAS.js.map +1 -0
- package/{companion-U3FKH7SQ.js → companion-JYLQKSFO.js} +4 -4
- package/index.js +4 -4
- package/{node-JU7A5NDT.js → node-RN4URNZ5.js} +4 -2
- package/package.json +1 -1
- package/{src-XAKZS5VF.js → src-42DMJB3D.js} +7 -7
- package/chunk-4RMM2OUU.js.map +0 -1
- /package/{agent-manager-TUFAFC6U.js.map → agent-manager-2AZVCQRI.js.map} +0 -0
- /package/{chat-UBUGGGBZ.js.map → chat-SWYI4ENT.js.map} +0 -0
- /package/{chunk-7JAJSV4L.js.map → chunk-ALWA4K5L.js.map} +0 -0
- /package/{chunk-5JUONZ3G.js.map → chunk-C6LIGJFX.js.map} +0 -0
- /package/{chunk-G4CR7O3L.js.map → chunk-GUIONCNA.js.map} +0 -0
- /package/{companion-U3FKH7SQ.js.map → companion-JYLQKSFO.js.map} +0 -0
- /package/{node-JU7A5NDT.js.map → node-RN4URNZ5.js.map} +0 -0
- /package/{src-XAKZS5VF.js.map → src-42DMJB3D.js.map} +0 -0
package/agent/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/create-agent.ts","../src/trpc/trpc.ts","../src/trpc/routers/process.ts","../src/services/process-manager.ts","../../../packages/shared/src/schemas/user.schema.ts","../../../packages/shared/src/schemas/org.schema.ts","../../../packages/shared/src/schemas/project.schema.ts","../../../packages/shared/src/schemas/service.schema.ts","../../../packages/shared/src/schemas/settings.schema.ts","../../../packages/shared/src/schemas/scenario.schema.ts","../../../packages/shared/src/schemas/log-source.schema.ts","../../../packages/shared/src/schemas/process.schema.ts","../../../packages/shared/src/schemas/log.schema.ts","../../../packages/shared/src/schemas/agent.schema.ts","../../../packages/shared/src/schemas/permission.schema.ts","../../../packages/shared/src/schemas/sync.schema.ts","../../../packages/shared/src/schemas/audit.schema.ts","../../../packages/shared/src/schemas/metrics.schema.ts","../../../packages/shared/src/schemas/environment.schema.ts","../../../packages/shared/src/schemas/environment-overrides.schema.ts","../../../packages/shared/src/schemas/api-key.schema.ts","../../../packages/shared/src/schemas/image.schema.ts","../../../packages/shared/src/schemas/kanban.schema.ts","../../../packages/shared/src/schemas/cloud-api-key.schema.ts","../../../packages/shared/src/schemas/integration.schema.ts","../../../packages/shared/src/schemas/changelog.schema.ts","../../../packages/shared/src/utils/crypto.ts","../../../packages/shared/src/js-log-parser.ts","../../../packages/shared/src/builtins.ts","../../../packages/shared/src/constants/intervals.ts","../../../packages/shared/src/constants/buffers.ts","../../../packages/shared/src/constants/timeouts.ts","../../../packages/shared/src/constants/editors.ts","../../../packages/shared/src/sync/json-crdt.ts","../../../packages/runner-native/src/native-runner.ts","../../../node_modules/shellwords/src/shellwords.ts","../../../packages/runner-docker/src/index.ts","../src/services/process-store.ts","../src/services/log-sources/console-log-source.ts","../src/services/log-parser.ts","../src/services/log-buffer.ts","../src/utils/strip-ansi.ts","../src/services/log-sources/file-log-source.ts","../src/services/log-sources/mongo-log-source.ts","../src/services/log-sources/mysql-log-source.ts","../src/services/log-sources/log-source-factory.ts","../src/services/metrics-collector.ts","../src/services/health-checker.ts","../src/utils/env.ts","../src/trpc/routers/config.ts","../src/services/traefik-manager.ts","../src/config/env.ts","../src/trpc/routers/health.ts","../../../packages/shared/src/node/node-path.ts","../../../packages/shared/src/node/user-path.ts","../../../packages/shared/src/node/log-timestamps.ts","../../../packages/shared/src/node/cli-invocation.ts","../../../packages/shared/src/node/aes-gcm.ts","../src/trpc/routers/terminal.ts","../src/services/terminal-manager.ts","../src/trpc/routers/git.ts","../src/utils/git-remote.ts","../src/trpc/routers/ai.ts","../src/services/ai-spawn-manager.ts","../../../packages/mcp-server/src/launch.ts","../src/services/codex-app-server-manager.ts","../src/services/ai-context-files.ts","../src/services/ai-paste-image.ts","../src/trpc/routers/wiki.ts","../src/trpc/router.ts","../src/index.ts"],"sourcesContent":["import express from 'express';\nimport cors from 'cors';\nimport { createServer, type Server } from 'node:http';\nimport { WebSocketServer, type WebSocket } from 'ws';\nimport crypto from 'node:crypto';\nimport { createExpressMiddleware } from '@trpc/server/adapters/express';\nimport { applyWSSHandler } from '@trpc/server/adapters/ws';\nimport { appRouter } from './trpc/router.js';\nimport { createContext, setPassphrase, getPassphrase } from './trpc/trpc.js';\nimport { processManager } from './services/process-manager.js';\nimport { traefikManager } from './services/traefik-manager.js';\nimport { codexAppServerManager } from './services/codex-app-server-manager.js';\nimport { getHealthData } from './trpc/routers/health.js';\nimport { env } from './config/env.js';\n\nexport interface AgentInstance {\n app: express.Express;\n server: Server;\n trpcWss: WebSocketServer;\n healthWss: WebSocketServer;\n passphraseHex: string;\n shutdown: () => Promise<void>;\n}\n\nexport function createAgent(opts?: { passphraseHex?: string; healthWsIntervalMs?: number }): AgentInstance {\n const passphraseHex = opts?.passphraseHex ?? crypto.randomBytes(32).toString('hex');\n const healthWsIntervalMs = opts?.healthWsIntervalMs ?? env.HEALTH_WS_INTERVAL;\n setPassphrase(passphraseHex);\n\n const app = express();\n const server = createServer(app);\n\n // Agent is accessed server-to-server only (CORS doesn't apply),\n // but restrict to localhost for defense-in-depth.\n app.use(cors({ origin: 'http://localhost:4000' }));\n\n // tRPC HTTP handler\n app.use('/api/trpc', createExpressMiddleware({\n router: appRouter,\n createContext,\n }));\n\n // Both WSS in noServer mode — we route upgrades manually\n const trpcWss = new WebSocketServer({ noServer: true });\n applyWSSHandler({\n wss: trpcWss,\n router: appRouter,\n createContext: ({ req }) => {\n // Extract auth from the WS upgrade request headers\n return { authorization: req.headers.authorization ?? null };\n },\n });\n\n const healthWss = new WebSocketServer({ noServer: true });\n\n healthWss.on('connection', (ws: WebSocket) => {\n // Send health immediately, then on interval\n const sendHealth = async () => {\n if (ws.readyState !== ws.OPEN) return;\n try {\n const data = await getHealthData();\n ws.send(JSON.stringify(data));\n } catch (err) {\n console.debug('[agent] Health data collection error:', err);\n }\n };\n\n void sendHealth();\n const interval = setInterval(sendHealth, healthWsIntervalMs);\n\n ws.on('close', () => clearInterval(interval));\n ws.on('error', () => clearInterval(interval));\n });\n\n // Route upgrade requests by path\n server.on('upgrade', (req, socket, head) => {\n const pathname = new URL(req.url ?? '/', `http://${req.headers.host}`).pathname;\n\n if (pathname === '/ws/health') {\n // Validate passphrase from Authorization header only (never query params)\n const authHeader = req.headers.authorization;\n let token: string | null = null;\n\n if (authHeader?.startsWith('Bearer ')) {\n token = authHeader.slice(7);\n }\n\n if (!token || !/^[0-9a-f]+$/i.test(token)) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n\n const tokenBuffer = Buffer.from(token, 'hex');\n const passphrase = getPassphrase();\n if (tokenBuffer.length !== passphrase.length || !crypto.timingSafeEqual(tokenBuffer, passphrase)) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n\n healthWss.handleUpgrade(req, socket, head, (ws) => {\n healthWss.emit('connection', ws, req);\n });\n } else {\n // Validate passphrase at upgrade level to prevent unauthenticated WS connections\n const trpcAuth = req.headers.authorization;\n let trpcToken: string | null = null;\n if (trpcAuth?.startsWith('Bearer ')) {\n trpcToken = trpcAuth.slice(7);\n }\n if (!trpcToken || !/^[0-9a-f]+$/i.test(trpcToken)) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n const trpcTokenBuffer = Buffer.from(trpcToken, 'hex');\n const trpcPassphrase = getPassphrase();\n if (trpcTokenBuffer.length !== trpcPassphrase.length || !crypto.timingSafeEqual(trpcTokenBuffer, trpcPassphrase)) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n\n trpcWss.handleUpgrade(req, socket, head, (ws) => {\n trpcWss.emit('connection', ws, req);\n });\n }\n });\n\n const shutdown = async () => {\n codexAppServerManager.shutdown();\n await traefikManager.stop();\n await processManager.shutdownAll();\n\n // Close WS servers and HTTP with timeout guards\n await Promise.race([\n new Promise<void>((resolve) => healthWss.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 5_000)),\n ]);\n await Promise.race([\n new Promise<void>((resolve) => trpcWss.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 5_000)),\n ]);\n await Promise.race([\n new Promise<void>((resolve) => server.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 5_000)),\n ]);\n };\n\n return { app, server, trpcWss, healthWss, passphraseHex, shutdown };\n}\n","import { initTRPC, TRPCError } from '@trpc/server';\nimport type { CreateExpressContextOptions } from '@trpc/server/adapters/express';\nimport crypto from 'node:crypto';\n\nlet agentPassphrase: Buffer;\n\nexport function setPassphrase(passphrase: string): void {\n if (!/^[0-9a-f]+$/i.test(passphrase)) {\n throw new Error('Passphrase must be a valid hex string');\n }\n agentPassphrase = Buffer.from(passphrase, 'hex');\n}\n\nexport function getPassphrase(): Buffer {\n return agentPassphrase;\n}\n\nexport function createContext({ req }: CreateExpressContextOptions) {\n return {\n authorization: req.headers.authorization ?? null,\n };\n}\n\ntype Context = Awaited<ReturnType<typeof createContext>>;\n\nconst t = initTRPC.context<Context>().create({\n errorFormatter({ shape, error }) {\n return {\n ...shape,\n data: {\n ...shape.data,\n // Only expose the message, never the full stack trace\n stack: undefined,\n },\n message: error instanceof TRPCError ? error.message : 'Internal server error',\n };\n },\n});\n\nexport const router = t.router;\n\n/** Auth middleware: validates Bearer passphrase using timing-safe comparison */\nconst authMiddleware = t.middleware(({ ctx, next }) => {\n const { authorization } = ctx;\n if (!authorization) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Missing Authorization header' });\n }\n\n const [scheme, token] = authorization.split(' ');\n if (scheme !== 'Bearer' || !token) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid Authorization format. Expected: Bearer <passphrase>' });\n }\n\n if (!/^[0-9a-f]+$/i.test(token)) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid passphrase format' });\n }\n\n const tokenBuffer = Buffer.from(token, 'hex');\n if (tokenBuffer.length !== agentPassphrase.length || !crypto.timingSafeEqual(tokenBuffer, agentPassphrase)) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid passphrase' });\n }\n\n return next({ ctx });\n});\n\nexport const protectedProcedure = t.procedure.use(authMiddleware);\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { processManager } from '../../services/process-manager.js';\nimport { ServiceConfigSchema, ServiceShortcutSchema, LOG_BUFFER_SIZE } from '@runeya/packages-shared';\n\n/** Max items in a subscription queue before dropping oldest */\nconst SUBSCRIPTION_QUEUE_MAX = LOG_BUFFER_SIZE;\n\nexport const processRouter = router({\n /** List all processes */\n list: protectedProcedure\n .query(() => {\n return processManager.listStatuses();\n }),\n\n /** Get a single process */\n get: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(({ input }) => {\n const status = processManager.getStatus(input.id);\n if (!status) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Process ${input.id} not found` });\n }\n return status;\n }),\n\n /** Deploy a service config (stores it, doesn't start) */\n deploy: protectedProcedure\n .input(ServiceConfigSchema)\n .mutation(({ input }) => {\n const id = processManager.deploy(input);\n return { id };\n }),\n\n /** Undeploy: stop + remove */\n undeploy: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n await processManager.undeploy(input.id);\n return { success: true };\n }),\n\n /** Update the service config for a deployed process */\n updateConfig: protectedProcedure\n .input(z.object({ serviceId: z.string().max(128), config: ServiceConfigSchema }))\n .mutation(({ input }) => {\n processManager.updateConfig(input.serviceId, input.config);\n return { success: true as const };\n }),\n\n /** Start a deployed process */\n start: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n console.log(`[agent] start service=${input.id}`);\n await processManager.start(input.id);\n return processManager.getStatus(input.id);\n }),\n\n /** Stop a running process */\n stop: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n console.log(`[agent] stop service=${input.id}`);\n await processManager.stop(input.id);\n return processManager.getStatus(input.id);\n }),\n\n /** Restart a process */\n restart: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n console.log(`[agent] restart service=${input.id}`);\n await processManager.restart(input.id);\n return processManager.getStatus(input.id);\n }),\n\n /** Get buffered logs for a process */\n logs: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(({ input }) => {\n const logs = processManager.getLogs(input.id);\n return logs;\n }),\n\n /** Clear buffered logs for a process */\n clearLogBuffer: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(({ input }) => {\n processManager.clearLogBuffer(input.id);\n return { success: true };\n }),\n\n /** Execute a shortcut command and stream output into the process log */\n executeShortcut: protectedProcedure\n .input(z.object({ id: z.string().max(128), shortcut: ServiceShortcutSchema }))\n .mutation(async ({ input }) => {\n const result = await processManager.executeShortcut(input.id, input.shortcut);\n return result;\n }),\n\n /** Cancel a running shortcut command */\n cancelShortcut: protectedProcedure\n .input(z.object({ id: z.string().max(128), shortcutId: z.string().max(128) }))\n .mutation(({ input }) => {\n processManager.cancelShortcut(input.id, input.shortcutId);\n return { success: true };\n }),\n\n /** Cancel a running ad-hoc command */\n cancelAdHocCommand: protectedProcedure\n .input(z.object({ id: z.string().max(128), commandId: z.string().max(128).optional() }))\n .mutation(({ input }) => {\n processManager.cancelAdHocCommand(input.id, input.commandId);\n return { success: true };\n }),\n\n /** Execute an ad-hoc command and stream output into the process log */\n executeAdHocCommand: protectedProcedure\n .input(z.object({\n id: z.string().max(128),\n command: z.string().min(1).max(4096),\n cwd: z.string().max(4096).optional(),\n commandId: z.string().max(128).optional(),\n }))\n .mutation(async ({ input }) => {\n const result = await processManager.executeAdHocCommand(input.id, input.command, input.cwd, input.commandId);\n return result;\n }),\n\n /** List active log source types for a process */\n logSources: protectedProcedure\n .input(z.object({ processId: z.string().max(128) }))\n .query(({ input }) => {\n return processManager.getLogSourceTypes(input.processId);\n }),\n\n /** Get current metrics for a process */\n metrics: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n return processManager.getMetrics(input.id);\n }),\n\n /** Subscribe to real-time log stream (yields batches of ParsedLog[]) */\n onLog: protectedProcedure\n .input(z.object({ processId: z.string().max(128).optional() }).optional())\n .subscription(async function* ({ input }) {\n const queue: unknown[][] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (batch: unknown[]) => {\n const filtered = input?.processId\n ? batch.filter((log) => (log as { processId?: string }).processId === input.processId)\n : batch;\n if (filtered.length === 0) return;\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(filtered);\n if (resolve) { resolve(); resolve = null; }\n };\n\n processManager.on('logs', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift();\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n processManager.off('logs', handler);\n }\n }),\n\n /** Subscribe to real-time status changes */\n onStatus: protectedProcedure\n .input(z.object({ processId: z.string().max(128).optional() }).optional())\n .subscription(async function* ({ input }) {\n console.debug('[agent] onStatus subscription started', input?.processId ? `for process ${input.processId}` : '(all processes)');\n const queue: unknown[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (status: unknown) => {\n const entry = status as { id?: string };\n if (!input?.processId || entry.id === input.processId) {\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(status);\n if (resolve) { resolve(); resolve = null; }\n }\n };\n\n processManager.on('status', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift();\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n console.debug('[agent] onStatus subscription ended', input?.processId ? `for process ${input.processId}` : '(all processes)');\n processManager.off('status', handler);\n }\n }),\n\n /** Subscribe to real-time health status changes */\n onHealth: protectedProcedure\n .input(z.object({ processId: z.string().max(128).optional() }).optional())\n .subscription(async function* ({ input }) {\n const queue: unknown[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (healthData: unknown) => {\n const entry = healthData as { processId?: string };\n if (!input?.processId || entry.processId === input.processId) {\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(healthData);\n if (resolve) { resolve(); resolve = null; }\n }\n };\n\n processManager.on('health', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift();\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n processManager.off('health', handler);\n }\n }),\n\n /** Subscribe to real-time metrics */\n onMetrics: protectedProcedure\n .input(z.object({ processId: z.string().max(128).optional() }).optional())\n .subscription(async function* ({ input }) {\n const queue: unknown[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (metrics: unknown) => {\n const entry = metrics as { processId?: string };\n if (!input?.processId || entry.processId === input.processId) {\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(metrics);\n if (resolve) { resolve(); resolve = null; }\n }\n };\n\n processManager.on('metrics', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift();\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n processManager.off('metrics', handler);\n }\n }),\n});\n","import { EventEmitter } from 'node:events';\nimport { randomUUID } from 'node:crypto';\nimport { networkInterfaces, homedir, platform } from 'node:os';\nimport { join, isAbsolute, resolve } from 'node:path';\nimport type { ServiceConfig, ProcessStatus, ServiceShortcut, JSLogParserDef, ILogSource } from '@runeya/packages-shared';\nimport { interpolateBuiltinsInEnv, withDeprecatedAliases } from '@runeya/packages-shared';\nimport { NativeRunner, findUnresolvedEnvVars, resolveCwd } from '@runeya/packages-runner-native';\nimport type { Runner, RunnerStartConfig } from '@runeya/packages-runner-native';\nimport { DockerRunner, type DockerRunnerStartConfig } from '@runeya/packages-runner-docker';\nimport { processStore, type StoredProcess, type CommandProcess } from './process-store.js';\nimport { ConsoleLogSource } from './log-sources/console-log-source.js';\nimport { LogBuffer } from './log-buffer.js';\nimport { LogParser } from './log-parser.js';\nimport { createLogSource } from './log-sources/log-source-factory.js';\nimport { MetricsCollector } from './metrics-collector.js';\nimport { healthChecker } from './health-checker.js';\nimport { traefikManager } from './traefik-manager.js';\nimport killPort from 'kill-port';\nimport { env } from '../config/env.js';\nimport { resolveEnv } from '../utils/env.js';\n\n/**\n * Le répertoire d'une commande, ancré sur celui du projet.\n *\n * Une commande porte son propre `cwd`, souvent vide ou relatif ; le serveur, lui,\n * pose `resolvedCwd` — l'emplacement du projet sur cette machine. Sans cet\n * ancrage, une commande sans `cwd` retombait sur le répertoire de l'agent (celui\n * du lancement de Runeya) et s'exécutait contre le mauvais dépôt.\n *\n * Un `cwd` absolu, ou que l'agent étend lui-même (`~`, `$VAR`), passe intact :\n * le préfixer produirait un chemin qui n'existe nulle part.\n */\nexport function anchorCommandCwd(\n cwd: string | undefined,\n serviceConfig: ServiceConfig,\n): string | undefined {\n const base = serviceConfig.resolvedCwd ?? serviceConfig.cwd;\n const raw = (cwd ?? '').trim();\n if (!raw || raw === '.') return base ?? undefined;\n if (!base || !isAbsolute(base)) return raw;\n if (isAbsolute(raw) || raw.startsWith('~') || raw.startsWith('$')) return raw;\n return join(base, raw);\n}\n\n/**\n * Le répertoire où les commandes d'un service s'exécutent réellement, absolu.\n *\n * Passe par exactement les mêmes étapes que le lancement — ancrage sur le\n * projet, expansion des variables — puis absolutise contre le répertoire de\n * l'agent, ce que le spawn fait de toute façon. Une valeur reconstruite\n * autrement ne prouverait rien ; celle-ci dit où le code tourne vraiment,\n * y compris quand il retombe sur le répertoire de l'agent.\n */\nfunction effectiveProcessCwd(serviceConfig: ServiceConfig): string {\n const first = serviceConfig.commands?.[0];\n const anchored = anchorCommandCwd(first?.cwd, serviceConfig);\n return resolve(resolveCwd(anchored, resolveEnv(serviceConfig.env)));\n}\n\n/** Get the first non-internal IPv4 LAN address of this machine. */\nfunction getLanIp(): string {\n const nets = networkInterfaces();\n for (const name of Object.keys(nets)) {\n for (const net of nets[name] ?? []) {\n if (net.family === 'IPv4' && !net.internal) {\n return net.address;\n }\n }\n }\n return '127.0.0.1';\n}\n\n/**\n * Les builtins que seule la machine d'exécution peut produire : son IP sur le\n * réseau local, son système, le dossier de son utilisateur, et le répertoire\n * de travail effectif du service. Le serveur laisse volontairement ces\n * références intactes — les résoudre chez lui graverait la machine qui a\n * déployé plutôt que celle qui exécute.\n */\nexport function resolveAgentBuiltins(serviceConfig: ServiceConfig): Record<string, string> {\n const values: Record<string, string> = {\n 'agent.HOST_LAN': getLanIp(),\n 'agent.OS': platform(),\n 'agent.HOME': homedir(),\n // Le cwd est calculé avec l'env AVANT substitution : une variable qui\n // référencerait `{{service.CWD}}` ne peut donc pas se boucler sur\n // elle-même — la substitution ne repasse jamais sur son propre résultat.\n 'service.CWD': resolve(resolveCwd(\n serviceConfig.resolvedCwd ?? serviceConfig.cwd,\n resolveEnv(serviceConfig.env),\n )),\n };\n return withDeprecatedAliases(values);\n}\n\n/**\n * L'env d'un service, ses références de machine remplacées.\n *\n * Tout ce qui exécute quelque chose sur cette machine passe par ici — le\n * démarrage, un raccourci, une commande ponctuelle. Les deux derniers se\n * contentaient de `resolveEnv`, si bien qu'un `{{agent.HOST_LAN}}` y arrivait\n * en clair alors que le service démarré, lui, recevait l'adresse : la même\n * variable ne valait pas la même chose selon la façon de la lire.\n */\nexport function resolveMachineBuiltins(serviceConfig: ServiceConfig): Record<string, string> {\n return interpolateBuiltinsInEnv(serviceConfig.env ?? {}, resolveAgentBuiltins(serviceConfig));\n}\n\nexport class ProcessManager extends EventEmitter {\n private runners: Map<string, Runner> = new Map();\n private consoleLogSource: ConsoleLogSource;\n private metricsCollector: MetricsCollector;\n\n /** Shared buffer for all non-console log sources (file, mongo, mysql) */\n private additionalBuffer = new LogBuffer(env.LOG_BUFFER_SIZE);\n /** Per-processId list of active non-console log sources */\n private additionalSources = new Map<string, ILogSource[]>();\n\n constructor() {\n super();\n this.runners.set('native', new NativeRunner());\n this.runners.set('docker', new DockerRunner());\n this.consoleLogSource = new ConsoleLogSource(env.LOG_BUFFER_SIZE);\n this.metricsCollector = new MetricsCollector(env.METRICS_INTERVAL);\n\n // Forward events from sub-components\n this.consoleLogSource.on('logs', (batch) => this.emit('logs', batch));\n this.metricsCollector.on('metrics', (metrics) => this.emit('metrics', metrics));\n healthChecker.on('health', (result) => {\n this.emit('health', result);\n // Re-emit status so frontend picks up the updated healthStatus\n this.emitStatus(result.processId);\n });\n }\n\n /** Log warnings for any $VAR references that could not be resolved in the given strings.\n * Returns true if any unresolved variables were found. */\n private warnUnresolvedVars(processId: string, env: Record<string, string>, fields: Record<string, string | undefined>): boolean {\n let found = false;\n for (const [label, value] of Object.entries(fields)) {\n if (!value) continue;\n const unresolved = findUnresolvedEnvVars(value, env);\n if (unresolved.length > 0) {\n found = true;\n this.consoleLogSource.addSystemLog(\n processId,\n `Unresolved variable${unresolved.length > 1 ? 's' : ''} in ${label}: ${unresolved.map((n: string) => '$' + n).join(', ')}`,\n 'warn',\n { id: randomUUID(), type: 'system-warn', header: 'Unresolved variable', state: 'self' },\n );\n }\n }\n return found;\n }\n\n /** Deploy a service config (store it, don't start it) */\n deploy(config: ServiceConfig): string {\n // Use service ID as process ID for stability across agent restarts\n // This ensures the process ID remains the same when re-deployed after hot reload\n const id = config.id;\n\n // If process already exists, just update the config\n const existing = processStore.get(id);\n if (existing) {\n console.log(`[process-manager] Process ${id} already deployed, updating config`);\n existing.serviceConfig = config;\n this.emitStatus(id);\n return id;\n }\n\n const stored: StoredProcess = {\n id,\n serviceConfig: config,\n commandProcesses: [],\n state: 'stopped',\n exitCode: null,\n startedAt: null,\n restartCount: 0,\n manuallyStopped: false,\n operationInProgress: false,\n };\n processStore.set(id, stored);\n this.emitStatus(id);\n return id;\n }\n\n /** Update the service config for a deployed process (identified by serviceId).\n * Process must be stopped — updating while running would cause mid-flight inconsistencies. */\n updateConfig(serviceId: string, config: ServiceConfig): void {\n const proc = processStore.getByServiceId(serviceId);\n if (!proc) throw new Error(`No process found for service ${serviceId}`);\n if (proc.state === 'running' || proc.state === 'starting') {\n throw new Error(`Cannot update config while process is ${proc.state}. Stop the process first.`);\n }\n proc.serviceConfig = config;\n }\n\n /** Undeploy: stop if running, then remove */\n async undeploy(processId: string): Promise<void> {\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n\n if (proc.state === 'running' || proc.state === 'starting') {\n await this.stop(processId);\n }\n this.consoleLogSource.clearHistory(processId);\n this.additionalBuffer.clear(processId);\n healthChecker.stopChecking(processId);\n this.metricsCollector.stopAll();\n processStore.delete(processId);\n }\n\n /** Start a deployed process — launches ALL commands in parallel */\n async start(processId: string): Promise<void> {\n console.debug('[process-manager] Starting process', processId);\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n if (proc.state === 'running' || proc.state === 'starting') {\n throw new Error(`Process ${processId} is already ${proc.state}`);\n }\n\n // Resolve the machine-bound builtins ({{agent.*}}, {{service.CWD}}) the\n // server deliberately left alone\n if (proc.serviceConfig.env) {\n proc.serviceConfig = {\n ...proc.serviceConfig,\n env: resolveMachineBuiltins(proc.serviceConfig),\n };\n }\n\n const commands = (proc.serviceConfig.commands ?? []).filter((c) => c.command.trim());\n const isDocker = proc.serviceConfig.runner === 'docker';\n\n // If no commands, treat as no-op (service is just a container for shortcuts/env)\n // Exception: Docker runner can start with no commands (uses image CMD/ENTRYPOINT)\n if (commands.length === 0 && !isDocker) {\n this.consoleLogSource.addSystemLog(processId, 'No commands configured — nothing to start', 'warn');\n return;\n }\n\n // Immediately set to 'starting' to prevent race conditions from double-clicks\n proc.manuallyStopped = false;\n proc.state = 'starting';\n proc.exitCode = null;\n proc.commandProcesses = [];\n this.emitStatus(processId);\n\n const runner = this.runners.get(proc.serviceConfig.runner);\n if (!runner) {\n proc.state = 'errored';\n proc.exitCode = 1;\n this.emitStatus(processId);\n throw new Error(`Runner '${proc.serviceConfig.runner}' not available`);\n }\n\n // Set JS parsers for the log streamer (per-process)\n const jsParsers = (proc.serviceConfig.resolvedLogParsers ?? []) as JSLogParserDef[];\n this.consoleLogSource.setJSParsers(processId, jsParsers);\n\n // For Docker runner with no commands, use a synthetic entry so the container starts\n // using the image's built-in CMD/ENTRYPOINT.\n const effectiveCommands =\n isDocker && commands.length === 0\n ? [{ id: '__docker_default__', label: 'Docker container', command: '', shell: false, cwd: undefined }]\n : commands;\n\n // Warn about unresolved $VAR references in paths — abort if any found\n const mergedEnv = resolveEnv(proc.serviceConfig.env);\n let hasUnresolved = false;\n hasUnresolved = this.warnUnresolvedVars(processId, mergedEnv, { cwd: proc.serviceConfig.cwd }) || hasUnresolved;\n for (const cmd of effectiveCommands) {\n hasUnresolved = this.warnUnresolvedVars(processId, mergedEnv, { [`${cmd.label || cmd.command} cwd`]: cmd.cwd }) || hasUnresolved;\n }\n if (proc.serviceConfig.dockerConfig?.volumes) {\n for (const vol of proc.serviceConfig.dockerConfig.volumes) {\n hasUnresolved = this.warnUnresolvedVars(processId, mergedEnv, { volume: vol }) || hasUnresolved;\n }\n }\n if (hasUnresolved) {\n this.consoleLogSource.addSystemLog(processId, 'Cannot start: unresolved variables in path (see above)', 'error', { id: randomUUID(), type: 'command-fail', header: 'Start aborted', state: 'self' });\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n return;\n }\n\n // Kill any process occupying the service ports before starting (silently ignore errors)\n const servicePorts = proc.serviceConfig.ports ?? [];\n for (const servicePort of servicePorts) {\n try {\n await killPort(servicePort);\n } catch {\n // Port not in use — ignore\n }\n }\n\n // Docker shared mode: start one persistent container, then exec each command inside it\n const dc = proc.serviceConfig.dockerConfig;\n const isSharedMode = isDocker && dc?.useNativeCommand && dc?.nativeCommandMode === 'shared';\n\n if (isSharedMode) {\n if (!dc) {\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n throw new Error('Docker runner selected but no dockerConfig found on service');\n }\n const dockerRunner = runner as DockerRunner;\n const sharedContainerConfig: DockerRunnerStartConfig = {\n command: '',\n shell: false,\n cwd: resolveCwd(proc.serviceConfig.resolvedCwd ?? proc.serviceConfig.cwd, resolveEnv(proc.serviceConfig.env)),\n env: resolveEnv(proc.serviceConfig.env),\n dockerConfig: dc,\n serviceId: processId,\n };\n const sharedProc = dockerRunner.startSharedContainer(sharedContainerConfig);\n proc.sharedContainerProcess = sharedProc;\n this.consoleLogSource.attach(processId, sharedProc.stdout, sharedProc.stderr, null);\n\n // Wait until the container is confirmed running before exec-ing into it\n try {\n await sharedProc.containerReady;\n } catch (err: unknown) {\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n throw new Error(`Shared container failed to start: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const containerName = `runeya-${processId}`;\n for (const cmd of effectiveCommands) {\n let runnerProcess;\n try {\n console.debug(`[process-manager] Exec in shared container \"${cmd.label || cmd.command}\": ${cmd.command}`);\n runnerProcess = dockerRunner.execInContainer(containerName, cmd.command, resolveEnv(proc.serviceConfig.env), proc.serviceConfig.dockerConfig?.nativeShell || 'sh');\n console.debug('[process-manager] Exec started');\n } catch (err: unknown) {\n const errMsg = err instanceof Error ? err.message : String(err);\n console.error('[process-manager] Failed to exec command \"' + (cmd.label || cmd.command) + '\":', errMsg); // nosemgrep: unsafe-formatstring\n this.consoleLogSource.addSystemLog(processId, `Failed to exec \"${cmd.label || cmd.command}\": ${errMsg}`, 'error');\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n await this.stopCommandProcesses(proc);\n throw new Error(`Failed to exec command \"${cmd.label || cmd.command}\": ${errMsg}`);\n }\n\n const cmdProcess: CommandProcess = {\n commandId: cmd.id,\n runnerProcess,\n pid: null,\n containerName: runnerProcess.containerName ?? null,\n exitCode: null,\n };\n proc.commandProcesses = [...proc.commandProcesses, cmdProcess];\n this.consoleLogSource.addSystemLog(processId, cmd.command, 'info', { id: randomUUID(), type: 'command-start', header: cmd.label || cmd.command, state: 'self', collapsable: false });\n this.consoleLogSource.attach(processId, runnerProcess.stdout, runnerProcess.stderr, null);\n\n runnerProcess.exitPromise.then(({ exitCode, signal, error }) => {\n const current = processStore.get(processId);\n if (!current) return;\n const cpIdx = current.commandProcesses.findIndex(cp => cp.commandId === cmd.id);\n if (cpIdx >= 0) {\n current.commandProcesses = current.commandProcesses.map((cp, i) =>\n i === cpIdx ? { ...cp, runnerProcess: null, exitCode } : cp\n );\n }\n if (exitCode !== 0) {\n const errorMsg = error\n ? error\n : signal\n ? `terminated with signal ${signal}`\n : `exited with code ${exitCode}`;\n this.consoleLogSource.addSystemLog(processId, errorMsg, 'error', { id: randomUUID(), type: 'command-fail', header: cmd.label || cmd.command, state: 'self' });\n }\n this.updateAggregateState(processId);\n }, (err: Error) => {\n console.error('[process-manager] Exec error for command \"' + (cmd.label || cmd.command) + '\":', err.message); // nosemgrep: unsafe-formatstring\n const current = processStore.get(processId);\n if (!current) return;\n const cpIdx = current.commandProcesses.findIndex(cp => cp.commandId === cmd.id);\n if (cpIdx >= 0) {\n current.commandProcesses = current.commandProcesses.map((cp, i) =>\n i === cpIdx ? { ...cp, runnerProcess: null, exitCode: 1 } : cp\n );\n }\n this.consoleLogSource.addSystemLog(processId, `exec failed: ${err.message}`, 'error', { id: randomUUID(), type: 'command-fail', header: cmd.label || cmd.command, state: 'self' });\n this.updateAggregateState(processId);\n });\n }\n\n proc.startedAt = new Date();\n proc.state = 'running';\n proc.operationInProgress = false;\n this.emitStatus(processId);\n await this.startAdditionalSources(processId, proc.serviceConfig);\n healthChecker.startChecking(processId);\n return;\n }\n\n // Start each command (isolated or native runner)\n const mergedServiceEnv = resolveEnv(proc.serviceConfig.env);\n for (const cmd of effectiveCommands) {\n const runnerConfig: RunnerStartConfig = {\n command: cmd.command,\n shell: cmd.shell ?? false,\n cwd: anchorCommandCwd(cmd.cwd, proc.serviceConfig),\n env: mergedServiceEnv,\n };\n\n let runnerProcess;\n try {\n console.debug(`[process-manager] Starting command \"${cmd.label || cmd.command}\": ${cmd.command}`);\n if (proc.serviceConfig.runner === 'docker') {\n if (!proc.serviceConfig.dockerConfig) {\n throw new Error('Docker runner selected but no dockerConfig found on service');\n }\n const dockerConfig: DockerRunnerStartConfig = {\n command: cmd.command,\n shell: cmd.shell ?? false,\n cwd: resolveCwd(proc.serviceConfig.resolvedCwd ?? proc.serviceConfig.cwd, mergedServiceEnv),\n env: mergedServiceEnv,\n dockerConfig: proc.serviceConfig.dockerConfig,\n serviceId: processId,\n cmdId: cmd.id,\n };\n runnerProcess = (runner as DockerRunner).start(dockerConfig);\n } else {\n runnerProcess = runner.start(runnerConfig);\n }\n console.debug('[process-manager] Command started, PID:', runnerProcess.pid);\n } catch (err: unknown) {\n const errMsg = err instanceof Error ? err.message : String(err);\n console.error('[process-manager] Failed to start command \"' + (cmd.label || cmd.command) + '\":', errMsg); // nosemgrep: unsafe-formatstring\n this.consoleLogSource.addSystemLog(processId, `Failed to start \"${cmd.label || cmd.command}\": ${errMsg}`, 'error');\n // Mark all as errored and stop any already-started commands\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n await this.stopCommandProcesses(proc);\n throw new Error(`Failed to start command \"${cmd.label || cmd.command}\": ${errMsg}`);\n }\n\n const cmdProcess: CommandProcess = {\n commandId: cmd.id,\n runnerProcess,\n pid: runnerProcess.pid ?? null,\n containerName: runnerProcess.containerName ?? null,\n exitCode: null,\n };\n proc.commandProcesses = [...proc.commandProcesses, cmdProcess];\n\n // Emit command-start BEFORE attach so it always appears before any output in the buffer\n if (cmd.id !== '__docker_default__') {\n this.consoleLogSource.addSystemLog(\n processId,\n cmd.command,\n 'info',\n { id: randomUUID(), type: 'command-start', header: cmd.label || cmd.command, state: 'self', collapsable: false },\n );\n }\n\n // Attach log streaming with the command's PID\n this.consoleLogSource.attach(processId, runnerProcess.stdout, runnerProcess.stderr, runnerProcess.pid ?? null);\n\n // Start metrics collection — native (PID) or Docker (container name)\n if (runnerProcess.pid) {\n this.metricsCollector.startCollecting(processId, runnerProcess.pid);\n } else if (runnerProcess.containerName) {\n this.metricsCollector.startCollectingDocker(processId, runnerProcess.containerName);\n }\n\n // Handle exit per command\n runnerProcess.exitPromise.then(({ exitCode, signal, error }) => {\n const current = processStore.get(processId);\n if (!current) return;\n\n // Update this command's state\n const cpIdx = current.commandProcesses.findIndex(cp => cp.commandId === cmd.id);\n if (cpIdx >= 0) {\n current.commandProcesses = current.commandProcesses.map((cp, i) =>\n i === cpIdx ? { ...cp, runnerProcess: null, exitCode } : cp\n );\n }\n\n if (runnerProcess.pid) {\n this.metricsCollector.stopCollecting(processId);\n }\n\n // Log exit info for this command (only on failure)\n if (exitCode !== 0) {\n const errorMsg = error\n ? error\n : signal\n ? `terminated with signal ${signal}`\n : `exited with code ${exitCode}`;\n this.consoleLogSource.addSystemLog(processId, errorMsg, 'error', { id: randomUUID(), type: 'command-fail', header: cmd.label || cmd.command, state: 'self' });\n }\n\n // Update aggregate state\n this.updateAggregateState(processId);\n }, (err: Error) => {\n console.error('[process-manager] Spawn error for command \"' + (cmd.label || cmd.command) + '\":', err.message); // nosemgrep: unsafe-formatstring\n const current = processStore.get(processId);\n if (!current) return;\n\n const cpIdx = current.commandProcesses.findIndex(cp => cp.commandId === cmd.id);\n if (cpIdx >= 0) {\n current.commandProcesses = current.commandProcesses.map((cp, i) =>\n i === cpIdx ? { ...cp, runnerProcess: null, exitCode: 1 } : cp\n );\n }\n\n this.consoleLogSource.addSystemLog(processId, `spawn failed: ${err.message}`, 'error', { id: randomUUID(), type: 'command-fail', header: cmd.label || cmd.command, state: 'self' });\n this.updateAggregateState(processId);\n });\n }\n\n proc.startedAt = new Date();\n proc.state = 'running';\n proc.operationInProgress = false;\n this.emitStatus(processId);\n traefikManager.scheduleDynamicRegen();\n\n // Start additional log sources (file, mongo, mysql…) declared in logSources\n await this.startAdditionalSources(processId, proc.serviceConfig);\n\n // Start health checking if configured\n healthChecker.startChecking(processId);\n }\n\n /** Stop a running process: stop ALL command processes */\n async stop(processId: string): Promise<void> {\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n\n const hasActiveCommands = proc.commandProcesses.some(cp => cp.runnerProcess);\n const hasSharedContainer = !!proc.sharedContainerProcess;\n if (!hasActiveCommands && !hasSharedContainer) {\n proc.state = 'stopped';\n this.emitStatus(processId);\n return;\n }\n\n // Mark as manually stopped to prevent auto-restart with 'unless-stopped' strategy\n proc.manuallyStopped = true;\n\n await this.stopCommandProcesses(proc);\n await this.stopAdditionalSources(processId);\n\n proc.state = 'stopped';\n healthChecker.stopChecking(processId);\n this.metricsCollector.stopCollecting(processId);\n this.emitStatus(processId);\n traefikManager.scheduleDynamicRegen();\n }\n\n /** Restart = stop + start */\n async restart(processId: string): Promise<void> {\n await this.stop(processId);\n const proc = processStore.get(processId);\n if (proc) proc.restartCount++;\n await this.start(processId);\n }\n\n /** Get status of a process */\n getStatus(processId: string): ProcessStatus | null {\n const proc = processStore.get(processId);\n if (!proc) return null;\n return this.toProcessStatus(proc);\n }\n\n /** Get all process statuses */\n listStatuses(): ProcessStatus[] {\n return processStore.getAll().map(p => this.toProcessStatus(p));\n }\n\n /** Get logs for a process — merges console + additional sources, sorted by timestamp */\n getLogs(processId: string): ReturnType<ConsoleLogSource['getHistory']> {\n const consoleLogs = this.consoleLogSource.getHistory(processId);\n const additionalLogs = this.additionalBuffer.getByProcessId(processId);\n if (additionalLogs.length === 0) return consoleLogs;\n return [...consoleLogs, ...additionalLogs].sort(\n (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),\n );\n }\n\n /** Clear buffered logs for a process (does not delete parse rules) */\n clearLogBuffer(processId: string): void {\n this.consoleLogSource.clearBufferOnly(processId);\n this.additionalBuffer.clear(processId);\n }\n\n /** Return the types of active log sources for a given processId */\n getLogSourceTypes(processId: string): string[] {\n const types: string[] = ['console'];\n const extra = this.additionalSources.get(processId);\n if (extra) {\n for (const src of extra) types.push(src.type);\n }\n return types;\n }\n\n /** Get current metrics for a process */\n async getMetrics(processId: string): ReturnType<MetricsCollector['getMetrics']> {\n return this.metricsCollector.getMetrics(processId);\n }\n\n /** Get available runner types */\n async getAvailableRunners(): Promise<string[]> {\n const available: string[] = [];\n for (const [type, runner] of this.runners) {\n try {\n if (await runner.isAvailable()) {\n available.push(type);\n }\n } catch {\n // Runner availability check failed — treat as unavailable\n }\n }\n return available;\n }\n\n /** Shutdown all processes */\n async shutdownAll(): Promise<void> {\n const processes = processStore.getAll();\n await Promise.allSettled(\n processes\n .filter(p => p.state === 'running' || p.state === 'starting')\n .map(p => this.stop(p.id))\n );\n healthChecker.stopAll();\n this.metricsCollector.stopAll();\n }\n\n /** Launch a one-off command (shortcut or ad-hoc) using the appropriate runner for the process.\n * Centralises runner selection so executeShortcut / executeAdHocCommand share the logic. */\n private launchOneOffCommand(\n proc: StoredProcess,\n command: string,\n cwd: string | undefined,\n env: Record<string, string>,\n ) {\n const serviceConfig = proc.serviceConfig;\n // An explicit cwd (a shortcut's own) wins; otherwise the project-anchored\n // one, which is what makes a cloud project's shortcuts run in its directory.\n const effectiveCwd = anchorCommandCwd(cwd, serviceConfig);\n\n if (serviceConfig.runner === 'docker' && serviceConfig.dockerConfig) {\n const dockerRunner = this.runners.get('docker') as DockerRunner;\n if (!dockerRunner) throw new Error('Docker runner not available');\n const dockerConfig: DockerRunnerStartConfig = {\n command,\n shell: false,\n cwd: resolveCwd(effectiveCwd, env),\n env,\n dockerConfig: serviceConfig.dockerConfig,\n serviceId: proc.id,\n };\n return dockerRunner.runShortcut(dockerConfig, command);\n } else {\n const nativeRunner = this.runners.get('native') as NativeRunner;\n if (!nativeRunner) throw new Error('Native runner not available');\n return nativeRunner.start({\n command,\n shell: true,\n cwd: effectiveCwd,\n env,\n });\n }\n }\n\n private activeShortcuts = new Map<string, ReturnType<ProcessManager['launchOneOffCommand']>>();\n private activeAdHocCommands = new Map<string, ReturnType<ProcessManager['launchOneOffCommand']>>();\n\n cancelShortcut(processId: string, shortcutId: string): void {\n const key = `${processId}:${shortcutId}`;\n const proc = this.activeShortcuts.get(key);\n if (proc) proc.kill('SIGTERM');\n }\n\n cancelAdHocCommand(processId: string, commandId?: string): void {\n const targets: ReturnType<ProcessManager['launchOneOffCommand']>[] = [];\n if (commandId) {\n const key = `${processId}:${commandId}`;\n const proc = this.activeAdHocCommands.get(key);\n if (proc) targets.push(proc);\n } else {\n for (const [key, proc] of this.activeAdHocCommands) {\n if (key.startsWith(`${processId}:`)) targets.push(proc);\n }\n }\n for (const proc of targets) {\n proc.kill('SIGTERM');\n // Force kill after grace period if still running\n void Promise.race([\n proc.exitPromise,\n new Promise<void>((resolve) => setTimeout(resolve, 3000)),\n ]).then((result) => {\n if (result === undefined) proc.kill('SIGKILL');\n });\n }\n }\n\n /** Execute a shortcut command and stream its output as logs for the given process */\n async executeShortcut(processId: string, shortcut: ServiceShortcut): Promise<{ exitCode: number | null }> {\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n\n // Ensure JS parsers are loaded even if the process was never started (lazy deploy only sets config in store)\n const jsParsers = (proc.serviceConfig.resolvedLogParsers ?? []) as JSLogParserDef[];\n this.consoleLogSource.setJSParsers(processId, jsParsers);\n\n const shortcutName = shortcut.label || shortcut.command;\n this.consoleLogSource.addSystemLog(processId, `[shortcut] Running \"${shortcutName}\": ${shortcut.command}`, 'info');\n\n const serviceConfig = proc.serviceConfig;\n const env = resolveEnv(resolveMachineBuiltins(serviceConfig));\n\n const effectiveCwd = anchorCommandCwd(shortcut.cwd, serviceConfig);\n if (this.warnUnresolvedVars(processId, env, { 'shortcut cwd': effectiveCwd })) {\n this.consoleLogSource.addSystemLog(processId, `Cannot run shortcut \"${shortcutName}\": unresolved variables (see above)`, 'error', { id: randomUUID(), type: 'command-fail', header: shortcutName, state: 'self' });\n return { exitCode: 1 };\n }\n\n let runnerProcess;\n try {\n runnerProcess = this.launchOneOffCommand(proc, shortcut.command, shortcut.cwd, env);\n } catch (err: unknown) {\n this.consoleLogSource.addSystemLog(processId, `Failed to start: ${err instanceof Error ? err.message : String(err)}`, 'error', { id: randomUUID(), type: 'command-fail', header: shortcutName, state: 'self' });\n return { exitCode: 1 };\n }\n\n const shortcutKey = `${processId}:${shortcut.id}`;\n this.activeShortcuts.set(shortcutKey, runnerProcess);\n\n // Attach stdout/stderr to the same log stream as the parent process, with shortcut's PID\n this.consoleLogSource.attach(processId, runnerProcess.stdout, runnerProcess.stderr, runnerProcess.pid ?? null);\n\n const { exitCode, signal, error } = await runnerProcess.exitPromise;\n this.activeShortcuts.delete(shortcutKey);\n\n if (exitCode === 0) {\n this.consoleLogSource.addSystemLog(processId, `[shortcut] \"${shortcutName}\" completed successfully`, 'info');\n } else if (signal) {\n this.consoleLogSource.addSystemLog(processId, `[shortcut] \"${shortcutName}\" cancelled`, 'info');\n } else {\n const errorMsg = error ? error : `exited with code ${exitCode}`;\n this.consoleLogSource.addSystemLog(processId, errorMsg, 'error', { id: randomUUID(), type: 'command-fail', header: shortcutName, state: 'self' });\n }\n\n return { exitCode };\n }\n\n /** Execute an ad-hoc command and stream its output as logs for the given process */\n async executeAdHocCommand(processId: string, command: string, cwd?: string, commandId?: string): Promise<{ exitCode: number | null }> {\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n\n // Ensure JS parsers are loaded even if the process was never started (lazy deploy only sets config in store)\n const jsParsers = (proc.serviceConfig.resolvedLogParsers ?? []) as JSLogParserDef[];\n this.consoleLogSource.setJSParsers(processId, jsParsers);\n\n const serviceConfig = proc.serviceConfig;\n const env = resolveEnv(resolveMachineBuiltins(serviceConfig));\n\n const effectiveCwd = anchorCommandCwd(cwd, serviceConfig);\n if (this.warnUnresolvedVars(processId, env, { cwd: effectiveCwd })) {\n this.consoleLogSource.addSystemLog(processId, `Cannot run command: unresolved variables (see above)`, 'error', { id: randomUUID(), type: 'command-fail', header: command, state: 'self' });\n return { exitCode: 1 };\n }\n\n this.consoleLogSource.addSystemLog(processId, `$ ${command}`, 'info');\n\n let runnerProcess;\n try {\n runnerProcess = this.launchOneOffCommand(proc, command, cwd, env);\n } catch (err: unknown) {\n this.consoleLogSource.addSystemLog(processId, `Failed to start: ${err instanceof Error ? err.message : String(err)}`, 'error', { id: randomUUID(), type: 'command-fail', header: command, state: 'self' });\n return { exitCode: 1 };\n }\n\n const cmdKey = `${processId}:${commandId ?? randomUUID()}`;\n this.activeAdHocCommands.set(cmdKey, runnerProcess);\n\n // Attach stdout/stderr to the same log stream as the parent process, with command's PID\n this.consoleLogSource.attach(processId, runnerProcess.stdout, runnerProcess.stderr, runnerProcess.pid ?? null);\n\n const { exitCode, signal, error } = await runnerProcess.exitPromise;\n this.activeAdHocCommands.delete(cmdKey);\n\n if (signal) {\n this.consoleLogSource.addSystemLog(processId, `command cancelled`, 'info');\n } else if (exitCode !== 0) {\n const errorMsg = error ? error : `exited with code ${exitCode}`;\n this.consoleLogSource.addSystemLog(processId, errorMsg, 'error', { id: randomUUID(), type: 'command-fail', header: command, state: 'self' });\n }\n\n return { exitCode };\n }\n\n /** Instantiate and start non-console log sources from serviceConfig.logSources */\n private async startAdditionalSources(processId: string, serviceConfig: ServiceConfig): Promise<void> {\n const configs = serviceConfig.logSources ?? [];\n if (configs.length === 0) return;\n\n const serviceEnv = resolveEnv(serviceConfig.env);\n const resolvedCwd = resolveCwd(serviceConfig.resolvedCwd ?? serviceConfig.cwd, serviceEnv);\n\n const jsParsers = (serviceConfig.resolvedLogParsers ?? []) as JSLogParserDef[];\n const logParser = new LogParser(jsParsers);\n const sources: ILogSource[] = configs.map((srcConfig) => {\n if (srcConfig.type === 'file') {\n const absPath = isAbsolute(srcConfig.path) ? srcConfig.path : join(resolvedCwd, srcConfig.path);\n return createLogSource({ ...srcConfig, path: absPath }, this.additionalBuffer, logParser);\n }\n return createLogSource(srcConfig, this.additionalBuffer, logParser);\n });\n\n for (const src of sources) {\n src.on('logs', (batch) => this.emit('logs', batch));\n try {\n await src.start(processId);\n } catch (err: unknown) {\n console.error('[process-manager] Failed to start log source', src.type, 'for', processId + ':', err instanceof Error ? err.message : String(err));\n }\n }\n\n this.additionalSources.set(processId, sources);\n }\n\n /** Stop and remove all non-console log sources for a process */\n private async stopAdditionalSources(processId: string): Promise<void> {\n const sources = this.additionalSources.get(processId);\n if (!sources) return;\n await Promise.allSettled(sources.map((s) => s.stop()));\n this.additionalSources.delete(processId);\n }\n\n /** Stop all command processes within a stored process */\n private async stopCommandProcesses(proc: StoredProcess): Promise<void> {\n const graceMs = env.GRACE_PERIOD;\n\n // Shared mode: kill the container first — that terminates all exec sessions inside it.\n // Then drain the exec exitPromises with a short timeout (they should resolve near-instantly).\n if (proc.sharedContainerProcess) {\n const sharedProc = proc.sharedContainerProcess;\n proc.sharedContainerProcess = null;\n sharedProc.kill('SIGTERM');\n await Promise.race([\n sharedProc.exitPromise,\n new Promise<void>((resolve) => setTimeout(resolve, graceMs)),\n ]);\n // Exec processes die when the container stops — drain them quickly\n const activeExecs = proc.commandProcesses.filter(cp => cp.runnerProcess);\n await Promise.all(\n activeExecs.map(async (cp) => {\n await Promise.race([\n cp.runnerProcess!.exitPromise,\n new Promise<void>((resolve) => setTimeout(resolve, 2000)),\n ]);\n cp.runnerProcess = null;\n })\n );\n return;\n }\n\n const activeProcesses = proc.commandProcesses.filter(cp => cp.runnerProcess);\n\n // Send SIGTERM to all\n for (const cp of activeProcesses) {\n cp.runnerProcess!.kill('SIGTERM');\n }\n\n // Wait for all to exit or force kill after grace period\n await Promise.all(\n activeProcesses.map(async (cp) => {\n const exited = await Promise.race([\n cp.runnerProcess!.exitPromise.then(() => true),\n new Promise<false>((resolve) => setTimeout(() => resolve(false), graceMs)),\n ]);\n\n if (!exited && cp.runnerProcess) {\n cp.runnerProcess.kill('SIGKILL');\n await cp.runnerProcess.exitPromise;\n }\n\n cp.runnerProcess = null;\n })\n );\n }\n\n /** Update aggregate state based on individual command process states */\n private updateAggregateState(processId: string): void {\n const proc = processStore.get(processId);\n if (!proc) return;\n\n const cps = proc.commandProcesses;\n const anyRunning = cps.some(cp => cp.runnerProcess !== null);\n const anyErrored = cps.some(cp => cp.exitCode !== null && cp.exitCode !== 0);\n const allDone = cps.every(cp => cp.runnerProcess === null);\n\n if (anyRunning) {\n // Still running — keep state as running\n return;\n }\n\n if (allDone) {\n // Shared mode: all execs finished naturally — kill the container too\n if (proc.sharedContainerProcess) {\n const sharedProc = proc.sharedContainerProcess;\n proc.sharedContainerProcess = null;\n sharedProc.kill('SIGTERM');\n }\n\n if (anyErrored) {\n proc.state = 'errored';\n proc.exitCode = 1;\n } else {\n proc.state = 'stopped';\n proc.exitCode = 0;\n }\n healthChecker.stopChecking(processId);\n this.metricsCollector.stopCollecting(processId);\n this.emitStatus(processId);\n this.handleAutoRestart(processId, proc);\n }\n }\n\n private handleAutoRestart(processId: string, current: StoredProcess): void {\n const strategy = current.serviceConfig.restartStrategy\n ?? (current.serviceConfig.autoRestart ? 'on-failure' : 'none');\n\n const shouldRestart = (() => {\n switch (strategy) {\n case 'on-failure':\n return current.state === 'errored';\n case 'always':\n return true;\n case 'unless-stopped':\n return !current.manuallyStopped;\n default:\n return false;\n }\n })();\n\n const maxRestarts = current.serviceConfig.maxRestarts;\n const hitMaxRestarts = maxRestarts !== undefined && maxRestarts !== null && current.restartCount >= maxRestarts;\n\n if (shouldRestart && !hitMaxRestarts) {\n current.restartCount++;\n // Exponential backoff: baseDelay * 2^(restartCount - 1), capped at 30s\n const baseDelay = current.serviceConfig.restartBackoffMs ?? 1000;\n const exponent = Math.min(current.restartCount - 1, 20);\n const delay = Math.min(baseDelay * Math.pow(2, exponent), 30_000);\n this.consoleLogSource.addSystemLog(\n processId,\n `Auto-restarting in ${delay}ms (attempt ${current.restartCount}${maxRestarts ? `/${maxRestarts}` : ''}, strategy: ${strategy})`,\n 'warn'\n );\n setTimeout(() => {\n if (processStore.has(processId)) {\n this.start(processId).catch((err) => {\n console.error('[process-manager] Auto-restart failed for', processId, ':', err.message);\n });\n }\n }, delay);\n } else if (shouldRestart && hitMaxRestarts) {\n this.consoleLogSource.addSystemLog(\n processId,\n `Max restarts reached (${maxRestarts}). Not restarting.`,\n 'error'\n );\n }\n }\n\n private toProcessStatus(proc: StoredProcess): ProcessStatus {\n const uptime = proc.startedAt && proc.state === 'running'\n ? Date.now() - proc.startedAt.getTime()\n : 0;\n const healthStatus = healthChecker.getHealthStatus(proc.id);\n const pids = proc.commandProcesses\n .map(cp => cp.pid)\n .filter((pid): pid is number => pid !== null);\n return {\n id: proc.id,\n serviceId: proc.serviceConfig.id,\n agentId: env.AGENT_ID ?? 'local',\n state: proc.state,\n pid: pids[0] ?? null,\n pids,\n exitCode: proc.exitCode,\n startedAt: proc.startedAt,\n restartCount: proc.restartCount,\n uptime,\n healthStatus,\n cwd: effectiveProcessCwd(proc.serviceConfig),\n };\n }\n\n private emitStatus(processId: string): void {\n const status = this.getStatus(processId);\n if (status) {\n this.emit('status', status);\n if (traefikManager.isEnabled()) {\n traefikManager.scheduleDynamicRegen();\n }\n }\n }\n}\n\n// Singleton instance\nexport const processManager = new ProcessManager();\n","import { z } from 'zod';\n\nexport const UserSchema = z.object({\n id: z.string().max(128),\n email: z.string().email().max(320),\n name: z.string().min(1).max(500),\n avatar: z.string().url().max(2048).nullable().optional(),\n});\n\nexport type User = z.infer<typeof UserSchema>;\n","import { z } from 'zod';\n\nexport const OrgSchema = z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(100),\n slug: z.string().min(1).max(100).regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/),\n ownerId: z.string().max(128),\n});\n\nexport type Org = z.infer<typeof OrgSchema>;\n\nexport const OrgMemberSchema = z.object({\n id: z.string().max(128),\n orgId: z.string().max(128),\n userId: z.string().max(128),\n globalRole: z.enum(['owner', 'admin', 'member']),\n invitedAt: z.coerce.date(),\n joinedAt: z.coerce.date().nullable().optional(),\n});\n\nexport type OrgMember = z.infer<typeof OrgMemberSchema>;\n","import { z } from 'zod';\n\nexport const ProjectSchema = z.object({\n id: z.string().max(128),\n orgId: z.string().max(128).nullable().optional(),\n name: z.string().min(1).max(200),\n description: z.string().max(10000).optional().default(''),\n serviceIds: z.array(z.string().max(128)).max(10000).default([]),\n\n // Environment support\n // NOTE: activeEnvironmentId is runtime-only (not persisted to JSON)\n // It's initialized to 'local' by default at load time\n activeEnvironmentId: z.string().max(128).optional(),\n environmentIds: z.array(z.string().max(128)).max(100).default([]),\n\n // Ordre d'affichage des groupes de services dans la sidebar (noms de groupes).\n // Les groupes absents de cette liste sont affichés après, par ordre alphabétique.\n groupOrder: z.array(z.string().max(200)).max(100).default([]),\n});\n\nexport type Project = z.infer<typeof ProjectSchema>;\n\nexport const CreateProjectSchema = ProjectSchema.omit({ id: true }).partial().required({ name: true });\nexport type CreateProject = z.infer<typeof CreateProjectSchema>;\n\nexport const UpdateProjectSchema = ProjectSchema.partial().required({ id: true });\nexport type UpdateProject = z.infer<typeof UpdateProjectSchema>;\n","import { z } from 'zod';\nimport { JSLogParserSchema } from './settings.schema.js';\nimport { LogSourceConfigSchema } from './log-source.schema.js';\n\nexport const HealthCheckSchema = z.object({\n type: z.enum(['http', 'command']).default('http'),\n // HTTP-specific (required when type=http)\n path: z.string().min(1).max(500).startsWith('/').optional(),\n method: z.enum(['GET', 'HEAD', 'POST', 'PUT']).optional().default('GET'),\n expectedStatus: z.number().int().min(100).max(599).optional().default(200),\n // Command-specific (required when type=command)\n command: z.string().min(1).max(4096).optional(),\n // Shared\n interval: z.number().int().positive().default(1000),\n timeout: z.number().int().positive().default(1000),\n retries: z.number().int().nonnegative().default(3),\n initialDelay: z.number().int().nonnegative().optional().default(0),\n}).refine(\n (data) => data.type === 'http' ? !!data.path : !!data.command,\n { message: 'HTTP type requires path; command type requires command' },\n);\n\nexport type HealthCheck = z.infer<typeof HealthCheckSchema>;\n\nexport const BootstrapCommandSchema = z.object({\n id: z.string().min(1).max(64),\n label: z.string().max(200).default(''),\n entrypoint: z.string().max(4096).optional(),\n command: z.string().max(4096).default(''),\n user: z.string().max(256).optional(),\n});\n\nexport type BootstrapCommand = z.infer<typeof BootstrapCommandSchema>;\n\nexport const DockerConfigSchema = z.object({\n // Image mode (pull from registry) — mutually exclusive with build mode in UI\n image: z.string().min(1).max(1024).optional(),\n\n // Build mode — Dockerfile stored inline in services.json\n dockerfile: z.string().max(65536).optional(),\n buildContext: z.string().max(4096).optional(),\n buildArgs: z.record(z.string().max(256), z.string().max(4096)).default({}).refine(\n (obj) => Object.keys(obj).length <= 50,\n { message: 'Max 50 build args' },\n ),\n targetStage: z.string().max(256).optional(),\n\n // Runtime config\n networkMode: z.enum(['host', 'bridge']).default('host'),\n ports: z.array(z.string().max(64)).max(100).default([]),\n volumes: z.array(z.string().max(1024)).max(100).default([]),\n mountRootpath: z.boolean().default(false),\n entrypoint: z.string().max(4096).optional(),\n command: z.string().max(4096).optional(),\n user: z.string().max(256).optional(),\n useNativeCommand: z.boolean().default(false),\n nativeCommandMode: z.enum(['shared', 'isolated']).default('isolated'),\n nativeShell: z.string().max(256).default('sh'),\n bootstrapCommands: z.array(BootstrapCommandSchema).max(20).default([]),\n});\n\nexport type DockerConfig = z.infer<typeof DockerConfigSchema>;\n\nexport const RestartStrategySchema = z.enum(['none', 'on-failure', 'always', 'unless-stopped']).default('none');\nexport type RestartStrategy = z.infer<typeof RestartStrategySchema>;\n\nexport const ServiceShortcutSchema = z.object({\n id: z.string().min(1).max(64),\n label: z.string().max(200).default(''),\n command: z.string().max(4096).default(''),\n cwd: z.string().max(4096).optional(),\n});\n\nexport type ServiceShortcut = z.infer<typeof ServiceShortcutSchema>;\n\nexport const ServiceCommandSchema = z.object({\n id: z.string().min(1).max(64),\n label: z.string().max(200).default(''),\n command: z.string().max(4096).default(''),\n cwd: z.string().max(4096).optional(),\n shell: z.boolean().optional().default(true),\n});\n\nexport type ServiceCommand = z.infer<typeof ServiceCommandSchema>;\n\n// --- Variable Slot Schema ---\n// A VariableSlot represents a single value with optional pre/post concatenation.\n// The final resolved value is: pre + interpolate(value) + post\nexport const VariableSlotSchema = z.object({\n value: z.string().max(8192).default(''),\n pre: z.string().max(8192).default(''),\n post: z.string().max(8192).default(''),\n isSecret: z.boolean().default(false),\n // Deux décisions distinctes, et il ne faut pas les confondre :\n //\n // - `shareWithAi` est une permission de **lecture** : une IA (le chat de\n // Runeya, un agent par le serveur MCP) peut voir la valeur de ce secret.\n // Une variable publique est lisible de toute façon, le drapeau ne la\n // concerne pas.\n // - `injectIntoAi` est une **exécution** : la variable est posée dans\n // l'environnement du process des agents (Claude Code, Codex, …) lancés\n // depuis Runeya pendant que cet environnement est actif.\n //\n // Les deux sont opt-in : sans rien cocher, aucun secret ne part vers une IA.\n // Injecter implique lire (ce que le process reçoit, l'agent le voit), donc\n // la lecture accepte l'un OU l'autre : voir `isSharedWithAi`, qui est le seul\n // endroit où cette règle s'écrit.\n shareWithAi: z.boolean().default(false),\n injectIntoAi: z.boolean().default(false),\n // Une variable obligatoire doit avoir une valeur finale non vide avant qu'un\n // service de cet environnement puisse démarrer. Le démarrage est refusé\n // sinon, avec la liste des manquantes — l'assistant est le moyen de remplir.\n required: z.boolean().default(false),\n // Une variable « seulement surchargeable » n'a jamais de valeur partagée :\n // `value` reste vide dans le document synchronisé, et chaque poste DOIT\n // fournir sa propre surcharge machine-locale (chemin local, jeton personnel).\n // `pre` et `post` restent partagés — ils décrivent la forme, pas le secret.\n overrideOnly: z.boolean().default(false),\n // À quoi sert cette variable, pour quelqu'un qui doit la remplir. Affichée\n // par l'assistant de complétion et dans l'éditeur.\n //\n // Du **markdown**, pas du texte brut : une description gagne à pouvoir\n // pointer vers la console qui délivre le jeton. Écrite et relue par le même\n // éditeur Tiptap (`packages/editor-ui`), jamais injectée en HTML — Tiptap\n // analyse le markdown dans son propre schéma, si bien qu'une description\n // arrivée d'un autre poste par la synchronisation ne peut rien exécuter.\n description: z.string().max(2000).default(''),\n}).refine(\n (slot) => !slot.overrideOnly || slot.value === '',\n { message: 'An override-only variable cannot carry a shared value', path: ['value'] },\n);\n\nexport type VariableSlot = z.infer<typeof VariableSlotSchema>;\n\n/**\n * Son auteur a-t-il partagé cette variable avec les IA ?\n *\n * Deux cases mènent au même oui : `shareWithAi`, le partage en lecture, et\n * `injectIntoAi`, car une variable posée dans l'environnement du process d'un\n * agent est de fait lisible par lui — la lui refuser à la lecture tout en la\n * lui passant ne protégerait rien et rendrait l'interface menteuse.\n *\n * Le seul endroit où cette règle s'écrit. Deux précautions d'emploi :\n *\n * - Le drapeau ne décide que du sort des **secrets**. Une variable publique est\n * lisible de toute façon, et savoir laquelle est secrète n'est pas affaire de\n * définition : une variable non marquée qui référence un secret le devient à\n * la résolution. C'est donc au filtre de croiser les deux.\n * - Il se lit sur la **définition**, jamais sur un slot de surcharge : une\n * surcharge remplace le slot entier et n'en porte aucun drapeau (même piège\n * que `findMissingVariables`).\n */\nexport function isSharedWithAi(slot: Pick<VariableSlot, 'shareWithAi' | 'injectIntoAi'>): boolean {\n return slot.shareWithAi || slot.injectIntoAi;\n}\n\n/** Pourquoi une variable est réclamée par l'assistant de complétion. */\nexport const MissingVariableReasonSchema = z.enum(['required', 'overrideOnly']);\nexport type MissingVariableReason = z.infer<typeof MissingVariableReasonSchema>;\n\n/** Une variable qu'il faut remplir avant de démarrer. */\nexport const MissingVariableSchema = z.object({\n variableId: z.string().max(128),\n key: z.string().max(256),\n description: z.string().max(2000),\n reason: MissingVariableReasonSchema,\n isSecret: z.boolean(),\n environmentId: z.string().max(128),\n environmentName: z.string().max(200),\n});\n\nexport type MissingVariable = z.infer<typeof MissingVariableSchema>;\n\n// A Variable has a key (env var name) and a value slot.\nexport const VariableSchema = z.object({\n key: z.string().min(1).max(256),\n value: VariableSlotSchema,\n});\n\nexport type Variable = z.infer<typeof VariableSchema>;\n\n// Record of variableId → Variable. Max 200 entries.\n// The key is a unique variable ID (UUID), the Variable contains the env var name in `key`.\nexport const VariablesRecordSchema = z.record(\n z.string().max(128),\n VariableSchema,\n).refine(\n (obj) => Object.keys(obj).length <= 200,\n { message: 'Max 200 variables' },\n);\n\nexport type VariablesRecord = z.infer<typeof VariablesRecordSchema>;\n\n// Record of variable name → VariableSlot (used on disk for base values and overrides separately)\nexport const VariableSlotsRecordSchema = z.record(\n z.string().max(256),\n VariableSlotSchema,\n).refine(\n (obj) => Object.keys(obj).length <= 200,\n { message: 'Max 200 variable slots' },\n);\n\nexport type VariableSlotsRecord = z.infer<typeof VariableSlotsRecordSchema>;\n\nexport const ServiceConfigSchema = z.object({\n id: z.string().max(128),\n orgId: z.string().max(128).nullable().optional(),\n agentId: z.string().max(128).optional(), // Optional: if absent, inherited from active environment's agentId\n name: z.string().min(1).max(200),\n commands: z.array(ServiceCommandSchema).max(50).optional().default([]),\n cwd: z.string().max(4096).optional(),\n ports: z.array(z.number().int().positive().max(65535)).max(20).optional().default([]),\n\n // Metadata fields (migration from old Runeya)\n groups: z.array(z.string().max(200)).max(20).optional().default([]),\n description: z.string().max(2000).optional(),\n /** Path (relative to service.cwd or absolute) where the service's docs/wiki markdown files live. Optional — defaults to service.cwd. */\n docsPath: z.string().max(4096).optional(),\n url: z.string().max(2048).optional(),\n localUrls: z.array(z.object({\n url: z.string().max(253).regex(/^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,}$/),\n port: z.number().int().min(1).max(65535),\n })).max(20).optional().default([]),\n openapiUrl: z.string().max(2048).optional(),\n git: z.object({\n remote: z.string().max(2048).optional(),\n home: z.string().max(2048).optional(),\n }).optional(),\n meta: z.record(z.string().max(256), z.string().max(2000)).optional()\n .refine((obj) => !obj || Object.keys(obj).length <= 100, { message: 'Too many meta keys (max 100)' }),\n\n // Transient env dict (resolved by server before deployment, used directly by agent runner — NOT persisted)\n env: z.record(z.string().max(256), z.string().max(8192)).default({}).refine(\n (obj) => Object.keys(obj).length <= 200,\n { message: 'Too many env vars (max 200)' },\n ),\n envSecrets: z.array(z.string().max(256)).max(200).default([]),\n\n // Transient: resolved JS log parsers (from parserIds, resolved by server before deployment — NOT persisted)\n resolvedLogParsers: z.array(JSLogParserSchema).default([]).optional(),\n\n // Transient: resolved working directory (cwd with env vars expanded — NOT persisted)\n resolvedCwd: z.string().optional(),\n\n runner: z.enum(['native', 'docker']).optional().default('native'),\n dockerConfig: DockerConfigSchema.optional(),\n healthCheck: HealthCheckSchema.optional(),\n parserIds: z.array(z.string().max(128)).max(50).default([]),\n shortcuts: z.array(ServiceShortcutSchema).max(50).optional().default([]),\n autoRestart: z.boolean().optional().default(false),\n clearLogsOnStart: z.boolean().optional().default(false),\n restartStrategy: RestartStrategySchema.optional(),\n maxRestarts: z.number().int().nonnegative().optional(),\n restartBackoffMs: z.number().int().positive().optional().default(1000),\n\n // Log sources additionnelles (au-delà du stdout/stderr console par défaut)\n logSources: z.array(LogSourceConfigSchema).max(20).optional().default([]),\n});\n\nexport type ServiceConfig = z.infer<typeof ServiceConfigSchema>;\n\nexport const CreateServiceSchema = ServiceConfigSchema.omit({ id: true }).partial().required({ name: true });\nexport type CreateService = z.infer<typeof CreateServiceSchema>;\n\nexport const UpdateServiceSchema = ServiceConfigSchema.partial().required({ id: true }).extend({\n agentId: z.string().max(128).nullable().optional(), // null = clear (inherit from env), undefined = no change\n cwd: z.string().max(4096).nullable().optional(),\n git: z.object({ remote: z.string().max(2048).optional(), home: z.string().max(2048).optional() }).nullable().optional(),\n meta: z.record(z.string().max(256), z.string().max(2000)).nullable().optional()\n .refine((obj) => !obj || Object.keys(obj).length <= 100, { message: 'Too many meta keys (max 100)' }),\n healthCheck: HealthCheckSchema.nullable().optional(),\n});\nexport type UpdateService = z.infer<typeof UpdateServiceSchema>;\n","import { z } from 'zod';\nimport { ScenarioSchema } from './scenario.schema.js';\n\nexport const AI_PROVIDERS = ['anthropic', 'openai', 'mistral', 'groq', 'ollama'] as const;\nexport type AIProviderType = (typeof AI_PROVIDERS)[number];\n\nexport const AIProviderSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n provider: z.enum(AI_PROVIDERS),\n encryptedApiKey: z.string().max(2000).default(''),\n model: z.string().max(200).optional(),\n active: z.boolean().default(false),\n createdAt: z.coerce.date(),\n updatedAt: z.coerce.date(),\n});\n\nexport type AIProvider = z.infer<typeof AIProviderSchema>;\n\nexport const JSLogParserSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n description: z.string().max(2000).optional(),\n code: z.string().min(1).max(50000).refine(\n (s) => !s.includes('require(') && !s.includes('import ') && !s.includes('eval('),\n { message: 'Code must not contain require, import, or eval patterns' }\n ),\n enabled: z.boolean().default(true),\n builtin: z.boolean().optional(),\n createdAt: z.coerce.date(),\n updatedAt: z.coerce.date(),\n});\n\nexport type JSLogParser = z.infer<typeof JSLogParserSchema>;\n\nexport const NOTIFICATION_CATEGORIES = [\n 'scenario_waiting_input',\n 'ai_conversation_complete',\n 'ai_conversation_error',\n 'service_error_log',\n 'service_status_changed',\n 'service_health_changed',\n] as const;\nexport type NotificationCategory = (typeof NOTIFICATION_CATEGORIES)[number];\n\nexport const NotificationPreferencesSchema = z.object({\n scenario_waiting_input: z.boolean().default(true),\n ai_conversation_complete: z.boolean().default(true),\n ai_conversation_error: z.boolean().default(true),\n service_error_log: z.boolean().default(true),\n service_status_changed: z.boolean().default(true),\n service_health_changed: z.boolean().default(true),\n /** Service IDs excluded from error-log notifications */\n service_error_log_excluded: z.array(z.string().max(100)).max(500).default([]),\n /** Service IDs excluded from status-change notifications */\n service_status_changed_excluded: z.array(z.string().max(100)).max(500).default([]),\n /** Service IDs excluded from health-change notifications */\n service_health_changed_excluded: z.array(z.string().max(100)).max(500).default([]),\n});\nexport type NotificationPreferences = z.infer<typeof NotificationPreferencesSchema>;\n\n/**\n * Réglages du compagnon de relecture.\n *\n * Au niveau du POSTE, en clair, et non dans le coffre d'une organisation (§9) :\n * ce n'est pas un réglage d'équipe. Il décrit comment cette machine fait\n * travailler ses agents, il ne contient aucun secret, et le ranger dans un\n * coffre chiffré le rendrait dépendant de l'organisation qu'on regarde — un\n * même poste aurait autant de compagnons que d'organisations, sans raison.\n */\nexport const CompanionSettingsSchema = z.object({\n /** Activer le compagnon d'office sur les conversations créées ensuite. */\n enabledByDefault: z.boolean().default(false),\n /**\n * Spécificités ajoutées aux consignes Runeya.\n *\n * Vide — l'absence — signifie « aucune spécificité ». On ne recopie pas le\n * texte par défaut dans le réglage : les consignes Runeya restent dans le\n * code, pour profiter de leurs corrections.\n *\n * Rejeté au-delà de la borne plutôt que tronqué (§1) : un prompt coupé en\n * plein milieu produirait des relectures incohérentes sans rien signaler.\n */\n prompt: z.string().max(20_000).optional(),\n});\n\nexport type CompanionSettings = z.infer<typeof CompanionSettingsSchema>;\n\nexport const SettingsSchema = z.object({\n mode: z.enum(['local-simple', 'cloud']),\n cloudUrl: z.string().url().max(2048).nullable().optional(),\n logParsers: z.array(JSLogParserSchema).max(100).default([]),\n scenarios: z.array(ScenarioSchema).max(100).default([]),\n /** Absolute path to the folder where the global wiki/docs markdown files live. Optional. */\n globalDocsPath: z.string().max(4096).optional(),\n /**\n * Optionnel plutôt que défauté : un réglage absent est un réglage jamais\n * touché, et le rendre obligatoire dans le type forcerait chaque appelant qui\n * construit un objet de réglages à inventer une valeur.\n */\n companion: CompanionSettingsSchema.optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n\n\nexport const TraefikConfigSchema = z.object({\n enabled: z.boolean().default(false),\n acmeEmail: z.string().email().max(256).optional(),\n wildcardDomain: z.string().max(253).optional(),\n httpPort: z.number().int().min(1).max(65535).default(80),\n httpsPort: z.number().int().min(1).max(65535).default(443),\n dnsProvider: z.string().max(64).optional(),\n dnsCredentials: z.record(z.string().max(64), z.string().max(2048)).default({}),\n acmeStaging: z.boolean().default(false),\n encryptedCert: z.string().max(65536).optional(),\n encryptedCertKey: z.string().max(65536).optional(),\n});\n\nexport type TraefikConfig = z.infer<typeof TraefikConfigSchema>;\n\n\nexport const SettingsPrivateSchema = z.object({\n aiProviders: z.array(AIProviderSchema).max(50).default([]),\n scenarios: z.array(ScenarioSchema).max(100).default([]),\n notifications: NotificationPreferencesSchema.default(() => ({\n scenario_waiting_input: true,\n ai_conversation_complete: true,\n ai_conversation_error: true,\n service_error_log: true,\n service_status_changed: true,\n service_health_changed: true,\n service_error_log_excluded: [],\n service_status_changed_excluded: [],\n service_health_changed_excluded: [],\n })),\n traefikConfig: TraefikConfigSchema.optional(),\n});\n\nexport type SettingsPrivate = z.infer<typeof SettingsPrivateSchema>;\n\nexport const SchemaVersionSchema = z.object({\n version: z.number().int().positive(),\n migratedAt: z.coerce.date(),\n});\n\nexport type SchemaVersion = z.infer<typeof SchemaVersionSchema>;\n","import { z } from 'zod';\n\nconst PositionSchema = z.object({\n x: z.number(),\n y: z.number(),\n});\n\nexport const ScenarioGroupSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n description: z.string().max(1000).optional(),\n color: z.string().max(32).optional(),\n position: PositionSchema.default({ x: 0, y: 0 }),\n width: z.number().default(300),\n height: z.number().default(200),\n});\n\nexport type ScenarioGroup = z.infer<typeof ScenarioGroupSchema>;\n\nexport const SCENARIO_ROLES = [\n 'manager',\n 'engineer',\n 'designer',\n 'analyst',\n 'qa',\n 'devops',\n 'product',\n 'writer',\n 'researcher',\n 'other',\n] as const;\n\nexport type ScenarioRole = typeof SCENARIO_ROLES[number];\n\n// --- Presets ---\n\nexport const ScenarioPresetRoleSchema = z.object({\n id: z.string().min(1).max(64),\n name: z.string().min(1).max(200),\n systemPrompt: z.string().max(10_000).default(''),\n prompt: z.string().max(10_000).default(''),\n});\n\nexport type ScenarioPresetRole = z.infer<typeof ScenarioPresetRoleSchema>;\n\nexport const ScenarioPresetInitialDataSchema = z.object({\n leaderId: z.string().min(1).max(128),\n groups: z.array(z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n description: z.string().max(1000).optional(),\n color: z.string().max(32).optional(),\n position: z.object({ x: z.number(), y: z.number() }).default({ x: 0, y: 0 }),\n width: z.number().default(300),\n height: z.number().default(200),\n })).max(100).default([]),\n nodes: z.array(z.object({\n id: z.string().min(1).max(128),\n type: z.enum(['ai', 'ask']).default('ai'),\n parentIds: z.array(z.string().max(128)).default([]),\n groupId: z.string().max(128).nullable().default(null),\n label: z.string().max(240).default(''),\n role: z.string().max(64).default('other'),\n prompt: z.string().max(50_000).default(''),\n question: z.string().max(2_000).default(''),\n autoGenerated: z.boolean().default(true),\n canAddNode: z.boolean().default(false),\n aiCli: z.enum(['claude-code', 'codex']).default('claude-code'),\n model: z.string().max(128).default('sonnet'),\n position: z.object({ x: z.number(), y: z.number() }).default({ x: 0, y: 0 }),\n })).min(1).max(500),\n});\n\nexport type ScenarioPresetInitialData = z.infer<typeof ScenarioPresetInitialDataSchema>;\n\nconst LocalizedStringSchema = z.record(z.string(), z.string().max(100));\n\nexport const ScenarioPresetLabelsSchema = z.object({\n group: LocalizedStringSchema.optional(),\n node: LocalizedStringSchema.optional(),\n role: LocalizedStringSchema.optional(),\n leader: LocalizedStringSchema.optional(),\n});\n\nexport type ScenarioPresetLabels = z.infer<typeof ScenarioPresetLabelsSchema>;\n\nexport const ScenarioPresetSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n icon: z.string().max(64).optional(),\n defaultTraversalMode: z.enum(['hierarchical', 'topological']).optional(),\n canChangeTraversalMode: z.boolean().default(true),\n roles: z.array(ScenarioPresetRoleSchema).min(1).max(100),\n initialData: ScenarioPresetInitialDataSchema.optional(),\n labels: ScenarioPresetLabelsSchema.optional(),\n});\n\nexport type ScenarioPreset = z.infer<typeof ScenarioPresetSchema>;\n\n// --- Node ---\n\nexport const ScenarioNodeSchema = z.object({\n id: z.string().min(1).max(128),\n type: z.enum(['ai', 'ask']).default('ai'),\n parentIds: z.array(z.string().max(128)).default([]),\n groupId: z.string().max(128).nullable().default(null),\n label: z.string().max(240).default(''),\n role: z.string().max(64).default('other'),\n prompt: z.string().max(50_000).default(''),\n question: z.string().max(2_000).default(''),\n autoGenerated: z.boolean().default(true),\n canAddNode: z.boolean().default(false),\n aiCli: z.enum(['claude-code', 'codex']).default('claude-code'),\n model: z.string().max(128).default('sonnet'),\n position: PositionSchema.default({ x: 0, y: 0 }),\n injectParentOutputs: z.boolean().default(false),\n injectedAncestorIds: z.array(z.string().max(128)).default([]),\n});\n\nexport type ScenarioNode = z.infer<typeof ScenarioNodeSchema>;\n\nexport const ScenarioSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n icon: z.string().max(64).optional(),\n description: z.string().max(2000).optional(),\n leaderId: z.string().min(1).max(128),\n groups: z.array(ScenarioGroupSchema).max(100).default([]),\n nodes: z.array(ScenarioNodeSchema).min(1).max(500),\n traversalMode: z.enum(['hierarchical', 'topological']).default('hierarchical'),\n presetId: z.string().max(128).optional(),\n isPublished: z.boolean().default(false),\n createdAt: z.number(),\n updatedAt: z.number(),\n});\n\nexport type Scenario = z.infer<typeof ScenarioSchema>;\n","import { z } from 'zod';\n\nconst safePath = z\n .string()\n .min(1)\n .max(4096)\n .refine(\n (p) => !p.includes('\\0'),\n { message: 'path must not contain null bytes' },\n )\n .refine(\n (p) => !/(^|[/\\\\])\\.\\.([/\\\\]|$)/.test(p),\n { message: 'path must not contain path-traversal sequences (..)' },\n )\n;\n\nexport const ConsoleLogSourceSchema = z.object({\n type: z.literal('console'),\n});\nexport type ConsoleLogSource = z.infer<typeof ConsoleLogSourceSchema>;\n\nexport const FileLogSourceSchema = z.object({\n type: z.literal('file'),\n path: safePath,\n encoding: z.string().max(32).default('utf-8'),\n startFromEnd: z.boolean().default(true),\n createIfNotExists: z.boolean().default(false),\n});\nexport type FileLogSource = z.infer<typeof FileLogSourceSchema>;\n\nexport const MongoLogSourceSchema = z.object({\n type: z.literal('mongo'),\n /** @sensitive — stored encrypted (AES-256-GCM) on disk */\n connectionString: z.string().min(1).max(2048),\n database: z.string().min(1).max(256),\n collection: z.string().min(1).max(256),\n filter: z.record(z.string(), z.unknown()).optional(),\n timestampField: z.string().max(128).default('timestamp'),\n messageField: z.string().max(128).default('message'),\n levelField: z.string().max(128).optional(),\n});\nexport type MongoLogSource = z.infer<typeof MongoLogSourceSchema>;\n\nexport const MySQLLogSourceSchema = z.object({\n type: z.literal('mysql'),\n host: z.string().min(1).max(253),\n port: z.number().int().min(1).max(65535).default(3306),\n user: z.string().min(1).max(256),\n /** @sensitive — stored encrypted (AES-256-GCM) on disk */\n password: z.string().max(2048),\n database: z.string().min(1).max(256),\n table: z.string().min(1).max(256),\n query: z.string().max(8192).optional(),\n timestampColumn: z.string().max(128).default('created_at'),\n messageColumn: z.string().max(128).default('message'),\n levelColumn: z.string().max(128).optional(),\n pollIntervalMs: z.number().int().min(500).max(60000).default(2000),\n});\nexport type MySQLLogSource = z.infer<typeof MySQLLogSourceSchema>;\n\nexport const LogSourceConfigSchema = z.discriminatedUnion('type', [\n ConsoleLogSourceSchema,\n FileLogSourceSchema,\n MongoLogSourceSchema,\n MySQLLogSourceSchema,\n]);\nexport type LogSourceConfig = z.infer<typeof LogSourceConfigSchema>;\nexport type LogSourceType = LogSourceConfig['type'];\n","import { z } from 'zod';\n\nexport const ProcessStateSchema = z.enum(['starting', 'running', 'stopped', 'errored']);\nexport type ProcessState = z.infer<typeof ProcessStateSchema>;\n\nexport const HealthStatusSchema = z.enum(['healthy', 'unhealthy', 'unknown']);\nexport type HealthStatus = z.infer<typeof HealthStatusSchema>;\n\nexport const ProcessStatusSchema = z.object({\n id: z.string().max(128),\n serviceId: z.string().max(128),\n agentId: z.string().max(128),\n state: ProcessStateSchema,\n pid: z.number().int().nullable().optional(),\n pids: z.array(z.number().int()).optional().default([]),\n exitCode: z.number().int().nullable().optional(),\n startedAt: z.coerce.date().nullable().optional(),\n restartCount: z.number().int().nonnegative().default(0),\n uptime: z.number().nonnegative().default(0),\n healthStatus: HealthStatusSchema.default('unknown'),\n /**\n * Le répertoire où le processus s'exécute VRAIMENT, absolutisé par l'agent.\n *\n * Rapporté par l'agent plutôt que déduit de la config : entre le `cwd` de la\n * commande, celui du service, l'ancrage sur le projet et les variables que\n * l'agent étend lui-même, la valeur affichée n'aurait rien prouvé. Ce qui\n * intéresse quand un service tourne contre le mauvais dépôt, c'est le chemin\n * final — y compris quand il retombe sur le répertoire de l'agent.\n */\n cwd: z.string().max(4096).nullable().optional(),\n});\n\nexport type ProcessStatus = z.infer<typeof ProcessStatusSchema>;\n","import { z } from 'zod';\n\nexport const LogLevelSchema = z.enum(['debug', 'info', 'warn', 'error', 'fatal']);\nexport type LogLevel = z.infer<typeof LogLevelSchema>;\n\nexport const LogLineSchema = z.object({\n /** Raw log line as received from the process (immutable context) */\n raw: z.string(),\n /** Source stream (immutable context) */\n stream: z.enum(['stdout', 'stderr']),\n /** Severity level */\n level: LogLevelSchema,\n /** Parsed/enriched message to display */\n message: z.string(),\n /** When true, the line is hidden from the log view */\n hidden: z.boolean(),\n /** Arbitrary key/value pairs shown in the detail panel */\n metadata: z.record(z.string().max(256), z.unknown()).refine(\n (obj) => Object.keys(obj).length <= 100,\n { message: 'Too many metadata keys (max 100)' },\n ),\n /** Full parsed JSON object when the line is JSON */\n json: z.record(z.string(), z.unknown()).optional(),\n /** Custom header for the JSON log card (supports HTML, sanitized before display) */\n jsonHeader: z.string().max(256).optional(),\n});\n\nexport type LogLine = z.infer<typeof LogLineSchema>;\n\nexport const LogCardDirectiveSchema = z.object({\n id: z.string().max(128),\n type: z.string().max(64),\n header: z.string().max(256),\n collapsable: z.boolean().optional(),\n collapsed: z.boolean().optional(),\n state: z.enum(['open', 'append', 'close', 'self']),\n});\nexport type LogCardDirective = z.infer<typeof LogCardDirectiveSchema>;\n\nexport const ParsedLogSchema = z.object({\n id: z.string().max(128),\n processId: z.string().max(128),\n pid: z.number().int().nullable().optional(),\n timestamp: z.coerce.date(),\n level: LogLevelSchema.default('info'),\n message: z.string().max(16384),\n raw: z.string().max(16384),\n stream: z.enum(['stdout', 'stderr']).default('stdout'),\n hidden: z.boolean().optional().default(false),\n metadata: z.record(z.string().max(256), z.unknown()).optional().refine(\n (obj) => !obj || Object.keys(obj).length <= 100,\n { message: 'Too many metadata keys (max 100)' },\n ),\n json: z.record(z.string(), z.unknown()).optional(),\n logCard: LogCardDirectiveSchema.optional(),\n sourceType: z.enum(['console', 'file', 'mongo', 'mysql']).optional(),\n sourcePath: z.string().max(4096).optional(),\n});\n\nexport type ParsedLog = z.infer<typeof ParsedLogSchema>;\n","import { z } from 'zod';\n\n/** Regex for valid POSIX environment variable names */\nexport const ENV_VAR_NAME_REGEX = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport const AgentConfigSchema = z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(100),\n url: z.string().url().max(2048),\n passphrase: z.string().min(1).max(1024),\n passthroughEnv: z.array(\n z.string().regex(ENV_VAR_NAME_REGEX).max(256),\n ).max(100).default([]),\n});\n\nexport type AgentConfig = z.infer<typeof AgentConfigSchema>;\n\nexport const AgentStatusSchema = z.object({\n connected: z.boolean(),\n lastSeen: z.string().nullable().optional(),\n uptime: z.number().nonnegative().default(0),\n runnersAvailable: z.array(z.enum(['native', 'docker'])).default(['native']),\n lanIp: z.string().optional(),\n /**\n * Ce que la machine de l'agent vaut pour les builtins de portée `agent`.\n * Sert à PRÉVISUALISER — la valeur injectée reste calculée au lancement, par\n * l'agent lui-même : une IP change, un agent se déconnecte, et un statut\n * n'est qu'un cliché.\n */\n os: z.string().max(64).optional(),\n home: z.string().max(4096).optional(),\n cwd: z.string().max(4096).optional(),\n});\n\nexport type AgentStatus = z.infer<typeof AgentStatusSchema>;\n","import { z } from 'zod';\n\nexport const GlobalRoleSchema = z.enum(['owner', 'admin', 'member']);\nexport type GlobalRole = z.infer<typeof GlobalRoleSchema>;\n\nexport const ProjectRoleSchema = z.enum(['admin', 'editor', 'viewer']);\nexport type ProjectRole = z.infer<typeof ProjectRoleSchema>;\n\nexport const ProjectMemberRoleSchema = z.object({\n id: z.string().max(128),\n projectId: z.string().max(128),\n userId: z.string().max(128),\n role: ProjectRoleSchema,\n});\n\nexport type ProjectMemberRole = z.infer<typeof ProjectMemberRoleSchema>;\n","import { z } from 'zod';\n\nexport const ConfigVersionSchema = z.object({\n id: z.string().max(128),\n entityType: z.enum(['project', 'service']),\n entityId: z.string().max(128),\n version: z.string().max(128),\n parentVersion: z.string().max(128),\n data: z.record(z.string(), z.unknown()).refine(\n (obj) => Object.keys(obj).length <= 1000,\n 'Too many data keys (max 1000)',\n ),\n patch: z.array(z.record(z.string(), z.unknown())).max(1000),\n userId: z.string().max(128),\n timestamp: z.coerce.date(),\n resolved: z.boolean().default(false),\n});\n\nexport type ConfigVersion = z.infer<typeof ConfigVersionSchema>;\n\nexport const ConfigChangeSchema = z.object({\n entityType: z.enum(['project', 'service']),\n entityId: z.string().max(128),\n version: z.string().max(128),\n parentVersion: z.string().max(128),\n data: z.record(z.string(), z.unknown()).refine(\n (obj) => Object.keys(obj).length <= 1000,\n 'Too many data keys (max 1000)',\n ),\n patch: z.array(z.record(z.string(), z.unknown())).max(1000),\n});\n\nexport type ConfigChange = z.infer<typeof ConfigChangeSchema>;\n\nexport const SyncStatusSchema = z.object({\n connected: z.boolean(),\n lastSync: z.coerce.date().nullable().optional(),\n pendingChanges: z.number().int().nonnegative().default(0),\n conflicts: z.number().int().nonnegative().default(0),\n});\n\nexport type SyncStatus = z.infer<typeof SyncStatusSchema>;\n","import { z } from 'zod';\n\nexport const AuditActionSchema = z.enum([\n 'create', 'update', 'delete',\n 'invite', 'remove',\n 'deploy', 'start', 'stop',\n 'roleChange',\n]);\n\nexport type AuditAction = z.infer<typeof AuditActionSchema>;\n\nexport const AuditEntityTypeSchema = z.enum([\n 'org', 'project', 'service', 'member', 'permission',\n]);\n\nexport type AuditEntityType = z.infer<typeof AuditEntityTypeSchema>;\n\nexport const AuditLogSchema = z.object({\n id: z.string().max(128),\n orgId: z.string().max(128),\n userId: z.string().max(128),\n action: AuditActionSchema,\n entityType: AuditEntityTypeSchema,\n entityId: z.string().max(128),\n metadata: z.record(z.string().max(256), z.unknown()).default({}).refine(\n (obj) => Object.keys(obj).length <= 100,\n { message: 'Too many metadata keys (max 100)' },\n ),\n timestamp: z.coerce.date(),\n});\n\nexport type AuditLog = z.infer<typeof AuditLogSchema>;\n","import { z } from 'zod';\n\nexport const ProcessMetricsSchema = z.object({\n processId: z.string().max(128),\n cpu: z.number().nonnegative(),\n memory: z.number().int().nonnegative(),\n timestamp: z.string(),\n});\n\nexport type ProcessMetrics = z.infer<typeof ProcessMetricsSchema>;\n","import { z } from 'zod';\nimport { VariableSchema } from './service.schema.js';\n\n// Environment schema — uses VariablesRecord for variable storage\nexport const EnvironmentVariablesSchema = z.record(\n z.string().max(256),\n VariableSchema,\n).refine(\n (obj) => Object.keys(obj).length <= 200,\n { message: 'Max 200 variables' },\n);\n\nexport const EnvironmentSchema = z.object({\n id: z.string().max(128),\n projectId: z.string().max(128),\n name: z.string().min(1).max(200),\n description: z.string().max(2000).optional().default(''),\n parentIds: z.array(z.string().max(128)).max(10).default([]),\n variables: EnvironmentVariablesSchema.default({}),\n // Scope: 'global' = project-level env, 'service' = per-service env\n scope: z.enum(['global', 'service']).default('global'),\n // When scope='service': the serviceId this env belongs to\n reference: z.string().max(128).optional(),\n // When scope='service': the globalEnvId this env activates on\n activateOn: z.string().max(128).optional(),\n immutable: z.boolean().default(false),\n default: z.boolean().optional().default(false),\n color: z.string().max(20).optional(),\n bgColor: z.string().max(20).optional(),\n // When scope='global': the default agent used by services that don't have an explicit agentId\n agentId: z.string().max(128).optional(),\n});\n\nexport type Environment = z.infer<typeof EnvironmentSchema>;\n\n// Resolved environment: flattened env dict + secrets list + source tracking\nexport const ResolvedEnvironmentSchema = z.object({\n variables: z.record(z.string().max(256), VariableSchema)\n .refine((obj) => Object.keys(obj).length <= 500, { message: 'Max 500 resolved variables' }),\n env: z.record(z.string().max(256), z.string().max(8192))\n .refine((obj) => Object.keys(obj).length <= 500, { message: 'Max 500 resolved env vars' }),\n envSecrets: z.array(z.string().max(256)).max(500),\n sources: z.record(z.string().max(256), z.object({\n environmentId: z.string().max(128),\n environmentName: z.string().max(200),\n overridden: z.boolean(),\n resolvedFrom: z.object({\n environmentId: z.string().max(128),\n environmentName: z.string().max(200),\n }).optional(),\n // Set when a machine-local override was applied to this variable, pointing\n // at the environment that carries the winning override. Distinct from\n // `overridden`, which also covers \"shadows an inherited variable\".\n overriddenBy: z.object({\n environmentId: z.string().max(128),\n environmentName: z.string().max(200),\n }).optional(),\n })).refine((obj) => Object.keys(obj).length <= 500, { message: 'Max 500 source entries' }),\n});\n\nexport type ResolvedEnvironment = z.infer<typeof ResolvedEnvironmentSchema>;\n\nexport const CreateEnvironmentSchema = EnvironmentSchema.omit({ id: true }).extend({\n description: z.string().max(2000).optional().default(''),\n parentIds: z.array(z.string().max(128)).max(10).optional().default([]),\n variables: EnvironmentVariablesSchema.optional().default({}),\n scope: z.enum(['global', 'service']).optional().default('global'),\n reference: z.string().max(128).optional(),\n activateOn: z.string().max(128).optional(),\n immutable: z.boolean().optional().default(false),\n});\nexport type CreateEnvironment = z.input<typeof CreateEnvironmentSchema>;\n\n// IMPORTANT: Do NOT simplify this to `EnvironmentSchema.partial().required({ id: true })`.\n//\n// EnvironmentSchema has .default() on several fields (variables: {}, parentIds: [], description: '',\n// scope: 'global', immutable: false, default: false). When Zod parses a partial update input that\n// omits those fields, .partial() alone does NOT strip the defaults — Zod still fills them in.\n// The store checks `input.variables !== undefined` to decide whether to overwrite, so if Zod\n// silently injects `variables: {}`, the store wipes ALL existing variables on every save.\n//\n// The .extend() below overrides those fields without .default(), making them truly optional\n// (undefined when absent). DO NOT remove it or merge the .extend() back into EnvironmentSchema.\nexport const UpdateEnvironmentSchema = EnvironmentSchema\n .partial()\n .required({ id: true })\n .extend({\n description: z.string().max(2000).optional(),\n parentIds: z.array(z.string().max(128)).max(10).optional(),\n variables: EnvironmentVariablesSchema.optional(),\n scope: z.enum(['global', 'service']).optional(),\n immutable: z.boolean().optional(),\n default: z.boolean().optional(),\n agentId: z.string().max(128).nullable().optional(), // null = clear (no default agent)\n });\nexport type UpdateEnvironment = z.infer<typeof UpdateEnvironmentSchema>;\n","import { z } from 'zod';\nimport { VariableSlotSchema } from './service.schema.js';\n\n// An override carries ONLY a value slot: the env var name always comes from the\n// variable definition in `environments.json`, looked up by variable ID. Storing\n// a `key` here would go stale as soon as the variable is renamed in the UI.\nexport const VariableOverrideSchema = z.object({\n value: VariableSlotSchema,\n});\n\nexport type VariableOverride = z.infer<typeof VariableOverrideSchema>;\n\n// Environment overrides: Record<variableId, VariableOverride>\n// Flat structure — each override is keyed by the variable's unique ID.\nexport const EnvironmentOverridesSchema = z.record(\n z.string().max(128),\n VariableOverrideSchema,\n).refine(\n (obj) => Object.keys(obj).length <= 5000,\n { message: 'Max 5000 overrides' },\n);\n\nexport type EnvironmentOverrides = z.infer<typeof EnvironmentOverridesSchema>;\n","import { z } from 'zod';\n\nexport const ApiServiceActionSchema = z.enum([\n 'service:read',\n 'service:start',\n 'service:stop',\n 'service:restart',\n 'service:healthcheck',\n 'service:status',\n 'logs:read',\n]);\nexport type ApiServiceAction = z.infer<typeof ApiServiceActionSchema>;\n\nexport const ApiEnvActionSchema = z.enum(['env:read', 'env:write']);\nexport type ApiEnvAction = z.infer<typeof ApiEnvActionSchema>;\n\nexport const ApiEnvPermSchema = z.object({\n environmentId: z.string().max(128),\n actions: z.array(ApiEnvActionSchema).max(10).default(['env:read']),\n includeSecrets: z.boolean().default(false),\n});\nexport type ApiEnvPerm = z.infer<typeof ApiEnvPermSchema>;\n\nexport const ApiServicePermSchema = z.object({\n serviceId: z.string().max(128),\n actions: z.array(ApiServiceActionSchema).max(10).default(['service:read']),\n environments: z.array(ApiEnvPermSchema).max(100).default([]),\n});\nexport type ApiServicePerm = z.infer<typeof ApiServicePermSchema>;\n\nexport const ApiKeyScopeSchema = z.object({\n services: z.array(ApiServicePermSchema).max(500).default([]),\n});\nexport type ApiKeyScope = z.infer<typeof ApiKeyScopeSchema>;\n\nexport const ApiKeySchema = z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(200),\n key: z.string().regex(/^[0-9a-f]{64}$/i),\n scopes: ApiKeyScopeSchema,\n createdAt: z.string().max(64),\n isPublic: z.boolean().default(false),\n});\nexport type ApiKey = z.infer<typeof ApiKeySchema>;\n\n/**\n * Shape of an API key as it sits on disk: `key` holds the *encrypted* secret,\n * so it no longer matches the 64-hex form the in-memory type guarantees.\n * Legacy files written before encryption still parse — the store decrypts only\n * what looks encrypted and re-persists.\n */\nexport const PersistedApiKeySchema = ApiKeySchema.extend({\n key: z.string().min(1).max(4096),\n});\nexport type PersistedApiKey = z.infer<typeof PersistedApiKeySchema>;\n\nexport const ApiKeysFileSchema = z.object({\n keys: z.array(PersistedApiKeySchema).max(100),\n});\n\n/** An API key as exposed by the API: the secret is never part of it. */\nexport const MaskedApiKeySchema = ApiKeySchema.omit({ key: true }).extend({\n /** Last 4 characters of the secret, for recognising a key in a list. */\n keyPreview: z.string().max(8),\n});\nexport type MaskedApiKey = z.infer<typeof MaskedApiKeySchema>;\n\n","import { z } from 'zod';\n\nexport const ALLOWED_IMAGE_MIME_TYPES = ['image/png', 'image/jpeg', 'image/webp', 'image/gif'] as const;\n\nexport const ImagePartSchema = z.object({\n type: z.literal('image'),\n imageId: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'Must be a valid UUID'),\n url: z.string().min(1),\n mimeType: z.enum(ALLOWED_IMAGE_MIME_TYPES),\n altText: z.string().max(500).optional(),\n});\n\nexport type ImagePart = z.infer<typeof ImagePartSchema>;\n\nexport const ImageUploadResponseSchema = z.object({\n imageId: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'Must be a valid UUID'),\n url: z.string().min(1),\n mimeType: z.enum(ALLOWED_IMAGE_MIME_TYPES),\n originalName: z.string(),\n});\n\nexport type ImageUploadResponse = z.infer<typeof ImageUploadResponseSchema>;\n\nexport const ImageMetaSchema = z.object({\n imageId: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'Must be a valid UUID'),\n filePath: z.string().min(1),\n mimeType: z.enum(ALLOWED_IMAGE_MIME_TYPES),\n originalName: z.string().min(1),\n createdAt: z.number().positive(),\n size: z.number().positive().optional(),\n});\n\nexport type ImageMeta = z.infer<typeof ImageMetaSchema>;\n","import { z } from 'zod';\n\n// --- Attachments ---\n/**\n * A file attached to a card. The bytes live in object storage; the card keeps\n * only this descriptor, so a board document stays small no matter how many\n * files it carries.\n */\nexport const KanbanAttachmentSchema = z.object({\n /** Server-issued id, also the storage key. */\n id: z.string().max(128),\n name: z.string().max(255),\n size: z.number().int().nonnegative(),\n contentType: z.string().max(128),\n});\nexport type KanbanAttachment = z.infer<typeof KanbanAttachmentSchema>;\n\n// --- Card History ---\nexport const KanbanCardEventSchema = z.object({\n type: z.enum(['created', 'edited', 'moved', 'image_added', 'image_removed', 'title_changed', 'conversation_started', 'scenario_started', 'comment', 'archived', 'unarchived']),\n timestamp: z.string(),\n /** Extra context: old/new column name, old/new title, comment text, etc. */\n /**\n * Le texte de l'entrée : le corps d'un commentaire, ou le contexte du geste.\n *\n * Borné comme le corps d'une carte (100 000), et non plus à 5 000 : un\n * commentaire est de la prose comme une description, et rien de technique ne\n * justifiait un écart de vingt fois. La borne étroite s'est vue à l'import\n * d'un Kanbanize, où des commentaires de 12 000 caractères passaient par\n * l'API publique — bornée, elle, à 20 000 — pour écrire en base une donnée que\n * ce schéma déclarait invalide, et qu'aucune reprise depuis l'interface\n * n'aurait ensuite pu enregistrer.\n */\n detail: z.string().max(100_000).optional(),\n /**\n * Stable identity of the event, used to tell an edit from an insertion when a\n * whole history is written back. Absent on events recorded before the field\n * existed; those fall back to (type, timestamp).\n */\n id: z.string().max(128).optional(),\n /**\n * La colonne où l'événement fait entrer la carte (`created`, `moved`,\n * `unarchived`). Le `detail` n'en porte que le titre, qu'un renommage rend\n * introuvable : l'identifiant, lui, tient. Absent des événements antérieurs\n * que la migration n'a pas pu rapprocher.\n */\n columnId: z.string().max(128).optional(),\n /** Who authored this event — 'ai' or 'user'. Only set for comment events. */\n author: z.enum(['ai', 'user']).optional(),\n /**\n * Qui est derrière l'événement, estampillé par le serveur — jamais pris du\n * client, sans quoi n'importe qui pourrait signer au nom d'un autre.\n *\n * Posé sur les commentaires (c'est ce qui rend « mon propre commentaire »\n * répondable ; `author` ne sépare que l'IA de l'humain) et sur les\n * déplacements. Absent des événements écrits avant qu'on l'estampille : un\n * lecteur doit donc afficher « on ne sait pas », pas un nom vide.\n *\n * Pour une clé d'API, c'est le nom de la clé et non son porteur : la clé\n * emprunte les droits de son créateur, pas son identité — personne ne doit\n * croire qu'un humain a déplacé ce qu'un robot de CI a déplacé.\n */\n authorUser: z.object({ id: z.string().max(128), name: z.string().max(200) }).optional(),\n /** Set when the author amended their comment, so the UI can say so. */\n editedAt: z.string().optional(),\n /** Files attached to a comment — same storage as a card's own attachments. */\n attachments: z.array(KanbanAttachmentSchema).max(20).optional(),\n /** Conversation that produced this event (comments only). Used to navigate back to the conversation. */\n conversationId: z.string().optional(),\n});\nexport type KanbanCardEvent = z.infer<typeof KanbanCardEventSchema>;\n\n// --- Card ---\nexport const KanbanCardSchema = z.object({\n id: z.string(),\n title: z.string().min(1).max(500),\n markdown: z.string().max(100_000).default(''),\n /**\n * Legacy inline images, kept so boards written before object storage still\n * render. New uploads go to `attachments` instead.\n */\n images: z.array(z.string()).default([]),\n /** Files attached to the card — stored out of band, referenced here. */\n attachments: z.array(KanbanAttachmentSchema).max(50).default([]),\n order: z.number().int(),\n /**\n * La priorité de la carte, de 1 à 10 — 10 étant le plus urgent.\n *\n * Facultative, et absente veut dire « pas de priorité », pas « la plus\n * basse » : une carte qu'on n'a pas encore arbitrée ne doit pas se ranger\n * d'office au fond de la pile.\n */\n priority: z.number().int().min(1).max(10).optional(),\n\n /**\n * Les groupes de la carte — des étiquettes libres, posées par l'équipe.\n *\n * Rien ne les déclare ailleurs : un groupe existe parce qu'une carte le\n * porte, et disparaît avec la dernière qui le portait. C'est ce qui permet\n * d'en créer un en le tapant, sans passer par un écran d'administration.\n */\n groups: z.array(z.string().min(1).max(60)).max(30).optional(),\n /**\n * L'échéance de la carte : le jour où elle est attendue, `AAAA-MM-JJ`.\n *\n * Un jour, pas un instant, et c'est une décision : une équipe se dit « pour\n * vendredi », jamais « pour vendredi 23:59:59 UTC ». Stocker un instant\n * ferait afficher une échéance au 4 mars comme le 3 mars à qui travaille à\n * l'ouest de Greenwich — la carte serait en retard d'un jour pour la moitié\n * de l'équipe, et personne ne saurait pourquoi.\n *\n * Facultative, et absente veut dire « pas d'échéance », pas « en retard » :\n * une carte qu'on n'a pas datée ne doit pas s'annoncer comme urgente.\n */\n deadline: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/).optional(),\n\n /**\n * La couleur de la carte, en hexadécimal (`#RRGGBB`) — un liseré en haut de\n * la carte, et rien d'autre : ce qu'elle veut dire appartient à l'équipe.\n *\n * Bornée à une notation stricte plutôt qu'à une chaîne libre : cette valeur\n * finit dans un attribut `style`, et une couleur ne doit pouvoir contenir\n * qu'une couleur. Absente sur les cartes sans couleur.\n */\n color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),\n /**\n * Le journal de la carte — commentaires compris.\n *\n * Optionnel, et c'est tout l'intérêt : c'est la partie qui grossit sans fin\n * (une IA bavarde y écrit des pages), alors les lectures de tableau ne le\n * transportent plus. `undefined` veut dire « pas chargé », et une écriture\n * qui l'omet laisse au serveur celui qu'il a en base — à ne pas confondre\n * avec `[]`, qui demanderait bel et bien de le vider.\n */\n history: z.array(KanbanCardEventSchema).optional(),\n /**\n * Ce que le journal absent laisse quand même dire : combien de commentaires,\n * et quand fut le dernier. Posés par le serveur en lecture, ignorés en\n * écriture — la carte ne les stocke pas, ils se déduisent de `history`.\n */\n commentCount: z.number().int().nonnegative().optional(),\n lastCommentAt: z.string().optional(),\n /**\n * L'auteur du dernier commentaire, pour son avatar sur la tuile. Même règle :\n * posé en lecture, ignoré en écriture. `id`/`name` absents quand le\n * commentaire précède l'estampille d'auteur — on sait alors seulement si\n * c'était une IA.\n */\n lastCommentBy: z\n .object({ id: z.string().max(128).optional(), name: z.string().max(200).optional(), author: z.enum(['ai', 'user']).optional() })\n .optional(),\n /**\n * Les entrées de journal qui ouvrent une conversation IA. Elles restent dans\n * la lecture allégée — il y en a une poignée par carte, et l'hôte s'en sert\n * pour dire, sans ouvrir la carte, qu'une IA y travaille.\n */\n conversationEvents: z.array(KanbanCardEventSchema).optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n /**\n * Quand la carte a été archivée — absente tant qu'elle est au tableau.\n *\n * Une carte archivée reste dans sa colonne en base : c'est la lecture qui la\n * retire du tableau, jamais une écriture qui la déplace. Rien à recoller donc\n * au désarchivage, et aucun cimetière où une carte pourrait se perdre.\n */\n archivedAt: z.string().optional(),\n /**\n * La colonne d'où la carte a été archivée, telle qu'elle s'appelait alors.\n *\n * L'identifiant sert à l'y remettre, le titre à le dire dans l'archive même\n * quand la colonne a disparu depuis — auquel cas le désarchivage repose la\n * carte dans la première colonne, sans se taire sur son origine.\n */\n archivedFrom: z\n .object({ columnId: z.string().max(128), columnTitle: z.string().max(200) })\n .optional(),\n /**\n * Quand la carte a été supprimée. Rien n'est effacé : la carte reste en base,\n * et toutes les lectures l'écartent.\n *\n * Une suppression est le seul geste que rien ne rattrape — sauf à ne pas\n * l'exécuter vraiment. La colonne et le tableau portent le même champ, pour\n * que supprimer l'un n'emporte jamais les cartes de l'autre.\n */\n deletedAt: z.string().optional(),\n /**\n * People assigned to the card. Names are denormalized for display; the server\n * keeps only members of the owning organization, and notifies newcomers.\n */\n assignees: z\n .array(z.object({ id: z.string().max(128), name: z.string().max(200) }))\n .max(20)\n .default([]),\n /**\n * Who first created the card. Stamped by the server the first time a card id\n * appears in a board write, never taken from the client — a member could\n * otherwise claim any authorship. Absent on cards created before this field\n * existed, so readers must treat it as unknown rather than assume.\n */\n createdBy: z\n .object({ id: z.string().max(128), name: z.string().max(200) })\n .optional(),\n});\nexport type KanbanCard = z.infer<typeof KanbanCardSchema>;\n\n// --- Column ---\nexport const KanbanColumnSchema = z.object({\n id: z.string(),\n title: z.string().min(1).max(200),\n order: z.number().int(),\n cards: z.array(KanbanCardSchema).default([]),\n /**\n * Le regroupement auquel la colonne appartient, s'il y en a un.\n *\n * Un pointeur vers le parent, et rien dans l'autre sens : le groupe ne tient\n * pas la liste de ses membres. Deux listes qui prétendent dire qui contient\n * quoi finissent par se contredire, et un déplacement devient alors deux\n * écritures au lieu d'une.\n */\n groupId: z.string().optional(),\n /**\n * Colonne de cartes finalisées : y entrer compte comme « finalisée » dans les\n * statistiques de la liste, au même titre qu'un archivage.\n */\n done: z.boolean().optional(),\n /** Supprimée, mais conservée — voir `deletedAt` sur la carte. */\n deletedAt: z.string().optional(),\n});\nexport type KanbanColumn = z.infer<typeof KanbanColumnSchema>;\n\n// --- Column group ---\n/**\n * Un regroupement de colonnes : un bandeau au-dessus d'elles, pas une colonne.\n *\n * Il ne porte aucune carte — jamais — et c'est ce qui le rend inoffensif :\n * `columnId`, les rangs fractionnaires et tout le déplacement de cartes\n * ignorent son existence. Un groupe peut en contenir un autre (`parentId`).\n *\n * Il n'a délibérément **pas** d'`order` : sa place se déduit de celle de ses\n * colonnes, dont l'ordre reste l'unique source de vérité. Un groupe qui aurait\n * son propre rang pourrait contredire celui de ses membres, et il n'existerait\n * alors aucune bonne réponse à « laquelle des deux positions gagne ».\n */\nexport const KanbanColumnGroupSchema = z.object({\n id: z.string(),\n title: z.string().min(1).max(200),\n /** La couleur du bandeau, en hexadécimal — l'interface décide du défaut. */\n color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),\n /** Le groupe parent, pour les regroupements imbriqués. */\n parentId: z.string().optional(),\n /** Supprimé, mais conservé — comme une colonne. */\n deletedAt: z.string().optional(),\n});\nexport type KanbanColumnGroup = z.infer<typeof KanbanColumnGroupSchema>;\n\n// --- Board ---\nexport const KanbanBoardSchema = z.object({\n id: z.string(),\n name: z.string().min(1).max(200),\n description: z.string().max(10_000).default(''),\n /**\n * Le mode d'emploi du tableau, en texte libre : ce que veulent dire ses\n * colonnes, quand une carte a le droit d'avancer, les conventions de\n * l'équipe. Écrit par les humains, lu surtout par l'IA — il est injecté dans\n * le prompt des agents pour qu'ils travaillent selon les règles du tableau\n * plutôt que selon les leurs.\n */\n instructions: z.string().max(20_000).default(''),\n columns: z.array(KanbanColumnSchema).default([]),\n /** Les regroupements de colonnes — vide sur un tableau qui n'en a jamais eu. */\n columnGroups: z.array(KanbanColumnGroupSchema).default([]),\n /**\n * Les projets auxquels le tableau est rattaché, par leur identifiant.\n *\n * Un rattachement, pas une possession : il ne sert qu'à filtrer la liste des\n * tableaux, et un tableau sans projet (`[]`, le cas par défaut) reste visible\n * partout. Plusieurs projets sont permis parce qu'une équipe partage souvent\n * un même tableau entre deux projets — obliger à choisir l'un des deux\n * ferait disparaître le tableau de la liste de l'autre.\n *\n * Les identifiants sont ceux des projets de l'organisation ; le serveur\n * refuse ceux qu'il ne connaît pas plutôt que de garder un lien mort.\n */\n projectIds: z.array(z.string().min(1).max(128)).max(20).default([]),\n archived: z.boolean().default(false),\n /** Supprimé, mais conservé avec ses cartes — voir `deletedAt` sur la carte. */\n deletedAt: z.string().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\nexport type KanbanBoard = z.infer<typeof KanbanBoardSchema>;\n\n// --- Inputs ---\nexport const CreateKanbanBoardInput = z.object({\n name: z.string().min(1).max(200),\n description: z.string().max(10_000).optional(),\n instructions: z.string().max(20_000).optional(),\n projectIds: z.array(z.string().min(1).max(128)).max(20).optional(),\n});\nexport type CreateKanbanBoardInput = z.infer<typeof CreateKanbanBoardInput>;\n\nexport const UpdateKanbanBoardInput = z.object({\n id: z.string(),\n name: z.string().min(1).max(200).optional(),\n description: z.string().max(10_000).optional(),\n instructions: z.string().max(20_000).optional(),\n columns: z.array(KanbanColumnSchema).optional(),\n archived: z.boolean().optional(),\n projectIds: z.array(z.string().min(1).max(128)).max(20).optional(),\n});\nexport type UpdateKanbanBoardInput = z.infer<typeof UpdateKanbanBoardInput>;\n\n// --- Card links ---\n/**\n * Un lien entre deux cartes, rangé hors des tableaux.\n *\n * Le lien ne vit pas dans la carte, et c'est délibéré : une carte se réécrit\n * par tableau entier, et un client plus ancien — dont le Zod ignore le champ —\n * effacerait silencieusement le lien en sauvegardant le tableau. Dans sa propre\n * collection, il survit à toutes les écritures de tableau, y compris celles des\n * versions qui ne le connaissent pas.\n *\n * Un seul type pour l'instant, la filiation : `parent` est la carte au-dessus,\n * `child` celle qui en dépend. Une carte a au plus un parent (c'est le\n * `parent_id` habituel), et les deux extrémités peuvent vivre sur des tableaux\n * différents — la même organisation, en revanche, toujours.\n */\nexport const KanbanCardLinkSchema = z.object({\n id: z.string().max(128),\n /** Le tableau et la carte qui *dépendent* de l'autre. */\n childBoardId: z.string().max(64),\n childCardId: z.string().max(128),\n /** Le tableau et la carte *dont* on dépend. */\n parentBoardId: z.string().max(64),\n parentCardId: z.string().max(128),\n createdAt: z.string(),\n createdBy: z.object({ id: z.string().max(128), name: z.string().max(200) }).optional(),\n});\nexport type KanbanCardLink = z.infer<typeof KanbanCardLinkSchema>;\n\n/**\n * De quoi afficher une carte liée sans ouvrir son tableau : son titre, sa\n * colonne, et le tableau où elle se trouve. Résolu à la lecture plutôt que\n * recopié dans le lien — un titre recopié devient faux au premier renommage.\n */\nexport const KanbanCardRefSchema = z.object({\n cardId: z.string().max(128),\n boardId: z.string().max(64),\n boardName: z.string().max(200),\n columnId: z.string().max(128),\n columnTitle: z.string().max(200),\n title: z.string().max(500),\n /** Les mêmes informations qu'une ligne de tableau montre d'une carte d'ici. */\n assignees: z.array(z.object({ id: z.string().max(128), name: z.string().max(200) })).default([]),\n commentCount: z.number().int().nonnegative().default(0),\n});\nexport type KanbanCardRef = z.infer<typeof KanbanCardRefSchema>;\n","import { z } from 'zod';\n\n/**\n * Les clés d'API du cloud : ce qu'un système tiers présente pour alimenter un\n * kanban sans être un humain connecté.\n *\n * Distinctes des clés de `api-key.schema.ts`, qui ouvrent l'API du serveur\n * *local* et nomment des services. Celles-ci appartiennent à une organisation\n * cloud et ne parlent que de tableaux — deux mondes, deux durées de vie, deux\n * écrans : les mélanger ferait qu'une clé de CI dépendrait d'un poste allumé.\n */\n\n/**\n * Ce qu'une clé a le droit de faire. Des portées séparées plutôt qu'un booléen\n * lecture/écriture : commenter est le geste d'un robot de CI qui rend compte, et\n * il n'a aucune raison de pouvoir aussi créer ou déplacer des cartes.\n *\n * `kanban:delete` est à part pour la même raison, en plus net : effacer est le\n * seul geste que rien ne rattrape. Une clé d'alimentation qui pourrait aussi\n * supprimer transformerait un bogue de script en perte de travail.\n */\nexport const CloudApiScopeSchema = z.enum([\n 'kanban:read',\n 'kanban:write',\n 'kanban:comment',\n 'kanban:delete',\n]);\nexport type CloudApiScope = z.infer<typeof CloudApiScopeSchema>;\n\nexport const CLOUD_API_SCOPES: CloudApiScope[] = [\n 'kanban:read',\n 'kanban:write',\n 'kanban:comment',\n 'kanban:delete',\n];\n\n/**\n * Le préfixe de tout secret émis. Il ne protège rien — il se lit dans un dépôt\n * ou un journal, et c'est le but : un scanner de secrets sait quoi chercher, et\n * un humain qui voit `rk_` dans un fichier sait ce qu'il tient.\n */\nexport const CLOUD_API_KEY_PREFIX = 'rk_';\n\n/** `rk_` suivi de 64 caractères hexadécimaux — 32 octets d'aléa. */\nexport const CloudApiKeySecretSchema = z.string().regex(/^rk_[0-9a-f]{64}$/);\n\nexport const CloudApiKeySchema = z.object({\n id: z.string().max(128),\n organizationId: z.string().max(128),\n name: z.string().min(1).max(200),\n scopes: z.array(CloudApiScopeSchema).min(1).max(10),\n /**\n * Les tableaux que la clé peut atteindre, ou `null` pour « tous ceux de\n * l'organisation ».\n *\n * `null` et `[]` ne sont pas la même chose : la liste vide n'ouvre rien, et\n * c'est délibéré — un tableau supprimé ne doit pas élargir une clé qui ne le\n * nommait plus que lui.\n */\n boards: z.array(z.string().max(64)).max(200).nullable(),\n createdAt: z.string().max(64),\n /** Dernier usage constaté, pour reconnaître une clé oubliée. */\n lastUsedAt: z.string().max(64).nullable(),\n /** Qui l'a émise — une clé sans visage ne se révoque jamais sereinement. */\n createdBy: z.object({ id: z.string().max(128), name: z.string().max(200) }),\n /** Les 4 derniers caractères du secret, pour reconnaître une clé dans une liste. */\n keyPreview: z.string().max(8),\n});\nexport type CloudApiKey = z.infer<typeof CloudApiKeySchema>;\n\n/**\n * La réponse de création — la seule fois où le secret circule.\n *\n * Le serveur n'en garde qu'un condensat : personne, pas même l'organisation, ne\n * peut le relire ensuite. Perdue, une clé se remplace, elle ne se retrouve pas.\n */\nexport const CreatedCloudApiKeySchema = z.object({\n key: CloudApiKeySchema,\n secret: CloudApiKeySecretSchema,\n});\nexport type CreatedCloudApiKey = z.infer<typeof CreatedCloudApiKeySchema>;\n\nexport const CreateCloudApiKeyInput = z.object({\n organizationId: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n scopes: z.array(CloudApiScopeSchema).min(1).max(10),\n boards: z.array(z.string().max(64)).max(200).nullable().default(null),\n});\nexport type CreateCloudApiKeyInput = z.infer<typeof CreateCloudApiKeyInput>;\n\nexport const UpdateCloudApiKeyInput = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200).optional(),\n scopes: z.array(CloudApiScopeSchema).min(1).max(10).optional(),\n boards: z.array(z.string().max(64)).max(200).nullable().optional(),\n});\nexport type UpdateCloudApiKeyInput = z.infer<typeof UpdateCloudApiKeyInput>;\n","import { z } from 'zod';\nimport { KanbanAttachmentSchema } from './kanban.schema.js';\n\n/**\n * Les intégrations de support : un outil de conversation client (Intercom,\n * HubSpot…) qui alimente un kanban du cloud.\n *\n * Le sens est **entrant seulement** : une conversation qui naît devient une\n * carte, ses messages deviennent des commentaires, sa résolution l'archive.\n * Répondre au client se fait toujours dans l'outil d'origine.\n */\n\n/** Les fournisseurs qu'on sait lire. Un de plus = un adaptateur de plus côté cloud. */\nexport const IntegrationProviderSchema = z.enum(['intercom', 'hubspot']);\nexport type IntegrationProvider = z.infer<typeof IntegrationProviderSchema>;\n\n/** Une connexion telle que l'écran de gestion la voit — jamais son secret. */\nexport const IntegrationConnectionSchema = z.object({\n id: z.string().max(128),\n organizationId: z.string().max(128),\n provider: IntegrationProviderSchema,\n name: z.string().min(1).max(200),\n /** Le tableau et la colonne de création — seulement avec la création automatique. */\n boardId: z.string().max(64).nullable(),\n columnId: z.string().max(128).nullable(),\n enabled: z.boolean(),\n /**\n * L'URL complète du webhook à coller chez le fournisseur, construite par le\n * cloud (domaine public des webhooks). Elle contient un jeton imprévisible.\n */\n webhookUrl: z.string().max(2048),\n /** Les quatre derniers caractères du secret de signature, pour le reconnaître. */\n secretPreview: z.string().max(8),\n region: z.string().max(16),\n /** Créer une carte pour toute conversation qui n'est encore liée nulle part. */\n autoCreate: z.boolean(),\n createdBy: z.object({ id: z.string().max(128), name: z.string().max(200) }),\n createdAt: z.string().max(64),\n lastEventAt: z.string().max(64).nullable(),\n});\nexport type IntegrationConnection = z.infer<typeof IntegrationConnectionSchema>;\n\n/** L'état d'une conversation, tel que le fournisseur le dit. */\nexport const IntegrationConversationStateSchema = z.enum(['open', 'resolved']);\n\nexport const IntegrationMessageSchema = z.object({\n id: z.string().max(256),\n author: z.object({ name: z.string().max(500), role: z.enum(['customer', 'agent']) }),\n body: z.string().max(100_000),\n internal: z.boolean(),\n sentAt: z.string().max(64),\n /** Fichiers joints et images, copiés dans Runeya : ils se lisent comme ceux d'une carte. */\n attachments: z.array(KanbanAttachmentSchema).max(50),\n /** Noms des fichiers qui n'ont pas pu être copiés. */\n missingAttachments: z.array(z.string().max(500)).max(50),\n});\nexport type IntegrationMessage = z.infer<typeof IntegrationMessageSchema>;\n\n/** Une conversation telle qu'une carte la montre. */\nexport const IntegrationConversationSchema = z.object({\n id: z.string().max(256),\n connectionId: z.string().max(128),\n provider: IntegrationProviderSchema,\n externalId: z.string().max(128),\n title: z.string().max(500),\n url: z.string().max(2000).nullable(),\n state: IntegrationConversationStateSchema,\n updatedAt: z.string().max(64),\n});\nexport type IntegrationConversation = z.infer<typeof IntegrationConversationSchema>;\n\n/** Une conversation liée à une carte : son fil, et les autres cartes qui la suivent. */\nexport const CardConversationSchema = IntegrationConversationSchema.extend({\n origin: z.enum(['auto', 'manual']),\n /** Les fichiers de la conversation sont en train d'être copiés : ils vont apparaître. */\n filesPending: z.boolean(),\n linkedAt: z.string().max(64),\n opening: z.object({\n author: IntegrationMessageSchema.shape.author,\n body: z.string().max(100_000),\n attachments: z.array(KanbanAttachmentSchema).max(50),\n missingAttachments: z.array(z.string().max(500)).max(50),\n }).nullable(),\n messages: z.array(IntegrationMessageSchema),\n otherCards: z.array(z.object({ boardId: z.string().max(64), cardId: z.string().max(64), title: z.string().max(500) })),\n});\nexport type CardConversation = z.infer<typeof CardConversationSchema>;\n\n/** Un résultat de recherche chez le fournisseur, et les cartes qui la suivent déjà. */\nexport const ConversationSearchHitSchema = IntegrationConversationSchema.extend({\n preview: z.string().max(500),\n linkedCards: z.array(z.object({ boardId: z.string().max(64), cardId: z.string().max(64), title: z.string().max(500) })),\n});\nexport type ConversationSearchHit = z.infer<typeof ConversationSearchHitSchema>;\n","import { z } from 'zod';\n\n/**\n * Le journal des nouveautés, tel qu'il est publié par le cloud.\n *\n * **Deux surfaces, jamais mélangées.** `app` est l'application locale, dont la\n * version est celle du CLI publié sur npm. `cloud` est l'API et son application\n * web, déployées au push et donc sans numéro de version : leurs entrées sont\n * datées. Un même travail qui touche les deux donne DEUX entrées — c'est ce qui\n * permet à un poste resté sur une vieille version de ne pas se voir annoncer des\n * nouveautés qu'il n'a pas, et au cloud d'annoncer les siennes sans attendre une\n * publication npm.\n *\n * L'ordre se déduit de `version` seule (voir `compareChangelogVersions`) : les\n * deux formes — `1.4.2` et `2026-09-03` — se comparent par segments numériques.\n */\n\nexport const ChangelogSurfaceSchema = z.enum(['app', 'cloud']);\nexport type ChangelogSurface = z.infer<typeof ChangelogSurfaceSchema>;\n\n/** Ce que le lecteur doit comprendre en un coup d'œil : est-ce un ajout, un correctif, une rupture. */\nexport const ChangelogChangeKindSchema = z.enum(['feature', 'improvement', 'fix', 'breaking']);\nexport type ChangelogChangeKind = z.infer<typeof ChangelogChangeKindSchema>;\n\n/**\n * Les deux langues de l'interface, toutes deux obligatoires : une entrée\n * publiée dans une seule langue laisserait la moitié des lecteurs devant un\n * trou, et rien dans l'affichage ne pourrait le rattraper.\n */\nexport const ChangelogTextSchema = z.object({\n fr: z.string().min(1).max(500),\n en: z.string().min(1).max(500),\n});\nexport type ChangelogText = z.infer<typeof ChangelogTextSchema>;\n\nexport const ChangelogChangeSchema = z.object({\n kind: ChangelogChangeKindSchema,\n text: ChangelogTextSchema,\n});\nexport type ChangelogChange = z.infer<typeof ChangelogChangeSchema>;\n\n/**\n * Une entrée en attente, telle que l'écrit celui qui fait le travail.\n *\n * Elle ne porte PAS de version : au moment où on l'écrit, le numéro n'existe pas\n * encore — l'app attend sa publication npm, et le cloud n'a jamais de numéro,\n * seulement sa date. Un fichier par entrée, pour que deux branches qui en\n * ajoutent chacune une ne se marchent pas dessus : un tableau partagé produirait\n * un conflit à chaque fusion, et le réflexe sous conflit est d'en perdre une.\n *\n * `title` est facultatif : il nomme la version, pas le changement. La première\n * entrée qui en porte un le donne à sa version ; une version peut n'en avoir\n * aucun, et s'annoncer par son seul numéro.\n */\nexport const ChangelogDraftSchema = ChangelogChangeSchema.extend({\n date: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/),\n title: ChangelogTextSchema.optional(),\n});\nexport type ChangelogDraft = z.infer<typeof ChangelogDraftSchema>;\n\nexport const ChangelogReleaseSchema = z.object({\n surface: ChangelogSurfaceSchema,\n /** `1.4.2` pour l'app (version npm publiée), `2026-09-03` — ou `2026-09-03.2` — pour le cloud. */\n version: z.string().min(1).max(32).regex(/^[0-9][0-9.-]*$/),\n /** Date de publication, `YYYY-MM-DD`. */\n date: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/),\n /** Facultatif : une version peut s'annoncer par son seul numéro. */\n title: ChangelogTextSchema.optional(),\n /** Une version sans changement n'a rien à annoncer : elle n'a pas sa place ici. */\n changes: z.array(ChangelogChangeSchema).min(1).max(50),\n});\nexport type ChangelogRelease = z.infer<typeof ChangelogReleaseSchema>;\n\n/** L'index : de quoi lister et dater, sans transporter les corps. */\nexport const ChangelogIndexItemSchema = ChangelogReleaseSchema.omit({ changes: true }).extend({\n changeCount: z.number().int().nonnegative(),\n});\nexport type ChangelogIndexItem = z.infer<typeof ChangelogIndexItemSchema>;\n\n/**\n * Ordonne deux versions de changelog, quelle que soit leur forme.\n *\n * Les segments sont comparés numériquement (`1.10.0` après `1.9.0`, que la\n * comparaison de chaînes aurait inversé), et une version plus courte perd contre\n * son préfixe plus long (`2026-09-03` avant `2026-09-03.2`).\n */\nexport function compareChangelogVersions(a: string, b: string): number {\n const pa = a.split(/[.-]/).map((n) => Number.parseInt(n, 10) || 0);\n const pb = b.split(/[.-]/).map((n) => Number.parseInt(n, 10) || 0);\n const len = Math.max(pa.length, pb.length);\n for (let i = 0; i < len; i++) {\n const da = pa[i] ?? 0;\n const db = pb[i] ?? 0;\n if (da > db) return 1;\n if (da < db) return -1;\n }\n return 0;\n}\n","import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync } from 'node:crypto';\n\nconst PREFIX = 'aes256gcm:';\nconst IV_LENGTH = 12;\nconst AUTH_TAG_LENGTH = 16;\nconst KEY_LENGTH = 32;\nconst PBKDF2_ITERATIONS = 100_000;\nconst PBKDF2_DIGEST = 'sha256';\n/** Fixed salt for key derivation — the purpose is the salt (lazy to avoid Buffer at module init) */\nlet _KDF_SALT: Buffer | undefined;\nfunction getKdfSalt(): Buffer {\n if (!_KDF_SALT) _KDF_SALT = Buffer.from('runeya-log-sources-key-v1', 'utf8');\n return _KDF_SALT;\n}\n\n/**\n * Derives a 32-byte AES-256 key from `rawKey` using PBKDF2-SHA256.\n * The input key may be any Buffer (e.g. the raw passphrase bytes).\n */\nexport function deriveKey(rawKey: Buffer): Buffer {\n return pbkdf2Sync(rawKey, getKdfSalt(), PBKDF2_ITERATIONS, KEY_LENGTH, PBKDF2_DIGEST);\n}\n\n/**\n * Encrypts `plaintext` using AES-256-GCM.\n * Returns a string in the format: `aes256gcm:<iv_hex>:<authTag_hex>:<ciphertext_hex>`\n */\nexport function encrypt(plaintext: string, key: Buffer): string {\n const iv = randomBytes(IV_LENGTH);\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return `${PREFIX}${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted.toString('hex')}`;\n}\n\n/**\n * Decrypts a ciphertext string produced by `encrypt()`.\n * Throws if the format is invalid or authentication fails.\n */\nexport function decrypt(ciphertext: string, key: Buffer): string {\n if (!isEncrypted(ciphertext)) {\n throw new Error('Value is not in encrypted format');\n }\n const parts = ciphertext.slice(PREFIX.length).split(':');\n if (parts.length !== 3) {\n throw new Error('Invalid encrypted value format');\n }\n const [ivHex, authTagHex, encryptedHex] = parts;\n const iv = Buffer.from(ivHex, 'hex');\n const authTag = Buffer.from(authTagHex, 'hex');\n const encryptedBuffer = Buffer.from(encryptedHex, 'hex');\n\n if (iv.length !== IV_LENGTH) throw new Error('Invalid IV length');\n if (authTag.length !== AUTH_TAG_LENGTH) throw new Error('Invalid authTag length');\n\n const decipher = createDecipheriv('aes-256-gcm', key, iv, { authTagLength: 16 });\n decipher.setAuthTag(authTag);\n return Buffer.concat([decipher.update(encryptedBuffer), decipher.final()]).toString('utf8');\n}\n\n/**\n * Returns true if `value` is in the encrypted format produced by `encrypt()`.\n * Safe to call on plain-text values (returns false).\n */\nexport function isEncrypted(value: string): boolean {\n return value.startsWith(PREFIX);\n}\n","import vm from 'node:vm';\nimport type { JSLogParser as JSLogParserDef } from './schemas/settings.schema.js';\nimport type { LogLine } from './schemas/log.schema.js';\nimport type { LogLevel } from './schemas/log.schema.js';\n\ninterface CompiledParser {\n id: string;\n name: string;\n enabled: boolean;\n fn: (line: LogLine) => LogLine;\n}\n\nconst VALID_LEVELS = new Set<string>(['debug', 'info', 'warn', 'error', 'fatal']);\n\n/** Budget CPU accordé à un parseur pour *une* ligne. */\nconst PARSE_TIMEOUT_MS = 50;\n/** Au-delà, le parseur est considéré hostile et désactivé pour la session. */\nconst MAX_CONSECUTIVE_TIMEOUTS = 10;\n\nexport class JSLogParser {\n private parsers: CompiledParser[] = [];\n\n constructor(definitions: JSLogParserDef[] = []) {\n this.setParsers(definitions);\n }\n\n setParsers(definitions: JSLogParserDef[]): void {\n this.parsers = [];\n\n for (const def of definitions) {\n if (!def.enabled) continue;\n\n try {\n const compiled = this.compileParser(def);\n this.parsers.push({\n id: def.id,\n name: def.name,\n enabled: true,\n fn: compiled,\n });\n } catch (err) {\n console.warn(\n `[js-log-parser] Failed to compile parser \"${def.name}\" (${def.id}): ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n }\n }\n }\n\n parse(line: LogLine): LogLine {\n let current = line;\n\n for (const parser of this.parsers) {\n try {\n current = parser.fn(current);\n } catch (err) {\n console.warn(\n `[js-log-parser] Parser \"${parser.name}\" threw error: ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n }\n }\n\n return this.sanitize(current);\n }\n\n /**\n * Compile le code utilisateur en une fonction bornée en temps.\n *\n * Le `timeout` de `runInNewContext` ne couvre que l'évaluation de la factory :\n * la closure retournée s'exécutait ensuite ligne par ligne directement sur\n * l'event loop, sans aucune borne. Une regex à backtracking exponentiel\n * fournie par l'utilisateur figeait donc l'agent entier — logs, statuts et\n * métriques de *tous* les services. Chaque invocation repasse maintenant par\n * la vm, avec son propre budget.\n */\n private compileParser(def: JSLogParserDef): (line: LogLine) => LogLine {\n const forbidden = ['require(', 'import ', 'eval('];\n for (const pat of forbidden) {\n if (def.code.includes(pat)) {\n throw new Error('Code contains forbidden patterns (require, import, eval)');\n }\n }\n\n const sandbox = {\n RegExp,\n String,\n Object,\n Array,\n JSON,\n Math,\n Date,\n undefined,\n null: null,\n };\n\n let script: vm.Script;\n try {\n script = new vm.Script(`(${def.code})`, { filename: `parser-${def.id}.js` });\n } catch (err) {\n throw new Error(`Compilation failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n // Le contexte est conservé : c'est lui qui permet de ré-entrer dans la vm\n // à chaque ligne, et donc d'armer un timeout par invocation.\n const context = vm.createContext({ ...sandbox, __line: null as unknown, __result: null as unknown });\n\n let parserFn: unknown;\n try {\n parserFn = script.runInContext(context, { timeout: 100 });\n } catch (err) {\n throw new Error(`Execution failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (typeof parserFn !== 'function') {\n throw new Error('Parser code must export a function');\n }\n\n (context as Record<string, unknown>)['__parserFn'] = parserFn;\n const callScript = new vm.Script('__result = __parserFn(__line);', {\n filename: `parser-${def.id}-call.js`,\n });\n\n let consecutiveTimeouts = 0;\n let disabled = false;\n\n return (line: LogLine): LogLine => {\n if (disabled) return line;\n\n const ctx = context as Record<string, unknown>;\n ctx['__line'] = line;\n ctx['__result'] = null;\n try {\n callScript.runInContext(context, { timeout: PARSE_TIMEOUT_MS });\n consecutiveTimeouts = 0;\n } catch (err) {\n // `instanceof Error` est faux ici : l'erreur de timeout ne vient pas du\n // même realm que ce module. On la reconnaît par son code/message.\n const e = err as { code?: unknown; message?: unknown } | null;\n const timedOut = !!e\n && (e.code === 'ERR_SCRIPT_EXECUTION_TIMEOUT'\n || (typeof e.message === 'string' && /execution timed out/i.test(e.message)));\n if (!timedOut) throw err;\n consecutiveTimeouts += 1;\n if (consecutiveTimeouts >= MAX_CONSECUTIVE_TIMEOUTS) {\n disabled = true;\n console.warn(\n `[js-log-parser] Parser \"${def.name}\" (${def.id}) disabled after ${MAX_CONSECUTIVE_TIMEOUTS} consecutive timeouts`,\n );\n }\n return line;\n }\n\n const result = ctx['__result'];\n if (result === null || result === undefined || typeof result !== 'object') {\n return line;\n }\n return result as LogLine;\n };\n }\n\n /** Sanitize the final LogLine: truncate message, limit metadata, validate level */\n private sanitize(line: LogLine): LogLine {\n let { message, metadata, level } = line;\n\n if (message.length > 16384) {\n message = message.substring(0, 16384) + '...[truncated]';\n }\n\n metadata = metadata ?? {};\n const metaKeys = Object.keys(metadata);\n if (metaKeys.length > 100) {\n const limited: Record<string, unknown> = {};\n for (let i = 0; i < 100; i++) {\n limited[metaKeys[i]] = metadata[metaKeys[i]];\n }\n metadata = limited;\n }\n\n if (!VALID_LEVELS.has(level)) {\n level = 'info' as LogLevel;\n }\n\n if (message !== line.message || metadata !== line.metadata || level !== line.level) {\n return { ...line, message, metadata, level };\n }\n return line;\n }\n}\n","/**\n * Variables intégrées — les `{{…}}` que Runeya remplit lui-même, par opposition\n * aux `{{environment.KEY}}` que l'utilisateur définit et que le résolveur\n * d'environnement traite (`apps/server/src/services/environment-resolver.ts`).\n *\n * Cette table est la SEULE déclaration : le serveur et l'agent y lisent ce\n * qu'ils doivent produire, l'interface ce qu'elle doit proposer et documenter.\n * Elle a été introduite parce que la liste vivait en trois exemplaires — dans\n * le routeur de service, dans le gestionnaire de processus et dans le tableau\n * de variables du web — et que le web en avait déjà oublié un.\n *\n * ## Portées\n *\n * - `server` : connu à la résolution, quand le serveur prépare la config à\n * déployer (nom, ports, projet, environnement actif).\n * - `agent` : ne peut être résolu QUE sur la machine qui exécute le service —\n * son IP, son utilisateur, son système, son répertoire de travail. Les\n * résoudre côté serveur graverait la machine qui a fait le déploiement, ce\n * qui ne se voit qu'en multi-machines, et tard.\n */\n\nexport type BuiltinScope = 'server' | 'agent';\n\nexport interface BuiltinVariable {\n /** Nom tel qu'il s'écrit entre accolades, sans les accolades */\n name: string;\n scope: BuiltinScope;\n /** Suffixe de la clé i18n de l'interface : `builtins.<descriptionKey>` */\n descriptionKey: string;\n /** Nom conservé pour ne pas casser les configurations existantes */\n deprecatedAlias?: string;\n}\n\nexport const BUILTIN_VARIABLES: readonly BuiltinVariable[] = [\n // ── Le service ───────────────────────────────────────────────────────────\n { name: 'service.NAME', scope: 'server', descriptionKey: 'serviceName' },\n { name: 'service.ID', scope: 'server', descriptionKey: 'serviceId' },\n { name: 'service.PORT', scope: 'server', descriptionKey: 'servicePort' },\n { name: 'service.URL', scope: 'server', descriptionKey: 'serviceUrl' },\n { name: 'service.BASE_URL', scope: 'server', descriptionKey: 'serviceBaseUrl' },\n { name: 'service.CWD', scope: 'agent', descriptionKey: 'serviceCwd' },\n\n // ── Le projet et l'environnement actif ───────────────────────────────────\n { name: 'project.NAME', scope: 'server', descriptionKey: 'projectName' },\n { name: 'runeya.ENV_NAME', scope: 'server', descriptionKey: 'envName' },\n\n // ── Le serveur Runeya ────────────────────────────────────────────────────\n // `service.HOST` a toujours désigné l'adresse d'écoute du SERVEUR, pas une\n // propriété du service : le nom trompait, il devient un alias.\n { name: 'runeya.HOST', scope: 'server', descriptionKey: 'runeyaHost', deprecatedAlias: 'service.HOST' },\n\n // ── La machine qui exécute ───────────────────────────────────────────────\n { name: 'agent.HOST_LAN', scope: 'agent', descriptionKey: 'agentHostLan', deprecatedAlias: 'service.HOST_LAN' },\n // Le NOM de l'agent est une étiquette de la configuration du serveur, pas\n // une propriété de la machine : c'est le serveur qui le connaît et le résout.\n { name: 'agent.NAME', scope: 'server', descriptionKey: 'agentName' },\n { name: 'agent.OS', scope: 'agent', descriptionKey: 'agentOs' },\n { name: 'agent.HOME', scope: 'agent', descriptionKey: 'agentHome' },\n];\n\nexport const BUILTINS_BY_SCOPE = (scope: BuiltinScope): readonly BuiltinVariable[] =>\n BUILTIN_VARIABLES.filter((b) => b.scope === scope);\n\n/**\n * Une référence `{{nom}}`. Le nom accepte les points (`service.PORT`,\n * `services.api.URL`) mais ni espace ni accolade : une référence ne peut donc\n * pas se former à la couture entre deux morceaux de texte.\n */\nconst BUILTIN_REFERENCE_RE = /\\{\\{([A-Za-z][A-Za-z0-9_.-]*)\\}\\}/g;\n\n/** Les `{{environment.KEY}}` appartiennent au résolveur, jamais aux builtins. */\nconst ENVIRONMENT_NAMESPACE = 'environment.';\n\n/** Le préfixe sous lequel un service en nomme un autre : `services.<slug>.PORT`. */\nconst CROSS_SERVICE_NAMESPACE = 'services.';\n\n/**\n * Remplace les références présentes dans `values`, et laisse les autres\n * intactes : une passe unique, jamais récursive — une valeur qui contient\n * elle-même une référence ne relance pas la substitution, faute de quoi deux\n * variables se pointant l'une l'autre boucleraient.\n */\nexport function interpolateBuiltins(text: string, values: Record<string, string>): string {\n return text.replace(BUILTIN_REFERENCE_RE, (match, name: string) => {\n if (name.startsWith(ENVIRONMENT_NAMESPACE)) return match;\n return values[name] ?? match;\n });\n}\n\n/**\n * Les slugs de services qu'un texte nomme, via `{{services.<slug>.PROP}}`.\n *\n * C'est l'arête d'un graphe de dépendances : si une variable de A cite\n * `services.b.PORT`, c'est que A a besoin de B pour tourner. La détection\n * s'appuie sur la MÊME expression que `interpolateBuiltins`, pour ne jamais\n * annoncer un lien que l'interpolation ne ferait pas — `{{services. b.URL}}`\n * n'est pas une référence, et ne doit donc pas devenir une arête.\n *\n * Une référence sans propriété (`{{services.b}}`) ne résout rien : elle ne\n * compte pas non plus.\n */\nexport function crossServiceSlugsIn(text: string): string[] {\n const slugs = new Set<string>();\n for (const match of text.matchAll(BUILTIN_REFERENCE_RE)) {\n const name = match[1];\n if (!name || !name.startsWith(CROSS_SERVICE_NAMESPACE)) continue;\n const rest = name.slice(CROSS_SERVICE_NAMESPACE.length);\n const dot = rest.indexOf('.');\n if (dot <= 0 || dot === rest.length - 1) continue;\n slugs.add(rest.slice(0, dot));\n }\n return [...slugs];\n}\n\n/** `interpolateBuiltins` appliqué à chaque valeur d'un dictionnaire d'env. */\nexport function interpolateBuiltinsInEnv(\n env: Record<string, string>,\n values: Record<string, string>,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n out[key] = interpolateBuiltins(value, values);\n }\n return out;\n}\n\n/**\n * Ajoute au dictionnaire les alias hérités, pour que `{{service.HOST}}`\n * continue de rendre ce que rend `{{runeya.HOST}}`.\n */\nexport function withDeprecatedAliases(values: Record<string, string>): Record<string, string> {\n const out = { ...values };\n for (const builtin of BUILTIN_VARIABLES) {\n if (builtin.deprecatedAlias && out[builtin.name] !== undefined) {\n out[builtin.deprecatedAlias] = out[builtin.name];\n }\n }\n return out;\n}\n\n/**\n * Nom sous lequel un service est adressable depuis un autre\n * (`{{services.<slug>.PORT}}`).\n *\n * Un nom de service est libre — accents, espaces, majuscules — alors qu'une\n * référence doit rester un mot sans espace. D'où ce passage en minuscules\n * tiretées, appliqué de la même façon par le serveur qui produit les valeurs\n * et par l'interface qui les propose.\n */\nexport function serviceSlug(name: string): string {\n return name\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\n/**\n * Les slugs que deux services d'un même projet se disputent.\n *\n * Un tel slug n'est adressable pour AUCUN des deux : rendre l'un plutôt que\n * l'autre dépendrait de l'ordre de chargement. La règle est ici, et non chez\n * ses deux appelants — celui qui produit les valeurs à interpoler et celui qui\n * dessine le graphe des liens — parce qu'ils doivent dire la même chose : un\n * lien montré à l'écran mais non interpolé au démarrage serait pire que pas de\n * lien du tout.\n */\nexport function ambiguousServiceSlugs(names: readonly string[]): Set<string> {\n const counts = new Map<string, number>();\n for (const name of names) {\n const slug = serviceSlug(name);\n if (slug) counts.set(slug, (counts.get(slug) ?? 0) + 1);\n }\n return new Set([...counts].filter(([, count]) => count > 1).map(([slug]) => slug));\n}\n\n/**\n * Les ports d'un service : `service.PORT` pour le premier — celui qu'on cite\n * dans neuf cas sur dix — puis `service.PORT_2`, `_3`… pour les suivants.\n */\nexport function servicePortValues(ports: readonly number[] | undefined, prefix = 'service'): Record<string, string> {\n const values: Record<string, string> = {};\n (ports ?? []).forEach((port, i) => {\n values[i === 0 ? `${prefix}.PORT` : `${prefix}.PORT_${i + 1}`] = String(port);\n });\n return values;\n}\n\n/**\n * Une adresse d'écoute « toutes interfaces » n'est pas une adresse à laquelle\n * on se connecte. En mode LAN, le serveur écoute sur `0.0.0.0` : bâtir\n * `http://0.0.0.0:3000` donnerait une URL que rien ne peut joindre.\n */\nexport function isWildcardHost(host: string): boolean {\n const h = host.trim();\n return h === '' || h === '0.0.0.0' || h === '::' || h === '[::]';\n}\n\n/** L'adresse de bouclage, sous ses écritures possibles. */\nfunction isLoopbackHost(host: string): boolean {\n const h = host.trim();\n return h === '127.0.0.1' || h === '::1' || h === '[::1]';\n}\n\n/**\n * L'hôte à écrire dans une URL, à partir de l'adresse d'écoute du serveur.\n *\n * La boucle locale devient `localhost` : c'est le nom que les développeurs\n * écrivent, celui des origines autorisées du dépôt, et celui qu'on colle dans\n * un navigateur. `{{runeya.HOST}}` continue de rendre l'adresse réelle — c'est\n * elle qu'un service met dans son bind, et la traduire là serait faux.\n *\n * Un hôte explicitement configuré (une IP de LAN, un nom de machine) n'est\n * jamais réécrit : le seul cas traduit est celui où l'adresse ne désigne que\n * « cette machine ». Une adresse « toutes interfaces » rend `null` — à\n * l'appelant de décider, l'agent connaissant seul son IP joignable.\n */\nexport function urlHostFor(host: string): string | null {\n if (isWildcardHost(host)) return null;\n return isLoopbackHost(host) ? 'localhost' : host.trim();\n}\n\n/**\n * Les URL par lesquelles on joint un service, une par port : `service.URL`,\n * `service.URL_2`… numérotées comme les ports, si bien que `URL_2` désigne\n * toujours le service sur `PORT_2`.\n *\n * Un domaine local est déclaré AVEC son port (c'est ce que le proxy route) :\n * l'URL d'un port est donc son domaine s'il en a un, sinon l'hôte et le port.\n * Un domaine déclaré sur un port absent de la liste des ports est ajouté à la\n * suite, pour ne pas se perdre.\n *\n * À ne pas confondre avec le champ `url` du service — son « URL de base »,\n * saisie librement, souvent l'adresse publique : celle-là s'écrit\n * `{{service.BASE_URL}}`. Faire rendre l'une par l'autre romprait la\n * correspondance entre `URL_n` et `PORT_n`.\n */\nexport function serviceUrlValues(service: {\n ports?: number[];\n localUrls?: { url: string; port: number }[];\n}, host: string, prefix = 'service'): Record<string, string> {\n const domainByPort = new Map((service.localUrls ?? []).map((lu) => [lu.port, lu.url]));\n const ports = [...(service.ports ?? [])];\n for (const local of service.localUrls ?? []) {\n if (!ports.includes(local.port)) ports.push(local.port);\n }\n\n const values: Record<string, string> = {};\n ports.forEach((port, i) => {\n const domain = domainByPort.get(port);\n values[i === 0 ? `${prefix}.URL` : `${prefix}.URL_${i + 1}`] =\n domain ? `http://${domain}` : `http://${host}:${port}`;\n });\n return values;\n}\n\n/** Les clés `services.<slug>.*` exposées pour un service voisin. */\nexport function crossServiceValues(service: {\n name: string;\n id: string;\n ports?: number[];\n localUrls?: { url: string; port: number }[];\n url?: string;\n}, host: string): Record<string, string> {\n const slug = serviceSlug(service.name);\n if (!slug) return {};\n return {\n [`services.${slug}.NAME`]: service.name,\n [`services.${slug}.ID`]: service.id,\n ...servicePortValues(service.ports, `services.${slug}`),\n ...serviceUrlValues(service, host, `services.${slug}`),\n ...(service.url ? { [`services.${slug}.BASE_URL`]: service.url } : {}),\n };\n}\n\n/** Une référence qu'aucune étape ne remplira : elle arrivera telle quelle dans le process. */\nexport interface UnresolvedReference {\n key: string;\n reference: string;\n}\n\n/** Les ports et URL numérotés que le serveur produit en plus des noms déclarés : `service.PORT_2`. */\nconst NUMBERED_SERVICE_BUILTIN_RE = /^service\\.(PORT|URL)_\\d+$/;\n\nfunction builtinScopeOf(name: string): BuiltinScope | null {\n const builtin = BUILTIN_VARIABLES.find((b) => b.name === name || b.deprecatedAlias === name);\n if (builtin) return builtin.scope;\n if (NUMBERED_SERVICE_BUILTIN_RE.test(name) || name.startsWith(CROSS_SERVICE_NAMESPACE)) return 'server';\n return null;\n}\n\n/**\n * Les références restées en place dans un env résolu, et qui le resteront.\n *\n * Le résolveur d'environnement, puis le serveur, puis l'agent remplissent\n * chacun les leurs et laissent intactes les autres — si bien qu'une faute de\n * frappe (`{{environment.DB_HSOT}}`) arrive au process comme du texte, sans\n * que rien ne le signale. Ce qui est signalé dépend de l'étape atteinte :\n *\n * - une référence d'environnement : toujours, le résolveur est déjà passé ;\n * - une variable intégrée du serveur : si `serverResolved` — sinon elle attend\n * le déploiement ; mais un nom qui n'en est pas une est une faute dans les\n * deux cas ;\n * - une variable intégrée de l'agent : jamais, elle se remplit au démarrage.\n *\n * `skipKeys` tait des clés — celles dont la valeur est masquée : la forme d'un\n * secret, références comprises, n'a pas à sortir.\n */\nexport function findUnresolvedReferences(\n env: Record<string, string>,\n opts: { serverResolved: boolean; skipKeys?: Iterable<string> },\n): UnresolvedReference[] {\n const skip = new Set(opts.skipKeys ?? []);\n const out: UnresolvedReference[] = [];\n for (const [key, value] of Object.entries(env)) {\n if (skip.has(key)) continue;\n for (const match of value.matchAll(BUILTIN_REFERENCE_RE)) {\n const reference = match[1]!;\n if (!reference.startsWith(ENVIRONMENT_NAMESPACE)) {\n const scope = builtinScopeOf(reference);\n if (scope === 'agent') continue;\n if (scope === 'server' && !opts.serverResolved) continue;\n }\n out.push({ key, reference });\n }\n }\n return out;\n}\n\n/** Une valeur recopiée, et la référence qui la suivrait. */\nexport interface BuiltinSuggestion {\n literal: string;\n reference: string;\n}\n\n/** Les variables intégrées qui valent la peine d'être reconnues : ports et adresses, du service ou d'un voisin. */\nconst SUGGESTABLE_BUILTIN_RE = /^(service|services\\.[^.]+)\\.(PORT|URL|BASE_URL)(_\\d+)?$/;\n\n/**\n * Les ports et URL de services recopiés dans une valeur, avec la référence qui\n * les remplacerait.\n *\n * Recopier `http://localhost:3211` fige l'adresse du front telle qu'elle est sur\n * ce poste, aujourd'hui : elle ne suit ni un changement de port ni un domaine\n * local. `{{services.front.URL}}`, si. `builtins` est ce que le serveur calcule\n * pour le service concerné (`buildServerBuiltins`).\n *\n * La plus longue valeur l'emporte (une URL avant le port qu'elle contient), et\n * à longueur égale la référence du service lui-même avant celle qui le nomme de\n * l'extérieur. Un nombre n'est reconnu qu'entier, et rien n'est lu à\n * l'intérieur d'une référence déjà écrite. Ce ne sont que des suggestions : la\n * valeur n'est jamais réécrite.\n */\nexport function suggestBuiltinReferences(text: string, builtins: Record<string, string>): BuiltinSuggestion[] {\n const candidates = Object.entries(builtins)\n .filter(([name, value]) => SUGGESTABLE_BUILTIN_RE.test(name) && value.length > 1 && !value.includes('{{'))\n .sort(([nameA, a], [nameB, b]) => b.length - a.length || Number(nameA.startsWith('services.')) - Number(nameB.startsWith('services.')));\n\n const claimed: [number, number][] = [...text.matchAll(BUILTIN_REFERENCE_RE)].map((m) => [m.index, m.index + m[0].length]);\n const overlaps = (start: number, end: number) => claimed.some(([s, e]) => start < e && end > s);\n const isDigit = (c: string | undefined) => c !== undefined && c >= '0' && c <= '9';\n\n const suggestions: BuiltinSuggestion[] = [];\n for (const [name, literal] of candidates) {\n let from = 0;\n for (let at = text.indexOf(literal, from); at !== -1; at = text.indexOf(literal, from)) {\n const end = at + literal.length;\n from = at + 1;\n if (overlaps(at, end)) continue;\n if (isDigit(literal[0]) && isDigit(text[at - 1])) continue;\n if (isDigit(literal[literal.length - 1]) && isDigit(text[end])) continue;\n claimed.push([at, end]);\n if (!suggestions.some((s) => s.literal === literal)) suggestions.push({ literal, reference: `{{${name}}}` });\n }\n }\n return suggestions;\n}\n","/** Health check default interval (ms) */\nexport const HEALTH_CHECK_INTERVAL = 30_000;\n\n/** Metrics collection interval (ms) */\nexport const METRICS_INTERVAL = 5_000;\n\n/** Agent health polling interval (ms) */\nexport const AGENT_HEALTH_POLL_INTERVAL = 15_000;\n\n/** UI search/filter debounce (ms) */\nexport const SEARCH_DEBOUNCE = 300;\n\n/** Health check initial delay before first check (ms) */\nexport const HEALTH_CHECK_INITIAL_DELAY = 5_000;\n\n/** Agent health WS interval (ms) */\nexport const HEALTH_WS_INTERVAL = 10_000;\n","/** Default log ring buffer size */\nexport const LOG_BUFFER_SIZE = 5_000;\n\n/** Max log entries displayed in UI */\nexport const LOG_DISPLAY_LIMIT = 500;\n","/** Default process grace period before SIGKILL (ms) */\nexport const GRACE_PERIOD = 10_000;\n\n/** HTTP fetch timeout for agent calls (ms) */\nexport const AGENT_FETCH_TIMEOUT = 10_000;\n\n/** HTTP fetch timeout for long-running agent calls like shortcuts/ad-hoc commands (ms) — 10 minutes */\nexport const AGENT_LONG_FETCH_TIMEOUT = 600_000;\n\n/** HTTP fetch timeout for process stop calls (ms) — grace period + generous buffer */\nexport const AGENT_STOP_FETCH_TIMEOUT = GRACE_PERIOD + 15_000;\n\n/** Passphrase extraction timeout during agent spawn (ms) */\nexport const PASSPHRASE_TIMEOUT = 30_000;\n\n/** Min WS reconnect delay (ms) */\nexport const WS_RECONNECT_MIN = 1_000;\n\n/** Max WS reconnect delay (ms) */\nexport const WS_RECONNECT_MAX = 15_000;\n\n/** Max WS reconnect attempts */\nexport const WS_RECONNECT_MAX_ATTEMPTS = 5;\n\n/** Base retry delay for subscriptions (ms) */\nexport const SUBSCRIPTION_RETRY_BASE = 1_000;\n","export interface EditorDefinition {\n key: string;\n name: string;\n command: string;\n}\n\nexport const SUPPORTED_EDITORS: EditorDefinition[] = [\n { key: 'vscode', name: 'Visual Studio Code', command: 'code' },\n { key: 'cursor', name: 'Cursor', command: 'cursor' },\n { key: 'windsurf', name: 'Windsurf', command: 'windsurf' },\n { key: 'sublime', name: 'Sublime Text', command: 'subl' },\n { key: 'atom', name: 'Atom', command: 'atom' },\n { key: 'antigravity', name: 'Antigravity', command: 'antigravity' },\n { key: 'intellij', name: 'IntelliJ IDEA', command: 'idea' },\n { key: 'android-studio', name: 'Android Studio', command: 'studio' },\n { key: 'webstorm', name: 'WebStorm', command: 'webstorm' },\n { key: 'zed', name: 'Zed', command: 'zed' },\n { key: 'neovim', name: 'Neovim', command: 'nvim' },\n { key: 'vim', name: 'Vim', command: 'vim' },\n { key: 'emacs', name: 'Emacs', command: 'emacs' },\n { key: 'fleet', name: 'Fleet', command: 'fleet' },\n];\n\nexport const EDITOR_BY_KEY = new Map<string, EditorDefinition>(\n SUPPORTED_EDITORS.map((e) => [e.key, e]),\n);\n","import * as Y from 'yjs';\n\n/**\n * Generic JSON ↔ Yjs mapping.\n *\n * The cloud must share exactly what git shares: the contents of the `.runeya`\n * files, whatever fields they happen to carry today. Enumerating those fields\n * would make this a hand-maintained allowlist — adding a field to a schema and\n * forgetting it here would not break anything, it would just silently stop\n * syncing. So nothing here names a field: any JSON shape round-trips.\n *\n * The mapping is structural rather than blob-per-file, because a blob makes\n * every concurrent edit last-writer-wins across a whole file. Mapping objects to\n * `Y.Map` and arrays to `Y.Array` lets Yjs merge edits to different fields — and\n * different array elements — the way it is meant to.\n *\n * Every write is a *diff*: identical input must produce no Yjs update at all.\n * Anything less loops forever (local → doc → local → doc).\n */\n\nexport type Json = null | boolean | number | string | Json[] | { [k: string]: Json };\n\n/**\n * Strip `undefined` and other non-JSON values by round-tripping.\n *\n * Zod leaves optional fields absent while JS code tends to set them to\n * `undefined`; `Y.Map.set(k, undefined)` is not `delete(k)`, so without this the\n * diff would see a change on every pass and never settle.\n */\nexport function normalize(value: unknown): Json {\n return JSON.parse(JSON.stringify(value ?? null)) as Json;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, Json> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/** Yjs value → plain JSON. */\nexport function toPlain(value: unknown): Json {\n if (value instanceof Y.Map) {\n const out: Record<string, Json> = {};\n for (const [k, v] of value.entries()) out[k] = toPlain(v);\n return out;\n }\n if (value instanceof Y.Array) return value.toArray().map(toPlain);\n return (value ?? null) as Json;\n}\n\n/**\n * Identity of an array element, used to align two versions of an array.\n *\n * An element with an `id` keeps that identity across edits, so a concurrent\n * change to one element and an insertion of another merge cleanly. Anything\n * else (scalars, objects with no id) is identified by its whole value: editing\n * it reads as delete + insert, i.e. last-writer-wins for that element.\n */\nfunction identityOf(value: Json): string {\n if (isPlainObject(value) && typeof value['id'] === 'string') return `id:${value['id']}`;\n return `v:${JSON.stringify(value)}`;\n}\n\nfunction identityOfY(value: unknown): string {\n if (value instanceof Y.Map) {\n const id = value.get('id');\n if (typeof id === 'string') return `id:${id}`;\n }\n return `v:${JSON.stringify(toPlain(value))}`;\n}\n\n/** Convert a JSON value into the Yjs type that represents it. */\nfunction toY(value: Json): unknown {\n if (Array.isArray(value)) {\n const arr = new Y.Array<unknown>();\n if (value.length > 0) arr.insert(0, value.map(toY));\n return arr;\n }\n if (isPlainObject(value)) {\n const map = new Y.Map<unknown>();\n for (const [k, v] of Object.entries(value)) map.set(k, toY(v));\n return map;\n }\n return value;\n}\n\n/**\n * Diff `next` into a `Y.Map`, recursing into nested objects and arrays and\n * deleting keys that `next` no longer has.\n */\nexport function applyToMap(map: Y.Map<unknown>, next: Record<string, Json>): void {\n for (const key of Array.from(map.keys())) {\n if (!(key in next)) map.delete(key);\n }\n for (const [key, value] of Object.entries(next)) {\n const current = map.get(key);\n if (Array.isArray(value)) {\n if (!(current instanceof Y.Array)) map.set(key, toY(value));\n else applyToArray(current, value);\n } else if (isPlainObject(value)) {\n if (!(current instanceof Y.Map)) map.set(key, toY(value));\n else applyToMap(current, value);\n } else if (current instanceof Y.Map || current instanceof Y.Array || current !== value) {\n map.set(key, value);\n }\n }\n}\n\n/**\n * Diff `next` into a `Y.Array` by aligning elements on their identity.\n *\n * Targeted inserts/deletes are what let Yjs keep both sides of a concurrent\n * append; rewriting the array wholesale (delete-all + insert) would drop one of\n * them, which is exactly the data loss this mapping exists to avoid.\n */\nexport function applyToArray(arr: Y.Array<unknown>, next: Json[]): void {\n const wanted = next.map(identityOf);\n const wantedCount = new Map<string, number>();\n for (const k of wanted) wantedCount.set(k, (wantedCount.get(k) ?? 0) + 1);\n\n // Drop elements `next` no longer contains (respecting duplicate counts).\n const seen = new Map<string, number>();\n for (let i = arr.length - 1; i >= 0; i--) {\n const key = identityOfY(arr.get(i));\n const used = seen.get(key) ?? 0;\n if (used >= (wantedCount.get(key) ?? 0)) arr.delete(i, 1);\n else seen.set(key, used + 1);\n }\n\n // Walk both sides in order: recurse into matches, insert what is missing.\n for (let j = 0; j < next.length; j++) {\n const key = wanted[j]!;\n if (j < arr.length && identityOfY(arr.get(j)) === key) {\n const current = arr.get(j);\n const value = next[j]!;\n if (current instanceof Y.Map && isPlainObject(value)) applyToMap(current, value);\n else if (current instanceof Y.Array && Array.isArray(value)) applyToArray(current, value);\n continue;\n }\n // Pull a later match into place rather than re-creating it, so a reorder\n // does not read as a delete + insert of unrelated content.\n let found = -1;\n for (let k = j + 1; k < arr.length; k++) {\n if (identityOfY(arr.get(k)) === key) {\n found = k;\n break;\n }\n }\n if (found !== -1) {\n const moved = toPlain(arr.get(found));\n arr.delete(found, 1);\n arr.insert(j, [toY(moved)]);\n } else {\n arr.insert(j, [toY(next[j]!)]);\n }\n }\n}\n\n/** A collection of entities keyed by id: `doc.getMap(name)` → `{ [id]: Y.Map }`. */\nexport function getCollection(doc: Y.Doc, name: string): Y.Map<unknown> {\n return doc.getMap(name);\n}\n\n/** Read one entity as plain JSON, or null when absent/malformed. */\nexport function readEntity(collection: Y.Map<unknown>, id: string): Record<string, Json> | null {\n const entity = collection.get(id);\n if (!(entity instanceof Y.Map)) return null;\n const plain = toPlain(entity);\n return isPlainObject(plain) ? plain : null;\n}\n\n/**\n * Write one entity, mutating only what differs. Must run inside\n * `doc.transact(..., origin)` so the bridge can tell local writes from remote.\n */\nexport function writeEntity(collection: Y.Map<unknown>, id: string, entity: unknown): void {\n const next = normalize(entity);\n if (!isPlainObject(next)) return;\n const current = collection.get(id);\n if (!(current instanceof Y.Map)) {\n collection.set(id, toY(next));\n return;\n }\n applyToMap(current, next);\n}\n","/// <reference path=\"./shellwords.d.ts\" />\nimport { execa } from 'execa';\nimport { execSync } from 'node:child_process';\nimport { homedir } from 'node:os';\nimport * as shellwordsModule from 'shellwords';\nimport type { Runner, RunnerProcess, RunnerStartConfig } from './types.js';\n\nconst shellwordsSplit = (shellwordsModule as { split: (str: string) => string[] }).split;\n\n/** Expand $VAR and ${VAR} references using the provided env dict.\n * Also expands leading ~ to the home directory.\n * Callers must pass a fully-merged env (passthrough + serviceEnv). */\nfunction expandEnvVars(str: string, serviceEnv?: Record<string, string>): string {\n const withHome = str.replace(/^~(\\/|$)/, `${homedir()}$1`);\n return withHome.replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (_, braced, plain) => {\n const name = braced ?? plain;\n return serviceEnv?.[name] ?? '';\n });\n}\n\n/** Resolve a cwd field: expand env vars, fallback to '.' if empty/undefined. */\nexport function resolveCwd(cwd: string | undefined, env?: Record<string, string>): string {\n if (!cwd) return '.';\n return expandEnvVars(cwd, env) || '.';\n}\n\n/** Find $VAR and ${VAR} references that are not defined in the provided env dict.\n * Callers must pass a fully-merged env (passthrough + serviceEnv). */\nexport function findUnresolvedEnvVars(str: string, serviceEnv?: Record<string, string>): string[] {\n const unresolved: string[] = [];\n str.replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (_, braced, plain) => {\n const name = braced ?? plain;\n if (serviceEnv?.[name] === undefined) {\n unresolved.push(name);\n }\n return '';\n });\n return unresolved;\n}\n\n/**\n * Build a safe environment for child processes.\n * SECURITY: Never spread ...process.env — it leaks secrets (passphrases, API keys, etc.).\n * Only pass system-essential variables plus the service's explicit env config.\n */\n/** Standard system binary directories to ensure basic commands (cat, sleep, etc.) are always found. */\nconst SYSTEM_PATH_DIRS = ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin', '/usr/bin', '/sbin', '/bin'];\n\nfunction buildSafeEnv(configEnv: Record<string, string> = {}): Record<string, string> {\n const safeKeys = ['PATH', 'HOME', 'USER', 'SHELL', 'LANG', 'TERM', 'NODE_ENV', 'TMPDIR', 'TZ', 'DBUS_SESSION_BUS_ADDRESS', 'XDG_RUNTIME_DIR'];\n const env: Record<string, string> = {};\n for (const key of safeKeys) {\n if (process.env[key]) {\n env[key] = process.env[key]!;\n }\n }\n // Augment PATH with standard system dirs to ensure basic commands are always available,\n // even when Runeya is started with a minimal PATH (e.g. via systemd or a launcher).\n const existingPath = env['PATH'] ?? '';\n const existingDirs = new Set(existingPath.split(':').filter(Boolean));\n const missingDirs = SYSTEM_PATH_DIRS.filter(d => !existingDirs.has(d));\n if (missingDirs.length > 0) {\n env['PATH'] = [existingPath, ...missingDirs].filter(Boolean).join(':');\n }\n return { ...env, ...configEnv };\n}\n\nexport class NativeRunner implements Runner {\n readonly type = 'native' as const;\n\n start(config: RunnerStartConfig): RunnerProcess {\n let subprocess;\n\n const cwd = resolveCwd(config.cwd, config.env);\n\n const isWindows = process.platform === 'win32';\n\n if (config.shell) {\n // Shell mode: execute entire command as shell script\n subprocess = execa(config.command, {\n cwd,\n env: buildSafeEnv(config.env),\n shell: true,\n detached: !isWindows, // Create new process group for group kill (not supported on Windows)\n windowsHide: true, // Prevent terminal windows from appearing on Windows\n stdio: ['ignore', 'pipe', 'pipe'],\n reject: false, // Don't throw on non-zero exit\n buffer: false, // Don't accumulate stdout/stderr in memory — we stream via readline\n });\n } else {\n // Normal mode: parse command with shellwords, execute with shell:false\n // This safely handles quoted arguments and escape sequences\n const args = shellwordsSplit(config.command);\n const cmd = args.shift();\n if (!cmd) {\n throw new Error('Invalid command: cannot parse empty or whitespace-only command');\n }\n\n subprocess = execa(cmd, args, {\n cwd,\n env: buildSafeEnv(config.env),\n shell: false, // SECURITY: shell:false prevents command injection\n detached: !isWindows, // Create new process group for group kill (not supported on Windows)\n windowsHide: true, // Prevent terminal windows from appearing on Windows\n stdio: ['ignore', 'pipe', 'pipe'],\n reject: false, // Don't throw on non-zero exit\n buffer: false, // Don't accumulate stdout/stderr in memory — we stream via readline\n });\n }\n\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>((resolve) => {\n subprocess.then((result) => {\n resolve({\n exitCode: result.exitCode ?? null,\n signal: (result.signal as NodeJS.Signals) ?? null,\n error: result.failed && result.shortMessage ? result.shortMessage : undefined,\n });\n }).catch((err) => {\n resolve({ exitCode: 1, signal: null, error: err.message ?? 'Unknown error' });\n });\n });\n\n return {\n pid: subprocess.pid,\n kill(signal: NodeJS.Signals = 'SIGTERM'): boolean {\n try {\n if (process.platform === 'win32') {\n if (!subprocess.pid) return false;\n // taskkill /F /T kills the entire process tree (including children keeping pipes open)\n execSync(`taskkill /F /T /PID ${subprocess.pid}`, { stdio: 'ignore' });\n return true;\n }\n // Unix: kill the entire process group\n if (subprocess.pid) {\n process.kill(-subprocess.pid, signal);\n return true;\n }\n return subprocess.kill(signal);\n } catch {\n return false;\n }\n },\n stdout: subprocess.stdout,\n stderr: subprocess.stderr,\n exitPromise,\n };\n }\n\n async isAvailable(): Promise<boolean> {\n return true; // Native runner is always available\n }\n}\n","const scan = (\n string: string,\n pattern: RegExp,\n callback: (match: RegExpMatchArray) => void,\n) => {\n let result = \"\";\n\n while (string.length > 0) {\n const match = string.match(pattern);\n\n if (match && match.index != null && match[0] != null) {\n result += string.slice(0, match.index);\n result += callback(match);\n string = string.slice(match.index + match[0].length);\n } else {\n result += string;\n string = \"\";\n }\n }\n\n return result;\n};\n\n/**\n * Splits a string into an array of tokens in the same way the UNIX Bourne shell does.\n *\n * @param line A string to split.\n * @returns An array of the split tokens.\n */\nexport const split = (line = \"\") => {\n const words = [];\n let field = \"\";\n scan(\n line,\n /\\s*(?:([^\\s\\\\'\"]+)|'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\"|(\\\\.?)|(\\S))(\\s|$)?/,\n (match) => {\n const [_raw, word, sq, dq, escape, garbage, separator] = match;\n\n if (garbage != null) {\n throw new Error(`Unmatched quote: ${line}`);\n }\n\n if (word) {\n field += word;\n } else {\n let addition;\n\n if (sq) {\n addition = sq;\n } else if (dq) {\n addition = dq;\n } else if (escape) {\n addition = escape;\n }\n\n if (addition) {\n field += addition.replace(/\\\\(?=.)/, \"\");\n }\n }\n\n if (separator != null) {\n words.push(field);\n field = \"\";\n }\n },\n );\n\n if (field) {\n words.push(field);\n }\n\n return words;\n};\n\n/**\n * Escapes a string so that it can be safely used in a Bourne shell command line.\n *\n * @param str A string to escape.\n * @returns The escaped string.\n */\nexport const escape = (str = \"\") => {\n return str\n .replace(/([^A-Za-z0-9_\\-.,:/@\\n])/g, \"\\\\$1\")\n .replace(/\\n/g, \"'\\n'\");\n};\n\n/**\n * Builds a command line string from an argument list.\n *\n * @param array An array of string arguments.\n * @returns The command line string.\n */\nexport const join = (array: string[]) =>\n array.map((element) => escape(element)).join(\" \");\n","import { execa } from 'execa';\nimport { PassThrough } from 'node:stream';\nimport { randomUUID } from 'node:crypto';\nimport { writeFile, unlink, mkdir } from 'node:fs/promises';\nimport { tmpdir, homedir, userInfo } from 'node:os';\nimport { join } from 'node:path';\nimport type { Runner, RunnerProcess, RunnerStartConfig } from '@runeya/packages-runner-native';\nimport type { BootstrapCommand, DockerConfig } from '@runeya/packages-shared';\n\n/** Split a command string into tokens, respecting single and double quotes. */\nfunction splitShellArgs(cmd: string): string[] {\n const args: string[] = [];\n let current = '';\n let inSingle = false;\n let inDouble = false;\n for (let i = 0; i < cmd.length; i++) {\n const ch = cmd[i];\n if (ch === \"'\" && !inDouble) {\n inSingle = !inSingle;\n } else if (ch === '\"' && !inSingle) {\n inDouble = !inDouble;\n } else if (ch === '\\\\' && inDouble && i + 1 < cmd.length) {\n current += cmd[++i];\n } else if (/\\s/.test(ch) && !inSingle && !inDouble) {\n if (current) { args.push(current); current = ''; }\n } else {\n current += ch;\n }\n }\n if (current) args.push(current);\n return args;\n}\n\nexport interface DockerRunnerStartConfig extends RunnerStartConfig {\n dockerConfig: DockerConfig;\n serviceId: string;\n cmdId?: string; // for isolated mode container naming\n rm?: boolean; // add --rm to docker run (for shortcuts / one-off commands)\n skipBootstrap?: boolean; // skip bootstrap commands (for shortcuts)\n}\n\n/** Sanitize a string for use as a Docker container/image name: lowercase, only [a-z0-9._-] */\nfunction sanitizeDockerName(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9._-]/g, '-').replace(/-{2,}/g, '-');\n}\n\n/** Expand $VAR and ${VAR} references using the provided env dict.\n * Also expands leading ~ to the home directory.\n * Callers must pass a fully-merged env (passthrough + serviceEnv). */\nfunction expandEnvVars(str: string, serviceEnv?: Record<string, string>): string {\n const withHome = str.replace(/^~(\\/|$)/, `${homedir()}$1`);\n return withHome.replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (_, braced, plain) => {\n const name = braced ?? plain;\n return serviceEnv?.[name] ?? '';\n });\n}\n\n/** Pre-create host-side volume directories so Docker doesn't create them as root.\n * Only processes bind mounts (host:container[:opts]) — skips named volumes. */\nasync function preMkdirVolumes(volumes: string[], serviceEnv?: Record<string, string>): Promise<void> {\n for (const v of volumes) {\n const expanded = expandEnvVars(v, serviceEnv);\n const parts = expanded.split(':');\n // Named volumes have no path separator or start with a letter/digit without '/'\n if (parts.length < 2) continue;\n const hostPath = parts[0];\n if (!hostPath.startsWith('/') && !hostPath.startsWith('.')) continue;\n await mkdir(hostPath, { recursive: true }).catch(() => {});\n }\n}\n\nexport class DockerRunner implements Runner {\n readonly type = 'docker' as const;\n\n public start(config: DockerRunnerStartConfig): RunnerProcess {\n const stdout = new PassThrough();\n const stderr = new PassThrough();\n const containerName = sanitizeDockerName(config.cmdId\n ? `runeya-${config.serviceId}-${config.cmdId}`\n : `runeya-${config.serviceId}`);\n let killed = false;\n\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>(\n (resolve) => {\n void (async () => {\n try {\n // 1. Force-remove any existing container (ignore errors)\n await execa('docker', ['rm', '-f', containerName], { reject: false });\n\n const dc = config.dockerConfig;\n let lastCardId: string | null = null;\n const envFlags: string[] = Object.entries(config.env ?? {}).flatMap(\n ([k, v]) => ['-e', `${k}=${v}`],\n );\n await preMkdirVolumes(dc.volumes ?? [], config.env);\n const volumeFlags: string[] = (dc.volumes ?? []).flatMap((v: string) => ['-v', expandEnvVars(v, config.env)]);\n if (dc.mountRootpath && config.cwd) {\n volumeFlags.push('-v', `${config.cwd}:${config.cwd}`);\n }\n\n // 2a. Pull mode\n if (dc.image && !dc.dockerfile) {\n lastCardId = randomUUID();\n // Emit phase marker using \\x00DOCKER_PHASE: prefix for unambiguous frontend detection\n stdout.write(\n '\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'pull', _cardId: lastCardId, _cardState: 'open', message: `--- Docker Pull: ${dc.image} ---` }) + '\\n',\n );\n const pull = execa('docker', ['pull', dc.image], { reject: false });\n pull.stdout?.pipe(stdout, { end: false });\n pull.stderr?.pipe(stderr, { end: false });\n await pull;\n }\n\n // 2b. Build mode\n let imageName = dc.image ?? containerName + ':latest';\n if (dc.dockerfile) {\n lastCardId = randomUUID();\n // Emit phase marker using \\x00DOCKER_PHASE: prefix for unambiguous frontend detection\n stdout.write(\n '\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'build', _cardId: lastCardId, _cardState: 'open', message: '--- Docker Build ---' }) + '\\n',\n );\n const tmpFile = join(tmpdir(), `runeya-${config.serviceId}-${randomUUID()}.dockerfile`);\n try {\n await writeFile(tmpFile, dc.dockerfile, 'utf8');\n const buildArgs = Object.entries(dc.buildArgs ?? {}).flatMap(\n ([k, v]) => ['--build-arg', `${k}=${v}`],\n );\n const targetArgs = dc.targetStage ? ['--target', dc.targetStage] : [];\n const buildContext = dc.buildContext ?? config.cwd ?? '.';\n imageName = `${containerName}:latest`;\n const build = execa(\n 'docker',\n ['build', '-f', tmpFile, '-t', imageName, ...buildArgs, ...targetArgs, buildContext],\n { reject: false },\n );\n build.stdout?.pipe(stdout, { end: false });\n build.stderr?.pipe(stderr, { end: false });\n await build;\n } finally {\n await unlink(tmpFile).catch(() => {});\n }\n }\n\n if (killed) {\n resolve({ exitCode: null, signal: 'SIGTERM' as NodeJS.Signals });\n return;\n }\n\n // Close the phase card (pull/build) so container run logs flow into normal log stream\n if (lastCardId) {\n stdout.write(\n '\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'close', _cardId: lastCardId, _cardState: 'close' }) + '\\n',\n );\n }\n\n // 3. Bootstrap commands — run sequentially before the main container\n const bootstrapCmds = config.skipBootstrap ? [] : (dc.bootstrapCommands ?? []).filter((c) => c.command.trim());\n for (const bsCmd of bootstrapCmds) {\n if (killed) {\n resolve({ exitCode: null, signal: 'SIGTERM' as NodeJS.Signals });\n return;\n }\n const bsCardId = randomUUID();\n const bsCmdName = bsCmd.label || bsCmd.command;\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'bootstrap', _cardId: bsCardId, _cardState: 'open', message: `Bootstrap: ${bsCmdName}` })}\\n`);\n const exitCode = await this.runBootstrap(bsCmd, imageName, config.env ?? {}, dc.volumes ?? [], stdout, stderr);\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'close', _cardId: bsCardId, _cardState: 'close' })}\\n`);\n if (exitCode !== 0) {\n stderr.write(`Bootstrap command \"${bsCmdName}\" failed with exit code ${exitCode}\\n`);\n resolve({ exitCode, signal: null, error: `Bootstrap \"${bsCmdName}\" failed (exit ${exitCode})` });\n return;\n }\n }\n\n if (killed) {\n resolve({ exitCode: null, signal: 'SIGTERM' as NodeJS.Signals });\n return;\n }\n\n // 4. Run container (foreground, no --detach, no --rm)\n const networkFlags =\n dc.networkMode === 'host'\n ? ['--network', 'host']\n : (dc.ports ?? []).flatMap((p) => ['-p', p]);\n // When useNativeCommand is true the user's native command takes full control:\n // ignore dc.entrypoint (it belongs to the \"docker command\" mode) and wrap the\n // command with sh -c so shell syntax (pipes, quotes, redirects) works inside\n // the container. When useNativeCommand is false, honour dc.entrypoint and use\n // dc.command (the docker-specific command field).\n let cmdArgs: string[];\n let entrypointFlags: string[];\n if (dc.useNativeCommand) {\n const shell = dc.nativeShell || 'sh';\n entrypointFlags = [];\n cmdArgs = config.command ? [shell, '-c', config.command] : [];\n } else {\n entrypointFlags = dc.entrypoint ? ['--entrypoint', dc.entrypoint] : [];\n cmdArgs = dc.command ? splitShellArgs(dc.command) : [];\n }\n const { uid, gid } = userInfo();\n const rmFlag = config.rm ? ['--rm'] : [];\n const runArgs = [\n 'run', ...rmFlag, '--init',\n '--name', containerName,\n '--user', dc.user || `${uid}:${gid}`,\n ...networkFlags,\n ...envFlags,\n ...volumeFlags,\n ...entrypointFlags,\n imageName,\n ...cmdArgs,\n ];\n const debugCardId = randomUUID();\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'run', _cardId: debugCardId, _cardState: 'open', message: 'Docker Run' })}\\n`);\n stdout.write(`docker ${runArgs.join(' ')}\\n`);\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'close', _cardId: debugCardId, _cardState: 'close' })}\\n`);\n const runProc = execa('docker', runArgs, { reject: false });\n runProc.stdout?.pipe(stdout, { end: false });\n runProc.stderr?.pipe(stderr, { end: false });\n const result = await runProc;\n resolve({ exitCode: result.exitCode ?? null, signal: (result.signal as NodeJS.Signals) ?? null });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr.write(`Docker infrastructure error: ${msg}\\n`);\n resolve({ exitCode: 1, signal: null });\n } finally {\n stdout.end();\n stderr.end();\n }\n })();\n },\n );\n\n return {\n pid: undefined,\n containerName,\n stdout,\n stderr,\n exitPromise,\n kill(_signal = 'SIGTERM') {\n killed = true;\n execa('docker', ['stop', containerName]).catch(() => {});\n return true;\n },\n };\n }\n\n /** Start a long-lived container (sleep infinity) for shared mode.\n * Returns the RunnerProcess (lifetime) plus a `containerReady` promise that resolves\n * once `docker run --detach` has completed and the container is confirmed running.\n * Callers must await `containerReady` before calling `execInContainer`. */\n public startSharedContainer(config: DockerRunnerStartConfig): RunnerProcess & { containerReady: Promise<void> } {\n const stdout = new PassThrough();\n const stderr = new PassThrough();\n const containerName = sanitizeDockerName(`runeya-${config.serviceId}`);\n let killed = false;\n\n let resolveReady!: () => void;\n let rejectReady!: (err: Error) => void;\n const containerReady = new Promise<void>((res, rej) => {\n resolveReady = res;\n rejectReady = rej;\n });\n\n // exitResolve is shared between the kill() path and the natural-exit path.\n // Whichever fires first wins — subsequent calls are no-ops (Promise settled).\n let exitResolve!: (result: { exitCode: number | null; signal: NodeJS.Signals | null; error?: string }) => void;\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>(\n (resolve) => { exitResolve = resolve; },\n );\n\n void (async () => {\n try {\n await execa('docker', ['rm', '-f', containerName], { reject: false });\n\n const dc = config.dockerConfig;\n let lastCardId: string | null = null;\n const envFlags: string[] = Object.entries(config.env ?? {}).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n await preMkdirVolumes(dc.volumes ?? [], config.env);\n const volumeFlags: string[] = (dc.volumes ?? []).flatMap((v: string) => ['-v', expandEnvVars(v, config.env)]);\n if (dc.mountRootpath && config.cwd) {\n volumeFlags.push('-v', `${config.cwd}:${config.cwd}`);\n }\n\n if (dc.image && !dc.dockerfile) {\n lastCardId = randomUUID();\n stdout.write('\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'pull', _cardId: lastCardId, _cardState: 'open', message: `--- Docker Pull: ${dc.image} ---` }) + '\\n');\n const pull = execa('docker', ['pull', dc.image], { reject: false });\n pull.stdout?.pipe(stdout, { end: false });\n pull.stderr?.pipe(stderr, { end: false });\n await pull;\n }\n\n let imageName = dc.image ?? containerName + ':latest';\n if (dc.dockerfile) {\n lastCardId = randomUUID();\n stdout.write('\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'build', _cardId: lastCardId, _cardState: 'open', message: '--- Docker Build ---' }) + '\\n');\n const tmpFile = join(tmpdir(), `runeya-${config.serviceId}-${randomUUID()}.dockerfile`);\n try {\n await writeFile(tmpFile, dc.dockerfile, 'utf8');\n const buildArgs = Object.entries(dc.buildArgs ?? {}).flatMap(([k, v]) => ['--build-arg', `${k}=${v}`]);\n const targetArgs = dc.targetStage ? ['--target', dc.targetStage] : [];\n const buildContext = dc.buildContext ?? config.cwd ?? '.';\n imageName = `${containerName}:latest`;\n const build = execa('docker', ['build', '-f', tmpFile, '-t', imageName, ...buildArgs, ...targetArgs, buildContext], { reject: false });\n build.stdout?.pipe(stdout, { end: false });\n build.stderr?.pipe(stderr, { end: false });\n await build;\n } finally {\n await unlink(tmpFile).catch(() => {});\n }\n }\n\n if (killed) {\n rejectReady(new Error('Killed before container started'));\n exitResolve({ exitCode: null, signal: 'SIGTERM' as NodeJS.Signals });\n return;\n }\n\n if (lastCardId) {\n stdout.write('\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'close', _cardId: lastCardId, _cardState: 'close' }) + '\\n');\n }\n\n const networkFlags = dc.networkMode === 'host'\n ? ['--network', 'host']\n : (dc.ports ?? []).flatMap((p: string) => ['-p', p]);\n const { uid, gid } = userInfo();\n const runArgs = [\n 'run', '--detach', '--init',\n '--name', containerName,\n '--user', dc.user || `${uid}:${gid}`,\n ...networkFlags,\n ...envFlags,\n ...volumeFlags,\n imageName,\n 'sleep', 'infinity',\n ];\n const debugCardId = randomUUID();\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'run', _cardId: debugCardId, _cardState: 'open', message: 'Docker Run (shared container)' })}\\n`);\n stdout.write(`docker ${runArgs.join(' ')}\\n`);\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'close', _cardId: debugCardId, _cardState: 'close' })}\\n`);\n\n const runProc = execa('docker', runArgs, { reject: false });\n runProc.stdout?.pipe(stdout, { end: false });\n runProc.stderr?.pipe(stderr, { end: false });\n const runResult = await runProc;\n if (runResult.exitCode !== 0) {\n rejectReady(new Error(`docker run exited with code ${runResult.exitCode}`));\n exitResolve({ exitCode: runResult.exitCode ?? 1, signal: null });\n return;\n }\n\n // Container is now running — signal callers they can exec into it\n resolveReady();\n\n // Wait for natural container exit (kill() resolves exitPromise first if called)\n const waitProc = execa('docker', ['wait', containerName], { reject: false });\n await waitProc;\n exitResolve({ exitCode: 0, signal: null });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr.write(`Docker infrastructure error: ${msg}\\n`);\n rejectReady(new Error(msg));\n exitResolve({ exitCode: 1, signal: null });\n } finally {\n stdout.end();\n stderr.end();\n }\n })();\n\n return {\n pid: undefined,\n containerName,\n stdout,\n stderr,\n exitPromise,\n containerReady,\n kill(_signal = 'SIGTERM') {\n killed = true;\n // Await docker kill, then immediately resolve exitPromise — don't wait for docker wait\n execa('docker', ['kill', containerName])\n .then(() => exitResolve({ exitCode: null, signal: 'SIGKILL' as NodeJS.Signals }))\n .catch(() => exitResolve({ exitCode: 1, signal: null }));\n return true;\n },\n };\n }\n\n /** Run a command inside a running shared container via `docker exec`.\n * Kill terminates the docker-exec process but does NOT stop the container. */\n public execInContainer(containerName: string, command: string, envVars: Record<string, string> = {}, shell = 'sh'): RunnerProcess {\n const stdout = new PassThrough();\n const stderr = new PassThrough();\n let dockerProc: ReturnType<typeof execa> | null = null;\n\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>(\n (resolve) => {\n void (async () => {\n try {\n const envFlags = Object.entries(envVars).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n const shellCmd = command.length ? command : 'true';\n dockerProc = execa(\n 'docker',\n ['exec', ...envFlags, containerName, shell, '-c', shellCmd],\n { reject: false },\n );\n dockerProc.stdout?.pipe(stdout, { end: false });\n dockerProc.stderr?.pipe(stderr, { end: false });\n const result = await dockerProc;\n resolve({ exitCode: result.exitCode ?? null, signal: (result.signal as NodeJS.Signals) ?? null });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr.write(`docker execInContainer error: ${msg}\\n`);\n resolve({ exitCode: 1, signal: null });\n } finally {\n stdout.end();\n stderr.end();\n }\n })();\n },\n );\n\n return {\n pid: undefined,\n containerName,\n stdout,\n stderr,\n exitPromise,\n kill(_signal = 'SIGTERM') {\n dockerProc?.kill('SIGTERM');\n return true;\n },\n };\n }\n\n /** Run a shortcut command in the context of a Docker service.\n * If a service container is running (shared or isolated), uses `docker exec`.\n * If not running, reuses `start()` with `--rm` and `skipBootstrap`. */\n public runShortcut(config: DockerRunnerStartConfig, shortcutCommand: string): RunnerProcess {\n const stdout = new PassThrough();\n const stderr = new PassThrough();\n let innerProcess: RunnerProcess | null = null;\n let dockerProc: ReturnType<typeof execa> | null = null;\n\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>(\n (resolve) => {\n void (async () => {\n try {\n // Find any running container for this service (covers both shared and isolated modes).\n const psResult = await execa(\n 'docker', ['ps', '--filter', `name=runeya-${config.serviceId}`, '--format', '{{.Names}}'],\n { reject: false },\n );\n const runningContainer = psResult.stdout.trim().split('\\n').find(n => n.startsWith(`runeya-${config.serviceId}`));\n\n if (runningContainer) {\n // Container is running — docker exec into it\n const shell = config.dockerConfig.nativeShell || 'sh';\n const envFlags = Object.entries(config.env ?? {}).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n const args = ['exec', ...envFlags, runningContainer, shell, '-c', shortcutCommand || 'true'];\n const cardId = randomUUID();\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'exec', _cardId: cardId, _cardState: 'open', message: 'Docker Exec' })}\\n`);\n stdout.write(`docker ${args.join(' ')}\\n`);\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'close', _cardId: cardId, _cardState: 'close' })}\\n`);\n dockerProc = execa('docker', args, { reject: false });\n dockerProc.stdout?.pipe(stdout, { end: false });\n dockerProc.stderr?.pipe(stderr, { end: false });\n const result = await dockerProc;\n resolve({ exitCode: result.exitCode ?? null, signal: (result.signal as NodeJS.Signals) ?? null });\n } else {\n // No running container — reuse start() with --rm, skip bootstrap, shortcut command\n // Force useNativeCommand so start() wraps the command with sh -c\n innerProcess = this.start({\n ...config,\n command: shortcutCommand,\n cmdId: `shortcut-${randomUUID()}`,\n rm: true,\n skipBootstrap: true,\n dockerConfig: { ...config.dockerConfig, useNativeCommand: true },\n });\n innerProcess.stdout?.pipe(stdout, { end: false });\n innerProcess.stderr?.pipe(stderr, { end: false });\n const result = await innerProcess.exitPromise;\n resolve(result);\n }\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr.write(`docker shortcut error: ${msg}\\n`);\n resolve({ exitCode: 1, signal: null });\n } finally {\n stdout.end();\n stderr.end();\n }\n })();\n },\n );\n\n return {\n pid: undefined,\n stdout,\n stderr,\n exitPromise,\n kill(signal = 'SIGTERM' as NodeJS.Signals) {\n if (innerProcess) return innerProcess.kill(signal);\n dockerProc?.kill('SIGTERM');\n return true;\n },\n };\n }\n\n public async isAvailable(): Promise<boolean> {\n const result = await execa('docker', ['info'], { reject: false });\n return result.exitCode === 0;\n }\n\n /** Run a single bootstrap command sequentially inside a temporary container (--rm).\n * Streams stdout/stderr into the provided PassThrough streams.\n * Resolves with the exit code when the container exits. */\n public async runBootstrap(\n cmd: BootstrapCommand,\n imageName: string,\n env: Record<string, string>,\n volumes: string[],\n stdout: PassThrough,\n stderr: PassThrough,\n ): Promise<number> {\n const containerName = sanitizeDockerName(`runeya-bootstrap-${randomUUID()}`);\n const envFlags: string[] = Object.entries(env).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n await preMkdirVolumes(volumes, env);\n const volumeFlags: string[] = volumes.map(v => expandEnvVars(v, env)).flatMap(v => ['-v', v]);\n const entrypointFlags: string[] = cmd.entrypoint ? ['--entrypoint', cmd.entrypoint] : [];\n const { uid, gid } = userInfo();\n const defaultUser = `${uid}:${gid}`;\n const userFlags: string[] = ['--user', cmd.user || defaultUser];\n const cmdArgs = splitShellArgs(cmd.command);\n\n const runArgs = [\n 'run', '--rm', '--init',\n '--name', containerName,\n '--network', 'host',\n ...envFlags,\n ...volumeFlags,\n ...entrypointFlags,\n ...userFlags,\n imageName,\n ...cmdArgs,\n ];\n\n const proc = execa('docker', runArgs, { reject: false });\n proc.stdout?.pipe(stdout, { end: false });\n proc.stderr?.pipe(stderr, { end: false });\n const result = await proc;\n return result.exitCode ?? 1;\n }\n}\n\nexport { type Runner, type RunnerProcess, type RunnerStartConfig } from '@runeya/packages-runner-native';\n","import type { ServiceConfig } from '@runeya/packages-shared';\nimport type { RunnerProcess } from '@runeya/packages-runner-native';\n\nexport interface CommandProcess {\n commandId: string;\n runnerProcess: RunnerProcess | null;\n pid: number | null;\n containerName: string | null;\n exitCode: number | null;\n}\n\nexport interface StoredProcess {\n id: string;\n serviceConfig: ServiceConfig;\n commandProcesses: CommandProcess[];\n state: 'starting' | 'running' | 'stopped' | 'errored';\n exitCode: number | null;\n startedAt: Date | null;\n restartCount: number;\n manuallyStopped: boolean;\n operationInProgress: boolean; // Prevent race conditions from concurrent operations\n sharedContainerProcess?: RunnerProcess | null; // Docker shared mode: the long-lived container process\n}\n\nclass ProcessStore {\n private processes = new Map<string, StoredProcess>();\n\n get(id: string): StoredProcess | undefined {\n return this.processes.get(id);\n }\n\n getAll(): StoredProcess[] {\n return Array.from(this.processes.values());\n }\n\n set(id: string, process: StoredProcess): void {\n this.processes.set(id, process);\n }\n\n delete(id: string): boolean {\n return this.processes.delete(id);\n }\n\n has(id: string): boolean {\n return this.processes.has(id);\n }\n\n clear(): void {\n this.processes.clear();\n }\n\n getByServiceId(serviceId: string): StoredProcess | undefined {\n return this.getAll().find(p => p.serviceConfig.id === serviceId);\n }\n}\n\nexport const processStore = new ProcessStore();\n","import { createInterface } from 'node:readline';\nimport { EventEmitter } from 'node:events';\nimport { randomUUID } from 'node:crypto';\nimport type { ParsedLog, JSLogParserDef, LogCardDirective, ILogSource } from '@runeya/packages-shared';\nimport { LOG_BUFFER_SIZE } from '@runeya/packages-shared';\nimport { LogParser } from '../log-parser.js';\nimport { LogBuffer } from '../log-buffer.js';\nimport { stripAnsi } from '../../utils/strip-ansi.js';\n\nconst DOCKER_PHASE_PREFIX = '\\x00DOCKER_PHASE:';\n\n/** Monotonic counter for fast log IDs (replaces randomUUID for hot-path logs) */\nlet logIdCounter = 0;\nfunction fastId(): string {\n return 'L' + (++logIdCounter).toString(36);\n}\n\ninterface ActiveCard {\n id: string;\n type: string;\n header: string;\n collapsable?: boolean;\n collapsed?: boolean;\n}\n\nexport class ConsoleLogSource extends EventEmitter implements ILogSource {\n readonly id: string;\n readonly type = 'console' as const;\n\n private parsers = new Map<string, LogParser>();\n private buffer: LogBuffer;\n private processPids = new Map<string, number | null>();\n private pendingBatch: ParsedLog[] = [];\n private batchScheduled = false;\n private readlineInterfaces: import('node:readline').Interface[] = [];\n\n constructor(bufferSize: number = LOG_BUFFER_SIZE) {\n super();\n this.id = randomUUID();\n this.buffer = new LogBuffer(bufferSize);\n }\n\n /** No-op: attach() is called separately after start() */\n async start(_processId: string): Promise<void> {\n // no-op for console source — actual streaming begins via attach()\n }\n\n /** Closes all active readline interfaces and releases resources */\n async stop(): Promise<void> {\n for (const rl of this.readlineInterfaces) {\n rl.close();\n }\n this.readlineInterfaces = [];\n }\n\n setJSParsers(processId: string, jsParsers: JSLogParserDef[] = []): void {\n const parser = new LogParser(jsParsers);\n this.parsers.set(processId, parser);\n }\n\n /** Attach to a process stdout/stderr and start streaming logs.\n * Each attach() call gets its own session card context so that multiple\n * concurrent commands (isolated mode) don't clobber each other's card state. */\n attach(processId: string, stdout: NodeJS.ReadableStream | null, stderr: NodeJS.ReadableStream | null, pid?: number | null): void {\n // Store the PID for this process so logs can reference it\n if (pid !== undefined) {\n const existingPid = this.processPids.get(processId);\n if (existingPid != null && existingPid !== pid) {\n console.warn(`[console-log-source] WARNING: Replacing PID ${existingPid} with ${pid} for process ${processId}. This may indicate a race condition or double-start.`);\n }\n this.processPids.set(processId, pid);\n }\n\n // Shared session state between stdout and stderr for THIS attach() call only\n let sessionCard: ActiveCard | null = null;\n\n if (stdout) {\n const rl = createInterface({ input: stdout });\n this.readlineInterfaces.push(rl);\n rl.on('line', (rawLine) => {\n // Nettoye avant l'analyse : un programme qui colore sa sortie (tout\n // l'ecosysteme Vite sous Windows) donnerait sinon des lignes dont ni le\n // JSON ni le niveau ne se reconnaissent plus.\n const line = stripAnsi(rawLine);\n const log = this.createLog(processId, line, 'stdout', sessionCard, (card) => { sessionCard = card; });\n if (!log) return;\n this.enqueueLog(log);\n });\n rl.on('error', (err) => {\n console.debug('[console-log-source] readline stdout error for', processId + ':', err.message);\n });\n }\n\n if (stderr) {\n const rl = createInterface({ input: stderr });\n this.readlineInterfaces.push(rl);\n rl.on('line', (rawLine) => {\n const line = stripAnsi(rawLine);\n const log = this.createLog(processId, line, 'stderr', sessionCard, (card) => { sessionCard = card; });\n if (!log) return;\n this.enqueueLog(log);\n });\n rl.on('error', (err) => {\n console.debug('[console-log-source] readline stderr error for', processId + ':', err.message);\n });\n }\n }\n\n /** Add a synthetic system/error log entry (e.g., spawn failure) */\n addSystemLog(\n processId: string,\n message: string,\n level: 'error' | 'warn' | 'info' = 'error',\n logCard?: LogCardDirective,\n ): void {\n console.debug('[console-log-source] Adding system log for', processId, ':', message);\n const pid = this.processPids.get(processId) ?? null;\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid,\n timestamp: new Date(),\n level,\n message,\n raw: message,\n stream: level === 'error' || level === 'warn' ? 'stderr' : 'stdout',\n hidden: false,\n metadata: {},\n sourceType: 'console',\n logCard,\n };\n this.enqueueLog(log);\n }\n\n getHistory(processId: string): ParsedLog[] {\n return this.buffer.getByProcessId(processId);\n }\n\n getAllHistory(): ParsedLog[] {\n return this.buffer.getAll();\n }\n\n clearHistory(processId?: string): void {\n this.buffer.clear(processId);\n if (processId) {\n this.parsers.delete(processId);\n this.processPids.delete(processId);\n } else {\n this.parsers.clear();\n this.processPids.clear();\n }\n }\n\n /** Clear only the log buffer, preserving parse rules for running processes */\n clearBufferOnly(processId: string): void {\n this.buffer.clear(processId);\n }\n\n private enqueueLog(log: ParsedLog): void {\n this.buffer.push(log);\n this.pendingBatch.push(log);\n if (!this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n\n private flushBatch(): void {\n this.batchScheduled = false;\n if (this.pendingBatch.length === 0) return;\n const batch = this.pendingBatch;\n this.pendingBatch = [];\n this.emit('logs', batch);\n }\n\n private getParser(processId: string): LogParser {\n let parser = this.parsers.get(processId);\n if (!parser) {\n parser = new LogParser();\n this.parsers.set(processId, parser);\n }\n return parser;\n }\n\n private createLog(\n processId: string,\n raw: string,\n stream: 'stdout' | 'stderr',\n sessionCard: ActiveCard | null,\n setSessionCard: (card: ActiveCard | null) => void,\n ): ParsedLog | null {\n // Detect and handle Docker phase markers\n if (raw.startsWith(DOCKER_PHASE_PREFIX)) {\n try {\n const meta = JSON.parse(raw.slice(DOCKER_PHASE_PREFIX.length)) as {\n _dockerPhase: string;\n _cardId: string;\n _cardState?: string;\n message?: string;\n };\n\n if (meta._cardState === 'close') {\n const closing = sessionCard;\n setSessionCard(null);\n if (closing) {\n const directive: LogCardDirective = {\n id: closing.id,\n type: closing.type,\n header: closing.header,\n state: 'close',\n };\n const pid = this.processPids.get(processId) ?? null;\n return {\n id: fastId(),\n processId,\n pid,\n timestamp: new Date(),\n level: 'info',\n message: '',\n raw,\n stream,\n hidden: true,\n sourceType: 'console',\n logCard: directive,\n };\n }\n return null;\n }\n\n const card: ActiveCard = {\n id: meta._cardId,\n type: meta._dockerPhase,\n header: meta.message ?? meta._dockerPhase,\n collapsed: meta._dockerPhase === 'run' || meta._dockerPhase === 'pull' || meta._dockerPhase === 'build' || meta._dockerPhase === 'exec',\n collapsable: true,\n };\n setSessionCard(card);\n const directive: LogCardDirective = {\n id: card.id,\n type: card.type,\n header: card.header,\n collapsable: card.collapsable,\n collapsed: card.collapsed,\n state: 'open',\n };\n const pid = this.processPids.get(processId) ?? null;\n return {\n id: fastId(),\n processId,\n pid,\n timestamp: new Date(),\n level: 'info',\n message: card.header,\n raw,\n stream,\n hidden: true,\n sourceType: 'console',\n logCard: directive,\n };\n } catch {\n // Not a valid marker — fall through to normal parsing\n }\n }\n\n const parsed = this.getParser(processId).parse(raw, stream);\n const pid = this.processPids.get(processId) ?? null;\n\n let logCard: LogCardDirective | undefined;\n if (parsed.json) {\n // JSON logs are always self-contained cards regardless of any active container card\nlogCard = { id: fastId(), type: 'json', header: parsed.jsonHeader ?? 'JSON', state: 'self', collapsable: true };\n } else if (sessionCard) {\n logCard = { id: sessionCard.id, type: sessionCard.type, header: sessionCard.header, state: 'append' };\n }\n\n return {\n id: fastId(),\n processId,\n pid,\n timestamp: new Date(),\n level: parsed.level,\n message: parsed.message,\n raw,\n stream,\n hidden: parsed.hidden,\n metadata: parsed.metadata,\n json: parsed.json,\n sourceType: 'console',\n logCard,\n };\n }\n}\n","import type { LogLevel, LogLine, JSLogParserDef } from '@runeya/packages-shared';\nimport { JSLogParser } from './js-log-parser.js';\n\nconst DEFAULT_LEVEL_PATTERNS: Array<{ pattern: RegExp; level: LogLevel }> = [\n { pattern: /\\b(fatal|FATAL)\\b/, level: 'fatal' },\n { pattern: /\\b(error|ERROR|ERR)\\b/, level: 'error' },\n { pattern: /\\b(warn|WARNING|WARN)\\b/, level: 'warn' },\n { pattern: /\\b(debug|DEBUG|DBG)\\b/, level: 'debug' },\n { pattern: /\\b(info|INFO|INF)\\b/, level: 'info' },\n];\n\nexport class LogParser {\n private jsParser: JSLogParser | null = null;\n\n constructor(jsParsers: JSLogParserDef[] = []) {\n this.setJSParsers(jsParsers);\n }\n\n setJSParsers(jsParsers: JSLogParserDef[]): void {\n if (jsParsers.length > 0) {\n this.jsParser = new JSLogParser(jsParsers);\n } else {\n this.jsParser = null;\n }\n }\n\n parse(raw: string, stream: 'stdout' | 'stderr' = 'stdout'): LogLine {\n // 1. Construct initial LogLine\n let line: LogLine = {\n raw,\n stream,\n level: stream === 'stderr' ? 'error' : 'info',\n message: raw,\n hidden: false,\n metadata: {},\n };\n\n // 2. Step 0: default regex level detection\n line = this.detectLevel(line);\n\n // 3. Run JS parser pipeline (all parsers in order)\n if (this.jsParser) {\n line = this.jsParser.parse(line);\n }\n\n return line;\n }\n\n private detectLevel(line: LogLine): LogLine {\n for (const { pattern, level } of DEFAULT_LEVEL_PATTERNS) {\n if (pattern.test(line.raw)) {\n return { ...line, level };\n }\n }\n return line;\n }\n}\n","import type { ParsedLog } from '@runeya/packages-shared';\nimport { LOG_BUFFER_SIZE } from '@runeya/packages-shared';\n\nexport class LogBuffer {\n private buffer: ParsedLog[] = [];\n private maxSize: number;\n /** Map-based index for O(1) processId lookups */\n private index = new Map<string, ParsedLog[]>();\n\n constructor(maxSize: number = LOG_BUFFER_SIZE) {\n this.maxSize = maxSize;\n }\n\n push(log: ParsedLog): void {\n if (this.buffer.length >= this.maxSize) {\n const evicted = this.buffer.shift()!;\n // Remove evicted entry from index\n const indexed = this.index.get(evicted.processId);\n if (indexed) {\n indexed.shift();\n if (indexed.length === 0) {\n this.index.delete(evicted.processId);\n }\n }\n }\n this.buffer.push(log);\n // Add to index\n let indexed = this.index.get(log.processId);\n if (!indexed) {\n indexed = [];\n this.index.set(log.processId, indexed);\n }\n indexed.push(log);\n }\n\n getAll(): ParsedLog[] {\n return [...this.buffer];\n }\n\n getByProcessId(processId: string): ParsedLog[] {\n const indexed = this.index.get(processId);\n return indexed ? [...indexed] : [];\n }\n\n clear(processId?: string): void {\n if (processId) {\n this.buffer = this.buffer.filter(l => l.processId !== processId);\n this.index.delete(processId);\n } else {\n this.buffer = [];\n this.index.clear();\n }\n }\n\n get size(): number {\n return this.buffer.length;\n }\n}\n","/**\n * Retirer les sequences ANSI d'une ligne de log.\n *\n * Les logs de service sont lus sur un tube, jamais sur un terminal : un\n * programme bien eleve n'y met donc pas de couleurs, et l'interface les affiche\n * en texte brut. Windows fait exception — `picocolors`, dont dependent Vite,\n * Nuxt et une bonne partie de l'ecosysteme, active la couleur des lors que la\n * plateforme est `win32`, sans regarder si la sortie est un terminal. Les codes\n * arrivaient donc jusqu'a l'ecran, lus comme du texte :\n * `ESC[36mi ESC[39m hmr update`.\n *\n * Nettoye ici plutot qu'a l'affichage, parce que la ligne est aussi ce que\n * lisent les analyseurs : un JSON precede d'un code couleur ne se reconnait\n * plus comme du JSON, et un niveau de log ne se retrouve plus derriere un\n * `ESC[31m`. C'est le meme bug, en silencieux.\n *\n * Applique sur toutes les plateformes : une ligne sans echappement ressort\n * telle quelle, et un programme qui force la couleur (`FORCE_COLOR`) est traite\n * partout comme il l'est sous Windows.\n */\n\n/**\n * D'abord OSC (`ESC] ... BEL` ou `ESC] ... ESC\\\\`), dont la charge utile est du\n * texte libre — un titre de fenetre, un lien — et doit etre avalee jusqu'a son\n * terminateur, sans quoi la moitie en ressort a l'ecran. Puis CSI et les\n * echappements a deux caracteres. `\\u009B` est la forme 8 bits du CSI, que\n * certains programmes emettent encore.\n */\n// eslint-disable-next-line no-control-regex\nconst ANSI_PATTERN = /\\u001B\\][^\\u0007\\u001B]*(?:\\u0007|\\u001B\\\\)|[\\u001B\\u009B][[()#;?]*(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nqry=><~]/g;\n\nexport function stripAnsi(line: string): string {\n // Chemin chaud : la quasi-totalite des lignes n'a aucun echappement, et le\n // flux de logs passe ici a chaque ligne de chaque service.\n if (!line.includes('\\u001B') && !line.includes('\\u009B')) return line;\n return line.replace(ANSI_PATTERN, '');\n}\n","import { EventEmitter } from 'node:events';\nimport * as fs from 'node:fs';\nimport * as fsPromises from 'node:fs/promises';\nimport type { ILogSource } from '@runeya/packages-shared';\nimport type { ParsedLog, FileLogSource as FileLogSourceConfig } from '@runeya/packages-shared';\nimport { LogBuffer } from '../log-buffer.js';\nimport { LogParser } from '../log-parser.js';\n\nlet idCounter = 0;\nfunction fastId(): string {\n return 'FLS' + (++idCounter).toString(36);\n}\n\nconst RETRY_ATTEMPTS = 3;\nconst RETRY_DELAY_MS = 5000;\n\nexport class FileLogSource extends EventEmitter implements ILogSource {\n readonly id: string;\n readonly type = 'file' as const;\n\n private config: FileLogSourceConfig;\n private logBuffer: LogBuffer;\n private logParser: LogParser;\n\n private isRunning = false;\n private offset = 0;\n private processId: string | null = null;\n private watcher: fs.FSWatcher | null = null;\n private pendingBatch: ParsedLog[] = [];\n private batchScheduled = false;\n\n constructor(config: FileLogSourceConfig, logBuffer: LogBuffer, logParser: LogParser) {\n super();\n this.id = fastId();\n this.config = config;\n this.logBuffer = logBuffer;\n this.logParser = logParser;\n }\n\n async start(processId: string): Promise<void> {\n if (this.isRunning) return;\n this.isRunning = true;\n this.processId = processId;\n\n // Attempt to open with retries if file doesn't exist yet\n let attempts = 0;\n while (true) {\n try {\n await fsPromises.access(this.config.path, fs.constants.R_OK);\n break;\n } catch (err: unknown) {\n const nodeErr = err as NodeJS.ErrnoException;\n if (nodeErr.code === 'EACCES') {\n this.emitSystemLog(processId, `[FileLogSource] Permission denied: ${this.config.path}`, 'error');\n return;\n }\n if (nodeErr.code === 'ENOENT' && this.config.createIfNotExists) {\n try {\n await fsPromises.mkdir(\n (await import('node:path')).dirname(this.config.path),\n { recursive: true },\n );\n await fsPromises.writeFile(this.config.path, '', { flag: 'a' });\n this.emitSystemLog(processId, `[FileLogSource] File created: ${this.config.path}`, 'info');\n break;\n } catch (createErr: unknown) {\n const ce = createErr as NodeJS.ErrnoException;\n this.emitSystemLog(processId, `[FileLogSource] Failed to create file: ${ce.message}`, 'error');\n return;\n }\n }\n attempts++;\n if (attempts >= RETRY_ATTEMPTS) {\n this.emitSystemLog(processId, `[FileLogSource] File not found after ${RETRY_ATTEMPTS} retries: ${this.config.path}`, 'error');\n return;\n }\n this.emitSystemLog(processId, `[FileLogSource] File not found, retrying in ${RETRY_DELAY_MS}ms: ${this.config.path}`, 'warn');\n await new Promise(r => setTimeout(r, RETRY_DELAY_MS));\n }\n }\n\n // Set initial offset\n if (this.config.startFromEnd) {\n const stat = await fsPromises.stat(this.config.path);\n this.offset = stat.size;\n } else {\n this.offset = 0;\n }\n\n // Watch for changes\n try {\n this.watcher = fs.watch(this.config.path, { persistent: false }, (event) => {\n if (event === 'change') {\n void this.readNewLines(processId);\n } else if (event === 'rename') {\n this.emitSystemLog(processId, `[FileLogSource] File renamed or deleted: ${this.config.path}`, 'error');\n void this.stop();\n }\n });\n\n this.watcher.on('error', (err: NodeJS.ErrnoException) => {\n this.emitSystemLog(processId, `[FileLogSource] Watcher error: ${err.message}`, 'error');\n void this.stop();\n });\n } catch (err: unknown) {\n const nodeErr = err as NodeJS.ErrnoException;\n this.emitSystemLog(processId, `[FileLogSource] Failed to watch file: ${nodeErr.message}`, 'error');\n }\n }\n\n async stop(): Promise<void> {\n this.isRunning = false;\n if (this.watcher) {\n this.watcher.close();\n this.watcher = null;\n }\n }\n\n getHistory(processId: string): ParsedLog[] {\n return this.logBuffer.getByProcessId(processId);\n }\n\n async readNewLines(processId: string): Promise<void> {\n let stat: fs.Stats;\n try {\n stat = await fsPromises.stat(this.config.path);\n } catch {\n return;\n }\n\n // Rotation detection\n if (stat.size < this.offset) {\n this.offset = 0;\n }\n\n if (stat.size === this.offset) return;\n\n const length = stat.size - this.offset;\n const buf = Buffer.alloc(length);\n\n let fd: fsPromises.FileHandle | null = null;\n try {\n fd = await fsPromises.open(this.config.path, 'r');\n await fd.read(buf, 0, length, this.offset);\n } catch {\n return;\n } finally {\n await fd?.close();\n }\n\n this.offset += length;\n\n const encoding = (this.config.encoding || 'utf-8') as BufferEncoding;\n const text = buf.toString(encoding);\n const lines = text.split('\\n');\n\n // Remove trailing empty string from final newline\n if (lines[lines.length - 1] === '') {\n lines.pop();\n }\n\n for (const line of lines) {\n if (!line) continue;\n const parsed = this.logParser.parse(line, 'stdout');\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid: null,\n timestamp: new Date(),\n level: parsed.level,\n message: parsed.message,\n raw: line,\n stream: 'stdout',\n hidden: parsed.hidden,\n metadata: parsed.metadata,\n json: parsed.json,\n sourceType: 'file',\n sourcePath: this.config.path,\n };\n this.logBuffer.push(log);\n this.pendingBatch.push(log);\n }\n\n if (this.pendingBatch.length > 0 && !this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n\n private flushBatch(): void {\n this.batchScheduled = false;\n if (this.pendingBatch.length === 0) return;\n const batch = this.pendingBatch;\n this.pendingBatch = [];\n this.emit('logs', batch);\n }\n\n private emitSystemLog(processId: string, message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid: null,\n timestamp: new Date(),\n level,\n message,\n raw: message,\n stream: 'stderr',\n hidden: false,\n metadata: {},\n sourceType: 'file',\n sourcePath: this.config.path,\n };\n this.logBuffer.push(log);\n this.pendingBatch.push(log);\n if (!this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n}\n","import { EventEmitter } from 'node:events';\nimport type { ILogSource, ParsedLog } from '@runeya/packages-shared';\nimport type { MongoLogSource as MongoLogSourceConfig } from '@runeya/packages-shared';\nimport { LogBuffer } from '../log-buffer.js';\nimport { LogParser } from '../log-parser.js';\nimport type { MongoClient, Collection, Document, WithId } from 'mongodb';\n\nlet idCounter = 0;\nfunction fastId(): string {\n return 'MLS' + (++idCounter).toString(36);\n}\n\nconst POLL_INTERVAL_MS = 5000;\nconst MAX_RETRIES = 5;\nconst BASE_RETRY_DELAY_MS = 1000;\n\nexport class MongoLogSource extends EventEmitter implements ILogSource {\n readonly id: string;\n readonly type = 'mongo' as const;\n\n private config: MongoLogSourceConfig;\n private logBuffer: LogBuffer;\n private logParser: LogParser;\n /** Overridable for tests */\n readonly baseRetryDelayMs: number;\n\n private client: MongoClient | null = null;\n private collection: Collection<Document> | null = null;\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private lastTimestamp: Date | null = null;\n private processId: string | null = null;\n private pendingBatch: ParsedLog[] = [];\n private batchScheduled = false;\n\n constructor(\n config: MongoLogSourceConfig,\n logBuffer: LogBuffer,\n logParser: LogParser,\n { baseRetryDelayMs = BASE_RETRY_DELAY_MS }: { baseRetryDelayMs?: number } = {},\n ) {\n super();\n this.id = fastId();\n this.config = config;\n this.logBuffer = logBuffer;\n this.logParser = logParser;\n this.baseRetryDelayMs = baseRetryDelayMs;\n }\n\n async start(processId: string): Promise<void> {\n this.processId = processId;\n\n const connStr = this.config.connectionString;\n\n let attempt = 0;\n while (attempt < MAX_RETRIES) {\n try {\n const { MongoClient: MC } = await import('mongodb');\n this.client = new MC(connStr, { serverSelectionTimeoutMS: 5000 });\n await this.client.connect();\n const db = this.client.db(this.config.database);\n this.collection = db.collection(this.config.collection);\n break;\n } catch (err: unknown) {\n attempt++;\n const msg = err instanceof Error ? err.message : String(err);\n this.emitSystemLog(processId, `[MongoLogSource] Connection failed (attempt ${attempt}/${MAX_RETRIES}): ${msg}`, 'warn');\n if (attempt >= MAX_RETRIES) {\n this.emitSystemLog(processId, `[MongoLogSource] Giving up after ${MAX_RETRIES} attempts`, 'error');\n return;\n }\n const delay = Math.min(this.baseRetryDelayMs * 2 ** attempt, 30000);\n await new Promise(r => setTimeout(r, delay));\n }\n }\n\n this.lastTimestamp = new Date();\n this.pollTimer = setInterval(() => void this.poll(processId), POLL_INTERVAL_MS);\n // Run first poll immediately\n await this.poll(processId);\n }\n\n async stop(): Promise<void> {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.client) {\n await this.client.close();\n this.client = null;\n this.collection = null;\n }\n }\n\n getHistory(processId: string): ParsedLog[] {\n return this.logBuffer.getByProcessId(processId);\n }\n\n private async poll(processId: string): Promise<void> {\n if (!this.collection) return;\n\n const tsField = this.config.timestampField;\n const msgField = this.config.messageField;\n const lvlField = this.config.levelField;\n\n const query: Record<string, unknown> = { ...this.config.filter };\n if (this.lastTimestamp) {\n query[tsField] = { $gt: this.lastTimestamp };\n }\n\n let docs: WithId<Document>[];\n try {\n docs = await this.collection.find(query).sort({ [tsField]: 1 }).toArray();\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n this.emitSystemLog(processId, `[MongoLogSource] Poll error: ${msg}`, 'error');\n return;\n }\n\n for (const doc of docs) {\n const rawMessage = String(doc[msgField] ?? '');\n const parsed = this.logParser.parse(rawMessage, 'stdout');\n\n let level = parsed.level;\n if (lvlField && doc[lvlField]) {\n const docLevel = String(doc[lvlField]).toLowerCase();\n if (['debug', 'info', 'warn', 'error', 'fatal'].includes(docLevel)) {\n level = docLevel as ParsedLog['level'];\n }\n }\n\n const docTimestamp = doc[tsField];\n const timestamp = docTimestamp instanceof Date ? docTimestamp : new Date();\n\n if (timestamp > (this.lastTimestamp ?? new Date(0))) {\n this.lastTimestamp = timestamp;\n }\n\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid: null,\n timestamp,\n level,\n message: rawMessage,\n raw: rawMessage,\n stream: 'stdout',\n hidden: false,\n metadata: parsed.metadata,\n json: parsed.json,\n sourceType: 'mongo',\n };\n\n this.logBuffer.push(log);\n this.pendingBatch.push(log);\n }\n\n if (this.pendingBatch.length > 0 && !this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n\n private flushBatch(): void {\n this.batchScheduled = false;\n if (this.pendingBatch.length === 0) return;\n const batch = this.pendingBatch;\n this.pendingBatch = [];\n this.emit('logs', batch);\n }\n\n private emitSystemLog(processId: string, message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid: null,\n timestamp: new Date(),\n level,\n message,\n raw: message,\n stream: 'stderr',\n hidden: false,\n metadata: {},\n sourceType: 'mongo',\n };\n this.logBuffer.push(log);\n this.pendingBatch.push(log);\n if (!this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n}\n","import { EventEmitter } from 'node:events';\nimport { createConnection, type Connection, type RowDataPacket } from 'mysql2/promise';\nimport type { ILogSource, ParsedLog, MySQLLogSource as MySQLLogSourceConfig } from '@runeya/packages-shared';\nimport type { LogBuffer } from '../log-buffer.js';\nimport type { LogParser } from '../log-parser.js';\n\nlet logIdCounter = 0;\nfunction fastId(): string {\n return 'ML' + (++logIdCounter).toString(36);\n}\n\nconst MAX_RETRIES = 5;\nconst RETRY_BASE_MS = 500;\n\nfunction parseLevel(val: unknown): 'debug' | 'info' | 'warn' | 'error' | 'fatal' {\n if (typeof val !== 'string') return 'info';\n const v = val.toLowerCase();\n if (v === 'fatal') return 'fatal';\n if (v === 'error' || v === 'err') return 'error';\n if (v === 'warn' || v === 'warning') return 'warn';\n if (v === 'debug' || v === 'dbg') return 'debug';\n return 'info';\n}\n\nfunction rowToLog(\n row: RowDataPacket,\n config: MySQLLogSourceConfig,\n processId: string,\n): ParsedLog {\n const rawTimestamp = row[config.timestampColumn];\n const timestamp =\n rawTimestamp instanceof Date\n ? rawTimestamp\n : new Date(rawTimestamp != null ? String(rawTimestamp) : Date.now());\n\n const message =\n row[config.messageColumn] != null\n ? String(row[config.messageColumn])\n : JSON.stringify(row);\n\n const level = config.levelColumn ? parseLevel(row[config.levelColumn]) : 'info';\n\n return {\n id: fastId(),\n processId,\n timestamp,\n level,\n message,\n raw: JSON.stringify(row),\n stream: 'stdout',\n hidden: false,\n sourceType: 'mysql',\n sourcePath: `${config.host}:${config.port}/${config.database}/${config.table}`,\n };\n}\n\nexport class MySQLLogSource extends EventEmitter implements ILogSource {\n readonly id: string;\n readonly type = 'mysql' as const;\n\n private lastTimestamp: Date = new Date(0);\n private pollTimer: NodeJS.Timeout | null = null;\n private connection: Connection | null = null;\n private retryCount = 0;\n private stopped = false;\n\n constructor(\n private readonly config: MySQLLogSourceConfig,\n private readonly logBuffer: LogBuffer,\n private readonly _logParser: LogParser,\n ) {\n super();\n this.id = `mysql-${config.host}-${config.database}-${config.table}-${Date.now()}`;\n }\n\n async start(processId: string): Promise<void> {\n this.stopped = false;\n this.lastTimestamp = new Date();\n await this.connect();\n this.schedulePoll(processId);\n }\n\n private async connect(): Promise<void> {\n this.connection = await createConnection({\n host: this.config.host,\n port: this.config.port,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n });\n }\n\n private schedulePoll(processId: string): void {\n if (this.stopped) return;\n this.pollTimer = setTimeout(() => {\n this.poll(processId).catch((err: Error) => {\n console.error('[mysql-log-source] Poll error for', this.id + ':', err.message);\n });\n }, this.config.pollIntervalMs);\n }\n\n private async poll(processId: string): Promise<void> {\n if (this.stopped) return;\n\n try {\n const rows = await this.executeQuery();\n if (rows.length > 0) {\n const batch: ParsedLog[] = [];\n for (const row of rows) {\n const log = rowToLog(row, this.config, processId);\n this.logBuffer.push(log);\n batch.push(log);\n\n const rawTs = row[this.config.timestampColumn];\n const ts = rawTs instanceof Date ? rawTs : new Date(rawTs != null ? String(rawTs) : Date.now());\n if (ts > this.lastTimestamp) {\n this.lastTimestamp = ts;\n }\n }\n this.emit('logs', batch);\n }\n this.retryCount = 0;\n } catch (err) {\n const error = err as Error;\n this.retryCount++;\n console.error(\n '[mysql-log-source] Query error (attempt ' + this.retryCount + '/' + MAX_RETRIES + ') for', this.id + ':', // nosemgrep: unsafe-formatstring\n error.message,\n );\n\n if (this.retryCount < MAX_RETRIES) {\n const delay = RETRY_BASE_MS * Math.pow(2, this.retryCount - 1);\n await this.reconnect(delay);\n } else {\n console.error(`[mysql-log-source] Max retries reached for ${this.id}, giving up.`);\n return;\n }\n }\n\n this.schedulePoll(processId);\n }\n\n private async executeQuery(): Promise<RowDataPacket[]> {\n if (!this.connection) throw new Error('No MySQL connection');\n\n if (this.config.query) {\n const [rows] = await this.connection.execute<RowDataPacket[]>(\n this.config.query,\n [this.lastTimestamp],\n );\n return rows;\n }\n\n const ts = this.config.timestampColumn;\n const table = this.config.table;\n const sql = `SELECT * FROM \\`${table}\\` WHERE \\`${ts}\\` > ? ORDER BY \\`${ts}\\` ASC`;\n const [rows] = await this.connection.execute<RowDataPacket[]>(sql, [this.lastTimestamp]);\n return rows;\n }\n\n private async reconnect(delayMs: number): Promise<void> {\n try {\n await this.connection?.end();\n } catch { /* ignore */ }\n this.connection = null;\n\n await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n if (this.stopped) return;\n\n try {\n await this.connect();\n } catch (err) {\n console.error('[mysql-log-source] Reconnect failed for', this.id + ':', (err as Error).message);\n }\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n try {\n await this.connection?.end();\n } catch { /* ignore */ }\n this.connection = null;\n }\n\n getHistory(processId: string): ParsedLog[] {\n return this.logBuffer.getByProcessId(processId);\n }\n}\n","import type { ILogSource, LogSourceConfig } from '@runeya/packages-shared';\nimport { ConsoleLogSource } from './console-log-source.js';\nimport { FileLogSource } from './file-log-source.js';\nimport { MongoLogSource } from './mongo-log-source.js';\nimport { MySQLLogSource } from './mysql-log-source.js';\nimport type { LogBuffer } from '../log-buffer.js';\nimport type { LogParser } from '../log-parser.js';\n\n/**\n * Factory function to create an ILogSource implementation from a config object.\n *\n * For `console`, a new ConsoleLogSource is created (manages its own internal buffer).\n * For all other types, the provided logBuffer and logParser are injected.\n *\n * @param config - Discriminated-union config from the service's logSources array\n * @param logBuffer - Shared buffer used by file/mongo/mysql sources\n * @param logParser - LogParser instance (unused by DB sources but passed for consistency)\n */\nexport function createLogSource(\n config: LogSourceConfig,\n logBuffer: LogBuffer,\n logParser: LogParser,\n): ILogSource {\n switch (config.type) {\n case 'console':\n return new ConsoleLogSource();\n case 'file':\n return new FileLogSource(config, logBuffer, logParser);\n case 'mongo':\n return new MongoLogSource(config, logBuffer, logParser);\n case 'mysql':\n return new MySQLLogSource(config, logBuffer, logParser);\n default: {\n // Exhaustiveness check — TypeScript will flag missing cases at compile time\n const _exhaustive: never = config;\n throw new Error(`Unknown log source type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n}\n","import pidusage from 'pidusage';\nimport { execFile } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\nimport type { ProcessMetrics } from '@runeya/packages-shared';\nimport { METRICS_INTERVAL } from '@runeya/packages-shared';\nimport { processStore } from './process-store.js';\n\n/** Parse `docker stats --no-stream --format json` output for a single container. */\nasync function getDockerStats(containerName: string): Promise<{ cpu: number; memory: number } | null> {\n return new Promise((resolve) => {\n execFile(\n 'docker',\n ['stats', '--no-stream', '--format', '{{json .}}', containerName],\n { timeout: 5000, windowsHide: true },\n (err, stdout) => {\n if (err || !stdout.trim()) { resolve(null); return; }\n try {\n const data = JSON.parse(stdout.trim()) as { CPUPerc: string; MemUsage: string };\n // parseFloat s'arrête au premier caractère non numérique : le « % » final tombe.\n const cpu = Number.parseFloat(data.CPUPerc);\n // MemUsage format: \"123MiB / 2GiB\" — take the left side\n const memStr = data.MemUsage.split('/')[0].trim();\n const memory = parseMemBytes(memStr);\n resolve({ cpu: Number.isNaN(cpu) ? 0 : cpu, memory });\n } catch {\n resolve(null);\n }\n },\n );\n });\n}\n\n/** Convert docker memory string (e.g. \"123MiB\", \"1.5GiB\", \"512kB\") to bytes. */\nfunction parseMemBytes(str: string): number {\n const m = str.match(/^([\\d.]+)\\s*(B|kB|MB|MiB|GiB|GB)$/i);\n if (!m) return 0;\n const val = Number.parseFloat(m[1]);\n const unit = m[2].toLowerCase();\n const multipliers: Record<string, number> = {\n b: 1, kb: 1e3, mb: 1e6, mib: 1024 * 1024, gib: 1024 ** 3, gb: 1e9,\n };\n return Math.round(val * (multipliers[unit] ?? 1));\n}\n\nexport class MetricsCollector extends EventEmitter {\n private intervals = new Map<string, ReturnType<typeof setInterval>>();\n private intervalMs: number;\n\n constructor(intervalMs: number = METRICS_INTERVAL) {\n super();\n this.intervalMs = intervalMs;\n }\n\n /** Start collecting metrics for a native process (by PID). */\n startCollecting(processId: string, pid: number): void {\n this.stopCollecting(processId);\n\n const interval = setInterval(async () => {\n try {\n const stats = await pidusage(pid);\n const metrics: ProcessMetrics = {\n processId,\n cpu: stats.cpu,\n memory: stats.memory,\n timestamp: new Date().toISOString(),\n };\n this.emit('metrics', metrics);\n } catch {\n // Process might have exited, stop collecting\n this.stopCollecting(processId);\n }\n }, this.intervalMs);\n\n this.intervals.set(processId, interval);\n }\n\n /** Start collecting metrics for a Docker container (by container name). */\n startCollectingDocker(processId: string, containerName: string): void {\n this.stopCollecting(processId);\n\n const interval = setInterval(async () => {\n const stats = await getDockerStats(containerName);\n if (!stats) {\n this.stopCollecting(processId);\n return;\n }\n const metrics: ProcessMetrics = {\n processId,\n cpu: stats.cpu,\n memory: stats.memory,\n timestamp: new Date().toISOString(),\n };\n this.emit('metrics', metrics);\n }, this.intervalMs);\n\n this.intervals.set(processId, interval);\n }\n\n /** Stop collecting metrics for a process */\n stopCollecting(processId: string): void {\n const interval = this.intervals.get(processId);\n if (interval) {\n clearInterval(interval);\n this.intervals.delete(processId);\n }\n }\n\n /** Get current metrics for a process (one-shot, uses first active PID or container name). */\n async getMetrics(processId: string): Promise<ProcessMetrics | null> {\n const proc = processStore.get(processId);\n if (!proc) return null;\n\n // Try native PID first\n const activePid = proc.commandProcesses.find(cp => cp.pid !== null)?.pid;\n if (activePid) {\n try {\n const stats = await pidusage(activePid);\n return {\n processId,\n cpu: stats.cpu,\n memory: stats.memory,\n timestamp: new Date().toISOString(),\n };\n } catch {\n // fall through to Docker\n }\n }\n\n // Try Docker container name\n const containerName = proc.commandProcesses.find(cp => cp.containerName)?.containerName;\n if (containerName) {\n const stats = await getDockerStats(containerName);\n if (stats) {\n return { processId, ...stats, timestamp: new Date().toISOString() };\n }\n }\n\n return null;\n }\n\n /** Stop all collection intervals */\n stopAll(): void {\n for (const [id] of this.intervals) {\n this.stopCollecting(id);\n }\n }\n}\n","import { EventEmitter } from 'node:events';\nimport { execa } from 'execa';\nimport * as shellwordsModule from 'shellwords';\nimport { HEALTH_CHECK_INTERVAL, HEALTH_CHECK_INITIAL_DELAY } from '@runeya/packages-shared';\nimport { processStore } from './process-store.js';\nimport { resolveCwd } from '../utils/env.js';\n\nconst shellwordsSplit = (shellwordsModule as { split: (str: string) => string[] }).split;\n\n/**\n * Build a safe environment for health check commands.\n * SECURITY: Never spread ...process.env — only pass system-essential variables\n * plus the service's explicit env config.\n */\nfunction buildHealthCheckEnv(serviceEnv: Record<string, string> = {}): Record<string, string> {\n const safeKeys = ['PATH', 'HOME', 'USER', 'SHELL', 'LANG', 'TERM', 'TMPDIR', 'TZ'];\n const env: Record<string, string> = {};\n for (const key of safeKeys) {\n if (process.env[key]) {\n env[key] = process.env[key]!;\n }\n }\n return { ...env, ...serviceEnv };\n}\n\ninterface HealthResult {\n processId: string;\n status: 'healthy' | 'unhealthy' | 'unknown';\n lastCheck: Date;\n consecutiveFailures: number;\n}\n\nclass HealthChecker extends EventEmitter {\n private timers: Map<string, ReturnType<typeof setInterval>> = new Map();\n private results: Map<string, HealthResult> = new Map();\n private failureCounts: Map<string, number> = new Map();\n private initialTimers: Map<string, ReturnType<typeof setTimeout>> = new Map();\n\n constructor() {\n super();\n // Allow many listeners since ProcessManager instances register on this singleton\n this.setMaxListeners(50);\n }\n\n /** Start health checking for a process */\n startChecking(processId: string): void {\n const proc = processStore.get(processId);\n if (!proc) return;\n const healthConfig = proc.serviceConfig.healthCheck;\n if (!healthConfig) return;\n\n const type = healthConfig.type ?? 'http';\n\n // Validate required fields based on type\n if (type === 'http' && !healthConfig.path) return;\n if (type === 'command' && !healthConfig.command) return;\n\n // Stop existing timer if any\n this.stopChecking(processId);\n\n this.results.set(processId, {\n processId,\n status: 'unknown',\n lastCheck: new Date(),\n consecutiveFailures: 0,\n });\n this.failureCounts.set(processId, 0);\n\n const interval = healthConfig.interval ?? HEALTH_CHECK_INTERVAL;\n const timeout = healthConfig.timeout ?? 5_000;\n const maxRetries = healthConfig.retries ?? 3;\n const initialDelay = healthConfig.initialDelay ?? HEALTH_CHECK_INITIAL_DELAY;\n\n const runCheck = type === 'command'\n ? () => this.checkCommand(processId, healthConfig.command!, timeout, maxRetries)\n : () => this.checkHttp(processId, healthConfig.path!, timeout, maxRetries, healthConfig.method ?? 'GET', healthConfig.expectedStatus ?? 200);\n\n // Initial check after a configurable delay (let process start)\n const initialTimer = setTimeout(runCheck, initialDelay);\n this.initialTimers.set(processId, initialTimer);\n\n // Periodic checks\n const timer = setInterval(runCheck, interval);\n this.timers.set(processId, timer);\n }\n\n /** Stop health checking for a process */\n stopChecking(processId: string): void {\n const timer = this.timers.get(processId);\n if (timer) {\n clearInterval(timer);\n this.timers.delete(processId);\n }\n const initialTimer = this.initialTimers.get(processId);\n if (initialTimer) {\n clearTimeout(initialTimer);\n this.initialTimers.delete(processId);\n }\n this.failureCounts.delete(processId);\n this.results.delete(processId);\n }\n\n /** Get current health result */\n getHealthResult(processId: string): HealthResult | null {\n return this.results.get(processId) ?? null;\n }\n\n /** Get health status string */\n getHealthStatus(processId: string): 'healthy' | 'unhealthy' | 'unknown' {\n return this.results.get(processId)?.status ?? 'unknown';\n }\n\n /** Stop all health checks */\n stopAll(): void {\n for (const id of this.timers.keys()) {\n this.stopChecking(id);\n }\n }\n\n private async checkHttp(\n processId: string,\n path: string,\n timeout: number,\n maxRetries: number,\n method: string = 'GET',\n expectedStatus: number = 200,\n ): Promise<void> {\n const proc = processStore.get(processId);\n if (!proc || proc.state !== 'running') {\n this.updateResult(processId, 'unknown', 0);\n return;\n }\n\n const port = proc.serviceConfig.ports?.[0];\n if (!port) {\n // No port configured, can't health check\n this.updateResult(processId, 'unknown', 0);\n return;\n }\n\n const url = `http://localhost:${port}${path}`;\n let failures = this.failureCounts.get(processId) ?? 0;\n\n try {\n const response = await fetch(url, {\n method,\n signal: AbortSignal.timeout(timeout),\n });\n if (response.status === expectedStatus) {\n failures = 0;\n this.failureCounts.set(processId, 0);\n this.updateResult(processId, 'healthy', failures);\n } else {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n }\n } catch {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n }\n }\n\n private async checkCommand(\n processId: string,\n command: string,\n timeout: number,\n maxRetries: number,\n ): Promise<void> {\n const proc = processStore.get(processId);\n if (!proc || proc.state !== 'running') {\n this.updateResult(processId, 'unknown', 0);\n return;\n }\n\n let failures = this.failureCounts.get(processId) ?? 0;\n\n try {\n const args: string[] = shellwordsSplit(command);\n const cmd = args.shift();\n if (!cmd) {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n return;\n }\n\n const serviceEnv = proc.serviceConfig.env ?? {};\n const cwd = resolveCwd(proc.serviceConfig.resolvedCwd ?? proc.serviceConfig.cwd, serviceEnv);\n const env = buildHealthCheckEnv(serviceEnv);\n const result = await execa(cmd, args, {\n cwd,\n env,\n shell: false,\n timeout,\n reject: false,\n });\n\n if (result.exitCode === 0) {\n failures = 0;\n this.failureCounts.set(processId, 0);\n this.updateResult(processId, 'healthy', failures);\n } else {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n }\n } catch {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n }\n }\n\n private updateResult(\n processId: string,\n status: 'healthy' | 'unhealthy' | 'unknown',\n consecutiveFailures: number,\n ): void {\n const result: HealthResult = {\n processId,\n status,\n lastCheck: new Date(),\n consecutiveFailures,\n };\n this.results.set(processId, result);\n this.emit('health', result);\n }\n}\n\nexport const healthChecker = new HealthChecker();\n","import { homedir } from 'node:os';\nimport { resolvePassthroughEnv } from '../trpc/routers/config.js';\n\n/**\n * Merge passthrough env (server-pushed) with an optional per-service env.\n * Priority: serviceEnv > passthroughEnv.\n */\nexport function resolveEnv(serviceEnv?: Record<string, string>): Record<string, string> {\n return { ...resolvePassthroughEnv(), ...serviceEnv };\n}\n\n/**\n * Expand $VAR, ${VAR}, and leading ~ in a string using resolveEnv(serviceEnv).\n * Unresolved references are left as-is.\n */\nexport function expandEnvVar(str: string, serviceEnv?: Record<string, string>): string {\n const env = resolveEnv(serviceEnv);\n return str\n .replace(/^~(\\/|$)/, `${env['HOME'] ?? homedir()}$1`)\n .replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (match, braced, plain) => env[braced ?? plain] ?? match);\n}\n\n/** Resolve a cwd string: expand env vars, fallback to '.' if empty/undefined. */\nexport function resolveCwd(cwd: string | undefined, serviceEnv?: Record<string, string>): string {\n if (!cwd) return '.';\n return expandEnvVar(cwd, serviceEnv) || '.';\n}\n","import { z } from 'zod';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { traefikManager } from '../../services/traefik-manager.js';\nimport { TraefikConfigSchema } from '@runeya/packages-shared';\n\n// In-memory passthrough state — set by server, read by process-manager\nlet passthroughEnvNames: string[] = [];\nlet passthroughEnvValues: Record<string, string> = {};\n\n/**\n * Resolve passthrough env: uses server-pushed values first,\n * falls back to agent's own process.env for each configured name.\n */\nexport function resolvePassthroughEnv(): Record<string, string> {\n const result: Record<string, string> = {};\n for (const name of passthroughEnvNames) {\n const value = passthroughEnvValues[name] ?? process.env[name];\n if (value !== undefined) {\n result[name] = value;\n }\n }\n return result;\n}\n\nexport const configRouter = router({\n setPassthroughEnv: protectedProcedure\n .input(z.object({\n names: z.array(\n z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(256),\n ).max(100),\n values: z.record(\n z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(256),\n z.string().max(32768),\n ).refine(obj => Object.keys(obj).length <= 100, 'Too many values').optional(),\n }))\n .mutation(({ input }) => {\n passthroughEnvNames = input.names;\n passthroughEnvValues = input.values ?? {};\n console.log(`[config] Passthrough env updated: ${input.names.length} variable(s), ${Object.keys(passthroughEnvValues).length} resolved value(s)`);\n return { success: true };\n }),\n\n getPassthroughEnv: protectedProcedure\n .query(() => {\n return resolvePassthroughEnv();\n }),\n\n setTraefikConfig: protectedProcedure\n .input(TraefikConfigSchema)\n .mutation(async ({ input }) => {\n await traefikManager.applyConfig(input);\n console.log(`[config] Traefik config applied: enabled=${input.enabled}`);\n return { success: true };\n }),\n\n getTraefikStatus: protectedProcedure\n .query(async () => {\n return traefikManager.getStatus();\n }),\n\n initTraefikConfig: protectedProcedure\n .input(TraefikConfigSchema)\n .mutation(({ input }) => {\n traefikManager.setConfig(input);\n return { success: true };\n }),\n\n restartTraefik: protectedProcedure\n .mutation(async () => {\n await traefikManager.restart();\n return { success: true };\n }),\n\n renewTraefikCert: protectedProcedure\n .mutation(async () => {\n await traefikManager.forceRenewCert();\n return { success: true };\n }),\n\n getTraefikConfigFiles: protectedProcedure\n .query(async () => {\n return traefikManager.getConfigFiles();\n }),\n\n getTraefikFileTree: protectedProcedure\n .query(async () => {\n return traefikManager.getFileTree();\n }),\n\n getTraefikLogs: protectedProcedure\n .input(z.object({ lines: z.number().int().min(1).max(500).default(100) }))\n .query(async ({ input }) => {\n const logs = await traefikManager.getLogs(input.lines);\n return { logs };\n }),\n});\n","import { spawn, execFile } from 'node:child_process';\nimport type { ChildProcess } from 'node:child_process';\nimport { mkdir, writeFile, rename, chmod, access, readFile } from 'node:fs/promises';\nimport { X509Certificate } from 'node:crypto';\nimport { join } from 'node:path';\nimport { homedir, platform } from 'node:os';\nimport { processStore } from './process-store.js';\n\ninterface TraefikConfig {\n enabled: boolean;\n acmeEmail?: string;\n wildcardDomain?: string;\n httpPort?: number;\n httpsPort?: number;\n dnsProvider?: string;\n dnsCredentials?: Record<string, string>;\n acmeStaging?: boolean;\n}\n\nclass TraefikManager {\n private process: ChildProcess | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private config: TraefikConfig | null = null;\n private dataDir: string = join(homedir(), '.runeya');\n\n private get traefikDir(): string {\n return join(this.dataDir, 'traefik');\n }\n\n private get dynamicDir(): string {\n return join(this.traefikDir, 'dynamic');\n }\n\n private get staticConfigPath(): string {\n return join(this.traefikDir, 'traefik.yml');\n }\n\n private get dynamicConfigPath(): string {\n return join(this.dynamicDir, 'services.yml');\n }\n\n private get acmeStorePath(): string {\n return join(this.traefikDir, 'acme.json');\n }\n\n private async atomicWrite(filePath: string, content: string): Promise<void> {\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, content, 'utf-8');\n await rename(tmpPath, filePath);\n }\n\n async applyConfig(config: TraefikConfig): Promise<void> {\n this.config = config;\n\n if (!config.enabled) {\n await this.stop();\n return;\n }\n\n await mkdir(this.dynamicDir, { recursive: true });\n await this.writeStaticConfig(config);\n await this.regenerateDynamic();\n\n // Restart container with new config\n await this.stop();\n await this.spawnTraefik(config);\n }\n\n /**\n * Escape a string for safe embedding inside a YAML double-quoted scalar.\n * Removes control characters (including newlines) and escapes backslashes and double-quotes.\n */\n private safeYamlStr(value: string): string {\n return value\n .replaceAll(/[\\x00-\\x1f\\x7f]/g, '') // strip control chars / newlines\n .replaceAll('\\\\', '\\\\\\\\') // escape backslashes\n .replaceAll('\"', '\\\\\"'); // escape double-quotes\n }\n\n private async writeStaticConfig(config: TraefikConfig): Promise<void> {\n const acmeEmail = this.safeYamlStr(config.acmeEmail ?? '');\n const dnsProvider = this.safeYamlStr(config.dnsProvider ?? '');\n\n const yaml = [\n `entryPoints:`,\n ` web:`,\n ` address: \":80\"`,\n ` http:`,\n ` redirections:`,\n ` entryPoint:`,\n ` to: websecure`,\n ` scheme: https`,\n ` websecure:`,\n ` address: \":443\"`,\n ``,\n `certificatesResolvers:`,\n ` letsencrypt:`,\n ` acme:`,\n ` email: \"${acmeEmail}\"`,\n ` storage: \"/acme.json\"`,\n ` dnsChallenge:`,\n ` provider: \"${dnsProvider}\"`,\n ...(config.acmeStaging ? [` caServer: \"https://acme-staging-v02.api.letsencrypt.org/directory\"`] : []),\n ``,\n `providers:`,\n ` file:`,\n ` directory: \"/etc/traefik/dynamic\"`,\n ` watch: true`,\n ].join('\\n');\n\n await this.atomicWrite(this.staticConfigPath, yaml);\n }\n\n async regenerateDynamic(): Promise<void> {\n await mkdir(this.dynamicDir, { recursive: true });\n const processes = processStore.getAll();\n const entries = processes.flatMap(p =>\n (p.serviceConfig.localUrls ?? []).map(lu => ({ url: lu.url, port: lu.port }))\n );\n\n // Sanitize wildcardDomain: only allow valid hostname characters.\n const wildcardDomainRaw = this.config?.wildcardDomain?.replace(/^\\*\\./, '');\n const wildcardDomain = wildcardDomainRaw?.replaceAll(/[^a-z0-9.-]/gi, '') || undefined;\n if (wildcardDomainRaw && wildcardDomain !== wildcardDomainRaw) {\n console.warn('[traefik-manager] wildcardDomain contained unsafe characters and was rejected');\n }\n const backendHost = platform() === 'linux' ? '127.0.0.1' : 'host.docker.internal';\n\n const routers: string[] = [];\n const backends: string[] = [];\n\n // Inject a permanent wildcard route so Traefik always requests the wildcard cert via DNS-01,\n // even when no user services have localUrls configured yet.\n if (wildcardDomain) {\n routers.push(\n ` acme-wildcard:`,\n ` rule: \"Host(\\`probe.${wildcardDomain}\\`)\"`,\n ` entryPoints:`,\n ` - websecure`,\n ` service: acme-wildcard`,\n ` tls:`,\n ` certResolver: letsencrypt`,\n ` domains:`,\n ` - main: \"*.${wildcardDomain}\"`,\n );\n backends.push(\n ` acme-wildcard:`,\n ` loadBalancer:`,\n ` servers:`,\n ` - url: \"http://${backendHost}:1\"`,\n );\n }\n\n for (const { url, port } of entries) {\n // Sanitize url: only allow valid hostname characters (letters, digits, dots, hyphens)\n // to prevent YAML/Traefik rule injection via crafted service localUrls.\n const safeUrl = url.replaceAll(/[^a-z0-9.-]/gi, '');\n if (!safeUrl || safeUrl !== url) {\n console.warn(`[traefik-manager] Skipping localUrl with unsafe characters: ${url}`);\n continue;\n }\n const routerName = url.replaceAll(/[^a-z0-9]/gi, '-');\n // Extract the root domain to reuse the wildcard cert (e.g. test.local.runeya.dev → *.local.runeya.dev)\n const parts = url.split('.');\n const wildcardForUrl = parts.length >= 2 ? `*.${parts.slice(1).join('.')}` : null;\n routers.push(\n ` ${routerName}:`,\n ` rule: \"Host(\\`${safeUrl}\\`)\"`,\n ` entryPoints:`,\n ` - websecure`,\n ` service: ${routerName}`,\n ` tls:`,\n ` certResolver: letsencrypt`,\n ...(wildcardForUrl ? [\n ` domains:`,\n ` - main: \"${wildcardForUrl}\"`,\n ] : []),\n );\n backends.push(\n ` ${routerName}:`,\n ` loadBalancer:`,\n ` servers:`,\n ` - url: \"http://${backendHost}:${port}\"`,\n );\n }\n\n if (routers.length === 0) {\n await this.atomicWrite(this.dynamicConfigPath, '');\n return;\n }\n\n const yaml = [\n `http:`,\n ` routers:`,\n ...routers,\n ` services:`,\n ...backends,\n ].join('\\n');\n\n await this.atomicWrite(this.dynamicConfigPath, yaml);\n }\n\n scheduleDynamicRegen(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n this.regenerateDynamic().catch(err =>\n console.error('[traefik-manager] Failed to regenerate dynamic config:', err),\n );\n this.debounceTimer = null;\n }, 500);\n }\n\n private async ensureAcmeJson(): Promise<void> {\n try {\n await writeFile(this.acmeStorePath, '{}', { flag: 'wx' });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n }\n await chmod(this.acmeStorePath, 0o600);\n }\n\n private spawnedAt = 0;\n\n private async spawnTraefik(config: TraefikConfig): Promise<void> {\n const credentials = config.dnsCredentials ?? {};\n const envFlags = Object.entries(credentials).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n\n await this.ensureAcmeJson();\n\n const generation = ++this.spawnedAt;\n\n const isLinux = platform() === 'linux';\n const networkArgs = isLinux\n ? ['--network', 'host']\n : ['-p', `${config.httpPort ?? 80}:80`, '-p', `${config.httpsPort ?? 443}:443`, '--add-host', 'host.docker.internal:host-gateway'];\n\n const args = [\n 'run', '--rm',\n '--name', 'runeya-traefik',\n ...networkArgs,\n '-v', `${this.traefikDir}:/etc/traefik`,\n '-v', `${this.acmeStorePath}:/acme.json`,\n ...envFlags,\n 'traefik:v3',\n ];\n\n this.process = spawn('docker', args, {\n windowsHide: true,\n shell: false,\n detached: false,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n this.process.stdout?.on('data', (data: Buffer) => {\n console.log('[traefik]', data.toString().trim());\n });\n\n this.process.stderr?.on('data', (data: Buffer) => {\n console.error('[traefik]', data.toString().trim());\n });\n\n this.process.on('error', (err) => {\n if (generation !== this.spawnedAt) return;\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n console.error('[traefik-manager] docker not found in PATH. Is Docker installed?');\n } else {\n console.error('[traefik-manager] Traefik container error:', err);\n }\n this.process = null;\n });\n\n this.process.on('exit', (code) => {\n if (generation !== this.spawnedAt) return;\n console.log(`[traefik-manager] Traefik container exited with code ${code}`);\n this.process = null;\n });\n\n console.log('[traefik-manager] Traefik container started (--network host)');\n }\n\n async stop(): Promise<void> {\n // Invalidate current generation so stale exit handlers don't null out the new process\n this.spawnedAt++;\n if (this.process) {\n this.process.kill('SIGTERM');\n this.process = null;\n }\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n // Force-remove the container whether it was started by us or externally\n await new Promise<void>((resolve) => {\n execFile('docker', ['rm', '-f', 'runeya-traefik'], { timeout: 10000, windowsHide: true }, () => resolve());\n });\n // Brief pause to let the port release before a potential restart\n await new Promise(resolve => setTimeout(resolve, 500));\n }\n\n async getConfigFiles(): Promise<{ static: string; dynamic: string }> {\n const [staticContent, dynamicContent] = await Promise.all([\n readFile(this.staticConfigPath, 'utf-8').catch(() => '(fichier absent)'),\n readFile(this.dynamicConfigPath, 'utf-8').catch(() => '(fichier absent)'),\n ]);\n return { static: staticContent, dynamic: dynamicContent };\n }\n\n async getFileTree(): Promise<Array<{ path: string; content: string }>> {\n const result: Array<{ path: string; content: string }> = [];\n const walk = async (dir: string, base: string) => {\n let entries: string[];\n try {\n const { readdir } = await import('node:fs/promises');\n entries = await readdir(dir);\n } catch { return; }\n for (const entry of entries) {\n const full = join(dir, entry);\n const rel = join(base, entry);\n try {\n const { stat } = await import('node:fs/promises');\n const s = await stat(full);\n if (s.isDirectory()) {\n await walk(full, rel);\n } else {\n const content = await readFile(full, 'utf-8').catch(() => '(lecture impossible)');\n result.push({ path: rel, content });\n }\n } catch { /* skip */ }\n }\n };\n await walk(this.traefikDir, '');\n return result;\n }\n\n async getLogs(lines = 100): Promise<string> {\n return new Promise((resolve) => {\n execFile('docker', ['logs', '--tail', String(lines), 'runeya-traefik'], { timeout: 10000, windowsHide: true }, (err, stdout, stderr) => {\n if (err) { resolve(''); return; }\n // Docker writes its own logs to stderr by default\n resolve((stdout + stderr).trim());\n });\n });\n }\n\n setConfig(config: TraefikConfig): void {\n this.config = config;\n }\n\n async restart(): Promise<void> {\n if (!this.config?.enabled) throw new Error('Traefik non activé');\n await this.stop();\n await this.spawnTraefik(this.config);\n }\n\n async forceRenewCert(): Promise<void> {\n if (!this.config?.enabled) throw new Error('Traefik non activé');\n // Wipe acme.json so Traefik re-requests a certificate on next start\n await writeFile(this.acmeStorePath, '{}', 'utf-8');\n await chmod(this.acmeStorePath, 0o600);\n // Restart container\n await this.stop();\n await this.spawnTraefik(this.config);\n }\n\n isEnabled(): boolean {\n return this.config?.enabled ?? false;\n }\n\n private async checkAcmeCert(): Promise<{\n hasCert: boolean;\n domain: string | null;\n expiresAt: string | null;\n daysLeft: number | null;\n expired: boolean;\n }> {\n const wildcardDomain = this.config?.wildcardDomain?.replace(/^\\*\\./, '') ?? null;\n try {\n const raw = await readFile(this.acmeStorePath, 'utf-8');\n const acme = JSON.parse(raw) as Record<string, {\n Certificates?: Array<{ domain: { main: string }; certificate: string }>;\n }>;\n\n const allCerts = Object.values(acme).flatMap(r => r.Certificates ?? []);\n if (allCerts.length === 0) return { hasCert: false, domain: wildcardDomain, expiresAt: null, daysLeft: null, expired: false };\n\n // Find cert matching wildcardDomain\n const match = wildcardDomain\n ? allCerts.find(c => c.domain.main === `*.${wildcardDomain}` || c.domain.main === wildcardDomain)\n : allCerts[0];\n\n if (!match) return { hasCert: false, domain: wildcardDomain, expiresAt: null, daysLeft: null, expired: false };\n\n // certificate field is base64-encoded PEM (full chain) — decode first\n const pem = Buffer.from(match.certificate, 'base64').toString('utf-8');\n // Extract just the first cert from the chain for X509Certificate parsing\n const firstCert = pem.match(/(-----BEGIN CERTIFICATE-----[\\s\\S]+?-----END CERTIFICATE-----)/)?.[1] ?? pem;\n const cert = new X509Certificate(firstCert);\n const expiresAt = cert.validTo;\n const expiresDate = new Date(expiresAt);\n const daysLeft = Math.floor((expiresDate.getTime() - Date.now()) / 86_400_000);\n\n return { hasCert: true, domain: match.domain.main, expiresAt, daysLeft, expired: daysLeft < 0 };\n } catch {\n return { hasCert: false, domain: wildcardDomain, expiresAt: null, daysLeft: null, expired: false };\n }\n }\n\n async getStatus(): Promise<{\n containerRunning: boolean;\n dockerAvailable: boolean;\n configFileExists: boolean;\n cert: { hasCert: boolean; domain: string | null; expiresAt: string | null; daysLeft: number | null; expired: boolean };\n }> {\n // Check Docker availability\n let dockerAvailable = false;\n try {\n await new Promise<void>((resolve, reject) => {\n execFile('docker', ['info', '--format', '{{.ServerVersion}}'], { timeout: 5000, windowsHide: true }, (err) => {\n if (err) reject(err instanceof Error ? err : new Error('docker info failed')); else resolve();\n });\n });\n dockerAvailable = true;\n } catch {\n dockerAvailable = false;\n }\n\n // Check static config file exists\n let configFileExists = false;\n try {\n await access(this.staticConfigPath);\n configFileExists = true;\n } catch {\n configFileExists = false;\n }\n\n // Check container running\n let containerRunning = false;\n if (dockerAvailable) {\n try {\n const output = await new Promise<string>((resolve, reject) => {\n execFile('docker', ['inspect', '--format', '{{.State.Running}}', 'runeya-traefik'], { timeout: 5000, windowsHide: true }, (err, stdout) => {\n if (err) reject(err instanceof Error ? err : new Error('docker inspect failed')); else resolve(stdout.trim());\n });\n });\n containerRunning = output === 'true';\n } catch {\n containerRunning = false;\n }\n }\n\n const cert = await this.checkAcmeCert();\n return { containerRunning, dockerAvailable, configFileExists, cert };\n }\n}\n\nexport const traefikManager = new TraefikManager();\n","import { z } from 'zod';\nimport {\n LOG_BUFFER_SIZE,\n METRICS_INTERVAL,\n GRACE_PERIOD,\n HEALTH_WS_INTERVAL,\n} from '@runeya/packages-shared';\n\nconst EnvSchema = z.object({\n RUNEYA_AGENT_PORT: z.coerce.number().int().min(1).max(65535).default(4001),\n RUNEYA_AGENT_HOST: z.string().default('127.0.0.1'),\n PASSPHRASE_OVERRIDE: z.string().regex(/^[0-9a-f]+$/i, 'Must be a hex string').optional(),\n AGENT_ID: z.string().optional(), // Set by spawner or manually for remote agents\n LOG_BUFFER_SIZE: z.coerce.number().int().positive().default(LOG_BUFFER_SIZE),\n METRICS_INTERVAL: z.coerce.number().int().positive().default(METRICS_INTERVAL),\n GRACE_PERIOD: z.coerce.number().int().positive().default(GRACE_PERIOD),\n HEALTH_WS_INTERVAL: z.coerce.number().int().positive().default(HEALTH_WS_INTERVAL),\n});\n\nexport const env = EnvSchema.parse(process.env);\n","import { router, protectedProcedure } from '../trpc.js';\nimport { processManager } from '../../services/process-manager.js';\nimport { networkInterfaces, homedir, platform } from 'node:os';\nimport { isCliAvailable } from '@runeya/packages-shared/node';\n\nconst startedAt = Date.now();\n\nfunction getLanIp(): string {\n const nets = networkInterfaces();\n for (const name of Object.keys(nets)) {\n for (const net of nets[name] ?? []) {\n if (net.family === 'IPv4' && !net.internal) {\n return net.address;\n }\n }\n }\n return '127.0.0.1';\n}\n\nexport async function getHealthData() {\n const runners = await processManager.getAvailableRunners();\n const processes = processManager.listStatuses();\n\n return {\n status: 'ok' as const,\n uptime: Math.floor((Date.now() - startedAt) / 1000),\n runnersAvailable: runners,\n processCount: processes.length,\n runningCount: processes.filter(p => p.state === 'running').length,\n lanIp: getLanIp(),\n // Ce qui décrit la machine, pour que l'interface puisse montrer la valeur\n // qu'aura `{{agent.OS}}`, `{{agent.HOME}}`, `{{service.CWD}}` AVANT que le\n // service ne démarre. La résolution, elle, reste faite ici au lancement :\n // ce statut n'est qu'un cliché, et l'agent reste l'autorité sur sa machine.\n os: platform(),\n home: homedir(),\n cwd: process.cwd(),\n };\n}\n\nexport const healthRouter = router({\n /** Health check - returns agent status */\n check: protectedProcedure\n .query(() => getHealthData()),\n\n /** Check which AI CLIs are available on this agent */\n checkCli: protectedProcedure\n .query(async () => {\n const [claudeOk, codexOk] = await Promise.all([\n isCliAvailable('claude'),\n isCliAvailable('codex'),\n ]);\n return { claudeAvailable: claudeOk, codexAvailable: codexOk };\n }),\n});\n","import { dirname, delimiter } from 'node:path';\n\n/**\n * Garantit que le répertoire du binaire Node est dans le `PATH` des services.\n *\n * Un raccourci de bureau n'hérite pas du `PATH` d'un shell de connexion : il\n * reçoit celui de la session graphique, où les gestionnaires de version (n, nvm,\n * fnm, volta, brew) ne figurent pas. Node, lui, est lancé par chemin absolu et\n * démarre très bien — mais `npm`, `npx`, `yarn` et `corepack`, qui vivent à côté\n * de lui, deviennent introuvables. Un service échoue alors sur un message qui ne\n * dit rien de sa cause : « cannot find package manager binary ».\n *\n * Le répertoire est ajouté en QUEUE : ce que la machine a déjà choisi de mettre\n * devant garde la main, et un `PATH` déjà complet ne change pas.\n */\nexport function ensureNodeBinOnPath(environment: NodeJS.ProcessEnv = process.env): void {\n appendToPath(dirname(process.execPath), environment);\n}\n\n/**\n * Ajoute un répertoire en queue du `PATH`, sans doublon ni séparateur vide.\n */\nexport function appendToPath(dir: string, environment: NodeJS.ProcessEnv = process.env): void {\n if (!dir) return;\n const current = environment['PATH'] ?? '';\n const entries = current.split(delimiter).filter(Boolean);\n if (entries.includes(dir)) return;\n environment['PATH'] = entries.length > 0 ? `${current}${delimiter}${dir}` : dir;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { homedir } from 'node:os';\nimport { existsSync, statSync } from 'node:fs';\nimport { join, delimiter } from 'node:path';\nimport { appendToPath } from './node-path.js';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Marqueur : un `.zshrc` interactif écrit volontiers sur stdout (bannières,\n * gestionnaires de version, `motd`). Sans balise, on ne sait pas quelle ligne\n * est le `PATH`.\n */\nconst MARKER = '__RUNEYA_PATH__';\n\n/** Le profil de l'utilisateur peut être long à charger — mais pas éternel. */\nconst SHELL_TIMEOUT_MS = 3000;\n\n/**\n * Emplacements où un CLI utilisateur s'installe sans passer par le système.\n * Filet de sécurité quand le shell de connexion n'a rien donné : on ne devine\n * pas les gestionnaires de version (chemins versionnés), seulement le banal.\n */\nfunction commonUserBins(home: string): string[] {\n return [\n join(home, '.local', 'bin'),\n join(home, 'bin'),\n join(home, '.npm-global', 'bin'),\n join(home, '.bun', 'bin'),\n join(home, '.cargo', 'bin'),\n '/opt/homebrew/bin',\n '/usr/local/bin',\n ];\n}\n\n/**\n * Demande son `PATH` au shell de connexion de l'utilisateur.\n *\n * Un raccourci de bureau reçoit le `PATH` de la session graphique, pas celui du\n * shell : `~/.local/bin`, nvm, fnm, volta, mise, asdf… n'y figurent pas. Le CLI\n * installé par l'utilisateur devient alors introuvable, et l'agent le déclare\n * simplement « non disponible ».\n *\n * Renvoie `null` en cas d'échec (Windows, pas de `SHELL`, timeout, profil qui\n * plante) : l'absence de réponse ne doit jamais empêcher l'agent de démarrer.\n */\nexport async function readLoginShellPath(): Promise<string | null> {\n if (process.platform === 'win32') return null;\n\n const shell = process.env['SHELL'];\n if (!shell || !existsSync(shell)) return null;\n\n try {\n // `-l -i` : le `PATH` d'un utilisateur vit aussi bien dans le profil de\n // connexion que dans le fichier interactif (`.zshrc`, `.bashrc`).\n // `shell: false` : le shell EST le programme lancé, pas l'interpréteur.\n const { stdout } = await execFileAsync(shell, ['-l', '-i', '-c', `echo \"${MARKER}$PATH\"`], {\n timeout: SHELL_TIMEOUT_MS,\n shell: false,\n encoding: 'utf8',\n maxBuffer: 1024 * 1024,\n env: { ...process.env, TERM: 'dumb' },\n });\n\n const line = stdout.split('\\n').find(l => l.includes(MARKER));\n if (!line) return null;\n\n const value = line.slice(line.indexOf(MARKER) + MARKER.length).trim();\n return value.length > 0 ? value : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Complète le `PATH` de l'agent avec ce que le shell de connexion connaît, puis\n * avec les emplacements utilisateur usuels qui existent réellement sur disque.\n *\n * Tout est ajouté EN QUEUE, comme pour Node : ce que la machine a déjà mis\n * devant garde la main, et un `PATH` déjà complet ne change pas.\n */\nexport async function ensureUserBinsOnPath(\n environment: NodeJS.ProcessEnv = process.env,\n home: string = homedir(),\n): Promise<void> {\n const shellPath = await readLoginShellPath();\n if (shellPath) {\n for (const entry of shellPath.split(delimiter).filter(Boolean)) {\n appendToPath(entry, environment);\n }\n }\n\n for (const dir of commonUserBins(home)) {\n if (isDirectory(dir)) appendToPath(dir, environment);\n }\n}\n\nfunction isDirectory(path: string): boolean {\n try {\n return statSync(path).isDirectory();\n } catch {\n return false;\n }\n}\n","/**\n * Horodate ce que le process écrit sur la console, en temps écoulé depuis son\n * démarrage.\n *\n * Les 300 et quelques appels à `console.log` du serveur, de l'agent et du CLI\n * n'ont pas à être réécrits : on enveloppe `console` une fois, au démarrage, et\n * tout ce qui passe par lui est daté — jusqu'aux bibliothèques tierces.\n *\n * Le delta plutôt que l'heure : ces journaux servent surtout à comprendre ce qui\n * prend du temps au sein d'un même lancement, et « +1.204s » se lit sans\n * soustraction mentale. L'heure absolue reste disponible dans le journal\n * d'audit, qui, lui, sert à recouper avec le cloud.\n */\n\n/**\n * Une ligne qui ne dit rien à dater : une ligne vide, ou un morceau d'encadré.\n *\n * La bannière de démarrage est dessinée ligne à ligne ; un horodatage devant\n * chacune casse l'alignement des colonnes et n'apprend rien — elles sont toutes\n * écrites dans la même milliseconde.\n */\nfunction isDecorative(args: unknown[]): boolean {\n if (args.length === 0) return true;\n const first = args[0];\n if (typeof first !== 'string') return false;\n const trimmed = first.trim();\n return trimmed === '' || /^[┌│└├┬┴┼─┐┘┤]/.test(trimmed);\n}\n\nconst LEVELS = ['log', 'info', 'warn', 'error', 'debug'] as const;\n\n/** Le temps écoulé, cadré pour que les lignes s'alignent en colonne. */\nfunction formatElapsed(startedAt: number, now: number): string {\n const seconds = (now - startedAt) / 1000;\n return `+${seconds.toFixed(3)}s`.padStart(10);\n}\n\n/**\n * Enveloppe `console`. Rend une fonction qui remet l'original en place — les\n * tests en ont besoin, et un mode dont la sortie est lue par un script aussi.\n *\n * Appelé deux fois, le second appel ne fait rien : sans cette garde, deux\n * horodatages se cumuleraient sur chaque ligne.\n */\nexport function stampConsole(startedAt: number = Date.now()): () => void {\n const target = console as unknown as Record<string, unknown> & { __runeyaStamped?: boolean };\n if (target.__runeyaStamped) return () => {};\n target.__runeyaStamped = true;\n\n const originals = LEVELS.map((level) => {\n const original = console[level].bind(console);\n console[level] = (...args: unknown[]) => (\n isDecorative(args)\n ? original(...args)\n : original(formatElapsed(startedAt, Date.now()), ...args)\n );\n return [level, original] as const;\n });\n\n return () => {\n for (const [level, original] of originals) console[level] = original;\n target.__runeyaStamped = false;\n };\n}\n","import { execFile, execFileSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, resolve as resolvePath } from 'node:path';\n\nexport interface CliInvocation {\n command: string;\n args: string[];\n}\n\n/**\n * Comment lancer un CLI global (`claude`, `codex`) sur la plateforme courante.\n *\n * Windows : un CLI installé globalement par npm n'est pas un `.exe` mais un\n * shim `claude.cmd`. Ni `child_process.spawn(..., { shell: false })` ni\n * `pty.spawn()` ne savent le lancer — node-pty échoue sur « File not found:\n * claude ». Passer par `cmd.exe /c` fonctionnerait mais abîme les arguments\n * (le prompt système contient guillemets, retours à la ligne et `%`), donc on\n * résout le point d'entrée JS visé par le shim et on le lance avec le `node`\n * courant.\n *\n * Sur POSIX la commande est rendue telle quelle : rien ne change pour Linux\n * ni macOS.\n */\nexport function resolveCliInvocation(cli: string, args: string[] = []): CliInvocation {\n if (process.platform !== 'win32') return { command: cli, args };\n if (/\\.exe$/i.test(cli)) return { command: cli, args };\n\n // 1. Localiser le shim sur le PATH (sauf si un chemin explicite est donné).\n let shim = cli;\n if (!cli.includes('\\\\') && !cli.includes('/')) {\n let found: string[] = [];\n try {\n // Borné : un `where` qui ne rend pas la main figerait le process appelant,\n // puisque la résolution est synchrone.\n found = execFileSync('where', [cli], { encoding: 'utf-8', timeout: 5_000, windowsHide: true })\n .split(/\\r?\\n/).map((l) => l.trim()).filter(Boolean);\n } catch { /* absent du PATH — laisser le spawn échouer avec son propre message */ }\n const exe = found.find((f) => /\\.exe$/i.test(f));\n if (exe) return { command: exe, args };\n shim = found.find((f) => /\\.cmd$/i.test(f)) ?? found[0] ?? cli;\n }\n if (/\\.exe$/i.test(shim)) return { command: shim, args };\n\n // 2. Extraire le point d'entrée `.js` du shim npm et le lancer avec node.\n if (/\\.cmd$/i.test(shim) && existsSync(shim)) {\n try {\n const content = readFileSync(shim, 'utf-8');\n // Les shims npm écrivent « %~dp0\\...\\cli.js » ; certains outils écrivent\n // « %~dp0%\\...\\cli.js ». Les deux formes mènent au même point d'entrée.\n const m = content.match(/%~?dp0%?\\\\?([^\"\\s]+\\.js)/i);\n if (m?.[1]) {\n const entry = resolvePath(dirname(shim), m[1].replace(/^\\\\+/, ''));\n if (existsSync(entry)) return { command: process.execPath, args: [entry, ...args] };\n }\n } catch { /* on retombe sur l'interpréteur de commandes */ }\n }\n\n // 3. Dernier recours : confier à l'interpréteur de commandes.\n const comspec = process.env['ComSpec'] || process.env['COMSPEC'] || 'cmd.exe';\n return { command: comspec, args: ['/d', '/s', '/c', shim, ...args] };\n}\n\n/**\n * La commande qui dit où vit un exécutable, selon la plateforme.\n *\n * `which` n'existe pas sur Windows ; une détection qui l'appelle y répond\n * toujours « absent », quel que soit l'outil installé.\n */\nexport function whichCommand(): string {\n return process.platform === 'win32' ? 'where' : 'which';\n}\n\n/**\n * `<cli> --version` répond-il ?\n *\n * Le même contrôle vivait côté serveur et côté agent, et les deux lançaient\n * `execFile('claude', …, { shell: false })` : sur Windows, un shim `.cmd` n'est\n * pas lançable ainsi, et la détection répondait « absent » pour un CLI\n * parfaitement installé — l'interface désactivait alors le runner.\n */\nexport async function isCliAvailable(cli: string, timeoutMs = 5_000): Promise<boolean> {\n const { command, args } = resolveCliInvocation(cli, ['--version']);\n return new Promise((resolve) => {\n execFile(command, args, { timeout: timeoutMs, windowsHide: true }, (err) => resolve(!err));\n });\n}\n","import { randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\n\nconst ALGORITHM = 'aes-256-gcm';\n\n/**\n * Encrypt under a caller-supplied key.\n *\n * The no-key forms in the server read the process keyring, which is the right default\n * everywhere except migration: converting a vault means holding two keys at\n * once, and neither of them is \"the\" current one.\n */\nexport function encryptValueWith(key: Buffer, plaintext: string): string {\n const iv = randomBytes(16);\n const cipher = createCipheriv(ALGORITHM, key, iv);\n let enc = cipher.update(plaintext, 'utf-8', 'hex');\n enc += cipher.final('hex');\n const authTag = cipher.getAuthTag().toString('hex');\n return `${iv.toString('hex')}:${authTag}:${enc}`;\n}\n\n/** Decrypt under a caller-supplied key. Throws when the key does not open it. */\nexport function decryptValueWith(key: Buffer, encrypted: string): string {\n const parts = encrypted.split(':');\n if (parts.length !== 3) throw new Error('Invalid encrypted value format — expected iv:authTag:ciphertext');\n const [ivHex, authTagHex, ciphertext] = parts;\n if (!/^[0-9a-f]+$/i.test(ivHex) || !/^[0-9a-f]+$/i.test(authTagHex) || (ciphertext !== '' && !/^[0-9a-f]+$/i.test(ciphertext))) {\n throw new Error('Invalid hex in encrypted value — possible data corruption');\n }\n const decipher = createDecipheriv(ALGORITHM, key, Buffer.from(ivHex, 'hex'), { authTagLength: 16 });\n decipher.setAuthTag(Buffer.from(authTagHex, 'hex'));\n let dec = decipher.update(ciphertext, 'hex', 'utf-8');\n dec += decipher.final('utf-8');\n return dec;\n}\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { terminalManager } from '../../services/terminal-manager.js';\n\nexport const terminalRouter = router({\n /** Spawn a new PTY shell session, returns a sessionId */\n create: protectedProcedure\n .input(z.object({\n cwd: z.string().max(512).optional(),\n cols: z.number().int().min(1).max(512).optional(),\n rows: z.number().int().min(1).max(256).optional(),\n title: z.string().max(128).optional(),\n }))\n .mutation(({ input }) => {\n const sessionId = terminalManager.create(input.cwd, input.cols, input.rows, input.title);\n return { sessionId };\n }),\n\n /** Les sessions encore vivantes : un onglet fermé côté web se retrouve ici */\n list: protectedProcedure\n .query(() => ({ sessions: terminalManager.list() })),\n\n /** Renommer un onglet */\n rename: protectedProcedure\n .input(z.object({ sessionId: z.string().max(128), title: z.string().max(128) }))\n .mutation(({ input }) => {\n terminalManager.rename(input.sessionId, input.title);\n return { ok: true as const };\n }),\n\n /** Write data (keystrokes) to a PTY session */\n write: protectedProcedure\n .input(z.object({ sessionId: z.string().max(128), data: z.string().max(65536) }))\n .mutation(({ input }) => {\n terminalManager.write(input.sessionId, input.data);\n return { ok: true as const };\n }),\n\n /** Resize a PTY session */\n resize: protectedProcedure\n .input(z.object({\n sessionId: z.string().max(128),\n cols: z.number().int().min(1).max(512),\n rows: z.number().int().min(1).max(256),\n }))\n .mutation(({ input }) => {\n terminalManager.resize(input.sessionId, input.cols, input.rows);\n return { ok: true as const };\n }),\n\n /** Destroy a PTY session */\n destroy: protectedProcedure\n .input(z.object({ sessionId: z.string().max(128) }))\n .mutation(({ input }) => {\n terminalManager.destroy(input.sessionId);\n return { ok: true as const };\n }),\n\n /** Stream PTY output for a session (async generator subscription) */\n onData: protectedProcedure\n .input(z.object({\n sessionId: z.string().max(128),\n /** Rejouer l'historique avant le flux : c'est ce qui rend l'onglet persistant. */\n replay: z.boolean().optional(),\n }))\n .subscription(async function* ({ input }) {\n const emitter = terminalManager.getEmitter(input.sessionId);\n if (!emitter) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Terminal session ${input.sessionId} not found` });\n }\n\n const queue: string[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n const onData = (data: string) => {\n queue.push(data);\n if (resolve) { resolve(); resolve = null; }\n };\n const onExit = () => {\n done = true;\n if (resolve) { resolve(); resolve = null; }\n };\n\n emitter.on('data', onData);\n emitter.on('exit', onExit);\n\n // L'historique est capturé avant tout `yield` : rien ne se perd entre les deux.\n const scrollback = input.replay ? terminalManager.getScrollback(input.sessionId) : '';\n if (scrollback) yield scrollback;\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n emitter.off('data', onData);\n emitter.off('exit', onExit);\n }\n }),\n});\n","import { EventEmitter } from 'node:events';\nimport os from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport * as pty from '@lydell/node-pty';\n\n/** Combien d'octets de sortie on garde pour rejouer un terminal réouvert. */\nconst SCROLLBACK_LIMIT = 256 * 1024;\n\nexport interface TerminalSessionInfo {\n sessionId: string;\n title: string;\n cwd: string;\n cols: number;\n rows: number;\n createdAt: number;\n}\n\ninterface TerminalSession {\n pty: pty.IPty;\n emitter: EventEmitter;\n /** Historique tronqué : ce qu'un onglet rouvert doit réafficher. */\n scrollback: string;\n info: TerminalSessionInfo;\n}\n\nclass TerminalManager {\n private sessions = new Map<string, TerminalSession>();\n\n create(cwd?: string, cols?: number, rows?: number, title?: string): string {\n const sessionId = randomUUID();\n const shell = process.env.SHELL ?? (os.platform() === 'win32' ? 'powershell.exe' : '/bin/bash');\n const resolvedCwd = cwd ?? process.cwd();\n const resolvedCols = cols ?? 80;\n const resolvedRows = rows ?? 24;\n\n const term = pty.spawn(shell, [], {\n name: 'xterm-256color',\n cols: resolvedCols,\n rows: resolvedRows,\n cwd: resolvedCwd,\n env: process.env as Record<string, string>,\n });\n\n const emitter = new EventEmitter();\n // Plusieurs vues web peuvent écouter la même session au fil des navigations.\n emitter.setMaxListeners(50);\n\n const session: TerminalSession = {\n pty: term,\n emitter,\n scrollback: '',\n info: {\n sessionId,\n title: title ?? 'Terminal',\n cwd: resolvedCwd,\n cols: resolvedCols,\n rows: resolvedRows,\n createdAt: Date.now(),\n },\n };\n\n term.onData((data) => {\n session.scrollback += data;\n if (session.scrollback.length > SCROLLBACK_LIMIT) {\n session.scrollback = session.scrollback.slice(-SCROLLBACK_LIMIT);\n }\n emitter.emit('data', data);\n });\n term.onExit(() => {\n emitter.emit('exit');\n this.sessions.delete(sessionId);\n });\n\n this.sessions.set(sessionId, session);\n return sessionId;\n }\n\n write(sessionId: string, data: string): void {\n this.sessions.get(sessionId)?.pty.write(data);\n }\n\n resize(sessionId: string, cols: number, rows: number): void {\n const session = this.sessions.get(sessionId);\n if (!session) return;\n session.pty.resize(cols, rows);\n session.info.cols = cols;\n session.info.rows = rows;\n }\n\n rename(sessionId: string, title: string): void {\n const session = this.sessions.get(sessionId);\n if (session) session.info.title = title;\n }\n\n destroy(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n try { session.pty.kill(); } catch { /* already dead */ }\n this.sessions.delete(sessionId);\n }\n }\n\n /** Les sessions encore vivantes : de quoi retrouver ses onglets après un aller-retour. */\n list(): TerminalSessionInfo[] {\n return [...this.sessions.values()]\n .map((s) => s.info)\n .sort((a, b) => a.createdAt - b.createdAt);\n }\n\n getScrollback(sessionId: string): string {\n return this.sessions.get(sessionId)?.scrollback ?? '';\n }\n\n getEmitter(sessionId: string): EventEmitter | null {\n return this.sessions.get(sessionId)?.emitter ?? null;\n }\n}\n\nexport const terminalManager = new TerminalManager();\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { execFile, spawn } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { existsSync, watch as fsWatch } from 'node:fs';\nimport { promises as fsPromises } from 'node:fs';\nimport { join, resolve as resolvePath } from 'node:path';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { expandEnvVar } from '../../utils/env.js';\nimport { sameGitRemote } from '../../utils/git-remote.js';\n\nconst execFileAsync = promisify(execFile);\n\nconst GIT_TIMEOUT = 15_000;\nconst DIFF_MAX_BYTES = 512 * 1024;\n\nconst CWD_SCHEMA = z.string().min(1).max(4096);\nconst SAFE_PATH_SCHEMA = z\n .string()\n .min(1)\n .max(4096)\n .refine((p) => !p.startsWith('/') && !p.includes('../'), {\n message: 'Path must be relative and not traverse up',\n });\nconst REMOTE_SCHEMA = z.string().min(1).max(128).regex(/^[a-zA-Z0-9_\\-.]+$/);\nconst BRANCH_SCHEMA = z.string().min(1).max(256).regex(/^[a-zA-Z0-9._\\-/]+$/);\n\n/**\n * Build a safe, explicit environment for git commands.\n */\nfunction gitSafeEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = {\n GIT_TERMINAL_PROMPT: '0',\n GIT_ASKPASS: 'echo',\n };\n if (process.env['PATH']) env['PATH'] = process.env['PATH'];\n if (process.env['HOME']) env['HOME'] = process.env['HOME'];\n if (process.env['GIT_AUTHOR_NAME']) env['GIT_AUTHOR_NAME'] = process.env['GIT_AUTHOR_NAME'];\n if (process.env['GIT_AUTHOR_EMAIL']) env['GIT_AUTHOR_EMAIL'] = process.env['GIT_AUTHOR_EMAIL'];\n if (process.env['GIT_COMMITTER_NAME']) env['GIT_COMMITTER_NAME'] = process.env['GIT_COMMITTER_NAME'];\n if (process.env['GIT_COMMITTER_EMAIL']) env['GIT_COMMITTER_EMAIL'] = process.env['GIT_COMMITTER_EMAIL'];\n if (process.env['SSH_AUTH_SOCK']) env['SSH_AUTH_SOCK'] = process.env['SSH_AUTH_SOCK'];\n return env;\n}\n\nconst activeGitProcesses = new Set<import('node:child_process').ChildProcess>();\n\n{\n const cleanup = () => {\n for (const proc of activeGitProcesses) {\n try { proc.kill('SIGTERM'); } catch { /* already dead */ }\n }\n };\n process.on('SIGTERM', cleanup);\n process.on('SIGINT', cleanup);\n}\n\nasync function git(args: string[], cwd: string, readOnly = false): Promise<string> {\n const ac = new AbortController();\n const timeout = setTimeout(() => ac.abort(), GIT_TIMEOUT);\n const env = gitSafeEnv();\n if (readOnly) env['GIT_OPTIONAL_LOCKS'] = '0';\n try {\n const result = execFileAsync('git', args, { cwd, signal: ac.signal, env, windowsHide: true });\n if (result.child) {\n activeGitProcesses.add(result.child);\n result.child.on('close', () => activeGitProcesses.delete(result.child!));\n }\n const { stdout } = await result;\n return stdout;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n const stderr = (err as { stderr?: string }).stderr ?? '';\n throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: stderr || message });\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function assertGitRepo(cwd: string): Promise<void> {\n try {\n await git(['rev-parse', '--git-dir'], cwd, true);\n } catch (err) {\n console.error('[git] assertGitRepo failed for cwd=%s:', cwd, err);\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Not a git repository: ${cwd}` });\n }\n}\n\n\n/**\n * Expand $VAR / ${VAR} and leading ~ in a cwd string using resolveEnv(),\n * assert the directory exists, and return the resolved path.\n * All git handlers must call this first and use the returned path.\n */\nfunction assertCwdExists(cwd: string): string {\n const resolved = expandEnvVar(cwd);\n if (!existsSync(resolved)) {\n console.error('[git] assertCwdExists: directory does not exist: %s (resolved=%s, process.cwd=%s)', cwd, resolved, process.cwd());\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Working directory does not exist: ${resolved}` });\n }\n return resolved;\n}\n\nasync function getGitStatus(cwd: string) {\n let branch = '';\n try {\n branch = (await git(['rev-parse', '--abbrev-ref', 'HEAD'], cwd, true)).trim();\n } catch {\n branch = 'HEAD';\n }\n\n const statusOutput = await git(['status', '--porcelain=v1', '-u'], cwd, true);\n const staged: string[] = [];\n const unstaged: string[] = [];\n const untracked: string[] = [];\n for (const line of statusOutput.split('\\n').filter(Boolean)) {\n const X = line[0];\n const Y = line[1];\n const file = line.slice(3);\n if (X === '?' && Y === '?') {\n untracked.push(file);\n } else {\n if (X !== ' ' && X !== '?') staged.push(file);\n if (Y !== ' ' && Y !== '?') unstaged.push(file);\n }\n }\n\n let ahead = 0;\n let behind = 0;\n try {\n const revListOut = await git(['rev-list', '--left-right', '--count', '@{upstream}...HEAD'], cwd, true);\n const parts = revListOut.trim().split(/\\s+/);\n behind = Number.parseInt(parts[0] ?? '0', 10);\n ahead = Number.parseInt(parts[1] ?? '0', 10);\n } catch { /* no upstream */ }\n\n let upstream = '';\n try {\n upstream = (await git(['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'], cwd, true)).trim();\n } catch { /* no upstream */ }\n\n // Total des lignes ajoutées/supprimées des changements suivis (staged + unstaged) vs HEAD.\n // Les fichiers binaires apparaissent comme \"-\\t-\" et sont ignorés.\n let additions = 0;\n let deletions = 0;\n try {\n const numstat = await git(['diff', '--numstat', 'HEAD'], cwd, true);\n for (const line of numstat.split('\\n').filter(Boolean)) {\n const [add, del] = line.split('\\t');\n const a = Number.parseInt(add ?? '', 10);\n const d = Number.parseInt(del ?? '', 10);\n if (!Number.isNaN(a)) additions += a;\n if (!Number.isNaN(d)) deletions += d;\n }\n } catch { /* no HEAD yet, or not a repo */ }\n\n return { branch, staged, unstaged, untracked, ahead, behind, upstream, additions, deletions };\n}\n\nexport const gitRouter = router({\n /** Check if a working directory exists and optionally verify its git remote */\n checkCwd: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n remote: z.string().max(2048).optional(),\n checkReachability: z.boolean().optional(),\n }))\n .query(async ({ input }) => {\n const resolvedCwd = expandEnvVar(input.cwd);\n // Detect vars that couldn't be resolved (still contain $)\n const unresolvedVars = [...resolvedCwd.matchAll(/\\$\\{?(\\w+)\\}?/g)].map(m => m[1]!);\n if (unresolvedVars.length > 0) {\n return { exists: false, actualRemote: null, remoteMatches: false, unreachable: false, resolvedCwd, unresolvedVars };\n }\n const absoluteCwd = resolvePath(resolvedCwd);\n const exists = existsSync(absoluteCwd);\n if (!exists || !input.remote) {\n return { exists, actualRemote: null, remoteMatches: false, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };\n }\n const { code: urlCode, out: actualRemote } = await runGitRaw(['-C', absoluteCwd, 'remote', 'get-url', 'origin'], 5000);\n if (urlCode !== 0) return { exists, actualRemote: null, remoteMatches: false, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };\n // Comparé ici, et pas côté serveur : seul l'agent voit la configuration ssh\n // qui donne son vrai hôte à un alias (`github-addworking` → `github.com`).\n const remoteMatches = await sameGitRemote(actualRemote, input.remote);\n if (input.checkReachability) {\n const { code: showCode } = await runGitRaw(['-C', absoluteCwd, 'remote', 'show', 'origin'], 10000);\n return { exists, actualRemote, remoteMatches, unreachable: showCode !== 0, resolvedCwd: absoluteCwd, unresolvedVars: [] };\n }\n return { exists, actualRemote, remoteMatches, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };\n }),\n\n /** Clone a git repository into a target directory */\n clone: protectedProcedure\n .input(z.object({\n remote: z.string().min(1).max(2048),\n cwd: CWD_SCHEMA,\n }))\n .mutation(async ({ input }) => {\n const absoluteCwd = resolvePath(expandEnvVar(input.cwd));\n if (existsSync(absoluteCwd)) {\n // Allow cloning into an existing empty directory, but reject non-empty ones\n const entries = await fsPromises.readdir(absoluteCwd);\n if (entries.length > 0) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Working directory already exists and is not empty' });\n }\n }\n console.log('[git.clone] remote=%s cwd=%s absoluteCwd=%s', input.remote, input.cwd, absoluteCwd);\n const { code, out } = await runGitRaw(['clone', input.remote, absoluteCwd], 5 * 60 * 1000, {\n GIT_SSH_COMMAND: 'ssh -o StrictHostKeyChecking=accept-new',\n });\n if (code !== 0) {\n console.error('[git.clone] failed (code=%d): %s', code, out);\n throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: `git clone failed: ${out}` });\n }\n return { success: true as const };\n }),\n\n /** Get full git status */\n status: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n return getGitStatus(cwd);\n }),\n\n /** Watch .git/ for changes and stream updated status */\n onStatusChange: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .subscription(async function* ({ input }) {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n\n const gitDir = (await git(['rev-parse', '--git-dir'], cwd, true)).trim();\n const absGitDir = resolvePath(cwd, gitDir);\n\n const queue: Array<'changed'> = [];\n let resolve: (() => void) | null = null;\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const onFsChange = () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n queue.push('changed');\n if (resolve) { resolve(); resolve = null; }\n }, 500);\n };\n\n // Watch .git dir for staged/committed changes\n const gitWatcher = fsWatch(absGitDir, { recursive: true }, () => {\n onFsChange();\n });\n gitWatcher.on('error', () => { /* directory deleted mid-watch, ignore */ });\n\n // Watch working tree for unstaged file modifications (exclude .git)\n const cwdWatcher = fsWatch(cwd, { recursive: true }, (event, filename) => {\n if (filename && filename.startsWith('.git')) return;\n onFsChange();\n });\n cwdWatcher.on('error', () => { /* directory deleted mid-watch, ignore */ });\n\n // Yield initial status immediately\n yield await getGitStatus(cwd);\n\n try {\n while (true) {\n if (queue.length > 0) {\n queue.length = 0;\n try {\n yield await getGitStatus(cwd);\n } catch { }\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n gitWatcher.close();\n cwdWatcher.close();\n if (debounceTimer) clearTimeout(debounceTimer);\n }\n }),\n\n /** Get commit log */\n log: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, limit: z.number().int().min(1).max(200).default(50) }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const format = '%H\\x1f%h\\x1f%an\\x1f%ae\\x1f%ai\\x1f%s';\n const output = await git(['log', `--max-count=${input.limit}`, `--format=${format}`], cwd, true);\n return output.split('\\n').filter(Boolean).map((line) => {\n const [hash, shortHash, author, email, date, ...subjectParts] = line.split('\\x1f');\n return { hash, shortHash, author, email, date, subject: subjectParts.join('\\x1f') };\n });\n }),\n\n /** List local and remote branches */\n branches: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const current = (await git(['rev-parse', '--abbrev-ref', 'HEAD'], cwd, true)).trim();\n const output = await git(['branch', '-a', '--format=%(refname:short)\u001f%(upstream:short)\u001f%(HEAD)'], cwd, true);\n const branches = output.split('\\n').filter(Boolean).map((line) => {\n const [name, upstream, head] = line.split('\\x1f');\n return { name, upstream: upstream ?? '', current: head === '*', remote: name.startsWith('remotes/') };\n });\n return { current, branches };\n }),\n\n /** Checkout a branch */\n checkout: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, branch: BRANCH_SCHEMA, create: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const args = input.create ? ['checkout', '-b', input.branch] : ['checkout', input.branch];\n await git(args, cwd);\n return { ok: true };\n }),\n\n /** Stage files */\n stage: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n await git(['add', '--', ...input.paths], cwd);\n return { ok: true };\n }),\n\n /** Stage all files */\n stageAll: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n await git(['add', '-A'], cwd);\n return { ok: true };\n }),\n\n /** Unstage files */\n unstage: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n await git(['restore', '--staged', '--', ...input.paths], cwd);\n return { ok: true };\n }),\n\n /** Unstage all files */\n unstageAll: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n // `git reset` unstages everything while keeping the working tree intact,\n // and works even on a repo with no commits yet (resets index to empty tree).\n await git(['reset', '--'], cwd);\n return { ok: true };\n }),\n\n /** Commit staged changes */\n commit: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, message: z.string().min(1).max(4096) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['commit', '-m', input.message], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Push to remote */\n push: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, remote: REMOTE_SCHEMA.default('origin'), setUpstream: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const branch = (await git(['rev-parse', '--abbrev-ref', 'HEAD'], cwd, true)).trim();\n const args = input.setUpstream\n ? ['push', '--set-upstream', input.remote, branch]\n : ['push', input.remote, branch];\n const output = await git(args, cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Pull from remote */\n pull: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, remote: REMOTE_SCHEMA.default('origin') }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['pull', input.remote], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Fetch from remote */\n fetch: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, remote: REMOTE_SCHEMA.default('origin') }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['fetch', input.remote], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Get diff for a file or the whole index */\n diff: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n path: z.string().max(4096).optional(),\n staged: z.boolean().default(false),\n untracked: z.boolean().default(false),\n }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n\n async function readFileSafe(filePath: string): Promise<string> {\n try { return await fsPromises.readFile(filePath, 'utf-8'); } catch { return ''; }\n }\n\n if (input.untracked && input.path) {\n const modified = await readFileSafe(join(cwd, input.path));\n return { diff: '', original: '', modified };\n }\n\n const args = input.staged ? ['diff', '--staged'] : ['diff'];\n if (input.path) args.push('--', input.path);\n const output = await git(args, cwd, true);\n\n let original = '';\n let modified = '';\n if (input.path) {\n if (input.staged) {\n try { original = await git(['show', `HEAD:${input.path}`], cwd, true); } catch { original = ''; }\n try { modified = await git(['show', `:0:${input.path}`], cwd, true); } catch { modified = original; }\n } else {\n try { original = await git(['show', `:0:${input.path}`], cwd, true); } catch { original = ''; }\n modified = await readFileSafe(join(cwd, input.path));\n }\n }\n\n return {\n diff: output.slice(0, DIFF_MAX_BYTES),\n original: original.slice(0, DIFF_MAX_BYTES),\n modified: modified.slice(0, DIFF_MAX_BYTES),\n };\n }),\n\n /** Discard changes to working tree files */\n discard: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n await git(['restore', '--', ...input.paths], cwd);\n return { ok: true };\n }),\n\n /** Get staged diff (used by server for AI commit message generation) */\n stagedDiff: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const diff = await git(['diff', '--staged'], cwd, true);\n return { diff: diff.slice(0, 30_000) };\n }),\n\n /** Merge a branch into the current branch */\n merge: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, branch: BRANCH_SCHEMA, noFf: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const args = input.noFf ? ['merge', '--no-ff', input.branch] : ['merge', input.branch];\n const output = await git(args, cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Rebase current branch onto another branch */\n rebase: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, branch: BRANCH_SCHEMA }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['rebase', input.branch], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** List remotes */\n remotes: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['remote', '-v'], cwd, true);\n const seen = new Set<string>();\n const remotes: Array<{ name: string; url: string }> = [];\n for (const line of output.split('\\n').filter(Boolean)) {\n const parts = line.split(/\\s+/);\n const name = parts[0];\n const url = parts[1];\n if (name && url && !seen.has(name)) {\n seen.add(name);\n remotes.push({ name, url });\n }\n }\n return remotes;\n }),\n\n /** List stash entries */\n stashList: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n // Format: \"<ref>\\x1f<message>\" per line (\\x1f separator keeps the message intact)\n const output = await git(['stash', 'list', '--format=%gd\\x1f%s'], cwd, true);\n const entries: Array<{ index: number; ref: string; message: string }> = [];\n for (const line of output.split('\\n').filter(Boolean)) {\n const [ref, message = ''] = line.split('\\x1f');\n // ref looks like \"stash@{0}\" → extract the numeric index\n const m = /stash@\\{(\\d+)\\}/.exec(ref ?? '');\n if (m) entries.push({ index: Number.parseInt(m[1], 10), ref: ref!, message });\n }\n return entries;\n }),\n\n /** Stash current changes */\n stashPush: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n message: z.string().max(4096).optional(),\n includeUntracked: z.boolean().default(true),\n }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const args = ['stash', 'push'];\n if (input.includeUntracked) args.push('--include-untracked');\n if (input.message) args.push('-m', input.message);\n const output = await git(args, cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Apply a stash entry and remove it from the list */\n stashPop: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, index: z.number().int().min(0).max(1000).default(0) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['stash', 'pop', `stash@{${input.index}}`], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Apply a stash entry without removing it from the list */\n stashApply: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, index: z.number().int().min(0).max(1000).default(0) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['stash', 'apply', `stash@{${input.index}}`], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Drop a stash entry */\n stashDrop: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, index: z.number().int().min(0).max(1000).default(0) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['stash', 'drop', `stash@{${input.index}}`], cwd);\n return { ok: true, output: output.trim() };\n }),\n});\n\n// Low-level helper for checkCwd/clone that needs raw exit code\nfunction runGitRaw(args: string[], timeoutMs: number, extraEnv?: Record<string, string>): Promise<{ code: number | null; out: string }> {\n return new Promise((res) => {\n const child = spawn('git', args, { shell: false, stdio: 'pipe', env: { ...process.env, ...extraEnv }, windowsHide: true });\n let out = '';\n child.stdout?.on('data', (d: Buffer) => { out += d.toString(); });\n child.stderr?.on('data', (d: Buffer) => { out += d.toString(); });\n const timer = setTimeout(() => { child.kill('SIGKILL'); res({ code: null, out }); }, timeoutMs);\n child.on('close', (code: number | null) => { clearTimeout(timer); res({ code, out: out.trim() }); });\n child.on('error', () => { clearTimeout(timer); res({ code: null, out }); });\n });\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\nexport interface ParsedRemote {\n host: string;\n path: string;\n}\n\n/**\n * Découpe une URL de remote git, qu'elle soit une URL (`ssh://`, `https://`…)\n * ou la forme scp (`git@host:owner/repo.git`). Le suffixe `.git` et les barres\n * de fin sont retirés : ils ne distinguent pas deux dépôts.\n */\nexport function parseGitRemote(url: string): ParsedRemote | null {\n const trimmed = url.trim();\n if (!trimmed) return null;\n\n let host: string;\n let path: string;\n\n const scp = /^(?:[^/@]+@)?([^/:]+):(?!\\/)(.+)$/.exec(trimmed);\n if (scp) {\n host = scp[1]!;\n path = scp[2]!;\n } else {\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n return null;\n }\n if (parsed.protocol === 'file:' || !parsed.hostname) return null;\n host = parsed.hostname;\n path = parsed.pathname;\n }\n\n path = path.replace(/^\\/+/, '').replace(/\\/+$/, '').replace(/\\.git$/i, '');\n if (!host || !path) return null;\n return { host: host.toLowerCase(), path: path.toLowerCase() };\n}\n\n/**\n * Résout un alias d'hôte SSH (`Host github-addworking` → `github.com`) via la\n * configuration ssh de l'utilisateur. Sans ça, deux remotes qui désignent le\n * même dépôt sont vus comme différents dès qu'un alias est utilisé.\n */\nexport async function resolveSshHost(host: string): Promise<string> {\n if (!/^[a-zA-Z0-9._-]+$/.test(host)) return host;\n try {\n const { stdout } = await execFileAsync('ssh', ['-G', host], {\n windowsHide: true,\n timeout: 3000,\n env: { PATH: process.env['PATH'] ?? '', HOME: process.env['HOME'] ?? '' },\n });\n const match = /^hostname (.+)$/m.exec(stdout);\n return match ? match[1]!.trim().toLowerCase() : host;\n } catch {\n return host;\n }\n}\n\n/**\n * Deux remotes désignent-ils le même dépôt ? La comparaison porte sur\n * `hôte + chemin`, après résolution des alias SSH et normalisation.\n */\nexport async function sameGitRemote(\n a: string,\n b: string,\n resolveHost: (host: string) => Promise<string> = resolveSshHost,\n): Promise<boolean> {\n if (a.trim() === b.trim()) return true;\n const left = parseGitRemote(a);\n const right = parseGitRemote(b);\n if (!left || !right) return false;\n if (left.path !== right.path) return false;\n if (left.host === right.host) return true;\n const [leftHost, rightHost] = await Promise.all([\n resolveHost(left.host),\n resolveHost(right.host),\n ]);\n return leftHost === rightHost;\n}\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { aiSpawnManager } from '../../services/ai-spawn-manager.js';\nimport { codexAppServerManager } from '../../services/codex-app-server-manager.js';\nimport { writeContextFiles } from '../../services/ai-context-files.js';\nimport { savePastedImage } from '../../services/ai-paste-image.js';\n\nconst MAX_CONTEXT_FILES = 20;\nconst MAX_CONTEXT_FILE_BYTES = 1_000_000;\nconst MAX_CONTEXT_TOTAL_BYTES = 5_000_000;\n\nexport const aiRouter = router({\n /** Spawn an AI CLI process. Returns a spawnId for streaming. */\n spawn: protectedProcedure\n .input(z.object({\n cli: z.string().max(64),\n args: z.array(z.string().max(500_000)),\n env: z.record(z.string().max(256), z.string().max(500_000)).optional(),\n cwd: z.string().max(4096).optional(),\n stdinData: z.string().max(10_000_000).optional(),\n enableMcp: z.boolean().optional(),\n mcpApiBaseUrl: z.string().max(512).optional(),\n mcpApiToken: z.string().max(8192).optional(),\n mcpProjectId: z.string().max(128).optional(),\n mcpOrgId: z.string().max(128).optional(),\n }))\n .mutation(({ input }) => {\n const spawnId = aiSpawnManager.spawn(input);\n return { spawnId };\n }),\n\n /** Stream stdout/stderr/exit chunks from offset. Reconnectable. */\n stream: protectedProcedure\n .input(z.object({\n spawnId: z.string().max(128),\n fromOffset: z.number().int().min(0).default(0),\n }))\n .subscription(async function* ({ input }) {\n try {\n for await (const item of aiSpawnManager.stream(input.spawnId, input.fromOffset)) {\n yield item;\n }\n } catch (err) {\n throw new TRPCError({\n code: 'NOT_FOUND',\n message: (err as Error).message,\n });\n }\n }),\n\n /** Spawn an AI CLI process in a PTY (interactive mode). Returns spawnId. */\n spawnPty: protectedProcedure\n .input(z.object({\n cli: z.string().max(64),\n args: z.array(z.string().max(500_000)),\n env: z.record(z.string().max(256), z.string().max(500_000)).optional(),\n cwd: z.string().max(4096).optional(),\n cols: z.number().int().min(1).max(1000).optional(),\n rows: z.number().int().min(1).max(1000).optional(),\n sessionId: z.string().max(128).optional(),\n enableMcp: z.boolean().optional(),\n mcpApiBaseUrl: z.string().max(512).optional(),\n mcpApiToken: z.string().max(8192).optional(),\n mcpProjectId: z.string().max(128).optional(),\n mcpOrgId: z.string().max(128).optional(),\n }))\n .mutation(({ input }) => {\n const spawnId = aiSpawnManager.spawnPty(input);\n return { spawnId };\n }),\n\n /** Find a running PTY spawn by its logical sessionId (for re-attach). */\n findPtyBySession: protectedProcedure\n .input(z.object({ sessionId: z.string().max(128) }))\n .query(({ input }) => {\n return aiSpawnManager.findPtyBySessionId(input.sessionId);\n }),\n\n /** Write input to a PTY spawn (user keystrokes). */\n writePty: protectedProcedure\n .input(z.object({\n spawnId: z.string().max(128),\n data: z.string().max(1_000_000),\n }))\n .mutation(({ input }) => {\n const ok = aiSpawnManager.writePty(input.spawnId, input.data);\n return { ok };\n }),\n\n /** Write attached-context files for an AI session to a temp dir. Returns absolute paths. */\n writeContextFiles: protectedProcedure\n .input(z.object({\n sessionId: z.string().min(1).max(128),\n files: z.array(z.object({\n name: z.string().min(1).max(256),\n content: z.string().max(MAX_CONTEXT_FILE_BYTES),\n })).min(1).max(MAX_CONTEXT_FILES),\n }).refine(\n (val) => val.files.reduce((sum, f) => sum + f.content.length, 0) <= MAX_CONTEXT_TOTAL_BYTES,\n { message: `Total context size exceeds ${MAX_CONTEXT_TOTAL_BYTES} bytes` },\n ))\n .mutation(async ({ input }) => {\n const paths = await writeContextFiles(input.sessionId, input.files);\n return { paths };\n }),\n\n /**\n * Save a pasted image to disk and try to populate the agent's system clipboard\n * so Claude's native paste detection picks it up. Returns the tmp path and\n * which clipboard method (if any) succeeded — caller decides whether to send\n * Ctrl+V (\\x16) or inject `@<path>` into the PTY.\n */\n pasteImage: protectedProcedure\n .input(z.object({\n sessionId: z.string().max(128).optional(),\n mimeType: z.string().max(64),\n base64: z.string().max(15_000_000),\n }))\n .mutation(async ({ input }) => {\n const res = await savePastedImage(input.base64, input.mimeType, input.sessionId);\n return res;\n }),\n\n /** Resize a PTY spawn. */\n resizePty: protectedProcedure\n .input(z.object({\n spawnId: z.string().max(128),\n cols: z.number().int().min(1).max(1000),\n rows: z.number().int().min(1).max(1000),\n }))\n .mutation(({ input }) => {\n const ok = aiSpawnManager.resizePty(input.spawnId, input.cols, input.rows);\n return { ok };\n }),\n\n /** Kill a running AI spawn. */\n kill: protectedProcedure\n .input(z.object({ spawnId: z.string().max(128) }))\n .mutation(({ input }) => {\n const killed = aiSpawnManager.kill(input.spawnId);\n return { ok: killed };\n }),\n\n /** List all spawns with buffer (running + done). */\n list: protectedProcedure\n .query(() => {\n return aiSpawnManager.list();\n }),\n\n /** Acknowledge receipt of all data — agent can clean up after TTL. */\n ack: protectedProcedure\n .input(z.object({ spawnId: z.string().max(128) }))\n .mutation(({ input }) => {\n const acked = aiSpawnManager.ack(input.spawnId);\n return { ok: acked };\n }),\n\n /** Forward a JSON-RPC request to the local codex app-server. */\n codexRequest: protectedProcedure\n .input(z.object({\n method: z.string().max(256),\n params: z.record(z.string(), z.unknown()).default({}),\n env: z.record(z.string().max(256), z.string().max(500_000)).optional(),\n }))\n .mutation(async ({ input }) => {\n await codexAppServerManager.ensureConnected(input.env);\n const result = await codexAppServerManager.sendRequest(input.method, input.params);\n return { result };\n }),\n\n /** Stream notifications from the codex app-server. Optionally filter by threadId. */\n codexNotifications: protectedProcedure\n .input(z.object({\n threadId: z.string().max(256).optional(),\n }).default({}))\n .subscription(async function* ({ input, signal }) {\n await codexAppServerManager.ensureConnected();\n\n const queue: Array<{ method: string; params: Record<string, unknown> }> = [];\n let resolve: (() => void) | null = null;\n\n const unsub = codexAppServerManager.onNotification((method, params) => {\n // Filter by threadId if provided\n if (input.threadId) {\n const notifThreadId = (params['threadId'] as string | undefined)\n ?? ((params['turn'] as Record<string, unknown> | undefined)?.['threadId'] as string | undefined);\n // Only filter if the notification has a threadId — pass through unscoped notifications\n if (notifThreadId && notifThreadId !== input.threadId) return;\n }\n queue.push({ method, params });\n if (resolve) { resolve(); resolve = null; }\n });\n\n try {\n while (!signal?.aborted) {\n while (queue.length > 0) {\n yield queue.shift()!;\n }\n await new Promise<void>((r) => { resolve = r; });\n }\n } finally {\n unsub();\n }\n }),\n\n /** Shut down the codex app-server process. */\n codexShutdown: protectedProcedure\n .mutation(() => {\n codexAppServerManager.shutdown();\n return { ok: true };\n }),\n});\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\nimport { randomUUID } from 'node:crypto';\nimport * as pty from '@lydell/node-pty';\nimport { claudeMcpArgs, codexMcpArgs } from '@runeya/packages-mcp-server/launch';\nimport { resolveCliInvocation } from '@runeya/packages-shared/node';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\n/**\n * @public — export requis : ces types apparaissent dans les signatures inférées\n * du routeur tRPC de l'agent (sinon TS4023 : \"cannot be named\").\n */\nexport interface AiSpawnChunk {\n type: 'stdout' | 'stderr' | 'exit' | 'pty-data';\n data: string;\n code?: number;\n}\n\n/**\n * @public — export requis : ces types apparaissent dans les signatures inférées\n * du routeur tRPC de l'agent (sinon TS4023 : \"cannot be named\").\n */\nexport interface AiSpawnInfo {\n spawnId: string;\n cli: string;\n status: 'running' | 'done' | 'error';\n exitCode: number | null;\n bufferLength: number;\n createdAt: number;\n doneAt: number | null;\n lastChunkAt: number | null;\n}\n\ninterface AiSpawn {\n spawnId: string;\n /** Optional logical session key (e.g. Claude --session-id) used to re-attach. */\n sessionId?: string;\n cli: string;\n status: 'running' | 'done' | 'error';\n exitCode: number | null;\n buffer: AiSpawnChunk[];\n proc: ChildProcess | null;\n ptyProc: pty.IPty | null;\n emitter: EventEmitter;\n createdAt: number;\n doneAt: number | null;\n acked: boolean;\n /** Timestamp of the most recent stdout/stderr/pty data chunk. */\n lastChunkAt: number | null;\n}\n\ninterface AiSpawnPtyOpts {\n cli: string;\n args: string[];\n env?: Record<string, string>;\n cwd?: string;\n cols?: number;\n rows?: number;\n /** Optional logical session id (e.g. Claude --session-id) — enables re-attach. */\n sessionId?: string;\n /** When true, resolve @runeya/packages-mcp-server locally and inject --mcp-config. */\n enableMcp?: boolean;\n /** Runeya server base URL for MCP server env (e.g. \"http://localhost:4000\"). */\n mcpApiBaseUrl?: string;\n /** Runeya API bearer token forwarded to the MCP server as RUNEYA_API_TOKEN. */\n mcpApiToken?: string;\n /** Project of the conversation, used by the MCP server to anchor its tools. */\n mcpProjectId?: string;\n mcpOrgId?: string;\n}\n\ninterface AiSpawnOpts {\n cli: string;\n args: string[];\n env?: Record<string, string>;\n cwd?: string;\n stdinData?: string;\n /** When true, resolve @runeya/packages-mcp-server locally and inject --mcp-config. */\n enableMcp?: boolean;\n /** Runeya server base URL for MCP server env (e.g. \"http://localhost:4000\"). */\n mcpApiBaseUrl?: string;\n /** Runeya API bearer token forwarded to the MCP server as RUNEYA_API_TOKEN. */\n mcpApiToken?: string;\n /** Project of the conversation, used by the MCP server to anchor its tools. */\n mcpProjectId?: string;\n mcpOrgId?: string;\n}\n\n// ─── Constants ────────────────────────────────────────────────────────────\n\nconst MAX_BUFFER_LINES = 100_000;\nconst MAX_CONCURRENT_SPAWNS = 100;\nconst CLEANUP_INTERVAL_MS = 60_000;\nconst TTL_ACKED_MS = 5 * 60_000; // 5 min after ack\nconst TTL_UNACKED_MS = 24 * 3600_000; // 24h safety net\n// Running interactive PTYs never exit on their own (Claude waits for input\n// forever). Reap one that has produced no output for this long so a forgotten,\n// navigated-away session stops holding a concurrency slot indefinitely.\nconst TTL_IDLE_PTY_MS = 30 * 60_000; // 30 min of PTY silence\n\n// ─── Spawn preparation (shared by spawn + spawnPty) ─────────────────────────\n\ninterface RuneyaSpawnInput {\n cli: string;\n args: string[];\n env?: Record<string, string>;\n enableMcp?: boolean;\n mcpApiBaseUrl?: string;\n mcpApiToken?: string;\n mcpProjectId?: string;\n mcpOrgId?: string;\n}\n\n/**\n * Resolve the child process env and CLI args from spawn opts. Single source of\n * truth for both `spawn` (headless `-p`) and `spawnPty` (interactive) so the two\n * paths can never drift apart.\n *\n * Runeya credentials follow ONE channel: they are merged into the child env\n * (from `env` and/or `mcpApiBaseUrl`/`mcpApiToken`), and the MCP server config\n * env is *derived from that final child env*. Whether the token arrives via\n * `env.RUNEYA_API_TOKEN` (headless path) or `mcpApiToken` (PTY path), both the\n * CLI process (so `$RUNEYA_API_TOKEN` resolves in its shell) and the MCP server\n * always see the same credentials.\n */\nfunction resolveSpawnEnvAndArgs(opts: RuneyaSpawnInput): { env: NodeJS.ProcessEnv; args: string[] } {\n const runeyaEnv: Record<string, string> = {\n ...(opts.mcpApiBaseUrl ? { RUNEYA_BASE_URL: opts.mcpApiBaseUrl } : {}),\n ...(opts.mcpApiToken ? { RUNEYA_API_TOKEN: opts.mcpApiToken } : {}),\n ...(opts.mcpProjectId ? { RUNEYA_PROJECT_ID: opts.mcpProjectId } : {}),\n ...(opts.mcpOrgId ? { RUNEYA_ORG_ID: opts.mcpOrgId } : {}),\n };\n const env = { ...process.env, ...opts.env, ...runeyaEnv } as NodeJS.ProcessEnv;\n\n let args = [...opts.args];\n if (opts.enableMcp) {\n const mcpEnv = {\n RUNEYA_BASE_URL: env.RUNEYA_BASE_URL,\n RUNEYA_API_TOKEN: env.RUNEYA_API_TOKEN,\n RUNEYA_PROJECT_ID: env.RUNEYA_PROJECT_ID,\n RUNEYA_ORG_ID: env.RUNEYA_ORG_ID,\n };\n try {\n if (opts.cli === 'claude') {\n // `--mcp-config` est une option : sa place dans la ligne est libre.\n args.push(...claudeMcpArgs(mcpEnv));\n } else if (opts.cli === 'codex') {\n // Les surcharges `-c` doivent PRÉCÉDER la sous-commande (`resume`…),\n // sinon codex les rattache à elle et les refuse.\n args = [...codexMcpArgs(mcpEnv), ...args];\n }\n } catch (err) {\n console.warn('[ai-spawn-manager] Failed to resolve MCP server path:', (err as Error).message);\n }\n }\n\n return { env, args };\n}\n\n// ─── Manager ──────────────────────────────────────────────────────────────\n\nclass AiSpawnManager {\n private spawns = new Map<string, AiSpawn>();\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n\n constructor() {\n this.cleanupInterval = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);\n }\n\n spawn(opts: AiSpawnOpts): string {\n // Guard: max concurrent spawns\n const running = [...this.spawns.values()].filter(s => s.status === 'running').length;\n if (running >= MAX_CONCURRENT_SPAWNS) {\n throw new Error(`Max concurrent AI spawns reached (${MAX_CONCURRENT_SPAWNS})`);\n }\n\n const spawnId = randomUUID();\n const emitter = new EventEmitter();\n\n // Resolve env + MCP args via the shared helper (symmetric with spawnPty).\n const { env, args } = resolveSpawnEnvAndArgs(opts);\n\n const invocation = resolveCliInvocation(opts.cli, args);\n\n const proc = spawn(invocation.command, invocation.args, {\n windowsHide: true,\n stdio: ['pipe', 'pipe', 'pipe'],\n shell: false,\n env,\n cwd: opts.cwd || undefined,\n });\n\n const entry: AiSpawn = {\n spawnId,\n cli: opts.cli,\n status: 'running',\n exitCode: null,\n buffer: [],\n proc,\n ptyProc: null,\n emitter,\n createdAt: Date.now(),\n doneAt: null,\n acked: false,\n lastChunkAt: null,\n };\n\n this.spawns.set(spawnId, entry);\n\n // Stdin\n if (opts.stdinData) {\n proc.stdin!.write(opts.stdinData);\n }\n proc.stdin!.end();\n\n // Stdout\n proc.stdout!.on('data', (chunk: Buffer) => {\n const data = chunk.toString('utf-8');\n this.pushChunk(entry, { type: 'stdout', data });\n });\n\n // Stderr\n proc.stderr!.on('data', (chunk: Buffer) => {\n const data = chunk.toString('utf-8');\n this.pushChunk(entry, { type: 'stderr', data });\n });\n\n // Close\n proc.on('close', (code) => {\n entry.status = code === 0 ? 'done' : 'error';\n entry.exitCode = code;\n entry.doneAt = Date.now();\n entry.proc = null;\n this.pushChunk(entry, { type: 'exit', data: '', code: code ?? 1 });\n });\n\n // Error (e.g. ENOENT)\n proc.on('error', (err) => {\n entry.status = 'error';\n entry.doneAt = Date.now();\n entry.proc = null;\n this.pushChunk(entry, { type: 'stderr', data: `spawn error: ${err.message}` });\n this.pushChunk(entry, { type: 'exit', data: '', code: 1 });\n });\n\n console.log(`[ai-spawn-manager] Spawned ${opts.cli} (${spawnId}), args: ${opts.args.length}, cwd: ${opts.cwd ?? '(default)'}`);\n return spawnId;\n }\n\n async *stream(spawnId: string, fromOffset: number = 0): AsyncGenerator<{ offset: number; chunk: AiSpawnChunk }> {\n const entry = this.spawns.get(spawnId);\n if (!entry) throw new Error(`AI spawn ${spawnId} not found`);\n\n let offset = fromOffset;\n let resolve: (() => void) | null = null;\n let done = false;\n\n const onChunk = () => {\n if (resolve) { resolve(); resolve = null; }\n };\n const onDone = () => {\n done = true;\n if (resolve) { resolve(); resolve = null; }\n };\n\n entry.emitter.on('chunk', onChunk);\n entry.emitter.on('done', onDone);\n\n // If already finished and offset covers everything, check immediately\n if (entry.status !== 'running' && offset >= entry.buffer.length) {\n done = true;\n }\n\n try {\n while (true) {\n // Yield any buffered chunks from offset\n while (offset < entry.buffer.length) {\n yield { offset, chunk: entry.buffer[offset]! };\n offset++;\n }\n\n // If process finished and no more chunks, we're done\n if (entry.status !== 'running' && offset >= entry.buffer.length) {\n break;\n }\n\n if (done && offset >= entry.buffer.length) break;\n\n // Wait for next chunk\n await new Promise<void>((r) => { resolve = r; });\n }\n } finally {\n entry.emitter.off('chunk', onChunk);\n entry.emitter.off('done', onDone);\n }\n }\n\n kill(spawnId: string): boolean {\n const entry = this.spawns.get(spawnId);\n if (!entry) return false;\n if (entry.proc) {\n try { entry.proc.kill('SIGTERM'); } catch { /* already dead */ }\n return true;\n }\n if (entry.ptyProc) {\n try { entry.ptyProc.kill(); } catch { /* already dead */ }\n return true;\n }\n return false;\n }\n\n // ── PTY mode ────────────────────────────────────────────────────────────\n\n spawnPty(opts: AiSpawnPtyOpts): string {\n const running = [...this.spawns.values()].filter(s => s.status === 'running').length;\n if (running >= MAX_CONCURRENT_SPAWNS) {\n throw new Error(`Max concurrent AI spawns reached (${MAX_CONCURRENT_SPAWNS})`);\n }\n\n const spawnId = randomUUID();\n const emitter = new EventEmitter();\n\n // Resolve env + MCP args via the shared helper (symmetric with spawn).\n // This also injects RUNEYA_BASE_URL / RUNEYA_API_TOKEN into the PTY's own\n // env so `$RUNEYA_API_TOKEN` resolves in the interactive Claude shell.\n const { env, args } = resolveSpawnEnvAndArgs(opts);\n\n const invocation = resolveCliInvocation(opts.cli, args);\n\n const ptyProc = pty.spawn(invocation.command, invocation.args, {\n name: 'xterm-256color',\n cols: opts.cols ?? 120,\n rows: opts.rows ?? 30,\n cwd: opts.cwd || process.cwd(),\n env: env as Record<string, string>,\n });\n\n const entry: AiSpawn = {\n spawnId,\n sessionId: opts.sessionId,\n cli: opts.cli,\n status: 'running',\n exitCode: null,\n buffer: [],\n proc: null,\n ptyProc,\n emitter,\n createdAt: Date.now(),\n doneAt: null,\n acked: false,\n lastChunkAt: null,\n };\n\n this.spawns.set(spawnId, entry);\n\n ptyProc.onData((data: string) => {\n this.pushChunk(entry, { type: 'pty-data', data });\n });\n\n ptyProc.onExit(({ exitCode }) => {\n entry.status = exitCode === 0 ? 'done' : 'error';\n entry.exitCode = exitCode;\n entry.doneAt = Date.now();\n entry.ptyProc = null;\n this.pushChunk(entry, { type: 'exit', data: '', code: exitCode });\n });\n\n console.log(`[ai-spawn-manager] Spawned PTY ${opts.cli} (${spawnId}), args: ${opts.args.length}, cwd: ${opts.cwd ?? '(default)'}, ${opts.cols ?? 120}x${opts.rows ?? 30}`);\n return spawnId;\n }\n\n writePty(spawnId: string, data: string): boolean {\n const entry = this.spawns.get(spawnId);\n if (!entry || !entry.ptyProc) return false;\n try { entry.ptyProc.write(data); return true; } catch { return false; }\n }\n\n /** Return a running PTY spawn matching the given logical sessionId, if any. */\n findPtyBySessionId(sessionId: string): AiSpawnInfo | null {\n for (const entry of this.spawns.values()) {\n if (\n entry.sessionId === sessionId\n && entry.status === 'running'\n && entry.ptyProc !== null\n ) {\n return {\n spawnId: entry.spawnId,\n cli: entry.cli,\n status: entry.status,\n exitCode: entry.exitCode,\n bufferLength: entry.buffer.length,\n createdAt: entry.createdAt,\n doneAt: entry.doneAt,\n lastChunkAt: entry.lastChunkAt,\n };\n }\n }\n return null;\n }\n\n resizePty(spawnId: string, cols: number, rows: number): boolean {\n const entry = this.spawns.get(spawnId);\n if (!entry || !entry.ptyProc) return false;\n try { entry.ptyProc.resize(cols, rows); return true; } catch { return false; }\n }\n\n list(): AiSpawnInfo[] {\n return [...this.spawns.values()].map(e => ({\n spawnId: e.spawnId,\n cli: e.cli,\n status: e.status,\n exitCode: e.exitCode,\n bufferLength: e.buffer.length,\n createdAt: e.createdAt,\n doneAt: e.doneAt,\n lastChunkAt: e.lastChunkAt,\n }));\n }\n\n ack(spawnId: string): boolean {\n const entry = this.spawns.get(spawnId);\n if (!entry) return false;\n entry.acked = true;\n return true;\n }\n\n // ── Internal ────────────────────────────────────────────────────────────\n\n private pushChunk(entry: AiSpawn, chunk: AiSpawnChunk): void {\n // Cap buffer\n if (entry.buffer.length >= MAX_BUFFER_LINES) {\n entry.buffer.shift();\n }\n entry.buffer.push(chunk);\n if (chunk.type === 'stdout' || chunk.type === 'stderr' || chunk.type === 'pty-data') {\n entry.lastChunkAt = Date.now();\n }\n entry.emitter.emit('chunk');\n\n if (chunk.type === 'exit') {\n entry.emitter.emit('done');\n }\n }\n\n private cleanup(): void {\n const now = Date.now();\n for (const [id, entry] of this.spawns) {\n if (entry.status === 'running') {\n // Idle PTY reaper: an interactive PTY with no output for TTL_IDLE_PTY_MS\n // is assumed abandoned. Kill it; onExit flips it to done/error and a\n // later pass deletes it via the normal TTL path.\n if (entry.ptyProc) {\n const idle = now - (entry.lastChunkAt ?? entry.createdAt);\n if (idle > TTL_IDLE_PTY_MS) {\n try { entry.ptyProc.kill(); } catch { /* already dead */ }\n console.log(`[ai-spawn-manager] Reaped idle PTY ${id} (idle ${Math.round(idle / 1000)}s)`);\n }\n }\n continue;\n }\n\n const age = now - (entry.doneAt ?? entry.createdAt);\n\n // Acked: short TTL\n if (entry.acked && age > TTL_ACKED_MS) {\n this.spawns.delete(id);\n console.log(`[ai-spawn-manager] Cleaned up acked spawn ${id}`);\n }\n\n // Unacked: safety net TTL\n if (!entry.acked && age > TTL_UNACKED_MS) {\n this.spawns.delete(id);\n console.log(`[ai-spawn-manager] Cleaned up unacked spawn ${id} (TTL ${TTL_UNACKED_MS}ms)`);\n }\n }\n }\n\n shutdown(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n for (const entry of this.spawns.values()) {\n if (entry.proc) {\n try { entry.proc.kill('SIGTERM'); } catch { /* ignore */ }\n }\n if (entry.ptyProc) {\n try { entry.ptyProc.kill(); } catch { /* ignore */ }\n }\n }\n }\n}\n\nexport const aiSpawnManager = new AiSpawnManager();\n","import { fileURLToPath } from 'node:url';\nimport { createRequire } from 'node:module';\nimport { existsSync } from 'node:fs';\n\n/**\n * Comment brancher le serveur MCP Runeya sur un CLI d'IA.\n *\n * Runeya n'installe rien dans la configuration de la machine : il passe sa\n * config MCP en ligne de commande, au moment où il lance lui-même le CLI. Le\n * `~/.claude.json` ou le `~/.codex/config.toml` de l'utilisateur reste intact,\n * et un CLI lancé à la main depuis un terminal ne voit pas ce serveur.\n *\n * Chaque CLI a sa syntaxe — d'où ce module, seule source de vérité partagée par\n * les deux points de lancement (l'agent, et le serveur en mode local).\n */\n\n/** Variables d'environnement que le serveur MCP attend pour joindre Runeya. */\nexport interface RuneyaMcpEnv {\n RUNEYA_BASE_URL?: string;\n RUNEYA_API_TOKEN?: string;\n /**\n * Le projet de la conversation qui lance ce CLI, s'il y en a un.\n *\n * Le serveur MCP en fait le défaut des tools qui acceptent un `projectId` :\n * sans lui, `list_services` rend tous les projets de la machine, quand\n * l'écran et le prompt n'en montrent qu'un.\n */\n RUNEYA_PROJECT_ID?: string;\n RUNEYA_ORG_ID?: string;\n}\n\n/**\n * Chemin du point d'entrée du serveur MCP, à lancer avec `node`.\n *\n * Ne PAS se fier à `import.meta.url` pour viser `./index.js` : ce module est\n * bundlé dans l'agent et dans le serveur (tsup y bundle les paquets @runeya\n * via `noExternal`), donc\n * `import.meta.url` y désigne le bundle hôte, pas ce paquet. On résout donc le\n * paquet, puis on sonde les emplacements de la version packagée, où les liens\n * symboliques de l'espace de travail n'existent plus.\n */\nexport function resolveMcpServerPath(): string {\n try {\n const req = createRequire(import.meta.url);\n return req.resolve('@runeya/packages-mcp-server');\n } catch { /* pas de node_modules résolvable : on sonde le disque */ }\n\n const candidates = [\n // Build packagé du CLI : dist/agent/index.js et dist/index.js côtoient\n // dist/mcp-server/, copié là par le post-build.\n new URL('../mcp-server/index.js', import.meta.url),\n new URL('./mcp-server/index.js', import.meta.url),\n // Monorepo, depuis un dist d'app.\n new URL('../../../packages/mcp-server/dist/index.js', import.meta.url),\n new URL('../../../../packages/mcp-server/dist/index.js', import.meta.url),\n ];\n for (const c of candidates) {\n const p = fileURLToPath(c);\n if (existsSync(p)) return p;\n }\n throw new Error('Could not locate @runeya/packages-mcp-server (built dist not found)');\n}\n\n/** Ne garde que les variables renseignées : une valeur vide n'aide personne. */\nfunction pickEnv(env: RuneyaMcpEnv): Record<string, string> {\n return {\n ...(env.RUNEYA_BASE_URL ? { RUNEYA_BASE_URL: env.RUNEYA_BASE_URL } : {}),\n ...(env.RUNEYA_API_TOKEN ? { RUNEYA_API_TOKEN: env.RUNEYA_API_TOKEN } : {}),\n ...(env.RUNEYA_PROJECT_ID ? { RUNEYA_PROJECT_ID: env.RUNEYA_PROJECT_ID } : {}),\n ...(env.RUNEYA_ORG_ID ? { RUNEYA_ORG_ID: env.RUNEYA_ORG_ID } : {}),\n };\n}\n\n/**\n * La config MCP de Runeya, au format `mcpServers` attendu par `--mcp-config`.\n *\n * Seul endroit du dépôt où ce JSON se fabrique. `chat.ts` en tenait deux copies\n * qui résolvaient le chemin avec `import.meta.url` — le piège que\n * `resolveMcpServerPath()` documente juste au-dessus : bundlées dans l'app\n * hôte, elles visaient un fichier qui n'existe pas, et le CLI démarrait sans\n * les tools Runeya, en silence.\n */\nexport function runeyaMcpConfig(env: RuneyaMcpEnv): string {\n return JSON.stringify({\n mcpServers: {\n runeya: {\n command: 'node',\n args: [resolveMcpServerPath()],\n env: pickEnv(env),\n },\n },\n });\n}\n\n/**\n * Arguments `--mcp-config` pour le CLI `claude`, qui attend du JSON.\n *\n * Volontairement non strict : le CLI démarre aussi les serveurs MCP de la\n * machine. Cela coûte quelques secondes par lancement, mais l'utilisateur garde\n * ses propres outils.\n */\nexport function claudeMcpArgs(env: RuneyaMcpEnv): string[] {\n return ['--mcp-config', runeyaMcpConfig(env)];\n}\n\n/**\n * Arguments `-c` pour le CLI `codex`, qui attend du TOML.\n *\n * Codex n'a pas d'équivalent de `--mcp-config` : il expose des surcharges de\n * configuration en TOML (`-c chemin.pointé=valeur`), à placer AVANT la\n * sous-commande. Une table inline décrit le serveur en une seule surcharge.\n */\nexport function codexMcpArgs(env: RuneyaMcpEnv): string[] {\n const fields = [\n `command=${tomlString('node')}`,\n `args=[${tomlString(resolveMcpServerPath())}]`,\n ];\n\n const entries = Object.entries(pickEnv(env));\n if (entries.length > 0) {\n const inline = entries.map(([k, v]) => `${k}=${tomlString(v)}`).join(',');\n fields.push(`env={${inline}}`);\n }\n\n return ['-c', `mcp_servers.runeya={${fields.join(',')}}`];\n}\n\n/**\n * Chaîne TOML de base : seuls la contre-oblique et le guillemet doivent être\n * échappés. Les caractères de contrôle, eux, sont interdits par le format — un\n * chemin ou un jeton qui en contiendrait casserait la config en silence.\n */\nfunction tomlString(value: string): string {\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/[\\u0000-\\u001f\\u007f]/g, (c) => `\\\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`);\n return `\"${escaped}\"`;\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline';\nimport { EventEmitter } from 'node:events';\nimport { codexMcpArgs } from '@runeya/packages-mcp-server/launch';\nimport { resolveCliInvocation } from '@runeya/packages-shared/node';\n\ninterface PendingRequest {\n resolve: (result: unknown) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\nconst REQUEST_TIMEOUT_MS = 300_000; // 5 min — turns can be long\n\n/**\n * Surcharges `-c` qui branchent le serveur MCP Runeya sur `codex app-server`.\n *\n * Le pendant de ce que `ai-spawn-manager` fait pour `claude` : rien n'est écrit\n * dans le `~/.codex/config.toml` de l'utilisateur, la config ne vit que le temps\n * du process. Les surcharges doivent précéder la sous-commande.\n *\n * Sans jeton Runeya, le serveur MCP ne pourrait rien appeler : on n'injecte donc\n * rien plutôt que de faire démarrer un serveur inutile à chaque lancement.\n */\nfunction resolveMcpArgs(env: NodeJS.ProcessEnv): string[] {\n if (!env['RUNEYA_API_TOKEN']) return [];\n try {\n return codexMcpArgs({\n RUNEYA_BASE_URL: env['RUNEYA_BASE_URL'],\n RUNEYA_API_TOKEN: env['RUNEYA_API_TOKEN'],\n });\n } catch (err) {\n console.warn('[codex-app-server-mgr] Failed to resolve MCP server path:', (err as Error).message);\n return [];\n }\n}\n\nclass CodexAppServerManager extends EventEmitter {\n private proc: ChildProcess | null = null;\n private rl: ReadlineInterface | null = null;\n private nextId = 1;\n private pending = new Map<number, PendingRequest>();\n private connected = false;\n private connecting: Promise<void> | null = null;\n\n private extraEnv: Record<string, string> = {};\n\n /** Ensure the app-server is running and initialized. Lazy — first call spawns it. */\n async ensureConnected(env?: Record<string, string>): Promise<void> {\n // Merge env vars — they'll be used on next spawn if not already connected\n if (env) Object.assign(this.extraEnv, env);\n if (this.connected) return;\n if (this.connecting) { await this.connecting; return; }\n\n this.connecting = this.doConnect();\n try {\n await this.connecting;\n } finally {\n this.connecting = null;\n }\n }\n\n private async doConnect(): Promise<void> {\n const env = { ...process.env, ...this.extraEnv };\n\n // Windows : shim `.cmd` — inchangé sur POSIX (voir resolveCliInvocation).\n const invocation = resolveCliInvocation('codex', [...resolveMcpArgs(env), 'app-server']);\n this.proc = spawn(invocation.command, invocation.args, {\n windowsHide: true,\n stdio: ['pipe', 'pipe', 'pipe'],\n env,\n });\n\n this.rl = createInterface({ input: this.proc.stdout! });\n this.rl.on('line', (line) => this.handleLine(line));\n\n this.proc.stderr!.on('data', (chunk: Buffer) => {\n console.warn(`[codex-app-server-mgr] stderr: ${chunk.toString('utf-8').trim()}`);\n });\n\n this.proc.on('exit', (code, signal) => {\n console.warn(`[codex-app-server-mgr] exited code=${code} signal=${signal}`);\n this.rejectAllPending(new Error(`codex app-server exited (code=${code})`));\n this.connected = false;\n this.proc = null;\n this.rl = null;\n this.emit('exit', code);\n });\n\n this.proc.on('error', (err) => {\n console.error(`[codex-app-server-mgr] spawn error:`, err.message);\n this.rejectAllPending(err);\n this.connected = false;\n this.proc = null;\n });\n\n // Initialize handshake\n await this.sendRequest('initialize', {\n clientInfo: { name: 'runeya-agent', title: 'Runeya Agent', version: '1.0.0' },\n capabilities: { experimentalApi: false },\n });\n this.writeLine({ method: 'initialized', params: {} });\n this.connected = true;\n console.log('[codex-app-server-mgr] Connected and initialized');\n }\n\n /** Forward a JSON-RPC request to the app-server and return the result. */\n async sendRequest(method: string, params: Record<string, unknown>): Promise<unknown> {\n if (!this.proc?.stdin?.writable) {\n throw new Error('codex app-server not connected');\n }\n const id = this.nextId++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error(`Request ${method} (id=${id}) timed out`));\n }, REQUEST_TIMEOUT_MS);\n this.pending.set(id, { resolve, reject, timer });\n this.writeLine({ jsonrpc: '2.0', method, id, params });\n });\n }\n\n /** Register a listener for all notifications. Returns unsubscribe function. */\n onNotification(handler: (method: string, params: Record<string, unknown>) => void): () => void {\n const wrapper = (method: string, params: Record<string, unknown>) => handler(method, params);\n this.on('notification', wrapper);\n return () => { this.off('notification', wrapper); };\n }\n\n get isConnected(): boolean { return this.connected; }\n\n shutdown(): void {\n if (this.proc) {\n try { this.proc.kill('SIGTERM'); } catch { /* ignore */ }\n }\n this.connected = false;\n this.rl?.close();\n this.rl = null;\n this.proc = null;\n this.rejectAllPending(new Error('Shutdown'));\n }\n\n private writeLine(obj: Record<string, unknown>): void {\n if (!this.proc?.stdin?.writable) return;\n this.proc.stdin.write(JSON.stringify(obj) + '\\n');\n }\n\n private handleLine(line: string): void {\n const trimmed = line.trim();\n if (!trimmed) return;\n\n let msg: Record<string, unknown>;\n try { msg = JSON.parse(trimmed); } catch { return; }\n\n // Response to pending request\n if ('id' in msg && typeof msg['id'] === 'number' && ('result' in msg || 'error' in msg)) {\n const p = this.pending.get(msg['id'] as number);\n if (p) {\n this.pending.delete(msg['id'] as number);\n clearTimeout(p.timer);\n if ('error' in msg && msg['error']) {\n const err = msg['error'] as { code: number; message: string };\n p.reject(new Error(`JSON-RPC error ${err.code}: ${err.message}`));\n } else {\n p.resolve(msg['result']);\n }\n }\n return;\n }\n\n // Notification (no id, has method)\n if ('method' in msg && typeof msg['method'] === 'string' && !('id' in msg)) {\n this.emit('notification', msg['method'] as string, (msg['params'] ?? {}) as Record<string, unknown>);\n }\n }\n\n private rejectAllPending(error: Error): void {\n for (const [, p] of this.pending) {\n clearTimeout(p.timer);\n p.reject(error);\n }\n this.pending.clear();\n }\n}\n\nexport const codexAppServerManager = new CodexAppServerManager();\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst ROOT_DIR_NAME = 'runeya-ai-context';\n\n/** Sanitize a filename so it stays on a single path segment and only contains safe chars. */\nfunction sanitizeName(name: string): string {\n // Replace path separators / unsafe chars with `_`. Keep [A-Za-z0-9._-].\n let safe = name.replace(/[^A-Za-z0-9._-]/g, '_');\n // Avoid empty / leading-dot weirdness.\n if (!safe || safe === '.' || safe === '..') safe = 'context';\n // Append `.md` if no extension.\n if (!/\\.[A-Za-z0-9]+$/.test(safe)) safe += '.md';\n return safe;\n}\n\nfunction sanitizeSessionId(sessionId: string): string {\n const safe = sessionId.replace(/[^A-Za-z0-9._-]/g, '_');\n return safe || 'session';\n}\n\nexport interface ContextFileInput {\n name: string;\n content: string;\n}\n\n/**\n * Write context files to <os.tmpdir()>/runeya-ai-context/<sessionId>/<sanitized-name>.\n * Returns absolute paths in input order.\n */\nexport async function writeContextFiles(\n sessionId: string,\n files: ContextFileInput[],\n): Promise<string[]> {\n const baseDir = path.join(os.tmpdir(), ROOT_DIR_NAME, sanitizeSessionId(sessionId));\n await mkdir(baseDir, { recursive: true });\n\n const paths: string[] = [];\n const usedNames = new Set<string>();\n for (let i = 0; i < files.length; i++) {\n const file = files[i]!;\n let name = sanitizeName(file.name);\n // Deduplicate within this batch.\n if (usedNames.has(name)) {\n const ext = path.extname(name);\n const base = name.slice(0, name.length - ext.length);\n name = `${base}-${i}${ext}`;\n }\n usedNames.add(name);\n const fullPath = path.join(baseDir, name);\n await writeFile(fullPath, file.content, 'utf8');\n paths.push(fullPath);\n }\n return paths;\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport { spawn } from 'node:child_process';\n\nconst TMP_DIR_NAME = 'runeya-ai-paste';\n\nconst MIME_TO_EXT: Record<string, string> = {\n 'image/png': 'png',\n 'image/jpeg': 'jpg',\n 'image/jpg': 'jpg',\n 'image/gif': 'gif',\n 'image/webp': 'webp',\n 'image/bmp': 'bmp',\n};\n\nfunction extForMime(mime: string): string {\n return MIME_TO_EXT[mime.toLowerCase()] ?? 'png';\n}\n\n/** Run a shell command, optionally piping a buffer to stdin. Resolves with exitCode. */\nfunction runCmd(\n cmd: string,\n args: string[],\n stdin?: Buffer,\n timeoutMs = 5000,\n): Promise<{ code: number; stderr: string }> {\n return new Promise((resolve) => {\n let settled = false;\n const settle = (code: number, stderr: string) => {\n if (settled) return;\n settled = true;\n resolve({ code, stderr });\n };\n try {\n const child = spawn(cmd, args, { stdio: ['pipe', 'ignore', 'pipe'], windowsHide: true });\n let stderr = '';\n child.stderr.on('data', (c) => { stderr += c.toString(); });\n child.on('error', (err) => settle(127, err.message));\n child.on('exit', (code) => settle(code ?? 1, stderr));\n const t = setTimeout(() => {\n try { child.kill('SIGKILL'); } catch { /* ignore */ }\n settle(124, 'timeout');\n }, timeoutMs);\n child.on('exit', () => clearTimeout(t));\n if (stdin) {\n child.stdin.on('error', () => { /* swallow EPIPE */ });\n child.stdin.end(stdin);\n } else {\n child.stdin.end();\n }\n } catch (err) {\n settle(127, (err as Error).message);\n }\n });\n}\n\ntype ClipboardMethod = 'xclip' | 'wl-copy' | 'pbcopy' | 'powershell' | null;\n\nexport interface PasteImageResult {\n tmpPath: string;\n clipboardMethod: ClipboardMethod;\n clipboardError?: string;\n}\n\n/**\n * Save a pasted image (base64) to a tmp file on disk and try to populate the\n * agent's system clipboard with it (so Claude's native paste detection picks\n * it up). Falls back to file-only injection (`@path`) if no clipboard tool is\n * available.\n */\nexport async function savePastedImage(\n base64: string,\n mimeType: string,\n sessionId: string | undefined,\n): Promise<PasteImageResult> {\n const buf = Buffer.from(base64, 'base64');\n if (buf.length === 0) throw new Error('Empty image payload');\n\n const ext = extForMime(mimeType);\n const baseDir = path.join(\n os.tmpdir(),\n TMP_DIR_NAME,\n sessionId ? sessionId.replaceAll(/[^A-Za-z0-9._-]/g, '_') : 'default',\n );\n await mkdir(baseDir, { recursive: true });\n const tmpPath = path.join(baseDir, `paste-${Date.now()}-${randomUUID().slice(0, 8)}.${ext}`);\n await writeFile(tmpPath, buf);\n\n const { method, error } = await tryWriteClipboard(buf, mimeType, tmpPath);\n\n return { tmpPath, clipboardMethod: method, clipboardError: error };\n}\n\nasync function tryWriteClipboard(\n buf: Buffer,\n mimeType: string,\n tmpPath: string,\n): Promise<{ method: ClipboardMethod; error?: string }> {\n const normalizedMime = mimeType.toLowerCase();\n const errors: string[] = [];\n\n if (process.platform === 'darwin') {\n // macOS: use osascript with a typed file reference. Only PNG/JPEG/TIFF\n // are well-supported as clipboard image types; for others, fall through.\n const klass = normalizedMime === 'image/jpeg' || normalizedMime === 'image/jpg'\n ? 'JPEG picture'\n : 'PNGf';\n const script = `set the clipboard to (read (POSIX file \"${tmpPath.replaceAll('\"', '\\\\\"')}\") as «class ${klass}»)`;\n const r = await runCmd('osascript', ['-e', script]);\n if (r.code === 0) return { method: 'pbcopy' };\n errors.push(`osascript: ${r.stderr.trim()}`);\n }\n\n // Linux X11 — xclip\n if (process.platform === 'linux') {\n const r = await runCmd('xclip', ['-selection', 'clipboard', '-t', normalizedMime, '-i'], buf);\n if (r.code === 0) return { method: 'xclip' };\n errors.push(`xclip: ${r.stderr.trim() || `exit ${r.code}`}`);\n\n // Linux Wayland — wl-copy\n const r2 = await runCmd('wl-copy', ['--type', normalizedMime], buf);\n if (r2.code === 0) return { method: 'wl-copy' };\n errors.push(`wl-copy: ${r2.stderr.trim() || `exit ${r2.code}`}`);\n }\n\n if (process.platform === 'win32') {\n // PowerShell: load image from disk, set as clipboard image.\n const ps = `Add-Type -AssemblyName System.Windows.Forms; ` +\n `Add-Type -AssemblyName System.Drawing; ` +\n `$img = [System.Drawing.Image]::FromFile(\"${tmpPath.replaceAll('\\\\', '\\\\\\\\')}\"); ` +\n `[System.Windows.Forms.Clipboard]::SetImage($img); $img.Dispose()`;\n const r = await runCmd('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', ps]);\n if (r.code === 0) return { method: 'powershell' };\n errors.push(`powershell: ${r.stderr.trim() || `exit ${r.code}`}`);\n }\n\n return { method: null, error: errors.join(' | ') || 'no clipboard tool available' };\n}\n\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { readFile, readdir, stat, realpath, writeFile, mkdir, rename, rm } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport type { Dirent } from 'node:fs';\nimport { resolve as resolvePath, join, relative, sep } from 'node:path';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { expandEnvVar } from '../../utils/env.js';\n\nconst CWD_SCHEMA = z.string().min(1).max(4096);\nconst REL_PATH_SCHEMA = z\n .string()\n .min(1)\n .max(512)\n .regex(/^[A-Za-z0-9_./-]+$/)\n .refine((p) => !p.includes('..') && !p.startsWith('/'), {\n message: 'Path must be a relative path without traversal',\n });\n\nconst MAX_FILES = 500;\nconst MAX_DEPTH = 8;\nconst MAX_FILE_BYTES = 2_000_000;\nconst IGNORED_DIRS = new Set([\n 'node_modules', '.git', 'dist', 'build', '.next', '.turbo',\n '.cache', 'coverage', '.yarn', '.pnpm-store', 'target', 'out',\n]);\n\ntype RepoFileEntry = { type: 'file'; name: string; path: string };\ntype RepoDirEntry = { type: 'dir'; name: string; path: string; children: RepoEntry[] };\nexport type RepoEntry = RepoFileEntry | RepoDirEntry;\n\nconst RepoEntrySchema: z.ZodType<RepoEntry> = z.lazy(() => z.union([\n z.object({ type: z.literal('file'), name: z.string(), path: z.string() }),\n z.object({ type: z.literal('dir'), name: z.string(), path: z.string(), children: z.array(RepoEntrySchema) }),\n]));\n\nasync function walkMarkdown(root: string, dir: string, depth: number, counter: { n: number }): Promise<RepoEntry[]> {\n if (depth > MAX_DEPTH || counter.n >= MAX_FILES) return [];\n let entries: Dirent[];\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n const out: RepoEntry[] = [];\n for (const e of entries) {\n if (counter.n >= MAX_FILES) break;\n if (e.name.startsWith('.') && e.name !== '.') continue;\n const abs = join(dir, e.name);\n const rel = relative(root, abs).split(sep).join('/');\n if (e.isDirectory()) {\n if (IGNORED_DIRS.has(e.name)) continue;\n const children = await walkMarkdown(root, abs, depth + 1, counter);\n out.push({ type: 'dir', name: e.name, path: rel, children });\n } else if (e.isFile() && /\\.(md|markdown)$/i.test(e.name)) {\n counter.n += 1;\n out.push({ type: 'file', name: e.name, path: rel });\n }\n }\n out.sort((a, b) => {\n if (a.type !== b.type) return a.type === 'dir' ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n return out;\n}\n\n/**\n * Resolve a relative path inside the root with traversal protection.\n * If `requireExist`, the target must exist on disk (uses realpath).\n * Otherwise resolves the parent's realpath and joins the leaf — this allows\n * creating new files/dirs while still preventing escape via symlinks.\n */\nasync function resolveSafePath(root: string, relPath: string, requireExist: boolean): Promise<string> {\n if (relPath.includes('..') || relPath.startsWith('/')) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Chemin invalide' });\n }\n const target = resolvePath(root, relPath);\n if (requireExist) {\n let real: string;\n try { real = await realpath(target); } catch {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Chemin introuvable' });\n }\n if (real !== root && !(real + sep).startsWith(root + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Hors du dossier autorisé' });\n }\n return real;\n }\n // For non-existing targets: check parent\n const parent = dirname(target);\n let realParent: string;\n try { realParent = await realpath(parent); } catch {\n // Parent doesn't exist either — must be created via createDir first or\n // the operation will create parents itself.\n realParent = parent;\n }\n if (realParent !== root && !(realParent + sep).startsWith(root + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Hors du dossier autorisé' });\n }\n // Reassemble the safe absolute path with the verified parent\n return resolvePath(realParent, target.slice(parent.length).replace(/^[\\\\/]+/, ''));\n}\n\nasync function resolveRoot(cwd: string): Promise<string> {\n const expanded = expandEnvVar(cwd);\n const abs = resolvePath(expanded);\n try {\n return await realpath(abs);\n } catch {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Dossier introuvable: ${abs}` });\n }\n}\n\nexport const wikiRouter = router({\n listRepoMarkdown: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const root = await resolveRoot(input.cwd);\n const counter = { n: 0 };\n const entries = await walkMarkdown(root, root, 0, counter);\n return { root, entries, truncated: counter.n >= MAX_FILES };\n }),\n\n readRepoMarkdown: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, path: REL_PATH_SCHEMA }))\n .query(async ({ input }) => {\n if (!/\\.(md|markdown)$/i.test(input.path)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Seuls les .md sont autorisés' });\n }\n const root = await resolveRoot(input.cwd);\n const target = resolvePath(root, input.path);\n let realTarget: string;\n try {\n realTarget = await realpath(target);\n } catch {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Fichier introuvable' });\n }\n const realTargetWithSep = realTarget + sep;\n if (realTarget !== root && !realTargetWithSep.startsWith(root + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Hors du dossier du service' });\n }\n const s = await stat(realTarget);\n if (!s.isFile()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Pas un fichier' });\n }\n if (s.size > MAX_FILE_BYTES) {\n throw new TRPCError({ code: 'PAYLOAD_TOO_LARGE', message: 'Fichier trop volumineux' });\n }\n const content = await readFile(realTarget, 'utf-8');\n return { path: input.path, content };\n }),\n\n writeMarkdown: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n path: REL_PATH_SCHEMA,\n content: z.string().max(5_000_000),\n }))\n .mutation(async ({ input }) => {\n if (!/\\.(md|markdown)$/i.test(input.path)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Seuls les .md/.markdown sont autorisés' });\n }\n const root = await resolveRoot(input.cwd);\n const target = await resolveSafePath(root, input.path, false);\n // Ensure parent exists\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, input.content, 'utf-8');\n return { path: input.path, ok: true };\n }),\n\n createFile: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, path: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n if (!/\\.(md|markdown)$/i.test(input.path)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Seuls les .md/.markdown sont autorisés' });\n }\n const root = await resolveRoot(input.cwd);\n const target = await resolveSafePath(root, input.path, false);\n // Refuse to overwrite existing\n try {\n await stat(target);\n throw new TRPCError({ code: 'CONFLICT', message: 'Fichier déjà existant' });\n } catch (err) {\n if (err instanceof TRPCError) throw err;\n // ENOENT — good, proceed\n }\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, '', 'utf-8');\n return { path: input.path, ok: true };\n }),\n\n createDir: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, path: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n const root = await resolveRoot(input.cwd);\n const target = await resolveSafePath(root, input.path, false);\n await mkdir(target, { recursive: true });\n return { path: input.path, ok: true };\n }),\n\n renamePath: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n fromPath: REL_PATH_SCHEMA,\n toPath: REL_PATH_SCHEMA,\n }))\n .mutation(async ({ input }) => {\n const root = await resolveRoot(input.cwd);\n const from = await resolveSafePath(root, input.fromPath, true);\n const to = await resolveSafePath(root, input.toPath, false);\n // Refuse to overwrite an existing target\n try {\n await stat(to);\n throw new TRPCError({ code: 'CONFLICT', message: 'La cible existe déjà' });\n } catch (err) {\n if (err instanceof TRPCError) throw err;\n }\n await mkdir(dirname(to), { recursive: true });\n await rename(from, to);\n return { fromPath: input.fromPath, toPath: input.toPath, ok: true };\n }),\n\n ensureRoot: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .mutation(async ({ input }) => {\n const expanded = expandEnvVar(input.cwd);\n const abs = resolvePath(expanded);\n await mkdir(abs, { recursive: true });\n const root = await realpath(abs);\n return { root, ok: true };\n }),\n\n deletePath: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, path: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n const root = await resolveRoot(input.cwd);\n const target = await resolveSafePath(root, input.path, true);\n if (target === root) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Impossible de supprimer la racine' });\n }\n await rm(target, { recursive: true, force: true });\n return { path: input.path, ok: true };\n }),\n});\n\n","import { router } from './trpc.js';\nimport { processRouter } from './routers/process.js';\nimport { healthRouter } from './routers/health.js';\nimport { configRouter } from './routers/config.js';\nimport { terminalRouter } from './routers/terminal.js';\nimport { gitRouter } from './routers/git.js';\nimport { aiRouter } from './routers/ai.js';\nimport { wikiRouter } from './routers/wiki.js';\n\nexport const appRouter = router({\n process: processRouter,\n health: healthRouter,\n config: configRouter,\n terminal: terminalRouter,\n git: gitRouter,\n ai: aiRouter,\n wiki: wikiRouter,\n});\n\n","import type { Server } from 'node:http';\nimport { createAgent } from './create-agent.js';\nimport { env } from './config/env.js';\nimport { ensureNodeBinOnPath, ensureUserBinsOnPath, stampConsole } from '@runeya/packages-shared/node';\n\n/**\n * Listen with retry for EADDRINUSE — handles the race condition when the CLI\n * restarts the server before the old agent has fully released the port.\n */\nfunction listenWithRetry(\n server: Server,\n port: number,\n host: string,\n maxRetries = 20,\n delay = 500,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n\n const tryListen = () => {\n const onError = (err: NodeJS.ErrnoException) => {\n // Clean up the 'listening' callback that server.listen() registered\n server.removeAllListeners('listening');\n\n if (err.code === 'EADDRINUSE' && attempts < maxRetries) {\n attempts++;\n console.log(`[agent] Port ${port} in use, retrying in ${delay}ms (${attempts}/${maxRetries})...`);\n setTimeout(tryListen, delay);\n } else {\n reject(err);\n }\n };\n\n server.once('error', onError);\n server.listen(port, host, () => {\n server.removeListener('error', onError);\n resolve();\n });\n };\n\n tryListen();\n });\n}\n\n// Node.js recursive fs.watch can throw ENOENT when a directory disappears\n// between the inotify notification and the internal readdirSync call.\n// Despite having .on('error') handlers, some Node versions emit the error\n// before the handler can catch it. Prevent agent crash for these benign errors.\nprocess.on('uncaughtException', (err: NodeJS.ErrnoException) => {\n if (err.code === 'ENOENT' && err.syscall === 'scandir') {\n console.warn(`[agent] Ignoring transient FSWatcher ENOENT: ${err.path}`);\n return;\n }\n console.error('[agent] Uncaught exception:', err);\n process.exit(1);\n});\n\nasync function main() {\n // Avant tout lancement de service : ce que l'agent hérite ici est ce que\n // chaque processus enfant héritera de lui.\n ensureNodeBinOnPath();\n // Puis ce que l'utilisateur a installé pour lui-même (claude, codex…) : un\n // raccourci de bureau n'hérite pas du PATH de son shell de connexion.\n await ensureUserBinsOnPath();\n\n // L'agent est un process à part, même lancé par le serveur : son `console`\n // n'est pas celui du CLI, et son delta part de son propre démarrage.\n stampConsole();\n\n const { server, shutdown, passphraseHex } = createAgent({\n passphraseHex: env.PASSPHRASE_OVERRIDE,\n });\n\n let shuttingDown = false;\n const gracefulShutdown = async () => {\n if (shuttingDown) {\n process.exit(1);\n }\n shuttingDown = true;\n console.log('Shutting down agent...');\n await shutdown();\n process.exit(0);\n };\n\n // Register before listenWithRetry so Ctrl+C works during the retry loop.\n process.on('SIGTERM', gracefulShutdown);\n process.on('SIGINT', gracefulShutdown);\n\n await listenWithRetry(server, env.RUNEYA_AGENT_PORT, env.RUNEYA_AGENT_HOST);\n // Print passphrase AFTER server is listening so the spawner's\n // first health check finds the HTTP server ready.\n //\n // Écrite sur stdout SANS passer par `console` : cette ligne n'est pas un\n // journal, c'est le canal par lequel le serveur récupère la passphrase, et il\n // la reconnaît sur un motif ancré en début de ligne. Un horodatage devant\n // l'aurait rendue invisible — le serveur attendait alors son délai entier\n // avant de renoncer.\n process.stdout.write(`RUNEYA_PASSPHRASE=${passphraseHex}\\n`);\n console.log(`Agent listening on ${env.RUNEYA_AGENT_HOST}:${env.RUNEYA_AGENT_PORT}`);\n}\n\nmain().catch((err) => {\n console.error('Failed to start agent:', err);\n process.exit(1);\n});\n"],"mappings":"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","names":["crypto","z","TRPCError","EventEmitter","randomUUID","homedir","platform","join","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","env","escape","env","resolve","execa","homedir","expandEnvVars","resolve","env","process","randomUUID","indexed","randomUUID","directive","pid","EventEmitter","fastId","stat","EventEmitter","idCounter","fastId","EventEmitter","logIdCounter","fastId","MAX_RETRIES","rows","resolve","EventEmitter","resolve","EventEmitter","EventEmitter","execa","homedir","z","execFile","mkdir","writeFile","access","join","homedir","join","homedir","writeFile","mkdir","resolve","execFile","readdir","stat","access","z","env","homedir","resolveCwd","shellwordsSplit","env","EventEmitter","path","resolveCwd","execa","z","z","join","platform","homedir","EventEmitter","env","randomUUID","resolve","z","TRPCError","resolve","networkInterfaces","homedir","platform","execFile","homedir","join","delimiter","execFile","join","homedir","delimiter","path","startedAt","execFile","existsSync","dirname","resolve","execFile","randomBytes","createCipheriv","createDecipheriv","getLanIp","networkInterfaces","platform","homedir","z","TRPCError","EventEmitter","randomUUID","z","TRPCError","resolve","z","TRPCError","execFile","spawn","promisify","existsSync","fsPromises","join","resolvePath","execFile","promisify","execFileAsync","path","execFileAsync","promisify","execFile","z","env","TRPCError","existsSync","Y","resolvePath","fsPromises","resolve","modified","join","spawn","z","TRPCError","spawn","EventEmitter","randomUUID","pty","existsSync","env","env","randomUUID","EventEmitter","spawn","resolve","spawn","createInterface","EventEmitter","env","EventEmitter","spawn","createInterface","resolve","mkdir","writeFile","os","mkdir","writeFile","path","os","randomUUID","spawn","resolve","t","z","TRPCError","resolve","z","TRPCError","readFile","stat","writeFile","mkdir","rename","dirname","resolvePath","join","CWD_SCHEMA","z","join","TRPCError","resolvePath","dirname","stat","readFile","mkdir","writeFile","rename","crypto","resolve","resolve"]}
|
|
1
|
+
{"version":3,"sources":["../src/create-agent.ts","../src/trpc/trpc.ts","../src/trpc/routers/process.ts","../src/services/process-manager.ts","../../../packages/shared/src/schemas/user.schema.ts","../../../packages/shared/src/schemas/org.schema.ts","../../../packages/shared/src/schemas/project.schema.ts","../../../packages/shared/src/schemas/service.schema.ts","../../../packages/shared/src/schemas/settings.schema.ts","../../../packages/shared/src/schemas/scenario.schema.ts","../../../packages/shared/src/schemas/log-source.schema.ts","../../../packages/shared/src/schemas/process.schema.ts","../../../packages/shared/src/schemas/log.schema.ts","../../../packages/shared/src/schemas/agent.schema.ts","../../../packages/shared/src/schemas/permission.schema.ts","../../../packages/shared/src/schemas/sync.schema.ts","../../../packages/shared/src/schemas/audit.schema.ts","../../../packages/shared/src/schemas/metrics.schema.ts","../../../packages/shared/src/schemas/environment.schema.ts","../../../packages/shared/src/schemas/environment-overrides.schema.ts","../../../packages/shared/src/schemas/api-key.schema.ts","../../../packages/shared/src/schemas/image.schema.ts","../../../packages/shared/src/schemas/kanban.schema.ts","../../../packages/shared/src/schemas/cloud-api-key.schema.ts","../../../packages/shared/src/schemas/integration.schema.ts","../../../packages/shared/src/schemas/changelog.schema.ts","../../../packages/shared/src/utils/crypto.ts","../../../packages/shared/src/js-log-parser.ts","../../../packages/shared/src/builtins.ts","../../../packages/shared/src/constants/intervals.ts","../../../packages/shared/src/constants/buffers.ts","../../../packages/shared/src/constants/timeouts.ts","../../../packages/shared/src/constants/editors.ts","../../../packages/shared/src/sync/json-crdt.ts","../../../packages/runner-native/src/native-runner.ts","../../../node_modules/shellwords/src/shellwords.ts","../../../packages/runner-docker/src/index.ts","../src/services/process-store.ts","../src/services/log-sources/console-log-source.ts","../src/services/log-parser.ts","../src/services/log-buffer.ts","../src/utils/strip-ansi.ts","../src/services/log-sources/file-log-source.ts","../src/services/log-sources/mongo-log-source.ts","../src/services/log-sources/mysql-log-source.ts","../src/services/log-sources/log-source-factory.ts","../src/services/metrics-collector.ts","../src/services/health-checker.ts","../src/utils/env.ts","../src/trpc/routers/config.ts","../src/services/traefik-manager.ts","../src/config/env.ts","../src/trpc/routers/health.ts","../../../packages/shared/src/node/node-path.ts","../../../packages/shared/src/node/user-path.ts","../../../packages/shared/src/node/log-timestamps.ts","../../../packages/shared/src/node/cli-invocation.ts","../../../packages/shared/src/node/aes-gcm.ts","../src/trpc/routers/terminal.ts","../src/services/terminal-manager.ts","../src/trpc/routers/git.ts","../src/utils/git-remote.ts","../src/trpc/routers/ai.ts","../src/services/ai-spawn-manager.ts","../../../packages/mcp-server/src/launch.ts","../src/services/codex-app-server-manager.ts","../src/services/ai-context-files.ts","../src/services/ai-paste-image.ts","../src/trpc/routers/wiki.ts","../src/trpc/router.ts","../src/index.ts"],"sourcesContent":["import express from 'express';\nimport cors from 'cors';\nimport { createServer, type Server } from 'node:http';\nimport { WebSocketServer, type WebSocket } from 'ws';\nimport crypto from 'node:crypto';\nimport { createExpressMiddleware } from '@trpc/server/adapters/express';\nimport { applyWSSHandler } from '@trpc/server/adapters/ws';\nimport { appRouter } from './trpc/router.js';\nimport { createContext, setPassphrase, getPassphrase } from './trpc/trpc.js';\nimport { processManager } from './services/process-manager.js';\nimport { traefikManager } from './services/traefik-manager.js';\nimport { codexAppServerManager } from './services/codex-app-server-manager.js';\nimport { getHealthData } from './trpc/routers/health.js';\nimport { env } from './config/env.js';\n\nexport interface AgentInstance {\n app: express.Express;\n server: Server;\n trpcWss: WebSocketServer;\n healthWss: WebSocketServer;\n passphraseHex: string;\n shutdown: () => Promise<void>;\n}\n\nexport function createAgent(opts?: { passphraseHex?: string; healthWsIntervalMs?: number }): AgentInstance {\n const passphraseHex = opts?.passphraseHex ?? crypto.randomBytes(32).toString('hex');\n const healthWsIntervalMs = opts?.healthWsIntervalMs ?? env.HEALTH_WS_INTERVAL;\n setPassphrase(passphraseHex);\n\n const app = express();\n const server = createServer(app);\n\n // Agent is accessed server-to-server only (CORS doesn't apply),\n // but restrict to localhost for defense-in-depth.\n app.use(cors({ origin: 'http://localhost:4000' }));\n\n // tRPC HTTP handler\n app.use('/api/trpc', createExpressMiddleware({\n router: appRouter,\n createContext,\n }));\n\n // Both WSS in noServer mode — we route upgrades manually\n const trpcWss = new WebSocketServer({ noServer: true });\n applyWSSHandler({\n wss: trpcWss,\n router: appRouter,\n createContext: ({ req }) => {\n // Extract auth from the WS upgrade request headers\n return { authorization: req.headers.authorization ?? null };\n },\n });\n\n const healthWss = new WebSocketServer({ noServer: true });\n\n healthWss.on('connection', (ws: WebSocket) => {\n // Send health immediately, then on interval\n const sendHealth = async () => {\n if (ws.readyState !== ws.OPEN) return;\n try {\n const data = await getHealthData();\n ws.send(JSON.stringify(data));\n } catch (err) {\n console.debug('[agent] Health data collection error:', err);\n }\n };\n\n void sendHealth();\n const interval = setInterval(sendHealth, healthWsIntervalMs);\n\n ws.on('close', () => clearInterval(interval));\n ws.on('error', () => clearInterval(interval));\n });\n\n // Route upgrade requests by path\n server.on('upgrade', (req, socket, head) => {\n const pathname = new URL(req.url ?? '/', `http://${req.headers.host}`).pathname;\n\n if (pathname === '/ws/health') {\n // Validate passphrase from Authorization header only (never query params)\n const authHeader = req.headers.authorization;\n let token: string | null = null;\n\n if (authHeader?.startsWith('Bearer ')) {\n token = authHeader.slice(7);\n }\n\n if (!token || !/^[0-9a-f]+$/i.test(token)) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n\n const tokenBuffer = Buffer.from(token, 'hex');\n const passphrase = getPassphrase();\n if (tokenBuffer.length !== passphrase.length || !crypto.timingSafeEqual(tokenBuffer, passphrase)) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n\n healthWss.handleUpgrade(req, socket, head, (ws) => {\n healthWss.emit('connection', ws, req);\n });\n } else {\n // Validate passphrase at upgrade level to prevent unauthenticated WS connections\n const trpcAuth = req.headers.authorization;\n let trpcToken: string | null = null;\n if (trpcAuth?.startsWith('Bearer ')) {\n trpcToken = trpcAuth.slice(7);\n }\n if (!trpcToken || !/^[0-9a-f]+$/i.test(trpcToken)) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n const trpcTokenBuffer = Buffer.from(trpcToken, 'hex');\n const trpcPassphrase = getPassphrase();\n if (trpcTokenBuffer.length !== trpcPassphrase.length || !crypto.timingSafeEqual(trpcTokenBuffer, trpcPassphrase)) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n\n trpcWss.handleUpgrade(req, socket, head, (ws) => {\n trpcWss.emit('connection', ws, req);\n });\n }\n });\n\n const shutdown = async () => {\n codexAppServerManager.shutdown();\n await traefikManager.stop();\n await processManager.shutdownAll();\n\n // Close WS servers and HTTP with timeout guards\n await Promise.race([\n new Promise<void>((resolve) => healthWss.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 5_000)),\n ]);\n await Promise.race([\n new Promise<void>((resolve) => trpcWss.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 5_000)),\n ]);\n await Promise.race([\n new Promise<void>((resolve) => server.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 5_000)),\n ]);\n };\n\n return { app, server, trpcWss, healthWss, passphraseHex, shutdown };\n}\n","import { initTRPC, TRPCError } from '@trpc/server';\nimport type { CreateExpressContextOptions } from '@trpc/server/adapters/express';\nimport crypto from 'node:crypto';\n\nlet agentPassphrase: Buffer;\n\nexport function setPassphrase(passphrase: string): void {\n if (!/^[0-9a-f]+$/i.test(passphrase)) {\n throw new Error('Passphrase must be a valid hex string');\n }\n agentPassphrase = Buffer.from(passphrase, 'hex');\n}\n\nexport function getPassphrase(): Buffer {\n return agentPassphrase;\n}\n\nexport function createContext({ req }: CreateExpressContextOptions) {\n return {\n authorization: req.headers.authorization ?? null,\n };\n}\n\ntype Context = Awaited<ReturnType<typeof createContext>>;\n\nconst t = initTRPC.context<Context>().create({\n errorFormatter({ shape, error }) {\n return {\n ...shape,\n data: {\n ...shape.data,\n // Only expose the message, never the full stack trace\n stack: undefined,\n },\n message: error instanceof TRPCError ? error.message : 'Internal server error',\n };\n },\n});\n\nexport const router = t.router;\n\n/** Auth middleware: validates Bearer passphrase using timing-safe comparison */\nconst authMiddleware = t.middleware(({ ctx, next }) => {\n const { authorization } = ctx;\n if (!authorization) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Missing Authorization header' });\n }\n\n const [scheme, token] = authorization.split(' ');\n if (scheme !== 'Bearer' || !token) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid Authorization format. Expected: Bearer <passphrase>' });\n }\n\n if (!/^[0-9a-f]+$/i.test(token)) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid passphrase format' });\n }\n\n const tokenBuffer = Buffer.from(token, 'hex');\n if (tokenBuffer.length !== agentPassphrase.length || !crypto.timingSafeEqual(tokenBuffer, agentPassphrase)) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid passphrase' });\n }\n\n return next({ ctx });\n});\n\nexport const protectedProcedure = t.procedure.use(authMiddleware);\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { processManager } from '../../services/process-manager.js';\nimport { ServiceConfigSchema, ServiceShortcutSchema, LOG_BUFFER_SIZE } from '@runeya/packages-shared';\n\n/** Max items in a subscription queue before dropping oldest */\nconst SUBSCRIPTION_QUEUE_MAX = LOG_BUFFER_SIZE;\n\nexport const processRouter = router({\n /** List all processes */\n list: protectedProcedure\n .query(() => {\n return processManager.listStatuses();\n }),\n\n /** Get a single process */\n get: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(({ input }) => {\n const status = processManager.getStatus(input.id);\n if (!status) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Process ${input.id} not found` });\n }\n return status;\n }),\n\n /** Deploy a service config (stores it, doesn't start) */\n deploy: protectedProcedure\n .input(ServiceConfigSchema)\n .mutation(({ input }) => {\n const id = processManager.deploy(input);\n return { id };\n }),\n\n /** Undeploy: stop + remove */\n undeploy: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n await processManager.undeploy(input.id);\n return { success: true };\n }),\n\n /** Update the service config for a deployed process */\n updateConfig: protectedProcedure\n .input(z.object({ serviceId: z.string().max(128), config: ServiceConfigSchema }))\n .mutation(({ input }) => {\n processManager.updateConfig(input.serviceId, input.config);\n return { success: true as const };\n }),\n\n /** Start a deployed process */\n start: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n console.log(`[agent] start service=${input.id}`);\n await processManager.start(input.id);\n return processManager.getStatus(input.id);\n }),\n\n /** Stop a running process */\n stop: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n console.log(`[agent] stop service=${input.id}`);\n await processManager.stop(input.id);\n return processManager.getStatus(input.id);\n }),\n\n /** Restart a process */\n restart: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n console.log(`[agent] restart service=${input.id}`);\n await processManager.restart(input.id);\n return processManager.getStatus(input.id);\n }),\n\n /** Get buffered logs for a process */\n logs: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(({ input }) => {\n const logs = processManager.getLogs(input.id);\n return logs;\n }),\n\n /** Clear buffered logs for a process */\n clearLogBuffer: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(({ input }) => {\n processManager.clearLogBuffer(input.id);\n return { success: true };\n }),\n\n /** Execute a shortcut command and stream output into the process log */\n executeShortcut: protectedProcedure\n .input(z.object({ id: z.string().max(128), shortcut: ServiceShortcutSchema }))\n .mutation(async ({ input }) => {\n const result = await processManager.executeShortcut(input.id, input.shortcut);\n return result;\n }),\n\n /** Cancel a running shortcut command */\n cancelShortcut: protectedProcedure\n .input(z.object({ id: z.string().max(128), shortcutId: z.string().max(128) }))\n .mutation(({ input }) => {\n processManager.cancelShortcut(input.id, input.shortcutId);\n return { success: true };\n }),\n\n /** Cancel a running ad-hoc command */\n cancelAdHocCommand: protectedProcedure\n .input(z.object({ id: z.string().max(128), commandId: z.string().max(128).optional() }))\n .mutation(({ input }) => {\n processManager.cancelAdHocCommand(input.id, input.commandId);\n return { success: true };\n }),\n\n /** Execute an ad-hoc command and stream output into the process log */\n executeAdHocCommand: protectedProcedure\n .input(z.object({\n id: z.string().max(128),\n command: z.string().min(1).max(4096),\n cwd: z.string().max(4096).optional(),\n commandId: z.string().max(128).optional(),\n }))\n .mutation(async ({ input }) => {\n const result = await processManager.executeAdHocCommand(input.id, input.command, input.cwd, input.commandId);\n return result;\n }),\n\n /** List active log source types for a process */\n logSources: protectedProcedure\n .input(z.object({ processId: z.string().max(128) }))\n .query(({ input }) => {\n return processManager.getLogSourceTypes(input.processId);\n }),\n\n /** Get current metrics for a process */\n metrics: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n return processManager.getMetrics(input.id);\n }),\n\n /** Subscribe to real-time log stream (yields batches of ParsedLog[]) */\n onLog: protectedProcedure\n .input(z.object({ processId: z.string().max(128).optional() }).optional())\n .subscription(async function* ({ input }) {\n const queue: unknown[][] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (batch: unknown[]) => {\n const filtered = input?.processId\n ? batch.filter((log) => (log as { processId?: string }).processId === input.processId)\n : batch;\n if (filtered.length === 0) return;\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(filtered);\n if (resolve) { resolve(); resolve = null; }\n };\n\n processManager.on('logs', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift();\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n processManager.off('logs', handler);\n }\n }),\n\n /** Subscribe to real-time status changes */\n onStatus: protectedProcedure\n .input(z.object({ processId: z.string().max(128).optional() }).optional())\n .subscription(async function* ({ input }) {\n console.debug('[agent] onStatus subscription started', input?.processId ? `for process ${input.processId}` : '(all processes)');\n const queue: unknown[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (status: unknown) => {\n const entry = status as { id?: string };\n if (!input?.processId || entry.id === input.processId) {\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(status);\n if (resolve) { resolve(); resolve = null; }\n }\n };\n\n processManager.on('status', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift();\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n console.debug('[agent] onStatus subscription ended', input?.processId ? `for process ${input.processId}` : '(all processes)');\n processManager.off('status', handler);\n }\n }),\n\n /** Subscribe to real-time health status changes */\n onHealth: protectedProcedure\n .input(z.object({ processId: z.string().max(128).optional() }).optional())\n .subscription(async function* ({ input }) {\n const queue: unknown[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (healthData: unknown) => {\n const entry = healthData as { processId?: string };\n if (!input?.processId || entry.processId === input.processId) {\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(healthData);\n if (resolve) { resolve(); resolve = null; }\n }\n };\n\n processManager.on('health', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift();\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n processManager.off('health', handler);\n }\n }),\n\n /** Subscribe to real-time metrics */\n onMetrics: protectedProcedure\n .input(z.object({ processId: z.string().max(128).optional() }).optional())\n .subscription(async function* ({ input }) {\n const queue: unknown[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (metrics: unknown) => {\n const entry = metrics as { processId?: string };\n if (!input?.processId || entry.processId === input.processId) {\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(metrics);\n if (resolve) { resolve(); resolve = null; }\n }\n };\n\n processManager.on('metrics', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift();\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n processManager.off('metrics', handler);\n }\n }),\n});\n","import { EventEmitter } from 'node:events';\nimport { randomUUID } from 'node:crypto';\nimport { networkInterfaces, homedir, platform } from 'node:os';\nimport { join, isAbsolute, resolve } from 'node:path';\nimport type { ServiceConfig, ProcessStatus, ServiceShortcut, JSLogParserDef, ILogSource } from '@runeya/packages-shared';\nimport { interpolateBuiltinsInEnv, withDeprecatedAliases } from '@runeya/packages-shared';\nimport { NativeRunner, findUnresolvedEnvVars, resolveCwd } from '@runeya/packages-runner-native';\nimport type { Runner, RunnerStartConfig } from '@runeya/packages-runner-native';\nimport { DockerRunner, type DockerRunnerStartConfig } from '@runeya/packages-runner-docker';\nimport { processStore, type StoredProcess, type CommandProcess } from './process-store.js';\nimport { ConsoleLogSource } from './log-sources/console-log-source.js';\nimport { LogBuffer } from './log-buffer.js';\nimport { LogParser } from './log-parser.js';\nimport { createLogSource } from './log-sources/log-source-factory.js';\nimport { MetricsCollector } from './metrics-collector.js';\nimport { healthChecker } from './health-checker.js';\nimport { traefikManager } from './traefik-manager.js';\nimport killPort from 'kill-port';\nimport { env } from '../config/env.js';\nimport { resolveEnv } from '../utils/env.js';\n\n/**\n * Le répertoire d'une commande, ancré sur celui du projet.\n *\n * Une commande porte son propre `cwd`, souvent vide ou relatif ; le serveur, lui,\n * pose `resolvedCwd` — l'emplacement du projet sur cette machine. Sans cet\n * ancrage, une commande sans `cwd` retombait sur le répertoire de l'agent (celui\n * du lancement de Runeya) et s'exécutait contre le mauvais dépôt.\n *\n * Un `cwd` absolu, ou que l'agent étend lui-même (`~`, `$VAR`), passe intact :\n * le préfixer produirait un chemin qui n'existe nulle part.\n */\nexport function anchorCommandCwd(\n cwd: string | undefined,\n serviceConfig: ServiceConfig,\n): string | undefined {\n const base = serviceConfig.resolvedCwd ?? serviceConfig.cwd;\n const raw = (cwd ?? '').trim();\n if (!raw || raw === '.') return base ?? undefined;\n if (!base || !isAbsolute(base)) return raw;\n if (isAbsolute(raw) || raw.startsWith('~') || raw.startsWith('$')) return raw;\n return join(base, raw);\n}\n\n/**\n * Le répertoire où les commandes d'un service s'exécutent réellement, absolu.\n *\n * Passe par exactement les mêmes étapes que le lancement — ancrage sur le\n * projet, expansion des variables — puis absolutise contre le répertoire de\n * l'agent, ce que le spawn fait de toute façon. Une valeur reconstruite\n * autrement ne prouverait rien ; celle-ci dit où le code tourne vraiment,\n * y compris quand il retombe sur le répertoire de l'agent.\n */\nfunction effectiveProcessCwd(serviceConfig: ServiceConfig): string {\n const first = serviceConfig.commands?.[0];\n const anchored = anchorCommandCwd(first?.cwd, serviceConfig);\n return resolve(resolveCwd(anchored, resolveEnv(serviceConfig.env)));\n}\n\n/** Get the first non-internal IPv4 LAN address of this machine. */\nfunction getLanIp(): string {\n const nets = networkInterfaces();\n for (const name of Object.keys(nets)) {\n for (const net of nets[name] ?? []) {\n if (net.family === 'IPv4' && !net.internal) {\n return net.address;\n }\n }\n }\n return '127.0.0.1';\n}\n\n/**\n * Les builtins que seule la machine d'exécution peut produire : son IP sur le\n * réseau local, son système, le dossier de son utilisateur, et le répertoire\n * de travail effectif du service. Le serveur laisse volontairement ces\n * références intactes — les résoudre chez lui graverait la machine qui a\n * déployé plutôt que celle qui exécute.\n */\nexport function resolveAgentBuiltins(serviceConfig: ServiceConfig): Record<string, string> {\n const values: Record<string, string> = {\n 'agent.HOST_LAN': getLanIp(),\n 'agent.OS': platform(),\n 'agent.HOME': homedir(),\n // Le cwd est calculé avec l'env AVANT substitution : une variable qui\n // référencerait `{{service.CWD}}` ne peut donc pas se boucler sur\n // elle-même — la substitution ne repasse jamais sur son propre résultat.\n 'service.CWD': resolve(resolveCwd(\n serviceConfig.resolvedCwd ?? serviceConfig.cwd,\n resolveEnv(serviceConfig.env),\n )),\n };\n return withDeprecatedAliases(values);\n}\n\n/**\n * L'env d'un service, ses références de machine remplacées.\n *\n * Tout ce qui exécute quelque chose sur cette machine passe par ici — le\n * démarrage, un raccourci, une commande ponctuelle. Les deux derniers se\n * contentaient de `resolveEnv`, si bien qu'un `{{agent.HOST_LAN}}` y arrivait\n * en clair alors que le service démarré, lui, recevait l'adresse : la même\n * variable ne valait pas la même chose selon la façon de la lire.\n */\nexport function resolveMachineBuiltins(serviceConfig: ServiceConfig): Record<string, string> {\n return interpolateBuiltinsInEnv(serviceConfig.env ?? {}, resolveAgentBuiltins(serviceConfig));\n}\n\nexport class ProcessManager extends EventEmitter {\n private runners: Map<string, Runner> = new Map();\n private consoleLogSource: ConsoleLogSource;\n private metricsCollector: MetricsCollector;\n\n /** Shared buffer for all non-console log sources (file, mongo, mysql) */\n private additionalBuffer = new LogBuffer(env.LOG_BUFFER_SIZE);\n /** Per-processId list of active non-console log sources */\n private additionalSources = new Map<string, ILogSource[]>();\n\n constructor() {\n super();\n this.runners.set('native', new NativeRunner());\n this.runners.set('docker', new DockerRunner());\n this.consoleLogSource = new ConsoleLogSource(env.LOG_BUFFER_SIZE);\n this.metricsCollector = new MetricsCollector(env.METRICS_INTERVAL);\n\n // Forward events from sub-components\n this.consoleLogSource.on('logs', (batch) => this.emit('logs', batch));\n this.metricsCollector.on('metrics', (metrics) => this.emit('metrics', metrics));\n healthChecker.on('health', (result) => {\n this.emit('health', result);\n // Re-emit status so frontend picks up the updated healthStatus\n this.emitStatus(result.processId);\n });\n }\n\n /** Log warnings for any $VAR references that could not be resolved in the given strings.\n * Returns true if any unresolved variables were found. */\n private warnUnresolvedVars(processId: string, env: Record<string, string>, fields: Record<string, string | undefined>): boolean {\n let found = false;\n for (const [label, value] of Object.entries(fields)) {\n if (!value) continue;\n const unresolved = findUnresolvedEnvVars(value, env);\n if (unresolved.length > 0) {\n found = true;\n this.consoleLogSource.addSystemLog(\n processId,\n `Unresolved variable${unresolved.length > 1 ? 's' : ''} in ${label}: ${unresolved.map((n: string) => '$' + n).join(', ')}`,\n 'warn',\n { id: randomUUID(), type: 'system-warn', header: 'Unresolved variable', state: 'self' },\n );\n }\n }\n return found;\n }\n\n /** Deploy a service config (store it, don't start it) */\n deploy(config: ServiceConfig): string {\n // Use service ID as process ID for stability across agent restarts\n // This ensures the process ID remains the same when re-deployed after hot reload\n const id = config.id;\n\n // If process already exists, just update the config\n const existing = processStore.get(id);\n if (existing) {\n console.log(`[process-manager] Process ${id} already deployed, updating config`);\n existing.serviceConfig = config;\n this.emitStatus(id);\n return id;\n }\n\n const stored: StoredProcess = {\n id,\n serviceConfig: config,\n commandProcesses: [],\n state: 'stopped',\n exitCode: null,\n startedAt: null,\n restartCount: 0,\n manuallyStopped: false,\n operationInProgress: false,\n };\n processStore.set(id, stored);\n this.emitStatus(id);\n return id;\n }\n\n /** Update the service config for a deployed process (identified by serviceId).\n * Process must be stopped — updating while running would cause mid-flight inconsistencies. */\n updateConfig(serviceId: string, config: ServiceConfig): void {\n const proc = processStore.getByServiceId(serviceId);\n if (!proc) throw new Error(`No process found for service ${serviceId}`);\n if (proc.state === 'running' || proc.state === 'starting') {\n throw new Error(`Cannot update config while process is ${proc.state}. Stop the process first.`);\n }\n proc.serviceConfig = config;\n }\n\n /** Undeploy: stop if running, then remove */\n async undeploy(processId: string): Promise<void> {\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n\n if (proc.state === 'running' || proc.state === 'starting') {\n await this.stop(processId);\n }\n this.consoleLogSource.clearHistory(processId);\n this.additionalBuffer.clear(processId);\n healthChecker.stopChecking(processId);\n this.metricsCollector.stopAll();\n processStore.delete(processId);\n }\n\n /** Start a deployed process — launches ALL commands in parallel */\n async start(processId: string): Promise<void> {\n console.debug('[process-manager] Starting process', processId);\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n if (proc.state === 'running' || proc.state === 'starting') {\n throw new Error(`Process ${processId} is already ${proc.state}`);\n }\n\n // Resolve the machine-bound builtins ({{agent.*}}, {{service.CWD}}) the\n // server deliberately left alone\n if (proc.serviceConfig.env) {\n proc.serviceConfig = {\n ...proc.serviceConfig,\n env: resolveMachineBuiltins(proc.serviceConfig),\n };\n }\n\n const commands = (proc.serviceConfig.commands ?? []).filter((c) => c.command.trim());\n const isDocker = proc.serviceConfig.runner === 'docker';\n\n // If no commands, treat as no-op (service is just a container for shortcuts/env)\n // Exception: Docker runner can start with no commands (uses image CMD/ENTRYPOINT)\n if (commands.length === 0 && !isDocker) {\n this.consoleLogSource.addSystemLog(processId, 'No commands configured — nothing to start', 'warn');\n return;\n }\n\n // Immediately set to 'starting' to prevent race conditions from double-clicks\n proc.manuallyStopped = false;\n proc.state = 'starting';\n proc.exitCode = null;\n proc.commandProcesses = [];\n this.emitStatus(processId);\n\n const runner = this.runners.get(proc.serviceConfig.runner);\n if (!runner) {\n proc.state = 'errored';\n proc.exitCode = 1;\n this.emitStatus(processId);\n throw new Error(`Runner '${proc.serviceConfig.runner}' not available`);\n }\n\n // Set JS parsers for the log streamer (per-process)\n const jsParsers = (proc.serviceConfig.resolvedLogParsers ?? []) as JSLogParserDef[];\n this.consoleLogSource.setJSParsers(processId, jsParsers);\n\n // For Docker runner with no commands, use a synthetic entry so the container starts\n // using the image's built-in CMD/ENTRYPOINT.\n const effectiveCommands =\n isDocker && commands.length === 0\n ? [{ id: '__docker_default__', label: 'Docker container', command: '', shell: false, cwd: undefined }]\n : commands;\n\n // Warn about unresolved $VAR references in paths — abort if any found\n const mergedEnv = resolveEnv(proc.serviceConfig.env);\n let hasUnresolved = false;\n hasUnresolved = this.warnUnresolvedVars(processId, mergedEnv, { cwd: proc.serviceConfig.cwd }) || hasUnresolved;\n for (const cmd of effectiveCommands) {\n hasUnresolved = this.warnUnresolvedVars(processId, mergedEnv, { [`${cmd.label || cmd.command} cwd`]: cmd.cwd }) || hasUnresolved;\n }\n if (proc.serviceConfig.dockerConfig?.volumes) {\n for (const vol of proc.serviceConfig.dockerConfig.volumes) {\n hasUnresolved = this.warnUnresolvedVars(processId, mergedEnv, { volume: vol }) || hasUnresolved;\n }\n }\n if (hasUnresolved) {\n this.consoleLogSource.addSystemLog(processId, 'Cannot start: unresolved variables in path (see above)', 'error', { id: randomUUID(), type: 'command-fail', header: 'Start aborted', state: 'self' });\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n return;\n }\n\n // Kill any process occupying the service ports before starting (silently ignore errors)\n const servicePorts = proc.serviceConfig.ports ?? [];\n for (const servicePort of servicePorts) {\n try {\n await killPort(servicePort);\n } catch {\n // Port not in use — ignore\n }\n }\n\n // Docker shared mode: start one persistent container, then exec each command inside it\n const dc = proc.serviceConfig.dockerConfig;\n const isSharedMode = isDocker && dc?.useNativeCommand && dc?.nativeCommandMode === 'shared';\n\n if (isSharedMode) {\n if (!dc) {\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n throw new Error('Docker runner selected but no dockerConfig found on service');\n }\n const dockerRunner = runner as DockerRunner;\n const sharedContainerConfig: DockerRunnerStartConfig = {\n command: '',\n shell: false,\n cwd: resolveCwd(proc.serviceConfig.resolvedCwd ?? proc.serviceConfig.cwd, resolveEnv(proc.serviceConfig.env)),\n env: resolveEnv(proc.serviceConfig.env),\n dockerConfig: dc,\n serviceId: processId,\n };\n const sharedProc = dockerRunner.startSharedContainer(sharedContainerConfig);\n proc.sharedContainerProcess = sharedProc;\n this.consoleLogSource.attach(processId, sharedProc.stdout, sharedProc.stderr, null);\n\n // Wait until the container is confirmed running before exec-ing into it\n try {\n await sharedProc.containerReady;\n } catch (err: unknown) {\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n throw new Error(`Shared container failed to start: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const containerName = `runeya-${processId}`;\n for (const cmd of effectiveCommands) {\n let runnerProcess;\n try {\n console.debug(`[process-manager] Exec in shared container \"${cmd.label || cmd.command}\": ${cmd.command}`);\n runnerProcess = dockerRunner.execInContainer(containerName, cmd.command, resolveEnv(proc.serviceConfig.env), proc.serviceConfig.dockerConfig?.nativeShell || 'sh');\n console.debug('[process-manager] Exec started');\n } catch (err: unknown) {\n const errMsg = err instanceof Error ? err.message : String(err);\n console.error('[process-manager] Failed to exec command \"' + (cmd.label || cmd.command) + '\":', errMsg); // nosemgrep: unsafe-formatstring\n this.consoleLogSource.addSystemLog(processId, `Failed to exec \"${cmd.label || cmd.command}\": ${errMsg}`, 'error');\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n await this.stopCommandProcesses(proc);\n throw new Error(`Failed to exec command \"${cmd.label || cmd.command}\": ${errMsg}`);\n }\n\n const cmdProcess: CommandProcess = {\n commandId: cmd.id,\n runnerProcess,\n pid: null,\n containerName: runnerProcess.containerName ?? null,\n exitCode: null,\n };\n proc.commandProcesses = [...proc.commandProcesses, cmdProcess];\n this.consoleLogSource.addSystemLog(processId, cmd.command, 'info', { id: randomUUID(), type: 'command-start', header: cmd.label || cmd.command, state: 'self', collapsable: false });\n this.consoleLogSource.attach(processId, runnerProcess.stdout, runnerProcess.stderr, null);\n\n runnerProcess.exitPromise.then(({ exitCode, signal, error }) => {\n const current = processStore.get(processId);\n if (!current) return;\n const cpIdx = current.commandProcesses.findIndex(cp => cp.commandId === cmd.id);\n if (cpIdx >= 0) {\n current.commandProcesses = current.commandProcesses.map((cp, i) =>\n i === cpIdx ? { ...cp, runnerProcess: null, exitCode } : cp\n );\n }\n if (exitCode !== 0) {\n const errorMsg = error\n ? error\n : signal\n ? `terminated with signal ${signal}`\n : `exited with code ${exitCode}`;\n this.consoleLogSource.addSystemLog(processId, errorMsg, 'error', { id: randomUUID(), type: 'command-fail', header: cmd.label || cmd.command, state: 'self' });\n }\n this.updateAggregateState(processId);\n }, (err: Error) => {\n console.error('[process-manager] Exec error for command \"' + (cmd.label || cmd.command) + '\":', err.message); // nosemgrep: unsafe-formatstring\n const current = processStore.get(processId);\n if (!current) return;\n const cpIdx = current.commandProcesses.findIndex(cp => cp.commandId === cmd.id);\n if (cpIdx >= 0) {\n current.commandProcesses = current.commandProcesses.map((cp, i) =>\n i === cpIdx ? { ...cp, runnerProcess: null, exitCode: 1 } : cp\n );\n }\n this.consoleLogSource.addSystemLog(processId, `exec failed: ${err.message}`, 'error', { id: randomUUID(), type: 'command-fail', header: cmd.label || cmd.command, state: 'self' });\n this.updateAggregateState(processId);\n });\n }\n\n proc.startedAt = new Date();\n proc.state = 'running';\n proc.operationInProgress = false;\n this.emitStatus(processId);\n await this.startAdditionalSources(processId, proc.serviceConfig);\n healthChecker.startChecking(processId);\n return;\n }\n\n // Start each command (isolated or native runner)\n const mergedServiceEnv = resolveEnv(proc.serviceConfig.env);\n for (const cmd of effectiveCommands) {\n const runnerConfig: RunnerStartConfig = {\n command: cmd.command,\n shell: cmd.shell ?? false,\n cwd: anchorCommandCwd(cmd.cwd, proc.serviceConfig),\n env: mergedServiceEnv,\n };\n\n let runnerProcess;\n try {\n console.debug(`[process-manager] Starting command \"${cmd.label || cmd.command}\": ${cmd.command}`);\n if (proc.serviceConfig.runner === 'docker') {\n if (!proc.serviceConfig.dockerConfig) {\n throw new Error('Docker runner selected but no dockerConfig found on service');\n }\n const dockerConfig: DockerRunnerStartConfig = {\n command: cmd.command,\n shell: cmd.shell ?? false,\n cwd: resolveCwd(proc.serviceConfig.resolvedCwd ?? proc.serviceConfig.cwd, mergedServiceEnv),\n env: mergedServiceEnv,\n dockerConfig: proc.serviceConfig.dockerConfig,\n serviceId: processId,\n cmdId: cmd.id,\n };\n runnerProcess = (runner as DockerRunner).start(dockerConfig);\n } else {\n runnerProcess = runner.start(runnerConfig);\n }\n console.debug('[process-manager] Command started, PID:', runnerProcess.pid);\n } catch (err: unknown) {\n const errMsg = err instanceof Error ? err.message : String(err);\n console.error('[process-manager] Failed to start command \"' + (cmd.label || cmd.command) + '\":', errMsg); // nosemgrep: unsafe-formatstring\n this.consoleLogSource.addSystemLog(processId, `Failed to start \"${cmd.label || cmd.command}\": ${errMsg}`, 'error');\n // Mark all as errored and stop any already-started commands\n proc.state = 'errored';\n proc.exitCode = 1;\n proc.operationInProgress = false;\n this.emitStatus(processId);\n await this.stopCommandProcesses(proc);\n throw new Error(`Failed to start command \"${cmd.label || cmd.command}\": ${errMsg}`);\n }\n\n const cmdProcess: CommandProcess = {\n commandId: cmd.id,\n runnerProcess,\n pid: runnerProcess.pid ?? null,\n containerName: runnerProcess.containerName ?? null,\n exitCode: null,\n };\n proc.commandProcesses = [...proc.commandProcesses, cmdProcess];\n\n // Emit command-start BEFORE attach so it always appears before any output in the buffer\n if (cmd.id !== '__docker_default__') {\n this.consoleLogSource.addSystemLog(\n processId,\n cmd.command,\n 'info',\n { id: randomUUID(), type: 'command-start', header: cmd.label || cmd.command, state: 'self', collapsable: false },\n );\n }\n\n // Attach log streaming with the command's PID\n this.consoleLogSource.attach(processId, runnerProcess.stdout, runnerProcess.stderr, runnerProcess.pid ?? null);\n\n // Start metrics collection — native (PID) or Docker (container name)\n if (runnerProcess.pid) {\n this.metricsCollector.startCollecting(processId, runnerProcess.pid);\n } else if (runnerProcess.containerName) {\n this.metricsCollector.startCollectingDocker(processId, runnerProcess.containerName);\n }\n\n // Handle exit per command\n runnerProcess.exitPromise.then(({ exitCode, signal, error }) => {\n const current = processStore.get(processId);\n if (!current) return;\n\n // Update this command's state\n const cpIdx = current.commandProcesses.findIndex(cp => cp.commandId === cmd.id);\n if (cpIdx >= 0) {\n current.commandProcesses = current.commandProcesses.map((cp, i) =>\n i === cpIdx ? { ...cp, runnerProcess: null, exitCode } : cp\n );\n }\n\n if (runnerProcess.pid) {\n this.metricsCollector.stopCollecting(processId);\n }\n\n // Log exit info for this command (only on failure)\n if (exitCode !== 0) {\n const errorMsg = error\n ? error\n : signal\n ? `terminated with signal ${signal}`\n : `exited with code ${exitCode}`;\n this.consoleLogSource.addSystemLog(processId, errorMsg, 'error', { id: randomUUID(), type: 'command-fail', header: cmd.label || cmd.command, state: 'self' });\n }\n\n // Update aggregate state\n this.updateAggregateState(processId);\n }, (err: Error) => {\n console.error('[process-manager] Spawn error for command \"' + (cmd.label || cmd.command) + '\":', err.message); // nosemgrep: unsafe-formatstring\n const current = processStore.get(processId);\n if (!current) return;\n\n const cpIdx = current.commandProcesses.findIndex(cp => cp.commandId === cmd.id);\n if (cpIdx >= 0) {\n current.commandProcesses = current.commandProcesses.map((cp, i) =>\n i === cpIdx ? { ...cp, runnerProcess: null, exitCode: 1 } : cp\n );\n }\n\n this.consoleLogSource.addSystemLog(processId, `spawn failed: ${err.message}`, 'error', { id: randomUUID(), type: 'command-fail', header: cmd.label || cmd.command, state: 'self' });\n this.updateAggregateState(processId);\n });\n }\n\n proc.startedAt = new Date();\n proc.state = 'running';\n proc.operationInProgress = false;\n this.emitStatus(processId);\n traefikManager.scheduleDynamicRegen();\n\n // Start additional log sources (file, mongo, mysql…) declared in logSources\n await this.startAdditionalSources(processId, proc.serviceConfig);\n\n // Start health checking if configured\n healthChecker.startChecking(processId);\n }\n\n /** Stop a running process: stop ALL command processes */\n async stop(processId: string): Promise<void> {\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n\n const hasActiveCommands = proc.commandProcesses.some(cp => cp.runnerProcess);\n const hasSharedContainer = !!proc.sharedContainerProcess;\n if (!hasActiveCommands && !hasSharedContainer) {\n proc.state = 'stopped';\n this.emitStatus(processId);\n return;\n }\n\n // Mark as manually stopped to prevent auto-restart with 'unless-stopped' strategy\n proc.manuallyStopped = true;\n\n await this.stopCommandProcesses(proc);\n await this.stopAdditionalSources(processId);\n\n proc.state = 'stopped';\n healthChecker.stopChecking(processId);\n this.metricsCollector.stopCollecting(processId);\n this.emitStatus(processId);\n traefikManager.scheduleDynamicRegen();\n }\n\n /** Restart = stop + start */\n async restart(processId: string): Promise<void> {\n await this.stop(processId);\n const proc = processStore.get(processId);\n if (proc) proc.restartCount++;\n await this.start(processId);\n }\n\n /** Get status of a process */\n getStatus(processId: string): ProcessStatus | null {\n const proc = processStore.get(processId);\n if (!proc) return null;\n return this.toProcessStatus(proc);\n }\n\n /** Get all process statuses */\n listStatuses(): ProcessStatus[] {\n return processStore.getAll().map(p => this.toProcessStatus(p));\n }\n\n /** Get logs for a process — merges console + additional sources, sorted by timestamp */\n getLogs(processId: string): ReturnType<ConsoleLogSource['getHistory']> {\n const consoleLogs = this.consoleLogSource.getHistory(processId);\n const additionalLogs = this.additionalBuffer.getByProcessId(processId);\n if (additionalLogs.length === 0) return consoleLogs;\n return [...consoleLogs, ...additionalLogs].sort(\n (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),\n );\n }\n\n /** Clear buffered logs for a process (does not delete parse rules) */\n clearLogBuffer(processId: string): void {\n this.consoleLogSource.clearBufferOnly(processId);\n this.additionalBuffer.clear(processId);\n }\n\n /** Return the types of active log sources for a given processId */\n getLogSourceTypes(processId: string): string[] {\n const types: string[] = ['console'];\n const extra = this.additionalSources.get(processId);\n if (extra) {\n for (const src of extra) types.push(src.type);\n }\n return types;\n }\n\n /** Get current metrics for a process */\n async getMetrics(processId: string): ReturnType<MetricsCollector['getMetrics']> {\n return this.metricsCollector.getMetrics(processId);\n }\n\n /** Get available runner types */\n async getAvailableRunners(): Promise<string[]> {\n const available: string[] = [];\n for (const [type, runner] of this.runners) {\n try {\n if (await runner.isAvailable()) {\n available.push(type);\n }\n } catch {\n // Runner availability check failed — treat as unavailable\n }\n }\n return available;\n }\n\n /** Shutdown all processes */\n async shutdownAll(): Promise<void> {\n const processes = processStore.getAll();\n await Promise.allSettled(\n processes\n .filter(p => p.state === 'running' || p.state === 'starting')\n .map(p => this.stop(p.id))\n );\n healthChecker.stopAll();\n this.metricsCollector.stopAll();\n }\n\n /** Launch a one-off command (shortcut or ad-hoc) using the appropriate runner for the process.\n * Centralises runner selection so executeShortcut / executeAdHocCommand share the logic. */\n private launchOneOffCommand(\n proc: StoredProcess,\n command: string,\n cwd: string | undefined,\n env: Record<string, string>,\n ) {\n const serviceConfig = proc.serviceConfig;\n // An explicit cwd (a shortcut's own) wins; otherwise the project-anchored\n // one, which is what makes a cloud project's shortcuts run in its directory.\n const effectiveCwd = anchorCommandCwd(cwd, serviceConfig);\n\n if (serviceConfig.runner === 'docker' && serviceConfig.dockerConfig) {\n const dockerRunner = this.runners.get('docker') as DockerRunner;\n if (!dockerRunner) throw new Error('Docker runner not available');\n const dockerConfig: DockerRunnerStartConfig = {\n command,\n shell: false,\n cwd: resolveCwd(effectiveCwd, env),\n env,\n dockerConfig: serviceConfig.dockerConfig,\n serviceId: proc.id,\n };\n return dockerRunner.runShortcut(dockerConfig, command);\n } else {\n const nativeRunner = this.runners.get('native') as NativeRunner;\n if (!nativeRunner) throw new Error('Native runner not available');\n return nativeRunner.start({\n command,\n shell: true,\n cwd: effectiveCwd,\n env,\n });\n }\n }\n\n private activeShortcuts = new Map<string, ReturnType<ProcessManager['launchOneOffCommand']>>();\n private activeAdHocCommands = new Map<string, ReturnType<ProcessManager['launchOneOffCommand']>>();\n\n cancelShortcut(processId: string, shortcutId: string): void {\n const key = `${processId}:${shortcutId}`;\n const proc = this.activeShortcuts.get(key);\n if (proc) proc.kill('SIGTERM');\n }\n\n cancelAdHocCommand(processId: string, commandId?: string): void {\n const targets: ReturnType<ProcessManager['launchOneOffCommand']>[] = [];\n if (commandId) {\n const key = `${processId}:${commandId}`;\n const proc = this.activeAdHocCommands.get(key);\n if (proc) targets.push(proc);\n } else {\n for (const [key, proc] of this.activeAdHocCommands) {\n if (key.startsWith(`${processId}:`)) targets.push(proc);\n }\n }\n for (const proc of targets) {\n proc.kill('SIGTERM');\n // Force kill after grace period if still running\n void Promise.race([\n proc.exitPromise,\n new Promise<void>((resolve) => setTimeout(resolve, 3000)),\n ]).then((result) => {\n if (result === undefined) proc.kill('SIGKILL');\n });\n }\n }\n\n /** Execute a shortcut command and stream its output as logs for the given process */\n async executeShortcut(processId: string, shortcut: ServiceShortcut): Promise<{ exitCode: number | null }> {\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n\n // Ensure JS parsers are loaded even if the process was never started (lazy deploy only sets config in store)\n const jsParsers = (proc.serviceConfig.resolvedLogParsers ?? []) as JSLogParserDef[];\n this.consoleLogSource.setJSParsers(processId, jsParsers);\n\n const shortcutName = shortcut.label || shortcut.command;\n this.consoleLogSource.addSystemLog(processId, `[shortcut] Running \"${shortcutName}\": ${shortcut.command}`, 'info');\n\n const serviceConfig = proc.serviceConfig;\n const env = resolveEnv(resolveMachineBuiltins(serviceConfig));\n\n const effectiveCwd = anchorCommandCwd(shortcut.cwd, serviceConfig);\n if (this.warnUnresolvedVars(processId, env, { 'shortcut cwd': effectiveCwd })) {\n this.consoleLogSource.addSystemLog(processId, `Cannot run shortcut \"${shortcutName}\": unresolved variables (see above)`, 'error', { id: randomUUID(), type: 'command-fail', header: shortcutName, state: 'self' });\n return { exitCode: 1 };\n }\n\n let runnerProcess;\n try {\n runnerProcess = this.launchOneOffCommand(proc, shortcut.command, shortcut.cwd, env);\n } catch (err: unknown) {\n this.consoleLogSource.addSystemLog(processId, `Failed to start: ${err instanceof Error ? err.message : String(err)}`, 'error', { id: randomUUID(), type: 'command-fail', header: shortcutName, state: 'self' });\n return { exitCode: 1 };\n }\n\n const shortcutKey = `${processId}:${shortcut.id}`;\n this.activeShortcuts.set(shortcutKey, runnerProcess);\n\n // Attach stdout/stderr to the same log stream as the parent process, with shortcut's PID\n this.consoleLogSource.attach(processId, runnerProcess.stdout, runnerProcess.stderr, runnerProcess.pid ?? null);\n\n const { exitCode, signal, error } = await runnerProcess.exitPromise;\n this.activeShortcuts.delete(shortcutKey);\n\n if (exitCode === 0) {\n this.consoleLogSource.addSystemLog(processId, `[shortcut] \"${shortcutName}\" completed successfully`, 'info');\n } else if (signal) {\n this.consoleLogSource.addSystemLog(processId, `[shortcut] \"${shortcutName}\" cancelled`, 'info');\n } else {\n const errorMsg = error ? error : `exited with code ${exitCode}`;\n this.consoleLogSource.addSystemLog(processId, errorMsg, 'error', { id: randomUUID(), type: 'command-fail', header: shortcutName, state: 'self' });\n }\n\n return { exitCode };\n }\n\n /** Execute an ad-hoc command and stream its output as logs for the given process */\n async executeAdHocCommand(processId: string, command: string, cwd?: string, commandId?: string): Promise<{ exitCode: number | null }> {\n const proc = processStore.get(processId);\n if (!proc) throw new Error(`Process ${processId} not found`);\n\n // Ensure JS parsers are loaded even if the process was never started (lazy deploy only sets config in store)\n const jsParsers = (proc.serviceConfig.resolvedLogParsers ?? []) as JSLogParserDef[];\n this.consoleLogSource.setJSParsers(processId, jsParsers);\n\n const serviceConfig = proc.serviceConfig;\n const env = resolveEnv(resolveMachineBuiltins(serviceConfig));\n\n const effectiveCwd = anchorCommandCwd(cwd, serviceConfig);\n if (this.warnUnresolvedVars(processId, env, { cwd: effectiveCwd })) {\n this.consoleLogSource.addSystemLog(processId, `Cannot run command: unresolved variables (see above)`, 'error', { id: randomUUID(), type: 'command-fail', header: command, state: 'self' });\n return { exitCode: 1 };\n }\n\n this.consoleLogSource.addSystemLog(processId, `$ ${command}`, 'info');\n\n let runnerProcess;\n try {\n runnerProcess = this.launchOneOffCommand(proc, command, cwd, env);\n } catch (err: unknown) {\n this.consoleLogSource.addSystemLog(processId, `Failed to start: ${err instanceof Error ? err.message : String(err)}`, 'error', { id: randomUUID(), type: 'command-fail', header: command, state: 'self' });\n return { exitCode: 1 };\n }\n\n const cmdKey = `${processId}:${commandId ?? randomUUID()}`;\n this.activeAdHocCommands.set(cmdKey, runnerProcess);\n\n // Attach stdout/stderr to the same log stream as the parent process, with command's PID\n this.consoleLogSource.attach(processId, runnerProcess.stdout, runnerProcess.stderr, runnerProcess.pid ?? null);\n\n const { exitCode, signal, error } = await runnerProcess.exitPromise;\n this.activeAdHocCommands.delete(cmdKey);\n\n if (signal) {\n this.consoleLogSource.addSystemLog(processId, `command cancelled`, 'info');\n } else if (exitCode !== 0) {\n const errorMsg = error ? error : `exited with code ${exitCode}`;\n this.consoleLogSource.addSystemLog(processId, errorMsg, 'error', { id: randomUUID(), type: 'command-fail', header: command, state: 'self' });\n }\n\n return { exitCode };\n }\n\n /** Instantiate and start non-console log sources from serviceConfig.logSources */\n private async startAdditionalSources(processId: string, serviceConfig: ServiceConfig): Promise<void> {\n const configs = serviceConfig.logSources ?? [];\n if (configs.length === 0) return;\n\n const serviceEnv = resolveEnv(serviceConfig.env);\n const resolvedCwd = resolveCwd(serviceConfig.resolvedCwd ?? serviceConfig.cwd, serviceEnv);\n\n const jsParsers = (serviceConfig.resolvedLogParsers ?? []) as JSLogParserDef[];\n const logParser = new LogParser(jsParsers);\n const sources: ILogSource[] = configs.map((srcConfig) => {\n if (srcConfig.type === 'file') {\n const absPath = isAbsolute(srcConfig.path) ? srcConfig.path : join(resolvedCwd, srcConfig.path);\n return createLogSource({ ...srcConfig, path: absPath }, this.additionalBuffer, logParser);\n }\n return createLogSource(srcConfig, this.additionalBuffer, logParser);\n });\n\n for (const src of sources) {\n src.on('logs', (batch) => this.emit('logs', batch));\n try {\n await src.start(processId);\n } catch (err: unknown) {\n console.error('[process-manager] Failed to start log source', src.type, 'for', processId + ':', err instanceof Error ? err.message : String(err));\n }\n }\n\n this.additionalSources.set(processId, sources);\n }\n\n /** Stop and remove all non-console log sources for a process */\n private async stopAdditionalSources(processId: string): Promise<void> {\n const sources = this.additionalSources.get(processId);\n if (!sources) return;\n await Promise.allSettled(sources.map((s) => s.stop()));\n this.additionalSources.delete(processId);\n }\n\n /** Stop all command processes within a stored process */\n private async stopCommandProcesses(proc: StoredProcess): Promise<void> {\n const graceMs = env.GRACE_PERIOD;\n\n // Shared mode: kill the container first — that terminates all exec sessions inside it.\n // Then drain the exec exitPromises with a short timeout (they should resolve near-instantly).\n if (proc.sharedContainerProcess) {\n const sharedProc = proc.sharedContainerProcess;\n proc.sharedContainerProcess = null;\n sharedProc.kill('SIGTERM');\n await Promise.race([\n sharedProc.exitPromise,\n new Promise<void>((resolve) => setTimeout(resolve, graceMs)),\n ]);\n // Exec processes die when the container stops — drain them quickly\n const activeExecs = proc.commandProcesses.filter(cp => cp.runnerProcess);\n await Promise.all(\n activeExecs.map(async (cp) => {\n await Promise.race([\n cp.runnerProcess!.exitPromise,\n new Promise<void>((resolve) => setTimeout(resolve, 2000)),\n ]);\n cp.runnerProcess = null;\n })\n );\n return;\n }\n\n const activeProcesses = proc.commandProcesses.filter(cp => cp.runnerProcess);\n\n // Send SIGTERM to all\n for (const cp of activeProcesses) {\n cp.runnerProcess!.kill('SIGTERM');\n }\n\n // Wait for all to exit or force kill after grace period\n await Promise.all(\n activeProcesses.map(async (cp) => {\n const exited = await Promise.race([\n cp.runnerProcess!.exitPromise.then(() => true),\n new Promise<false>((resolve) => setTimeout(() => resolve(false), graceMs)),\n ]);\n\n if (!exited && cp.runnerProcess) {\n cp.runnerProcess.kill('SIGKILL');\n await cp.runnerProcess.exitPromise;\n }\n\n cp.runnerProcess = null;\n })\n );\n }\n\n /** Update aggregate state based on individual command process states */\n private updateAggregateState(processId: string): void {\n const proc = processStore.get(processId);\n if (!proc) return;\n\n const cps = proc.commandProcesses;\n const anyRunning = cps.some(cp => cp.runnerProcess !== null);\n const anyErrored = cps.some(cp => cp.exitCode !== null && cp.exitCode !== 0);\n const allDone = cps.every(cp => cp.runnerProcess === null);\n\n if (anyRunning) {\n // Still running — keep state as running\n return;\n }\n\n if (allDone) {\n // Shared mode: all execs finished naturally — kill the container too\n if (proc.sharedContainerProcess) {\n const sharedProc = proc.sharedContainerProcess;\n proc.sharedContainerProcess = null;\n sharedProc.kill('SIGTERM');\n }\n\n if (anyErrored) {\n proc.state = 'errored';\n proc.exitCode = 1;\n } else {\n proc.state = 'stopped';\n proc.exitCode = 0;\n }\n healthChecker.stopChecking(processId);\n this.metricsCollector.stopCollecting(processId);\n this.emitStatus(processId);\n this.handleAutoRestart(processId, proc);\n }\n }\n\n private handleAutoRestart(processId: string, current: StoredProcess): void {\n const strategy = current.serviceConfig.restartStrategy\n ?? (current.serviceConfig.autoRestart ? 'on-failure' : 'none');\n\n const shouldRestart = (() => {\n switch (strategy) {\n case 'on-failure':\n return current.state === 'errored';\n case 'always':\n return true;\n case 'unless-stopped':\n return !current.manuallyStopped;\n default:\n return false;\n }\n })();\n\n const maxRestarts = current.serviceConfig.maxRestarts;\n const hitMaxRestarts = maxRestarts !== undefined && maxRestarts !== null && current.restartCount >= maxRestarts;\n\n if (shouldRestart && !hitMaxRestarts) {\n current.restartCount++;\n // Exponential backoff: baseDelay * 2^(restartCount - 1), capped at 30s\n const baseDelay = current.serviceConfig.restartBackoffMs ?? 1000;\n const exponent = Math.min(current.restartCount - 1, 20);\n const delay = Math.min(baseDelay * Math.pow(2, exponent), 30_000);\n this.consoleLogSource.addSystemLog(\n processId,\n `Auto-restarting in ${delay}ms (attempt ${current.restartCount}${maxRestarts ? `/${maxRestarts}` : ''}, strategy: ${strategy})`,\n 'warn'\n );\n setTimeout(() => {\n if (processStore.has(processId)) {\n this.start(processId).catch((err) => {\n console.error('[process-manager] Auto-restart failed for', processId, ':', err.message);\n });\n }\n }, delay);\n } else if (shouldRestart && hitMaxRestarts) {\n this.consoleLogSource.addSystemLog(\n processId,\n `Max restarts reached (${maxRestarts}). Not restarting.`,\n 'error'\n );\n }\n }\n\n private toProcessStatus(proc: StoredProcess): ProcessStatus {\n const uptime = proc.startedAt && proc.state === 'running'\n ? Date.now() - proc.startedAt.getTime()\n : 0;\n const healthStatus = healthChecker.getHealthStatus(proc.id);\n const pids = proc.commandProcesses\n .map(cp => cp.pid)\n .filter((pid): pid is number => pid !== null);\n return {\n id: proc.id,\n serviceId: proc.serviceConfig.id,\n agentId: env.AGENT_ID ?? 'local',\n state: proc.state,\n pid: pids[0] ?? null,\n pids,\n exitCode: proc.exitCode,\n startedAt: proc.startedAt,\n restartCount: proc.restartCount,\n uptime,\n healthStatus,\n cwd: effectiveProcessCwd(proc.serviceConfig),\n };\n }\n\n private emitStatus(processId: string): void {\n const status = this.getStatus(processId);\n if (status) {\n this.emit('status', status);\n if (traefikManager.isEnabled()) {\n traefikManager.scheduleDynamicRegen();\n }\n }\n }\n}\n\n// Singleton instance\nexport const processManager = new ProcessManager();\n","import { z } from 'zod';\n\nexport const UserSchema = z.object({\n id: z.string().max(128),\n email: z.string().email().max(320),\n name: z.string().min(1).max(500),\n avatar: z.string().url().max(2048).nullable().optional(),\n});\n\nexport type User = z.infer<typeof UserSchema>;\n","import { z } from 'zod';\n\nexport const OrgSchema = z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(100),\n slug: z.string().min(1).max(100).regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/),\n ownerId: z.string().max(128),\n});\n\nexport type Org = z.infer<typeof OrgSchema>;\n\nexport const OrgMemberSchema = z.object({\n id: z.string().max(128),\n orgId: z.string().max(128),\n userId: z.string().max(128),\n globalRole: z.enum(['owner', 'admin', 'member']),\n invitedAt: z.coerce.date(),\n joinedAt: z.coerce.date().nullable().optional(),\n});\n\nexport type OrgMember = z.infer<typeof OrgMemberSchema>;\n","import { z } from 'zod';\n\nexport const ProjectSchema = z.object({\n id: z.string().max(128),\n orgId: z.string().max(128).nullable().optional(),\n name: z.string().min(1).max(200),\n description: z.string().max(10000).optional().default(''),\n serviceIds: z.array(z.string().max(128)).max(10000).default([]),\n\n // Environment support\n // NOTE: activeEnvironmentId is runtime-only (not persisted to JSON)\n // It's initialized to 'local' by default at load time\n activeEnvironmentId: z.string().max(128).optional(),\n environmentIds: z.array(z.string().max(128)).max(100).default([]),\n\n // Ordre d'affichage des groupes de services dans la sidebar (noms de groupes).\n // Les groupes absents de cette liste sont affichés après, par ordre alphabétique.\n groupOrder: z.array(z.string().max(200)).max(100).default([]),\n});\n\nexport type Project = z.infer<typeof ProjectSchema>;\n\nexport const CreateProjectSchema = ProjectSchema.omit({ id: true }).partial().required({ name: true });\nexport type CreateProject = z.infer<typeof CreateProjectSchema>;\n\nexport const UpdateProjectSchema = ProjectSchema.partial().required({ id: true });\nexport type UpdateProject = z.infer<typeof UpdateProjectSchema>;\n","import { z } from 'zod';\nimport { JSLogParserSchema } from './settings.schema.js';\nimport { LogSourceConfigSchema } from './log-source.schema.js';\n\nexport const HealthCheckSchema = z.object({\n type: z.enum(['http', 'command']).default('http'),\n // HTTP-specific (required when type=http)\n path: z.string().min(1).max(500).startsWith('/').optional(),\n method: z.enum(['GET', 'HEAD', 'POST', 'PUT']).optional().default('GET'),\n expectedStatus: z.number().int().min(100).max(599).optional().default(200),\n // Command-specific (required when type=command)\n command: z.string().min(1).max(4096).optional(),\n // Shared\n interval: z.number().int().positive().default(1000),\n timeout: z.number().int().positive().default(1000),\n retries: z.number().int().nonnegative().default(3),\n initialDelay: z.number().int().nonnegative().optional().default(0),\n}).refine(\n (data) => data.type === 'http' ? !!data.path : !!data.command,\n { message: 'HTTP type requires path; command type requires command' },\n);\n\nexport type HealthCheck = z.infer<typeof HealthCheckSchema>;\n\nexport const BootstrapCommandSchema = z.object({\n id: z.string().min(1).max(64),\n label: z.string().max(200).default(''),\n entrypoint: z.string().max(4096).optional(),\n command: z.string().max(4096).default(''),\n user: z.string().max(256).optional(),\n});\n\nexport type BootstrapCommand = z.infer<typeof BootstrapCommandSchema>;\n\nexport const DockerConfigSchema = z.object({\n // Image mode (pull from registry) — mutually exclusive with build mode in UI\n image: z.string().min(1).max(1024).optional(),\n\n // Build mode — Dockerfile stored inline in services.json\n dockerfile: z.string().max(65536).optional(),\n buildContext: z.string().max(4096).optional(),\n buildArgs: z.record(z.string().max(256), z.string().max(4096)).default({}).refine(\n (obj) => Object.keys(obj).length <= 50,\n { message: 'Max 50 build args' },\n ),\n targetStage: z.string().max(256).optional(),\n\n // Runtime config\n networkMode: z.enum(['host', 'bridge']).default('host'),\n ports: z.array(z.string().max(64)).max(100).default([]),\n volumes: z.array(z.string().max(1024)).max(100).default([]),\n mountRootpath: z.boolean().default(false),\n entrypoint: z.string().max(4096).optional(),\n command: z.string().max(4096).optional(),\n user: z.string().max(256).optional(),\n useNativeCommand: z.boolean().default(false),\n nativeCommandMode: z.enum(['shared', 'isolated']).default('isolated'),\n nativeShell: z.string().max(256).default('sh'),\n bootstrapCommands: z.array(BootstrapCommandSchema).max(20).default([]),\n});\n\nexport type DockerConfig = z.infer<typeof DockerConfigSchema>;\n\nexport const RestartStrategySchema = z.enum(['none', 'on-failure', 'always', 'unless-stopped']).default('none');\nexport type RestartStrategy = z.infer<typeof RestartStrategySchema>;\n\nexport const ServiceShortcutSchema = z.object({\n id: z.string().min(1).max(64),\n label: z.string().max(200).default(''),\n command: z.string().max(4096).default(''),\n cwd: z.string().max(4096).optional(),\n});\n\nexport type ServiceShortcut = z.infer<typeof ServiceShortcutSchema>;\n\nexport const ServiceCommandSchema = z.object({\n id: z.string().min(1).max(64),\n label: z.string().max(200).default(''),\n command: z.string().max(4096).default(''),\n cwd: z.string().max(4096).optional(),\n shell: z.boolean().optional().default(true),\n});\n\nexport type ServiceCommand = z.infer<typeof ServiceCommandSchema>;\n\n// --- Variable Slot Schema ---\n// A VariableSlot represents a single value with optional pre/post concatenation.\n// The final resolved value is: pre + interpolate(value) + post\nexport const VariableSlotSchema = z.object({\n value: z.string().max(8192).default(''),\n pre: z.string().max(8192).default(''),\n post: z.string().max(8192).default(''),\n isSecret: z.boolean().default(false),\n // Deux décisions distinctes, et il ne faut pas les confondre :\n //\n // - `shareWithAi` est une permission de **lecture** : une IA (le chat de\n // Runeya, un agent par le serveur MCP) peut voir la valeur de ce secret.\n // Une variable publique est lisible de toute façon, le drapeau ne la\n // concerne pas.\n // - `injectIntoAi` est une **exécution** : la variable est posée dans\n // l'environnement du process des agents (Claude Code, Codex, …) lancés\n // depuis Runeya pendant que cet environnement est actif.\n //\n // Les deux sont opt-in : sans rien cocher, aucun secret ne part vers une IA.\n // Injecter implique lire (ce que le process reçoit, l'agent le voit), donc\n // la lecture accepte l'un OU l'autre : voir `isSharedWithAi`, qui est le seul\n // endroit où cette règle s'écrit.\n shareWithAi: z.boolean().default(false),\n injectIntoAi: z.boolean().default(false),\n // Une variable obligatoire doit avoir une valeur finale non vide avant qu'un\n // service de cet environnement puisse démarrer. Le démarrage est refusé\n // sinon, avec la liste des manquantes — l'assistant est le moyen de remplir.\n required: z.boolean().default(false),\n // Une variable « seulement surchargeable » n'a jamais de valeur partagée :\n // `value` reste vide dans le document synchronisé, et chaque poste DOIT\n // fournir sa propre surcharge machine-locale (chemin local, jeton personnel).\n // `pre` et `post` restent partagés — ils décrivent la forme, pas le secret.\n overrideOnly: z.boolean().default(false),\n // À quoi sert cette variable, pour quelqu'un qui doit la remplir. Affichée\n // par l'assistant de complétion et dans l'éditeur.\n //\n // Du **markdown**, pas du texte brut : une description gagne à pouvoir\n // pointer vers la console qui délivre le jeton. Écrite et relue par le même\n // éditeur Tiptap (`packages/editor-ui`), jamais injectée en HTML — Tiptap\n // analyse le markdown dans son propre schéma, si bien qu'une description\n // arrivée d'un autre poste par la synchronisation ne peut rien exécuter.\n description: z.string().max(2000).default(''),\n}).refine(\n (slot) => !slot.overrideOnly || slot.value === '',\n { message: 'An override-only variable cannot carry a shared value', path: ['value'] },\n);\n\nexport type VariableSlot = z.infer<typeof VariableSlotSchema>;\n\n/**\n * Son auteur a-t-il partagé cette variable avec les IA ?\n *\n * Deux cases mènent au même oui : `shareWithAi`, le partage en lecture, et\n * `injectIntoAi`, car une variable posée dans l'environnement du process d'un\n * agent est de fait lisible par lui — la lui refuser à la lecture tout en la\n * lui passant ne protégerait rien et rendrait l'interface menteuse.\n *\n * Le seul endroit où cette règle s'écrit. Deux précautions d'emploi :\n *\n * - Le drapeau ne décide que du sort des **secrets**. Une variable publique est\n * lisible de toute façon, et savoir laquelle est secrète n'est pas affaire de\n * définition : une variable non marquée qui référence un secret le devient à\n * la résolution. C'est donc au filtre de croiser les deux.\n * - Il se lit sur la **définition**, jamais sur un slot de surcharge : une\n * surcharge remplace le slot entier et n'en porte aucun drapeau (même piège\n * que `findMissingVariables`).\n */\nexport function isSharedWithAi(slot: Pick<VariableSlot, 'shareWithAi' | 'injectIntoAi'>): boolean {\n return slot.shareWithAi || slot.injectIntoAi;\n}\n\n/** Pourquoi une variable est réclamée par l'assistant de complétion. */\nexport const MissingVariableReasonSchema = z.enum(['required', 'overrideOnly']);\nexport type MissingVariableReason = z.infer<typeof MissingVariableReasonSchema>;\n\n/** Une variable qu'il faut remplir avant de démarrer. */\nexport const MissingVariableSchema = z.object({\n variableId: z.string().max(128),\n key: z.string().max(256),\n description: z.string().max(2000),\n reason: MissingVariableReasonSchema,\n isSecret: z.boolean(),\n environmentId: z.string().max(128),\n environmentName: z.string().max(200),\n});\n\nexport type MissingVariable = z.infer<typeof MissingVariableSchema>;\n\n// A Variable has a key (env var name) and a value slot.\nexport const VariableSchema = z.object({\n key: z.string().min(1).max(256),\n value: VariableSlotSchema,\n});\n\nexport type Variable = z.infer<typeof VariableSchema>;\n\n// Record of variableId → Variable. Max 200 entries.\n// The key is a unique variable ID (UUID), the Variable contains the env var name in `key`.\nexport const VariablesRecordSchema = z.record(\n z.string().max(128),\n VariableSchema,\n).refine(\n (obj) => Object.keys(obj).length <= 200,\n { message: 'Max 200 variables' },\n);\n\nexport type VariablesRecord = z.infer<typeof VariablesRecordSchema>;\n\n// Record of variable name → VariableSlot (used on disk for base values and overrides separately)\nexport const VariableSlotsRecordSchema = z.record(\n z.string().max(256),\n VariableSlotSchema,\n).refine(\n (obj) => Object.keys(obj).length <= 200,\n { message: 'Max 200 variable slots' },\n);\n\nexport type VariableSlotsRecord = z.infer<typeof VariableSlotsRecordSchema>;\n\nexport const ServiceConfigSchema = z.object({\n id: z.string().max(128),\n orgId: z.string().max(128).nullable().optional(),\n agentId: z.string().max(128).optional(), // Optional: if absent, inherited from active environment's agentId\n name: z.string().min(1).max(200),\n commands: z.array(ServiceCommandSchema).max(50).optional().default([]),\n cwd: z.string().max(4096).optional(),\n ports: z.array(z.number().int().positive().max(65535)).max(20).optional().default([]),\n\n // Metadata fields (migration from old Runeya)\n groups: z.array(z.string().max(200)).max(20).optional().default([]),\n description: z.string().max(2000).optional(),\n /** Path (relative to service.cwd or absolute) where the service's docs/wiki markdown files live. Optional — defaults to service.cwd. */\n docsPath: z.string().max(4096).optional(),\n url: z.string().max(2048).optional(),\n localUrls: z.array(z.object({\n url: z.string().max(253).regex(/^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,}$/),\n port: z.number().int().min(1).max(65535),\n })).max(20).optional().default([]),\n openapiUrl: z.string().max(2048).optional(),\n git: z.object({\n remote: z.string().max(2048).optional(),\n home: z.string().max(2048).optional(),\n }).optional(),\n meta: z.record(z.string().max(256), z.string().max(2000)).optional()\n .refine((obj) => !obj || Object.keys(obj).length <= 100, { message: 'Too many meta keys (max 100)' }),\n\n // Transient env dict (resolved by server before deployment, used directly by agent runner — NOT persisted)\n env: z.record(z.string().max(256), z.string().max(8192)).default({}).refine(\n (obj) => Object.keys(obj).length <= 200,\n { message: 'Too many env vars (max 200)' },\n ),\n envSecrets: z.array(z.string().max(256)).max(200).default([]),\n\n // Transient: resolved JS log parsers (from parserIds, resolved by server before deployment — NOT persisted)\n resolvedLogParsers: z.array(JSLogParserSchema).default([]).optional(),\n\n // Transient: resolved working directory (cwd with env vars expanded — NOT persisted)\n resolvedCwd: z.string().optional(),\n\n runner: z.enum(['native', 'docker']).optional().default('native'),\n dockerConfig: DockerConfigSchema.optional(),\n healthCheck: HealthCheckSchema.optional(),\n parserIds: z.array(z.string().max(128)).max(50).default([]),\n shortcuts: z.array(ServiceShortcutSchema).max(50).optional().default([]),\n autoRestart: z.boolean().optional().default(false),\n clearLogsOnStart: z.boolean().optional().default(false),\n restartStrategy: RestartStrategySchema.optional(),\n maxRestarts: z.number().int().nonnegative().optional(),\n restartBackoffMs: z.number().int().positive().optional().default(1000),\n\n // Log sources additionnelles (au-delà du stdout/stderr console par défaut)\n logSources: z.array(LogSourceConfigSchema).max(20).optional().default([]),\n});\n\nexport type ServiceConfig = z.infer<typeof ServiceConfigSchema>;\n\nexport const CreateServiceSchema = ServiceConfigSchema.omit({ id: true }).partial().required({ name: true });\nexport type CreateService = z.infer<typeof CreateServiceSchema>;\n\nexport const UpdateServiceSchema = ServiceConfigSchema.partial().required({ id: true }).extend({\n agentId: z.string().max(128).nullable().optional(), // null = clear (inherit from env), undefined = no change\n cwd: z.string().max(4096).nullable().optional(),\n git: z.object({ remote: z.string().max(2048).optional(), home: z.string().max(2048).optional() }).nullable().optional(),\n meta: z.record(z.string().max(256), z.string().max(2000)).nullable().optional()\n .refine((obj) => !obj || Object.keys(obj).length <= 100, { message: 'Too many meta keys (max 100)' }),\n healthCheck: HealthCheckSchema.nullable().optional(),\n});\nexport type UpdateService = z.infer<typeof UpdateServiceSchema>;\n","import { z } from 'zod';\nimport { ScenarioSchema } from './scenario.schema.js';\n\nexport const AI_PROVIDERS = ['anthropic', 'openai', 'mistral', 'groq', 'ollama'] as const;\nexport type AIProviderType = (typeof AI_PROVIDERS)[number];\n\nexport const AIProviderSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n provider: z.enum(AI_PROVIDERS),\n encryptedApiKey: z.string().max(2000).default(''),\n model: z.string().max(200).optional(),\n active: z.boolean().default(false),\n createdAt: z.coerce.date(),\n updatedAt: z.coerce.date(),\n});\n\nexport type AIProvider = z.infer<typeof AIProviderSchema>;\n\nexport const JSLogParserSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n description: z.string().max(2000).optional(),\n code: z.string().min(1).max(50000).refine(\n (s) => !s.includes('require(') && !s.includes('import ') && !s.includes('eval('),\n { message: 'Code must not contain require, import, or eval patterns' }\n ),\n enabled: z.boolean().default(true),\n builtin: z.boolean().optional(),\n createdAt: z.coerce.date(),\n updatedAt: z.coerce.date(),\n});\n\nexport type JSLogParser = z.infer<typeof JSLogParserSchema>;\n\nexport const NOTIFICATION_CATEGORIES = [\n 'scenario_waiting_input',\n 'ai_conversation_complete',\n 'ai_conversation_error',\n 'service_error_log',\n 'service_status_changed',\n 'service_health_changed',\n] as const;\nexport type NotificationCategory = (typeof NOTIFICATION_CATEGORIES)[number];\n\nexport const NotificationPreferencesSchema = z.object({\n scenario_waiting_input: z.boolean().default(true),\n ai_conversation_complete: z.boolean().default(true),\n ai_conversation_error: z.boolean().default(true),\n service_error_log: z.boolean().default(true),\n service_status_changed: z.boolean().default(true),\n service_health_changed: z.boolean().default(true),\n /** Service IDs excluded from error-log notifications */\n service_error_log_excluded: z.array(z.string().max(100)).max(500).default([]),\n /** Service IDs excluded from status-change notifications */\n service_status_changed_excluded: z.array(z.string().max(100)).max(500).default([]),\n /** Service IDs excluded from health-change notifications */\n service_health_changed_excluded: z.array(z.string().max(100)).max(500).default([]),\n});\nexport type NotificationPreferences = z.infer<typeof NotificationPreferencesSchema>;\n\n/**\n * Réglages du compagnon de relecture.\n *\n * Au niveau du POSTE, en clair, et non dans le coffre d'une organisation (§9) :\n * ce n'est pas un réglage d'équipe. Il décrit comment cette machine fait\n * travailler ses agents, il ne contient aucun secret, et le ranger dans un\n * coffre chiffré le rendrait dépendant de l'organisation qu'on regarde — un\n * même poste aurait autant de compagnons que d'organisations, sans raison.\n */\nexport const CompanionSettingsSchema = z.object({\n /** Activer le compagnon d'office sur les conversations créées ensuite. */\n enabledByDefault: z.boolean().default(false),\n /**\n * Spécificités ajoutées aux consignes Runeya.\n *\n * Vide — l'absence — signifie « aucune spécificité ». On ne recopie pas le\n * texte par défaut dans le réglage : les consignes Runeya restent dans le\n * code, pour profiter de leurs corrections.\n *\n * Rejeté au-delà de la borne plutôt que tronqué (§1) : un prompt coupé en\n * plein milieu produirait des relectures incohérentes sans rien signaler.\n */\n prompt: z.string().max(20_000).optional(),\n});\n\nexport type CompanionSettings = z.infer<typeof CompanionSettingsSchema>;\n\nexport const SettingsSchema = z.object({\n mode: z.enum(['local-simple', 'cloud']),\n cloudUrl: z.string().url().max(2048).nullable().optional(),\n logParsers: z.array(JSLogParserSchema).max(100).default([]),\n scenarios: z.array(ScenarioSchema).max(100).default([]),\n /** Absolute path to the folder where the global wiki/docs markdown files live. Optional. */\n globalDocsPath: z.string().max(4096).optional(),\n /**\n * Optionnel plutôt que défauté : un réglage absent est un réglage jamais\n * touché, et le rendre obligatoire dans le type forcerait chaque appelant qui\n * construit un objet de réglages à inventer une valeur.\n */\n companion: CompanionSettingsSchema.optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n\n\nexport const TraefikConfigSchema = z.object({\n enabled: z.boolean().default(false),\n acmeEmail: z.string().email().max(256).optional(),\n wildcardDomain: z.string().max(253).optional(),\n httpPort: z.number().int().min(1).max(65535).default(80),\n httpsPort: z.number().int().min(1).max(65535).default(443),\n dnsProvider: z.string().max(64).optional(),\n dnsCredentials: z.record(z.string().max(64), z.string().max(2048)).default({}),\n acmeStaging: z.boolean().default(false),\n encryptedCert: z.string().max(65536).optional(),\n encryptedCertKey: z.string().max(65536).optional(),\n});\n\nexport type TraefikConfig = z.infer<typeof TraefikConfigSchema>;\n\n\nexport const SettingsPrivateSchema = z.object({\n aiProviders: z.array(AIProviderSchema).max(50).default([]),\n scenarios: z.array(ScenarioSchema).max(100).default([]),\n notifications: NotificationPreferencesSchema.default(() => ({\n scenario_waiting_input: true,\n ai_conversation_complete: true,\n ai_conversation_error: true,\n service_error_log: true,\n service_status_changed: true,\n service_health_changed: true,\n service_error_log_excluded: [],\n service_status_changed_excluded: [],\n service_health_changed_excluded: [],\n })),\n traefikConfig: TraefikConfigSchema.optional(),\n});\n\nexport type SettingsPrivate = z.infer<typeof SettingsPrivateSchema>;\n\nexport const SchemaVersionSchema = z.object({\n version: z.number().int().positive(),\n migratedAt: z.coerce.date(),\n});\n\nexport type SchemaVersion = z.infer<typeof SchemaVersionSchema>;\n","import { z } from 'zod';\n\nconst PositionSchema = z.object({\n x: z.number(),\n y: z.number(),\n});\n\nexport const ScenarioGroupSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n description: z.string().max(1000).optional(),\n color: z.string().max(32).optional(),\n position: PositionSchema.default({ x: 0, y: 0 }),\n width: z.number().default(300),\n height: z.number().default(200),\n});\n\nexport type ScenarioGroup = z.infer<typeof ScenarioGroupSchema>;\n\nexport const SCENARIO_ROLES = [\n 'manager',\n 'engineer',\n 'designer',\n 'analyst',\n 'qa',\n 'devops',\n 'product',\n 'writer',\n 'researcher',\n 'other',\n] as const;\n\nexport type ScenarioRole = typeof SCENARIO_ROLES[number];\n\n// --- Presets ---\n\nexport const ScenarioPresetRoleSchema = z.object({\n id: z.string().min(1).max(64),\n name: z.string().min(1).max(200),\n systemPrompt: z.string().max(10_000).default(''),\n prompt: z.string().max(10_000).default(''),\n});\n\nexport type ScenarioPresetRole = z.infer<typeof ScenarioPresetRoleSchema>;\n\nexport const ScenarioPresetInitialDataSchema = z.object({\n leaderId: z.string().min(1).max(128),\n groups: z.array(z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n description: z.string().max(1000).optional(),\n color: z.string().max(32).optional(),\n position: z.object({ x: z.number(), y: z.number() }).default({ x: 0, y: 0 }),\n width: z.number().default(300),\n height: z.number().default(200),\n })).max(100).default([]),\n nodes: z.array(z.object({\n id: z.string().min(1).max(128),\n type: z.enum(['ai', 'ask']).default('ai'),\n parentIds: z.array(z.string().max(128)).default([]),\n groupId: z.string().max(128).nullable().default(null),\n label: z.string().max(240).default(''),\n role: z.string().max(64).default('other'),\n prompt: z.string().max(50_000).default(''),\n question: z.string().max(2_000).default(''),\n autoGenerated: z.boolean().default(true),\n canAddNode: z.boolean().default(false),\n aiCli: z.enum(['claude-code', 'codex']).default('claude-code'),\n model: z.string().max(128).default('sonnet'),\n position: z.object({ x: z.number(), y: z.number() }).default({ x: 0, y: 0 }),\n })).min(1).max(500),\n});\n\nexport type ScenarioPresetInitialData = z.infer<typeof ScenarioPresetInitialDataSchema>;\n\nconst LocalizedStringSchema = z.record(z.string(), z.string().max(100));\n\nexport const ScenarioPresetLabelsSchema = z.object({\n group: LocalizedStringSchema.optional(),\n node: LocalizedStringSchema.optional(),\n role: LocalizedStringSchema.optional(),\n leader: LocalizedStringSchema.optional(),\n});\n\nexport type ScenarioPresetLabels = z.infer<typeof ScenarioPresetLabelsSchema>;\n\nexport const ScenarioPresetSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n icon: z.string().max(64).optional(),\n defaultTraversalMode: z.enum(['hierarchical', 'topological']).optional(),\n canChangeTraversalMode: z.boolean().default(true),\n roles: z.array(ScenarioPresetRoleSchema).min(1).max(100),\n initialData: ScenarioPresetInitialDataSchema.optional(),\n labels: ScenarioPresetLabelsSchema.optional(),\n});\n\nexport type ScenarioPreset = z.infer<typeof ScenarioPresetSchema>;\n\n// --- Node ---\n\nexport const ScenarioNodeSchema = z.object({\n id: z.string().min(1).max(128),\n type: z.enum(['ai', 'ask']).default('ai'),\n parentIds: z.array(z.string().max(128)).default([]),\n groupId: z.string().max(128).nullable().default(null),\n label: z.string().max(240).default(''),\n role: z.string().max(64).default('other'),\n prompt: z.string().max(50_000).default(''),\n question: z.string().max(2_000).default(''),\n autoGenerated: z.boolean().default(true),\n canAddNode: z.boolean().default(false),\n aiCli: z.enum(['claude-code', 'codex']).default('claude-code'),\n model: z.string().max(128).default('sonnet'),\n position: PositionSchema.default({ x: 0, y: 0 }),\n injectParentOutputs: z.boolean().default(false),\n injectedAncestorIds: z.array(z.string().max(128)).default([]),\n});\n\nexport type ScenarioNode = z.infer<typeof ScenarioNodeSchema>;\n\nexport const ScenarioSchema = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n icon: z.string().max(64).optional(),\n description: z.string().max(2000).optional(),\n leaderId: z.string().min(1).max(128),\n groups: z.array(ScenarioGroupSchema).max(100).default([]),\n nodes: z.array(ScenarioNodeSchema).min(1).max(500),\n traversalMode: z.enum(['hierarchical', 'topological']).default('hierarchical'),\n presetId: z.string().max(128).optional(),\n isPublished: z.boolean().default(false),\n createdAt: z.number(),\n updatedAt: z.number(),\n});\n\nexport type Scenario = z.infer<typeof ScenarioSchema>;\n","import { z } from 'zod';\n\nconst safePath = z\n .string()\n .min(1)\n .max(4096)\n .refine(\n (p) => !p.includes('\\0'),\n { message: 'path must not contain null bytes' },\n )\n .refine(\n (p) => !/(^|[/\\\\])\\.\\.([/\\\\]|$)/.test(p),\n { message: 'path must not contain path-traversal sequences (..)' },\n )\n;\n\nexport const ConsoleLogSourceSchema = z.object({\n type: z.literal('console'),\n});\nexport type ConsoleLogSource = z.infer<typeof ConsoleLogSourceSchema>;\n\nexport const FileLogSourceSchema = z.object({\n type: z.literal('file'),\n path: safePath,\n encoding: z.string().max(32).default('utf-8'),\n startFromEnd: z.boolean().default(true),\n createIfNotExists: z.boolean().default(false),\n});\nexport type FileLogSource = z.infer<typeof FileLogSourceSchema>;\n\nexport const MongoLogSourceSchema = z.object({\n type: z.literal('mongo'),\n /** @sensitive — stored encrypted (AES-256-GCM) on disk */\n connectionString: z.string().min(1).max(2048),\n database: z.string().min(1).max(256),\n collection: z.string().min(1).max(256),\n filter: z.record(z.string(), z.unknown()).optional(),\n timestampField: z.string().max(128).default('timestamp'),\n messageField: z.string().max(128).default('message'),\n levelField: z.string().max(128).optional(),\n});\nexport type MongoLogSource = z.infer<typeof MongoLogSourceSchema>;\n\nexport const MySQLLogSourceSchema = z.object({\n type: z.literal('mysql'),\n host: z.string().min(1).max(253),\n port: z.number().int().min(1).max(65535).default(3306),\n user: z.string().min(1).max(256),\n /** @sensitive — stored encrypted (AES-256-GCM) on disk */\n password: z.string().max(2048),\n database: z.string().min(1).max(256),\n table: z.string().min(1).max(256),\n query: z.string().max(8192).optional(),\n timestampColumn: z.string().max(128).default('created_at'),\n messageColumn: z.string().max(128).default('message'),\n levelColumn: z.string().max(128).optional(),\n pollIntervalMs: z.number().int().min(500).max(60000).default(2000),\n});\nexport type MySQLLogSource = z.infer<typeof MySQLLogSourceSchema>;\n\nexport const LogSourceConfigSchema = z.discriminatedUnion('type', [\n ConsoleLogSourceSchema,\n FileLogSourceSchema,\n MongoLogSourceSchema,\n MySQLLogSourceSchema,\n]);\nexport type LogSourceConfig = z.infer<typeof LogSourceConfigSchema>;\nexport type LogSourceType = LogSourceConfig['type'];\n","import { z } from 'zod';\n\nexport const ProcessStateSchema = z.enum(['starting', 'running', 'stopped', 'errored']);\nexport type ProcessState = z.infer<typeof ProcessStateSchema>;\n\nexport const HealthStatusSchema = z.enum(['healthy', 'unhealthy', 'unknown']);\nexport type HealthStatus = z.infer<typeof HealthStatusSchema>;\n\nexport const ProcessStatusSchema = z.object({\n id: z.string().max(128),\n serviceId: z.string().max(128),\n agentId: z.string().max(128),\n state: ProcessStateSchema,\n pid: z.number().int().nullable().optional(),\n pids: z.array(z.number().int()).optional().default([]),\n exitCode: z.number().int().nullable().optional(),\n startedAt: z.coerce.date().nullable().optional(),\n restartCount: z.number().int().nonnegative().default(0),\n uptime: z.number().nonnegative().default(0),\n healthStatus: HealthStatusSchema.default('unknown'),\n /**\n * Le répertoire où le processus s'exécute VRAIMENT, absolutisé par l'agent.\n *\n * Rapporté par l'agent plutôt que déduit de la config : entre le `cwd` de la\n * commande, celui du service, l'ancrage sur le projet et les variables que\n * l'agent étend lui-même, la valeur affichée n'aurait rien prouvé. Ce qui\n * intéresse quand un service tourne contre le mauvais dépôt, c'est le chemin\n * final — y compris quand il retombe sur le répertoire de l'agent.\n */\n cwd: z.string().max(4096).nullable().optional(),\n});\n\nexport type ProcessStatus = z.infer<typeof ProcessStatusSchema>;\n","import { z } from 'zod';\n\nexport const LogLevelSchema = z.enum(['debug', 'info', 'warn', 'error', 'fatal']);\nexport type LogLevel = z.infer<typeof LogLevelSchema>;\n\nexport const LogLineSchema = z.object({\n /** Raw log line as received from the process (immutable context) */\n raw: z.string(),\n /** Source stream (immutable context) */\n stream: z.enum(['stdout', 'stderr']),\n /** Severity level */\n level: LogLevelSchema,\n /** Parsed/enriched message to display */\n message: z.string(),\n /** When true, the line is hidden from the log view */\n hidden: z.boolean(),\n /** Arbitrary key/value pairs shown in the detail panel */\n metadata: z.record(z.string().max(256), z.unknown()).refine(\n (obj) => Object.keys(obj).length <= 100,\n { message: 'Too many metadata keys (max 100)' },\n ),\n /** Full parsed JSON object when the line is JSON */\n json: z.record(z.string(), z.unknown()).optional(),\n /** Custom header for the JSON log card (supports HTML, sanitized before display) */\n jsonHeader: z.string().max(256).optional(),\n});\n\nexport type LogLine = z.infer<typeof LogLineSchema>;\n\nexport const LogCardDirectiveSchema = z.object({\n id: z.string().max(128),\n type: z.string().max(64),\n header: z.string().max(256),\n collapsable: z.boolean().optional(),\n collapsed: z.boolean().optional(),\n state: z.enum(['open', 'append', 'close', 'self']),\n});\nexport type LogCardDirective = z.infer<typeof LogCardDirectiveSchema>;\n\nexport const ParsedLogSchema = z.object({\n id: z.string().max(128),\n processId: z.string().max(128),\n pid: z.number().int().nullable().optional(),\n timestamp: z.coerce.date(),\n level: LogLevelSchema.default('info'),\n message: z.string().max(16384),\n raw: z.string().max(16384),\n stream: z.enum(['stdout', 'stderr']).default('stdout'),\n hidden: z.boolean().optional().default(false),\n metadata: z.record(z.string().max(256), z.unknown()).optional().refine(\n (obj) => !obj || Object.keys(obj).length <= 100,\n { message: 'Too many metadata keys (max 100)' },\n ),\n json: z.record(z.string(), z.unknown()).optional(),\n logCard: LogCardDirectiveSchema.optional(),\n sourceType: z.enum(['console', 'file', 'mongo', 'mysql']).optional(),\n sourcePath: z.string().max(4096).optional(),\n});\n\nexport type ParsedLog = z.infer<typeof ParsedLogSchema>;\n","import { z } from 'zod';\n\n/** Regex for valid POSIX environment variable names */\nexport const ENV_VAR_NAME_REGEX = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport const AgentConfigSchema = z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(100),\n url: z.string().url().max(2048),\n passphrase: z.string().min(1).max(1024),\n passthroughEnv: z.array(\n z.string().regex(ENV_VAR_NAME_REGEX).max(256),\n ).max(100).default([]),\n});\n\nexport type AgentConfig = z.infer<typeof AgentConfigSchema>;\n\nexport const AgentStatusSchema = z.object({\n connected: z.boolean(),\n lastSeen: z.string().nullable().optional(),\n uptime: z.number().nonnegative().default(0),\n runnersAvailable: z.array(z.enum(['native', 'docker'])).default(['native']),\n lanIp: z.string().optional(),\n /**\n * Ce que la machine de l'agent vaut pour les builtins de portée `agent`.\n * Sert à PRÉVISUALISER — la valeur injectée reste calculée au lancement, par\n * l'agent lui-même : une IP change, un agent se déconnecte, et un statut\n * n'est qu'un cliché.\n */\n os: z.string().max(64).optional(),\n home: z.string().max(4096).optional(),\n cwd: z.string().max(4096).optional(),\n});\n\nexport type AgentStatus = z.infer<typeof AgentStatusSchema>;\n","import { z } from 'zod';\n\nexport const GlobalRoleSchema = z.enum(['owner', 'admin', 'member']);\nexport type GlobalRole = z.infer<typeof GlobalRoleSchema>;\n\nexport const ProjectRoleSchema = z.enum(['admin', 'editor', 'viewer']);\nexport type ProjectRole = z.infer<typeof ProjectRoleSchema>;\n\nexport const ProjectMemberRoleSchema = z.object({\n id: z.string().max(128),\n projectId: z.string().max(128),\n userId: z.string().max(128),\n role: ProjectRoleSchema,\n});\n\nexport type ProjectMemberRole = z.infer<typeof ProjectMemberRoleSchema>;\n","import { z } from 'zod';\n\nexport const ConfigVersionSchema = z.object({\n id: z.string().max(128),\n entityType: z.enum(['project', 'service']),\n entityId: z.string().max(128),\n version: z.string().max(128),\n parentVersion: z.string().max(128),\n data: z.record(z.string(), z.unknown()).refine(\n (obj) => Object.keys(obj).length <= 1000,\n 'Too many data keys (max 1000)',\n ),\n patch: z.array(z.record(z.string(), z.unknown())).max(1000),\n userId: z.string().max(128),\n timestamp: z.coerce.date(),\n resolved: z.boolean().default(false),\n});\n\nexport type ConfigVersion = z.infer<typeof ConfigVersionSchema>;\n\nexport const ConfigChangeSchema = z.object({\n entityType: z.enum(['project', 'service']),\n entityId: z.string().max(128),\n version: z.string().max(128),\n parentVersion: z.string().max(128),\n data: z.record(z.string(), z.unknown()).refine(\n (obj) => Object.keys(obj).length <= 1000,\n 'Too many data keys (max 1000)',\n ),\n patch: z.array(z.record(z.string(), z.unknown())).max(1000),\n});\n\nexport type ConfigChange = z.infer<typeof ConfigChangeSchema>;\n\nexport const SyncStatusSchema = z.object({\n connected: z.boolean(),\n lastSync: z.coerce.date().nullable().optional(),\n pendingChanges: z.number().int().nonnegative().default(0),\n conflicts: z.number().int().nonnegative().default(0),\n});\n\nexport type SyncStatus = z.infer<typeof SyncStatusSchema>;\n","import { z } from 'zod';\n\nexport const AuditActionSchema = z.enum([\n 'create', 'update', 'delete',\n 'invite', 'remove',\n 'deploy', 'start', 'stop',\n 'roleChange',\n]);\n\nexport type AuditAction = z.infer<typeof AuditActionSchema>;\n\nexport const AuditEntityTypeSchema = z.enum([\n 'org', 'project', 'service', 'member', 'permission',\n]);\n\nexport type AuditEntityType = z.infer<typeof AuditEntityTypeSchema>;\n\nexport const AuditLogSchema = z.object({\n id: z.string().max(128),\n orgId: z.string().max(128),\n userId: z.string().max(128),\n action: AuditActionSchema,\n entityType: AuditEntityTypeSchema,\n entityId: z.string().max(128),\n metadata: z.record(z.string().max(256), z.unknown()).default({}).refine(\n (obj) => Object.keys(obj).length <= 100,\n { message: 'Too many metadata keys (max 100)' },\n ),\n timestamp: z.coerce.date(),\n});\n\nexport type AuditLog = z.infer<typeof AuditLogSchema>;\n","import { z } from 'zod';\n\nexport const ProcessMetricsSchema = z.object({\n processId: z.string().max(128),\n cpu: z.number().nonnegative(),\n memory: z.number().int().nonnegative(),\n timestamp: z.string(),\n});\n\nexport type ProcessMetrics = z.infer<typeof ProcessMetricsSchema>;\n","import { z } from 'zod';\nimport { VariableSchema } from './service.schema.js';\n\n// Environment schema — uses VariablesRecord for variable storage\nexport const EnvironmentVariablesSchema = z.record(\n z.string().max(256),\n VariableSchema,\n).refine(\n (obj) => Object.keys(obj).length <= 200,\n { message: 'Max 200 variables' },\n);\n\nexport const EnvironmentSchema = z.object({\n id: z.string().max(128),\n projectId: z.string().max(128),\n name: z.string().min(1).max(200),\n description: z.string().max(2000).optional().default(''),\n parentIds: z.array(z.string().max(128)).max(10).default([]),\n variables: EnvironmentVariablesSchema.default({}),\n // Scope: 'global' = project-level env, 'service' = per-service env\n scope: z.enum(['global', 'service']).default('global'),\n // When scope='service': the serviceId this env belongs to\n reference: z.string().max(128).optional(),\n // When scope='service': the globalEnvId this env activates on\n activateOn: z.string().max(128).optional(),\n immutable: z.boolean().default(false),\n default: z.boolean().optional().default(false),\n color: z.string().max(20).optional(),\n bgColor: z.string().max(20).optional(),\n // When scope='global': the default agent used by services that don't have an explicit agentId\n agentId: z.string().max(128).optional(),\n});\n\nexport type Environment = z.infer<typeof EnvironmentSchema>;\n\n// Resolved environment: flattened env dict + secrets list + source tracking\nexport const ResolvedEnvironmentSchema = z.object({\n variables: z.record(z.string().max(256), VariableSchema)\n .refine((obj) => Object.keys(obj).length <= 500, { message: 'Max 500 resolved variables' }),\n env: z.record(z.string().max(256), z.string().max(8192))\n .refine((obj) => Object.keys(obj).length <= 500, { message: 'Max 500 resolved env vars' }),\n envSecrets: z.array(z.string().max(256)).max(500),\n sources: z.record(z.string().max(256), z.object({\n environmentId: z.string().max(128),\n environmentName: z.string().max(200),\n overridden: z.boolean(),\n resolvedFrom: z.object({\n environmentId: z.string().max(128),\n environmentName: z.string().max(200),\n }).optional(),\n // Set when a machine-local override was applied to this variable, pointing\n // at the environment that carries the winning override. Distinct from\n // `overridden`, which also covers \"shadows an inherited variable\".\n overriddenBy: z.object({\n environmentId: z.string().max(128),\n environmentName: z.string().max(200),\n }).optional(),\n })).refine((obj) => Object.keys(obj).length <= 500, { message: 'Max 500 source entries' }),\n});\n\nexport type ResolvedEnvironment = z.infer<typeof ResolvedEnvironmentSchema>;\n\nexport const CreateEnvironmentSchema = EnvironmentSchema.omit({ id: true }).extend({\n description: z.string().max(2000).optional().default(''),\n parentIds: z.array(z.string().max(128)).max(10).optional().default([]),\n variables: EnvironmentVariablesSchema.optional().default({}),\n scope: z.enum(['global', 'service']).optional().default('global'),\n reference: z.string().max(128).optional(),\n activateOn: z.string().max(128).optional(),\n immutable: z.boolean().optional().default(false),\n});\nexport type CreateEnvironment = z.input<typeof CreateEnvironmentSchema>;\n\n// IMPORTANT: Do NOT simplify this to `EnvironmentSchema.partial().required({ id: true })`.\n//\n// EnvironmentSchema has .default() on several fields (variables: {}, parentIds: [], description: '',\n// scope: 'global', immutable: false, default: false). When Zod parses a partial update input that\n// omits those fields, .partial() alone does NOT strip the defaults — Zod still fills them in.\n// The store checks `input.variables !== undefined` to decide whether to overwrite, so if Zod\n// silently injects `variables: {}`, the store wipes ALL existing variables on every save.\n//\n// The .extend() below overrides those fields without .default(), making them truly optional\n// (undefined when absent). DO NOT remove it or merge the .extend() back into EnvironmentSchema.\nexport const UpdateEnvironmentSchema = EnvironmentSchema\n .partial()\n .required({ id: true })\n .extend({\n description: z.string().max(2000).optional(),\n parentIds: z.array(z.string().max(128)).max(10).optional(),\n variables: EnvironmentVariablesSchema.optional(),\n scope: z.enum(['global', 'service']).optional(),\n immutable: z.boolean().optional(),\n default: z.boolean().optional(),\n agentId: z.string().max(128).nullable().optional(), // null = clear (no default agent)\n });\nexport type UpdateEnvironment = z.infer<typeof UpdateEnvironmentSchema>;\n","import { z } from 'zod';\nimport { VariableSlotSchema } from './service.schema.js';\n\n// An override carries ONLY a value slot: the env var name always comes from the\n// variable definition in `environments.json`, looked up by variable ID. Storing\n// a `key` here would go stale as soon as the variable is renamed in the UI.\nexport const VariableOverrideSchema = z.object({\n value: VariableSlotSchema,\n});\n\nexport type VariableOverride = z.infer<typeof VariableOverrideSchema>;\n\n// Environment overrides: Record<variableId, VariableOverride>\n// Flat structure — each override is keyed by the variable's unique ID.\nexport const EnvironmentOverridesSchema = z.record(\n z.string().max(128),\n VariableOverrideSchema,\n).refine(\n (obj) => Object.keys(obj).length <= 5000,\n { message: 'Max 5000 overrides' },\n);\n\nexport type EnvironmentOverrides = z.infer<typeof EnvironmentOverridesSchema>;\n","import { z } from 'zod';\n\nexport const ApiServiceActionSchema = z.enum([\n 'service:read',\n 'service:start',\n 'service:stop',\n 'service:restart',\n 'service:healthcheck',\n 'service:status',\n 'logs:read',\n]);\nexport type ApiServiceAction = z.infer<typeof ApiServiceActionSchema>;\n\nexport const ApiEnvActionSchema = z.enum(['env:read', 'env:write']);\nexport type ApiEnvAction = z.infer<typeof ApiEnvActionSchema>;\n\nexport const ApiEnvPermSchema = z.object({\n environmentId: z.string().max(128),\n actions: z.array(ApiEnvActionSchema).max(10).default(['env:read']),\n includeSecrets: z.boolean().default(false),\n});\nexport type ApiEnvPerm = z.infer<typeof ApiEnvPermSchema>;\n\nexport const ApiServicePermSchema = z.object({\n serviceId: z.string().max(128),\n actions: z.array(ApiServiceActionSchema).max(10).default(['service:read']),\n environments: z.array(ApiEnvPermSchema).max(100).default([]),\n});\nexport type ApiServicePerm = z.infer<typeof ApiServicePermSchema>;\n\nexport const ApiKeyScopeSchema = z.object({\n services: z.array(ApiServicePermSchema).max(500).default([]),\n});\nexport type ApiKeyScope = z.infer<typeof ApiKeyScopeSchema>;\n\nexport const ApiKeySchema = z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(200),\n key: z.string().regex(/^[0-9a-f]{64}$/i),\n scopes: ApiKeyScopeSchema,\n createdAt: z.string().max(64),\n isPublic: z.boolean().default(false),\n});\nexport type ApiKey = z.infer<typeof ApiKeySchema>;\n\n/**\n * Shape of an API key as it sits on disk: `key` holds the *encrypted* secret,\n * so it no longer matches the 64-hex form the in-memory type guarantees.\n * Legacy files written before encryption still parse — the store decrypts only\n * what looks encrypted and re-persists.\n */\nexport const PersistedApiKeySchema = ApiKeySchema.extend({\n key: z.string().min(1).max(4096),\n});\nexport type PersistedApiKey = z.infer<typeof PersistedApiKeySchema>;\n\nexport const ApiKeysFileSchema = z.object({\n keys: z.array(PersistedApiKeySchema).max(100),\n});\n\n/** An API key as exposed by the API: the secret is never part of it. */\nexport const MaskedApiKeySchema = ApiKeySchema.omit({ key: true }).extend({\n /** Last 4 characters of the secret, for recognising a key in a list. */\n keyPreview: z.string().max(8),\n});\nexport type MaskedApiKey = z.infer<typeof MaskedApiKeySchema>;\n\n","import { z } from 'zod';\n\nexport const ALLOWED_IMAGE_MIME_TYPES = ['image/png', 'image/jpeg', 'image/webp', 'image/gif'] as const;\n\nexport const ImagePartSchema = z.object({\n type: z.literal('image'),\n imageId: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'Must be a valid UUID'),\n url: z.string().min(1),\n mimeType: z.enum(ALLOWED_IMAGE_MIME_TYPES),\n altText: z.string().max(500).optional(),\n});\n\nexport type ImagePart = z.infer<typeof ImagePartSchema>;\n\nexport const ImageUploadResponseSchema = z.object({\n imageId: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'Must be a valid UUID'),\n url: z.string().min(1),\n mimeType: z.enum(ALLOWED_IMAGE_MIME_TYPES),\n originalName: z.string(),\n});\n\nexport type ImageUploadResponse = z.infer<typeof ImageUploadResponseSchema>;\n\nexport const ImageMetaSchema = z.object({\n imageId: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'Must be a valid UUID'),\n filePath: z.string().min(1),\n mimeType: z.enum(ALLOWED_IMAGE_MIME_TYPES),\n originalName: z.string().min(1),\n createdAt: z.number().positive(),\n size: z.number().positive().optional(),\n});\n\nexport type ImageMeta = z.infer<typeof ImageMetaSchema>;\n","import { z } from 'zod';\n\n// --- Attachments ---\n/**\n * A file attached to a card. The bytes live in object storage; the card keeps\n * only this descriptor, so a board document stays small no matter how many\n * files it carries.\n */\nexport const KanbanAttachmentSchema = z.object({\n /** Server-issued id, also the storage key. */\n id: z.string().max(128),\n name: z.string().max(255),\n size: z.number().int().nonnegative(),\n contentType: z.string().max(128),\n});\nexport type KanbanAttachment = z.infer<typeof KanbanAttachmentSchema>;\n\n// --- Card History ---\nexport const KanbanCardEventSchema = z.object({\n type: z.enum(['created', 'edited', 'moved', 'image_added', 'image_removed', 'title_changed', 'conversation_started', 'scenario_started', 'comment', 'archived', 'unarchived']),\n timestamp: z.string(),\n /** Extra context: old/new column name, old/new title, comment text, etc. */\n /**\n * Le texte de l'entrée : le corps d'un commentaire, ou le contexte du geste.\n *\n * Borné comme le corps d'une carte (100 000), et non plus à 5 000 : un\n * commentaire est de la prose comme une description, et rien de technique ne\n * justifiait un écart de vingt fois. La borne étroite s'est vue à l'import\n * d'un Kanbanize, où des commentaires de 12 000 caractères passaient par\n * l'API publique — bornée, elle, à 20 000 — pour écrire en base une donnée que\n * ce schéma déclarait invalide, et qu'aucune reprise depuis l'interface\n * n'aurait ensuite pu enregistrer.\n */\n detail: z.string().max(100_000).optional(),\n /**\n * Stable identity of the event, used to tell an edit from an insertion when a\n * whole history is written back. Absent on events recorded before the field\n * existed; those fall back to (type, timestamp).\n */\n id: z.string().max(128).optional(),\n /**\n * La colonne où l'événement fait entrer la carte (`created`, `moved`,\n * `unarchived`). Le `detail` n'en porte que le titre, qu'un renommage rend\n * introuvable : l'identifiant, lui, tient. Absent des événements antérieurs\n * que la migration n'a pas pu rapprocher.\n */\n columnId: z.string().max(128).optional(),\n /** Who authored this event — 'ai' or 'user'. Only set for comment events. */\n author: z.enum(['ai', 'user']).optional(),\n /**\n * Qui est derrière l'événement, estampillé par le serveur — jamais pris du\n * client, sans quoi n'importe qui pourrait signer au nom d'un autre.\n *\n * Posé sur les commentaires (c'est ce qui rend « mon propre commentaire »\n * répondable ; `author` ne sépare que l'IA de l'humain) et sur les\n * déplacements. Absent des événements écrits avant qu'on l'estampille : un\n * lecteur doit donc afficher « on ne sait pas », pas un nom vide.\n *\n * Pour une clé d'API, c'est le nom de la clé et non son porteur : la clé\n * emprunte les droits de son créateur, pas son identité — personne ne doit\n * croire qu'un humain a déplacé ce qu'un robot de CI a déplacé.\n */\n authorUser: z.object({ id: z.string().max(128), name: z.string().max(200) }).optional(),\n /** Set when the author amended their comment, so the UI can say so. */\n editedAt: z.string().optional(),\n /** Files attached to a comment — same storage as a card's own attachments. */\n attachments: z.array(KanbanAttachmentSchema).max(20).optional(),\n /** Conversation that produced this event (comments only). Used to navigate back to the conversation. */\n conversationId: z.string().optional(),\n});\nexport type KanbanCardEvent = z.infer<typeof KanbanCardEventSchema>;\n\n// --- Card ---\nexport const KanbanCardSchema = z.object({\n id: z.string(),\n title: z.string().min(1).max(500),\n markdown: z.string().max(100_000).default(''),\n /**\n * Legacy inline images, kept so boards written before object storage still\n * render. New uploads go to `attachments` instead.\n */\n images: z.array(z.string()).default([]),\n /** Files attached to the card — stored out of band, referenced here. */\n attachments: z.array(KanbanAttachmentSchema).max(50).default([]),\n order: z.number().int(),\n /**\n * La priorité de la carte, de 1 à 10 — 10 étant le plus urgent.\n *\n * Facultative, et absente veut dire « pas de priorité », pas « la plus\n * basse » : une carte qu'on n'a pas encore arbitrée ne doit pas se ranger\n * d'office au fond de la pile.\n */\n priority: z.number().int().min(1).max(10).optional(),\n\n /**\n * Les groupes de la carte — des étiquettes libres, posées par l'équipe.\n *\n * Rien ne les déclare ailleurs : un groupe existe parce qu'une carte le\n * porte, et disparaît avec la dernière qui le portait. C'est ce qui permet\n * d'en créer un en le tapant, sans passer par un écran d'administration.\n */\n groups: z.array(z.string().min(1).max(60)).max(30).optional(),\n /**\n * L'échéance de la carte : le jour où elle est attendue, `AAAA-MM-JJ`.\n *\n * Un jour, pas un instant, et c'est une décision : une équipe se dit « pour\n * vendredi », jamais « pour vendredi 23:59:59 UTC ». Stocker un instant\n * ferait afficher une échéance au 4 mars comme le 3 mars à qui travaille à\n * l'ouest de Greenwich — la carte serait en retard d'un jour pour la moitié\n * de l'équipe, et personne ne saurait pourquoi.\n *\n * Facultative, et absente veut dire « pas d'échéance », pas « en retard » :\n * une carte qu'on n'a pas datée ne doit pas s'annoncer comme urgente.\n */\n deadline: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/).optional(),\n\n /**\n * La couleur de la carte, en hexadécimal (`#RRGGBB`) — un liseré en haut de\n * la carte, et rien d'autre : ce qu'elle veut dire appartient à l'équipe.\n *\n * Bornée à une notation stricte plutôt qu'à une chaîne libre : cette valeur\n * finit dans un attribut `style`, et une couleur ne doit pouvoir contenir\n * qu'une couleur. Absente sur les cartes sans couleur.\n */\n color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),\n /**\n * Le journal de la carte — commentaires compris.\n *\n * Optionnel, et c'est tout l'intérêt : c'est la partie qui grossit sans fin\n * (une IA bavarde y écrit des pages), alors les lectures de tableau ne le\n * transportent plus. `undefined` veut dire « pas chargé », et une écriture\n * qui l'omet laisse au serveur celui qu'il a en base — à ne pas confondre\n * avec `[]`, qui demanderait bel et bien de le vider.\n */\n history: z.array(KanbanCardEventSchema).optional(),\n /**\n * Ce que le journal absent laisse quand même dire : combien de commentaires,\n * et quand fut le dernier. Posés par le serveur en lecture, ignorés en\n * écriture — la carte ne les stocke pas, ils se déduisent de `history`.\n */\n commentCount: z.number().int().nonnegative().optional(),\n lastCommentAt: z.string().optional(),\n /**\n * L'auteur du dernier commentaire, pour son avatar sur la tuile. Même règle :\n * posé en lecture, ignoré en écriture. `id`/`name` absents quand le\n * commentaire précède l'estampille d'auteur — on sait alors seulement si\n * c'était une IA.\n */\n lastCommentBy: z\n .object({ id: z.string().max(128).optional(), name: z.string().max(200).optional(), author: z.enum(['ai', 'user']).optional() })\n .optional(),\n /**\n * Les entrées de journal qui ouvrent une conversation IA. Elles restent dans\n * la lecture allégée — il y en a une poignée par carte, et l'hôte s'en sert\n * pour dire, sans ouvrir la carte, qu'une IA y travaille.\n */\n conversationEvents: z.array(KanbanCardEventSchema).optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n /**\n * Quand la carte a été archivée — absente tant qu'elle est au tableau.\n *\n * Une carte archivée reste dans sa colonne en base : c'est la lecture qui la\n * retire du tableau, jamais une écriture qui la déplace. Rien à recoller donc\n * au désarchivage, et aucun cimetière où une carte pourrait se perdre.\n */\n archivedAt: z.string().optional(),\n /**\n * La colonne d'où la carte a été archivée, telle qu'elle s'appelait alors.\n *\n * L'identifiant sert à l'y remettre, le titre à le dire dans l'archive même\n * quand la colonne a disparu depuis — auquel cas le désarchivage repose la\n * carte dans la première colonne, sans se taire sur son origine.\n */\n archivedFrom: z\n .object({ columnId: z.string().max(128), columnTitle: z.string().max(200) })\n .optional(),\n /**\n * Quand la carte a été supprimée. Rien n'est effacé : la carte reste en base,\n * et toutes les lectures l'écartent.\n *\n * Une suppression est le seul geste que rien ne rattrape — sauf à ne pas\n * l'exécuter vraiment. La colonne et le tableau portent le même champ, pour\n * que supprimer l'un n'emporte jamais les cartes de l'autre.\n */\n deletedAt: z.string().optional(),\n /**\n * People assigned to the card. Names are denormalized for display; the server\n * keeps only members of the owning organization, and notifies newcomers.\n */\n assignees: z\n .array(z.object({ id: z.string().max(128), name: z.string().max(200) }))\n .max(20)\n .default([]),\n /**\n * Who first created the card. Stamped by the server the first time a card id\n * appears in a board write, never taken from the client — a member could\n * otherwise claim any authorship. Absent on cards created before this field\n * existed, so readers must treat it as unknown rather than assume.\n */\n createdBy: z\n .object({ id: z.string().max(128), name: z.string().max(200) })\n .optional(),\n});\nexport type KanbanCard = z.infer<typeof KanbanCardSchema>;\n\n// --- Column ---\nexport const KanbanColumnSchema = z.object({\n id: z.string(),\n title: z.string().min(1).max(200),\n order: z.number().int(),\n cards: z.array(KanbanCardSchema).default([]),\n /**\n * Le regroupement auquel la colonne appartient, s'il y en a un.\n *\n * Un pointeur vers le parent, et rien dans l'autre sens : le groupe ne tient\n * pas la liste de ses membres. Deux listes qui prétendent dire qui contient\n * quoi finissent par se contredire, et un déplacement devient alors deux\n * écritures au lieu d'une.\n */\n groupId: z.string().optional(),\n /**\n * Colonne de cartes finalisées : y entrer compte comme « finalisée » dans les\n * statistiques de la liste, au même titre qu'un archivage.\n */\n done: z.boolean().optional(),\n /** Supprimée, mais conservée — voir `deletedAt` sur la carte. */\n deletedAt: z.string().optional(),\n});\nexport type KanbanColumn = z.infer<typeof KanbanColumnSchema>;\n\n// --- Column group ---\n/**\n * Un regroupement de colonnes : un bandeau au-dessus d'elles, pas une colonne.\n *\n * Il ne porte aucune carte — jamais — et c'est ce qui le rend inoffensif :\n * `columnId`, les rangs fractionnaires et tout le déplacement de cartes\n * ignorent son existence. Un groupe peut en contenir un autre (`parentId`).\n *\n * Il n'a délibérément **pas** d'`order` : sa place se déduit de celle de ses\n * colonnes, dont l'ordre reste l'unique source de vérité. Un groupe qui aurait\n * son propre rang pourrait contredire celui de ses membres, et il n'existerait\n * alors aucune bonne réponse à « laquelle des deux positions gagne ».\n */\nexport const KanbanColumnGroupSchema = z.object({\n id: z.string(),\n title: z.string().min(1).max(200),\n /** La couleur du bandeau, en hexadécimal — l'interface décide du défaut. */\n color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),\n /** Le groupe parent, pour les regroupements imbriqués. */\n parentId: z.string().optional(),\n /** Supprimé, mais conservé — comme une colonne. */\n deletedAt: z.string().optional(),\n});\nexport type KanbanColumnGroup = z.infer<typeof KanbanColumnGroupSchema>;\n\n// --- Board ---\nexport const KanbanBoardSchema = z.object({\n id: z.string(),\n name: z.string().min(1).max(200),\n description: z.string().max(10_000).default(''),\n /**\n * Le mode d'emploi du tableau, en texte libre : ce que veulent dire ses\n * colonnes, quand une carte a le droit d'avancer, les conventions de\n * l'équipe. Écrit par les humains, lu surtout par l'IA — il est injecté dans\n * le prompt des agents pour qu'ils travaillent selon les règles du tableau\n * plutôt que selon les leurs.\n */\n instructions: z.string().max(20_000).default(''),\n columns: z.array(KanbanColumnSchema).default([]),\n /** Les regroupements de colonnes — vide sur un tableau qui n'en a jamais eu. */\n columnGroups: z.array(KanbanColumnGroupSchema).default([]),\n /**\n * Les projets auxquels le tableau est rattaché, par leur identifiant.\n *\n * Un rattachement, pas une possession : il ne sert qu'à filtrer la liste des\n * tableaux, et un tableau sans projet (`[]`, le cas par défaut) reste visible\n * partout. Plusieurs projets sont permis parce qu'une équipe partage souvent\n * un même tableau entre deux projets — obliger à choisir l'un des deux\n * ferait disparaître le tableau de la liste de l'autre.\n *\n * Les identifiants sont ceux des projets de l'organisation ; le serveur\n * refuse ceux qu'il ne connaît pas plutôt que de garder un lien mort.\n */\n projectIds: z.array(z.string().min(1).max(128)).max(20).default([]),\n archived: z.boolean().default(false),\n /** Supprimé, mais conservé avec ses cartes — voir `deletedAt` sur la carte. */\n deletedAt: z.string().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\nexport type KanbanBoard = z.infer<typeof KanbanBoardSchema>;\n\n// --- Inputs ---\nexport const CreateKanbanBoardInput = z.object({\n name: z.string().min(1).max(200),\n description: z.string().max(10_000).optional(),\n instructions: z.string().max(20_000).optional(),\n projectIds: z.array(z.string().min(1).max(128)).max(20).optional(),\n});\nexport type CreateKanbanBoardInput = z.infer<typeof CreateKanbanBoardInput>;\n\nexport const UpdateKanbanBoardInput = z.object({\n id: z.string(),\n name: z.string().min(1).max(200).optional(),\n description: z.string().max(10_000).optional(),\n instructions: z.string().max(20_000).optional(),\n columns: z.array(KanbanColumnSchema).optional(),\n archived: z.boolean().optional(),\n projectIds: z.array(z.string().min(1).max(128)).max(20).optional(),\n});\nexport type UpdateKanbanBoardInput = z.infer<typeof UpdateKanbanBoardInput>;\n\n// --- Card links ---\n/**\n * Un lien entre deux cartes, rangé hors des tableaux.\n *\n * Le lien ne vit pas dans la carte, et c'est délibéré : une carte se réécrit\n * par tableau entier, et un client plus ancien — dont le Zod ignore le champ —\n * effacerait silencieusement le lien en sauvegardant le tableau. Dans sa propre\n * collection, il survit à toutes les écritures de tableau, y compris celles des\n * versions qui ne le connaissent pas.\n *\n * Un seul type pour l'instant, la filiation : `parent` est la carte au-dessus,\n * `child` celle qui en dépend. Une carte a au plus un parent (c'est le\n * `parent_id` habituel), et les deux extrémités peuvent vivre sur des tableaux\n * différents — la même organisation, en revanche, toujours.\n */\nexport const KanbanCardLinkSchema = z.object({\n id: z.string().max(128),\n /** Le tableau et la carte qui *dépendent* de l'autre. */\n childBoardId: z.string().max(64),\n childCardId: z.string().max(128),\n /** Le tableau et la carte *dont* on dépend. */\n parentBoardId: z.string().max(64),\n parentCardId: z.string().max(128),\n createdAt: z.string(),\n createdBy: z.object({ id: z.string().max(128), name: z.string().max(200) }).optional(),\n});\nexport type KanbanCardLink = z.infer<typeof KanbanCardLinkSchema>;\n\n/**\n * De quoi afficher une carte liée sans ouvrir son tableau : son titre, sa\n * colonne, et le tableau où elle se trouve. Résolu à la lecture plutôt que\n * recopié dans le lien — un titre recopié devient faux au premier renommage.\n */\nexport const KanbanCardRefSchema = z.object({\n cardId: z.string().max(128),\n boardId: z.string().max(64),\n boardName: z.string().max(200),\n columnId: z.string().max(128),\n columnTitle: z.string().max(200),\n title: z.string().max(500),\n /** Les mêmes informations qu'une ligne de tableau montre d'une carte d'ici. */\n assignees: z.array(z.object({ id: z.string().max(128), name: z.string().max(200) })).default([]),\n commentCount: z.number().int().nonnegative().default(0),\n});\nexport type KanbanCardRef = z.infer<typeof KanbanCardRefSchema>;\n","import { z } from 'zod';\n\n/**\n * Les clés d'API du cloud : ce qu'un système tiers présente pour alimenter un\n * kanban sans être un humain connecté.\n *\n * Distinctes des clés de `api-key.schema.ts`, qui ouvrent l'API du serveur\n * *local* et nomment des services. Celles-ci appartiennent à une organisation\n * cloud et ne parlent que de tableaux — deux mondes, deux durées de vie, deux\n * écrans : les mélanger ferait qu'une clé de CI dépendrait d'un poste allumé.\n */\n\n/**\n * Ce qu'une clé a le droit de faire. Des portées séparées plutôt qu'un booléen\n * lecture/écriture : commenter est le geste d'un robot de CI qui rend compte, et\n * il n'a aucune raison de pouvoir aussi créer ou déplacer des cartes.\n *\n * `kanban:delete` est à part pour la même raison, en plus net : effacer est le\n * seul geste que rien ne rattrape. Une clé d'alimentation qui pourrait aussi\n * supprimer transformerait un bogue de script en perte de travail.\n */\nexport const CloudApiScopeSchema = z.enum([\n 'kanban:read',\n 'kanban:write',\n 'kanban:comment',\n 'kanban:delete',\n]);\nexport type CloudApiScope = z.infer<typeof CloudApiScopeSchema>;\n\nexport const CLOUD_API_SCOPES: CloudApiScope[] = [\n 'kanban:read',\n 'kanban:write',\n 'kanban:comment',\n 'kanban:delete',\n];\n\n/**\n * Le préfixe de tout secret émis. Il ne protège rien — il se lit dans un dépôt\n * ou un journal, et c'est le but : un scanner de secrets sait quoi chercher, et\n * un humain qui voit `rk_` dans un fichier sait ce qu'il tient.\n */\nexport const CLOUD_API_KEY_PREFIX = 'rk_';\n\n/** `rk_` suivi de 64 caractères hexadécimaux — 32 octets d'aléa. */\nexport const CloudApiKeySecretSchema = z.string().regex(/^rk_[0-9a-f]{64}$/);\n\nexport const CloudApiKeySchema = z.object({\n id: z.string().max(128),\n organizationId: z.string().max(128),\n name: z.string().min(1).max(200),\n scopes: z.array(CloudApiScopeSchema).min(1).max(10),\n /**\n * Les tableaux que la clé peut atteindre, ou `null` pour « tous ceux de\n * l'organisation ».\n *\n * `null` et `[]` ne sont pas la même chose : la liste vide n'ouvre rien, et\n * c'est délibéré — un tableau supprimé ne doit pas élargir une clé qui ne le\n * nommait plus que lui.\n */\n boards: z.array(z.string().max(64)).max(200).nullable(),\n createdAt: z.string().max(64),\n /** Dernier usage constaté, pour reconnaître une clé oubliée. */\n lastUsedAt: z.string().max(64).nullable(),\n /** Qui l'a émise — une clé sans visage ne se révoque jamais sereinement. */\n createdBy: z.object({ id: z.string().max(128), name: z.string().max(200) }),\n /** Les 4 derniers caractères du secret, pour reconnaître une clé dans une liste. */\n keyPreview: z.string().max(8),\n});\nexport type CloudApiKey = z.infer<typeof CloudApiKeySchema>;\n\n/**\n * La réponse de création — la seule fois où le secret circule.\n *\n * Le serveur n'en garde qu'un condensat : personne, pas même l'organisation, ne\n * peut le relire ensuite. Perdue, une clé se remplace, elle ne se retrouve pas.\n */\nexport const CreatedCloudApiKeySchema = z.object({\n key: CloudApiKeySchema,\n secret: CloudApiKeySecretSchema,\n});\nexport type CreatedCloudApiKey = z.infer<typeof CreatedCloudApiKeySchema>;\n\nexport const CreateCloudApiKeyInput = z.object({\n organizationId: z.string().min(1).max(128),\n name: z.string().min(1).max(200),\n scopes: z.array(CloudApiScopeSchema).min(1).max(10),\n boards: z.array(z.string().max(64)).max(200).nullable().default(null),\n});\nexport type CreateCloudApiKeyInput = z.infer<typeof CreateCloudApiKeyInput>;\n\nexport const UpdateCloudApiKeyInput = z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200).optional(),\n scopes: z.array(CloudApiScopeSchema).min(1).max(10).optional(),\n boards: z.array(z.string().max(64)).max(200).nullable().optional(),\n});\nexport type UpdateCloudApiKeyInput = z.infer<typeof UpdateCloudApiKeyInput>;\n","import { z } from 'zod';\nimport { KanbanAttachmentSchema } from './kanban.schema.js';\n\n/**\n * Les intégrations de support : un outil de conversation client (Intercom,\n * HubSpot…) qui alimente un kanban du cloud.\n *\n * Le sens est **entrant seulement** : une conversation qui naît devient une\n * carte, ses messages deviennent des commentaires, sa résolution l'archive.\n * Répondre au client se fait toujours dans l'outil d'origine.\n */\n\n/** Les fournisseurs qu'on sait lire. Un de plus = un adaptateur de plus côté cloud. */\nexport const IntegrationProviderSchema = z.enum(['intercom', 'hubspot']);\nexport type IntegrationProvider = z.infer<typeof IntegrationProviderSchema>;\n\n/** Une connexion telle que l'écran de gestion la voit — jamais son secret. */\nexport const IntegrationConnectionSchema = z.object({\n id: z.string().max(128),\n organizationId: z.string().max(128),\n provider: IntegrationProviderSchema,\n name: z.string().min(1).max(200),\n /** Le tableau et la colonne de création — seulement avec la création automatique. */\n boardId: z.string().max(64).nullable(),\n columnId: z.string().max(128).nullable(),\n enabled: z.boolean(),\n /**\n * L'URL complète du webhook à coller chez le fournisseur, construite par le\n * cloud (domaine public des webhooks). Elle contient un jeton imprévisible.\n */\n webhookUrl: z.string().max(2048),\n /** Les quatre derniers caractères du secret de signature, pour le reconnaître. */\n secretPreview: z.string().max(8),\n region: z.string().max(16),\n /** Créer une carte pour toute conversation qui n'est encore liée nulle part. */\n autoCreate: z.boolean(),\n createdBy: z.object({ id: z.string().max(128), name: z.string().max(200) }),\n createdAt: z.string().max(64),\n lastEventAt: z.string().max(64).nullable(),\n});\nexport type IntegrationConnection = z.infer<typeof IntegrationConnectionSchema>;\n\n/** L'état d'une conversation, tel que le fournisseur le dit. */\nexport const IntegrationConversationStateSchema = z.enum(['open', 'resolved']);\n\nexport const IntegrationMessageSchema = z.object({\n id: z.string().max(256),\n author: z.object({ name: z.string().max(500), role: z.enum(['customer', 'agent']) }),\n body: z.string().max(100_000),\n internal: z.boolean(),\n sentAt: z.string().max(64),\n /** Fichiers joints et images, copiés dans Runeya : ils se lisent comme ceux d'une carte. */\n attachments: z.array(KanbanAttachmentSchema).max(50),\n /** Noms des fichiers qui n'ont pas pu être copiés. */\n missingAttachments: z.array(z.string().max(500)).max(50),\n});\nexport type IntegrationMessage = z.infer<typeof IntegrationMessageSchema>;\n\n/** Une conversation telle qu'une carte la montre. */\nexport const IntegrationConversationSchema = z.object({\n id: z.string().max(256),\n connectionId: z.string().max(128),\n provider: IntegrationProviderSchema,\n externalId: z.string().max(128),\n title: z.string().max(500),\n url: z.string().max(2000).nullable(),\n state: IntegrationConversationStateSchema,\n updatedAt: z.string().max(64),\n});\nexport type IntegrationConversation = z.infer<typeof IntegrationConversationSchema>;\n\n/** Une conversation liée à une carte : son fil, et les autres cartes qui la suivent. */\nexport const CardConversationSchema = IntegrationConversationSchema.extend({\n origin: z.enum(['auto', 'manual']),\n /** Les fichiers de la conversation sont en train d'être copiés : ils vont apparaître. */\n filesPending: z.boolean(),\n linkedAt: z.string().max(64),\n opening: z.object({\n author: IntegrationMessageSchema.shape.author,\n body: z.string().max(100_000),\n attachments: z.array(KanbanAttachmentSchema).max(50),\n missingAttachments: z.array(z.string().max(500)).max(50),\n }).nullable(),\n messages: z.array(IntegrationMessageSchema),\n otherCards: z.array(z.object({ boardId: z.string().max(64), cardId: z.string().max(64), title: z.string().max(500) })),\n});\nexport type CardConversation = z.infer<typeof CardConversationSchema>;\n\n/** Un résultat de recherche chez le fournisseur, et les cartes qui la suivent déjà. */\nexport const ConversationSearchHitSchema = IntegrationConversationSchema.extend({\n preview: z.string().max(500),\n linkedCards: z.array(z.object({ boardId: z.string().max(64), cardId: z.string().max(64), title: z.string().max(500) })),\n});\nexport type ConversationSearchHit = z.infer<typeof ConversationSearchHitSchema>;\n","import { z } from 'zod';\n\n/**\n * Le journal des nouveautés, tel qu'il est publié par le cloud.\n *\n * **Deux surfaces, jamais mélangées.** `app` est l'application locale, dont la\n * version est celle du CLI publié sur npm. `cloud` est l'API et son application\n * web, déployées au push et donc sans numéro de version : leurs entrées sont\n * datées. Un même travail qui touche les deux donne DEUX entrées — c'est ce qui\n * permet à un poste resté sur une vieille version de ne pas se voir annoncer des\n * nouveautés qu'il n'a pas, et au cloud d'annoncer les siennes sans attendre une\n * publication npm.\n *\n * L'ordre se déduit de `version` seule (voir `compareChangelogVersions`) : les\n * deux formes — `1.4.2` et `2026-09-03` — se comparent par segments numériques.\n */\n\nexport const ChangelogSurfaceSchema = z.enum(['app', 'cloud']);\nexport type ChangelogSurface = z.infer<typeof ChangelogSurfaceSchema>;\n\n/** Ce que le lecteur doit comprendre en un coup d'œil : est-ce un ajout, un correctif, une rupture. */\nexport const ChangelogChangeKindSchema = z.enum(['feature', 'improvement', 'fix', 'breaking']);\nexport type ChangelogChangeKind = z.infer<typeof ChangelogChangeKindSchema>;\n\n/**\n * Les deux langues de l'interface, toutes deux obligatoires : une entrée\n * publiée dans une seule langue laisserait la moitié des lecteurs devant un\n * trou, et rien dans l'affichage ne pourrait le rattraper.\n */\nexport const ChangelogTextSchema = z.object({\n fr: z.string().min(1).max(500),\n en: z.string().min(1).max(500),\n});\nexport type ChangelogText = z.infer<typeof ChangelogTextSchema>;\n\nexport const ChangelogChangeSchema = z.object({\n kind: ChangelogChangeKindSchema,\n text: ChangelogTextSchema,\n});\nexport type ChangelogChange = z.infer<typeof ChangelogChangeSchema>;\n\n/**\n * Une entrée en attente, telle que l'écrit celui qui fait le travail.\n *\n * Elle ne porte PAS de version : au moment où on l'écrit, le numéro n'existe pas\n * encore — l'app attend sa publication npm, et le cloud n'a jamais de numéro,\n * seulement sa date. Un fichier par entrée, pour que deux branches qui en\n * ajoutent chacune une ne se marchent pas dessus : un tableau partagé produirait\n * un conflit à chaque fusion, et le réflexe sous conflit est d'en perdre une.\n *\n * `title` est facultatif : il nomme la version, pas le changement. La première\n * entrée qui en porte un le donne à sa version ; une version peut n'en avoir\n * aucun, et s'annoncer par son seul numéro.\n */\nexport const ChangelogDraftSchema = ChangelogChangeSchema.extend({\n date: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/),\n title: ChangelogTextSchema.optional(),\n});\nexport type ChangelogDraft = z.infer<typeof ChangelogDraftSchema>;\n\nexport const ChangelogReleaseSchema = z.object({\n surface: ChangelogSurfaceSchema,\n /** `1.4.2` pour l'app (version npm publiée), `2026-09-03` — ou `2026-09-03.2` — pour le cloud. */\n version: z.string().min(1).max(32).regex(/^[0-9][0-9.-]*$/),\n /** Date de publication, `YYYY-MM-DD`. */\n date: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/),\n /** Facultatif : une version peut s'annoncer par son seul numéro. */\n title: ChangelogTextSchema.optional(),\n /** Une version sans changement n'a rien à annoncer : elle n'a pas sa place ici. */\n changes: z.array(ChangelogChangeSchema).min(1).max(50),\n});\nexport type ChangelogRelease = z.infer<typeof ChangelogReleaseSchema>;\n\n/** L'index : de quoi lister et dater, sans transporter les corps. */\nexport const ChangelogIndexItemSchema = ChangelogReleaseSchema.omit({ changes: true }).extend({\n changeCount: z.number().int().nonnegative(),\n});\nexport type ChangelogIndexItem = z.infer<typeof ChangelogIndexItemSchema>;\n\n/**\n * Ordonne deux versions de changelog, quelle que soit leur forme.\n *\n * Les segments sont comparés numériquement (`1.10.0` après `1.9.0`, que la\n * comparaison de chaînes aurait inversé), et une version plus courte perd contre\n * son préfixe plus long (`2026-09-03` avant `2026-09-03.2`).\n */\nexport function compareChangelogVersions(a: string, b: string): number {\n const pa = a.split(/[.-]/).map((n) => Number.parseInt(n, 10) || 0);\n const pb = b.split(/[.-]/).map((n) => Number.parseInt(n, 10) || 0);\n const len = Math.max(pa.length, pb.length);\n for (let i = 0; i < len; i++) {\n const da = pa[i] ?? 0;\n const db = pb[i] ?? 0;\n if (da > db) return 1;\n if (da < db) return -1;\n }\n return 0;\n}\n","import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync } from 'node:crypto';\n\nconst PREFIX = 'aes256gcm:';\nconst IV_LENGTH = 12;\nconst AUTH_TAG_LENGTH = 16;\nconst KEY_LENGTH = 32;\nconst PBKDF2_ITERATIONS = 100_000;\nconst PBKDF2_DIGEST = 'sha256';\n/** Fixed salt for key derivation — the purpose is the salt (lazy to avoid Buffer at module init) */\nlet _KDF_SALT: Buffer | undefined;\nfunction getKdfSalt(): Buffer {\n if (!_KDF_SALT) _KDF_SALT = Buffer.from('runeya-log-sources-key-v1', 'utf8');\n return _KDF_SALT;\n}\n\n/**\n * Derives a 32-byte AES-256 key from `rawKey` using PBKDF2-SHA256.\n * The input key may be any Buffer (e.g. the raw passphrase bytes).\n */\nexport function deriveKey(rawKey: Buffer): Buffer {\n return pbkdf2Sync(rawKey, getKdfSalt(), PBKDF2_ITERATIONS, KEY_LENGTH, PBKDF2_DIGEST);\n}\n\n/**\n * Encrypts `plaintext` using AES-256-GCM.\n * Returns a string in the format: `aes256gcm:<iv_hex>:<authTag_hex>:<ciphertext_hex>`\n */\nexport function encrypt(plaintext: string, key: Buffer): string {\n const iv = randomBytes(IV_LENGTH);\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return `${PREFIX}${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted.toString('hex')}`;\n}\n\n/**\n * Decrypts a ciphertext string produced by `encrypt()`.\n * Throws if the format is invalid or authentication fails.\n */\nexport function decrypt(ciphertext: string, key: Buffer): string {\n if (!isEncrypted(ciphertext)) {\n throw new Error('Value is not in encrypted format');\n }\n const parts = ciphertext.slice(PREFIX.length).split(':');\n if (parts.length !== 3) {\n throw new Error('Invalid encrypted value format');\n }\n const [ivHex, authTagHex, encryptedHex] = parts;\n const iv = Buffer.from(ivHex, 'hex');\n const authTag = Buffer.from(authTagHex, 'hex');\n const encryptedBuffer = Buffer.from(encryptedHex, 'hex');\n\n if (iv.length !== IV_LENGTH) throw new Error('Invalid IV length');\n if (authTag.length !== AUTH_TAG_LENGTH) throw new Error('Invalid authTag length');\n\n const decipher = createDecipheriv('aes-256-gcm', key, iv, { authTagLength: 16 });\n decipher.setAuthTag(authTag);\n return Buffer.concat([decipher.update(encryptedBuffer), decipher.final()]).toString('utf8');\n}\n\n/**\n * Returns true if `value` is in the encrypted format produced by `encrypt()`.\n * Safe to call on plain-text values (returns false).\n */\nexport function isEncrypted(value: string): boolean {\n return value.startsWith(PREFIX);\n}\n","import vm from 'node:vm';\nimport type { JSLogParser as JSLogParserDef } from './schemas/settings.schema.js';\nimport type { LogLine } from './schemas/log.schema.js';\nimport type { LogLevel } from './schemas/log.schema.js';\n\ninterface CompiledParser {\n id: string;\n name: string;\n enabled: boolean;\n fn: (line: LogLine) => LogLine;\n}\n\nconst VALID_LEVELS = new Set<string>(['debug', 'info', 'warn', 'error', 'fatal']);\n\n/** Budget CPU accordé à un parseur pour *une* ligne. */\nconst PARSE_TIMEOUT_MS = 50;\n/** Au-delà, le parseur est considéré hostile et désactivé pour la session. */\nconst MAX_CONSECUTIVE_TIMEOUTS = 10;\n\nexport class JSLogParser {\n private parsers: CompiledParser[] = [];\n\n constructor(definitions: JSLogParserDef[] = []) {\n this.setParsers(definitions);\n }\n\n setParsers(definitions: JSLogParserDef[]): void {\n this.parsers = [];\n\n for (const def of definitions) {\n if (!def.enabled) continue;\n\n try {\n const compiled = this.compileParser(def);\n this.parsers.push({\n id: def.id,\n name: def.name,\n enabled: true,\n fn: compiled,\n });\n } catch (err) {\n console.warn(\n `[js-log-parser] Failed to compile parser \"${def.name}\" (${def.id}): ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n }\n }\n }\n\n parse(line: LogLine): LogLine {\n let current = line;\n\n for (const parser of this.parsers) {\n try {\n current = parser.fn(current);\n } catch (err) {\n console.warn(\n `[js-log-parser] Parser \"${parser.name}\" threw error: ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n }\n }\n\n return this.sanitize(current);\n }\n\n /**\n * Compile le code utilisateur en une fonction bornée en temps.\n *\n * Le `timeout` de `runInNewContext` ne couvre que l'évaluation de la factory :\n * la closure retournée s'exécutait ensuite ligne par ligne directement sur\n * l'event loop, sans aucune borne. Une regex à backtracking exponentiel\n * fournie par l'utilisateur figeait donc l'agent entier — logs, statuts et\n * métriques de *tous* les services. Chaque invocation repasse maintenant par\n * la vm, avec son propre budget.\n */\n private compileParser(def: JSLogParserDef): (line: LogLine) => LogLine {\n const forbidden = ['require(', 'import ', 'eval('];\n for (const pat of forbidden) {\n if (def.code.includes(pat)) {\n throw new Error('Code contains forbidden patterns (require, import, eval)');\n }\n }\n\n const sandbox = {\n RegExp,\n String,\n Object,\n Array,\n JSON,\n Math,\n Date,\n undefined,\n null: null,\n };\n\n let script: vm.Script;\n try {\n script = new vm.Script(`(${def.code})`, { filename: `parser-${def.id}.js` });\n } catch (err) {\n throw new Error(`Compilation failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n // Le contexte est conservé : c'est lui qui permet de ré-entrer dans la vm\n // à chaque ligne, et donc d'armer un timeout par invocation.\n const context = vm.createContext({ ...sandbox, __line: null as unknown, __result: null as unknown });\n\n let parserFn: unknown;\n try {\n parserFn = script.runInContext(context, { timeout: 100 });\n } catch (err) {\n throw new Error(`Execution failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (typeof parserFn !== 'function') {\n throw new Error('Parser code must export a function');\n }\n\n (context as Record<string, unknown>)['__parserFn'] = parserFn;\n const callScript = new vm.Script('__result = __parserFn(__line);', {\n filename: `parser-${def.id}-call.js`,\n });\n\n let consecutiveTimeouts = 0;\n let disabled = false;\n\n return (line: LogLine): LogLine => {\n if (disabled) return line;\n\n const ctx = context as Record<string, unknown>;\n ctx['__line'] = line;\n ctx['__result'] = null;\n try {\n callScript.runInContext(context, { timeout: PARSE_TIMEOUT_MS });\n consecutiveTimeouts = 0;\n } catch (err) {\n // `instanceof Error` est faux ici : l'erreur de timeout ne vient pas du\n // même realm que ce module. On la reconnaît par son code/message.\n const e = err as { code?: unknown; message?: unknown } | null;\n const timedOut = !!e\n && (e.code === 'ERR_SCRIPT_EXECUTION_TIMEOUT'\n || (typeof e.message === 'string' && /execution timed out/i.test(e.message)));\n if (!timedOut) throw err;\n consecutiveTimeouts += 1;\n if (consecutiveTimeouts >= MAX_CONSECUTIVE_TIMEOUTS) {\n disabled = true;\n console.warn(\n `[js-log-parser] Parser \"${def.name}\" (${def.id}) disabled after ${MAX_CONSECUTIVE_TIMEOUTS} consecutive timeouts`,\n );\n }\n return line;\n }\n\n const result = ctx['__result'];\n if (result === null || result === undefined || typeof result !== 'object') {\n return line;\n }\n return result as LogLine;\n };\n }\n\n /** Sanitize the final LogLine: truncate message, limit metadata, validate level */\n private sanitize(line: LogLine): LogLine {\n let { message, metadata, level } = line;\n\n if (message.length > 16384) {\n message = message.substring(0, 16384) + '...[truncated]';\n }\n\n metadata = metadata ?? {};\n const metaKeys = Object.keys(metadata);\n if (metaKeys.length > 100) {\n const limited: Record<string, unknown> = {};\n for (let i = 0; i < 100; i++) {\n limited[metaKeys[i]] = metadata[metaKeys[i]];\n }\n metadata = limited;\n }\n\n if (!VALID_LEVELS.has(level)) {\n level = 'info' as LogLevel;\n }\n\n if (message !== line.message || metadata !== line.metadata || level !== line.level) {\n return { ...line, message, metadata, level };\n }\n return line;\n }\n}\n","/**\n * Variables intégrées — les `{{…}}` que Runeya remplit lui-même, par opposition\n * aux `{{environment.KEY}}` que l'utilisateur définit et que le résolveur\n * d'environnement traite (`apps/server/src/services/environment-resolver.ts`).\n *\n * Cette table est la SEULE déclaration : le serveur et l'agent y lisent ce\n * qu'ils doivent produire, l'interface ce qu'elle doit proposer et documenter.\n * Elle a été introduite parce que la liste vivait en trois exemplaires — dans\n * le routeur de service, dans le gestionnaire de processus et dans le tableau\n * de variables du web — et que le web en avait déjà oublié un.\n *\n * ## Portées\n *\n * - `server` : connu à la résolution, quand le serveur prépare la config à\n * déployer (nom, ports, projet, environnement actif).\n * - `agent` : ne peut être résolu QUE sur la machine qui exécute le service —\n * son IP, son utilisateur, son système, son répertoire de travail. Les\n * résoudre côté serveur graverait la machine qui a fait le déploiement, ce\n * qui ne se voit qu'en multi-machines, et tard.\n */\n\nexport type BuiltinScope = 'server' | 'agent';\n\nexport interface BuiltinVariable {\n /** Nom tel qu'il s'écrit entre accolades, sans les accolades */\n name: string;\n scope: BuiltinScope;\n /** Suffixe de la clé i18n de l'interface : `builtins.<descriptionKey>` */\n descriptionKey: string;\n /** Nom conservé pour ne pas casser les configurations existantes */\n deprecatedAlias?: string;\n}\n\nexport const BUILTIN_VARIABLES: readonly BuiltinVariable[] = [\n // ── Le service ───────────────────────────────────────────────────────────\n { name: 'service.NAME', scope: 'server', descriptionKey: 'serviceName' },\n { name: 'service.ID', scope: 'server', descriptionKey: 'serviceId' },\n { name: 'service.PORT', scope: 'server', descriptionKey: 'servicePort' },\n { name: 'service.URL', scope: 'server', descriptionKey: 'serviceUrl' },\n { name: 'service.BASE_URL', scope: 'server', descriptionKey: 'serviceBaseUrl' },\n { name: 'service.CWD', scope: 'agent', descriptionKey: 'serviceCwd' },\n\n // ── Le projet et l'environnement actif ───────────────────────────────────\n { name: 'project.NAME', scope: 'server', descriptionKey: 'projectName' },\n { name: 'runeya.ENV_NAME', scope: 'server', descriptionKey: 'envName' },\n\n // ── Le serveur Runeya ────────────────────────────────────────────────────\n // `service.HOST` a toujours désigné l'adresse d'écoute du SERVEUR, pas une\n // propriété du service : le nom trompait, il devient un alias.\n { name: 'runeya.HOST', scope: 'server', descriptionKey: 'runeyaHost', deprecatedAlias: 'service.HOST' },\n\n // ── La machine qui exécute ───────────────────────────────────────────────\n { name: 'agent.HOST_LAN', scope: 'agent', descriptionKey: 'agentHostLan', deprecatedAlias: 'service.HOST_LAN' },\n // Le NOM de l'agent est une étiquette de la configuration du serveur, pas\n // une propriété de la machine : c'est le serveur qui le connaît et le résout.\n { name: 'agent.NAME', scope: 'server', descriptionKey: 'agentName' },\n { name: 'agent.OS', scope: 'agent', descriptionKey: 'agentOs' },\n { name: 'agent.HOME', scope: 'agent', descriptionKey: 'agentHome' },\n];\n\nexport const BUILTINS_BY_SCOPE = (scope: BuiltinScope): readonly BuiltinVariable[] =>\n BUILTIN_VARIABLES.filter((b) => b.scope === scope);\n\n/**\n * Une référence `{{nom}}`. Le nom accepte les points (`service.PORT`,\n * `services.api.URL`) mais ni espace ni accolade : une référence ne peut donc\n * pas se former à la couture entre deux morceaux de texte.\n */\nconst BUILTIN_REFERENCE_RE = /\\{\\{([A-Za-z][A-Za-z0-9_.-]*)\\}\\}/g;\n\n/** Les `{{environment.KEY}}` appartiennent au résolveur, jamais aux builtins. */\nconst ENVIRONMENT_NAMESPACE = 'environment.';\n\n/** Le préfixe sous lequel un service en nomme un autre : `services.<slug>.PORT`. */\nconst CROSS_SERVICE_NAMESPACE = 'services.';\n\n/**\n * Remplace les références présentes dans `values`, et laisse les autres\n * intactes : une passe unique, jamais récursive — une valeur qui contient\n * elle-même une référence ne relance pas la substitution, faute de quoi deux\n * variables se pointant l'une l'autre boucleraient.\n */\nexport function interpolateBuiltins(text: string, values: Record<string, string>): string {\n return text.replace(BUILTIN_REFERENCE_RE, (match, name: string) => {\n if (name.startsWith(ENVIRONMENT_NAMESPACE)) return match;\n return values[name] ?? match;\n });\n}\n\n/**\n * Les slugs de services qu'un texte nomme, via `{{services.<slug>.PROP}}`.\n *\n * C'est l'arête d'un graphe de dépendances : si une variable de A cite\n * `services.b.PORT`, c'est que A a besoin de B pour tourner. La détection\n * s'appuie sur la MÊME expression que `interpolateBuiltins`, pour ne jamais\n * annoncer un lien que l'interpolation ne ferait pas — `{{services. b.URL}}`\n * n'est pas une référence, et ne doit donc pas devenir une arête.\n *\n * Une référence sans propriété (`{{services.b}}`) ne résout rien : elle ne\n * compte pas non plus.\n */\nexport function crossServiceSlugsIn(text: string): string[] {\n const slugs = new Set<string>();\n for (const match of text.matchAll(BUILTIN_REFERENCE_RE)) {\n const name = match[1];\n if (!name || !name.startsWith(CROSS_SERVICE_NAMESPACE)) continue;\n const rest = name.slice(CROSS_SERVICE_NAMESPACE.length);\n const dot = rest.indexOf('.');\n if (dot <= 0 || dot === rest.length - 1) continue;\n slugs.add(rest.slice(0, dot));\n }\n return [...slugs];\n}\n\n/** `interpolateBuiltins` appliqué à chaque valeur d'un dictionnaire d'env. */\nexport function interpolateBuiltinsInEnv(\n env: Record<string, string>,\n values: Record<string, string>,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n out[key] = interpolateBuiltins(value, values);\n }\n return out;\n}\n\n/**\n * Ajoute au dictionnaire les alias hérités, pour que `{{service.HOST}}`\n * continue de rendre ce que rend `{{runeya.HOST}}`.\n */\nexport function withDeprecatedAliases(values: Record<string, string>): Record<string, string> {\n const out = { ...values };\n for (const builtin of BUILTIN_VARIABLES) {\n if (builtin.deprecatedAlias && out[builtin.name] !== undefined) {\n out[builtin.deprecatedAlias] = out[builtin.name];\n }\n }\n return out;\n}\n\n/**\n * Nom sous lequel un service est adressable depuis un autre\n * (`{{services.<slug>.PORT}}`).\n *\n * Un nom de service est libre — accents, espaces, majuscules — alors qu'une\n * référence doit rester un mot sans espace. D'où ce passage en minuscules\n * tiretées, appliqué de la même façon par le serveur qui produit les valeurs\n * et par l'interface qui les propose.\n */\nexport function serviceSlug(name: string): string {\n return name\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\n/**\n * Les slugs que deux services d'un même projet se disputent.\n *\n * Un tel slug n'est adressable pour AUCUN des deux : rendre l'un plutôt que\n * l'autre dépendrait de l'ordre de chargement. La règle est ici, et non chez\n * ses deux appelants — celui qui produit les valeurs à interpoler et celui qui\n * dessine le graphe des liens — parce qu'ils doivent dire la même chose : un\n * lien montré à l'écran mais non interpolé au démarrage serait pire que pas de\n * lien du tout.\n */\nexport function ambiguousServiceSlugs(names: readonly string[]): Set<string> {\n const counts = new Map<string, number>();\n for (const name of names) {\n const slug = serviceSlug(name);\n if (slug) counts.set(slug, (counts.get(slug) ?? 0) + 1);\n }\n return new Set([...counts].filter(([, count]) => count > 1).map(([slug]) => slug));\n}\n\n/**\n * Les ports d'un service : `service.PORT` pour le premier — celui qu'on cite\n * dans neuf cas sur dix — puis `service.PORT_2`, `_3`… pour les suivants.\n */\nexport function servicePortValues(ports: readonly number[] | undefined, prefix = 'service'): Record<string, string> {\n const values: Record<string, string> = {};\n (ports ?? []).forEach((port, i) => {\n values[i === 0 ? `${prefix}.PORT` : `${prefix}.PORT_${i + 1}`] = String(port);\n });\n return values;\n}\n\n/**\n * Une adresse d'écoute « toutes interfaces » n'est pas une adresse à laquelle\n * on se connecte. En mode LAN, le serveur écoute sur `0.0.0.0` : bâtir\n * `http://0.0.0.0:3000` donnerait une URL que rien ne peut joindre.\n */\nexport function isWildcardHost(host: string): boolean {\n const h = host.trim();\n return h === '' || h === '0.0.0.0' || h === '::' || h === '[::]';\n}\n\n/** L'adresse de bouclage, sous ses écritures possibles. */\nfunction isLoopbackHost(host: string): boolean {\n const h = host.trim();\n return h === '127.0.0.1' || h === '::1' || h === '[::1]';\n}\n\n/**\n * L'hôte à écrire dans une URL, à partir de l'adresse d'écoute du serveur.\n *\n * La boucle locale devient `localhost` : c'est le nom que les développeurs\n * écrivent, celui des origines autorisées du dépôt, et celui qu'on colle dans\n * un navigateur. `{{runeya.HOST}}` continue de rendre l'adresse réelle — c'est\n * elle qu'un service met dans son bind, et la traduire là serait faux.\n *\n * Un hôte explicitement configuré (une IP de LAN, un nom de machine) n'est\n * jamais réécrit : le seul cas traduit est celui où l'adresse ne désigne que\n * « cette machine ». Une adresse « toutes interfaces » rend `null` — à\n * l'appelant de décider, l'agent connaissant seul son IP joignable.\n */\nexport function urlHostFor(host: string): string | null {\n if (isWildcardHost(host)) return null;\n return isLoopbackHost(host) ? 'localhost' : host.trim();\n}\n\n/**\n * Les URL par lesquelles on joint un service, une par port : `service.URL`,\n * `service.URL_2`… numérotées comme les ports, si bien que `URL_2` désigne\n * toujours le service sur `PORT_2`.\n *\n * Un domaine local est déclaré AVEC son port (c'est ce que le proxy route) :\n * l'URL d'un port est donc son domaine s'il en a un, sinon l'hôte et le port.\n * Un domaine déclaré sur un port absent de la liste des ports est ajouté à la\n * suite, pour ne pas se perdre.\n *\n * À ne pas confondre avec le champ `url` du service — son « URL de base »,\n * saisie librement, souvent l'adresse publique : celle-là s'écrit\n * `{{service.BASE_URL}}`. Faire rendre l'une par l'autre romprait la\n * correspondance entre `URL_n` et `PORT_n`.\n */\nexport function serviceUrlValues(service: {\n ports?: number[];\n localUrls?: { url: string; port: number }[];\n}, host: string, prefix = 'service'): Record<string, string> {\n const domainByPort = new Map((service.localUrls ?? []).map((lu) => [lu.port, lu.url]));\n const ports = [...(service.ports ?? [])];\n for (const local of service.localUrls ?? []) {\n if (!ports.includes(local.port)) ports.push(local.port);\n }\n\n const values: Record<string, string> = {};\n ports.forEach((port, i) => {\n const domain = domainByPort.get(port);\n values[i === 0 ? `${prefix}.URL` : `${prefix}.URL_${i + 1}`] =\n domain ? `http://${domain}` : `http://${host}:${port}`;\n });\n return values;\n}\n\n/** Les clés `services.<slug>.*` exposées pour un service voisin. */\nexport function crossServiceValues(service: {\n name: string;\n id: string;\n ports?: number[];\n localUrls?: { url: string; port: number }[];\n url?: string;\n}, host: string): Record<string, string> {\n const slug = serviceSlug(service.name);\n if (!slug) return {};\n return {\n [`services.${slug}.NAME`]: service.name,\n [`services.${slug}.ID`]: service.id,\n ...servicePortValues(service.ports, `services.${slug}`),\n ...serviceUrlValues(service, host, `services.${slug}`),\n ...(service.url ? { [`services.${slug}.BASE_URL`]: service.url } : {}),\n };\n}\n\n/** Une référence qu'aucune étape ne remplira : elle arrivera telle quelle dans le process. */\nexport interface UnresolvedReference {\n key: string;\n reference: string;\n}\n\n/** Les ports et URL numérotés que le serveur produit en plus des noms déclarés : `service.PORT_2`. */\nconst NUMBERED_SERVICE_BUILTIN_RE = /^service\\.(PORT|URL)_\\d+$/;\n\nfunction builtinScopeOf(name: string): BuiltinScope | null {\n const builtin = BUILTIN_VARIABLES.find((b) => b.name === name || b.deprecatedAlias === name);\n if (builtin) return builtin.scope;\n if (NUMBERED_SERVICE_BUILTIN_RE.test(name) || name.startsWith(CROSS_SERVICE_NAMESPACE)) return 'server';\n return null;\n}\n\n/**\n * Les références restées en place dans un env résolu, et qui le resteront.\n *\n * Le résolveur d'environnement, puis le serveur, puis l'agent remplissent\n * chacun les leurs et laissent intactes les autres — si bien qu'une faute de\n * frappe (`{{environment.DB_HSOT}}`) arrive au process comme du texte, sans\n * que rien ne le signale. Ce qui est signalé dépend de l'étape atteinte :\n *\n * - une référence d'environnement : toujours, le résolveur est déjà passé ;\n * - une variable intégrée du serveur : si `serverResolved` — sinon elle attend\n * le déploiement ; mais un nom qui n'en est pas une est une faute dans les\n * deux cas ;\n * - une variable intégrée de l'agent : jamais, elle se remplit au démarrage.\n *\n * `skipKeys` tait des clés — celles dont la valeur est masquée : la forme d'un\n * secret, références comprises, n'a pas à sortir.\n */\nexport function findUnresolvedReferences(\n env: Record<string, string>,\n opts: { serverResolved: boolean; skipKeys?: Iterable<string> },\n): UnresolvedReference[] {\n const skip = new Set(opts.skipKeys ?? []);\n const out: UnresolvedReference[] = [];\n for (const [key, value] of Object.entries(env)) {\n if (skip.has(key)) continue;\n for (const match of value.matchAll(BUILTIN_REFERENCE_RE)) {\n const reference = match[1]!;\n if (!reference.startsWith(ENVIRONMENT_NAMESPACE)) {\n const scope = builtinScopeOf(reference);\n if (scope === 'agent') continue;\n if (scope === 'server' && !opts.serverResolved) continue;\n }\n out.push({ key, reference });\n }\n }\n return out;\n}\n\n/** Une valeur recopiée, et la référence qui la suivrait. */\nexport interface BuiltinSuggestion {\n literal: string;\n reference: string;\n}\n\n/** Les variables intégrées qui valent la peine d'être reconnues : ports et adresses, du service ou d'un voisin. */\nconst SUGGESTABLE_BUILTIN_RE = /^(service|services\\.[^.]+)\\.(PORT|URL|BASE_URL)(_\\d+)?$/;\n\n/**\n * Les ports et URL de services recopiés dans une valeur, avec la référence qui\n * les remplacerait.\n *\n * Recopier `http://localhost:3211` fige l'adresse du front telle qu'elle est sur\n * ce poste, aujourd'hui : elle ne suit ni un changement de port ni un domaine\n * local. `{{services.front.URL}}`, si. `builtins` est ce que le serveur calcule\n * pour le service concerné (`buildServerBuiltins`).\n *\n * La plus longue valeur l'emporte (une URL avant le port qu'elle contient), et\n * à longueur égale la référence du service lui-même avant celle qui le nomme de\n * l'extérieur. Un nombre n'est reconnu qu'entier, et rien n'est lu à\n * l'intérieur d'une référence déjà écrite. Ce ne sont que des suggestions : la\n * valeur n'est jamais réécrite.\n */\nexport function suggestBuiltinReferences(text: string, builtins: Record<string, string>): BuiltinSuggestion[] {\n const candidates = Object.entries(builtins)\n .filter(([name, value]) => SUGGESTABLE_BUILTIN_RE.test(name) && value.length > 1 && !value.includes('{{'))\n .sort(([nameA, a], [nameB, b]) => b.length - a.length || Number(nameA.startsWith('services.')) - Number(nameB.startsWith('services.')));\n\n const claimed: [number, number][] = [...text.matchAll(BUILTIN_REFERENCE_RE)].map((m) => [m.index, m.index + m[0].length]);\n const overlaps = (start: number, end: number) => claimed.some(([s, e]) => start < e && end > s);\n const isDigit = (c: string | undefined) => c !== undefined && c >= '0' && c <= '9';\n\n const suggestions: BuiltinSuggestion[] = [];\n for (const [name, literal] of candidates) {\n let from = 0;\n for (let at = text.indexOf(literal, from); at !== -1; at = text.indexOf(literal, from)) {\n const end = at + literal.length;\n from = at + 1;\n if (overlaps(at, end)) continue;\n if (isDigit(literal[0]) && isDigit(text[at - 1])) continue;\n if (isDigit(literal[literal.length - 1]) && isDigit(text[end])) continue;\n claimed.push([at, end]);\n if (!suggestions.some((s) => s.literal === literal)) suggestions.push({ literal, reference: `{{${name}}}` });\n }\n }\n return suggestions;\n}\n","/** Health check default interval (ms) */\nexport const HEALTH_CHECK_INTERVAL = 30_000;\n\n/** Metrics collection interval (ms) */\nexport const METRICS_INTERVAL = 5_000;\n\n/** Agent health polling interval (ms) */\nexport const AGENT_HEALTH_POLL_INTERVAL = 15_000;\n\n/** UI search/filter debounce (ms) */\nexport const SEARCH_DEBOUNCE = 300;\n\n/** Health check initial delay before first check (ms) */\nexport const HEALTH_CHECK_INITIAL_DELAY = 5_000;\n\n/** Agent health WS interval (ms) */\nexport const HEALTH_WS_INTERVAL = 10_000;\n","/** Default log ring buffer size */\nexport const LOG_BUFFER_SIZE = 5_000;\n\n/** Max log entries displayed in UI */\nexport const LOG_DISPLAY_LIMIT = 500;\n","/** Default process grace period before SIGKILL (ms) */\nexport const GRACE_PERIOD = 10_000;\n\n/** HTTP fetch timeout for agent calls (ms) */\nexport const AGENT_FETCH_TIMEOUT = 10_000;\n\n/** HTTP fetch timeout for long-running agent calls like shortcuts/ad-hoc commands (ms) — 10 minutes */\nexport const AGENT_LONG_FETCH_TIMEOUT = 600_000;\n\n/** HTTP fetch timeout for process stop calls (ms) — grace period + generous buffer */\nexport const AGENT_STOP_FETCH_TIMEOUT = GRACE_PERIOD + 15_000;\n\n/** Passphrase extraction timeout during agent spawn (ms) */\nexport const PASSPHRASE_TIMEOUT = 30_000;\n\n/** Min WS reconnect delay (ms) */\nexport const WS_RECONNECT_MIN = 1_000;\n\n/** Max WS reconnect delay (ms) */\nexport const WS_RECONNECT_MAX = 15_000;\n\n/** Max WS reconnect attempts */\nexport const WS_RECONNECT_MAX_ATTEMPTS = 5;\n\n/** Base retry delay for subscriptions (ms) */\nexport const SUBSCRIPTION_RETRY_BASE = 1_000;\n","export interface EditorDefinition {\n key: string;\n name: string;\n command: string;\n}\n\nexport const SUPPORTED_EDITORS: EditorDefinition[] = [\n { key: 'vscode', name: 'Visual Studio Code', command: 'code' },\n { key: 'cursor', name: 'Cursor', command: 'cursor' },\n { key: 'windsurf', name: 'Windsurf', command: 'windsurf' },\n { key: 'sublime', name: 'Sublime Text', command: 'subl' },\n { key: 'atom', name: 'Atom', command: 'atom' },\n { key: 'antigravity', name: 'Antigravity', command: 'antigravity' },\n { key: 'intellij', name: 'IntelliJ IDEA', command: 'idea' },\n { key: 'android-studio', name: 'Android Studio', command: 'studio' },\n { key: 'webstorm', name: 'WebStorm', command: 'webstorm' },\n { key: 'zed', name: 'Zed', command: 'zed' },\n { key: 'neovim', name: 'Neovim', command: 'nvim' },\n { key: 'vim', name: 'Vim', command: 'vim' },\n { key: 'emacs', name: 'Emacs', command: 'emacs' },\n { key: 'fleet', name: 'Fleet', command: 'fleet' },\n];\n\nexport const EDITOR_BY_KEY = new Map<string, EditorDefinition>(\n SUPPORTED_EDITORS.map((e) => [e.key, e]),\n);\n","import * as Y from 'yjs';\n\n/**\n * Generic JSON ↔ Yjs mapping.\n *\n * The cloud must share exactly what git shares: the contents of the `.runeya`\n * files, whatever fields they happen to carry today. Enumerating those fields\n * would make this a hand-maintained allowlist — adding a field to a schema and\n * forgetting it here would not break anything, it would just silently stop\n * syncing. So nothing here names a field: any JSON shape round-trips.\n *\n * The mapping is structural rather than blob-per-file, because a blob makes\n * every concurrent edit last-writer-wins across a whole file. Mapping objects to\n * `Y.Map` and arrays to `Y.Array` lets Yjs merge edits to different fields — and\n * different array elements — the way it is meant to.\n *\n * Every write is a *diff*: identical input must produce no Yjs update at all.\n * Anything less loops forever (local → doc → local → doc).\n */\n\nexport type Json = null | boolean | number | string | Json[] | { [k: string]: Json };\n\n/**\n * Strip `undefined` and other non-JSON values by round-tripping.\n *\n * Zod leaves optional fields absent while JS code tends to set them to\n * `undefined`; `Y.Map.set(k, undefined)` is not `delete(k)`, so without this the\n * diff would see a change on every pass and never settle.\n */\nexport function normalize(value: unknown): Json {\n return JSON.parse(JSON.stringify(value ?? null)) as Json;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, Json> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/** Yjs value → plain JSON. */\nexport function toPlain(value: unknown): Json {\n if (value instanceof Y.Map) {\n const out: Record<string, Json> = {};\n for (const [k, v] of value.entries()) out[k] = toPlain(v);\n return out;\n }\n if (value instanceof Y.Array) return value.toArray().map(toPlain);\n return (value ?? null) as Json;\n}\n\n/**\n * Identity of an array element, used to align two versions of an array.\n *\n * An element with an `id` keeps that identity across edits, so a concurrent\n * change to one element and an insertion of another merge cleanly. Anything\n * else (scalars, objects with no id) is identified by its whole value: editing\n * it reads as delete + insert, i.e. last-writer-wins for that element.\n */\nfunction identityOf(value: Json): string {\n if (isPlainObject(value) && typeof value['id'] === 'string') return `id:${value['id']}`;\n return `v:${JSON.stringify(value)}`;\n}\n\nfunction identityOfY(value: unknown): string {\n if (value instanceof Y.Map) {\n const id = value.get('id');\n if (typeof id === 'string') return `id:${id}`;\n }\n return `v:${JSON.stringify(toPlain(value))}`;\n}\n\n/** Convert a JSON value into the Yjs type that represents it. */\nfunction toY(value: Json): unknown {\n if (Array.isArray(value)) {\n const arr = new Y.Array<unknown>();\n if (value.length > 0) arr.insert(0, value.map(toY));\n return arr;\n }\n if (isPlainObject(value)) {\n const map = new Y.Map<unknown>();\n for (const [k, v] of Object.entries(value)) map.set(k, toY(v));\n return map;\n }\n return value;\n}\n\n/**\n * Diff `next` into a `Y.Map`, recursing into nested objects and arrays and\n * deleting keys that `next` no longer has.\n */\nexport function applyToMap(map: Y.Map<unknown>, next: Record<string, Json>): void {\n for (const key of Array.from(map.keys())) {\n if (!(key in next)) map.delete(key);\n }\n for (const [key, value] of Object.entries(next)) {\n const current = map.get(key);\n if (Array.isArray(value)) {\n if (!(current instanceof Y.Array)) map.set(key, toY(value));\n else applyToArray(current, value);\n } else if (isPlainObject(value)) {\n if (!(current instanceof Y.Map)) map.set(key, toY(value));\n else applyToMap(current, value);\n } else if (current instanceof Y.Map || current instanceof Y.Array || current !== value) {\n map.set(key, value);\n }\n }\n}\n\n/**\n * Diff `next` into a `Y.Array` by aligning elements on their identity.\n *\n * Targeted inserts/deletes are what let Yjs keep both sides of a concurrent\n * append; rewriting the array wholesale (delete-all + insert) would drop one of\n * them, which is exactly the data loss this mapping exists to avoid.\n */\nexport function applyToArray(arr: Y.Array<unknown>, next: Json[]): void {\n const wanted = next.map(identityOf);\n const wantedCount = new Map<string, number>();\n for (const k of wanted) wantedCount.set(k, (wantedCount.get(k) ?? 0) + 1);\n\n // Drop elements `next` no longer contains (respecting duplicate counts).\n const seen = new Map<string, number>();\n for (let i = arr.length - 1; i >= 0; i--) {\n const key = identityOfY(arr.get(i));\n const used = seen.get(key) ?? 0;\n if (used >= (wantedCount.get(key) ?? 0)) arr.delete(i, 1);\n else seen.set(key, used + 1);\n }\n\n // Walk both sides in order: recurse into matches, insert what is missing.\n for (let j = 0; j < next.length; j++) {\n const key = wanted[j]!;\n if (j < arr.length && identityOfY(arr.get(j)) === key) {\n const current = arr.get(j);\n const value = next[j]!;\n if (current instanceof Y.Map && isPlainObject(value)) applyToMap(current, value);\n else if (current instanceof Y.Array && Array.isArray(value)) applyToArray(current, value);\n continue;\n }\n // Pull a later match into place rather than re-creating it, so a reorder\n // does not read as a delete + insert of unrelated content.\n let found = -1;\n for (let k = j + 1; k < arr.length; k++) {\n if (identityOfY(arr.get(k)) === key) {\n found = k;\n break;\n }\n }\n if (found !== -1) {\n const moved = toPlain(arr.get(found));\n arr.delete(found, 1);\n arr.insert(j, [toY(moved)]);\n } else {\n arr.insert(j, [toY(next[j]!)]);\n }\n }\n}\n\n/** A collection of entities keyed by id: `doc.getMap(name)` → `{ [id]: Y.Map }`. */\nexport function getCollection(doc: Y.Doc, name: string): Y.Map<unknown> {\n return doc.getMap(name);\n}\n\n/** Read one entity as plain JSON, or null when absent/malformed. */\nexport function readEntity(collection: Y.Map<unknown>, id: string): Record<string, Json> | null {\n const entity = collection.get(id);\n if (!(entity instanceof Y.Map)) return null;\n const plain = toPlain(entity);\n return isPlainObject(plain) ? plain : null;\n}\n\n/**\n * Write one entity, mutating only what differs. Must run inside\n * `doc.transact(..., origin)` so the bridge can tell local writes from remote.\n */\nexport function writeEntity(collection: Y.Map<unknown>, id: string, entity: unknown): void {\n const next = normalize(entity);\n if (!isPlainObject(next)) return;\n const current = collection.get(id);\n if (!(current instanceof Y.Map)) {\n collection.set(id, toY(next));\n return;\n }\n applyToMap(current, next);\n}\n","/// <reference path=\"./shellwords.d.ts\" />\nimport { execa } from 'execa';\nimport { execSync } from 'node:child_process';\nimport { homedir } from 'node:os';\nimport * as shellwordsModule from 'shellwords';\nimport type { Runner, RunnerProcess, RunnerStartConfig } from './types.js';\n\nconst shellwordsSplit = (shellwordsModule as { split: (str: string) => string[] }).split;\n\n/** Expand $VAR and ${VAR} references using the provided env dict.\n * Also expands leading ~ to the home directory.\n * Callers must pass a fully-merged env (passthrough + serviceEnv). */\nfunction expandEnvVars(str: string, serviceEnv?: Record<string, string>): string {\n const withHome = str.replace(/^~(\\/|$)/, `${homedir()}$1`);\n return withHome.replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (_, braced, plain) => {\n const name = braced ?? plain;\n return serviceEnv?.[name] ?? '';\n });\n}\n\n/** Resolve a cwd field: expand env vars, fallback to '.' if empty/undefined. */\nexport function resolveCwd(cwd: string | undefined, env?: Record<string, string>): string {\n if (!cwd) return '.';\n return expandEnvVars(cwd, env) || '.';\n}\n\n/** Find $VAR and ${VAR} references that are not defined in the provided env dict.\n * Callers must pass a fully-merged env (passthrough + serviceEnv). */\nexport function findUnresolvedEnvVars(str: string, serviceEnv?: Record<string, string>): string[] {\n const unresolved: string[] = [];\n str.replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (_, braced, plain) => {\n const name = braced ?? plain;\n if (serviceEnv?.[name] === undefined) {\n unresolved.push(name);\n }\n return '';\n });\n return unresolved;\n}\n\n/**\n * Build a safe environment for child processes.\n * SECURITY: Never spread ...process.env — it leaks secrets (passphrases, API keys, etc.).\n * Only pass system-essential variables plus the service's explicit env config.\n */\n/** Standard system binary directories to ensure basic commands (cat, sleep, etc.) are always found. */\nconst SYSTEM_PATH_DIRS = ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin', '/usr/bin', '/sbin', '/bin'];\n\nfunction buildSafeEnv(configEnv: Record<string, string> = {}): Record<string, string> {\n const safeKeys = ['PATH', 'HOME', 'USER', 'SHELL', 'LANG', 'TERM', 'NODE_ENV', 'TMPDIR', 'TZ', 'DBUS_SESSION_BUS_ADDRESS', 'XDG_RUNTIME_DIR'];\n const env: Record<string, string> = {};\n for (const key of safeKeys) {\n if (process.env[key]) {\n env[key] = process.env[key]!;\n }\n }\n // Augment PATH with standard system dirs to ensure basic commands are always available,\n // even when Runeya is started with a minimal PATH (e.g. via systemd or a launcher).\n const existingPath = env['PATH'] ?? '';\n const existingDirs = new Set(existingPath.split(':').filter(Boolean));\n const missingDirs = SYSTEM_PATH_DIRS.filter(d => !existingDirs.has(d));\n if (missingDirs.length > 0) {\n env['PATH'] = [existingPath, ...missingDirs].filter(Boolean).join(':');\n }\n return { ...env, ...configEnv };\n}\n\nexport class NativeRunner implements Runner {\n readonly type = 'native' as const;\n\n start(config: RunnerStartConfig): RunnerProcess {\n let subprocess;\n\n const cwd = resolveCwd(config.cwd, config.env);\n\n const isWindows = process.platform === 'win32';\n\n if (config.shell) {\n // Shell mode: execute entire command as shell script\n subprocess = execa(config.command, {\n cwd,\n env: buildSafeEnv(config.env),\n shell: true,\n detached: !isWindows, // Create new process group for group kill (not supported on Windows)\n windowsHide: true, // Prevent terminal windows from appearing on Windows\n stdio: ['ignore', 'pipe', 'pipe'],\n reject: false, // Don't throw on non-zero exit\n buffer: false, // Don't accumulate stdout/stderr in memory — we stream via readline\n });\n } else {\n // Normal mode: parse command with shellwords, execute with shell:false\n // This safely handles quoted arguments and escape sequences\n const args = shellwordsSplit(config.command);\n const cmd = args.shift();\n if (!cmd) {\n throw new Error('Invalid command: cannot parse empty or whitespace-only command');\n }\n\n subprocess = execa(cmd, args, {\n cwd,\n env: buildSafeEnv(config.env),\n shell: false, // SECURITY: shell:false prevents command injection\n detached: !isWindows, // Create new process group for group kill (not supported on Windows)\n windowsHide: true, // Prevent terminal windows from appearing on Windows\n stdio: ['ignore', 'pipe', 'pipe'],\n reject: false, // Don't throw on non-zero exit\n buffer: false, // Don't accumulate stdout/stderr in memory — we stream via readline\n });\n }\n\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>((resolve) => {\n subprocess.then((result) => {\n resolve({\n exitCode: result.exitCode ?? null,\n signal: (result.signal as NodeJS.Signals) ?? null,\n error: result.failed && result.shortMessage ? result.shortMessage : undefined,\n });\n }).catch((err) => {\n resolve({ exitCode: 1, signal: null, error: err.message ?? 'Unknown error' });\n });\n });\n\n return {\n pid: subprocess.pid,\n kill(signal: NodeJS.Signals = 'SIGTERM'): boolean {\n try {\n if (process.platform === 'win32') {\n if (!subprocess.pid) return false;\n // taskkill /F /T kills the entire process tree (including children keeping pipes open)\n execSync(`taskkill /F /T /PID ${subprocess.pid}`, { stdio: 'ignore' });\n return true;\n }\n // Unix: kill the entire process group\n if (subprocess.pid) {\n process.kill(-subprocess.pid, signal);\n return true;\n }\n return subprocess.kill(signal);\n } catch {\n return false;\n }\n },\n stdout: subprocess.stdout,\n stderr: subprocess.stderr,\n exitPromise,\n };\n }\n\n async isAvailable(): Promise<boolean> {\n return true; // Native runner is always available\n }\n}\n","const scan = (\n string: string,\n pattern: RegExp,\n callback: (match: RegExpMatchArray) => void,\n) => {\n let result = \"\";\n\n while (string.length > 0) {\n const match = string.match(pattern);\n\n if (match && match.index != null && match[0] != null) {\n result += string.slice(0, match.index);\n result += callback(match);\n string = string.slice(match.index + match[0].length);\n } else {\n result += string;\n string = \"\";\n }\n }\n\n return result;\n};\n\n/**\n * Splits a string into an array of tokens in the same way the UNIX Bourne shell does.\n *\n * @param line A string to split.\n * @returns An array of the split tokens.\n */\nexport const split = (line = \"\") => {\n const words = [];\n let field = \"\";\n scan(\n line,\n /\\s*(?:([^\\s\\\\'\"]+)|'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\"|(\\\\.?)|(\\S))(\\s|$)?/,\n (match) => {\n const [_raw, word, sq, dq, escape, garbage, separator] = match;\n\n if (garbage != null) {\n throw new Error(`Unmatched quote: ${line}`);\n }\n\n if (word) {\n field += word;\n } else {\n let addition;\n\n if (sq) {\n addition = sq;\n } else if (dq) {\n addition = dq;\n } else if (escape) {\n addition = escape;\n }\n\n if (addition) {\n field += addition.replace(/\\\\(?=.)/, \"\");\n }\n }\n\n if (separator != null) {\n words.push(field);\n field = \"\";\n }\n },\n );\n\n if (field) {\n words.push(field);\n }\n\n return words;\n};\n\n/**\n * Escapes a string so that it can be safely used in a Bourne shell command line.\n *\n * @param str A string to escape.\n * @returns The escaped string.\n */\nexport const escape = (str = \"\") => {\n return str\n .replace(/([^A-Za-z0-9_\\-.,:/@\\n])/g, \"\\\\$1\")\n .replace(/\\n/g, \"'\\n'\");\n};\n\n/**\n * Builds a command line string from an argument list.\n *\n * @param array An array of string arguments.\n * @returns The command line string.\n */\nexport const join = (array: string[]) =>\n array.map((element) => escape(element)).join(\" \");\n","import { execa } from 'execa';\nimport { PassThrough } from 'node:stream';\nimport { randomUUID } from 'node:crypto';\nimport { writeFile, unlink, mkdir } from 'node:fs/promises';\nimport { tmpdir, homedir, userInfo } from 'node:os';\nimport { join } from 'node:path';\nimport type { Runner, RunnerProcess, RunnerStartConfig } from '@runeya/packages-runner-native';\nimport type { BootstrapCommand, DockerConfig } from '@runeya/packages-shared';\n\n/** Split a command string into tokens, respecting single and double quotes. */\nfunction splitShellArgs(cmd: string): string[] {\n const args: string[] = [];\n let current = '';\n let inSingle = false;\n let inDouble = false;\n for (let i = 0; i < cmd.length; i++) {\n const ch = cmd[i];\n if (ch === \"'\" && !inDouble) {\n inSingle = !inSingle;\n } else if (ch === '\"' && !inSingle) {\n inDouble = !inDouble;\n } else if (ch === '\\\\' && inDouble && i + 1 < cmd.length) {\n current += cmd[++i];\n } else if (/\\s/.test(ch) && !inSingle && !inDouble) {\n if (current) { args.push(current); current = ''; }\n } else {\n current += ch;\n }\n }\n if (current) args.push(current);\n return args;\n}\n\nexport interface DockerRunnerStartConfig extends RunnerStartConfig {\n dockerConfig: DockerConfig;\n serviceId: string;\n cmdId?: string; // for isolated mode container naming\n rm?: boolean; // add --rm to docker run (for shortcuts / one-off commands)\n skipBootstrap?: boolean; // skip bootstrap commands (for shortcuts)\n}\n\n/** Sanitize a string for use as a Docker container/image name: lowercase, only [a-z0-9._-] */\nfunction sanitizeDockerName(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9._-]/g, '-').replace(/-{2,}/g, '-');\n}\n\n/** Expand $VAR and ${VAR} references using the provided env dict.\n * Also expands leading ~ to the home directory.\n * Callers must pass a fully-merged env (passthrough + serviceEnv). */\nfunction expandEnvVars(str: string, serviceEnv?: Record<string, string>): string {\n const withHome = str.replace(/^~(\\/|$)/, `${homedir()}$1`);\n return withHome.replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (_, braced, plain) => {\n const name = braced ?? plain;\n return serviceEnv?.[name] ?? '';\n });\n}\n\n/** Pre-create host-side volume directories so Docker doesn't create them as root.\n * Only processes bind mounts (host:container[:opts]) — skips named volumes. */\nasync function preMkdirVolumes(volumes: string[], serviceEnv?: Record<string, string>): Promise<void> {\n for (const v of volumes) {\n const expanded = expandEnvVars(v, serviceEnv);\n const parts = expanded.split(':');\n // Named volumes have no path separator or start with a letter/digit without '/'\n if (parts.length < 2) continue;\n const hostPath = parts[0];\n if (!hostPath.startsWith('/') && !hostPath.startsWith('.')) continue;\n await mkdir(hostPath, { recursive: true }).catch(() => {});\n }\n}\n\nexport class DockerRunner implements Runner {\n readonly type = 'docker' as const;\n\n public start(config: DockerRunnerStartConfig): RunnerProcess {\n const stdout = new PassThrough();\n const stderr = new PassThrough();\n const containerName = sanitizeDockerName(config.cmdId\n ? `runeya-${config.serviceId}-${config.cmdId}`\n : `runeya-${config.serviceId}`);\n let killed = false;\n\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>(\n (resolve) => {\n void (async () => {\n try {\n // 1. Force-remove any existing container (ignore errors)\n await execa('docker', ['rm', '-f', containerName], { reject: false });\n\n const dc = config.dockerConfig;\n let lastCardId: string | null = null;\n const envFlags: string[] = Object.entries(config.env ?? {}).flatMap(\n ([k, v]) => ['-e', `${k}=${v}`],\n );\n await preMkdirVolumes(dc.volumes ?? [], config.env);\n const volumeFlags: string[] = (dc.volumes ?? []).flatMap((v: string) => ['-v', expandEnvVars(v, config.env)]);\n if (dc.mountRootpath && config.cwd) {\n volumeFlags.push('-v', `${config.cwd}:${config.cwd}`);\n }\n\n // 2a. Pull mode\n if (dc.image && !dc.dockerfile) {\n lastCardId = randomUUID();\n // Emit phase marker using \\x00DOCKER_PHASE: prefix for unambiguous frontend detection\n stdout.write(\n '\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'pull', _cardId: lastCardId, _cardState: 'open', message: `--- Docker Pull: ${dc.image} ---` }) + '\\n',\n );\n const pull = execa('docker', ['pull', dc.image], { reject: false });\n pull.stdout?.pipe(stdout, { end: false });\n pull.stderr?.pipe(stderr, { end: false });\n await pull;\n }\n\n // 2b. Build mode\n let imageName = dc.image ?? containerName + ':latest';\n if (dc.dockerfile) {\n lastCardId = randomUUID();\n // Emit phase marker using \\x00DOCKER_PHASE: prefix for unambiguous frontend detection\n stdout.write(\n '\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'build', _cardId: lastCardId, _cardState: 'open', message: '--- Docker Build ---' }) + '\\n',\n );\n const tmpFile = join(tmpdir(), `runeya-${config.serviceId}-${randomUUID()}.dockerfile`);\n try {\n await writeFile(tmpFile, dc.dockerfile, 'utf8');\n const buildArgs = Object.entries(dc.buildArgs ?? {}).flatMap(\n ([k, v]) => ['--build-arg', `${k}=${v}`],\n );\n const targetArgs = dc.targetStage ? ['--target', dc.targetStage] : [];\n const buildContext = dc.buildContext ?? config.cwd ?? '.';\n imageName = `${containerName}:latest`;\n const build = execa(\n 'docker',\n ['build', '-f', tmpFile, '-t', imageName, ...buildArgs, ...targetArgs, buildContext],\n { reject: false },\n );\n build.stdout?.pipe(stdout, { end: false });\n build.stderr?.pipe(stderr, { end: false });\n await build;\n } finally {\n await unlink(tmpFile).catch(() => {});\n }\n }\n\n if (killed) {\n resolve({ exitCode: null, signal: 'SIGTERM' as NodeJS.Signals });\n return;\n }\n\n // Close the phase card (pull/build) so container run logs flow into normal log stream\n if (lastCardId) {\n stdout.write(\n '\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'close', _cardId: lastCardId, _cardState: 'close' }) + '\\n',\n );\n }\n\n // 3. Bootstrap commands — run sequentially before the main container\n const bootstrapCmds = config.skipBootstrap ? [] : (dc.bootstrapCommands ?? []).filter((c) => c.command.trim());\n for (const bsCmd of bootstrapCmds) {\n if (killed) {\n resolve({ exitCode: null, signal: 'SIGTERM' as NodeJS.Signals });\n return;\n }\n const bsCardId = randomUUID();\n const bsCmdName = bsCmd.label || bsCmd.command;\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'bootstrap', _cardId: bsCardId, _cardState: 'open', message: `Bootstrap: ${bsCmdName}` })}\\n`);\n const exitCode = await this.runBootstrap(bsCmd, imageName, config.env ?? {}, dc.volumes ?? [], stdout, stderr);\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'close', _cardId: bsCardId, _cardState: 'close' })}\\n`);\n if (exitCode !== 0) {\n stderr.write(`Bootstrap command \"${bsCmdName}\" failed with exit code ${exitCode}\\n`);\n resolve({ exitCode, signal: null, error: `Bootstrap \"${bsCmdName}\" failed (exit ${exitCode})` });\n return;\n }\n }\n\n if (killed) {\n resolve({ exitCode: null, signal: 'SIGTERM' as NodeJS.Signals });\n return;\n }\n\n // 4. Run container (foreground, no --detach, no --rm)\n const networkFlags =\n dc.networkMode === 'host'\n ? ['--network', 'host']\n : (dc.ports ?? []).flatMap((p) => ['-p', p]);\n // When useNativeCommand is true the user's native command takes full control:\n // ignore dc.entrypoint (it belongs to the \"docker command\" mode) and wrap the\n // command with sh -c so shell syntax (pipes, quotes, redirects) works inside\n // the container. When useNativeCommand is false, honour dc.entrypoint and use\n // dc.command (the docker-specific command field).\n let cmdArgs: string[];\n let entrypointFlags: string[];\n if (dc.useNativeCommand) {\n const shell = dc.nativeShell || 'sh';\n entrypointFlags = [];\n cmdArgs = config.command ? [shell, '-c', config.command] : [];\n } else {\n entrypointFlags = dc.entrypoint ? ['--entrypoint', dc.entrypoint] : [];\n cmdArgs = dc.command ? splitShellArgs(dc.command) : [];\n }\n const { uid, gid } = userInfo();\n const rmFlag = config.rm ? ['--rm'] : [];\n const runArgs = [\n 'run', ...rmFlag, '--init',\n '--name', containerName,\n '--user', dc.user || `${uid}:${gid}`,\n ...networkFlags,\n ...envFlags,\n ...volumeFlags,\n ...entrypointFlags,\n imageName,\n ...cmdArgs,\n ];\n const debugCardId = randomUUID();\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'run', _cardId: debugCardId, _cardState: 'open', message: 'Docker Run' })}\\n`);\n stdout.write(`docker ${runArgs.join(' ')}\\n`);\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'close', _cardId: debugCardId, _cardState: 'close' })}\\n`);\n const runProc = execa('docker', runArgs, { reject: false });\n runProc.stdout?.pipe(stdout, { end: false });\n runProc.stderr?.pipe(stderr, { end: false });\n const result = await runProc;\n resolve({ exitCode: result.exitCode ?? null, signal: (result.signal as NodeJS.Signals) ?? null });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr.write(`Docker infrastructure error: ${msg}\\n`);\n resolve({ exitCode: 1, signal: null });\n } finally {\n stdout.end();\n stderr.end();\n }\n })();\n },\n );\n\n return {\n pid: undefined,\n containerName,\n stdout,\n stderr,\n exitPromise,\n kill(_signal = 'SIGTERM') {\n killed = true;\n execa('docker', ['stop', containerName]).catch(() => {});\n return true;\n },\n };\n }\n\n /** Start a long-lived container (sleep infinity) for shared mode.\n * Returns the RunnerProcess (lifetime) plus a `containerReady` promise that resolves\n * once `docker run --detach` has completed and the container is confirmed running.\n * Callers must await `containerReady` before calling `execInContainer`. */\n public startSharedContainer(config: DockerRunnerStartConfig): RunnerProcess & { containerReady: Promise<void> } {\n const stdout = new PassThrough();\n const stderr = new PassThrough();\n const containerName = sanitizeDockerName(`runeya-${config.serviceId}`);\n let killed = false;\n\n let resolveReady!: () => void;\n let rejectReady!: (err: Error) => void;\n const containerReady = new Promise<void>((res, rej) => {\n resolveReady = res;\n rejectReady = rej;\n });\n\n // exitResolve is shared between the kill() path and the natural-exit path.\n // Whichever fires first wins — subsequent calls are no-ops (Promise settled).\n let exitResolve!: (result: { exitCode: number | null; signal: NodeJS.Signals | null; error?: string }) => void;\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>(\n (resolve) => { exitResolve = resolve; },\n );\n\n void (async () => {\n try {\n await execa('docker', ['rm', '-f', containerName], { reject: false });\n\n const dc = config.dockerConfig;\n let lastCardId: string | null = null;\n const envFlags: string[] = Object.entries(config.env ?? {}).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n await preMkdirVolumes(dc.volumes ?? [], config.env);\n const volumeFlags: string[] = (dc.volumes ?? []).flatMap((v: string) => ['-v', expandEnvVars(v, config.env)]);\n if (dc.mountRootpath && config.cwd) {\n volumeFlags.push('-v', `${config.cwd}:${config.cwd}`);\n }\n\n if (dc.image && !dc.dockerfile) {\n lastCardId = randomUUID();\n stdout.write('\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'pull', _cardId: lastCardId, _cardState: 'open', message: `--- Docker Pull: ${dc.image} ---` }) + '\\n');\n const pull = execa('docker', ['pull', dc.image], { reject: false });\n pull.stdout?.pipe(stdout, { end: false });\n pull.stderr?.pipe(stderr, { end: false });\n await pull;\n }\n\n let imageName = dc.image ?? containerName + ':latest';\n if (dc.dockerfile) {\n lastCardId = randomUUID();\n stdout.write('\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'build', _cardId: lastCardId, _cardState: 'open', message: '--- Docker Build ---' }) + '\\n');\n const tmpFile = join(tmpdir(), `runeya-${config.serviceId}-${randomUUID()}.dockerfile`);\n try {\n await writeFile(tmpFile, dc.dockerfile, 'utf8');\n const buildArgs = Object.entries(dc.buildArgs ?? {}).flatMap(([k, v]) => ['--build-arg', `${k}=${v}`]);\n const targetArgs = dc.targetStage ? ['--target', dc.targetStage] : [];\n const buildContext = dc.buildContext ?? config.cwd ?? '.';\n imageName = `${containerName}:latest`;\n const build = execa('docker', ['build', '-f', tmpFile, '-t', imageName, ...buildArgs, ...targetArgs, buildContext], { reject: false });\n build.stdout?.pipe(stdout, { end: false });\n build.stderr?.pipe(stderr, { end: false });\n await build;\n } finally {\n await unlink(tmpFile).catch(() => {});\n }\n }\n\n if (killed) {\n rejectReady(new Error('Killed before container started'));\n exitResolve({ exitCode: null, signal: 'SIGTERM' as NodeJS.Signals });\n return;\n }\n\n if (lastCardId) {\n stdout.write('\\x00DOCKER_PHASE:' + JSON.stringify({ _dockerPhase: 'close', _cardId: lastCardId, _cardState: 'close' }) + '\\n');\n }\n\n const networkFlags = dc.networkMode === 'host'\n ? ['--network', 'host']\n : (dc.ports ?? []).flatMap((p: string) => ['-p', p]);\n const { uid, gid } = userInfo();\n const runArgs = [\n 'run', '--detach', '--init',\n '--name', containerName,\n '--user', dc.user || `${uid}:${gid}`,\n ...networkFlags,\n ...envFlags,\n ...volumeFlags,\n imageName,\n 'sleep', 'infinity',\n ];\n const debugCardId = randomUUID();\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'run', _cardId: debugCardId, _cardState: 'open', message: 'Docker Run (shared container)' })}\\n`);\n stdout.write(`docker ${runArgs.join(' ')}\\n`);\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'close', _cardId: debugCardId, _cardState: 'close' })}\\n`);\n\n const runProc = execa('docker', runArgs, { reject: false });\n runProc.stdout?.pipe(stdout, { end: false });\n runProc.stderr?.pipe(stderr, { end: false });\n const runResult = await runProc;\n if (runResult.exitCode !== 0) {\n rejectReady(new Error(`docker run exited with code ${runResult.exitCode}`));\n exitResolve({ exitCode: runResult.exitCode ?? 1, signal: null });\n return;\n }\n\n // Container is now running — signal callers they can exec into it\n resolveReady();\n\n // Wait for natural container exit (kill() resolves exitPromise first if called)\n const waitProc = execa('docker', ['wait', containerName], { reject: false });\n await waitProc;\n exitResolve({ exitCode: 0, signal: null });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr.write(`Docker infrastructure error: ${msg}\\n`);\n rejectReady(new Error(msg));\n exitResolve({ exitCode: 1, signal: null });\n } finally {\n stdout.end();\n stderr.end();\n }\n })();\n\n return {\n pid: undefined,\n containerName,\n stdout,\n stderr,\n exitPromise,\n containerReady,\n kill(_signal = 'SIGTERM') {\n killed = true;\n // Await docker kill, then immediately resolve exitPromise — don't wait for docker wait\n execa('docker', ['kill', containerName])\n .then(() => exitResolve({ exitCode: null, signal: 'SIGKILL' as NodeJS.Signals }))\n .catch(() => exitResolve({ exitCode: 1, signal: null }));\n return true;\n },\n };\n }\n\n /** Run a command inside a running shared container via `docker exec`.\n * Kill terminates the docker-exec process but does NOT stop the container. */\n public execInContainer(containerName: string, command: string, envVars: Record<string, string> = {}, shell = 'sh'): RunnerProcess {\n const stdout = new PassThrough();\n const stderr = new PassThrough();\n let dockerProc: ReturnType<typeof execa> | null = null;\n\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>(\n (resolve) => {\n void (async () => {\n try {\n const envFlags = Object.entries(envVars).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n const shellCmd = command.length ? command : 'true';\n dockerProc = execa(\n 'docker',\n ['exec', ...envFlags, containerName, shell, '-c', shellCmd],\n { reject: false },\n );\n dockerProc.stdout?.pipe(stdout, { end: false });\n dockerProc.stderr?.pipe(stderr, { end: false });\n const result = await dockerProc;\n resolve({ exitCode: result.exitCode ?? null, signal: (result.signal as NodeJS.Signals) ?? null });\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr.write(`docker execInContainer error: ${msg}\\n`);\n resolve({ exitCode: 1, signal: null });\n } finally {\n stdout.end();\n stderr.end();\n }\n })();\n },\n );\n\n return {\n pid: undefined,\n containerName,\n stdout,\n stderr,\n exitPromise,\n kill(_signal = 'SIGTERM') {\n dockerProc?.kill('SIGTERM');\n return true;\n },\n };\n }\n\n /** Run a shortcut command in the context of a Docker service.\n * If a service container is running (shared or isolated), uses `docker exec`.\n * If not running, reuses `start()` with `--rm` and `skipBootstrap`. */\n public runShortcut(config: DockerRunnerStartConfig, shortcutCommand: string): RunnerProcess {\n const stdout = new PassThrough();\n const stderr = new PassThrough();\n let innerProcess: RunnerProcess | null = null;\n let dockerProc: ReturnType<typeof execa> | null = null;\n\n const exitPromise = new Promise<{ exitCode: number | null; signal: NodeJS.Signals | null; error?: string }>(\n (resolve) => {\n void (async () => {\n try {\n // Find any running container for this service (covers both shared and isolated modes).\n const psResult = await execa(\n 'docker', ['ps', '--filter', `name=runeya-${config.serviceId}`, '--format', '{{.Names}}'],\n { reject: false },\n );\n const runningContainer = psResult.stdout.trim().split('\\n').find(n => n.startsWith(`runeya-${config.serviceId}`));\n\n if (runningContainer) {\n // Container is running — docker exec into it\n const shell = config.dockerConfig.nativeShell || 'sh';\n const envFlags = Object.entries(config.env ?? {}).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n const args = ['exec', ...envFlags, runningContainer, shell, '-c', shortcutCommand || 'true'];\n const cardId = randomUUID();\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'exec', _cardId: cardId, _cardState: 'open', message: 'Docker Exec' })}\\n`);\n stdout.write(`docker ${args.join(' ')}\\n`);\n stdout.write(`\\x00DOCKER_PHASE:${JSON.stringify({ _dockerPhase: 'close', _cardId: cardId, _cardState: 'close' })}\\n`);\n dockerProc = execa('docker', args, { reject: false });\n dockerProc.stdout?.pipe(stdout, { end: false });\n dockerProc.stderr?.pipe(stderr, { end: false });\n const result = await dockerProc;\n resolve({ exitCode: result.exitCode ?? null, signal: (result.signal as NodeJS.Signals) ?? null });\n } else {\n // No running container — reuse start() with --rm, skip bootstrap, shortcut command\n // Force useNativeCommand so start() wraps the command with sh -c\n innerProcess = this.start({\n ...config,\n command: shortcutCommand,\n cmdId: `shortcut-${randomUUID()}`,\n rm: true,\n skipBootstrap: true,\n dockerConfig: { ...config.dockerConfig, useNativeCommand: true },\n });\n innerProcess.stdout?.pipe(stdout, { end: false });\n innerProcess.stderr?.pipe(stderr, { end: false });\n const result = await innerProcess.exitPromise;\n resolve(result);\n }\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n stderr.write(`docker shortcut error: ${msg}\\n`);\n resolve({ exitCode: 1, signal: null });\n } finally {\n stdout.end();\n stderr.end();\n }\n })();\n },\n );\n\n return {\n pid: undefined,\n stdout,\n stderr,\n exitPromise,\n kill(signal = 'SIGTERM' as NodeJS.Signals) {\n if (innerProcess) return innerProcess.kill(signal);\n dockerProc?.kill('SIGTERM');\n return true;\n },\n };\n }\n\n public async isAvailable(): Promise<boolean> {\n const result = await execa('docker', ['info'], { reject: false });\n return result.exitCode === 0;\n }\n\n /** Run a single bootstrap command sequentially inside a temporary container (--rm).\n * Streams stdout/stderr into the provided PassThrough streams.\n * Resolves with the exit code when the container exits. */\n public async runBootstrap(\n cmd: BootstrapCommand,\n imageName: string,\n env: Record<string, string>,\n volumes: string[],\n stdout: PassThrough,\n stderr: PassThrough,\n ): Promise<number> {\n const containerName = sanitizeDockerName(`runeya-bootstrap-${randomUUID()}`);\n const envFlags: string[] = Object.entries(env).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n await preMkdirVolumes(volumes, env);\n const volumeFlags: string[] = volumes.map(v => expandEnvVars(v, env)).flatMap(v => ['-v', v]);\n const entrypointFlags: string[] = cmd.entrypoint ? ['--entrypoint', cmd.entrypoint] : [];\n const { uid, gid } = userInfo();\n const defaultUser = `${uid}:${gid}`;\n const userFlags: string[] = ['--user', cmd.user || defaultUser];\n const cmdArgs = splitShellArgs(cmd.command);\n\n const runArgs = [\n 'run', '--rm', '--init',\n '--name', containerName,\n '--network', 'host',\n ...envFlags,\n ...volumeFlags,\n ...entrypointFlags,\n ...userFlags,\n imageName,\n ...cmdArgs,\n ];\n\n const proc = execa('docker', runArgs, { reject: false });\n proc.stdout?.pipe(stdout, { end: false });\n proc.stderr?.pipe(stderr, { end: false });\n const result = await proc;\n return result.exitCode ?? 1;\n }\n}\n\nexport { type Runner, type RunnerProcess, type RunnerStartConfig } from '@runeya/packages-runner-native';\n","import type { ServiceConfig } from '@runeya/packages-shared';\nimport type { RunnerProcess } from '@runeya/packages-runner-native';\n\nexport interface CommandProcess {\n commandId: string;\n runnerProcess: RunnerProcess | null;\n pid: number | null;\n containerName: string | null;\n exitCode: number | null;\n}\n\nexport interface StoredProcess {\n id: string;\n serviceConfig: ServiceConfig;\n commandProcesses: CommandProcess[];\n state: 'starting' | 'running' | 'stopped' | 'errored';\n exitCode: number | null;\n startedAt: Date | null;\n restartCount: number;\n manuallyStopped: boolean;\n operationInProgress: boolean; // Prevent race conditions from concurrent operations\n sharedContainerProcess?: RunnerProcess | null; // Docker shared mode: the long-lived container process\n}\n\nclass ProcessStore {\n private processes = new Map<string, StoredProcess>();\n\n get(id: string): StoredProcess | undefined {\n return this.processes.get(id);\n }\n\n getAll(): StoredProcess[] {\n return Array.from(this.processes.values());\n }\n\n set(id: string, process: StoredProcess): void {\n this.processes.set(id, process);\n }\n\n delete(id: string): boolean {\n return this.processes.delete(id);\n }\n\n has(id: string): boolean {\n return this.processes.has(id);\n }\n\n clear(): void {\n this.processes.clear();\n }\n\n getByServiceId(serviceId: string): StoredProcess | undefined {\n return this.getAll().find(p => p.serviceConfig.id === serviceId);\n }\n}\n\nexport const processStore = new ProcessStore();\n","import { createInterface } from 'node:readline';\nimport { EventEmitter } from 'node:events';\nimport { randomUUID } from 'node:crypto';\nimport type { ParsedLog, JSLogParserDef, LogCardDirective, ILogSource } from '@runeya/packages-shared';\nimport { LOG_BUFFER_SIZE } from '@runeya/packages-shared';\nimport { LogParser } from '../log-parser.js';\nimport { LogBuffer } from '../log-buffer.js';\nimport { stripAnsi } from '../../utils/strip-ansi.js';\n\nconst DOCKER_PHASE_PREFIX = '\\x00DOCKER_PHASE:';\n\n/** Monotonic counter for fast log IDs (replaces randomUUID for hot-path logs) */\nlet logIdCounter = 0;\nfunction fastId(): string {\n return 'L' + (++logIdCounter).toString(36);\n}\n\ninterface ActiveCard {\n id: string;\n type: string;\n header: string;\n collapsable?: boolean;\n collapsed?: boolean;\n}\n\nexport class ConsoleLogSource extends EventEmitter implements ILogSource {\n readonly id: string;\n readonly type = 'console' as const;\n\n private parsers = new Map<string, LogParser>();\n private buffer: LogBuffer;\n private processPids = new Map<string, number | null>();\n private pendingBatch: ParsedLog[] = [];\n private batchScheduled = false;\n private readlineInterfaces: import('node:readline').Interface[] = [];\n\n constructor(bufferSize: number = LOG_BUFFER_SIZE) {\n super();\n this.id = randomUUID();\n this.buffer = new LogBuffer(bufferSize);\n }\n\n /** No-op: attach() is called separately after start() */\n async start(_processId: string): Promise<void> {\n // no-op for console source — actual streaming begins via attach()\n }\n\n /** Closes all active readline interfaces and releases resources */\n async stop(): Promise<void> {\n for (const rl of this.readlineInterfaces) {\n rl.close();\n }\n this.readlineInterfaces = [];\n }\n\n setJSParsers(processId: string, jsParsers: JSLogParserDef[] = []): void {\n const parser = new LogParser(jsParsers);\n this.parsers.set(processId, parser);\n }\n\n /** Attach to a process stdout/stderr and start streaming logs.\n * Each attach() call gets its own session card context so that multiple\n * concurrent commands (isolated mode) don't clobber each other's card state. */\n attach(processId: string, stdout: NodeJS.ReadableStream | null, stderr: NodeJS.ReadableStream | null, pid?: number | null): void {\n // Store the PID for this process so logs can reference it\n if (pid !== undefined) {\n const existingPid = this.processPids.get(processId);\n if (existingPid != null && existingPid !== pid) {\n console.warn(`[console-log-source] WARNING: Replacing PID ${existingPid} with ${pid} for process ${processId}. This may indicate a race condition or double-start.`);\n }\n this.processPids.set(processId, pid);\n }\n\n // Shared session state between stdout and stderr for THIS attach() call only\n let sessionCard: ActiveCard | null = null;\n\n if (stdout) {\n const rl = createInterface({ input: stdout });\n this.readlineInterfaces.push(rl);\n rl.on('line', (rawLine) => {\n // Nettoye avant l'analyse : un programme qui colore sa sortie (tout\n // l'ecosysteme Vite sous Windows) donnerait sinon des lignes dont ni le\n // JSON ni le niveau ne se reconnaissent plus.\n const line = stripAnsi(rawLine);\n const log = this.createLog(processId, line, 'stdout', sessionCard, (card) => { sessionCard = card; });\n if (!log) return;\n this.enqueueLog(log);\n });\n rl.on('error', (err) => {\n console.debug('[console-log-source] readline stdout error for', processId + ':', err.message);\n });\n }\n\n if (stderr) {\n const rl = createInterface({ input: stderr });\n this.readlineInterfaces.push(rl);\n rl.on('line', (rawLine) => {\n const line = stripAnsi(rawLine);\n const log = this.createLog(processId, line, 'stderr', sessionCard, (card) => { sessionCard = card; });\n if (!log) return;\n this.enqueueLog(log);\n });\n rl.on('error', (err) => {\n console.debug('[console-log-source] readline stderr error for', processId + ':', err.message);\n });\n }\n }\n\n /** Add a synthetic system/error log entry (e.g., spawn failure) */\n addSystemLog(\n processId: string,\n message: string,\n level: 'error' | 'warn' | 'info' = 'error',\n logCard?: LogCardDirective,\n ): void {\n console.debug('[console-log-source] Adding system log for', processId, ':', message);\n const pid = this.processPids.get(processId) ?? null;\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid,\n timestamp: new Date(),\n level,\n message,\n raw: message,\n stream: level === 'error' || level === 'warn' ? 'stderr' : 'stdout',\n hidden: false,\n metadata: {},\n sourceType: 'console',\n logCard,\n };\n this.enqueueLog(log);\n }\n\n getHistory(processId: string): ParsedLog[] {\n return this.buffer.getByProcessId(processId);\n }\n\n getAllHistory(): ParsedLog[] {\n return this.buffer.getAll();\n }\n\n clearHistory(processId?: string): void {\n this.buffer.clear(processId);\n if (processId) {\n this.parsers.delete(processId);\n this.processPids.delete(processId);\n } else {\n this.parsers.clear();\n this.processPids.clear();\n }\n }\n\n /** Clear only the log buffer, preserving parse rules for running processes */\n clearBufferOnly(processId: string): void {\n this.buffer.clear(processId);\n }\n\n private enqueueLog(log: ParsedLog): void {\n this.buffer.push(log);\n this.pendingBatch.push(log);\n if (!this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n\n private flushBatch(): void {\n this.batchScheduled = false;\n if (this.pendingBatch.length === 0) return;\n const batch = this.pendingBatch;\n this.pendingBatch = [];\n this.emit('logs', batch);\n }\n\n private getParser(processId: string): LogParser {\n let parser = this.parsers.get(processId);\n if (!parser) {\n parser = new LogParser();\n this.parsers.set(processId, parser);\n }\n return parser;\n }\n\n private createLog(\n processId: string,\n raw: string,\n stream: 'stdout' | 'stderr',\n sessionCard: ActiveCard | null,\n setSessionCard: (card: ActiveCard | null) => void,\n ): ParsedLog | null {\n // Detect and handle Docker phase markers\n if (raw.startsWith(DOCKER_PHASE_PREFIX)) {\n try {\n const meta = JSON.parse(raw.slice(DOCKER_PHASE_PREFIX.length)) as {\n _dockerPhase: string;\n _cardId: string;\n _cardState?: string;\n message?: string;\n };\n\n if (meta._cardState === 'close') {\n const closing = sessionCard;\n setSessionCard(null);\n if (closing) {\n const directive: LogCardDirective = {\n id: closing.id,\n type: closing.type,\n header: closing.header,\n state: 'close',\n };\n const pid = this.processPids.get(processId) ?? null;\n return {\n id: fastId(),\n processId,\n pid,\n timestamp: new Date(),\n level: 'info',\n message: '',\n raw,\n stream,\n hidden: true,\n sourceType: 'console',\n logCard: directive,\n };\n }\n return null;\n }\n\n const card: ActiveCard = {\n id: meta._cardId,\n type: meta._dockerPhase,\n header: meta.message ?? meta._dockerPhase,\n collapsed: meta._dockerPhase === 'run' || meta._dockerPhase === 'pull' || meta._dockerPhase === 'build' || meta._dockerPhase === 'exec',\n collapsable: true,\n };\n setSessionCard(card);\n const directive: LogCardDirective = {\n id: card.id,\n type: card.type,\n header: card.header,\n collapsable: card.collapsable,\n collapsed: card.collapsed,\n state: 'open',\n };\n const pid = this.processPids.get(processId) ?? null;\n return {\n id: fastId(),\n processId,\n pid,\n timestamp: new Date(),\n level: 'info',\n message: card.header,\n raw,\n stream,\n hidden: true,\n sourceType: 'console',\n logCard: directive,\n };\n } catch {\n // Not a valid marker — fall through to normal parsing\n }\n }\n\n const parsed = this.getParser(processId).parse(raw, stream);\n const pid = this.processPids.get(processId) ?? null;\n\n let logCard: LogCardDirective | undefined;\n if (parsed.json) {\n // JSON logs are always self-contained cards regardless of any active container card\nlogCard = { id: fastId(), type: 'json', header: parsed.jsonHeader ?? 'JSON', state: 'self', collapsable: true };\n } else if (sessionCard) {\n logCard = { id: sessionCard.id, type: sessionCard.type, header: sessionCard.header, state: 'append' };\n }\n\n return {\n id: fastId(),\n processId,\n pid,\n timestamp: new Date(),\n level: parsed.level,\n message: parsed.message,\n raw,\n stream,\n hidden: parsed.hidden,\n metadata: parsed.metadata,\n json: parsed.json,\n sourceType: 'console',\n logCard,\n };\n }\n}\n","import type { LogLevel, LogLine, JSLogParserDef } from '@runeya/packages-shared';\nimport { JSLogParser } from './js-log-parser.js';\n\nconst DEFAULT_LEVEL_PATTERNS: Array<{ pattern: RegExp; level: LogLevel }> = [\n { pattern: /\\b(fatal|FATAL)\\b/, level: 'fatal' },\n { pattern: /\\b(error|ERROR|ERR)\\b/, level: 'error' },\n { pattern: /\\b(warn|WARNING|WARN)\\b/, level: 'warn' },\n { pattern: /\\b(debug|DEBUG|DBG)\\b/, level: 'debug' },\n { pattern: /\\b(info|INFO|INF)\\b/, level: 'info' },\n];\n\nexport class LogParser {\n private jsParser: JSLogParser | null = null;\n\n constructor(jsParsers: JSLogParserDef[] = []) {\n this.setJSParsers(jsParsers);\n }\n\n setJSParsers(jsParsers: JSLogParserDef[]): void {\n if (jsParsers.length > 0) {\n this.jsParser = new JSLogParser(jsParsers);\n } else {\n this.jsParser = null;\n }\n }\n\n parse(raw: string, stream: 'stdout' | 'stderr' = 'stdout'): LogLine {\n // 1. Construct initial LogLine\n let line: LogLine = {\n raw,\n stream,\n level: stream === 'stderr' ? 'error' : 'info',\n message: raw,\n hidden: false,\n metadata: {},\n };\n\n // 2. Step 0: default regex level detection\n line = this.detectLevel(line);\n\n // 3. Run JS parser pipeline (all parsers in order)\n if (this.jsParser) {\n line = this.jsParser.parse(line);\n }\n\n return line;\n }\n\n private detectLevel(line: LogLine): LogLine {\n for (const { pattern, level } of DEFAULT_LEVEL_PATTERNS) {\n if (pattern.test(line.raw)) {\n return { ...line, level };\n }\n }\n return line;\n }\n}\n","import type { ParsedLog } from '@runeya/packages-shared';\nimport { LOG_BUFFER_SIZE } from '@runeya/packages-shared';\n\nexport class LogBuffer {\n private buffer: ParsedLog[] = [];\n private maxSize: number;\n /** Map-based index for O(1) processId lookups */\n private index = new Map<string, ParsedLog[]>();\n\n constructor(maxSize: number = LOG_BUFFER_SIZE) {\n this.maxSize = maxSize;\n }\n\n push(log: ParsedLog): void {\n if (this.buffer.length >= this.maxSize) {\n const evicted = this.buffer.shift()!;\n // Remove evicted entry from index\n const indexed = this.index.get(evicted.processId);\n if (indexed) {\n indexed.shift();\n if (indexed.length === 0) {\n this.index.delete(evicted.processId);\n }\n }\n }\n this.buffer.push(log);\n // Add to index\n let indexed = this.index.get(log.processId);\n if (!indexed) {\n indexed = [];\n this.index.set(log.processId, indexed);\n }\n indexed.push(log);\n }\n\n getAll(): ParsedLog[] {\n return [...this.buffer];\n }\n\n getByProcessId(processId: string): ParsedLog[] {\n const indexed = this.index.get(processId);\n return indexed ? [...indexed] : [];\n }\n\n clear(processId?: string): void {\n if (processId) {\n this.buffer = this.buffer.filter(l => l.processId !== processId);\n this.index.delete(processId);\n } else {\n this.buffer = [];\n this.index.clear();\n }\n }\n\n get size(): number {\n return this.buffer.length;\n }\n}\n","/**\n * Retirer les sequences ANSI d'une ligne de log.\n *\n * Les logs de service sont lus sur un tube, jamais sur un terminal : un\n * programme bien eleve n'y met donc pas de couleurs, et l'interface les affiche\n * en texte brut. Windows fait exception — `picocolors`, dont dependent Vite,\n * Nuxt et une bonne partie de l'ecosysteme, active la couleur des lors que la\n * plateforme est `win32`, sans regarder si la sortie est un terminal. Les codes\n * arrivaient donc jusqu'a l'ecran, lus comme du texte :\n * `ESC[36mi ESC[39m hmr update`.\n *\n * Nettoye ici plutot qu'a l'affichage, parce que la ligne est aussi ce que\n * lisent les analyseurs : un JSON precede d'un code couleur ne se reconnait\n * plus comme du JSON, et un niveau de log ne se retrouve plus derriere un\n * `ESC[31m`. C'est le meme bug, en silencieux.\n *\n * Applique sur toutes les plateformes : une ligne sans echappement ressort\n * telle quelle, et un programme qui force la couleur (`FORCE_COLOR`) est traite\n * partout comme il l'est sous Windows.\n */\n\n/**\n * D'abord OSC (`ESC] ... BEL` ou `ESC] ... ESC\\\\`), dont la charge utile est du\n * texte libre — un titre de fenetre, un lien — et doit etre avalee jusqu'a son\n * terminateur, sans quoi la moitie en ressort a l'ecran. Puis CSI et les\n * echappements a deux caracteres. `\\u009B` est la forme 8 bits du CSI, que\n * certains programmes emettent encore.\n */\n// eslint-disable-next-line no-control-regex\nconst ANSI_PATTERN = /\\u001B\\][^\\u0007\\u001B]*(?:\\u0007|\\u001B\\\\)|[\\u001B\\u009B][[()#;?]*(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nqry=><~]/g;\n\nexport function stripAnsi(line: string): string {\n // Chemin chaud : la quasi-totalite des lignes n'a aucun echappement, et le\n // flux de logs passe ici a chaque ligne de chaque service.\n if (!line.includes('\\u001B') && !line.includes('\\u009B')) return line;\n return line.replace(ANSI_PATTERN, '');\n}\n","import { EventEmitter } from 'node:events';\nimport * as fs from 'node:fs';\nimport * as fsPromises from 'node:fs/promises';\nimport type { ILogSource } from '@runeya/packages-shared';\nimport type { ParsedLog, FileLogSource as FileLogSourceConfig } from '@runeya/packages-shared';\nimport { LogBuffer } from '../log-buffer.js';\nimport { LogParser } from '../log-parser.js';\n\nlet idCounter = 0;\nfunction fastId(): string {\n return 'FLS' + (++idCounter).toString(36);\n}\n\nconst RETRY_ATTEMPTS = 3;\nconst RETRY_DELAY_MS = 5000;\n\nexport class FileLogSource extends EventEmitter implements ILogSource {\n readonly id: string;\n readonly type = 'file' as const;\n\n private config: FileLogSourceConfig;\n private logBuffer: LogBuffer;\n private logParser: LogParser;\n\n private isRunning = false;\n private offset = 0;\n private processId: string | null = null;\n private watcher: fs.FSWatcher | null = null;\n private pendingBatch: ParsedLog[] = [];\n private batchScheduled = false;\n\n constructor(config: FileLogSourceConfig, logBuffer: LogBuffer, logParser: LogParser) {\n super();\n this.id = fastId();\n this.config = config;\n this.logBuffer = logBuffer;\n this.logParser = logParser;\n }\n\n async start(processId: string): Promise<void> {\n if (this.isRunning) return;\n this.isRunning = true;\n this.processId = processId;\n\n // Attempt to open with retries if file doesn't exist yet\n let attempts = 0;\n while (true) {\n try {\n await fsPromises.access(this.config.path, fs.constants.R_OK);\n break;\n } catch (err: unknown) {\n const nodeErr = err as NodeJS.ErrnoException;\n if (nodeErr.code === 'EACCES') {\n this.emitSystemLog(processId, `[FileLogSource] Permission denied: ${this.config.path}`, 'error');\n return;\n }\n if (nodeErr.code === 'ENOENT' && this.config.createIfNotExists) {\n try {\n await fsPromises.mkdir(\n (await import('node:path')).dirname(this.config.path),\n { recursive: true },\n );\n await fsPromises.writeFile(this.config.path, '', { flag: 'a' });\n this.emitSystemLog(processId, `[FileLogSource] File created: ${this.config.path}`, 'info');\n break;\n } catch (createErr: unknown) {\n const ce = createErr as NodeJS.ErrnoException;\n this.emitSystemLog(processId, `[FileLogSource] Failed to create file: ${ce.message}`, 'error');\n return;\n }\n }\n attempts++;\n if (attempts >= RETRY_ATTEMPTS) {\n this.emitSystemLog(processId, `[FileLogSource] File not found after ${RETRY_ATTEMPTS} retries: ${this.config.path}`, 'error');\n return;\n }\n this.emitSystemLog(processId, `[FileLogSource] File not found, retrying in ${RETRY_DELAY_MS}ms: ${this.config.path}`, 'warn');\n await new Promise(r => setTimeout(r, RETRY_DELAY_MS));\n }\n }\n\n // Set initial offset\n if (this.config.startFromEnd) {\n const stat = await fsPromises.stat(this.config.path);\n this.offset = stat.size;\n } else {\n this.offset = 0;\n }\n\n // Watch for changes\n try {\n this.watcher = fs.watch(this.config.path, { persistent: false }, (event) => {\n if (event === 'change') {\n void this.readNewLines(processId);\n } else if (event === 'rename') {\n this.emitSystemLog(processId, `[FileLogSource] File renamed or deleted: ${this.config.path}`, 'error');\n void this.stop();\n }\n });\n\n this.watcher.on('error', (err: NodeJS.ErrnoException) => {\n this.emitSystemLog(processId, `[FileLogSource] Watcher error: ${err.message}`, 'error');\n void this.stop();\n });\n } catch (err: unknown) {\n const nodeErr = err as NodeJS.ErrnoException;\n this.emitSystemLog(processId, `[FileLogSource] Failed to watch file: ${nodeErr.message}`, 'error');\n }\n }\n\n async stop(): Promise<void> {\n this.isRunning = false;\n if (this.watcher) {\n this.watcher.close();\n this.watcher = null;\n }\n }\n\n getHistory(processId: string): ParsedLog[] {\n return this.logBuffer.getByProcessId(processId);\n }\n\n async readNewLines(processId: string): Promise<void> {\n let stat: fs.Stats;\n try {\n stat = await fsPromises.stat(this.config.path);\n } catch {\n return;\n }\n\n // Rotation detection\n if (stat.size < this.offset) {\n this.offset = 0;\n }\n\n if (stat.size === this.offset) return;\n\n const length = stat.size - this.offset;\n const buf = Buffer.alloc(length);\n\n let fd: fsPromises.FileHandle | null = null;\n try {\n fd = await fsPromises.open(this.config.path, 'r');\n await fd.read(buf, 0, length, this.offset);\n } catch {\n return;\n } finally {\n await fd?.close();\n }\n\n this.offset += length;\n\n const encoding = (this.config.encoding || 'utf-8') as BufferEncoding;\n const text = buf.toString(encoding);\n const lines = text.split('\\n');\n\n // Remove trailing empty string from final newline\n if (lines[lines.length - 1] === '') {\n lines.pop();\n }\n\n for (const line of lines) {\n if (!line) continue;\n const parsed = this.logParser.parse(line, 'stdout');\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid: null,\n timestamp: new Date(),\n level: parsed.level,\n message: parsed.message,\n raw: line,\n stream: 'stdout',\n hidden: parsed.hidden,\n metadata: parsed.metadata,\n json: parsed.json,\n sourceType: 'file',\n sourcePath: this.config.path,\n };\n this.logBuffer.push(log);\n this.pendingBatch.push(log);\n }\n\n if (this.pendingBatch.length > 0 && !this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n\n private flushBatch(): void {\n this.batchScheduled = false;\n if (this.pendingBatch.length === 0) return;\n const batch = this.pendingBatch;\n this.pendingBatch = [];\n this.emit('logs', batch);\n }\n\n private emitSystemLog(processId: string, message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid: null,\n timestamp: new Date(),\n level,\n message,\n raw: message,\n stream: 'stderr',\n hidden: false,\n metadata: {},\n sourceType: 'file',\n sourcePath: this.config.path,\n };\n this.logBuffer.push(log);\n this.pendingBatch.push(log);\n if (!this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n}\n","import { EventEmitter } from 'node:events';\nimport type { ILogSource, ParsedLog } from '@runeya/packages-shared';\nimport type { MongoLogSource as MongoLogSourceConfig } from '@runeya/packages-shared';\nimport { LogBuffer } from '../log-buffer.js';\nimport { LogParser } from '../log-parser.js';\nimport type { MongoClient, Collection, Document, WithId } from 'mongodb';\n\nlet idCounter = 0;\nfunction fastId(): string {\n return 'MLS' + (++idCounter).toString(36);\n}\n\nconst POLL_INTERVAL_MS = 5000;\nconst MAX_RETRIES = 5;\nconst BASE_RETRY_DELAY_MS = 1000;\n\nexport class MongoLogSource extends EventEmitter implements ILogSource {\n readonly id: string;\n readonly type = 'mongo' as const;\n\n private config: MongoLogSourceConfig;\n private logBuffer: LogBuffer;\n private logParser: LogParser;\n /** Overridable for tests */\n readonly baseRetryDelayMs: number;\n\n private client: MongoClient | null = null;\n private collection: Collection<Document> | null = null;\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private lastTimestamp: Date | null = null;\n private processId: string | null = null;\n private pendingBatch: ParsedLog[] = [];\n private batchScheduled = false;\n\n constructor(\n config: MongoLogSourceConfig,\n logBuffer: LogBuffer,\n logParser: LogParser,\n { baseRetryDelayMs = BASE_RETRY_DELAY_MS }: { baseRetryDelayMs?: number } = {},\n ) {\n super();\n this.id = fastId();\n this.config = config;\n this.logBuffer = logBuffer;\n this.logParser = logParser;\n this.baseRetryDelayMs = baseRetryDelayMs;\n }\n\n async start(processId: string): Promise<void> {\n this.processId = processId;\n\n const connStr = this.config.connectionString;\n\n let attempt = 0;\n while (attempt < MAX_RETRIES) {\n try {\n const { MongoClient: MC } = await import('mongodb');\n this.client = new MC(connStr, { serverSelectionTimeoutMS: 5000 });\n await this.client.connect();\n const db = this.client.db(this.config.database);\n this.collection = db.collection(this.config.collection);\n break;\n } catch (err: unknown) {\n attempt++;\n const msg = err instanceof Error ? err.message : String(err);\n this.emitSystemLog(processId, `[MongoLogSource] Connection failed (attempt ${attempt}/${MAX_RETRIES}): ${msg}`, 'warn');\n if (attempt >= MAX_RETRIES) {\n this.emitSystemLog(processId, `[MongoLogSource] Giving up after ${MAX_RETRIES} attempts`, 'error');\n return;\n }\n const delay = Math.min(this.baseRetryDelayMs * 2 ** attempt, 30000);\n await new Promise(r => setTimeout(r, delay));\n }\n }\n\n this.lastTimestamp = new Date();\n this.pollTimer = setInterval(() => void this.poll(processId), POLL_INTERVAL_MS);\n // Run first poll immediately\n await this.poll(processId);\n }\n\n async stop(): Promise<void> {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.client) {\n await this.client.close();\n this.client = null;\n this.collection = null;\n }\n }\n\n getHistory(processId: string): ParsedLog[] {\n return this.logBuffer.getByProcessId(processId);\n }\n\n private async poll(processId: string): Promise<void> {\n if (!this.collection) return;\n\n const tsField = this.config.timestampField;\n const msgField = this.config.messageField;\n const lvlField = this.config.levelField;\n\n const query: Record<string, unknown> = { ...this.config.filter };\n if (this.lastTimestamp) {\n query[tsField] = { $gt: this.lastTimestamp };\n }\n\n let docs: WithId<Document>[];\n try {\n docs = await this.collection.find(query).sort({ [tsField]: 1 }).toArray();\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n this.emitSystemLog(processId, `[MongoLogSource] Poll error: ${msg}`, 'error');\n return;\n }\n\n for (const doc of docs) {\n const rawMessage = String(doc[msgField] ?? '');\n const parsed = this.logParser.parse(rawMessage, 'stdout');\n\n let level = parsed.level;\n if (lvlField && doc[lvlField]) {\n const docLevel = String(doc[lvlField]).toLowerCase();\n if (['debug', 'info', 'warn', 'error', 'fatal'].includes(docLevel)) {\n level = docLevel as ParsedLog['level'];\n }\n }\n\n const docTimestamp = doc[tsField];\n const timestamp = docTimestamp instanceof Date ? docTimestamp : new Date();\n\n if (timestamp > (this.lastTimestamp ?? new Date(0))) {\n this.lastTimestamp = timestamp;\n }\n\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid: null,\n timestamp,\n level,\n message: rawMessage,\n raw: rawMessage,\n stream: 'stdout',\n hidden: false,\n metadata: parsed.metadata,\n json: parsed.json,\n sourceType: 'mongo',\n };\n\n this.logBuffer.push(log);\n this.pendingBatch.push(log);\n }\n\n if (this.pendingBatch.length > 0 && !this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n\n private flushBatch(): void {\n this.batchScheduled = false;\n if (this.pendingBatch.length === 0) return;\n const batch = this.pendingBatch;\n this.pendingBatch = [];\n this.emit('logs', batch);\n }\n\n private emitSystemLog(processId: string, message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\n const log: ParsedLog = {\n id: fastId(),\n processId,\n pid: null,\n timestamp: new Date(),\n level,\n message,\n raw: message,\n stream: 'stderr',\n hidden: false,\n metadata: {},\n sourceType: 'mongo',\n };\n this.logBuffer.push(log);\n this.pendingBatch.push(log);\n if (!this.batchScheduled) {\n this.batchScheduled = true;\n setImmediate(() => this.flushBatch());\n }\n }\n}\n","import { EventEmitter } from 'node:events';\nimport { createConnection, type Connection, type RowDataPacket } from 'mysql2/promise';\nimport type { ILogSource, ParsedLog, MySQLLogSource as MySQLLogSourceConfig } from '@runeya/packages-shared';\nimport type { LogBuffer } from '../log-buffer.js';\nimport type { LogParser } from '../log-parser.js';\n\nlet logIdCounter = 0;\nfunction fastId(): string {\n return 'ML' + (++logIdCounter).toString(36);\n}\n\nconst MAX_RETRIES = 5;\nconst RETRY_BASE_MS = 500;\n\nfunction parseLevel(val: unknown): 'debug' | 'info' | 'warn' | 'error' | 'fatal' {\n if (typeof val !== 'string') return 'info';\n const v = val.toLowerCase();\n if (v === 'fatal') return 'fatal';\n if (v === 'error' || v === 'err') return 'error';\n if (v === 'warn' || v === 'warning') return 'warn';\n if (v === 'debug' || v === 'dbg') return 'debug';\n return 'info';\n}\n\nfunction rowToLog(\n row: RowDataPacket,\n config: MySQLLogSourceConfig,\n processId: string,\n): ParsedLog {\n const rawTimestamp = row[config.timestampColumn];\n const timestamp =\n rawTimestamp instanceof Date\n ? rawTimestamp\n : new Date(rawTimestamp != null ? String(rawTimestamp) : Date.now());\n\n const message =\n row[config.messageColumn] != null\n ? String(row[config.messageColumn])\n : JSON.stringify(row);\n\n const level = config.levelColumn ? parseLevel(row[config.levelColumn]) : 'info';\n\n return {\n id: fastId(),\n processId,\n timestamp,\n level,\n message,\n raw: JSON.stringify(row),\n stream: 'stdout',\n hidden: false,\n sourceType: 'mysql',\n sourcePath: `${config.host}:${config.port}/${config.database}/${config.table}`,\n };\n}\n\nexport class MySQLLogSource extends EventEmitter implements ILogSource {\n readonly id: string;\n readonly type = 'mysql' as const;\n\n private lastTimestamp: Date = new Date(0);\n private pollTimer: NodeJS.Timeout | null = null;\n private connection: Connection | null = null;\n private retryCount = 0;\n private stopped = false;\n\n constructor(\n private readonly config: MySQLLogSourceConfig,\n private readonly logBuffer: LogBuffer,\n private readonly _logParser: LogParser,\n ) {\n super();\n this.id = `mysql-${config.host}-${config.database}-${config.table}-${Date.now()}`;\n }\n\n async start(processId: string): Promise<void> {\n this.stopped = false;\n this.lastTimestamp = new Date();\n await this.connect();\n this.schedulePoll(processId);\n }\n\n private async connect(): Promise<void> {\n this.connection = await createConnection({\n host: this.config.host,\n port: this.config.port,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n });\n }\n\n private schedulePoll(processId: string): void {\n if (this.stopped) return;\n this.pollTimer = setTimeout(() => {\n this.poll(processId).catch((err: Error) => {\n console.error('[mysql-log-source] Poll error for', this.id + ':', err.message);\n });\n }, this.config.pollIntervalMs);\n }\n\n private async poll(processId: string): Promise<void> {\n if (this.stopped) return;\n\n try {\n const rows = await this.executeQuery();\n if (rows.length > 0) {\n const batch: ParsedLog[] = [];\n for (const row of rows) {\n const log = rowToLog(row, this.config, processId);\n this.logBuffer.push(log);\n batch.push(log);\n\n const rawTs = row[this.config.timestampColumn];\n const ts = rawTs instanceof Date ? rawTs : new Date(rawTs != null ? String(rawTs) : Date.now());\n if (ts > this.lastTimestamp) {\n this.lastTimestamp = ts;\n }\n }\n this.emit('logs', batch);\n }\n this.retryCount = 0;\n } catch (err) {\n const error = err as Error;\n this.retryCount++;\n console.error(\n '[mysql-log-source] Query error (attempt ' + this.retryCount + '/' + MAX_RETRIES + ') for', this.id + ':', // nosemgrep: unsafe-formatstring\n error.message,\n );\n\n if (this.retryCount < MAX_RETRIES) {\n const delay = RETRY_BASE_MS * Math.pow(2, this.retryCount - 1);\n await this.reconnect(delay);\n } else {\n console.error(`[mysql-log-source] Max retries reached for ${this.id}, giving up.`);\n return;\n }\n }\n\n this.schedulePoll(processId);\n }\n\n private async executeQuery(): Promise<RowDataPacket[]> {\n if (!this.connection) throw new Error('No MySQL connection');\n\n if (this.config.query) {\n const [rows] = await this.connection.execute<RowDataPacket[]>(\n this.config.query,\n [this.lastTimestamp],\n );\n return rows;\n }\n\n const ts = this.config.timestampColumn;\n const table = this.config.table;\n const sql = `SELECT * FROM \\`${table}\\` WHERE \\`${ts}\\` > ? ORDER BY \\`${ts}\\` ASC`;\n const [rows] = await this.connection.execute<RowDataPacket[]>(sql, [this.lastTimestamp]);\n return rows;\n }\n\n private async reconnect(delayMs: number): Promise<void> {\n try {\n await this.connection?.end();\n } catch { /* ignore */ }\n this.connection = null;\n\n await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n if (this.stopped) return;\n\n try {\n await this.connect();\n } catch (err) {\n console.error('[mysql-log-source] Reconnect failed for', this.id + ':', (err as Error).message);\n }\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n try {\n await this.connection?.end();\n } catch { /* ignore */ }\n this.connection = null;\n }\n\n getHistory(processId: string): ParsedLog[] {\n return this.logBuffer.getByProcessId(processId);\n }\n}\n","import type { ILogSource, LogSourceConfig } from '@runeya/packages-shared';\nimport { ConsoleLogSource } from './console-log-source.js';\nimport { FileLogSource } from './file-log-source.js';\nimport { MongoLogSource } from './mongo-log-source.js';\nimport { MySQLLogSource } from './mysql-log-source.js';\nimport type { LogBuffer } from '../log-buffer.js';\nimport type { LogParser } from '../log-parser.js';\n\n/**\n * Factory function to create an ILogSource implementation from a config object.\n *\n * For `console`, a new ConsoleLogSource is created (manages its own internal buffer).\n * For all other types, the provided logBuffer and logParser are injected.\n *\n * @param config - Discriminated-union config from the service's logSources array\n * @param logBuffer - Shared buffer used by file/mongo/mysql sources\n * @param logParser - LogParser instance (unused by DB sources but passed for consistency)\n */\nexport function createLogSource(\n config: LogSourceConfig,\n logBuffer: LogBuffer,\n logParser: LogParser,\n): ILogSource {\n switch (config.type) {\n case 'console':\n return new ConsoleLogSource();\n case 'file':\n return new FileLogSource(config, logBuffer, logParser);\n case 'mongo':\n return new MongoLogSource(config, logBuffer, logParser);\n case 'mysql':\n return new MySQLLogSource(config, logBuffer, logParser);\n default: {\n // Exhaustiveness check — TypeScript will flag missing cases at compile time\n const _exhaustive: never = config;\n throw new Error(`Unknown log source type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n}\n","import pidusage from 'pidusage';\nimport { execFile } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\nimport type { ProcessMetrics } from '@runeya/packages-shared';\nimport { METRICS_INTERVAL } from '@runeya/packages-shared';\nimport { processStore } from './process-store.js';\n\n/** Parse `docker stats --no-stream --format json` output for a single container. */\nasync function getDockerStats(containerName: string): Promise<{ cpu: number; memory: number } | null> {\n return new Promise((resolve) => {\n execFile(\n 'docker',\n ['stats', '--no-stream', '--format', '{{json .}}', containerName],\n { timeout: 5000, windowsHide: true },\n (err, stdout) => {\n if (err || !stdout.trim()) { resolve(null); return; }\n try {\n const data = JSON.parse(stdout.trim()) as { CPUPerc: string; MemUsage: string };\n // parseFloat s'arrête au premier caractère non numérique : le « % » final tombe.\n const cpu = Number.parseFloat(data.CPUPerc);\n // MemUsage format: \"123MiB / 2GiB\" — take the left side\n const memStr = data.MemUsage.split('/')[0].trim();\n const memory = parseMemBytes(memStr);\n resolve({ cpu: Number.isNaN(cpu) ? 0 : cpu, memory });\n } catch {\n resolve(null);\n }\n },\n );\n });\n}\n\n/** Convert docker memory string (e.g. \"123MiB\", \"1.5GiB\", \"512kB\") to bytes. */\nfunction parseMemBytes(str: string): number {\n const m = str.match(/^([\\d.]+)\\s*(B|kB|MB|MiB|GiB|GB)$/i);\n if (!m) return 0;\n const val = Number.parseFloat(m[1]);\n const unit = m[2].toLowerCase();\n const multipliers: Record<string, number> = {\n b: 1, kb: 1e3, mb: 1e6, mib: 1024 * 1024, gib: 1024 ** 3, gb: 1e9,\n };\n return Math.round(val * (multipliers[unit] ?? 1));\n}\n\nexport class MetricsCollector extends EventEmitter {\n private intervals = new Map<string, ReturnType<typeof setInterval>>();\n private intervalMs: number;\n\n constructor(intervalMs: number = METRICS_INTERVAL) {\n super();\n this.intervalMs = intervalMs;\n }\n\n /** Start collecting metrics for a native process (by PID). */\n startCollecting(processId: string, pid: number): void {\n this.stopCollecting(processId);\n\n const interval = setInterval(async () => {\n try {\n const stats = await pidusage(pid);\n const metrics: ProcessMetrics = {\n processId,\n cpu: stats.cpu,\n memory: stats.memory,\n timestamp: new Date().toISOString(),\n };\n this.emit('metrics', metrics);\n } catch {\n // Process might have exited, stop collecting\n this.stopCollecting(processId);\n }\n }, this.intervalMs);\n\n this.intervals.set(processId, interval);\n }\n\n /** Start collecting metrics for a Docker container (by container name). */\n startCollectingDocker(processId: string, containerName: string): void {\n this.stopCollecting(processId);\n\n const interval = setInterval(async () => {\n const stats = await getDockerStats(containerName);\n if (!stats) {\n this.stopCollecting(processId);\n return;\n }\n const metrics: ProcessMetrics = {\n processId,\n cpu: stats.cpu,\n memory: stats.memory,\n timestamp: new Date().toISOString(),\n };\n this.emit('metrics', metrics);\n }, this.intervalMs);\n\n this.intervals.set(processId, interval);\n }\n\n /** Stop collecting metrics for a process */\n stopCollecting(processId: string): void {\n const interval = this.intervals.get(processId);\n if (interval) {\n clearInterval(interval);\n this.intervals.delete(processId);\n }\n }\n\n /** Get current metrics for a process (one-shot, uses first active PID or container name). */\n async getMetrics(processId: string): Promise<ProcessMetrics | null> {\n const proc = processStore.get(processId);\n if (!proc) return null;\n\n // Try native PID first\n const activePid = proc.commandProcesses.find(cp => cp.pid !== null)?.pid;\n if (activePid) {\n try {\n const stats = await pidusage(activePid);\n return {\n processId,\n cpu: stats.cpu,\n memory: stats.memory,\n timestamp: new Date().toISOString(),\n };\n } catch {\n // fall through to Docker\n }\n }\n\n // Try Docker container name\n const containerName = proc.commandProcesses.find(cp => cp.containerName)?.containerName;\n if (containerName) {\n const stats = await getDockerStats(containerName);\n if (stats) {\n return { processId, ...stats, timestamp: new Date().toISOString() };\n }\n }\n\n return null;\n }\n\n /** Stop all collection intervals */\n stopAll(): void {\n for (const [id] of this.intervals) {\n this.stopCollecting(id);\n }\n }\n}\n","import { EventEmitter } from 'node:events';\nimport { execa } from 'execa';\nimport * as shellwordsModule from 'shellwords';\nimport { HEALTH_CHECK_INTERVAL, HEALTH_CHECK_INITIAL_DELAY } from '@runeya/packages-shared';\nimport { processStore } from './process-store.js';\nimport { resolveCwd } from '../utils/env.js';\n\nconst shellwordsSplit = (shellwordsModule as { split: (str: string) => string[] }).split;\n\n/**\n * Build a safe environment for health check commands.\n * SECURITY: Never spread ...process.env — only pass system-essential variables\n * plus the service's explicit env config.\n */\nfunction buildHealthCheckEnv(serviceEnv: Record<string, string> = {}): Record<string, string> {\n const safeKeys = ['PATH', 'HOME', 'USER', 'SHELL', 'LANG', 'TERM', 'TMPDIR', 'TZ'];\n const env: Record<string, string> = {};\n for (const key of safeKeys) {\n if (process.env[key]) {\n env[key] = process.env[key]!;\n }\n }\n return { ...env, ...serviceEnv };\n}\n\ninterface HealthResult {\n processId: string;\n status: 'healthy' | 'unhealthy' | 'unknown';\n lastCheck: Date;\n consecutiveFailures: number;\n}\n\nclass HealthChecker extends EventEmitter {\n private timers: Map<string, ReturnType<typeof setInterval>> = new Map();\n private results: Map<string, HealthResult> = new Map();\n private failureCounts: Map<string, number> = new Map();\n private initialTimers: Map<string, ReturnType<typeof setTimeout>> = new Map();\n\n constructor() {\n super();\n // Allow many listeners since ProcessManager instances register on this singleton\n this.setMaxListeners(50);\n }\n\n /** Start health checking for a process */\n startChecking(processId: string): void {\n const proc = processStore.get(processId);\n if (!proc) return;\n const healthConfig = proc.serviceConfig.healthCheck;\n if (!healthConfig) return;\n\n const type = healthConfig.type ?? 'http';\n\n // Validate required fields based on type\n if (type === 'http' && !healthConfig.path) return;\n if (type === 'command' && !healthConfig.command) return;\n\n // Stop existing timer if any\n this.stopChecking(processId);\n\n this.results.set(processId, {\n processId,\n status: 'unknown',\n lastCheck: new Date(),\n consecutiveFailures: 0,\n });\n this.failureCounts.set(processId, 0);\n\n const interval = healthConfig.interval ?? HEALTH_CHECK_INTERVAL;\n const timeout = healthConfig.timeout ?? 5_000;\n const maxRetries = healthConfig.retries ?? 3;\n const initialDelay = healthConfig.initialDelay ?? HEALTH_CHECK_INITIAL_DELAY;\n\n const runCheck = type === 'command'\n ? () => this.checkCommand(processId, healthConfig.command!, timeout, maxRetries)\n : () => this.checkHttp(processId, healthConfig.path!, timeout, maxRetries, healthConfig.method ?? 'GET', healthConfig.expectedStatus ?? 200);\n\n // Initial check after a configurable delay (let process start)\n const initialTimer = setTimeout(runCheck, initialDelay);\n this.initialTimers.set(processId, initialTimer);\n\n // Periodic checks\n const timer = setInterval(runCheck, interval);\n this.timers.set(processId, timer);\n }\n\n /** Stop health checking for a process */\n stopChecking(processId: string): void {\n const timer = this.timers.get(processId);\n if (timer) {\n clearInterval(timer);\n this.timers.delete(processId);\n }\n const initialTimer = this.initialTimers.get(processId);\n if (initialTimer) {\n clearTimeout(initialTimer);\n this.initialTimers.delete(processId);\n }\n this.failureCounts.delete(processId);\n this.results.delete(processId);\n }\n\n /** Get current health result */\n getHealthResult(processId: string): HealthResult | null {\n return this.results.get(processId) ?? null;\n }\n\n /** Get health status string */\n getHealthStatus(processId: string): 'healthy' | 'unhealthy' | 'unknown' {\n return this.results.get(processId)?.status ?? 'unknown';\n }\n\n /** Stop all health checks */\n stopAll(): void {\n for (const id of this.timers.keys()) {\n this.stopChecking(id);\n }\n }\n\n private async checkHttp(\n processId: string,\n path: string,\n timeout: number,\n maxRetries: number,\n method: string = 'GET',\n expectedStatus: number = 200,\n ): Promise<void> {\n const proc = processStore.get(processId);\n if (!proc || proc.state !== 'running') {\n this.updateResult(processId, 'unknown', 0);\n return;\n }\n\n const port = proc.serviceConfig.ports?.[0];\n if (!port) {\n // No port configured, can't health check\n this.updateResult(processId, 'unknown', 0);\n return;\n }\n\n const url = `http://localhost:${port}${path}`;\n let failures = this.failureCounts.get(processId) ?? 0;\n\n try {\n const response = await fetch(url, {\n method,\n signal: AbortSignal.timeout(timeout),\n });\n if (response.status === expectedStatus) {\n failures = 0;\n this.failureCounts.set(processId, 0);\n this.updateResult(processId, 'healthy', failures);\n } else {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n }\n } catch {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n }\n }\n\n private async checkCommand(\n processId: string,\n command: string,\n timeout: number,\n maxRetries: number,\n ): Promise<void> {\n const proc = processStore.get(processId);\n if (!proc || proc.state !== 'running') {\n this.updateResult(processId, 'unknown', 0);\n return;\n }\n\n let failures = this.failureCounts.get(processId) ?? 0;\n\n try {\n const args: string[] = shellwordsSplit(command);\n const cmd = args.shift();\n if (!cmd) {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n return;\n }\n\n const serviceEnv = proc.serviceConfig.env ?? {};\n const cwd = resolveCwd(proc.serviceConfig.resolvedCwd ?? proc.serviceConfig.cwd, serviceEnv);\n const env = buildHealthCheckEnv(serviceEnv);\n const result = await execa(cmd, args, {\n cwd,\n env,\n shell: false,\n timeout,\n reject: false,\n });\n\n if (result.exitCode === 0) {\n failures = 0;\n this.failureCounts.set(processId, 0);\n this.updateResult(processId, 'healthy', failures);\n } else {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n }\n } catch {\n failures++;\n this.failureCounts.set(processId, failures);\n const status = failures >= maxRetries ? 'unhealthy' : 'unknown';\n this.updateResult(processId, status, failures);\n }\n }\n\n private updateResult(\n processId: string,\n status: 'healthy' | 'unhealthy' | 'unknown',\n consecutiveFailures: number,\n ): void {\n const result: HealthResult = {\n processId,\n status,\n lastCheck: new Date(),\n consecutiveFailures,\n };\n this.results.set(processId, result);\n this.emit('health', result);\n }\n}\n\nexport const healthChecker = new HealthChecker();\n","import { homedir } from 'node:os';\nimport { resolvePassthroughEnv } from '../trpc/routers/config.js';\n\n/**\n * Merge passthrough env (server-pushed) with an optional per-service env.\n * Priority: serviceEnv > passthroughEnv.\n */\nexport function resolveEnv(serviceEnv?: Record<string, string>): Record<string, string> {\n return { ...resolvePassthroughEnv(), ...serviceEnv };\n}\n\n/**\n * Expand $VAR, ${VAR}, and leading ~ in a string using resolveEnv(serviceEnv).\n * Unresolved references are left as-is.\n */\nexport function expandEnvVar(str: string, serviceEnv?: Record<string, string>): string {\n const env = resolveEnv(serviceEnv);\n return str\n .replace(/^~(\\/|$)/, `${env['HOME'] ?? homedir()}$1`)\n .replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (match, braced, plain) => env[braced ?? plain] ?? match);\n}\n\n/** Resolve a cwd string: expand env vars, fallback to '.' if empty/undefined. */\nexport function resolveCwd(cwd: string | undefined, serviceEnv?: Record<string, string>): string {\n if (!cwd) return '.';\n return expandEnvVar(cwd, serviceEnv) || '.';\n}\n","import { z } from 'zod';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { traefikManager } from '../../services/traefik-manager.js';\nimport { TraefikConfigSchema } from '@runeya/packages-shared';\n\n// In-memory passthrough state — set by server, read by process-manager\nlet passthroughEnvNames: string[] = [];\nlet passthroughEnvValues: Record<string, string> = {};\n\n/**\n * Resolve passthrough env: uses server-pushed values first,\n * falls back to agent's own process.env for each configured name.\n */\nexport function resolvePassthroughEnv(): Record<string, string> {\n const result: Record<string, string> = {};\n for (const name of passthroughEnvNames) {\n const value = passthroughEnvValues[name] ?? process.env[name];\n if (value !== undefined) {\n result[name] = value;\n }\n }\n return result;\n}\n\nexport const configRouter = router({\n setPassthroughEnv: protectedProcedure\n .input(z.object({\n names: z.array(\n z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(256),\n ).max(100),\n values: z.record(\n z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(256),\n z.string().max(32768),\n ).refine(obj => Object.keys(obj).length <= 100, 'Too many values').optional(),\n }))\n .mutation(({ input }) => {\n passthroughEnvNames = input.names;\n passthroughEnvValues = input.values ?? {};\n console.log(`[config] Passthrough env updated: ${input.names.length} variable(s), ${Object.keys(passthroughEnvValues).length} resolved value(s)`);\n return { success: true };\n }),\n\n getPassthroughEnv: protectedProcedure\n .query(() => {\n return resolvePassthroughEnv();\n }),\n\n setTraefikConfig: protectedProcedure\n .input(TraefikConfigSchema)\n .mutation(async ({ input }) => {\n await traefikManager.applyConfig(input);\n console.log(`[config] Traefik config applied: enabled=${input.enabled}`);\n return { success: true };\n }),\n\n getTraefikStatus: protectedProcedure\n .query(async () => {\n return traefikManager.getStatus();\n }),\n\n initTraefikConfig: protectedProcedure\n .input(TraefikConfigSchema)\n .mutation(({ input }) => {\n traefikManager.setConfig(input);\n return { success: true };\n }),\n\n restartTraefik: protectedProcedure\n .mutation(async () => {\n await traefikManager.restart();\n return { success: true };\n }),\n\n renewTraefikCert: protectedProcedure\n .mutation(async () => {\n await traefikManager.forceRenewCert();\n return { success: true };\n }),\n\n getTraefikConfigFiles: protectedProcedure\n .query(async () => {\n return traefikManager.getConfigFiles();\n }),\n\n getTraefikFileTree: protectedProcedure\n .query(async () => {\n return traefikManager.getFileTree();\n }),\n\n getTraefikLogs: protectedProcedure\n .input(z.object({ lines: z.number().int().min(1).max(500).default(100) }))\n .query(async ({ input }) => {\n const logs = await traefikManager.getLogs(input.lines);\n return { logs };\n }),\n});\n","import { spawn, execFile } from 'node:child_process';\nimport type { ChildProcess } from 'node:child_process';\nimport { mkdir, writeFile, rename, chmod, access, readFile } from 'node:fs/promises';\nimport { X509Certificate } from 'node:crypto';\nimport { join } from 'node:path';\nimport { homedir, platform } from 'node:os';\nimport { processStore } from './process-store.js';\n\ninterface TraefikConfig {\n enabled: boolean;\n acmeEmail?: string;\n wildcardDomain?: string;\n httpPort?: number;\n httpsPort?: number;\n dnsProvider?: string;\n dnsCredentials?: Record<string, string>;\n acmeStaging?: boolean;\n}\n\nclass TraefikManager {\n private process: ChildProcess | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private config: TraefikConfig | null = null;\n private dataDir: string = join(homedir(), '.runeya');\n\n private get traefikDir(): string {\n return join(this.dataDir, 'traefik');\n }\n\n private get dynamicDir(): string {\n return join(this.traefikDir, 'dynamic');\n }\n\n private get staticConfigPath(): string {\n return join(this.traefikDir, 'traefik.yml');\n }\n\n private get dynamicConfigPath(): string {\n return join(this.dynamicDir, 'services.yml');\n }\n\n private get acmeStorePath(): string {\n return join(this.traefikDir, 'acme.json');\n }\n\n private async atomicWrite(filePath: string, content: string): Promise<void> {\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, content, 'utf-8');\n await rename(tmpPath, filePath);\n }\n\n async applyConfig(config: TraefikConfig): Promise<void> {\n this.config = config;\n\n if (!config.enabled) {\n await this.stop();\n return;\n }\n\n await mkdir(this.dynamicDir, { recursive: true });\n await this.writeStaticConfig(config);\n await this.regenerateDynamic();\n\n // Restart container with new config\n await this.stop();\n await this.spawnTraefik(config);\n }\n\n /**\n * Escape a string for safe embedding inside a YAML double-quoted scalar.\n * Removes control characters (including newlines) and escapes backslashes and double-quotes.\n */\n private safeYamlStr(value: string): string {\n return value\n .replaceAll(/[\\x00-\\x1f\\x7f]/g, '') // strip control chars / newlines\n .replaceAll('\\\\', '\\\\\\\\') // escape backslashes\n .replaceAll('\"', '\\\\\"'); // escape double-quotes\n }\n\n private async writeStaticConfig(config: TraefikConfig): Promise<void> {\n const acmeEmail = this.safeYamlStr(config.acmeEmail ?? '');\n const dnsProvider = this.safeYamlStr(config.dnsProvider ?? '');\n\n const yaml = [\n `entryPoints:`,\n ` web:`,\n ` address: \":80\"`,\n ` http:`,\n ` redirections:`,\n ` entryPoint:`,\n ` to: websecure`,\n ` scheme: https`,\n ` websecure:`,\n ` address: \":443\"`,\n ``,\n `certificatesResolvers:`,\n ` letsencrypt:`,\n ` acme:`,\n ` email: \"${acmeEmail}\"`,\n ` storage: \"/acme.json\"`,\n ` dnsChallenge:`,\n ` provider: \"${dnsProvider}\"`,\n ...(config.acmeStaging ? [` caServer: \"https://acme-staging-v02.api.letsencrypt.org/directory\"`] : []),\n ``,\n `providers:`,\n ` file:`,\n ` directory: \"/etc/traefik/dynamic\"`,\n ` watch: true`,\n ].join('\\n');\n\n await this.atomicWrite(this.staticConfigPath, yaml);\n }\n\n async regenerateDynamic(): Promise<void> {\n await mkdir(this.dynamicDir, { recursive: true });\n const processes = processStore.getAll();\n const entries = processes.flatMap(p =>\n (p.serviceConfig.localUrls ?? []).map(lu => ({ url: lu.url, port: lu.port }))\n );\n\n // Sanitize wildcardDomain: only allow valid hostname characters.\n const wildcardDomainRaw = this.config?.wildcardDomain?.replace(/^\\*\\./, '');\n const wildcardDomain = wildcardDomainRaw?.replaceAll(/[^a-z0-9.-]/gi, '') || undefined;\n if (wildcardDomainRaw && wildcardDomain !== wildcardDomainRaw) {\n console.warn('[traefik-manager] wildcardDomain contained unsafe characters and was rejected');\n }\n const backendHost = platform() === 'linux' ? '127.0.0.1' : 'host.docker.internal';\n\n const routers: string[] = [];\n const backends: string[] = [];\n\n // Inject a permanent wildcard route so Traefik always requests the wildcard cert via DNS-01,\n // even when no user services have localUrls configured yet.\n if (wildcardDomain) {\n routers.push(\n ` acme-wildcard:`,\n ` rule: \"Host(\\`probe.${wildcardDomain}\\`)\"`,\n ` entryPoints:`,\n ` - websecure`,\n ` service: acme-wildcard`,\n ` tls:`,\n ` certResolver: letsencrypt`,\n ` domains:`,\n ` - main: \"*.${wildcardDomain}\"`,\n );\n backends.push(\n ` acme-wildcard:`,\n ` loadBalancer:`,\n ` servers:`,\n ` - url: \"http://${backendHost}:1\"`,\n );\n }\n\n for (const { url, port } of entries) {\n // Sanitize url: only allow valid hostname characters (letters, digits, dots, hyphens)\n // to prevent YAML/Traefik rule injection via crafted service localUrls.\n const safeUrl = url.replaceAll(/[^a-z0-9.-]/gi, '');\n if (!safeUrl || safeUrl !== url) {\n console.warn(`[traefik-manager] Skipping localUrl with unsafe characters: ${url}`);\n continue;\n }\n const routerName = url.replaceAll(/[^a-z0-9]/gi, '-');\n // Extract the root domain to reuse the wildcard cert (e.g. test.local.runeya.dev → *.local.runeya.dev)\n const parts = url.split('.');\n const wildcardForUrl = parts.length >= 2 ? `*.${parts.slice(1).join('.')}` : null;\n routers.push(\n ` ${routerName}:`,\n ` rule: \"Host(\\`${safeUrl}\\`)\"`,\n ` entryPoints:`,\n ` - websecure`,\n ` service: ${routerName}`,\n ` tls:`,\n ` certResolver: letsencrypt`,\n ...(wildcardForUrl ? [\n ` domains:`,\n ` - main: \"${wildcardForUrl}\"`,\n ] : []),\n );\n backends.push(\n ` ${routerName}:`,\n ` loadBalancer:`,\n ` servers:`,\n ` - url: \"http://${backendHost}:${port}\"`,\n );\n }\n\n if (routers.length === 0) {\n await this.atomicWrite(this.dynamicConfigPath, '');\n return;\n }\n\n const yaml = [\n `http:`,\n ` routers:`,\n ...routers,\n ` services:`,\n ...backends,\n ].join('\\n');\n\n await this.atomicWrite(this.dynamicConfigPath, yaml);\n }\n\n scheduleDynamicRegen(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n this.regenerateDynamic().catch(err =>\n console.error('[traefik-manager] Failed to regenerate dynamic config:', err),\n );\n this.debounceTimer = null;\n }, 500);\n }\n\n private async ensureAcmeJson(): Promise<void> {\n try {\n await writeFile(this.acmeStorePath, '{}', { flag: 'wx' });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n }\n await chmod(this.acmeStorePath, 0o600);\n }\n\n private spawnedAt = 0;\n\n private async spawnTraefik(config: TraefikConfig): Promise<void> {\n const credentials = config.dnsCredentials ?? {};\n const envFlags = Object.entries(credentials).flatMap(([k, v]) => ['-e', `${k}=${v}`]);\n\n await this.ensureAcmeJson();\n\n const generation = ++this.spawnedAt;\n\n const isLinux = platform() === 'linux';\n const networkArgs = isLinux\n ? ['--network', 'host']\n : ['-p', `${config.httpPort ?? 80}:80`, '-p', `${config.httpsPort ?? 443}:443`, '--add-host', 'host.docker.internal:host-gateway'];\n\n const args = [\n 'run', '--rm',\n '--name', 'runeya-traefik',\n ...networkArgs,\n '-v', `${this.traefikDir}:/etc/traefik`,\n '-v', `${this.acmeStorePath}:/acme.json`,\n ...envFlags,\n 'traefik:v3',\n ];\n\n this.process = spawn('docker', args, {\n windowsHide: true,\n shell: false,\n detached: false,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n this.process.stdout?.on('data', (data: Buffer) => {\n console.log('[traefik]', data.toString().trim());\n });\n\n this.process.stderr?.on('data', (data: Buffer) => {\n console.error('[traefik]', data.toString().trim());\n });\n\n this.process.on('error', (err) => {\n if (generation !== this.spawnedAt) return;\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n console.error('[traefik-manager] docker not found in PATH. Is Docker installed?');\n } else {\n console.error('[traefik-manager] Traefik container error:', err);\n }\n this.process = null;\n });\n\n this.process.on('exit', (code) => {\n if (generation !== this.spawnedAt) return;\n console.log(`[traefik-manager] Traefik container exited with code ${code}`);\n this.process = null;\n });\n\n console.log('[traefik-manager] Traefik container started (--network host)');\n }\n\n async stop(): Promise<void> {\n // Invalidate current generation so stale exit handlers don't null out the new process\n this.spawnedAt++;\n if (this.process) {\n this.process.kill('SIGTERM');\n this.process = null;\n }\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n // Force-remove the container whether it was started by us or externally\n await new Promise<void>((resolve) => {\n execFile('docker', ['rm', '-f', 'runeya-traefik'], { timeout: 10000, windowsHide: true }, () => resolve());\n });\n // Brief pause to let the port release before a potential restart\n await new Promise(resolve => setTimeout(resolve, 500));\n }\n\n async getConfigFiles(): Promise<{ static: string; dynamic: string }> {\n const [staticContent, dynamicContent] = await Promise.all([\n readFile(this.staticConfigPath, 'utf-8').catch(() => '(fichier absent)'),\n readFile(this.dynamicConfigPath, 'utf-8').catch(() => '(fichier absent)'),\n ]);\n return { static: staticContent, dynamic: dynamicContent };\n }\n\n async getFileTree(): Promise<Array<{ path: string; content: string }>> {\n const result: Array<{ path: string; content: string }> = [];\n const walk = async (dir: string, base: string) => {\n let entries: string[];\n try {\n const { readdir } = await import('node:fs/promises');\n entries = await readdir(dir);\n } catch { return; }\n for (const entry of entries) {\n const full = join(dir, entry);\n const rel = join(base, entry);\n try {\n const { stat } = await import('node:fs/promises');\n const s = await stat(full);\n if (s.isDirectory()) {\n await walk(full, rel);\n } else {\n const content = await readFile(full, 'utf-8').catch(() => '(lecture impossible)');\n result.push({ path: rel, content });\n }\n } catch { /* skip */ }\n }\n };\n await walk(this.traefikDir, '');\n return result;\n }\n\n async getLogs(lines = 100): Promise<string> {\n return new Promise((resolve) => {\n execFile('docker', ['logs', '--tail', String(lines), 'runeya-traefik'], { timeout: 10000, windowsHide: true }, (err, stdout, stderr) => {\n if (err) { resolve(''); return; }\n // Docker writes its own logs to stderr by default\n resolve((stdout + stderr).trim());\n });\n });\n }\n\n setConfig(config: TraefikConfig): void {\n this.config = config;\n }\n\n async restart(): Promise<void> {\n if (!this.config?.enabled) throw new Error('Traefik non activé');\n await this.stop();\n await this.spawnTraefik(this.config);\n }\n\n async forceRenewCert(): Promise<void> {\n if (!this.config?.enabled) throw new Error('Traefik non activé');\n // Wipe acme.json so Traefik re-requests a certificate on next start\n await writeFile(this.acmeStorePath, '{}', 'utf-8');\n await chmod(this.acmeStorePath, 0o600);\n // Restart container\n await this.stop();\n await this.spawnTraefik(this.config);\n }\n\n isEnabled(): boolean {\n return this.config?.enabled ?? false;\n }\n\n private async checkAcmeCert(): Promise<{\n hasCert: boolean;\n domain: string | null;\n expiresAt: string | null;\n daysLeft: number | null;\n expired: boolean;\n }> {\n const wildcardDomain = this.config?.wildcardDomain?.replace(/^\\*\\./, '') ?? null;\n try {\n const raw = await readFile(this.acmeStorePath, 'utf-8');\n const acme = JSON.parse(raw) as Record<string, {\n Certificates?: Array<{ domain: { main: string }; certificate: string }>;\n }>;\n\n const allCerts = Object.values(acme).flatMap(r => r.Certificates ?? []);\n if (allCerts.length === 0) return { hasCert: false, domain: wildcardDomain, expiresAt: null, daysLeft: null, expired: false };\n\n // Find cert matching wildcardDomain\n const match = wildcardDomain\n ? allCerts.find(c => c.domain.main === `*.${wildcardDomain}` || c.domain.main === wildcardDomain)\n : allCerts[0];\n\n if (!match) return { hasCert: false, domain: wildcardDomain, expiresAt: null, daysLeft: null, expired: false };\n\n // certificate field is base64-encoded PEM (full chain) — decode first\n const pem = Buffer.from(match.certificate, 'base64').toString('utf-8');\n // Extract just the first cert from the chain for X509Certificate parsing\n const firstCert = pem.match(/(-----BEGIN CERTIFICATE-----[\\s\\S]+?-----END CERTIFICATE-----)/)?.[1] ?? pem;\n const cert = new X509Certificate(firstCert);\n const expiresAt = cert.validTo;\n const expiresDate = new Date(expiresAt);\n const daysLeft = Math.floor((expiresDate.getTime() - Date.now()) / 86_400_000);\n\n return { hasCert: true, domain: match.domain.main, expiresAt, daysLeft, expired: daysLeft < 0 };\n } catch {\n return { hasCert: false, domain: wildcardDomain, expiresAt: null, daysLeft: null, expired: false };\n }\n }\n\n async getStatus(): Promise<{\n containerRunning: boolean;\n dockerAvailable: boolean;\n configFileExists: boolean;\n cert: { hasCert: boolean; domain: string | null; expiresAt: string | null; daysLeft: number | null; expired: boolean };\n }> {\n // Check Docker availability\n let dockerAvailable = false;\n try {\n await new Promise<void>((resolve, reject) => {\n execFile('docker', ['info', '--format', '{{.ServerVersion}}'], { timeout: 5000, windowsHide: true }, (err) => {\n if (err) reject(err instanceof Error ? err : new Error('docker info failed')); else resolve();\n });\n });\n dockerAvailable = true;\n } catch {\n dockerAvailable = false;\n }\n\n // Check static config file exists\n let configFileExists = false;\n try {\n await access(this.staticConfigPath);\n configFileExists = true;\n } catch {\n configFileExists = false;\n }\n\n // Check container running\n let containerRunning = false;\n if (dockerAvailable) {\n try {\n const output = await new Promise<string>((resolve, reject) => {\n execFile('docker', ['inspect', '--format', '{{.State.Running}}', 'runeya-traefik'], { timeout: 5000, windowsHide: true }, (err, stdout) => {\n if (err) reject(err instanceof Error ? err : new Error('docker inspect failed')); else resolve(stdout.trim());\n });\n });\n containerRunning = output === 'true';\n } catch {\n containerRunning = false;\n }\n }\n\n const cert = await this.checkAcmeCert();\n return { containerRunning, dockerAvailable, configFileExists, cert };\n }\n}\n\nexport const traefikManager = new TraefikManager();\n","import { z } from 'zod';\nimport {\n LOG_BUFFER_SIZE,\n METRICS_INTERVAL,\n GRACE_PERIOD,\n HEALTH_WS_INTERVAL,\n} from '@runeya/packages-shared';\n\nconst EnvSchema = z.object({\n RUNEYA_AGENT_PORT: z.coerce.number().int().min(1).max(65535).default(4001),\n RUNEYA_AGENT_HOST: z.string().default('127.0.0.1'),\n PASSPHRASE_OVERRIDE: z.string().regex(/^[0-9a-f]+$/i, 'Must be a hex string').optional(),\n AGENT_ID: z.string().optional(), // Set by spawner or manually for remote agents\n LOG_BUFFER_SIZE: z.coerce.number().int().positive().default(LOG_BUFFER_SIZE),\n METRICS_INTERVAL: z.coerce.number().int().positive().default(METRICS_INTERVAL),\n GRACE_PERIOD: z.coerce.number().int().positive().default(GRACE_PERIOD),\n HEALTH_WS_INTERVAL: z.coerce.number().int().positive().default(HEALTH_WS_INTERVAL),\n});\n\nexport const env = EnvSchema.parse(process.env);\n","import { router, protectedProcedure } from '../trpc.js';\nimport { processManager } from '../../services/process-manager.js';\nimport { networkInterfaces, homedir, platform } from 'node:os';\nimport { isCliAvailable } from '@runeya/packages-shared/node';\n\nconst startedAt = Date.now();\n\nfunction getLanIp(): string {\n const nets = networkInterfaces();\n for (const name of Object.keys(nets)) {\n for (const net of nets[name] ?? []) {\n if (net.family === 'IPv4' && !net.internal) {\n return net.address;\n }\n }\n }\n return '127.0.0.1';\n}\n\nexport async function getHealthData() {\n const runners = await processManager.getAvailableRunners();\n const processes = processManager.listStatuses();\n\n return {\n status: 'ok' as const,\n uptime: Math.floor((Date.now() - startedAt) / 1000),\n runnersAvailable: runners,\n processCount: processes.length,\n runningCount: processes.filter(p => p.state === 'running').length,\n lanIp: getLanIp(),\n // Ce qui décrit la machine, pour que l'interface puisse montrer la valeur\n // qu'aura `{{agent.OS}}`, `{{agent.HOME}}`, `{{service.CWD}}` AVANT que le\n // service ne démarre. La résolution, elle, reste faite ici au lancement :\n // ce statut n'est qu'un cliché, et l'agent reste l'autorité sur sa machine.\n os: platform(),\n home: homedir(),\n cwd: process.cwd(),\n };\n}\n\nexport const healthRouter = router({\n /** Health check - returns agent status */\n check: protectedProcedure\n .query(() => getHealthData()),\n\n /** Check which AI CLIs are available on this agent */\n checkCli: protectedProcedure\n .query(async () => {\n const [claudeOk, codexOk] = await Promise.all([\n isCliAvailable('claude'),\n isCliAvailable('codex'),\n ]);\n return { claudeAvailable: claudeOk, codexAvailable: codexOk };\n }),\n});\n","import { dirname, delimiter } from 'node:path';\n\n/**\n * Garantit que le répertoire du binaire Node est dans le `PATH` des services.\n *\n * Un raccourci de bureau n'hérite pas du `PATH` d'un shell de connexion : il\n * reçoit celui de la session graphique, où les gestionnaires de version (n, nvm,\n * fnm, volta, brew) ne figurent pas. Node, lui, est lancé par chemin absolu et\n * démarre très bien — mais `npm`, `npx`, `yarn` et `corepack`, qui vivent à côté\n * de lui, deviennent introuvables. Un service échoue alors sur un message qui ne\n * dit rien de sa cause : « cannot find package manager binary ».\n *\n * Le répertoire est REMONTÉ en tête. Y être présent ne suffit pas : un poste où\n * `/usr/bin/node` est un Node système ancien le résoudrait avant le nôtre, et le\n * service démarrerait sur la mauvaise version sans rien signaler. Un lanceur de\n * bureau transmet volontiers un `PATH` qui contient déjà tout — dans le\n * désordre — et un simple ajout n'y changerait alors rien.\n */\nexport function ensureNodeBinOnPath(environment: NodeJS.ProcessEnv = process.env): void {\n promoteOnPath(dirname(process.execPath), environment);\n}\n\n/**\n * Ajoute un répertoire en queue du `PATH`, sans doublon ni séparateur vide.\n */\nexport function appendToPath(dir: string, environment: NodeJS.ProcessEnv = process.env): void {\n if (!dir) return;\n const current = environment['PATH'] ?? '';\n const entries = current.split(delimiter).filter(Boolean);\n if (entries.includes(dir)) return;\n environment['PATH'] = entries.length > 0 ? `${current}${delimiter}${dir}` : dir;\n}\n\n/**\n * REMONTE un répertoire en tête du `PATH`, qu'il y figure déjà ou non.\n *\n * Réservé à ce dont on connaît la provenance : le Node qui nous exécute, le\n * `PATH` du shell de connexion. Contrairement à `appendToPath`, une entrée déjà\n * présente n'est pas laissée où elle est : elle est retirée de sa position puis\n * remise devant — sans quoi la correction serait inerte là où elle compte le\n * plus. Un lanceur de bureau peut transmettre un `PATH` contenant déjà nvm,\n * `~/.local/bin` et le reste, tous relégués derrière `/usr/bin` : rien n'y\n * manque, tout y est mal placé.\n *\n * Les doublons du répertoire visé disparaissent au passage — il n'en reste\n * qu'une occurrence, en tête.\n */\nexport function promoteOnPath(dir: string, environment: NodeJS.ProcessEnv = process.env): void {\n if (!dir) return;\n const current = environment['PATH'] ?? '';\n const others = current.split(delimiter).filter(Boolean).filter(entry => entry !== dir);\n environment['PATH'] = [dir, ...others].join(delimiter);\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { homedir } from 'node:os';\nimport { existsSync, statSync } from 'node:fs';\nimport { join, delimiter } from 'node:path';\nimport { appendToPath, promoteOnPath } from './node-path.js';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Marqueur : un `.zshrc` interactif écrit volontiers sur stdout (bannières,\n * gestionnaires de version, `motd`). Sans balise, on ne sait pas quelle ligne\n * est le `PATH`.\n */\nconst MARKER = '__RUNEYA_PATH__';\n\n/** Le profil de l'utilisateur peut être long à charger — mais pas éternel. */\nconst SHELL_TIMEOUT_MS = 3000;\n\n/**\n * Emplacements où un CLI utilisateur s'installe sans passer par le système.\n * Filet de sécurité quand le shell de connexion n'a rien donné : on ne devine\n * pas les gestionnaires de version (chemins versionnés), seulement le banal.\n */\nfunction commonUserBins(home: string): string[] {\n return [\n join(home, '.local', 'bin'),\n join(home, 'bin'),\n join(home, '.npm-global', 'bin'),\n join(home, '.bun', 'bin'),\n join(home, '.cargo', 'bin'),\n '/opt/homebrew/bin',\n '/usr/local/bin',\n ];\n}\n\n/**\n * Demande son `PATH` au shell de connexion de l'utilisateur.\n *\n * Un raccourci de bureau reçoit le `PATH` de la session graphique, pas celui du\n * shell : `~/.local/bin`, nvm, fnm, volta, mise, asdf… n'y figurent pas. Le CLI\n * installé par l'utilisateur devient alors introuvable, et l'agent le déclare\n * simplement « non disponible ».\n *\n * Renvoie `null` en cas d'échec (Windows, pas de `SHELL`, timeout, profil qui\n * plante) : l'absence de réponse ne doit jamais empêcher l'agent de démarrer.\n */\nexport async function readLoginShellPath(): Promise<string | null> {\n if (process.platform === 'win32') return null;\n\n const shell = process.env['SHELL'];\n if (!shell || !existsSync(shell)) {\n warnProbeFailed(shell ? `shell introuvable : ${shell}` : 'SHELL absent de cet environnement');\n return null;\n }\n\n try {\n // `-l -i` : le `PATH` d'un utilisateur vit aussi bien dans le profil de\n // connexion que dans le fichier interactif (`.zshrc`, `.bashrc`).\n // `shell: false` : le shell EST le programme lancé, pas l'interpréteur.\n const { stdout } = await execFileAsync(shell, ['-l', '-i', '-c', `echo \"${MARKER}$PATH\"`], {\n timeout: SHELL_TIMEOUT_MS,\n shell: false,\n encoding: 'utf8',\n maxBuffer: 1024 * 1024,\n env: { ...process.env, TERM: 'dumb' },\n });\n\n const line = stdout.split('\\n').find(l => l.includes(MARKER));\n if (!line) {\n warnProbeFailed(`aucune ligne marquée dans la réponse de ${shell}`);\n return null;\n }\n\n const value = line.slice(line.indexOf(MARKER) + MARKER.length).trim();\n if (value.length === 0) {\n warnProbeFailed(`${shell} a répondu un PATH vide`);\n return null;\n }\n return value;\n } catch (err) {\n const reason = (err as { killed?: boolean }).killed\n ? `${shell} n'a pas répondu en ${SHELL_TIMEOUT_MS} ms`\n : `${shell} a échoué : ${err instanceof Error ? err.message : String(err)}`;\n warnProbeFailed(reason);\n return null;\n }\n}\n\n/**\n * Un échec muet ici se paie cher : les outils que l'utilisateur a installés pour\n * lui-même restent introuvables, et rien ne dit pourquoi. Le service démarre\n * alors sur une version qu'il n'a pas choisie, ou pas du tout.\n */\nfunction warnProbeFailed(reason: string): void {\n console.warn(`[path] PATH du shell de connexion non lu (${reason}) — les outils installés par l'utilisateur peuvent rester introuvables.`);\n}\n\n/**\n * Complète le `PATH` de l'agent avec ce que le shell de connexion connaît, puis\n * avec les emplacements utilisateur usuels qui existent réellement sur disque.\n *\n * Le `PATH` du shell passe EN TÊTE, comme pour Node. Le mettre en queue\n * revenait à ne rien faire là où ça comptait : sur un poste portant un Node\n * système en `/usr/bin`, celui-ci l'emportait sur la version choisie par\n * l'utilisateur (nvm, fnm, volta…), et le service démarrait sur la mauvaise\n * sans qu'aucun message ne le dise. Ce que l'utilisateur a choisi pour son\n * shell est ce qu'il attend de ses services.\n *\n * Les entrées du shell sont REMONTÉES, même déjà présentes : un lanceur de\n * bureau transmet parfois un `PATH` qui les contient toutes, reléguées derrière\n * `/usr/bin` — ajouter ce qui manque n'y changerait rien, il faut réordonner.\n *\n * Les emplacements usuels, eux, restent EN QUEUE : ce sont des devinettes, pas\n * une préférence exprimée, et ils ne délogent donc personne.\n */\nexport async function ensureUserBinsOnPath(\n environment: NodeJS.ProcessEnv = process.env,\n home: string = homedir(),\n): Promise<void> {\n const shellPath = await readLoginShellPath();\n if (shellPath) {\n // Parcours à l'envers : chaque entrée passe devant la précédente, donc\n // remonter la liste de la fin vers le début restitue son ordre d'origine.\n const entries = shellPath.split(delimiter).filter(Boolean);\n for (let i = entries.length - 1; i >= 0; i--) {\n promoteOnPath(entries[i]!, environment);\n }\n }\n\n for (const dir of commonUserBins(home)) {\n if (isDirectory(dir)) appendToPath(dir, environment);\n }\n}\n\nfunction isDirectory(path: string): boolean {\n try {\n return statSync(path).isDirectory();\n } catch {\n return false;\n }\n}\n","/**\n * Horodate ce que le process écrit sur la console, en temps écoulé depuis son\n * démarrage.\n *\n * Les 300 et quelques appels à `console.log` du serveur, de l'agent et du CLI\n * n'ont pas à être réécrits : on enveloppe `console` une fois, au démarrage, et\n * tout ce qui passe par lui est daté — jusqu'aux bibliothèques tierces.\n *\n * Le delta plutôt que l'heure : ces journaux servent surtout à comprendre ce qui\n * prend du temps au sein d'un même lancement, et « +1.204s » se lit sans\n * soustraction mentale. L'heure absolue reste disponible dans le journal\n * d'audit, qui, lui, sert à recouper avec le cloud.\n */\n\n/**\n * Une ligne qui ne dit rien à dater : une ligne vide, ou un morceau d'encadré.\n *\n * La bannière de démarrage est dessinée ligne à ligne ; un horodatage devant\n * chacune casse l'alignement des colonnes et n'apprend rien — elles sont toutes\n * écrites dans la même milliseconde.\n */\nfunction isDecorative(args: unknown[]): boolean {\n if (args.length === 0) return true;\n const first = args[0];\n if (typeof first !== 'string') return false;\n const trimmed = first.trim();\n return trimmed === '' || /^[┌│└├┬┴┼─┐┘┤]/.test(trimmed);\n}\n\nconst LEVELS = ['log', 'info', 'warn', 'error', 'debug'] as const;\n\n/** Le temps écoulé, cadré pour que les lignes s'alignent en colonne. */\nfunction formatElapsed(startedAt: number, now: number): string {\n const seconds = (now - startedAt) / 1000;\n return `+${seconds.toFixed(3)}s`.padStart(10);\n}\n\n/**\n * Enveloppe `console`. Rend une fonction qui remet l'original en place — les\n * tests en ont besoin, et un mode dont la sortie est lue par un script aussi.\n *\n * Appelé deux fois, le second appel ne fait rien : sans cette garde, deux\n * horodatages se cumuleraient sur chaque ligne.\n */\nexport function stampConsole(startedAt: number = Date.now()): () => void {\n const target = console as unknown as Record<string, unknown> & { __runeyaStamped?: boolean };\n if (target.__runeyaStamped) return () => {};\n target.__runeyaStamped = true;\n\n const originals = LEVELS.map((level) => {\n const original = console[level].bind(console);\n console[level] = (...args: unknown[]) => (\n isDecorative(args)\n ? original(...args)\n : original(formatElapsed(startedAt, Date.now()), ...args)\n );\n return [level, original] as const;\n });\n\n return () => {\n for (const [level, original] of originals) console[level] = original;\n target.__runeyaStamped = false;\n };\n}\n","import { execFile, execFileSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, resolve as resolvePath } from 'node:path';\n\nexport interface CliInvocation {\n command: string;\n args: string[];\n}\n\n/**\n * Comment lancer un CLI global (`claude`, `codex`) sur la plateforme courante.\n *\n * Windows : un CLI installé globalement par npm n'est pas un `.exe` mais un\n * shim `claude.cmd`. Ni `child_process.spawn(..., { shell: false })` ni\n * `pty.spawn()` ne savent le lancer — node-pty échoue sur « File not found:\n * claude ». Passer par `cmd.exe /c` fonctionnerait mais abîme les arguments\n * (le prompt système contient guillemets, retours à la ligne et `%`), donc on\n * résout le point d'entrée JS visé par le shim et on le lance avec le `node`\n * courant.\n *\n * Sur POSIX la commande est rendue telle quelle : rien ne change pour Linux\n * ni macOS.\n */\nexport function resolveCliInvocation(cli: string, args: string[] = []): CliInvocation {\n if (process.platform !== 'win32') return { command: cli, args };\n if (/\\.exe$/i.test(cli)) return { command: cli, args };\n\n // 1. Localiser le shim sur le PATH (sauf si un chemin explicite est donné).\n let shim = cli;\n if (!cli.includes('\\\\') && !cli.includes('/')) {\n let found: string[] = [];\n try {\n // Borné : un `where` qui ne rend pas la main figerait le process appelant,\n // puisque la résolution est synchrone.\n found = execFileSync('where', [cli], { encoding: 'utf-8', timeout: 5_000, windowsHide: true })\n .split(/\\r?\\n/).map((l) => l.trim()).filter(Boolean);\n } catch { /* absent du PATH — laisser le spawn échouer avec son propre message */ }\n const exe = found.find((f) => /\\.exe$/i.test(f));\n if (exe) return { command: exe, args };\n shim = found.find((f) => /\\.cmd$/i.test(f)) ?? found[0] ?? cli;\n }\n if (/\\.exe$/i.test(shim)) return { command: shim, args };\n\n // 2. Extraire le point d'entrée `.js` du shim npm et le lancer avec node.\n if (/\\.cmd$/i.test(shim) && existsSync(shim)) {\n try {\n const content = readFileSync(shim, 'utf-8');\n // Les shims npm écrivent « %~dp0\\...\\cli.js » ; certains outils écrivent\n // « %~dp0%\\...\\cli.js ». Les deux formes mènent au même point d'entrée.\n const m = content.match(/%~?dp0%?\\\\?([^\"\\s]+\\.js)/i);\n if (m?.[1]) {\n const entry = resolvePath(dirname(shim), m[1].replace(/^\\\\+/, ''));\n if (existsSync(entry)) return { command: process.execPath, args: [entry, ...args] };\n }\n } catch { /* on retombe sur l'interpréteur de commandes */ }\n }\n\n // 3. Dernier recours : confier à l'interpréteur de commandes.\n const comspec = process.env['ComSpec'] || process.env['COMSPEC'] || 'cmd.exe';\n return { command: comspec, args: ['/d', '/s', '/c', shim, ...args] };\n}\n\n/**\n * La commande qui dit où vit un exécutable, selon la plateforme.\n *\n * `which` n'existe pas sur Windows ; une détection qui l'appelle y répond\n * toujours « absent », quel que soit l'outil installé.\n */\nexport function whichCommand(): string {\n return process.platform === 'win32' ? 'where' : 'which';\n}\n\n/**\n * `<cli> --version` répond-il ?\n *\n * Le même contrôle vivait côté serveur et côté agent, et les deux lançaient\n * `execFile('claude', …, { shell: false })` : sur Windows, un shim `.cmd` n'est\n * pas lançable ainsi, et la détection répondait « absent » pour un CLI\n * parfaitement installé — l'interface désactivait alors le runner.\n */\nexport async function isCliAvailable(cli: string, timeoutMs = 5_000): Promise<boolean> {\n const { command, args } = resolveCliInvocation(cli, ['--version']);\n return new Promise((resolve) => {\n execFile(command, args, { timeout: timeoutMs, windowsHide: true }, (err) => resolve(!err));\n });\n}\n","import { randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\n\nconst ALGORITHM = 'aes-256-gcm';\n\n/**\n * Encrypt under a caller-supplied key.\n *\n * The no-key forms in the server read the process keyring, which is the right default\n * everywhere except migration: converting a vault means holding two keys at\n * once, and neither of them is \"the\" current one.\n */\nexport function encryptValueWith(key: Buffer, plaintext: string): string {\n const iv = randomBytes(16);\n const cipher = createCipheriv(ALGORITHM, key, iv);\n let enc = cipher.update(plaintext, 'utf-8', 'hex');\n enc += cipher.final('hex');\n const authTag = cipher.getAuthTag().toString('hex');\n return `${iv.toString('hex')}:${authTag}:${enc}`;\n}\n\n/** Decrypt under a caller-supplied key. Throws when the key does not open it. */\nexport function decryptValueWith(key: Buffer, encrypted: string): string {\n const parts = encrypted.split(':');\n if (parts.length !== 3) throw new Error('Invalid encrypted value format — expected iv:authTag:ciphertext');\n const [ivHex, authTagHex, ciphertext] = parts;\n if (!/^[0-9a-f]+$/i.test(ivHex) || !/^[0-9a-f]+$/i.test(authTagHex) || (ciphertext !== '' && !/^[0-9a-f]+$/i.test(ciphertext))) {\n throw new Error('Invalid hex in encrypted value — possible data corruption');\n }\n const decipher = createDecipheriv(ALGORITHM, key, Buffer.from(ivHex, 'hex'), { authTagLength: 16 });\n decipher.setAuthTag(Buffer.from(authTagHex, 'hex'));\n let dec = decipher.update(ciphertext, 'hex', 'utf-8');\n dec += decipher.final('utf-8');\n return dec;\n}\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { terminalManager } from '../../services/terminal-manager.js';\n\nexport const terminalRouter = router({\n /** Spawn a new PTY shell session, returns a sessionId */\n create: protectedProcedure\n .input(z.object({\n cwd: z.string().max(512).optional(),\n cols: z.number().int().min(1).max(512).optional(),\n rows: z.number().int().min(1).max(256).optional(),\n title: z.string().max(128).optional(),\n }))\n .mutation(({ input }) => {\n const sessionId = terminalManager.create(input.cwd, input.cols, input.rows, input.title);\n return { sessionId };\n }),\n\n /** Les sessions encore vivantes : un onglet fermé côté web se retrouve ici */\n list: protectedProcedure\n .query(() => ({ sessions: terminalManager.list() })),\n\n /** Renommer un onglet */\n rename: protectedProcedure\n .input(z.object({ sessionId: z.string().max(128), title: z.string().max(128) }))\n .mutation(({ input }) => {\n terminalManager.rename(input.sessionId, input.title);\n return { ok: true as const };\n }),\n\n /** Write data (keystrokes) to a PTY session */\n write: protectedProcedure\n .input(z.object({ sessionId: z.string().max(128), data: z.string().max(65536) }))\n .mutation(({ input }) => {\n terminalManager.write(input.sessionId, input.data);\n return { ok: true as const };\n }),\n\n /** Resize a PTY session */\n resize: protectedProcedure\n .input(z.object({\n sessionId: z.string().max(128),\n cols: z.number().int().min(1).max(512),\n rows: z.number().int().min(1).max(256),\n }))\n .mutation(({ input }) => {\n terminalManager.resize(input.sessionId, input.cols, input.rows);\n return { ok: true as const };\n }),\n\n /** Destroy a PTY session */\n destroy: protectedProcedure\n .input(z.object({ sessionId: z.string().max(128) }))\n .mutation(({ input }) => {\n terminalManager.destroy(input.sessionId);\n return { ok: true as const };\n }),\n\n /** Stream PTY output for a session (async generator subscription) */\n onData: protectedProcedure\n .input(z.object({\n sessionId: z.string().max(128),\n /** Rejouer l'historique avant le flux : c'est ce qui rend l'onglet persistant. */\n replay: z.boolean().optional(),\n }))\n .subscription(async function* ({ input }) {\n const emitter = terminalManager.getEmitter(input.sessionId);\n if (!emitter) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Terminal session ${input.sessionId} not found` });\n }\n\n const queue: string[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n const onData = (data: string) => {\n queue.push(data);\n if (resolve) { resolve(); resolve = null; }\n };\n const onExit = () => {\n done = true;\n if (resolve) { resolve(); resolve = null; }\n };\n\n emitter.on('data', onData);\n emitter.on('exit', onExit);\n\n // L'historique est capturé avant tout `yield` : rien ne se perd entre les deux.\n const scrollback = input.replay ? terminalManager.getScrollback(input.sessionId) : '';\n if (scrollback) yield scrollback;\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n emitter.off('data', onData);\n emitter.off('exit', onExit);\n }\n }),\n});\n","import { EventEmitter } from 'node:events';\nimport os from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport * as pty from '@lydell/node-pty';\n\n/** Combien d'octets de sortie on garde pour rejouer un terminal réouvert. */\nconst SCROLLBACK_LIMIT = 256 * 1024;\n\nexport interface TerminalSessionInfo {\n sessionId: string;\n title: string;\n cwd: string;\n cols: number;\n rows: number;\n createdAt: number;\n}\n\ninterface TerminalSession {\n pty: pty.IPty;\n emitter: EventEmitter;\n /** Historique tronqué : ce qu'un onglet rouvert doit réafficher. */\n scrollback: string;\n info: TerminalSessionInfo;\n}\n\nclass TerminalManager {\n private sessions = new Map<string, TerminalSession>();\n\n create(cwd?: string, cols?: number, rows?: number, title?: string): string {\n const sessionId = randomUUID();\n const shell = process.env.SHELL ?? (os.platform() === 'win32' ? 'powershell.exe' : '/bin/bash');\n const resolvedCwd = cwd ?? process.cwd();\n const resolvedCols = cols ?? 80;\n const resolvedRows = rows ?? 24;\n\n const term = pty.spawn(shell, [], {\n name: 'xterm-256color',\n cols: resolvedCols,\n rows: resolvedRows,\n cwd: resolvedCwd,\n env: process.env as Record<string, string>,\n });\n\n const emitter = new EventEmitter();\n // Plusieurs vues web peuvent écouter la même session au fil des navigations.\n emitter.setMaxListeners(50);\n\n const session: TerminalSession = {\n pty: term,\n emitter,\n scrollback: '',\n info: {\n sessionId,\n title: title ?? 'Terminal',\n cwd: resolvedCwd,\n cols: resolvedCols,\n rows: resolvedRows,\n createdAt: Date.now(),\n },\n };\n\n term.onData((data) => {\n session.scrollback += data;\n if (session.scrollback.length > SCROLLBACK_LIMIT) {\n session.scrollback = session.scrollback.slice(-SCROLLBACK_LIMIT);\n }\n emitter.emit('data', data);\n });\n term.onExit(() => {\n emitter.emit('exit');\n this.sessions.delete(sessionId);\n });\n\n this.sessions.set(sessionId, session);\n return sessionId;\n }\n\n write(sessionId: string, data: string): void {\n this.sessions.get(sessionId)?.pty.write(data);\n }\n\n resize(sessionId: string, cols: number, rows: number): void {\n const session = this.sessions.get(sessionId);\n if (!session) return;\n session.pty.resize(cols, rows);\n session.info.cols = cols;\n session.info.rows = rows;\n }\n\n rename(sessionId: string, title: string): void {\n const session = this.sessions.get(sessionId);\n if (session) session.info.title = title;\n }\n\n destroy(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n try { session.pty.kill(); } catch { /* already dead */ }\n this.sessions.delete(sessionId);\n }\n }\n\n /** Les sessions encore vivantes : de quoi retrouver ses onglets après un aller-retour. */\n list(): TerminalSessionInfo[] {\n return [...this.sessions.values()]\n .map((s) => s.info)\n .sort((a, b) => a.createdAt - b.createdAt);\n }\n\n getScrollback(sessionId: string): string {\n return this.sessions.get(sessionId)?.scrollback ?? '';\n }\n\n getEmitter(sessionId: string): EventEmitter | null {\n return this.sessions.get(sessionId)?.emitter ?? null;\n }\n}\n\nexport const terminalManager = new TerminalManager();\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { execFile, spawn } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { existsSync, watch as fsWatch } from 'node:fs';\nimport { promises as fsPromises } from 'node:fs';\nimport { join, resolve as resolvePath } from 'node:path';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { expandEnvVar } from '../../utils/env.js';\nimport { sameGitRemote } from '../../utils/git-remote.js';\n\nconst execFileAsync = promisify(execFile);\n\nconst GIT_TIMEOUT = 15_000;\nconst DIFF_MAX_BYTES = 512 * 1024;\n\nconst CWD_SCHEMA = z.string().min(1).max(4096);\nconst SAFE_PATH_SCHEMA = z\n .string()\n .min(1)\n .max(4096)\n .refine((p) => !p.startsWith('/') && !p.includes('../'), {\n message: 'Path must be relative and not traverse up',\n });\nconst REMOTE_SCHEMA = z.string().min(1).max(128).regex(/^[a-zA-Z0-9_\\-.]+$/);\nconst BRANCH_SCHEMA = z.string().min(1).max(256).regex(/^[a-zA-Z0-9._\\-/]+$/);\n\n/**\n * Build a safe, explicit environment for git commands.\n */\nfunction gitSafeEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = {\n GIT_TERMINAL_PROMPT: '0',\n GIT_ASKPASS: 'echo',\n };\n if (process.env['PATH']) env['PATH'] = process.env['PATH'];\n if (process.env['HOME']) env['HOME'] = process.env['HOME'];\n if (process.env['GIT_AUTHOR_NAME']) env['GIT_AUTHOR_NAME'] = process.env['GIT_AUTHOR_NAME'];\n if (process.env['GIT_AUTHOR_EMAIL']) env['GIT_AUTHOR_EMAIL'] = process.env['GIT_AUTHOR_EMAIL'];\n if (process.env['GIT_COMMITTER_NAME']) env['GIT_COMMITTER_NAME'] = process.env['GIT_COMMITTER_NAME'];\n if (process.env['GIT_COMMITTER_EMAIL']) env['GIT_COMMITTER_EMAIL'] = process.env['GIT_COMMITTER_EMAIL'];\n if (process.env['SSH_AUTH_SOCK']) env['SSH_AUTH_SOCK'] = process.env['SSH_AUTH_SOCK'];\n return env;\n}\n\nconst activeGitProcesses = new Set<import('node:child_process').ChildProcess>();\n\n{\n const cleanup = () => {\n for (const proc of activeGitProcesses) {\n try { proc.kill('SIGTERM'); } catch { /* already dead */ }\n }\n };\n process.on('SIGTERM', cleanup);\n process.on('SIGINT', cleanup);\n}\n\nasync function git(args: string[], cwd: string, readOnly = false): Promise<string> {\n const ac = new AbortController();\n const timeout = setTimeout(() => ac.abort(), GIT_TIMEOUT);\n const env = gitSafeEnv();\n if (readOnly) env['GIT_OPTIONAL_LOCKS'] = '0';\n try {\n const result = execFileAsync('git', args, { cwd, signal: ac.signal, env, windowsHide: true });\n if (result.child) {\n activeGitProcesses.add(result.child);\n result.child.on('close', () => activeGitProcesses.delete(result.child!));\n }\n const { stdout } = await result;\n return stdout;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n const stderr = (err as { stderr?: string }).stderr ?? '';\n throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: stderr || message });\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function assertGitRepo(cwd: string): Promise<void> {\n try {\n await git(['rev-parse', '--git-dir'], cwd, true);\n } catch (err) {\n console.error('[git] assertGitRepo failed for cwd=%s:', cwd, err);\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Not a git repository: ${cwd}` });\n }\n}\n\n\n/**\n * Expand $VAR / ${VAR} and leading ~ in a cwd string using resolveEnv(),\n * assert the directory exists, and return the resolved path.\n * All git handlers must call this first and use the returned path.\n */\nfunction assertCwdExists(cwd: string): string {\n const resolved = expandEnvVar(cwd);\n if (!existsSync(resolved)) {\n console.error('[git] assertCwdExists: directory does not exist: %s (resolved=%s, process.cwd=%s)', cwd, resolved, process.cwd());\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Working directory does not exist: ${resolved}` });\n }\n return resolved;\n}\n\nasync function getGitStatus(cwd: string) {\n let branch = '';\n try {\n branch = (await git(['rev-parse', '--abbrev-ref', 'HEAD'], cwd, true)).trim();\n } catch {\n branch = 'HEAD';\n }\n\n const statusOutput = await git(['status', '--porcelain=v1', '-u'], cwd, true);\n const staged: string[] = [];\n const unstaged: string[] = [];\n const untracked: string[] = [];\n for (const line of statusOutput.split('\\n').filter(Boolean)) {\n const X = line[0];\n const Y = line[1];\n const file = line.slice(3);\n if (X === '?' && Y === '?') {\n untracked.push(file);\n } else {\n if (X !== ' ' && X !== '?') staged.push(file);\n if (Y !== ' ' && Y !== '?') unstaged.push(file);\n }\n }\n\n let ahead = 0;\n let behind = 0;\n try {\n const revListOut = await git(['rev-list', '--left-right', '--count', '@{upstream}...HEAD'], cwd, true);\n const parts = revListOut.trim().split(/\\s+/);\n behind = Number.parseInt(parts[0] ?? '0', 10);\n ahead = Number.parseInt(parts[1] ?? '0', 10);\n } catch { /* no upstream */ }\n\n let upstream = '';\n try {\n upstream = (await git(['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'], cwd, true)).trim();\n } catch { /* no upstream */ }\n\n // Total des lignes ajoutées/supprimées des changements suivis (staged + unstaged) vs HEAD.\n // Les fichiers binaires apparaissent comme \"-\\t-\" et sont ignorés.\n let additions = 0;\n let deletions = 0;\n try {\n const numstat = await git(['diff', '--numstat', 'HEAD'], cwd, true);\n for (const line of numstat.split('\\n').filter(Boolean)) {\n const [add, del] = line.split('\\t');\n const a = Number.parseInt(add ?? '', 10);\n const d = Number.parseInt(del ?? '', 10);\n if (!Number.isNaN(a)) additions += a;\n if (!Number.isNaN(d)) deletions += d;\n }\n } catch { /* no HEAD yet, or not a repo */ }\n\n return { branch, staged, unstaged, untracked, ahead, behind, upstream, additions, deletions };\n}\n\nexport const gitRouter = router({\n /** Check if a working directory exists and optionally verify its git remote */\n checkCwd: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n remote: z.string().max(2048).optional(),\n checkReachability: z.boolean().optional(),\n }))\n .query(async ({ input }) => {\n const resolvedCwd = expandEnvVar(input.cwd);\n // Detect vars that couldn't be resolved (still contain $)\n const unresolvedVars = [...resolvedCwd.matchAll(/\\$\\{?(\\w+)\\}?/g)].map(m => m[1]!);\n if (unresolvedVars.length > 0) {\n return { exists: false, actualRemote: null, remoteMatches: false, unreachable: false, resolvedCwd, unresolvedVars };\n }\n const absoluteCwd = resolvePath(resolvedCwd);\n const exists = existsSync(absoluteCwd);\n if (!exists || !input.remote) {\n return { exists, actualRemote: null, remoteMatches: false, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };\n }\n const { code: urlCode, out: actualRemote } = await runGitRaw(['-C', absoluteCwd, 'remote', 'get-url', 'origin'], 5000);\n if (urlCode !== 0) return { exists, actualRemote: null, remoteMatches: false, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };\n // Comparé ici, et pas côté serveur : seul l'agent voit la configuration ssh\n // qui donne son vrai hôte à un alias (`github-addworking` → `github.com`).\n const remoteMatches = await sameGitRemote(actualRemote, input.remote);\n if (input.checkReachability) {\n const { code: showCode } = await runGitRaw(['-C', absoluteCwd, 'remote', 'show', 'origin'], 10000);\n return { exists, actualRemote, remoteMatches, unreachable: showCode !== 0, resolvedCwd: absoluteCwd, unresolvedVars: [] };\n }\n return { exists, actualRemote, remoteMatches, unreachable: false, resolvedCwd: absoluteCwd, unresolvedVars: [] };\n }),\n\n /** Clone a git repository into a target directory */\n clone: protectedProcedure\n .input(z.object({\n remote: z.string().min(1).max(2048),\n cwd: CWD_SCHEMA,\n }))\n .mutation(async ({ input }) => {\n const absoluteCwd = resolvePath(expandEnvVar(input.cwd));\n if (existsSync(absoluteCwd)) {\n // Allow cloning into an existing empty directory, but reject non-empty ones\n const entries = await fsPromises.readdir(absoluteCwd);\n if (entries.length > 0) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Working directory already exists and is not empty' });\n }\n }\n console.log('[git.clone] remote=%s cwd=%s absoluteCwd=%s', input.remote, input.cwd, absoluteCwd);\n const { code, out } = await runGitRaw(['clone', input.remote, absoluteCwd], 5 * 60 * 1000, {\n GIT_SSH_COMMAND: 'ssh -o StrictHostKeyChecking=accept-new',\n });\n if (code !== 0) {\n console.error('[git.clone] failed (code=%d): %s', code, out);\n throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: `git clone failed: ${out}` });\n }\n return { success: true as const };\n }),\n\n /** Get full git status */\n status: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n return getGitStatus(cwd);\n }),\n\n /** Watch .git/ for changes and stream updated status */\n onStatusChange: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .subscription(async function* ({ input }) {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n\n const gitDir = (await git(['rev-parse', '--git-dir'], cwd, true)).trim();\n const absGitDir = resolvePath(cwd, gitDir);\n\n const queue: Array<'changed'> = [];\n let resolve: (() => void) | null = null;\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const onFsChange = () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n queue.push('changed');\n if (resolve) { resolve(); resolve = null; }\n }, 500);\n };\n\n // Watch .git dir for staged/committed changes\n const gitWatcher = fsWatch(absGitDir, { recursive: true }, () => {\n onFsChange();\n });\n gitWatcher.on('error', () => { /* directory deleted mid-watch, ignore */ });\n\n // Watch working tree for unstaged file modifications (exclude .git)\n const cwdWatcher = fsWatch(cwd, { recursive: true }, (event, filename) => {\n if (filename && filename.startsWith('.git')) return;\n onFsChange();\n });\n cwdWatcher.on('error', () => { /* directory deleted mid-watch, ignore */ });\n\n // Yield initial status immediately\n yield await getGitStatus(cwd);\n\n try {\n while (true) {\n if (queue.length > 0) {\n queue.length = 0;\n try {\n yield await getGitStatus(cwd);\n } catch { }\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n gitWatcher.close();\n cwdWatcher.close();\n if (debounceTimer) clearTimeout(debounceTimer);\n }\n }),\n\n /** Get commit log */\n log: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, limit: z.number().int().min(1).max(200).default(50) }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const format = '%H\\x1f%h\\x1f%an\\x1f%ae\\x1f%ai\\x1f%s';\n const output = await git(['log', `--max-count=${input.limit}`, `--format=${format}`], cwd, true);\n return output.split('\\n').filter(Boolean).map((line) => {\n const [hash, shortHash, author, email, date, ...subjectParts] = line.split('\\x1f');\n return { hash, shortHash, author, email, date, subject: subjectParts.join('\\x1f') };\n });\n }),\n\n /** List local and remote branches */\n branches: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const current = (await git(['rev-parse', '--abbrev-ref', 'HEAD'], cwd, true)).trim();\n const output = await git(['branch', '-a', '--format=%(refname:short)\u001f%(upstream:short)\u001f%(HEAD)'], cwd, true);\n const branches = output.split('\\n').filter(Boolean).map((line) => {\n const [name, upstream, head] = line.split('\\x1f');\n return { name, upstream: upstream ?? '', current: head === '*', remote: name.startsWith('remotes/') };\n });\n return { current, branches };\n }),\n\n /** Checkout a branch */\n checkout: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, branch: BRANCH_SCHEMA, create: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const args = input.create ? ['checkout', '-b', input.branch] : ['checkout', input.branch];\n await git(args, cwd);\n return { ok: true };\n }),\n\n /** Stage files */\n stage: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n await git(['add', '--', ...input.paths], cwd);\n return { ok: true };\n }),\n\n /** Stage all files */\n stageAll: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n await git(['add', '-A'], cwd);\n return { ok: true };\n }),\n\n /** Unstage files */\n unstage: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n await git(['restore', '--staged', '--', ...input.paths], cwd);\n return { ok: true };\n }),\n\n /** Unstage all files */\n unstageAll: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n // `git reset` unstages everything while keeping the working tree intact,\n // and works even on a repo with no commits yet (resets index to empty tree).\n await git(['reset', '--'], cwd);\n return { ok: true };\n }),\n\n /** Commit staged changes */\n commit: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, message: z.string().min(1).max(4096) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['commit', '-m', input.message], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Push to remote */\n push: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, remote: REMOTE_SCHEMA.default('origin'), setUpstream: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const branch = (await git(['rev-parse', '--abbrev-ref', 'HEAD'], cwd, true)).trim();\n const args = input.setUpstream\n ? ['push', '--set-upstream', input.remote, branch]\n : ['push', input.remote, branch];\n const output = await git(args, cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Pull from remote */\n pull: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, remote: REMOTE_SCHEMA.default('origin') }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['pull', input.remote], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Fetch from remote */\n fetch: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, remote: REMOTE_SCHEMA.default('origin') }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['fetch', input.remote], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Get diff for a file or the whole index */\n diff: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n path: z.string().max(4096).optional(),\n staged: z.boolean().default(false),\n untracked: z.boolean().default(false),\n }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n\n async function readFileSafe(filePath: string): Promise<string> {\n try { return await fsPromises.readFile(filePath, 'utf-8'); } catch { return ''; }\n }\n\n if (input.untracked && input.path) {\n const modified = await readFileSafe(join(cwd, input.path));\n return { diff: '', original: '', modified };\n }\n\n const args = input.staged ? ['diff', '--staged'] : ['diff'];\n if (input.path) args.push('--', input.path);\n const output = await git(args, cwd, true);\n\n let original = '';\n let modified = '';\n if (input.path) {\n if (input.staged) {\n try { original = await git(['show', `HEAD:${input.path}`], cwd, true); } catch { original = ''; }\n try { modified = await git(['show', `:0:${input.path}`], cwd, true); } catch { modified = original; }\n } else {\n try { original = await git(['show', `:0:${input.path}`], cwd, true); } catch { original = ''; }\n modified = await readFileSafe(join(cwd, input.path));\n }\n }\n\n return {\n diff: output.slice(0, DIFF_MAX_BYTES),\n original: original.slice(0, DIFF_MAX_BYTES),\n modified: modified.slice(0, DIFF_MAX_BYTES),\n };\n }),\n\n /** Discard changes to working tree files */\n discard: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n await git(['restore', '--', ...input.paths], cwd);\n return { ok: true };\n }),\n\n /** Get staged diff (used by server for AI commit message generation) */\n stagedDiff: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const diff = await git(['diff', '--staged'], cwd, true);\n return { diff: diff.slice(0, 30_000) };\n }),\n\n /** Merge a branch into the current branch */\n merge: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, branch: BRANCH_SCHEMA, noFf: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const args = input.noFf ? ['merge', '--no-ff', input.branch] : ['merge', input.branch];\n const output = await git(args, cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Rebase current branch onto another branch */\n rebase: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, branch: BRANCH_SCHEMA }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['rebase', input.branch], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** List remotes */\n remotes: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['remote', '-v'], cwd, true);\n const seen = new Set<string>();\n const remotes: Array<{ name: string; url: string }> = [];\n for (const line of output.split('\\n').filter(Boolean)) {\n const parts = line.split(/\\s+/);\n const name = parts[0];\n const url = parts[1];\n if (name && url && !seen.has(name)) {\n seen.add(name);\n remotes.push({ name, url });\n }\n }\n return remotes;\n }),\n\n /** List stash entries */\n stashList: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n // Format: \"<ref>\\x1f<message>\" per line (\\x1f separator keeps the message intact)\n const output = await git(['stash', 'list', '--format=%gd\\x1f%s'], cwd, true);\n const entries: Array<{ index: number; ref: string; message: string }> = [];\n for (const line of output.split('\\n').filter(Boolean)) {\n const [ref, message = ''] = line.split('\\x1f');\n // ref looks like \"stash@{0}\" → extract the numeric index\n const m = /stash@\\{(\\d+)\\}/.exec(ref ?? '');\n if (m) entries.push({ index: Number.parseInt(m[1], 10), ref: ref!, message });\n }\n return entries;\n }),\n\n /** Stash current changes */\n stashPush: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n message: z.string().max(4096).optional(),\n includeUntracked: z.boolean().default(true),\n }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const args = ['stash', 'push'];\n if (input.includeUntracked) args.push('--include-untracked');\n if (input.message) args.push('-m', input.message);\n const output = await git(args, cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Apply a stash entry and remove it from the list */\n stashPop: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, index: z.number().int().min(0).max(1000).default(0) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['stash', 'pop', `stash@{${input.index}}`], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Apply a stash entry without removing it from the list */\n stashApply: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, index: z.number().int().min(0).max(1000).default(0) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['stash', 'apply', `stash@{${input.index}}`], cwd);\n return { ok: true, output: output.trim() };\n }),\n\n /** Drop a stash entry */\n stashDrop: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, index: z.number().int().min(0).max(1000).default(0) }))\n .mutation(async ({ input }) => {\n const cwd = assertCwdExists(input.cwd);\n await assertGitRepo(cwd);\n const output = await git(['stash', 'drop', `stash@{${input.index}}`], cwd);\n return { ok: true, output: output.trim() };\n }),\n});\n\n// Low-level helper for checkCwd/clone that needs raw exit code\nfunction runGitRaw(args: string[], timeoutMs: number, extraEnv?: Record<string, string>): Promise<{ code: number | null; out: string }> {\n return new Promise((res) => {\n const child = spawn('git', args, { shell: false, stdio: 'pipe', env: { ...process.env, ...extraEnv }, windowsHide: true });\n let out = '';\n child.stdout?.on('data', (d: Buffer) => { out += d.toString(); });\n child.stderr?.on('data', (d: Buffer) => { out += d.toString(); });\n const timer = setTimeout(() => { child.kill('SIGKILL'); res({ code: null, out }); }, timeoutMs);\n child.on('close', (code: number | null) => { clearTimeout(timer); res({ code, out: out.trim() }); });\n child.on('error', () => { clearTimeout(timer); res({ code: null, out }); });\n });\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\nexport interface ParsedRemote {\n host: string;\n path: string;\n}\n\n/**\n * Découpe une URL de remote git, qu'elle soit une URL (`ssh://`, `https://`…)\n * ou la forme scp (`git@host:owner/repo.git`). Le suffixe `.git` et les barres\n * de fin sont retirés : ils ne distinguent pas deux dépôts.\n */\nexport function parseGitRemote(url: string): ParsedRemote | null {\n const trimmed = url.trim();\n if (!trimmed) return null;\n\n let host: string;\n let path: string;\n\n const scp = /^(?:[^/@]+@)?([^/:]+):(?!\\/)(.+)$/.exec(trimmed);\n if (scp) {\n host = scp[1]!;\n path = scp[2]!;\n } else {\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n return null;\n }\n if (parsed.protocol === 'file:' || !parsed.hostname) return null;\n host = parsed.hostname;\n path = parsed.pathname;\n }\n\n path = path.replace(/^\\/+/, '').replace(/\\/+$/, '').replace(/\\.git$/i, '');\n if (!host || !path) return null;\n return { host: host.toLowerCase(), path: path.toLowerCase() };\n}\n\n/**\n * Résout un alias d'hôte SSH (`Host github-addworking` → `github.com`) via la\n * configuration ssh de l'utilisateur. Sans ça, deux remotes qui désignent le\n * même dépôt sont vus comme différents dès qu'un alias est utilisé.\n */\nexport async function resolveSshHost(host: string): Promise<string> {\n if (!/^[a-zA-Z0-9._-]+$/.test(host)) return host;\n try {\n const { stdout } = await execFileAsync('ssh', ['-G', host], {\n windowsHide: true,\n timeout: 3000,\n env: { PATH: process.env['PATH'] ?? '', HOME: process.env['HOME'] ?? '' },\n });\n const match = /^hostname (.+)$/m.exec(stdout);\n return match ? match[1]!.trim().toLowerCase() : host;\n } catch {\n return host;\n }\n}\n\n/**\n * Deux remotes désignent-ils le même dépôt ? La comparaison porte sur\n * `hôte + chemin`, après résolution des alias SSH et normalisation.\n */\nexport async function sameGitRemote(\n a: string,\n b: string,\n resolveHost: (host: string) => Promise<string> = resolveSshHost,\n): Promise<boolean> {\n if (a.trim() === b.trim()) return true;\n const left = parseGitRemote(a);\n const right = parseGitRemote(b);\n if (!left || !right) return false;\n if (left.path !== right.path) return false;\n if (left.host === right.host) return true;\n const [leftHost, rightHost] = await Promise.all([\n resolveHost(left.host),\n resolveHost(right.host),\n ]);\n return leftHost === rightHost;\n}\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { aiSpawnManager } from '../../services/ai-spawn-manager.js';\nimport { codexAppServerManager } from '../../services/codex-app-server-manager.js';\nimport { writeContextFiles } from '../../services/ai-context-files.js';\nimport { savePastedImage } from '../../services/ai-paste-image.js';\n\nconst MAX_CONTEXT_FILES = 20;\nconst MAX_CONTEXT_FILE_BYTES = 1_000_000;\nconst MAX_CONTEXT_TOTAL_BYTES = 5_000_000;\n\nexport const aiRouter = router({\n /** Spawn an AI CLI process. Returns a spawnId for streaming. */\n spawn: protectedProcedure\n .input(z.object({\n cli: z.string().max(64),\n args: z.array(z.string().max(500_000)),\n env: z.record(z.string().max(256), z.string().max(500_000)).optional(),\n cwd: z.string().max(4096).optional(),\n stdinData: z.string().max(10_000_000).optional(),\n enableMcp: z.boolean().optional(),\n mcpApiBaseUrl: z.string().max(512).optional(),\n mcpApiToken: z.string().max(8192).optional(),\n mcpProjectId: z.string().max(128).optional(),\n mcpOrgId: z.string().max(128).optional(),\n }))\n .mutation(({ input }) => {\n const spawnId = aiSpawnManager.spawn(input);\n return { spawnId };\n }),\n\n /** Stream stdout/stderr/exit chunks from offset. Reconnectable. */\n stream: protectedProcedure\n .input(z.object({\n spawnId: z.string().max(128),\n fromOffset: z.number().int().min(0).default(0),\n }))\n .subscription(async function* ({ input }) {\n try {\n for await (const item of aiSpawnManager.stream(input.spawnId, input.fromOffset)) {\n yield item;\n }\n } catch (err) {\n throw new TRPCError({\n code: 'NOT_FOUND',\n message: (err as Error).message,\n });\n }\n }),\n\n /** Spawn an AI CLI process in a PTY (interactive mode). Returns spawnId. */\n spawnPty: protectedProcedure\n .input(z.object({\n cli: z.string().max(64),\n args: z.array(z.string().max(500_000)),\n env: z.record(z.string().max(256), z.string().max(500_000)).optional(),\n cwd: z.string().max(4096).optional(),\n cols: z.number().int().min(1).max(1000).optional(),\n rows: z.number().int().min(1).max(1000).optional(),\n sessionId: z.string().max(128).optional(),\n enableMcp: z.boolean().optional(),\n mcpApiBaseUrl: z.string().max(512).optional(),\n mcpApiToken: z.string().max(8192).optional(),\n mcpProjectId: z.string().max(128).optional(),\n mcpOrgId: z.string().max(128).optional(),\n }))\n .mutation(({ input }) => {\n const spawnId = aiSpawnManager.spawnPty(input);\n return { spawnId };\n }),\n\n /** Find a running PTY spawn by its logical sessionId (for re-attach). */\n findPtyBySession: protectedProcedure\n .input(z.object({ sessionId: z.string().max(128) }))\n .query(({ input }) => {\n return aiSpawnManager.findPtyBySessionId(input.sessionId);\n }),\n\n /** Write input to a PTY spawn (user keystrokes). */\n writePty: protectedProcedure\n .input(z.object({\n spawnId: z.string().max(128),\n data: z.string().max(1_000_000),\n }))\n .mutation(({ input }) => {\n const ok = aiSpawnManager.writePty(input.spawnId, input.data);\n return { ok };\n }),\n\n /** Write attached-context files for an AI session to a temp dir. Returns absolute paths. */\n writeContextFiles: protectedProcedure\n .input(z.object({\n sessionId: z.string().min(1).max(128),\n files: z.array(z.object({\n name: z.string().min(1).max(256),\n content: z.string().max(MAX_CONTEXT_FILE_BYTES),\n })).min(1).max(MAX_CONTEXT_FILES),\n }).refine(\n (val) => val.files.reduce((sum, f) => sum + f.content.length, 0) <= MAX_CONTEXT_TOTAL_BYTES,\n { message: `Total context size exceeds ${MAX_CONTEXT_TOTAL_BYTES} bytes` },\n ))\n .mutation(async ({ input }) => {\n const paths = await writeContextFiles(input.sessionId, input.files);\n return { paths };\n }),\n\n /**\n * Save a pasted image to disk and try to populate the agent's system clipboard\n * so Claude's native paste detection picks it up. Returns the tmp path and\n * which clipboard method (if any) succeeded — caller decides whether to send\n * Ctrl+V (\\x16) or inject `@<path>` into the PTY.\n */\n pasteImage: protectedProcedure\n .input(z.object({\n sessionId: z.string().max(128).optional(),\n mimeType: z.string().max(64),\n base64: z.string().max(15_000_000),\n }))\n .mutation(async ({ input }) => {\n const res = await savePastedImage(input.base64, input.mimeType, input.sessionId);\n return res;\n }),\n\n /** Resize a PTY spawn. */\n resizePty: protectedProcedure\n .input(z.object({\n spawnId: z.string().max(128),\n cols: z.number().int().min(1).max(1000),\n rows: z.number().int().min(1).max(1000),\n }))\n .mutation(({ input }) => {\n const ok = aiSpawnManager.resizePty(input.spawnId, input.cols, input.rows);\n return { ok };\n }),\n\n /** Kill a running AI spawn. */\n kill: protectedProcedure\n .input(z.object({ spawnId: z.string().max(128) }))\n .mutation(({ input }) => {\n const killed = aiSpawnManager.kill(input.spawnId);\n return { ok: killed };\n }),\n\n /** List all spawns with buffer (running + done). */\n list: protectedProcedure\n .query(() => {\n return aiSpawnManager.list();\n }),\n\n /** Acknowledge receipt of all data — agent can clean up after TTL. */\n ack: protectedProcedure\n .input(z.object({ spawnId: z.string().max(128) }))\n .mutation(({ input }) => {\n const acked = aiSpawnManager.ack(input.spawnId);\n return { ok: acked };\n }),\n\n /** Forward a JSON-RPC request to the local codex app-server. */\n codexRequest: protectedProcedure\n .input(z.object({\n method: z.string().max(256),\n params: z.record(z.string(), z.unknown()).default({}),\n env: z.record(z.string().max(256), z.string().max(500_000)).optional(),\n }))\n .mutation(async ({ input }) => {\n await codexAppServerManager.ensureConnected(input.env);\n const result = await codexAppServerManager.sendRequest(input.method, input.params);\n return { result };\n }),\n\n /** Stream notifications from the codex app-server. Optionally filter by threadId. */\n codexNotifications: protectedProcedure\n .input(z.object({\n threadId: z.string().max(256).optional(),\n }).default({}))\n .subscription(async function* ({ input, signal }) {\n await codexAppServerManager.ensureConnected();\n\n const queue: Array<{ method: string; params: Record<string, unknown> }> = [];\n let resolve: (() => void) | null = null;\n\n const unsub = codexAppServerManager.onNotification((method, params) => {\n // Filter by threadId if provided\n if (input.threadId) {\n const notifThreadId = (params['threadId'] as string | undefined)\n ?? ((params['turn'] as Record<string, unknown> | undefined)?.['threadId'] as string | undefined);\n // Only filter if the notification has a threadId — pass through unscoped notifications\n if (notifThreadId && notifThreadId !== input.threadId) return;\n }\n queue.push({ method, params });\n if (resolve) { resolve(); resolve = null; }\n });\n\n try {\n while (!signal?.aborted) {\n while (queue.length > 0) {\n yield queue.shift()!;\n }\n await new Promise<void>((r) => { resolve = r; });\n }\n } finally {\n unsub();\n }\n }),\n\n /** Shut down the codex app-server process. */\n codexShutdown: protectedProcedure\n .mutation(() => {\n codexAppServerManager.shutdown();\n return { ok: true };\n }),\n});\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\nimport { randomUUID } from 'node:crypto';\nimport * as pty from '@lydell/node-pty';\nimport { claudeMcpArgs, codexMcpArgs } from '@runeya/packages-mcp-server/launch';\nimport { resolveCliInvocation } from '@runeya/packages-shared/node';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\n/**\n * @public — export requis : ces types apparaissent dans les signatures inférées\n * du routeur tRPC de l'agent (sinon TS4023 : \"cannot be named\").\n */\nexport interface AiSpawnChunk {\n type: 'stdout' | 'stderr' | 'exit' | 'pty-data';\n data: string;\n code?: number;\n}\n\n/**\n * @public — export requis : ces types apparaissent dans les signatures inférées\n * du routeur tRPC de l'agent (sinon TS4023 : \"cannot be named\").\n */\nexport interface AiSpawnInfo {\n spawnId: string;\n cli: string;\n status: 'running' | 'done' | 'error';\n exitCode: number | null;\n bufferLength: number;\n createdAt: number;\n doneAt: number | null;\n lastChunkAt: number | null;\n}\n\ninterface AiSpawn {\n spawnId: string;\n /** Optional logical session key (e.g. Claude --session-id) used to re-attach. */\n sessionId?: string;\n cli: string;\n status: 'running' | 'done' | 'error';\n exitCode: number | null;\n buffer: AiSpawnChunk[];\n proc: ChildProcess | null;\n ptyProc: pty.IPty | null;\n emitter: EventEmitter;\n createdAt: number;\n doneAt: number | null;\n acked: boolean;\n /** Timestamp of the most recent stdout/stderr/pty data chunk. */\n lastChunkAt: number | null;\n}\n\ninterface AiSpawnPtyOpts {\n cli: string;\n args: string[];\n env?: Record<string, string>;\n cwd?: string;\n cols?: number;\n rows?: number;\n /** Optional logical session id (e.g. Claude --session-id) — enables re-attach. */\n sessionId?: string;\n /** When true, resolve @runeya/packages-mcp-server locally and inject --mcp-config. */\n enableMcp?: boolean;\n /** Runeya server base URL for MCP server env (e.g. \"http://localhost:4000\"). */\n mcpApiBaseUrl?: string;\n /** Runeya API bearer token forwarded to the MCP server as RUNEYA_API_TOKEN. */\n mcpApiToken?: string;\n /** Project of the conversation, used by the MCP server to anchor its tools. */\n mcpProjectId?: string;\n mcpOrgId?: string;\n}\n\ninterface AiSpawnOpts {\n cli: string;\n args: string[];\n env?: Record<string, string>;\n cwd?: string;\n stdinData?: string;\n /** When true, resolve @runeya/packages-mcp-server locally and inject --mcp-config. */\n enableMcp?: boolean;\n /** Runeya server base URL for MCP server env (e.g. \"http://localhost:4000\"). */\n mcpApiBaseUrl?: string;\n /** Runeya API bearer token forwarded to the MCP server as RUNEYA_API_TOKEN. */\n mcpApiToken?: string;\n /** Project of the conversation, used by the MCP server to anchor its tools. */\n mcpProjectId?: string;\n mcpOrgId?: string;\n}\n\n// ─── Constants ────────────────────────────────────────────────────────────\n\nconst MAX_BUFFER_LINES = 100_000;\nconst MAX_CONCURRENT_SPAWNS = 100;\nconst CLEANUP_INTERVAL_MS = 60_000;\nconst TTL_ACKED_MS = 5 * 60_000; // 5 min after ack\nconst TTL_UNACKED_MS = 24 * 3600_000; // 24h safety net\n// Running interactive PTYs never exit on their own (Claude waits for input\n// forever). Reap one that has produced no output for this long so a forgotten,\n// navigated-away session stops holding a concurrency slot indefinitely.\nconst TTL_IDLE_PTY_MS = 30 * 60_000; // 30 min of PTY silence\n\n// ─── Spawn preparation (shared by spawn + spawnPty) ─────────────────────────\n\ninterface RuneyaSpawnInput {\n cli: string;\n args: string[];\n env?: Record<string, string>;\n enableMcp?: boolean;\n mcpApiBaseUrl?: string;\n mcpApiToken?: string;\n mcpProjectId?: string;\n mcpOrgId?: string;\n}\n\n/**\n * Resolve the child process env and CLI args from spawn opts. Single source of\n * truth for both `spawn` (headless `-p`) and `spawnPty` (interactive) so the two\n * paths can never drift apart.\n *\n * Runeya credentials follow ONE channel: they are merged into the child env\n * (from `env` and/or `mcpApiBaseUrl`/`mcpApiToken`), and the MCP server config\n * env is *derived from that final child env*. Whether the token arrives via\n * `env.RUNEYA_API_TOKEN` (headless path) or `mcpApiToken` (PTY path), both the\n * CLI process (so `$RUNEYA_API_TOKEN` resolves in its shell) and the MCP server\n * always see the same credentials.\n */\nfunction resolveSpawnEnvAndArgs(opts: RuneyaSpawnInput): { env: NodeJS.ProcessEnv; args: string[] } {\n const runeyaEnv: Record<string, string> = {\n ...(opts.mcpApiBaseUrl ? { RUNEYA_BASE_URL: opts.mcpApiBaseUrl } : {}),\n ...(opts.mcpApiToken ? { RUNEYA_API_TOKEN: opts.mcpApiToken } : {}),\n ...(opts.mcpProjectId ? { RUNEYA_PROJECT_ID: opts.mcpProjectId } : {}),\n ...(opts.mcpOrgId ? { RUNEYA_ORG_ID: opts.mcpOrgId } : {}),\n };\n const env = { ...process.env, ...opts.env, ...runeyaEnv } as NodeJS.ProcessEnv;\n\n let args = [...opts.args];\n if (opts.enableMcp) {\n const mcpEnv = {\n RUNEYA_BASE_URL: env.RUNEYA_BASE_URL,\n RUNEYA_API_TOKEN: env.RUNEYA_API_TOKEN,\n RUNEYA_PROJECT_ID: env.RUNEYA_PROJECT_ID,\n RUNEYA_ORG_ID: env.RUNEYA_ORG_ID,\n };\n try {\n if (opts.cli === 'claude') {\n // `--mcp-config` est une option : sa place dans la ligne est libre.\n args.push(...claudeMcpArgs(mcpEnv));\n } else if (opts.cli === 'codex') {\n // Les surcharges `-c` doivent PRÉCÉDER la sous-commande (`resume`…),\n // sinon codex les rattache à elle et les refuse.\n args = [...codexMcpArgs(mcpEnv), ...args];\n }\n } catch (err) {\n console.warn('[ai-spawn-manager] Failed to resolve MCP server path:', (err as Error).message);\n }\n }\n\n return { env, args };\n}\n\n// ─── Manager ──────────────────────────────────────────────────────────────\n\nclass AiSpawnManager {\n private spawns = new Map<string, AiSpawn>();\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n\n constructor() {\n this.cleanupInterval = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);\n }\n\n spawn(opts: AiSpawnOpts): string {\n // Guard: max concurrent spawns\n const running = [...this.spawns.values()].filter(s => s.status === 'running').length;\n if (running >= MAX_CONCURRENT_SPAWNS) {\n throw new Error(`Max concurrent AI spawns reached (${MAX_CONCURRENT_SPAWNS})`);\n }\n\n const spawnId = randomUUID();\n const emitter = new EventEmitter();\n\n // Resolve env + MCP args via the shared helper (symmetric with spawnPty).\n const { env, args } = resolveSpawnEnvAndArgs(opts);\n\n const invocation = resolveCliInvocation(opts.cli, args);\n\n const proc = spawn(invocation.command, invocation.args, {\n windowsHide: true,\n stdio: ['pipe', 'pipe', 'pipe'],\n shell: false,\n env,\n cwd: opts.cwd || undefined,\n });\n\n const entry: AiSpawn = {\n spawnId,\n cli: opts.cli,\n status: 'running',\n exitCode: null,\n buffer: [],\n proc,\n ptyProc: null,\n emitter,\n createdAt: Date.now(),\n doneAt: null,\n acked: false,\n lastChunkAt: null,\n };\n\n this.spawns.set(spawnId, entry);\n\n // Stdin\n if (opts.stdinData) {\n proc.stdin!.write(opts.stdinData);\n }\n proc.stdin!.end();\n\n // Stdout\n proc.stdout!.on('data', (chunk: Buffer) => {\n const data = chunk.toString('utf-8');\n this.pushChunk(entry, { type: 'stdout', data });\n });\n\n // Stderr\n proc.stderr!.on('data', (chunk: Buffer) => {\n const data = chunk.toString('utf-8');\n this.pushChunk(entry, { type: 'stderr', data });\n });\n\n // Close\n proc.on('close', (code) => {\n entry.status = code === 0 ? 'done' : 'error';\n entry.exitCode = code;\n entry.doneAt = Date.now();\n entry.proc = null;\n this.pushChunk(entry, { type: 'exit', data: '', code: code ?? 1 });\n });\n\n // Error (e.g. ENOENT)\n proc.on('error', (err) => {\n entry.status = 'error';\n entry.doneAt = Date.now();\n entry.proc = null;\n this.pushChunk(entry, { type: 'stderr', data: `spawn error: ${err.message}` });\n this.pushChunk(entry, { type: 'exit', data: '', code: 1 });\n });\n\n console.log(`[ai-spawn-manager] Spawned ${opts.cli} (${spawnId}), args: ${opts.args.length}, cwd: ${opts.cwd ?? '(default)'}`);\n return spawnId;\n }\n\n async *stream(spawnId: string, fromOffset: number = 0): AsyncGenerator<{ offset: number; chunk: AiSpawnChunk }> {\n const entry = this.spawns.get(spawnId);\n if (!entry) throw new Error(`AI spawn ${spawnId} not found`);\n\n let offset = fromOffset;\n let resolve: (() => void) | null = null;\n let done = false;\n\n const onChunk = () => {\n if (resolve) { resolve(); resolve = null; }\n };\n const onDone = () => {\n done = true;\n if (resolve) { resolve(); resolve = null; }\n };\n\n entry.emitter.on('chunk', onChunk);\n entry.emitter.on('done', onDone);\n\n // If already finished and offset covers everything, check immediately\n if (entry.status !== 'running' && offset >= entry.buffer.length) {\n done = true;\n }\n\n try {\n while (true) {\n // Yield any buffered chunks from offset\n while (offset < entry.buffer.length) {\n yield { offset, chunk: entry.buffer[offset]! };\n offset++;\n }\n\n // If process finished and no more chunks, we're done\n if (entry.status !== 'running' && offset >= entry.buffer.length) {\n break;\n }\n\n if (done && offset >= entry.buffer.length) break;\n\n // Wait for next chunk\n await new Promise<void>((r) => { resolve = r; });\n }\n } finally {\n entry.emitter.off('chunk', onChunk);\n entry.emitter.off('done', onDone);\n }\n }\n\n kill(spawnId: string): boolean {\n const entry = this.spawns.get(spawnId);\n if (!entry) return false;\n if (entry.proc) {\n try { entry.proc.kill('SIGTERM'); } catch { /* already dead */ }\n return true;\n }\n if (entry.ptyProc) {\n try { entry.ptyProc.kill(); } catch { /* already dead */ }\n return true;\n }\n return false;\n }\n\n // ── PTY mode ────────────────────────────────────────────────────────────\n\n spawnPty(opts: AiSpawnPtyOpts): string {\n const running = [...this.spawns.values()].filter(s => s.status === 'running').length;\n if (running >= MAX_CONCURRENT_SPAWNS) {\n throw new Error(`Max concurrent AI spawns reached (${MAX_CONCURRENT_SPAWNS})`);\n }\n\n const spawnId = randomUUID();\n const emitter = new EventEmitter();\n\n // Resolve env + MCP args via the shared helper (symmetric with spawn).\n // This also injects RUNEYA_BASE_URL / RUNEYA_API_TOKEN into the PTY's own\n // env so `$RUNEYA_API_TOKEN` resolves in the interactive Claude shell.\n const { env, args } = resolveSpawnEnvAndArgs(opts);\n\n const invocation = resolveCliInvocation(opts.cli, args);\n\n const ptyProc = pty.spawn(invocation.command, invocation.args, {\n name: 'xterm-256color',\n cols: opts.cols ?? 120,\n rows: opts.rows ?? 30,\n cwd: opts.cwd || process.cwd(),\n env: env as Record<string, string>,\n });\n\n const entry: AiSpawn = {\n spawnId,\n sessionId: opts.sessionId,\n cli: opts.cli,\n status: 'running',\n exitCode: null,\n buffer: [],\n proc: null,\n ptyProc,\n emitter,\n createdAt: Date.now(),\n doneAt: null,\n acked: false,\n lastChunkAt: null,\n };\n\n this.spawns.set(spawnId, entry);\n\n ptyProc.onData((data: string) => {\n this.pushChunk(entry, { type: 'pty-data', data });\n });\n\n ptyProc.onExit(({ exitCode }) => {\n entry.status = exitCode === 0 ? 'done' : 'error';\n entry.exitCode = exitCode;\n entry.doneAt = Date.now();\n entry.ptyProc = null;\n this.pushChunk(entry, { type: 'exit', data: '', code: exitCode });\n });\n\n console.log(`[ai-spawn-manager] Spawned PTY ${opts.cli} (${spawnId}), args: ${opts.args.length}, cwd: ${opts.cwd ?? '(default)'}, ${opts.cols ?? 120}x${opts.rows ?? 30}`);\n return spawnId;\n }\n\n writePty(spawnId: string, data: string): boolean {\n const entry = this.spawns.get(spawnId);\n if (!entry || !entry.ptyProc) return false;\n try { entry.ptyProc.write(data); return true; } catch { return false; }\n }\n\n /** Return a running PTY spawn matching the given logical sessionId, if any. */\n findPtyBySessionId(sessionId: string): AiSpawnInfo | null {\n for (const entry of this.spawns.values()) {\n if (\n entry.sessionId === sessionId\n && entry.status === 'running'\n && entry.ptyProc !== null\n ) {\n return {\n spawnId: entry.spawnId,\n cli: entry.cli,\n status: entry.status,\n exitCode: entry.exitCode,\n bufferLength: entry.buffer.length,\n createdAt: entry.createdAt,\n doneAt: entry.doneAt,\n lastChunkAt: entry.lastChunkAt,\n };\n }\n }\n return null;\n }\n\n resizePty(spawnId: string, cols: number, rows: number): boolean {\n const entry = this.spawns.get(spawnId);\n if (!entry || !entry.ptyProc) return false;\n try { entry.ptyProc.resize(cols, rows); return true; } catch { return false; }\n }\n\n list(): AiSpawnInfo[] {\n return [...this.spawns.values()].map(e => ({\n spawnId: e.spawnId,\n cli: e.cli,\n status: e.status,\n exitCode: e.exitCode,\n bufferLength: e.buffer.length,\n createdAt: e.createdAt,\n doneAt: e.doneAt,\n lastChunkAt: e.lastChunkAt,\n }));\n }\n\n ack(spawnId: string): boolean {\n const entry = this.spawns.get(spawnId);\n if (!entry) return false;\n entry.acked = true;\n return true;\n }\n\n // ── Internal ────────────────────────────────────────────────────────────\n\n private pushChunk(entry: AiSpawn, chunk: AiSpawnChunk): void {\n // Cap buffer\n if (entry.buffer.length >= MAX_BUFFER_LINES) {\n entry.buffer.shift();\n }\n entry.buffer.push(chunk);\n if (chunk.type === 'stdout' || chunk.type === 'stderr' || chunk.type === 'pty-data') {\n entry.lastChunkAt = Date.now();\n }\n entry.emitter.emit('chunk');\n\n if (chunk.type === 'exit') {\n entry.emitter.emit('done');\n }\n }\n\n private cleanup(): void {\n const now = Date.now();\n for (const [id, entry] of this.spawns) {\n if (entry.status === 'running') {\n // Idle PTY reaper: an interactive PTY with no output for TTL_IDLE_PTY_MS\n // is assumed abandoned. Kill it; onExit flips it to done/error and a\n // later pass deletes it via the normal TTL path.\n if (entry.ptyProc) {\n const idle = now - (entry.lastChunkAt ?? entry.createdAt);\n if (idle > TTL_IDLE_PTY_MS) {\n try { entry.ptyProc.kill(); } catch { /* already dead */ }\n console.log(`[ai-spawn-manager] Reaped idle PTY ${id} (idle ${Math.round(idle / 1000)}s)`);\n }\n }\n continue;\n }\n\n const age = now - (entry.doneAt ?? entry.createdAt);\n\n // Acked: short TTL\n if (entry.acked && age > TTL_ACKED_MS) {\n this.spawns.delete(id);\n console.log(`[ai-spawn-manager] Cleaned up acked spawn ${id}`);\n }\n\n // Unacked: safety net TTL\n if (!entry.acked && age > TTL_UNACKED_MS) {\n this.spawns.delete(id);\n console.log(`[ai-spawn-manager] Cleaned up unacked spawn ${id} (TTL ${TTL_UNACKED_MS}ms)`);\n }\n }\n }\n\n shutdown(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n for (const entry of this.spawns.values()) {\n if (entry.proc) {\n try { entry.proc.kill('SIGTERM'); } catch { /* ignore */ }\n }\n if (entry.ptyProc) {\n try { entry.ptyProc.kill(); } catch { /* ignore */ }\n }\n }\n }\n}\n\nexport const aiSpawnManager = new AiSpawnManager();\n","import { fileURLToPath } from 'node:url';\nimport { createRequire } from 'node:module';\nimport { existsSync } from 'node:fs';\n\n/**\n * Comment brancher le serveur MCP Runeya sur un CLI d'IA.\n *\n * Runeya n'installe rien dans la configuration de la machine : il passe sa\n * config MCP en ligne de commande, au moment où il lance lui-même le CLI. Le\n * `~/.claude.json` ou le `~/.codex/config.toml` de l'utilisateur reste intact,\n * et un CLI lancé à la main depuis un terminal ne voit pas ce serveur.\n *\n * Chaque CLI a sa syntaxe — d'où ce module, seule source de vérité partagée par\n * les deux points de lancement (l'agent, et le serveur en mode local).\n */\n\n/** Variables d'environnement que le serveur MCP attend pour joindre Runeya. */\nexport interface RuneyaMcpEnv {\n RUNEYA_BASE_URL?: string;\n RUNEYA_API_TOKEN?: string;\n /**\n * Le projet de la conversation qui lance ce CLI, s'il y en a un.\n *\n * Le serveur MCP en fait le défaut des tools qui acceptent un `projectId` :\n * sans lui, `list_services` rend tous les projets de la machine, quand\n * l'écran et le prompt n'en montrent qu'un.\n */\n RUNEYA_PROJECT_ID?: string;\n RUNEYA_ORG_ID?: string;\n}\n\n/**\n * Chemin du point d'entrée du serveur MCP, à lancer avec `node`.\n *\n * Ne PAS se fier à `import.meta.url` pour viser `./index.js` : ce module est\n * bundlé dans l'agent et dans le serveur (tsup y bundle les paquets @runeya\n * via `noExternal`), donc\n * `import.meta.url` y désigne le bundle hôte, pas ce paquet. On résout donc le\n * paquet, puis on sonde les emplacements de la version packagée, où les liens\n * symboliques de l'espace de travail n'existent plus.\n */\nexport function resolveMcpServerPath(): string {\n try {\n const req = createRequire(import.meta.url);\n return req.resolve('@runeya/packages-mcp-server');\n } catch { /* pas de node_modules résolvable : on sonde le disque */ }\n\n const candidates = [\n // Build packagé du CLI : dist/agent/index.js et dist/index.js côtoient\n // dist/mcp-server/, copié là par le post-build.\n new URL('../mcp-server/index.js', import.meta.url),\n new URL('./mcp-server/index.js', import.meta.url),\n // Monorepo, depuis un dist d'app.\n new URL('../../../packages/mcp-server/dist/index.js', import.meta.url),\n new URL('../../../../packages/mcp-server/dist/index.js', import.meta.url),\n ];\n for (const c of candidates) {\n const p = fileURLToPath(c);\n if (existsSync(p)) return p;\n }\n throw new Error('Could not locate @runeya/packages-mcp-server (built dist not found)');\n}\n\n/** Ne garde que les variables renseignées : une valeur vide n'aide personne. */\nfunction pickEnv(env: RuneyaMcpEnv): Record<string, string> {\n return {\n ...(env.RUNEYA_BASE_URL ? { RUNEYA_BASE_URL: env.RUNEYA_BASE_URL } : {}),\n ...(env.RUNEYA_API_TOKEN ? { RUNEYA_API_TOKEN: env.RUNEYA_API_TOKEN } : {}),\n ...(env.RUNEYA_PROJECT_ID ? { RUNEYA_PROJECT_ID: env.RUNEYA_PROJECT_ID } : {}),\n ...(env.RUNEYA_ORG_ID ? { RUNEYA_ORG_ID: env.RUNEYA_ORG_ID } : {}),\n };\n}\n\n/**\n * La config MCP de Runeya, au format `mcpServers` attendu par `--mcp-config`.\n *\n * Seul endroit du dépôt où ce JSON se fabrique. `chat.ts` en tenait deux copies\n * qui résolvaient le chemin avec `import.meta.url` — le piège que\n * `resolveMcpServerPath()` documente juste au-dessus : bundlées dans l'app\n * hôte, elles visaient un fichier qui n'existe pas, et le CLI démarrait sans\n * les tools Runeya, en silence.\n */\nexport function runeyaMcpConfig(env: RuneyaMcpEnv): string {\n return JSON.stringify({\n mcpServers: {\n runeya: {\n command: 'node',\n args: [resolveMcpServerPath()],\n env: pickEnv(env),\n },\n },\n });\n}\n\n/**\n * Arguments `--mcp-config` pour le CLI `claude`, qui attend du JSON.\n *\n * Volontairement non strict : le CLI démarre aussi les serveurs MCP de la\n * machine. Cela coûte quelques secondes par lancement, mais l'utilisateur garde\n * ses propres outils.\n */\nexport function claudeMcpArgs(env: RuneyaMcpEnv): string[] {\n return ['--mcp-config', runeyaMcpConfig(env)];\n}\n\n/**\n * Arguments `-c` pour le CLI `codex`, qui attend du TOML.\n *\n * Codex n'a pas d'équivalent de `--mcp-config` : il expose des surcharges de\n * configuration en TOML (`-c chemin.pointé=valeur`), à placer AVANT la\n * sous-commande. Une table inline décrit le serveur en une seule surcharge.\n */\nexport function codexMcpArgs(env: RuneyaMcpEnv): string[] {\n const fields = [\n `command=${tomlString('node')}`,\n `args=[${tomlString(resolveMcpServerPath())}]`,\n ];\n\n const entries = Object.entries(pickEnv(env));\n if (entries.length > 0) {\n const inline = entries.map(([k, v]) => `${k}=${tomlString(v)}`).join(',');\n fields.push(`env={${inline}}`);\n }\n\n return ['-c', `mcp_servers.runeya={${fields.join(',')}}`];\n}\n\n/**\n * Chaîne TOML de base : seuls la contre-oblique et le guillemet doivent être\n * échappés. Les caractères de contrôle, eux, sont interdits par le format — un\n * chemin ou un jeton qui en contiendrait casserait la config en silence.\n */\nfunction tomlString(value: string): string {\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/[\\u0000-\\u001f\\u007f]/g, (c) => `\\\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`);\n return `\"${escaped}\"`;\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline';\nimport { EventEmitter } from 'node:events';\nimport { codexMcpArgs } from '@runeya/packages-mcp-server/launch';\nimport { resolveCliInvocation } from '@runeya/packages-shared/node';\n\ninterface PendingRequest {\n resolve: (result: unknown) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\nconst REQUEST_TIMEOUT_MS = 300_000; // 5 min — turns can be long\n\n/**\n * Surcharges `-c` qui branchent le serveur MCP Runeya sur `codex app-server`.\n *\n * Le pendant de ce que `ai-spawn-manager` fait pour `claude` : rien n'est écrit\n * dans le `~/.codex/config.toml` de l'utilisateur, la config ne vit que le temps\n * du process. Les surcharges doivent précéder la sous-commande.\n *\n * Sans jeton Runeya, le serveur MCP ne pourrait rien appeler : on n'injecte donc\n * rien plutôt que de faire démarrer un serveur inutile à chaque lancement.\n */\nfunction resolveMcpArgs(env: NodeJS.ProcessEnv): string[] {\n if (!env['RUNEYA_API_TOKEN']) return [];\n try {\n return codexMcpArgs({\n RUNEYA_BASE_URL: env['RUNEYA_BASE_URL'],\n RUNEYA_API_TOKEN: env['RUNEYA_API_TOKEN'],\n });\n } catch (err) {\n console.warn('[codex-app-server-mgr] Failed to resolve MCP server path:', (err as Error).message);\n return [];\n }\n}\n\nclass CodexAppServerManager extends EventEmitter {\n private proc: ChildProcess | null = null;\n private rl: ReadlineInterface | null = null;\n private nextId = 1;\n private pending = new Map<number, PendingRequest>();\n private connected = false;\n private connecting: Promise<void> | null = null;\n\n private extraEnv: Record<string, string> = {};\n\n /** Ensure the app-server is running and initialized. Lazy — first call spawns it. */\n async ensureConnected(env?: Record<string, string>): Promise<void> {\n // Merge env vars — they'll be used on next spawn if not already connected\n if (env) Object.assign(this.extraEnv, env);\n if (this.connected) return;\n if (this.connecting) { await this.connecting; return; }\n\n this.connecting = this.doConnect();\n try {\n await this.connecting;\n } finally {\n this.connecting = null;\n }\n }\n\n private async doConnect(): Promise<void> {\n const env = { ...process.env, ...this.extraEnv };\n\n // Windows : shim `.cmd` — inchangé sur POSIX (voir resolveCliInvocation).\n const invocation = resolveCliInvocation('codex', [...resolveMcpArgs(env), 'app-server']);\n this.proc = spawn(invocation.command, invocation.args, {\n windowsHide: true,\n stdio: ['pipe', 'pipe', 'pipe'],\n env,\n });\n\n this.rl = createInterface({ input: this.proc.stdout! });\n this.rl.on('line', (line) => this.handleLine(line));\n\n this.proc.stderr!.on('data', (chunk: Buffer) => {\n console.warn(`[codex-app-server-mgr] stderr: ${chunk.toString('utf-8').trim()}`);\n });\n\n this.proc.on('exit', (code, signal) => {\n console.warn(`[codex-app-server-mgr] exited code=${code} signal=${signal}`);\n this.rejectAllPending(new Error(`codex app-server exited (code=${code})`));\n this.connected = false;\n this.proc = null;\n this.rl = null;\n this.emit('exit', code);\n });\n\n this.proc.on('error', (err) => {\n console.error(`[codex-app-server-mgr] spawn error:`, err.message);\n this.rejectAllPending(err);\n this.connected = false;\n this.proc = null;\n });\n\n // Initialize handshake\n await this.sendRequest('initialize', {\n clientInfo: { name: 'runeya-agent', title: 'Runeya Agent', version: '1.0.0' },\n capabilities: { experimentalApi: false },\n });\n this.writeLine({ method: 'initialized', params: {} });\n this.connected = true;\n console.log('[codex-app-server-mgr] Connected and initialized');\n }\n\n /** Forward a JSON-RPC request to the app-server and return the result. */\n async sendRequest(method: string, params: Record<string, unknown>): Promise<unknown> {\n if (!this.proc?.stdin?.writable) {\n throw new Error('codex app-server not connected');\n }\n const id = this.nextId++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error(`Request ${method} (id=${id}) timed out`));\n }, REQUEST_TIMEOUT_MS);\n this.pending.set(id, { resolve, reject, timer });\n this.writeLine({ jsonrpc: '2.0', method, id, params });\n });\n }\n\n /** Register a listener for all notifications. Returns unsubscribe function. */\n onNotification(handler: (method: string, params: Record<string, unknown>) => void): () => void {\n const wrapper = (method: string, params: Record<string, unknown>) => handler(method, params);\n this.on('notification', wrapper);\n return () => { this.off('notification', wrapper); };\n }\n\n get isConnected(): boolean { return this.connected; }\n\n shutdown(): void {\n if (this.proc) {\n try { this.proc.kill('SIGTERM'); } catch { /* ignore */ }\n }\n this.connected = false;\n this.rl?.close();\n this.rl = null;\n this.proc = null;\n this.rejectAllPending(new Error('Shutdown'));\n }\n\n private writeLine(obj: Record<string, unknown>): void {\n if (!this.proc?.stdin?.writable) return;\n this.proc.stdin.write(JSON.stringify(obj) + '\\n');\n }\n\n private handleLine(line: string): void {\n const trimmed = line.trim();\n if (!trimmed) return;\n\n let msg: Record<string, unknown>;\n try { msg = JSON.parse(trimmed); } catch { return; }\n\n // Response to pending request\n if ('id' in msg && typeof msg['id'] === 'number' && ('result' in msg || 'error' in msg)) {\n const p = this.pending.get(msg['id'] as number);\n if (p) {\n this.pending.delete(msg['id'] as number);\n clearTimeout(p.timer);\n if ('error' in msg && msg['error']) {\n const err = msg['error'] as { code: number; message: string };\n p.reject(new Error(`JSON-RPC error ${err.code}: ${err.message}`));\n } else {\n p.resolve(msg['result']);\n }\n }\n return;\n }\n\n // Notification (no id, has method)\n if ('method' in msg && typeof msg['method'] === 'string' && !('id' in msg)) {\n this.emit('notification', msg['method'] as string, (msg['params'] ?? {}) as Record<string, unknown>);\n }\n }\n\n private rejectAllPending(error: Error): void {\n for (const [, p] of this.pending) {\n clearTimeout(p.timer);\n p.reject(error);\n }\n this.pending.clear();\n }\n}\n\nexport const codexAppServerManager = new CodexAppServerManager();\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst ROOT_DIR_NAME = 'runeya-ai-context';\n\n/** Sanitize a filename so it stays on a single path segment and only contains safe chars. */\nfunction sanitizeName(name: string): string {\n // Replace path separators / unsafe chars with `_`. Keep [A-Za-z0-9._-].\n let safe = name.replace(/[^A-Za-z0-9._-]/g, '_');\n // Avoid empty / leading-dot weirdness.\n if (!safe || safe === '.' || safe === '..') safe = 'context';\n // Append `.md` if no extension.\n if (!/\\.[A-Za-z0-9]+$/.test(safe)) safe += '.md';\n return safe;\n}\n\nfunction sanitizeSessionId(sessionId: string): string {\n const safe = sessionId.replace(/[^A-Za-z0-9._-]/g, '_');\n return safe || 'session';\n}\n\nexport interface ContextFileInput {\n name: string;\n content: string;\n}\n\n/**\n * Write context files to <os.tmpdir()>/runeya-ai-context/<sessionId>/<sanitized-name>.\n * Returns absolute paths in input order.\n */\nexport async function writeContextFiles(\n sessionId: string,\n files: ContextFileInput[],\n): Promise<string[]> {\n const baseDir = path.join(os.tmpdir(), ROOT_DIR_NAME, sanitizeSessionId(sessionId));\n await mkdir(baseDir, { recursive: true });\n\n const paths: string[] = [];\n const usedNames = new Set<string>();\n for (let i = 0; i < files.length; i++) {\n const file = files[i]!;\n let name = sanitizeName(file.name);\n // Deduplicate within this batch.\n if (usedNames.has(name)) {\n const ext = path.extname(name);\n const base = name.slice(0, name.length - ext.length);\n name = `${base}-${i}${ext}`;\n }\n usedNames.add(name);\n const fullPath = path.join(baseDir, name);\n await writeFile(fullPath, file.content, 'utf8');\n paths.push(fullPath);\n }\n return paths;\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport { spawn } from 'node:child_process';\n\nconst TMP_DIR_NAME = 'runeya-ai-paste';\n\nconst MIME_TO_EXT: Record<string, string> = {\n 'image/png': 'png',\n 'image/jpeg': 'jpg',\n 'image/jpg': 'jpg',\n 'image/gif': 'gif',\n 'image/webp': 'webp',\n 'image/bmp': 'bmp',\n};\n\nfunction extForMime(mime: string): string {\n return MIME_TO_EXT[mime.toLowerCase()] ?? 'png';\n}\n\n/** Run a shell command, optionally piping a buffer to stdin. Resolves with exitCode. */\nfunction runCmd(\n cmd: string,\n args: string[],\n stdin?: Buffer,\n timeoutMs = 5000,\n): Promise<{ code: number; stderr: string }> {\n return new Promise((resolve) => {\n let settled = false;\n const settle = (code: number, stderr: string) => {\n if (settled) return;\n settled = true;\n resolve({ code, stderr });\n };\n try {\n const child = spawn(cmd, args, { stdio: ['pipe', 'ignore', 'pipe'], windowsHide: true });\n let stderr = '';\n child.stderr.on('data', (c) => { stderr += c.toString(); });\n child.on('error', (err) => settle(127, err.message));\n child.on('exit', (code) => settle(code ?? 1, stderr));\n const t = setTimeout(() => {\n try { child.kill('SIGKILL'); } catch { /* ignore */ }\n settle(124, 'timeout');\n }, timeoutMs);\n child.on('exit', () => clearTimeout(t));\n if (stdin) {\n child.stdin.on('error', () => { /* swallow EPIPE */ });\n child.stdin.end(stdin);\n } else {\n child.stdin.end();\n }\n } catch (err) {\n settle(127, (err as Error).message);\n }\n });\n}\n\ntype ClipboardMethod = 'xclip' | 'wl-copy' | 'pbcopy' | 'powershell' | null;\n\nexport interface PasteImageResult {\n tmpPath: string;\n clipboardMethod: ClipboardMethod;\n clipboardError?: string;\n}\n\n/**\n * Save a pasted image (base64) to a tmp file on disk and try to populate the\n * agent's system clipboard with it (so Claude's native paste detection picks\n * it up). Falls back to file-only injection (`@path`) if no clipboard tool is\n * available.\n */\nexport async function savePastedImage(\n base64: string,\n mimeType: string,\n sessionId: string | undefined,\n): Promise<PasteImageResult> {\n const buf = Buffer.from(base64, 'base64');\n if (buf.length === 0) throw new Error('Empty image payload');\n\n const ext = extForMime(mimeType);\n const baseDir = path.join(\n os.tmpdir(),\n TMP_DIR_NAME,\n sessionId ? sessionId.replaceAll(/[^A-Za-z0-9._-]/g, '_') : 'default',\n );\n await mkdir(baseDir, { recursive: true });\n const tmpPath = path.join(baseDir, `paste-${Date.now()}-${randomUUID().slice(0, 8)}.${ext}`);\n await writeFile(tmpPath, buf);\n\n const { method, error } = await tryWriteClipboard(buf, mimeType, tmpPath);\n\n return { tmpPath, clipboardMethod: method, clipboardError: error };\n}\n\nasync function tryWriteClipboard(\n buf: Buffer,\n mimeType: string,\n tmpPath: string,\n): Promise<{ method: ClipboardMethod; error?: string }> {\n const normalizedMime = mimeType.toLowerCase();\n const errors: string[] = [];\n\n if (process.platform === 'darwin') {\n // macOS: use osascript with a typed file reference. Only PNG/JPEG/TIFF\n // are well-supported as clipboard image types; for others, fall through.\n const klass = normalizedMime === 'image/jpeg' || normalizedMime === 'image/jpg'\n ? 'JPEG picture'\n : 'PNGf';\n const script = `set the clipboard to (read (POSIX file \"${tmpPath.replaceAll('\"', '\\\\\"')}\") as «class ${klass}»)`;\n const r = await runCmd('osascript', ['-e', script]);\n if (r.code === 0) return { method: 'pbcopy' };\n errors.push(`osascript: ${r.stderr.trim()}`);\n }\n\n // Linux X11 — xclip\n if (process.platform === 'linux') {\n const r = await runCmd('xclip', ['-selection', 'clipboard', '-t', normalizedMime, '-i'], buf);\n if (r.code === 0) return { method: 'xclip' };\n errors.push(`xclip: ${r.stderr.trim() || `exit ${r.code}`}`);\n\n // Linux Wayland — wl-copy\n const r2 = await runCmd('wl-copy', ['--type', normalizedMime], buf);\n if (r2.code === 0) return { method: 'wl-copy' };\n errors.push(`wl-copy: ${r2.stderr.trim() || `exit ${r2.code}`}`);\n }\n\n if (process.platform === 'win32') {\n // PowerShell: load image from disk, set as clipboard image.\n const ps = `Add-Type -AssemblyName System.Windows.Forms; ` +\n `Add-Type -AssemblyName System.Drawing; ` +\n `$img = [System.Drawing.Image]::FromFile(\"${tmpPath.replaceAll('\\\\', '\\\\\\\\')}\"); ` +\n `[System.Windows.Forms.Clipboard]::SetImage($img); $img.Dispose()`;\n const r = await runCmd('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', ps]);\n if (r.code === 0) return { method: 'powershell' };\n errors.push(`powershell: ${r.stderr.trim() || `exit ${r.code}`}`);\n }\n\n return { method: null, error: errors.join(' | ') || 'no clipboard tool available' };\n}\n\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { readFile, readdir, stat, realpath, writeFile, mkdir, rename, rm } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport type { Dirent } from 'node:fs';\nimport { resolve as resolvePath, join, relative, sep } from 'node:path';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { expandEnvVar } from '../../utils/env.js';\n\nconst CWD_SCHEMA = z.string().min(1).max(4096);\nconst REL_PATH_SCHEMA = z\n .string()\n .min(1)\n .max(512)\n .regex(/^[A-Za-z0-9_./-]+$/)\n .refine((p) => !p.includes('..') && !p.startsWith('/'), {\n message: 'Path must be a relative path without traversal',\n });\n\nconst MAX_FILES = 500;\nconst MAX_DEPTH = 8;\nconst MAX_FILE_BYTES = 2_000_000;\nconst IGNORED_DIRS = new Set([\n 'node_modules', '.git', 'dist', 'build', '.next', '.turbo',\n '.cache', 'coverage', '.yarn', '.pnpm-store', 'target', 'out',\n]);\n\ntype RepoFileEntry = { type: 'file'; name: string; path: string };\ntype RepoDirEntry = { type: 'dir'; name: string; path: string; children: RepoEntry[] };\nexport type RepoEntry = RepoFileEntry | RepoDirEntry;\n\nconst RepoEntrySchema: z.ZodType<RepoEntry> = z.lazy(() => z.union([\n z.object({ type: z.literal('file'), name: z.string(), path: z.string() }),\n z.object({ type: z.literal('dir'), name: z.string(), path: z.string(), children: z.array(RepoEntrySchema) }),\n]));\n\nasync function walkMarkdown(root: string, dir: string, depth: number, counter: { n: number }): Promise<RepoEntry[]> {\n if (depth > MAX_DEPTH || counter.n >= MAX_FILES) return [];\n let entries: Dirent[];\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n const out: RepoEntry[] = [];\n for (const e of entries) {\n if (counter.n >= MAX_FILES) break;\n if (e.name.startsWith('.') && e.name !== '.') continue;\n const abs = join(dir, e.name);\n const rel = relative(root, abs).split(sep).join('/');\n if (e.isDirectory()) {\n if (IGNORED_DIRS.has(e.name)) continue;\n const children = await walkMarkdown(root, abs, depth + 1, counter);\n out.push({ type: 'dir', name: e.name, path: rel, children });\n } else if (e.isFile() && /\\.(md|markdown)$/i.test(e.name)) {\n counter.n += 1;\n out.push({ type: 'file', name: e.name, path: rel });\n }\n }\n out.sort((a, b) => {\n if (a.type !== b.type) return a.type === 'dir' ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n return out;\n}\n\n/**\n * Resolve a relative path inside the root with traversal protection.\n * If `requireExist`, the target must exist on disk (uses realpath).\n * Otherwise resolves the parent's realpath and joins the leaf — this allows\n * creating new files/dirs while still preventing escape via symlinks.\n */\nasync function resolveSafePath(root: string, relPath: string, requireExist: boolean): Promise<string> {\n if (relPath.includes('..') || relPath.startsWith('/')) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Chemin invalide' });\n }\n const target = resolvePath(root, relPath);\n if (requireExist) {\n let real: string;\n try { real = await realpath(target); } catch {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Chemin introuvable' });\n }\n if (real !== root && !(real + sep).startsWith(root + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Hors du dossier autorisé' });\n }\n return real;\n }\n // For non-existing targets: check parent\n const parent = dirname(target);\n let realParent: string;\n try { realParent = await realpath(parent); } catch {\n // Parent doesn't exist either — must be created via createDir first or\n // the operation will create parents itself.\n realParent = parent;\n }\n if (realParent !== root && !(realParent + sep).startsWith(root + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Hors du dossier autorisé' });\n }\n // Reassemble the safe absolute path with the verified parent\n return resolvePath(realParent, target.slice(parent.length).replace(/^[\\\\/]+/, ''));\n}\n\nasync function resolveRoot(cwd: string): Promise<string> {\n const expanded = expandEnvVar(cwd);\n const abs = resolvePath(expanded);\n try {\n return await realpath(abs);\n } catch {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Dossier introuvable: ${abs}` });\n }\n}\n\nexport const wikiRouter = router({\n listRepoMarkdown: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .query(async ({ input }) => {\n const root = await resolveRoot(input.cwd);\n const counter = { n: 0 };\n const entries = await walkMarkdown(root, root, 0, counter);\n return { root, entries, truncated: counter.n >= MAX_FILES };\n }),\n\n readRepoMarkdown: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, path: REL_PATH_SCHEMA }))\n .query(async ({ input }) => {\n if (!/\\.(md|markdown)$/i.test(input.path)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Seuls les .md sont autorisés' });\n }\n const root = await resolveRoot(input.cwd);\n const target = resolvePath(root, input.path);\n let realTarget: string;\n try {\n realTarget = await realpath(target);\n } catch {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Fichier introuvable' });\n }\n const realTargetWithSep = realTarget + sep;\n if (realTarget !== root && !realTargetWithSep.startsWith(root + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Hors du dossier du service' });\n }\n const s = await stat(realTarget);\n if (!s.isFile()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Pas un fichier' });\n }\n if (s.size > MAX_FILE_BYTES) {\n throw new TRPCError({ code: 'PAYLOAD_TOO_LARGE', message: 'Fichier trop volumineux' });\n }\n const content = await readFile(realTarget, 'utf-8');\n return { path: input.path, content };\n }),\n\n writeMarkdown: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n path: REL_PATH_SCHEMA,\n content: z.string().max(5_000_000),\n }))\n .mutation(async ({ input }) => {\n if (!/\\.(md|markdown)$/i.test(input.path)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Seuls les .md/.markdown sont autorisés' });\n }\n const root = await resolveRoot(input.cwd);\n const target = await resolveSafePath(root, input.path, false);\n // Ensure parent exists\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, input.content, 'utf-8');\n return { path: input.path, ok: true };\n }),\n\n createFile: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, path: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n if (!/\\.(md|markdown)$/i.test(input.path)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Seuls les .md/.markdown sont autorisés' });\n }\n const root = await resolveRoot(input.cwd);\n const target = await resolveSafePath(root, input.path, false);\n // Refuse to overwrite existing\n try {\n await stat(target);\n throw new TRPCError({ code: 'CONFLICT', message: 'Fichier déjà existant' });\n } catch (err) {\n if (err instanceof TRPCError) throw err;\n // ENOENT — good, proceed\n }\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, '', 'utf-8');\n return { path: input.path, ok: true };\n }),\n\n createDir: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, path: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n const root = await resolveRoot(input.cwd);\n const target = await resolveSafePath(root, input.path, false);\n await mkdir(target, { recursive: true });\n return { path: input.path, ok: true };\n }),\n\n renamePath: protectedProcedure\n .input(z.object({\n cwd: CWD_SCHEMA,\n fromPath: REL_PATH_SCHEMA,\n toPath: REL_PATH_SCHEMA,\n }))\n .mutation(async ({ input }) => {\n const root = await resolveRoot(input.cwd);\n const from = await resolveSafePath(root, input.fromPath, true);\n const to = await resolveSafePath(root, input.toPath, false);\n // Refuse to overwrite an existing target\n try {\n await stat(to);\n throw new TRPCError({ code: 'CONFLICT', message: 'La cible existe déjà' });\n } catch (err) {\n if (err instanceof TRPCError) throw err;\n }\n await mkdir(dirname(to), { recursive: true });\n await rename(from, to);\n return { fromPath: input.fromPath, toPath: input.toPath, ok: true };\n }),\n\n ensureRoot: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA }))\n .mutation(async ({ input }) => {\n const expanded = expandEnvVar(input.cwd);\n const abs = resolvePath(expanded);\n await mkdir(abs, { recursive: true });\n const root = await realpath(abs);\n return { root, ok: true };\n }),\n\n deletePath: protectedProcedure\n .input(z.object({ cwd: CWD_SCHEMA, path: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n const root = await resolveRoot(input.cwd);\n const target = await resolveSafePath(root, input.path, true);\n if (target === root) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Impossible de supprimer la racine' });\n }\n await rm(target, { recursive: true, force: true });\n return { path: input.path, ok: true };\n }),\n});\n\n","import { router } from './trpc.js';\nimport { processRouter } from './routers/process.js';\nimport { healthRouter } from './routers/health.js';\nimport { configRouter } from './routers/config.js';\nimport { terminalRouter } from './routers/terminal.js';\nimport { gitRouter } from './routers/git.js';\nimport { aiRouter } from './routers/ai.js';\nimport { wikiRouter } from './routers/wiki.js';\n\nexport const appRouter = router({\n process: processRouter,\n health: healthRouter,\n config: configRouter,\n terminal: terminalRouter,\n git: gitRouter,\n ai: aiRouter,\n wiki: wikiRouter,\n});\n\n","import type { Server } from 'node:http';\nimport { createAgent } from './create-agent.js';\nimport { env } from './config/env.js';\nimport { ensureNodeBinOnPath, ensureUserBinsOnPath, stampConsole } from '@runeya/packages-shared/node';\n\n/**\n * Listen with retry for EADDRINUSE — handles the race condition when the CLI\n * restarts the server before the old agent has fully released the port.\n */\nfunction listenWithRetry(\n server: Server,\n port: number,\n host: string,\n maxRetries = 20,\n delay = 500,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n\n const tryListen = () => {\n const onError = (err: NodeJS.ErrnoException) => {\n // Clean up the 'listening' callback that server.listen() registered\n server.removeAllListeners('listening');\n\n if (err.code === 'EADDRINUSE' && attempts < maxRetries) {\n attempts++;\n console.log(`[agent] Port ${port} in use, retrying in ${delay}ms (${attempts}/${maxRetries})...`);\n setTimeout(tryListen, delay);\n } else {\n reject(err);\n }\n };\n\n server.once('error', onError);\n server.listen(port, host, () => {\n server.removeListener('error', onError);\n resolve();\n });\n };\n\n tryListen();\n });\n}\n\n// Node.js recursive fs.watch can throw ENOENT when a directory disappears\n// between the inotify notification and the internal readdirSync call.\n// Despite having .on('error') handlers, some Node versions emit the error\n// before the handler can catch it. Prevent agent crash for these benign errors.\nprocess.on('uncaughtException', (err: NodeJS.ErrnoException) => {\n if (err.code === 'ENOENT' && err.syscall === 'scandir') {\n console.warn(`[agent] Ignoring transient FSWatcher ENOENT: ${err.path}`);\n return;\n }\n console.error('[agent] Uncaught exception:', err);\n process.exit(1);\n});\n\nasync function main() {\n // Avant tout lancement de service : ce que l'agent hérite ici est ce que\n // chaque processus enfant héritera de lui.\n ensureNodeBinOnPath();\n // Puis ce que l'utilisateur a installé pour lui-même (claude, codex…) : un\n // raccourci de bureau n'hérite pas du PATH de son shell de connexion.\n await ensureUserBinsOnPath();\n\n // L'agent est un process à part, même lancé par le serveur : son `console`\n // n'est pas celui du CLI, et son delta part de son propre démarrage.\n stampConsole();\n\n const { server, shutdown, passphraseHex } = createAgent({\n passphraseHex: env.PASSPHRASE_OVERRIDE,\n });\n\n let shuttingDown = false;\n const gracefulShutdown = async () => {\n if (shuttingDown) {\n process.exit(1);\n }\n shuttingDown = true;\n console.log('Shutting down agent...');\n await shutdown();\n process.exit(0);\n };\n\n // Register before listenWithRetry so Ctrl+C works during the retry loop.\n process.on('SIGTERM', gracefulShutdown);\n process.on('SIGINT', gracefulShutdown);\n\n await listenWithRetry(server, env.RUNEYA_AGENT_PORT, env.RUNEYA_AGENT_HOST);\n // Print passphrase AFTER server is listening so the spawner's\n // first health check finds the HTTP server ready.\n //\n // Écrite sur stdout SANS passer par `console` : cette ligne n'est pas un\n // journal, c'est le canal par lequel le serveur récupère la passphrase, et il\n // la reconnaît sur un motif ancré en début de ligne. Un horodatage devant\n // l'aurait rendue invisible — le serveur attendait alors son délai entier\n // avant de renoncer.\n process.stdout.write(`RUNEYA_PASSPHRASE=${passphraseHex}\\n`);\n console.log(`Agent listening on ${env.RUNEYA_AGENT_HOST}:${env.RUNEYA_AGENT_PORT}`);\n}\n\nmain().catch((err) => {\n console.error('Failed to start agent:', err);\n process.exit(1);\n});\n"],"mappings":"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","names":["crypto","z","TRPCError","EventEmitter","randomUUID","homedir","platform","join","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","env","escape","env","resolve","execa","homedir","expandEnvVars","resolve","env","process","randomUUID","indexed","randomUUID","directive","pid","EventEmitter","fastId","stat","EventEmitter","idCounter","fastId","EventEmitter","logIdCounter","fastId","MAX_RETRIES","rows","resolve","EventEmitter","resolve","EventEmitter","EventEmitter","execa","homedir","z","execFile","mkdir","writeFile","access","join","homedir","join","homedir","writeFile","mkdir","resolve","execFile","readdir","stat","access","z","env","homedir","resolveCwd","shellwordsSplit","env","EventEmitter","path","resolveCwd","execa","z","z","join","platform","homedir","EventEmitter","env","randomUUID","resolve","z","TRPCError","resolve","networkInterfaces","homedir","platform","execFile","homedir","join","delimiter","execFile","join","homedir","delimiter","path","startedAt","execFile","existsSync","dirname","resolve","execFile","randomBytes","createCipheriv","createDecipheriv","getLanIp","networkInterfaces","platform","homedir","z","TRPCError","EventEmitter","randomUUID","z","TRPCError","resolve","z","TRPCError","execFile","spawn","promisify","existsSync","fsPromises","join","resolvePath","execFile","promisify","execFileAsync","path","execFileAsync","promisify","execFile","z","env","TRPCError","existsSync","Y","resolvePath","fsPromises","resolve","modified","join","spawn","z","TRPCError","spawn","EventEmitter","randomUUID","pty","existsSync","env","env","randomUUID","EventEmitter","spawn","resolve","spawn","createInterface","EventEmitter","env","EventEmitter","spawn","createInterface","resolve","mkdir","writeFile","os","mkdir","writeFile","path","os","randomUUID","spawn","resolve","t","z","TRPCError","resolve","z","TRPCError","readFile","stat","writeFile","mkdir","rename","dirname","resolvePath","join","CWD_SCHEMA","z","join","TRPCError","resolvePath","dirname","stat","readFile","mkdir","writeFile","rename","crypto","resolve","resolve"]}
|