@hermespilot/link 0.1.6 → 0.1.7

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.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/http/app.ts","../src/constants.ts","../src/runtime/paths.ts","../src/storage/atomic-json.ts","../src/config/config.ts","../src/conversations/conversation-service.ts","../src/hermes/api-server.ts","../src/hermes/config.ts","../src/http/errors.ts","../src/hermes/cli.ts","../src/hermes/profiles.ts","../src/identity/identity.ts","../src/pairing/pairing.ts","../src/security/devices.ts","../src/relay/bootstrap.ts","../src/topology/network.ts","../src/security/app-connect-token.ts","../src/runtime/logger.ts"],"sourcesContent":["import Koa from 'koa'\nimport Router from '@koa/router'\nimport type { ServerResponse } from 'node:http'\nimport { Readable } from 'node:stream'\nimport { LINK_VERSION } from '../constants.js'\nimport { loadConfig } from '../config/config.js'\nimport { ConversationService, type ConversationEvent } from '../conversations/conversation-service.js'\nimport { LinkHttpError, isLinkHttpError } from './errors.js'\nimport {\n cancelHermesRun,\n createHermesRun,\n listHermesModels,\n streamHermesRunEvents,\n} from '../hermes/api-server.js'\nimport {\n createHermesProfile,\n deleteHermesProfile,\n getHermesProfileStatus,\n listHermesProfiles,\n renameHermesProfile,\n useHermesProfile,\n} from '../hermes/profiles.js'\nimport { loadIdentity } from '../identity/identity.js'\nimport { claimPairing, recordPairingClaim } from '../pairing/pairing.js'\nimport {\n authenticateDeviceAccessToken,\n refreshDeviceSession,\n revokeDeviceRefreshToken,\n type DeviceRecord,\n} from '../security/devices.js'\nimport { verifyAppConnectToken } from '../security/app-connect-token.js'\nimport { createFileLogger, readRecentLogEntries, type FileLogger } from '../runtime/logger.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\nimport { discoverRouteCandidates } from '../topology/network.js'\n\ninterface AuthContext {\n kind: 'device' | 'app-connect'\n device?: DeviceRecord\n accountId?: string\n}\n\nconst MAX_JSON_BODY_BYTES = 1024 * 1024\nconst MAX_BLOB_UPLOAD_BYTES = 50 * 1024 * 1024\n\nexport interface CreateAppOptions {\n paths?: RuntimePaths\n logger?: FileLogger\n onPairingClaimed?: () => void | Promise<void>\n}\n\nexport async function createApp(options: CreateAppOptions = {}): Promise<Koa> {\n const paths = options.paths ?? resolveRuntimePaths()\n const logger = options.logger ?? createFileLogger({ paths })\n const conversations = new ConversationService(paths, logger)\n const app = new Koa()\n const router = new Router()\n\n app.use(async (ctx, next) => {\n const startedAt = Date.now()\n try {\n await next()\n } catch (error) {\n const profileError = error instanceof Error && error.message === 'invalid profile name'\n const status = isLinkHttpError(error) ? error.status : profileError ? 400 : 500\n ctx.status = status\n ctx.body = {\n ok: false,\n error: {\n code: isLinkHttpError(error) ? error.code : status === 400 ? 'invalid_profile_name' : 'internal_error',\n message: error instanceof Error ? error.message : 'Internal error',\n },\n }\n void logger.write(status >= 500 ? 'error' : 'warn', 'http_request_failed', {\n method: ctx.method,\n path: ctx.path,\n status,\n code: isLinkHttpError(error) ? error.code : status === 400 ? 'invalid_profile_name' : 'internal_error',\n error: error instanceof Error ? error.message : String(error),\n })\n } finally {\n void logger.info('http_request', {\n method: ctx.method,\n path: ctx.path,\n status: ctx.status,\n duration_ms: Date.now() - startedAt,\n })\n }\n })\n\n router.get('/api/v1/bootstrap', async (ctx) => {\n const [identity, config] = await Promise.all([loadIdentity(paths), loadConfig(paths)])\n const routes = identity?.link_id\n ? await discoverRouteCandidates({\n port: config.port,\n relayBaseUrl: config.relayBaseUrl,\n linkId: identity.link_id,\n installId: identity.install_id,\n publicKeyPem: identity.public_key_pem,\n })\n : null\n ctx.set('cache-control', 'no-store')\n ctx.body = {\n link_id: identity?.link_id ?? null,\n display_name: identity?.link_id ? 'Hermes Link' : 'Unpaired Hermes Link',\n version: LINK_VERSION,\n api_version: 1,\n paired: Boolean(identity?.link_id),\n pairing_supported: Boolean(identity?.link_id),\n preferred_pairing_urls: routes?.preferredUrls ?? [],\n routes: routes ? routeObjects(routes.preferredUrls) : [],\n capabilities: {\n runs: true,\n sse: true,\n relay: true,\n profiles: true,\n logs: true,\n conversations: true,\n conversation_delete: true,\n blobs: true,\n },\n }\n })\n\n router.post('/api/v1/pairing/claim', async (ctx) => {\n const body = await readJsonBody(ctx.req)\n const sessionId = readString(body, 'session_id') ?? readString(body, 'sessionId')\n const claimToken = readString(body, 'claim_token') ?? readString(body, 'claimToken')\n if (!sessionId || !claimToken) {\n throw new LinkHttpError(400, 'pairing_claim_invalid', 'session_id and claim_token are required')\n }\n const claimed = await claimPairing({\n sessionId,\n claimToken,\n deviceLabel: readString(body, 'device_label') ?? readString(body, 'deviceLabel') ?? 'HermesPilot App',\n devicePlatform: readString(body, 'device_platform') ?? readString(body, 'devicePlatform') ?? 'unknown',\n paths,\n })\n ctx.body = claimed\n void logger.info('pairing_claimed', {\n device_id: claimed.device.device_id,\n device_platform: claimed.device.platform,\n })\n const timer = setTimeout(() => {\n void recordPairingClaim(\n {\n sessionId,\n deviceId: claimed.device.device_id,\n deviceLabel: claimed.device.label,\n devicePlatform: claimed.device.platform,\n },\n paths,\n ).catch((error: unknown) => {\n void logger.warn('pairing_claim_record_failed', {\n session_id: sessionId,\n error: error instanceof Error ? error.message : String(error),\n })\n })\n void options.onPairingClaimed?.()\n }, 250)\n timer.unref?.()\n })\n\n router.get('/api/v1/auth/me', async (ctx) => {\n const auth = await authenticateRequest(ctx, paths)\n const identity = await loadRequiredIdentity(paths)\n ctx.body = {\n ok: true,\n auth: { kind: auth.kind, account_id: auth.accountId ?? null },\n link: {\n link_id: identity.link_id,\n display_name: 'Hermes Link',\n },\n device: auth.device\n ? {\n id: auth.device.id,\n device_id: auth.device.id,\n label: auth.device.label,\n platform: auth.device.platform,\n scope: auth.device.scope,\n }\n : null,\n }\n })\n\n router.post('/api/v1/auth/refresh', async (ctx) => {\n const body = await readJsonBody(ctx.req)\n const refreshToken = readString(body, 'refresh_token') ?? readString(body, 'refreshToken')\n if (!refreshToken) {\n throw new LinkHttpError(400, 'refresh_token_required', 'refresh_token is required')\n }\n const session = await refreshDeviceSession(refreshToken, paths)\n ctx.body = {\n ok: true,\n device: session.device,\n access_token: {\n token: session.accessToken.token,\n expires_at: session.accessToken.expiresAt,\n },\n refresh_token: {\n token: session.refreshToken.token,\n expires_at: session.refreshToken.expiresAt,\n },\n }\n })\n\n router.post('/api/v1/auth/logout', async (ctx) => {\n const body = await readJsonBody(ctx.req)\n const refreshToken = readString(body, 'refresh_token') ?? readString(body, 'refreshToken')\n if (refreshToken) {\n await revokeDeviceRefreshToken(refreshToken, paths)\n }\n ctx.body = { ok: true }\n })\n\n router.get('/api/v1/status', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const [identity, config] = await Promise.all([loadIdentity(paths), loadConfig(paths)])\n ctx.body = {\n ok: true,\n version: LINK_VERSION,\n paired: Boolean(identity?.link_id),\n link_id: identity?.link_id ?? null,\n port: config.port,\n }\n })\n\n router.get('/api/v1/logs', async (ctx) => {\n await authenticateRequest(ctx, paths)\n ctx.set('cache-control', 'no-store')\n ctx.body = {\n ok: true,\n logs: await readRecentLogEntries({\n paths,\n limit: readLimit(ctx.query.limit),\n }),\n }\n })\n\n router.get('/api/v1/models', async (ctx) => {\n await authenticateRequest(ctx, paths)\n ctx.body = await listHermesModels()\n })\n\n router.get('/api/v1/conversations', async (ctx) => {\n await authenticateRequest(ctx, paths)\n ctx.set('cache-control', 'no-store')\n ctx.body = {\n ok: true,\n conversations: await conversations.listConversations(),\n }\n })\n\n router.post('/api/v1/conversations', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const body = await readJsonBody(ctx.req)\n ctx.status = 201\n ctx.body = {\n ok: true,\n conversation: await conversations.createConversation({\n title: readString(body, 'title') ?? undefined,\n }),\n }\n })\n\n router.get('/api/v1/conversations/:conversationId/messages', async (ctx) => {\n await authenticateRequest(ctx, paths)\n ctx.set('cache-control', 'no-store')\n const result = await conversations.getMessages(ctx.params.conversationId)\n ctx.body = {\n ok: true,\n conversation_id: ctx.params.conversationId,\n ...result,\n }\n })\n\n router.get('/api/v1/conversations/:conversationId/events', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const after = readInteger(ctx.query.after) ?? 0\n const history = await conversations.listEvents(ctx.params.conversationId, after)\n ctx.respond = false\n const response = ctx.res\n response.statusCode = 200\n response.setHeader('content-type', 'text/event-stream; charset=utf-8')\n response.setHeader('cache-control', 'no-store')\n response.setHeader('connection', 'keep-alive')\n for (const event of history) {\n writeSseEvent(response, event)\n }\n const unsubscribe = conversations.subscribe(ctx.params.conversationId, (event) => {\n writeSseEvent(response, event)\n })\n const cleanup = () => {\n unsubscribe()\n response.end()\n }\n ctx.req.on('close', cleanup)\n })\n\n router.post('/api/v1/conversations/:conversationId/messages', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const body = await readJsonBody(ctx.req)\n const content = readString(body, 'content') ?? readString(body, 'text') ?? readString(body, 'input') ?? ''\n const attachments = readMessageAttachments(body.attachments ?? body.blobs)\n if (!content && attachments.length === 0) {\n throw new LinkHttpError(400, 'message_content_required', 'message content is required')\n }\n ctx.status = 202\n ctx.body = {\n ok: true,\n ...(await conversations.sendMessage({\n conversationId: ctx.params.conversationId,\n content,\n attachments,\n clientMessageId: readString(body, 'client_message_id') ?? readString(body, 'clientMessageId') ?? undefined,\n idempotencyKey: readHeader(ctx, 'idempotency-key') ?? undefined,\n })),\n }\n })\n\n router.post('/api/v1/conversations/:conversationId/ack', async (ctx) => {\n await authenticateRequest(ctx, paths)\n ctx.body = { ok: true }\n })\n\n router.delete('/api/v1/conversations/:conversationId', async (ctx) => {\n await authenticateRequest(ctx, paths)\n ctx.body = {\n ok: true,\n ...(await conversations.deleteConversation(ctx.params.conversationId)),\n blob_gc_completed: true,\n }\n })\n\n router.post('/api/v1/conversations/:conversationId/blobs', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const bytes = await readRawBody(ctx.req, MAX_BLOB_UPLOAD_BYTES)\n if (bytes.byteLength === 0) {\n throw new LinkHttpError(400, 'blob_empty', 'Blob body is empty')\n }\n const blob = await conversations.writeBlob(ctx.params.conversationId, {\n bytes,\n filename: readHeader(ctx, 'x-filename') ?? undefined,\n mime: ctx.get('content-type') || undefined,\n })\n ctx.status = 201\n ctx.body = { ok: true, blob }\n })\n\n router.get('/api/v1/conversations/:conversationId/blobs/:blobId', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const blob = await conversations.readBlob(ctx.params.conversationId, ctx.params.blobId)\n ctx.set('content-type', blob.mime)\n ctx.set('content-length', String(blob.size))\n ctx.set('cache-control', 'private, max-age=86400')\n ctx.set('content-disposition', `inline; filename=\"${blob.filename.replaceAll('\"', '')}\"`)\n ctx.body = blob.bytes\n })\n\n router.post('/api/v1/runs', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const body = await readJsonBody(ctx.req)\n const input = readString(body, 'input')\n if (!input) {\n throw new LinkHttpError(400, 'run_input_required', 'input is required')\n }\n ctx.status = 202\n ctx.body = await createHermesRun({\n input,\n conversation_history: readConversationHistory(body.conversation_history ?? body.conversationHistory),\n session_id: readString(body, 'session_id') ?? readString(body, 'sessionId') ?? undefined,\n })\n })\n\n router.get('/api/v1/runs/:runId/events', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const response = await streamHermesRunEvents(ctx.params.runId)\n ctx.status = response.status\n for (const [key, value] of response.headers.entries()) {\n ctx.set(key, value)\n }\n ctx.respond = false\n const nodeResponse = ctx.res\n nodeResponse.statusCode = response.status\n for (const [key, value] of response.headers.entries()) {\n nodeResponse.setHeader(key, value)\n }\n if (response.body) {\n Readable.fromWeb(response.body as Parameters<typeof Readable.fromWeb>[0]).pipe(nodeResponse)\n } else {\n nodeResponse.end()\n }\n })\n\n router.post('/api/v1/runs/:runId/cancel', async (ctx) => {\n await authenticateRequest(ctx, paths)\n await cancelHermesRun(ctx.params.runId)\n ctx.body = { ok: true }\n })\n\n router.get('/api/v1/profiles', async (ctx) => {\n await authenticateRequest(ctx, paths)\n ctx.set('cache-control', 'no-store')\n ctx.body = {\n ok: true,\n profiles: await listHermesProfiles(),\n }\n })\n\n router.get('/api/v1/profiles/:name/status', async (ctx) => {\n await authenticateRequest(ctx, paths)\n ctx.set('cache-control', 'no-store')\n ctx.body = {\n ok: true,\n profile: await getHermesProfileStatus(ctx.params.name),\n }\n })\n\n router.post('/api/v1/profiles', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const body = await readJsonBody(ctx.req)\n const name = readProfileName(body)\n ctx.status = 201\n ctx.body = {\n ok: true,\n profile: await createHermesProfile(name),\n }\n })\n\n router.post('/api/v1/profiles/:name/use', async (ctx) => {\n await authenticateRequest(ctx, paths)\n ctx.body = {\n ok: true,\n profile: await useHermesProfile(ctx.params.name),\n }\n })\n\n router.patch('/api/v1/profiles/:name', async (ctx) => {\n await authenticateRequest(ctx, paths)\n const body = await readJsonBody(ctx.req)\n const name = readProfileName(body)\n ctx.body = {\n ok: true,\n profile: await renameHermesProfile(ctx.params.name, name),\n }\n })\n\n router.delete('/api/v1/profiles/:name', async (ctx) => {\n await authenticateRequest(ctx, paths)\n await deleteHermesProfile(ctx.params.name)\n ctx.status = 204\n })\n\n app.use(router.routes())\n app.use(router.allowedMethods())\n return app\n}\n\nasync function readJsonBody(request: NodeJS.ReadableStream): Promise<Record<string, unknown>> {\n const raw = await readRawBody(request, MAX_JSON_BODY_BYTES)\n if (raw.byteLength === 0) {\n return {}\n }\n try {\n return JSON.parse(Buffer.from(raw).toString('utf8')) as Record<string, unknown>\n } catch {\n throw new LinkHttpError(400, 'invalid_json', 'Request body must be valid JSON')\n }\n}\n\nasync function readRawBody(request: NodeJS.ReadableStream, maxBytes: number): Promise<Buffer> {\n const chunks: Buffer[] = []\n let totalBytes = 0\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n totalBytes += buffer.byteLength\n if (totalBytes > maxBytes) {\n throw new LinkHttpError(413, 'request_body_too_large', 'Request body is too large')\n }\n chunks.push(buffer)\n }\n return Buffer.concat(chunks)\n}\n\nfunction readProfileName(body: Record<string, unknown>): string {\n if (typeof body.name !== 'string') {\n throw new Error('invalid profile name')\n }\n return body.name\n}\n\nasync function authenticateRequest(ctx: Koa.ParameterizedContext, paths: RuntimePaths): Promise<AuthContext> {\n const token = readBearerToken(ctx.get('authorization'))\n if (!token) {\n throw new LinkHttpError(401, 'auth_required', 'Authorization bearer token is required')\n }\n const device = await authenticateDeviceAccessToken(token, paths)\n if (device) {\n return { kind: 'device', device }\n }\n const [identity, config] = await Promise.all([loadRequiredIdentity(paths), loadConfig(paths)])\n const claims = await verifyAppConnectToken(token, {\n config,\n linkId: identity.link_id,\n })\n return { kind: 'app-connect', accountId: claims.sub }\n}\n\nasync function loadRequiredIdentity(paths: RuntimePaths) {\n const identity = await loadIdentity(paths)\n if (!identity?.link_id) {\n throw new LinkHttpError(409, 'link_not_paired', 'Hermes Link is not paired')\n }\n return identity as NonNullable<typeof identity> & { link_id: string }\n}\n\nfunction readBearerToken(value: string): string | null {\n const trimmed = value.trim()\n if (!trimmed.toLowerCase().startsWith('bearer ')) {\n return null\n }\n const token = trimmed.slice(7).trim()\n return token || null\n}\n\nfunction readString(body: Record<string, unknown>, key: string): string | null {\n const value = body[key]\n return typeof value === 'string' && value.trim() ? value.trim() : null\n}\n\nfunction readLimit(value: unknown): number | undefined {\n const raw = Array.isArray(value) ? value[0] : value\n if (typeof raw !== 'string') {\n return undefined\n }\n const parsed = Number.parseInt(raw, 10)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nfunction readInteger(value: unknown): number | undefined {\n const raw = Array.isArray(value) ? value[0] : value\n if (typeof raw !== 'string') {\n return undefined\n }\n const parsed = Number.parseInt(raw, 10)\n return Number.isFinite(parsed) ? Math.max(0, parsed) : undefined\n}\n\nfunction readHeader(ctx: Koa.ParameterizedContext, name: string): string | null {\n const value = ctx.get(name).trim()\n return value ? value : null\n}\n\nfunction writeSseEvent(response: ServerResponse, event: ConversationEvent): void {\n response.write(`event: ${event.type}\\n`)\n response.write(`data: ${JSON.stringify(event)}\\n\\n`)\n}\n\nfunction readConversationHistory(value: unknown): Array<{ role: string; content: string }> {\n if (!Array.isArray(value)) {\n return []\n }\n return value\n .map((item) => {\n if (typeof item !== 'object' || item === null) {\n return null\n }\n const role = (item as { role?: unknown }).role\n const content = (item as { content?: unknown }).content\n if (typeof role !== 'string' || typeof content !== 'string') {\n return null\n }\n return { role, content }\n })\n .filter((item): item is { role: string; content: string } => Boolean(item))\n}\n\nfunction readMessageAttachments(value: unknown): Array<{ blob_id: string }> {\n if (!Array.isArray(value)) {\n return []\n }\n return value\n .map((item) => {\n if (typeof item === 'string' && item.trim()) {\n return { blob_id: item.trim() }\n }\n if (typeof item !== 'object' || item === null) {\n return null\n }\n const record = item as Record<string, unknown>\n const blobId = typeof record.blob_id === 'string'\n ? record.blob_id.trim()\n : typeof record.blobId === 'string'\n ? record.blobId.trim()\n : ''\n return blobId ? { blob_id: blobId } : null\n })\n .filter((item): item is { blob_id: string } => Boolean(item))\n}\n\nfunction routeObjects(urls: string[]) {\n return urls.map((url) => ({\n kind: url.includes('/api/v1/relay/links/') ? 'relay' : 'lan',\n url,\n observed_at: new Date().toISOString(),\n }))\n}\n","export const LINK_VERSION = '0.1.6'\nexport const LINK_COMMAND = 'hermeslink'\nexport const LINK_DEFAULT_PORT = 52379\nexport const LINK_RUNTIME_DIR_NAME = '.hermeslink'\n","import os from 'node:os'\nimport path from 'node:path'\nimport { LINK_RUNTIME_DIR_NAME } from '../constants.js'\n\nexport interface RuntimePaths {\n homeDir: string\n identityFile: string\n configFile: string\n stateFile: string\n credentialsFile: string\n databaseFile: string\n conversationsDir: string\n blobsDir: string\n indexesDir: string\n logsDir: string\n runDir: string\n pairingDir: string\n}\n\nexport function resolveRuntimeHome(): string {\n return process.env.HERMESLINK_HOME?.trim()\n ? path.resolve(process.env.HERMESLINK_HOME)\n : path.join(os.homedir(), LINK_RUNTIME_DIR_NAME)\n}\n\nexport function resolveRuntimePaths(homeDir = resolveRuntimeHome()): RuntimePaths {\n return {\n homeDir,\n identityFile: path.join(homeDir, 'identity.json'),\n configFile: path.join(homeDir, 'config.json'),\n stateFile: path.join(homeDir, 'state.json'),\n credentialsFile: path.join(homeDir, 'credentials.json'),\n databaseFile: path.join(homeDir, 'link.db'),\n conversationsDir: path.join(homeDir, 'conversations'),\n blobsDir: path.join(homeDir, 'blobs'),\n indexesDir: path.join(homeDir, 'indexes'),\n logsDir: path.join(homeDir, 'logs'),\n runDir: path.join(homeDir, 'run'),\n pairingDir: path.join(homeDir, 'pairing'),\n }\n}\n","import { mkdir, open, readFile, rename, rm } from 'node:fs/promises'\nimport path from 'node:path'\n\nexport async function readJsonFile<T>(filePath: string): Promise<T | null> {\n try {\n const raw = await readFile(filePath, 'utf8')\n return JSON.parse(raw) as T\n } catch (error) {\n if (isNodeError(error, 'ENOENT')) {\n return null\n }\n throw error\n }\n}\n\nexport async function writeJsonFile(filePath: string, value: unknown, mode = 0o600): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true, mode: 0o700 })\n const tmpPath = `${filePath}.${process.pid}.${Date.now()}.tmp`\n const payload = `${JSON.stringify(value, null, 2)}\\n`\n const handle = await open(tmpPath, 'w', mode)\n try {\n await handle.writeFile(payload, 'utf8')\n await handle.sync()\n } finally {\n await handle.close()\n }\n try {\n await rename(tmpPath, filePath)\n } catch (error) {\n await rm(tmpPath, { force: true })\n throw error\n }\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return typeof error === 'object' && error !== null && 'code' in error && error.code === code\n}\n\n","import { LINK_DEFAULT_PORT } from '../constants.js'\nimport type { ConfiguredLanguage } from '../i18n.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\nimport { readJsonFile, writeJsonFile } from '../storage/atomic-json.js'\n\nexport interface LinkConfig {\n port: number\n serverBaseUrl: string\n relayBaseUrl: string\n appConnectTokenIssuer: string\n appConnectTokenAudience: string\n language: ConfiguredLanguage\n}\n\nexport const defaultLinkConfig: LinkConfig = {\n port: LINK_DEFAULT_PORT,\n serverBaseUrl: 'https://hermes-server.clawpilot.me',\n relayBaseUrl: 'https://hermes-relay.clawpilot.me',\n appConnectTokenIssuer: 'https://hermes-server.clawpilot.me',\n appConnectTokenAudience: 'hermes-link',\n language: 'auto',\n}\n\nexport async function loadConfig(paths: RuntimePaths = resolveRuntimePaths()): Promise<LinkConfig> {\n const existing = await readJsonFile<Partial<LinkConfig>>(paths.configFile)\n const language = normalizeConfiguredLanguage(existing?.language)\n return {\n ...defaultLinkConfig,\n ...(existing ?? {}),\n language,\n }\n}\n\nexport async function saveConfig(\n patch: Partial<LinkConfig>,\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<LinkConfig> {\n const current = await loadConfig(paths)\n const next = { ...current, ...patch }\n await writeJsonFile(paths.configFile, next)\n return next\n}\n\nfunction normalizeConfiguredLanguage(language: unknown): ConfiguredLanguage {\n if (language === 'zh-CN' || language === 'en' || language === 'auto') {\n return language\n }\n return defaultLinkConfig.language\n}\n","import { EventEmitter } from 'node:events'\nimport { appendFile, mkdir, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { createHash, randomUUID } from 'node:crypto'\nimport { createHermesRun, streamHermesRunEvents } from '../hermes/api-server.js'\nimport { deleteHermesSession } from '../hermes/cli.js'\nimport { LinkHttpError } from '../http/errors.js'\nimport type { FileLogger } from '../runtime/logger.js'\nimport { type RuntimePaths } from '../runtime/paths.js'\nimport { readJsonFile, writeJsonFile } from '../storage/atomic-json.js'\n\nconst MAX_IMPORTED_BLOB_BYTES = 100 * 1024 * 1024\nconst MAX_UPLOADED_BLOB_BYTES = 50 * 1024 * 1024\nconst CONVERSATION_ID_PATTERN = /^conv_[a-f0-9]{32}$/u\nconst BLOB_ID_PATTERN = /^blob_[a-f0-9]{32}$/u\nconst MEDIA_TAG_PATTERN =\n /[`\"']?MEDIA:\\s*(`[^`\\n]+`|\"[^\"\\n]+\"|'[^'\\n]+'|(?:~\\/|\\/)\\S+(?:[^\\S\\n]+\\S+)*?\\.(?:png|jpe?g|gif|webp|heic|pdf|txt|md|json|csv|mp4|mov|avi|mkv|webm|ogg|opus|mp3|wav|m4a)(?=[\\s`\"',;:)\\]}]|$)|\\S+)[`\"']?/giu\n\nexport interface ConversationSummary {\n id: string\n title: string\n created_at: string\n updated_at: string\n last_event_seq: number\n last_message: {\n id: string\n role: string\n content_preview: string\n } | null\n}\n\nexport interface LinkMessagePart {\n type: 'text' | 'image' | 'file' | 'audio' | 'unsupported'\n text?: string\n blob?: string\n mime?: string\n size?: number\n filename?: string\n url?: string\n}\n\nexport interface LinkMessage {\n id: string\n schema_version: 1\n conversation_id: string\n role: 'user' | 'assistant' | 'tool' | 'system'\n status: 'completed' | 'streaming' | 'failed'\n run_id?: string\n client_message_id?: string\n created_at: string\n updated_at: string\n sender: {\n id: string\n type: 'human' | 'agent' | 'system' | 'tool'\n display_name: string\n profile?: string\n }\n parts: LinkMessagePart[]\n attachments: unknown[]\n hermes?: Record<string, unknown>\n raw?: {\n format: string\n payload: unknown\n }\n}\n\nexport interface ConversationEvent {\n seq: number\n type: string\n conversation_id: string\n message_id?: string\n run_id?: string\n created_at: string\n payload?: Record<string, unknown>\n raw?: {\n format: string\n payload: unknown\n }\n}\n\ninterface ConversationManifest {\n id: string\n schema_version: 1\n kind: 'direct' | 'room'\n title: string\n status: 'active' | 'deleted_soft'\n hermes_session_id: string\n created_at: string\n updated_at: string\n last_event_seq: number\n deleted_at?: string\n}\n\ninterface ConversationSnapshot {\n schema_version: 1\n messages: LinkMessage[]\n runs: LinkRun[]\n}\n\ninterface LinkRun {\n id: string\n hermes_run_id?: string\n conversation_id: string\n trigger_message_id: string\n assistant_message_id: string\n hermes_session_id: string\n status: 'running' | 'completed' | 'failed' | 'cancelled' | 'unknown'\n started_at: string\n completed_at?: string\n error_message?: string\n}\n\ninterface SendMessageInput {\n conversationId: string\n content: string\n attachments?: MessageAttachmentInput[]\n clientMessageId?: string\n idempotencyKey?: string\n}\n\ninterface MessageAttachmentInput {\n blob_id?: string\n blobId?: string\n}\n\ninterface SendMessageResult {\n conversation_id: string\n user_message: Pick<LinkMessage, 'id' | 'status'>\n assistant_message: Pick<LinkMessage, 'id' | 'status'>\n run: Pick<LinkRun, 'id' | 'status'>\n last_event_seq: number\n}\n\ntype ConversationEventListener = (event: ConversationEvent) => void\n\nexport class ConversationService {\n private readonly emitter = new EventEmitter()\n\n constructor(\n private readonly paths: RuntimePaths,\n private readonly logger: FileLogger,\n ) {\n this.emitter.setMaxListeners(0)\n }\n\n async listConversations(): Promise<ConversationSummary[]> {\n await mkdir(this.paths.conversationsDir, { recursive: true, mode: 0o700 })\n const entries = await readdir(this.paths.conversationsDir, { withFileTypes: true }).catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n return []\n }\n throw error\n })\n const summaries: ConversationSummary[] = []\n for (const entry of entries) {\n if (!entry.isDirectory()) {\n continue\n }\n const manifest = await this.readManifest(entry.name).catch(() => null)\n if (!manifest || manifest.status !== 'active') {\n continue\n }\n const snapshot = await this.readSnapshot(entry.name).catch(() => emptySnapshot())\n summaries.push(toSummary(manifest, snapshot))\n }\n return summaries.sort((left, right) => Date.parse(right.updated_at) - Date.parse(left.updated_at))\n }\n\n async createConversation(input: { title?: string } = {}): Promise<ConversationSummary> {\n await mkdir(this.paths.conversationsDir, { recursive: true, mode: 0o700 })\n const now = new Date().toISOString()\n const id = `conv_${randomUUID().replaceAll('-', '')}`\n const title = input.title?.trim() || 'Untitled'\n const manifest: ConversationManifest = {\n id,\n schema_version: 1,\n kind: 'direct',\n title,\n status: 'active',\n hermes_session_id: `hp_${id}`,\n created_at: now,\n updated_at: now,\n last_event_seq: 0,\n }\n await mkdir(this.conversationDir(id), { recursive: true, mode: 0o700 })\n await this.writeManifest(manifest)\n await this.writeSnapshot(id, emptySnapshot())\n const event = await this.appendEvent(manifest.id, {\n type: 'conversation.created',\n payload: { title },\n })\n return { ...toSummary({ ...manifest, last_event_seq: event.seq }, emptySnapshot()), last_event_seq: event.seq }\n }\n\n async getMessages(conversationId: string): Promise<{ messages: LinkMessage[]; last_event_seq: number }> {\n const manifest = await this.readActiveManifest(conversationId)\n const snapshot = await this.readSnapshot(conversationId)\n return {\n messages: snapshot.messages,\n last_event_seq: manifest.last_event_seq,\n }\n }\n\n async listEvents(conversationId: string, after = 0): Promise<ConversationEvent[]> {\n await this.readManifest(conversationId)\n const eventsPath = this.eventsPath(conversationId)\n const raw = await readFile(eventsPath, 'utf8').catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n return ''\n }\n throw error\n })\n return raw\n .split('\\n')\n .filter(Boolean)\n .map((line) => JSON.parse(line) as ConversationEvent)\n .filter((event) => event.seq > after)\n }\n\n subscribe(conversationId: string, listener: ConversationEventListener): () => void {\n const eventName = this.liveEventName(conversationId)\n this.emitter.on(eventName, listener)\n return () => this.emitter.off(eventName, listener)\n }\n\n async sendMessage(input: SendMessageInput): Promise<SendMessageResult> {\n const manifest = await this.readActiveManifest(input.conversationId)\n const content = input.content.trim()\n const userAttachmentParts = await this.resolveMessageAttachmentParts(\n manifest.id,\n input.attachments ?? [],\n )\n if (!content && userAttachmentParts.length === 0) {\n throw new LinkHttpError(400, 'message_content_required', 'message content is required')\n }\n const idempotencyKey = input.clientMessageId ?? input.idempotencyKey\n const snapshot = await this.readSnapshot(input.conversationId)\n if (idempotencyKey) {\n const existingUser = snapshot.messages.find((message) => message.client_message_id === idempotencyKey)\n if (existingUser) {\n const existingRun = snapshot.runs.find((run) => run.trigger_message_id === existingUser.id)\n const existingAssistant = existingRun\n ? snapshot.messages.find((message) => message.id === existingRun.assistant_message_id)\n : null\n return {\n conversation_id: manifest.id,\n user_message: { id: existingUser.id, status: existingUser.status },\n assistant_message: { id: existingAssistant?.id ?? '', status: existingAssistant?.status ?? 'failed' },\n run: { id: existingRun?.id ?? '', status: existingRun?.status ?? 'unknown' },\n last_event_seq: manifest.last_event_seq,\n }\n }\n }\n\n const now = new Date().toISOString()\n const userMessage: LinkMessage = {\n id: `msg_${randomUUID().replaceAll('-', '')}`,\n schema_version: 1,\n conversation_id: manifest.id,\n role: 'user',\n status: 'completed',\n client_message_id: idempotencyKey,\n created_at: now,\n updated_at: now,\n sender: { id: 'app_user', type: 'human', display_name: 'Me' },\n parts: [{ type: 'text', text: content }, ...userAttachmentParts],\n attachments: userAttachmentParts.map((part) => ({\n blob_id: part.blob,\n mime: part.mime,\n size: part.size,\n filename: part.filename,\n })),\n raw: { format: 'hermes-link-user-message', payload: { content, attachments: input.attachments ?? [] } },\n }\n const assistantMessage: LinkMessage = {\n id: `msg_${randomUUID().replaceAll('-', '')}`,\n schema_version: 1,\n conversation_id: manifest.id,\n role: 'assistant',\n status: 'streaming',\n created_at: now,\n updated_at: now,\n sender: { id: 'agent_default', type: 'agent', display_name: 'Hermes', profile: 'default' },\n parts: [{ type: 'text', text: '' }],\n attachments: [],\n }\n const run: LinkRun = {\n id: `run_${randomUUID().replaceAll('-', '')}`,\n conversation_id: manifest.id,\n trigger_message_id: userMessage.id,\n assistant_message_id: assistantMessage.id,\n hermes_session_id: manifest.hermes_session_id,\n status: 'running',\n started_at: now,\n }\n snapshot.messages.push(userMessage, assistantMessage)\n snapshot.runs.push(run)\n await this.writeSnapshot(manifest.id, snapshot)\n await this.appendEvent(manifest.id, {\n type: 'message.created',\n message_id: userMessage.id,\n payload: { message: userMessage },\n })\n await this.appendEvent(manifest.id, {\n type: 'message.created',\n message_id: assistantMessage.id,\n run_id: run.id,\n payload: { message: assistantMessage },\n })\n const runEvent = await this.appendEvent(manifest.id, {\n type: 'run.started',\n message_id: assistantMessage.id,\n run_id: run.id,\n payload: { run },\n })\n\n void this.startRunWorker(manifest.id, run.id, this.buildHermesInput(content, userAttachmentParts)).catch((error: unknown) => {\n void this.failRun(manifest.id, run.id, error instanceof Error ? error.message : String(error))\n })\n\n return {\n conversation_id: manifest.id,\n user_message: { id: userMessage.id, status: userMessage.status },\n assistant_message: { id: assistantMessage.id, status: assistantMessage.status },\n run: { id: run.id, status: run.status },\n last_event_seq: runEvent.seq,\n }\n }\n\n async deleteConversation(conversationId: string): Promise<{ conversation_id: string; hermes_deleted: boolean; deleted_at: string }> {\n const manifest = await this.readActiveManifest(conversationId)\n const snapshot = await this.readSnapshot(conversationId).catch(() => emptySnapshot())\n const referencedBlobIds = new Set([\n ...collectBlobIds(snapshot),\n ...(await this.listConversationBlobIds(conversationId)),\n ])\n await deleteHermesSession(manifest.hermes_session_id)\n const deletedAt = new Date().toISOString()\n const next: ConversationManifest = {\n ...manifest,\n status: 'deleted_soft',\n updated_at: deletedAt,\n deleted_at: deletedAt,\n }\n await this.writeManifest(next)\n const deleteEvent = await this.appendEvent(conversationId, {\n type: 'conversation.deleted',\n payload: { deleted_at: deletedAt, hermes_session_id: manifest.hermes_session_id },\n })\n await this.writeSnapshot(conversationId, emptySnapshot())\n await writeFile(this.eventsPath(conversationId), `${JSON.stringify(deleteEvent)}\\n`, { mode: 0o600 })\n await this.pruneConversationBlobReferences(conversationId, [...referencedBlobIds])\n return { conversation_id: conversationId, hermes_deleted: true, deleted_at: deletedAt }\n }\n\n async writeBlob(conversationId: string, input: { bytes: Uint8Array; filename?: string; mime?: string }): Promise<{ id: string; size: number; mime: string; filename: string }> {\n await this.readActiveManifest(conversationId)\n if (input.bytes.byteLength > MAX_UPLOADED_BLOB_BYTES) {\n throw new LinkHttpError(413, 'blob_too_large', 'Blob is too large')\n }\n const id = `blob_${randomUUID().replaceAll('-', '')}`\n const filePath = this.blobPath(id)\n await mkdir(path.dirname(filePath), { recursive: true, mode: 0o700 })\n await writeFile(filePath, input.bytes, { mode: 0o600 })\n const manifestPath = `${filePath}.json`\n const blob = {\n id,\n size: input.bytes.byteLength,\n mime: input.mime || 'application/octet-stream',\n filename: sanitizeFilename(input.filename, id),\n created_at: new Date().toISOString(),\n conversation_ids: [conversationId],\n }\n await writeJsonFile(manifestPath, blob)\n await this.appendEvent(conversationId, {\n type: 'blob.created',\n payload: blob,\n })\n return blob\n }\n\n async readBlob(conversationId: string, blobId: string): Promise<{ bytes: Buffer; mime: string; filename: string; size: number }> {\n await this.readActiveManifest(conversationId)\n const filePath = this.blobPath(blobId)\n const manifest = await this.readBlobManifest(conversationId, blobId)\n const bytes = await readFile(filePath).catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n throw new LinkHttpError(404, 'blob_not_found', 'Blob was not found')\n }\n throw error\n })\n return {\n bytes,\n mime: manifest.mime || 'application/octet-stream',\n filename: manifest.filename || blobId,\n size: manifest.size || bytes.byteLength,\n }\n }\n\n private async resolveMessageAttachmentParts(\n conversationId: string,\n attachments: MessageAttachmentInput[],\n ): Promise<LinkMessagePart[]> {\n const parts: LinkMessagePart[] = []\n const seen = new Set<string>()\n for (const attachment of attachments) {\n const blobId = attachment.blob_id ?? attachment.blobId\n if (!blobId || seen.has(blobId)) {\n continue\n }\n seen.add(blobId)\n const manifest = await this.readBlobManifest(conversationId, blobId)\n const mime = manifest.mime || 'application/octet-stream'\n parts.push({\n type: mediaKindForMime(mime),\n blob: blobId,\n mime,\n size: manifest.size,\n filename: manifest.filename || blobId,\n url: `/api/v1/conversations/${encodeURIComponent(conversationId)}/blobs/${encodeURIComponent(blobId)}`,\n })\n }\n return parts\n }\n\n private buildHermesInput(content: string, parts: LinkMessagePart[]): string {\n const attachmentLines = parts\n .filter((part) => part.blob)\n .map((part) => {\n const label = part.filename ?? part.blob\n const mime = part.mime ? `, ${part.mime}` : ''\n const size = part.size ? `, ${part.size} bytes` : ''\n return `- ${label}${mime}${size}: ${this.blobPath(part.blob!)}`\n })\n if (attachmentLines.length === 0) {\n return content\n }\n const prefix = content ? `${content}\\n\\n` : ''\n return `${prefix}Attachments available on this computer:\\n${attachmentLines.join('\\n')}`\n }\n\n private async readBlobManifest(\n conversationId: string,\n blobId: string,\n ): Promise<{ conversation_ids?: string[]; mime?: string; filename?: string; size?: number }> {\n assertValidConversationId(conversationId)\n assertValidBlobId(blobId)\n const manifest = await readJsonFile<{ conversation_ids?: string[]; mime?: string; filename?: string; size?: number }>(\n `${this.blobPath(blobId)}.json`,\n )\n if (!manifest?.conversation_ids?.includes(conversationId)) {\n throw new LinkHttpError(404, 'blob_not_found', 'Blob was not found')\n }\n return manifest\n }\n\n private async writeBlobFromFile(conversationId: string, source: MediaReference): Promise<{ id: string; size: number; mime: string; filename: string }> {\n const sourcePath = resolveMediaSourcePath(source.path)\n const fileStat = await stat(sourcePath).catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n throw new LinkHttpError(404, 'media_source_not_found', 'Hermes output file was not found')\n }\n throw error\n })\n if (!fileStat.isFile()) {\n throw new LinkHttpError(400, 'media_source_not_file', 'Hermes output media source is not a file')\n }\n if (fileStat.size > MAX_IMPORTED_BLOB_BYTES) {\n throw new LinkHttpError(413, 'media_source_too_large', 'Hermes output media source is too large')\n }\n return this.writeBlob(conversationId, {\n bytes: await readFile(sourcePath),\n filename: path.basename(sourcePath),\n mime: source.mime ?? inferMimeType(sourcePath),\n })\n }\n\n private async startRunWorker(conversationId: string, runId: string, input: string): Promise<void> {\n const snapshot = await this.readSnapshot(conversationId)\n const run = snapshot.runs.find((item) => item.id === runId)\n if (!run) {\n return\n }\n const runResponse = await createHermesRun({\n input,\n session_id: run.hermes_session_id,\n conversation_history: buildConversationHistory(snapshot, run),\n })\n await this.updateRun(conversationId, runId, { hermes_run_id: runResponse.run_id })\n const response = await streamHermesRunEvents(runResponse.run_id)\n for await (const event of parseSseResponse(response)) {\n if (!(await this.isConversationActive(conversationId))) {\n return\n }\n const type = event.payloadType\n if (type === 'run.completed') {\n await this.importMediaReferencesForEvent(conversationId, runId, event)\n await this.completeRun(conversationId, runId, event)\n return\n }\n if (type === 'run.failed') {\n await this.importMediaReferencesForEvent(conversationId, runId, event)\n await this.failRun(conversationId, runId, readErrorMessage(event.payload) ?? 'Hermes run failed', event)\n return\n }\n await this.persistHermesEvent(conversationId, runId, event)\n }\n await this.completeRun(conversationId, runId)\n }\n\n private async persistHermesEvent(conversationId: string, runId: string, event: ParsedSseEvent): Promise<void> {\n if (!(await this.isConversationActive(conversationId))) {\n return\n }\n const type = event.payloadType\n if (type === 'message.delta') {\n const delta = readDelta(event.payload)\n if (delta) {\n await this.appendAssistantDelta(conversationId, runId, delta, event.payload)\n }\n return\n }\n const messageId = await this.assistantMessageIdForRun(conversationId, runId)\n await this.appendEvent(conversationId, {\n type,\n message_id: messageId,\n run_id: runId,\n payload: event.payload,\n raw: { format: 'hermes-run-event', payload: event.rawPayload },\n })\n if (messageId) {\n await this.importMediaReferences(conversationId, runId, messageId, collectMediaReferences(event.payload))\n }\n }\n\n private async importMediaReferencesForEvent(conversationId: string, runId: string, event: ParsedSseEvent): Promise<void> {\n const messageId = await this.assistantMessageIdForRun(conversationId, runId)\n if (!messageId) {\n return\n }\n await this.importMediaReferences(conversationId, runId, messageId, collectMediaReferences(event.payload))\n }\n\n private async appendAssistantDelta(conversationId: string, runId: string, delta: string, rawPayload: unknown): Promise<void> {\n const snapshot = await this.readSnapshot(conversationId)\n const run = snapshot.runs.find((item) => item.id === runId)\n if (!run) {\n return\n }\n const assistant = snapshot.messages.find((message) => message.id === run.assistant_message_id)\n if (!assistant) {\n return\n }\n const textPart = assistant.parts.find((part) => part.type === 'text')\n if (textPart) {\n textPart.text = `${textPart.text ?? ''}${delta}`\n } else {\n assistant.parts.push({ type: 'text', text: delta })\n }\n assistant.updated_at = new Date().toISOString()\n assistant.raw = { format: 'hermes-run-event', payload: rawPayload }\n await this.writeSnapshot(conversationId, snapshot)\n await this.appendEvent(conversationId, {\n type: 'message.delta',\n message_id: assistant.id,\n run_id: runId,\n payload: { delta },\n raw: { format: 'hermes-run-event', payload: rawPayload },\n })\n }\n\n private async completeRun(conversationId: string, runId: string, source?: ParsedSseEvent): Promise<void> {\n let snapshot = await this.readSnapshot(conversationId)\n let run = snapshot.runs.find((item) => item.id === runId)\n if (!run) {\n return\n }\n const initialRun = run\n let assistant = snapshot.messages.find((message) => message.id === initialRun.assistant_message_id)\n if (assistant) {\n await this.importMediaReferences(conversationId, runId, assistant.id, collectMediaTags(messageText(assistant)))\n snapshot = await this.readSnapshot(conversationId)\n const refreshedRun = snapshot.runs.find((item) => item.id === runId)\n if (!refreshedRun) {\n return\n }\n run = refreshedRun\n assistant = snapshot.messages.find((message) => message.id === refreshedRun.assistant_message_id)\n }\n const completedAt = new Date().toISOString()\n run.status = 'completed'\n run.completed_at = completedAt\n if (assistant) {\n assistant.status = 'completed'\n assistant.updated_at = completedAt\n cleanMessageTextParts(assistant)\n }\n await this.writeSnapshot(conversationId, snapshot)\n if (assistant) {\n await this.appendEvent(conversationId, {\n type: 'message.completed',\n message_id: assistant.id,\n run_id: runId,\n payload: { message: assistant },\n })\n }\n await this.appendEvent(conversationId, {\n type: 'run.completed',\n message_id: assistant?.id,\n run_id: runId,\n payload: { run, ...(source ? { hermes: source.payload } : {}) },\n ...(source ? { raw: { format: 'hermes-run-event', payload: source.rawPayload } } : {}),\n })\n }\n\n private async failRun(conversationId: string, runId: string, message: string, source?: ParsedSseEvent): Promise<void> {\n const snapshot = await this.readSnapshot(conversationId).catch(() => null)\n if (!snapshot) {\n return\n }\n const run = snapshot.runs.find((item) => item.id === runId)\n if (!run) {\n return\n }\n run.status = 'failed'\n run.completed_at = new Date().toISOString()\n run.error_message = message\n const assistant = snapshot.messages.find((item) => item.id === run.assistant_message_id)\n if (assistant) {\n assistant.status = 'failed'\n assistant.updated_at = run.completed_at\n const textPart = assistant.parts.find((part) => part.type === 'text')\n if (textPart && !textPart.text) {\n textPart.text = message\n }\n }\n await this.writeSnapshot(conversationId, snapshot)\n await this.appendEvent(conversationId, {\n type: 'run.failed',\n message_id: assistant?.id,\n run_id: runId,\n payload: { error: { message }, run, ...(source ? { hermes: source.payload } : {}) },\n ...(source ? { raw: { format: 'hermes-run-event', payload: source.rawPayload } } : {}),\n })\n void this.logger.warn('conversation_run_failed', { conversation_id: conversationId, run_id: runId, error: message })\n }\n\n private async updateRun(conversationId: string, runId: string, patch: Partial<LinkRun>): Promise<void> {\n const snapshot = await this.readSnapshot(conversationId)\n const run = snapshot.runs.find((item) => item.id === runId)\n if (!run) {\n return\n }\n Object.assign(run, patch)\n await this.writeSnapshot(conversationId, snapshot)\n }\n\n private async assistantMessageIdForRun(conversationId: string, runId: string): Promise<string | undefined> {\n const snapshot = await this.readSnapshot(conversationId).catch(() => null)\n return snapshot?.runs.find((item) => item.id === runId)?.assistant_message_id\n }\n\n private async importMediaReferences(\n conversationId: string,\n runId: string,\n messageId: string,\n references: MediaReference[],\n ): Promise<void> {\n if (references.length === 0) {\n return\n }\n const snapshot = await this.readSnapshot(conversationId)\n const assistant = snapshot.messages.find((message) => message.id === messageId)\n if (!assistant) {\n return\n }\n const importedSourceKeys = readImportedMediaSourceKeys(assistant)\n const importedParts: LinkMessagePart[] = []\n for (const reference of references.slice(0, 10)) {\n try {\n const sourceKey = mediaSourceKey(reference.path)\n if (importedSourceKeys.has(sourceKey)) {\n continue\n }\n const blob = await this.writeBlobFromFile(conversationId, reference)\n const part: LinkMessagePart = {\n type: reference.kind ?? mediaKindForMime(blob.mime),\n blob: blob.id,\n mime: blob.mime,\n size: blob.size,\n filename: blob.filename,\n url: `/api/v1/conversations/${encodeURIComponent(conversationId)}/blobs/${encodeURIComponent(blob.id)}`,\n }\n assistant.parts.push(part)\n assistant.attachments.push({\n blob_id: blob.id,\n mime: blob.mime,\n size: blob.size,\n filename: blob.filename,\n source: 'hermes_output',\n })\n importedSourceKeys.add(sourceKey)\n importedParts.push(part)\n } catch (error) {\n void this.logger.warn('conversation_media_import_failed', {\n conversation_id: conversationId,\n run_id: runId,\n message_id: messageId,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n if (importedParts.length === 0) {\n return\n }\n assistant.hermes = {\n ...toRecord(assistant.hermes),\n imported_media_source_keys: [...importedSourceKeys],\n }\n assistant.updated_at = new Date().toISOString()\n await this.writeSnapshot(conversationId, snapshot)\n await this.appendEvent(conversationId, {\n type: 'message.parts.created',\n message_id: messageId,\n run_id: runId,\n payload: { parts: importedParts },\n })\n }\n\n private async appendEvent(\n conversationId: string,\n input: Omit<ConversationEvent, 'seq' | 'conversation_id' | 'created_at'>,\n ): Promise<ConversationEvent> {\n const manifest = await this.readManifest(conversationId)\n const now = new Date().toISOString()\n const event: ConversationEvent = {\n ...input,\n seq: manifest.last_event_seq + 1,\n conversation_id: conversationId,\n created_at: now,\n }\n await mkdir(this.conversationDir(conversationId), { recursive: true, mode: 0o700 })\n await appendFile(this.eventsPath(conversationId), `${JSON.stringify(event)}\\n`, { mode: 0o600 })\n await this.writeManifest({\n ...manifest,\n last_event_seq: event.seq,\n updated_at: now,\n })\n this.emitter.emit(this.liveEventName(conversationId), event)\n return event\n }\n\n private async readActiveManifest(conversationId: string): Promise<ConversationManifest> {\n const manifest = await this.readManifest(conversationId)\n if (manifest.status !== 'active') {\n throw new LinkHttpError(404, 'conversation_not_found', 'Conversation was not found')\n }\n return manifest\n }\n\n private async isConversationActive(conversationId: string): Promise<boolean> {\n const manifest = await this.readManifest(conversationId).catch(() => null)\n return manifest?.status === 'active'\n }\n\n private async readManifest(conversationId: string): Promise<ConversationManifest> {\n const manifest = await readJsonFile<ConversationManifest>(this.manifestPath(conversationId))\n if (!manifest) {\n throw new LinkHttpError(404, 'conversation_not_found', 'Conversation was not found')\n }\n return manifest\n }\n\n private writeManifest(manifest: ConversationManifest): Promise<void> {\n return writeJsonFile(this.manifestPath(manifest.id), manifest)\n }\n\n private async readSnapshot(conversationId: string): Promise<ConversationSnapshot> {\n return (await readJsonFile<ConversationSnapshot>(this.snapshotPath(conversationId))) ?? emptySnapshot()\n }\n\n private writeSnapshot(conversationId: string, snapshot: ConversationSnapshot): Promise<void> {\n return writeJsonFile(this.snapshotPath(conversationId), snapshot)\n }\n\n private conversationDir(conversationId: string): string {\n assertValidConversationId(conversationId)\n return path.join(this.paths.conversationsDir, conversationId)\n }\n\n private manifestPath(conversationId: string): string {\n return path.join(this.conversationDir(conversationId), 'manifest.json')\n }\n\n private snapshotPath(conversationId: string): string {\n return path.join(this.conversationDir(conversationId), 'snapshot.json')\n }\n\n private eventsPath(conversationId: string): string {\n return path.join(this.conversationDir(conversationId), 'events.ndjson')\n }\n\n private blobPath(blobId: string): string {\n assertValidBlobId(blobId)\n return path.join(this.paths.blobsDir, `${blobId}.bin`)\n }\n\n private liveEventName(conversationId: string): string {\n return `conversation:${conversationId}`\n }\n\n private async pruneConversationBlobReferences(conversationId: string, blobIds: string[]): Promise<void> {\n for (const blobId of blobIds) {\n try {\n const manifestPath = `${this.blobPath(blobId)}.json`\n const manifest = await readJsonFile<{ conversation_ids?: string[] }>(manifestPath)\n const nextConversationIds = (manifest?.conversation_ids ?? []).filter((id) => id !== conversationId)\n if (nextConversationIds.length > 0) {\n await writeJsonFile(manifestPath, { ...manifest, conversation_ids: nextConversationIds })\n continue\n }\n await rm(this.blobPath(blobId), { force: true })\n await rm(manifestPath, { force: true })\n } catch (error) {\n void this.logger.warn('conversation_blob_gc_failed', {\n conversation_id: conversationId,\n blob_id: blobId,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n }\n\n private async listConversationBlobIds(conversationId: string): Promise<string[]> {\n await mkdir(this.paths.blobsDir, { recursive: true, mode: 0o700 })\n const entries = await readdir(this.paths.blobsDir, { withFileTypes: true }).catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n return []\n }\n throw error\n })\n const blobIds: string[] = []\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.bin.json')) {\n continue\n }\n const blobId = entry.name.slice(0, -'.bin.json'.length)\n if (!BLOB_ID_PATTERN.test(blobId)) {\n continue\n }\n const manifest = await readJsonFile<{ conversation_ids?: string[] }>(\n path.join(this.paths.blobsDir, entry.name),\n ).catch(() => null)\n if (manifest?.conversation_ids?.includes(conversationId)) {\n blobIds.push(blobId)\n }\n }\n return blobIds\n }\n}\n\nexport async function removeConversationFiles(paths: RuntimePaths, conversationId: string): Promise<void> {\n assertValidConversationId(conversationId)\n await rm(path.join(paths.conversationsDir, conversationId), { recursive: true, force: true })\n}\n\ninterface ParsedSseEvent {\n eventName: string\n payloadType: string\n payload: Record<string, unknown>\n rawPayload: unknown\n}\n\ninterface MediaReference {\n path: string\n kind?: LinkMessagePart['type']\n mime?: string\n}\n\nasync function* parseSseResponse(response: Response): AsyncGenerator<ParsedSseEvent> {\n if (!response.body) {\n return\n }\n const decoder = new TextDecoder()\n let buffer = ''\n for await (const chunk of response.body as unknown as AsyncIterable<Uint8Array>) {\n buffer += decoder.decode(chunk, { stream: true })\n let separatorIndex = buffer.indexOf('\\n\\n')\n while (separatorIndex >= 0) {\n const block = buffer.slice(0, separatorIndex)\n buffer = buffer.slice(separatorIndex + 2)\n const parsed = parseSseBlock(block)\n if (parsed) {\n yield parsed\n }\n separatorIndex = buffer.indexOf('\\n\\n')\n }\n }\n const trailing = parseSseBlock(buffer)\n if (trailing) {\n yield trailing\n }\n}\n\nfunction parseSseBlock(block: string): ParsedSseEvent | null {\n const lines = block.split('\\n')\n let eventName = ''\n const data: string[] = []\n for (const rawLine of lines) {\n const line = rawLine.trimEnd()\n if (line.startsWith('event:')) {\n eventName = line.slice(6).trim()\n } else if (line.startsWith('data:')) {\n data.push(line.slice(5).trimStart())\n }\n }\n if (!eventName && data.length === 0) {\n return null\n }\n const raw = data.join('\\n')\n const decoded = decodeJson(raw)\n const payload = toRecord(decoded)\n const payloadType = (readString(payload, 'type') ?? readString(payload, 'event') ?? eventName) || 'message'\n return { eventName, payloadType, payload, rawPayload: decoded ?? raw }\n}\n\nfunction decodeJson(value: string): unknown {\n if (!value.trim()) {\n return {}\n }\n try {\n return JSON.parse(value) as unknown\n } catch {\n return { type: 'message.delta', delta: value }\n }\n}\n\nfunction emptySnapshot(): ConversationSnapshot {\n return { schema_version: 1, messages: [], runs: [] }\n}\n\nfunction toSummary(manifest: ConversationManifest, snapshot: ConversationSnapshot): ConversationSummary {\n const lastMessage = [...snapshot.messages].reverse().find((message) => message.parts.some((part) => part.type === 'text' && part.text))\n return {\n id: manifest.id,\n title: manifest.title,\n created_at: manifest.created_at,\n updated_at: manifest.updated_at,\n last_event_seq: manifest.last_event_seq,\n last_message: lastMessage\n ? {\n id: lastMessage.id,\n role: lastMessage.role,\n content_preview: previewText(lastMessage),\n }\n : null,\n }\n}\n\nfunction previewText(message: LinkMessage): string {\n return messageText(message).slice(0, 160)\n}\n\nfunction messageText(message: LinkMessage): string {\n return message.parts\n .filter((part) => part.type === 'text' && part.text)\n .map((part) => part.text)\n .join('')\n .trim()\n}\n\nfunction buildConversationHistory(snapshot: ConversationSnapshot, run: LinkRun): Array<{ role: string; content: string }> {\n const triggerIndex = snapshot.messages.findIndex((message) => message.id === run.trigger_message_id)\n const previousMessages = triggerIndex >= 0 ? snapshot.messages.slice(0, triggerIndex) : snapshot.messages\n return previousMessages\n .filter((message) => (message.role === 'user' || message.role === 'assistant') && message.status === 'completed')\n .map((message) => ({\n role: message.role,\n content: messageText(message),\n }))\n .filter((message) => message.content)\n}\n\nfunction readDelta(payload: Record<string, unknown>): string | null {\n return readString(payload, 'delta') ?? readString(payload, 'text') ?? readString(payload, 'content')\n}\n\nfunction readErrorMessage(payload: Record<string, unknown>): string | null {\n const error = toRecord(payload.error)\n return readString(error, 'message') ?? readString(payload, 'message')\n}\n\nfunction collectMediaReferences(payload: Record<string, unknown>): MediaReference[] {\n const references: MediaReference[] = []\n collectStructuredMediaReferences(payload, references)\n for (const key of ['output', 'content', 'message', 'text']) {\n const value = payload[key]\n if (typeof value === 'string') {\n references.push(...collectMediaTags(value))\n }\n }\n const unique = new Set<string>()\n return references.filter((reference) => {\n const key = `${reference.path}|${reference.mime ?? ''}|${reference.kind ?? ''}`\n if (unique.has(key)) {\n return false\n }\n unique.add(key)\n return true\n })\n}\n\nfunction collectStructuredMediaReferences(value: unknown, references: MediaReference[], depth = 0): void {\n if (depth > 4 || value === null || typeof value !== 'object') {\n return\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n collectStructuredMediaReferences(item, references, depth + 1)\n }\n return\n }\n const record = value as Record<string, unknown>\n for (const [key, item] of Object.entries(record)) {\n if (typeof item === 'string' && isExplicitMediaPathKey(key)) {\n references.push({\n path: item,\n kind: mediaKindForMime(readString(record, 'mime') ?? readString(record, 'mime_type') ?? inferMimeType(item)),\n mime: readString(record, 'mime') ?? readString(record, 'mime_type') ?? undefined,\n })\n continue\n }\n if (Array.isArray(item) || (item !== null && typeof item === 'object')) {\n collectStructuredMediaReferences(item, references, depth + 1)\n }\n }\n}\n\nfunction collectMediaTags(text: string): MediaReference[] {\n const references: MediaReference[] = []\n for (const match of text.matchAll(MEDIA_TAG_PATTERN)) {\n const rawPath = match[1]?.trim()\n const mediaPath = rawPath\n ?.replace(/^[\"'`]|[\"'`]$/gu, '')\n .replace(/[\"'`,.;:)}\\]]+$/gu, '')\n if (mediaPath) {\n references.push({\n path: mediaPath,\n kind: mediaKindForMime(inferMimeType(mediaPath)),\n })\n }\n }\n return references\n}\n\nfunction cleanMessageTextParts(message: LinkMessage): void {\n for (const part of message.parts) {\n if (part.type === 'text' && part.text) {\n part.text = cleanHermesDisplayText(part.text)\n }\n }\n}\n\nfunction cleanHermesDisplayText(text: string): string {\n if (!text.includes('MEDIA:') && !text.includes('[[audio_as_voice]]')) {\n return text\n }\n return text\n .replaceAll('[[audio_as_voice]]', '')\n .replace(MEDIA_TAG_PATTERN, '')\n .replace(/\\n{3,}/gu, '\\n\\n')\n .trimEnd()\n}\n\nfunction isExplicitMediaPathKey(key: string): boolean {\n return [\n 'file_path',\n 'screenshot_path',\n 'image_path',\n 'audio_path',\n 'video_path',\n 'media_path',\n 'artifact_path',\n ].includes(key)\n}\n\nfunction inferMimeType(filePath: string): string {\n const extension = path.extname(filePath).toLowerCase()\n return (\n {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.heic': 'image/heic',\n '.pdf': 'application/pdf',\n '.txt': 'text/plain',\n '.md': 'text/markdown',\n '.json': 'application/json',\n '.csv': 'text/csv',\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.m4a': 'audio/mp4',\n '.ogg': 'audio/ogg',\n '.opus': 'audio/ogg',\n '.mp4': 'video/mp4',\n '.mov': 'video/quicktime',\n '.webm': 'video/webm',\n } satisfies Record<string, string>\n )[extension] ?? 'application/octet-stream'\n}\n\nfunction mediaKindForMime(mime: string): LinkMessagePart['type'] {\n if (mime.startsWith('image/')) {\n return 'image'\n }\n if (mime.startsWith('audio/')) {\n return 'audio'\n }\n return 'file'\n}\n\nfunction collectBlobIds(snapshot: ConversationSnapshot): string[] {\n const blobIds = new Set<string>()\n for (const message of snapshot.messages) {\n for (const part of message.parts) {\n if (part.blob) {\n blobIds.add(part.blob)\n }\n }\n for (const attachment of message.attachments) {\n const record = toRecord(attachment)\n const blobId = readString(record, 'blob_id') ?? readString(record, 'blobId')\n if (blobId) {\n blobIds.add(blobId)\n }\n }\n }\n return [...blobIds]\n}\n\nfunction readImportedMediaSourceKeys(message: LinkMessage): Set<string> {\n const hermes = toRecord(message.hermes)\n const keys = hermes.imported_media_source_keys\n if (!Array.isArray(keys)) {\n return new Set<string>()\n }\n return new Set(keys.filter((key): key is string => typeof key === 'string' && key.length > 0))\n}\n\nfunction mediaSourceKey(sourcePath: string): string {\n return createHash('sha256').update(resolveMediaSourcePath(sourcePath)).digest('hex').slice(0, 32)\n}\n\nfunction sanitizeFilename(value: string | undefined, fallback: string): string {\n const base = path.basename((value ?? '').replace(/[\\r\\n\\t]/gu, ' ').trim())\n const safe = base.replace(/[/:\\\\]/gu, '_').slice(0, 200).trim()\n return safe || fallback\n}\n\nfunction resolveMediaSourcePath(sourcePath: string): string {\n const trimmed = sourcePath.trim()\n const expanded = trimmed.startsWith('~/') ? path.join(process.env.HOME ?? '', trimmed.slice(2)) : trimmed\n const resolved = path.resolve(expanded)\n if (!path.isAbsolute(expanded)) {\n throw new LinkHttpError(400, 'media_source_path_not_absolute', 'Hermes output media source must be an absolute path')\n }\n return resolved\n}\n\nfunction assertValidConversationId(conversationId: string): void {\n if (!CONVERSATION_ID_PATTERN.test(conversationId)) {\n throw new LinkHttpError(404, 'conversation_not_found', 'Conversation was not found')\n }\n}\n\nfunction assertValidBlobId(blobId: string): void {\n if (!BLOB_ID_PATTERN.test(blobId)) {\n throw new LinkHttpError(404, 'blob_not_found', 'Blob was not found')\n }\n}\n\nfunction readString(payload: Record<string, unknown>, key: string): string | null {\n const value = payload[key]\n return typeof value === 'string' && value.trim() ? value.trim() : null\n}\n\nfunction toRecord(value: unknown): Record<string, unknown> {\n return typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : {}\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return typeof error === 'object' && error !== null && 'code' in error && error.code === code\n}\n","import { randomUUID } from 'node:crypto'\nimport { readHermesApiServerConfig } from './config.js'\nimport { LinkHttpError } from '../http/errors.js'\n\nexport interface HermesRunRequest {\n input: string\n conversation_history?: Array<{ role: string; content: string }>\n session_id?: string\n}\n\nexport interface HermesApiClientOptions {\n fetchImpl?: typeof fetch\n}\n\nconst fallbackRuns = new Map<string, { input: string; createdAt: string }>()\n\nexport async function listHermesModels(options: HermesApiClientOptions = {}): Promise<unknown> {\n const response = await callHermesApi('/v1/models', { method: 'GET' }, options)\n if (response.status === 404) {\n return { models: [] }\n }\n return await readJsonResponse(response)\n}\n\nexport async function createHermesRun(\n input: HermesRunRequest,\n options: HermesApiClientOptions = {},\n): Promise<{ run_id: string; fallback: boolean }> {\n const response = await callHermesApi(\n '/v1/runs',\n {\n method: 'POST',\n body: JSON.stringify(input),\n headers: { 'content-type': 'application/json' },\n },\n options,\n )\n if (response.status === 404 || response.status === 503) {\n const runId = `run_${randomUUID().replaceAll('-', '')}`\n fallbackRuns.set(runId, { input: input.input, createdAt: new Date().toISOString() })\n return { run_id: runId, fallback: true }\n }\n const payload = await readJsonResponse(response)\n const runId = readString(payload, 'run_id') ?? readString(payload, 'runId') ?? readString(payload, 'id')\n if (!runId) {\n throw new LinkHttpError(502, 'hermes_run_invalid', 'Hermes API Server did not return a run id')\n }\n return { run_id: runId, fallback: false }\n}\n\nexport async function streamHermesRunEvents(\n runId: string,\n options: HermesApiClientOptions = {},\n): Promise<Response> {\n const fallback = fallbackRuns.get(runId)\n if (fallback) {\n fallbackRuns.delete(runId)\n return new Response(createFallbackSseStream(fallback.input), {\n headers: {\n 'content-type': 'text/event-stream; charset=utf-8',\n 'cache-control': 'no-store',\n },\n })\n }\n const response = await callHermesApi(`/v1/runs/${encodeURIComponent(runId)}/events`, { method: 'GET' }, options)\n if (!response.ok || !response.body) {\n throw new LinkHttpError(502, 'hermes_events_unavailable', 'Hermes run event stream is unavailable')\n }\n return new Response(response.body, {\n status: response.status,\n headers: {\n 'content-type': response.headers.get('content-type') ?? 'text/event-stream; charset=utf-8',\n 'cache-control': 'no-store',\n },\n })\n}\n\nexport async function cancelHermesRun(runId: string, options: HermesApiClientOptions = {}): Promise<void> {\n const response = await callHermesApi(\n `/v1/runs/${encodeURIComponent(runId)}/cancel`,\n { method: 'POST' },\n options,\n )\n if (!response.ok && response.status !== 404) {\n throw new LinkHttpError(502, 'hermes_cancel_failed', 'Hermes run cancel failed')\n }\n fallbackRuns.delete(runId)\n}\n\nasync function callHermesApi(\n path: string,\n init: RequestInit,\n options: HermesApiClientOptions,\n): Promise<Response> {\n const config = await readHermesApiServerConfig()\n if (!config.port || !config.key) {\n return new Response(null, { status: 503 })\n }\n const fetcher = options.fetchImpl ?? fetch\n const headers = new Headers(init.headers)\n headers.set('accept', headers.get('accept') ?? 'application/json')\n headers.set('x-api-key', config.key)\n headers.set('authorization', `Bearer ${config.key}`)\n return await fetcher(`http://127.0.0.1:${config.port}${path}`, {\n ...init,\n headers,\n }).catch(() => new Response(null, { status: 503 }))\n}\n\nasync function readJsonResponse(response: Response): Promise<Record<string, unknown>> {\n const payload = (await response.json().catch(() => null)) as unknown\n if (!response.ok || typeof payload !== 'object' || payload === null) {\n throw new LinkHttpError(502, 'hermes_response_invalid', 'Hermes API Server returned an invalid response')\n }\n return payload as Record<string, unknown>\n}\n\nfunction createFallbackSseStream(input: string): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder()\n return new ReadableStream<Uint8Array>({\n start(controller) {\n const message = `Hermes API Server is not running yet. Link received: ${input}`\n controller.enqueue(encoder.encode(`event: message.delta\\ndata: ${JSON.stringify({ type: 'message.delta', delta: message })}\\n\\n`))\n controller.enqueue(encoder.encode(`event: run.completed\\ndata: ${JSON.stringify({ type: 'run.completed' })}\\n\\n`))\n controller.close()\n },\n })\n}\n\nfunction readString(payload: Record<string, unknown>, key: string): string | null {\n const value = payload[key]\n return typeof value === 'string' && value.trim() ? value.trim() : null\n}\n","import { randomBytes } from 'node:crypto'\nimport { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport YAML from 'yaml'\n\nexport interface HermesApiServerConfig {\n host?: string\n port?: number\n key?: string\n}\n\nexport interface EnsureHermesConfigResult {\n configPath: string\n apiServer: HermesApiServerConfig\n changed: boolean\n keyAdded: boolean\n backupPath: string | null\n notice: string | null\n}\n\nexport function resolveHermesProfileDir(profileName = 'default'): string {\n if (profileName === 'default') {\n return path.join(os.homedir(), '.hermes')\n }\n return path.join(os.homedir(), '.hermes', 'profiles', profileName)\n}\n\nexport function resolveHermesConfigPath(profileName = 'default'): string {\n return path.join(resolveHermesProfileDir(profileName), 'config.yaml')\n}\n\nexport async function readHermesApiServerConfig(\n profileName = 'default',\n configPath = resolveHermesConfigPath(profileName),\n): Promise<HermesApiServerConfig> {\n const existingRaw = await readFile(configPath, 'utf8').catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n return null\n }\n throw error\n })\n if (!existingRaw) {\n return {}\n }\n const config = toRecord(YAML.parse(existingRaw))\n const platforms = toRecord(config.platforms)\n const apiServer = toRecord(platforms.api_server)\n return readApiServerConfig(toRecord(apiServer.extra))\n}\n\nexport async function ensureHermesApiServerKey(\n profileName = 'default',\n configPath = resolveHermesConfigPath(profileName),\n): Promise<EnsureHermesConfigResult> {\n const existingRaw = await readFile(configPath, 'utf8').catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n return null\n }\n throw error\n })\n const document = existingRaw ? YAML.parseDocument(existingRaw) : new YAML.Document({})\n const config = toRecord(document.toJSON())\n const platforms = ensureRecord(config, 'platforms')\n const apiServer = ensureRecord(platforms, 'api_server')\n const extra = ensureRecord(apiServer, 'extra')\n const beforeKey = typeof extra.key === 'string' && extra.key.length > 0 ? extra.key : null\n\n let changed = false\n if (!beforeKey) {\n extra.key = randomBytes(32).toString('base64url')\n changed = true\n }\n\n if (!changed) {\n return {\n configPath,\n apiServer: readApiServerConfig(extra),\n changed: false,\n keyAdded: false,\n backupPath: null,\n notice: null,\n }\n }\n\n const backupPath = existingRaw ? `${configPath}.bak.${Date.now()}` : null\n await mkdir(path.dirname(configPath), { recursive: true, mode: 0o700 })\n if (backupPath) {\n await copyFile(configPath, backupPath)\n }\n document.contents = document.createNode(config)\n await writeFile(configPath, document.toString(), { mode: 0o600 })\n\n return {\n configPath,\n apiServer: readApiServerConfig(extra),\n changed: true,\n keyAdded: true,\n backupPath,\n notice: '已为 Hermes API Server 自动补充 key;未覆盖已有 port/host/key。',\n }\n}\n\nfunction readApiServerConfig(extra: Record<string, unknown>): HermesApiServerConfig {\n return {\n host: typeof extra.host === 'string' ? extra.host : undefined,\n port: typeof extra.port === 'number' ? extra.port : undefined,\n key: typeof extra.key === 'string' ? extra.key : undefined,\n }\n}\n\nfunction toRecord(value: unknown): Record<string, unknown> {\n return typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : {}\n}\n\nfunction ensureRecord(parent: Record<string, unknown>, key: string): Record<string, unknown> {\n const value = parent[key]\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n return value as Record<string, unknown>\n }\n const next: Record<string, unknown> = {}\n parent[key] = next\n return next\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return typeof error === 'object' && error !== null && 'code' in error && error.code === code\n}\n","export class LinkHttpError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n message: string,\n ) {\n super(message)\n }\n}\n\nexport function isLinkHttpError(error: unknown): error is LinkHttpError {\n return error instanceof LinkHttpError\n}\n","import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { LinkHttpError } from '../http/errors.js'\n\nconst execFileAsync = promisify(execFile)\n\nexport async function deleteHermesSession(sessionId: string): Promise<void> {\n if (!sessionId.trim()) {\n throw new LinkHttpError(400, 'hermes_session_id_required', 'Hermes session id is required')\n }\n\n try {\n await execFileAsync(hermesBin(), ['sessions', 'delete', sessionId, '--yes'], {\n timeout: 10_000,\n windowsHide: true,\n })\n } catch (error) {\n throw new LinkHttpError(\n 502,\n 'hermes_session_delete_failed',\n error instanceof Error ? error.message : 'Hermes session delete failed',\n )\n }\n}\n\nfunction hermesBin(): string {\n return process.env.HERMES_BIN?.trim() || 'hermes'\n}\n","import { mkdir, readdir, rename, rm, stat } from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\nimport { readJsonFile, writeJsonFile } from '../storage/atomic-json.js'\nimport {\n ensureHermesApiServerKey,\n readHermesApiServerConfig,\n resolveHermesConfigPath,\n resolveHermesProfileDir,\n} from './config.js'\n\nexport interface HermesProfile {\n name: string\n active: boolean\n path: string\n configPath: string\n}\n\ninterface ProfileState {\n activeProfile: string\n}\n\nconst DEFAULT_PROFILE = 'default'\nconst PROFILE_NAME_PATTERN = /^[a-zA-Z0-9._-]{1,64}$/\n\nexport async function listHermesProfiles(paths: RuntimePaths = resolveRuntimePaths()): Promise<HermesProfile[]> {\n const activeProfile = await getActiveProfile(paths)\n const profiles = new Map<string, HermesProfile>()\n profiles.set(DEFAULT_PROFILE, profileInfo(DEFAULT_PROFILE, activeProfile))\n\n const profilesDir = path.join(os.homedir(), '.hermes', 'profiles')\n const entries = await readdir(profilesDir, { withFileTypes: true }).catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n return []\n }\n throw error\n })\n for (const entry of entries) {\n if (entry.isDirectory() && PROFILE_NAME_PATTERN.test(entry.name)) {\n profiles.set(entry.name, profileInfo(entry.name, activeProfile))\n }\n }\n\n return [...profiles.values()].sort((left, right) => {\n if (left.name === DEFAULT_PROFILE) {\n return -1\n }\n if (right.name === DEFAULT_PROFILE) {\n return 1\n }\n return left.name.localeCompare(right.name)\n })\n}\n\nexport async function getHermesProfileStatus(\n name: string,\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<HermesProfile & { exists: boolean; apiKeyConfigured: boolean }> {\n assertProfileName(name)\n const profile = profileInfo(name, await getActiveProfile(paths))\n const exists = await stat(profile.path)\n .then((value) => value.isDirectory())\n .catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n return false\n }\n throw error\n })\n const config = await readHermesApiServerConfig(name, profile.configPath)\n return {\n ...profile,\n exists,\n apiKeyConfigured: Boolean(config.key),\n }\n}\n\nexport async function createHermesProfile(name: string): Promise<HermesProfile> {\n assertProfileName(name)\n if (name === DEFAULT_PROFILE) {\n throw new Error('default profile already exists')\n }\n const profile = profileInfo(name, DEFAULT_PROFILE)\n if (await pathExists(profile.path)) {\n throw new Error('profile already exists')\n }\n await mkdir(profile.path, { recursive: true, mode: 0o700 })\n await ensureHermesApiServerKey(name, profile.configPath)\n return profile\n}\n\nexport async function useHermesProfile(\n name: string,\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<HermesProfile> {\n assertProfileName(name)\n const profile = profileInfo(name, name)\n await mkdir(profile.path, { recursive: true, mode: 0o700 })\n const current = (await readJsonFile<Record<string, unknown>>(paths.stateFile)) ?? {}\n await writeJsonFile(paths.stateFile, { ...current, activeProfile: name } satisfies ProfileState)\n return profile\n}\n\nexport async function renameHermesProfile(oldName: string, newName: string): Promise<HermesProfile> {\n assertMutableProfile(oldName)\n assertMutableProfile(newName)\n const oldProfile = profileInfo(oldName, DEFAULT_PROFILE)\n const newProfile = profileInfo(newName, DEFAULT_PROFILE)\n await rename(oldProfile.path, newProfile.path)\n return newProfile\n}\n\nexport async function deleteHermesProfile(name: string): Promise<void> {\n assertMutableProfile(name)\n await rm(resolveHermesProfileDir(name), { recursive: true, force: true })\n}\n\nasync function getActiveProfile(paths: RuntimePaths): Promise<string> {\n const state = await readJsonFile<Partial<ProfileState>>(paths.stateFile)\n return typeof state?.activeProfile === 'string' && PROFILE_NAME_PATTERN.test(state.activeProfile)\n ? state.activeProfile\n : DEFAULT_PROFILE\n}\n\nfunction profileInfo(name: string, activeProfile: string): HermesProfile {\n return {\n name,\n active: name === activeProfile,\n path: resolveHermesProfileDir(name),\n configPath: resolveHermesConfigPath(name),\n }\n}\n\nfunction assertMutableProfile(name: string): void {\n assertProfileName(name)\n if (name === DEFAULT_PROFILE) {\n throw new Error('default profile cannot be renamed or deleted')\n }\n}\n\nfunction assertProfileName(name: string): void {\n if (!PROFILE_NAME_PATTERN.test(name)) {\n throw new Error('invalid profile name')\n }\n}\n\nasync function pathExists(targetPath: string): Promise<boolean> {\n return await stat(targetPath)\n .then(() => true)\n .catch((error: unknown) => {\n if (isNodeError(error, 'ENOENT')) {\n return false\n }\n throw error\n })\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return typeof error === 'object' && error !== null && 'code' in error && error.code === code\n}\n","import { generateKeyPairSync, randomUUID, sign } from 'node:crypto'\nimport { mkdir, chmod } from 'node:fs/promises'\nimport { z } from 'zod'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\nimport { readJsonFile, writeJsonFile } from '../storage/atomic-json.js'\n\nconst linkIdentitySchema = z.object({\n install_id: z.string().min(1),\n link_id: z.string().min(1).nullable().optional(),\n public_key_pem: z.string().min(1),\n private_key_pem: z.string().min(1),\n created_at: z.string().min(1),\n updated_at: z.string().min(1),\n})\n\nexport type LinkIdentity = z.infer<typeof linkIdentitySchema>\n\nexport interface IdentityStatus {\n installId: string\n linkId: string | null\n hasPrivateKey: boolean\n publicKeyPem: string\n}\n\nexport async function loadIdentity(paths: RuntimePaths = resolveRuntimePaths()): Promise<LinkIdentity | null> {\n const value = await readJsonFile<unknown>(paths.identityFile)\n if (value === null) {\n return null\n }\n return linkIdentitySchema.parse(value)\n}\n\nexport async function ensureIdentity(paths: RuntimePaths = resolveRuntimePaths()): Promise<LinkIdentity> {\n const existing = await loadIdentity(paths)\n if (existing) {\n return existing\n }\n\n await mkdir(paths.homeDir, { recursive: true, mode: 0o700 })\n await chmod(paths.homeDir, 0o700).catch(() => undefined)\n\n const { publicKey, privateKey } = generateKeyPairSync('ed25519')\n const now = new Date().toISOString()\n const identity: LinkIdentity = {\n install_id: `install_${randomUUID().replaceAll('-', '')}`,\n link_id: null,\n public_key_pem: publicKey.export({ type: 'spki', format: 'pem' }).toString(),\n private_key_pem: privateKey.export({ type: 'pkcs8', format: 'pem' }).toString(),\n created_at: now,\n updated_at: now,\n }\n await writeJsonFile(paths.identityFile, identity)\n return identity\n}\n\nexport async function saveAssignedLinkId(\n linkId: string,\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<LinkIdentity> {\n const identity = await ensureIdentity(paths)\n const next: LinkIdentity = {\n ...identity,\n link_id: linkId,\n updated_at: new Date().toISOString(),\n }\n await writeJsonFile(paths.identityFile, next)\n return next\n}\n\nexport function signRelayNonce(identity: LinkIdentity, nonce: string): string {\n const signature = sign(null, Buffer.from(nonce, 'utf8'), identity.private_key_pem)\n return signature.toString('base64url')\n}\n\nexport function getIdentityStatus(identity: LinkIdentity): IdentityStatus {\n return {\n installId: identity.install_id,\n linkId: identity.link_id ?? null,\n hasPrivateKey: identity.private_key_pem.trim().length > 0,\n publicKeyPem: identity.public_key_pem,\n }\n}\n\n","import path from 'node:path'\nimport { rm } from 'node:fs/promises'\nimport { loadConfig } from '../config/config.js'\nimport { createDeviceSession } from '../security/devices.js'\nimport { ensureIdentity, loadIdentity, type LinkIdentity } from '../identity/identity.js'\nimport { bootstrapRelayLink } from '../relay/bootstrap.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\nimport { discoverRouteCandidates, type RouteDiscoveryResult } from '../topology/network.js'\nimport { LinkHttpError } from '../http/errors.js'\nimport { readJsonFile, writeJsonFile } from '../storage/atomic-json.js'\n\nexport interface PreparedPairing {\n sessionId: string\n code: string\n pairingToken: string\n relayBootstrapToken: string\n relayBaseUrl: string\n displayName: string\n linkId: string\n routes: RouteDiscoveryResult\n qrPayload: Record<string, unknown>\n}\n\nexport interface PairingClaimRecord {\n session_id: string\n device_id: string\n device_label: string\n device_platform: string\n claimed_at: string\n}\n\nexport async function preparePairing(paths: RuntimePaths = resolveRuntimePaths()): Promise<PreparedPairing> {\n const config = await loadConfig(paths)\n const identity = await ensureIdentity(paths)\n const created = await postServerJson<{\n sessionId: string\n code: string\n pairingToken: string\n relayBootstrapToken: string\n relayBaseUrl: string\n }>(config.serverBaseUrl, '/api/v1/link-pairings', {\n install_id: identity.install_id,\n link_id: identity.link_id ?? undefined,\n display_name: defaultDisplayName(),\n public_key_pem: identity.public_key_pem,\n })\n const relayBaseUrl = created.relayBaseUrl || config.relayBaseUrl\n const assigned = await bootstrapRelayLink({\n relayBaseUrl,\n relayBootstrapToken: created.relayBootstrapToken,\n identity,\n paths,\n })\n const updatedIdentity = (await loadIdentity(paths)) ?? identity\n const routes = await discoverRouteCandidates({\n port: config.port,\n relayBaseUrl,\n relayBootstrapToken: created.relayBootstrapToken,\n linkId: assigned.linkId,\n installId: updatedIdentity.install_id,\n publicKeyPem: updatedIdentity.public_key_pem,\n })\n await patchServerJson(config.serverBaseUrl, `/api/v1/link-pairings/${created.sessionId}/link`, created.pairingToken, {\n install_id: updatedIdentity.install_id,\n link_id: assigned.linkId,\n display_name: defaultDisplayName(),\n lan_ips: routes.lanIps,\n public_ipv4s: routes.publicIpv4s,\n public_ipv6s: routes.publicIpv6s,\n preferred_urls: routes.preferredUrls,\n })\n const qrPayload = {\n kind: 'hermes_link_pairing',\n version: 1,\n link_id: assigned.linkId,\n display_name: defaultDisplayName(),\n session_id: created.sessionId,\n code: created.code,\n preferred_urls: qrPreferredUrls(routes),\n }\n return {\n sessionId: created.sessionId,\n code: created.code,\n pairingToken: created.pairingToken,\n relayBootstrapToken: created.relayBootstrapToken,\n relayBaseUrl,\n displayName: defaultDisplayName(),\n linkId: assigned.linkId,\n routes,\n qrPayload,\n }\n}\n\nexport async function recordPairingClaim(\n input: {\n sessionId: string\n deviceId: string\n deviceLabel: string\n devicePlatform: string\n },\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<PairingClaimRecord> {\n const record: PairingClaimRecord = {\n session_id: input.sessionId,\n device_id: input.deviceId,\n device_label: input.deviceLabel,\n device_platform: input.devicePlatform,\n claimed_at: new Date().toISOString(),\n }\n await writeJsonFile(pairingClaimPath(input.sessionId, paths), record)\n return record\n}\n\nexport async function readPairingClaim(\n sessionId: string,\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<PairingClaimRecord | null> {\n const record = await readJsonFile<Partial<PairingClaimRecord>>(pairingClaimPath(sessionId, paths))\n if (!record || record.session_id !== sessionId || typeof record.device_id !== 'string') {\n return null\n }\n return {\n session_id: record.session_id,\n device_id: record.device_id,\n device_label: typeof record.device_label === 'string' ? record.device_label : '',\n device_platform: typeof record.device_platform === 'string' ? record.device_platform : 'unknown',\n claimed_at: typeof record.claimed_at === 'string' ? record.claimed_at : '',\n }\n}\n\nexport async function clearPairingClaim(\n sessionId: string,\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<void> {\n await rm(pairingClaimPath(sessionId, paths), { force: true }).catch(() => undefined)\n}\n\nexport async function claimPairing(input: {\n sessionId: string\n claimToken: string\n deviceLabel: string\n devicePlatform: string\n paths?: RuntimePaths\n}): Promise<{\n link: { link_id: string; display_name: string }\n device: ReturnType<typeof formatDevice>\n access_token: { token: string; expires_at: string }\n refresh_token: { token: string; expires_at: string }\n}> {\n const paths = input.paths ?? resolveRuntimePaths()\n const [identity, config] = await Promise.all([loadRequiredIdentity(paths), loadConfig(paths)])\n const verified = await postServerJson<{ ok: boolean; linkId: string }>(\n config.serverBaseUrl,\n `/api/v1/link-pairings/${input.sessionId}/claim/verify`,\n {\n claim_token: input.claimToken,\n },\n )\n if (verified.ok !== true || verified.linkId !== identity.link_id) {\n throw new LinkHttpError(409, 'pairing_claim_mismatch', 'Pairing claim does not match this Link')\n }\n const session = await createDeviceSession(\n {\n label: input.deviceLabel || 'HermesPilot App',\n platform: input.devicePlatform || 'unknown',\n },\n paths,\n )\n return {\n link: {\n link_id: identity.link_id,\n display_name: defaultDisplayName(),\n },\n device: formatDevice(session.device),\n access_token: {\n token: session.accessToken.token,\n expires_at: session.accessToken.expiresAt,\n },\n refresh_token: {\n token: session.refreshToken.token,\n expires_at: session.refreshToken.expiresAt,\n },\n }\n}\n\nasync function loadRequiredIdentity(paths: RuntimePaths): Promise<LinkIdentity & { link_id: string }> {\n const identity = await loadIdentity(paths)\n if (!identity?.link_id) {\n throw new LinkHttpError(409, 'link_not_paired', 'Hermes Link is not paired')\n }\n return identity as LinkIdentity & { link_id: string }\n}\n\nasync function postServerJson<T>(serverBaseUrl: string, path: string, body: Record<string, unknown>): Promise<T> {\n const response = await fetch(`${serverBaseUrl.replace(/\\/+$/u, '')}${path}`, {\n method: 'POST',\n headers: {\n accept: 'application/json',\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n return readJsonResponse<T>(response)\n}\n\nasync function patchServerJson<T>(\n serverBaseUrl: string,\n path: string,\n token: string,\n body: Record<string, unknown>,\n): Promise<T> {\n const response = await fetch(`${serverBaseUrl.replace(/\\/+$/u, '')}${path}`, {\n method: 'PATCH',\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n return readJsonResponse<T>(response)\n}\n\nasync function readJsonResponse<T>(response: Response): Promise<T> {\n const payload = (await response.json().catch(() => null)) as T | null\n if (!response.ok || !payload) {\n const message = readErrorMessage(payload) ?? `HermesPilot Server request failed with HTTP ${response.status}`\n throw new LinkHttpError(response.status, 'server_request_failed', message)\n }\n return payload\n}\n\nfunction readErrorMessage(payload: unknown): string | null {\n if (typeof payload !== 'object' || payload === null) {\n return null\n }\n const error = (payload as { error?: unknown }).error\n if (typeof error !== 'object' || error === null) {\n return null\n }\n const message = (error as { message?: unknown }).message\n return typeof message === 'string' ? message : null\n}\n\nfunction defaultDisplayName(): string {\n return `Hermes Link ${process.platform}`\n}\n\nfunction pairingClaimPath(sessionId: string, paths: RuntimePaths): string {\n return path.join(paths.pairingDir, `${Buffer.from(sessionId).toString('base64url')}.claimed.json`)\n}\n\nfunction qrPreferredUrls(routes: RouteDiscoveryResult): string[] {\n return routes.preferredUrls.filter((url) => !url.includes('/api/v1/relay/links/')).slice(0, 1)\n}\n\nfunction formatDevice(device: { id: string; device_id: string; label: string; platform: string; scope: 'admin' }) {\n return {\n id: device.id,\n device_id: device.device_id,\n label: device.label,\n platform: device.platform,\n scope: device.scope,\n }\n}\n","import { randomBytes, randomUUID, timingSafeEqual, createHash } from 'node:crypto'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\nimport { readJsonFile, writeJsonFile } from '../storage/atomic-json.js'\nimport { LinkHttpError } from '../http/errors.js'\n\nexport interface DeviceRecord {\n id: string\n label: string\n platform: string\n scope: 'admin'\n access_token_hash: string\n access_expires_at: string\n refresh_token_hash: string\n refresh_expires_at: string\n created_at: string\n updated_at: string\n revoked_at: string | null\n}\n\ninterface CredentialStore {\n devices: DeviceRecord[]\n}\n\nexport interface CreatedDeviceSession {\n device: {\n id: string\n device_id: string\n label: string\n platform: string\n scope: 'admin'\n }\n accessToken: {\n token: string\n expiresAt: string\n }\n refreshToken: {\n token: string\n expiresAt: string\n }\n}\n\nconst ACCESS_TOKEN_TTL_MS = 15 * 60 * 1000\nconst REFRESH_TOKEN_TTL_MS = 90 * 24 * 60 * 60 * 1000\n\nexport async function createDeviceSession(\n input: { label: string; platform: string },\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<CreatedDeviceSession> {\n const store = await readCredentialStore(paths)\n const now = new Date()\n const accessToken = randomToken('hpat_')\n const refreshToken = randomToken('hprt_')\n const device: DeviceRecord = {\n id: `dev_${randomUUID().replaceAll('-', '')}`,\n label: input.label,\n platform: input.platform,\n scope: 'admin',\n access_token_hash: sha256(accessToken),\n access_expires_at: new Date(now.getTime() + ACCESS_TOKEN_TTL_MS).toISOString(),\n refresh_token_hash: sha256(refreshToken),\n refresh_expires_at: new Date(now.getTime() + REFRESH_TOKEN_TTL_MS).toISOString(),\n created_at: now.toISOString(),\n updated_at: now.toISOString(),\n revoked_at: null,\n }\n store.devices.push(device)\n await writeCredentialStore(paths, store)\n return formatDeviceSession(device, accessToken, refreshToken)\n}\n\nexport async function authenticateDeviceAccessToken(\n token: string,\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<DeviceRecord | null> {\n const tokenHash = sha256(token)\n const store = await readCredentialStore(paths)\n const device = store.devices.find((item) => safeEqual(item.access_token_hash, tokenHash))\n if (!device || device.revoked_at || Date.parse(device.access_expires_at) <= Date.now()) {\n return null\n }\n return device\n}\n\nexport async function refreshDeviceSession(\n refreshToken: string,\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<CreatedDeviceSession> {\n const tokenHash = sha256(refreshToken)\n const store = await readCredentialStore(paths)\n const device = store.devices.find((item) => safeEqual(item.refresh_token_hash, tokenHash))\n if (!device || device.revoked_at || Date.parse(device.refresh_expires_at) <= Date.now()) {\n throw new LinkHttpError(401, 'refresh_token_invalid', 'Refresh token is invalid or expired')\n }\n\n const now = new Date()\n const nextAccessToken = randomToken('hpat_')\n const nextRefreshToken = randomToken('hprt_')\n device.access_token_hash = sha256(nextAccessToken)\n device.access_expires_at = new Date(now.getTime() + ACCESS_TOKEN_TTL_MS).toISOString()\n device.refresh_token_hash = sha256(nextRefreshToken)\n device.refresh_expires_at = new Date(now.getTime() + REFRESH_TOKEN_TTL_MS).toISOString()\n device.updated_at = now.toISOString()\n await writeCredentialStore(paths, store)\n return formatDeviceSession(device, nextAccessToken, nextRefreshToken)\n}\n\nexport async function revokeDeviceRefreshToken(\n refreshToken: string,\n paths: RuntimePaths = resolveRuntimePaths(),\n): Promise<void> {\n const tokenHash = sha256(refreshToken)\n const store = await readCredentialStore(paths)\n const device = store.devices.find((item) => safeEqual(item.refresh_token_hash, tokenHash))\n if (!device || device.revoked_at) {\n return\n }\n device.revoked_at = new Date().toISOString()\n device.updated_at = device.revoked_at\n await writeCredentialStore(paths, store)\n}\n\nasync function readCredentialStore(paths: RuntimePaths): Promise<CredentialStore> {\n const existing = await readJsonFile<Partial<CredentialStore>>(paths.credentialsFile)\n return {\n devices: Array.isArray(existing?.devices) ? existing.devices.filter(isDeviceRecord) : [],\n }\n}\n\nasync function writeCredentialStore(paths: RuntimePaths, store: CredentialStore): Promise<void> {\n await writeJsonFile(paths.credentialsFile, store)\n}\n\nfunction formatDeviceSession(device: DeviceRecord, accessToken: string, refreshToken: string): CreatedDeviceSession {\n return {\n device: {\n id: device.id,\n device_id: device.id,\n label: device.label,\n platform: device.platform,\n scope: device.scope,\n },\n accessToken: {\n token: accessToken,\n expiresAt: device.access_expires_at,\n },\n refreshToken: {\n token: refreshToken,\n expiresAt: device.refresh_expires_at,\n },\n }\n}\n\nfunction isDeviceRecord(value: unknown): value is DeviceRecord {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as DeviceRecord).id === 'string' &&\n typeof (value as DeviceRecord).access_token_hash === 'string' &&\n typeof (value as DeviceRecord).refresh_token_hash === 'string'\n )\n}\n\nfunction randomToken(prefix: string): string {\n return `${prefix}${randomBytes(24).toString('base64url')}`\n}\n\nfunction sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\nfunction safeEqual(left: string, right: string): boolean {\n const leftBytes = Buffer.from(left)\n const rightBytes = Buffer.from(right)\n return leftBytes.length === rightBytes.length && timingSafeEqual(leftBytes, rightBytes)\n}\n","import { saveAssignedLinkId, signRelayNonce, type LinkIdentity } from '../identity/identity.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\n\nexport interface RelayBootstrapOptions {\n relayBaseUrl: string\n relayBootstrapToken: string\n identity: LinkIdentity\n paths?: RuntimePaths\n fetchImpl?: typeof fetch\n}\n\nexport interface RelayBootstrapResult {\n linkId: string\n reused: boolean\n}\n\ninterface RelayChallengeResponse {\n ok?: unknown\n nonce?: unknown\n expires_at?: unknown\n}\n\ninterface RelayBootstrapResponse {\n ok?: unknown\n link_id?: unknown\n reused?: unknown\n}\n\nexport async function bootstrapRelayLink(options: RelayBootstrapOptions): Promise<RelayBootstrapResult> {\n const fetcher = options.fetchImpl ?? fetch\n const baseUrl = options.relayBaseUrl.replace(/\\/+$/u, '')\n const commonPayload = {\n install_id: options.identity.install_id,\n link_id: options.identity.link_id ?? undefined,\n public_key_pem: options.identity.public_key_pem,\n }\n const challenge = await postJson<RelayChallengeResponse>(\n fetcher,\n `${baseUrl}/api/v1/relay/link/challenge`,\n options.relayBootstrapToken,\n commonPayload,\n )\n if (challenge.ok !== true || typeof challenge.nonce !== 'string') {\n throw new Error('Relay did not return a valid install challenge')\n }\n\n const proof = {\n nonce: challenge.nonce,\n signature: signRelayNonce(options.identity, challenge.nonce),\n }\n const assigned = await postJson<RelayBootstrapResponse>(\n fetcher,\n `${baseUrl}/api/v1/relay/link/bootstrap`,\n options.relayBootstrapToken,\n {\n ...commonPayload,\n proof,\n },\n )\n if (assigned.ok !== true || typeof assigned.link_id !== 'string') {\n throw new Error('Relay did not return a valid link_id')\n }\n\n await saveAssignedLinkId(assigned.link_id, options.paths ?? resolveRuntimePaths())\n return {\n linkId: assigned.link_id,\n reused: assigned.reused === true,\n }\n}\n\nasync function postJson<T>(\n fetcher: typeof fetch,\n url: string,\n token: string,\n body: Record<string, unknown>,\n): Promise<T> {\n const response = await fetcher(url, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n const payload = (await response.json().catch(() => null)) as T | null\n if (!response.ok) {\n const message = readErrorMessage(payload) ?? `Relay request failed with HTTP ${response.status}`\n throw new Error(message)\n }\n if (!payload) {\n throw new Error('Relay returned an empty response')\n }\n return payload\n}\n\nfunction readErrorMessage(payload: unknown): string | null {\n if (typeof payload !== 'object' || payload === null) {\n return null\n }\n const error = (payload as { error?: unknown }).error\n if (typeof error !== 'object' || error === null) {\n return null\n }\n const message = (error as { message?: unknown }).message\n return typeof message === 'string' ? message : null\n}\n","import os from 'node:os'\nimport type { NetworkInterfaceInfo } from 'node:os'\n\nexport interface RouteDiscoveryResult {\n lanIps: string[]\n publicIpv4s: string[]\n publicIpv6s: string[]\n preferredUrls: string[]\n}\n\nconst VIRTUAL_INTERFACE_NAME_PATTERN =\n /(docker|veth|vmnet|vmenet|vbox|virtualbox|vmware|tailscale|zerotier|wireguard|utun|virbr|hyper-v|vethernet|loopback|\\blo\\b|^lo\\d*$|^br-|^bridge\\d+$|^zt|^tun|^tap|awdl|llw|anpi|gif|stf|ipsec|ppp)/iu\n\nconst MAX_LAN_IPS = 4\nconst MAX_PUBLIC_IPV4S = 2\nconst MAX_PUBLIC_IPV6S = 2\n\nexport async function discoverRouteCandidates(options: {\n port: number\n relayBaseUrl: string\n linkId: string\n installId: string\n publicKeyPem: string\n relayBootstrapToken?: string\n fetchImpl?: typeof fetch\n}): Promise<RouteDiscoveryResult> {\n const lanIps = discoverLanIps()\n const publicIps = options.relayBootstrapToken\n ? await observePublicRoute(options).catch(() => ({ publicIpv4s: [], publicIpv6s: [] }))\n : { publicIpv4s: [], publicIpv6s: [] }\n const publicIpv4s = unique(publicIps.publicIpv4s.filter(isUsablePublicIpv4)).slice(0, MAX_PUBLIC_IPV4S)\n const publicIpv6s = unique(publicIps.publicIpv6s.filter(isUsablePublicIpv6)).slice(0, MAX_PUBLIC_IPV6S)\n const preferredUrls = [\n ...lanIps.map((ip) => buildDirectUrl(ip, options.port)),\n ...publicIpv4s.map((ip) => buildDirectUrl(ip, options.port)),\n ...publicIpv6s.map((ip) => buildDirectUrl(ip, options.port)),\n `${options.relayBaseUrl.replace(/\\/+$/u, '')}/api/v1/relay/links/${options.linkId}`,\n ]\n return {\n lanIps,\n publicIpv4s,\n publicIpv6s,\n preferredUrls,\n }\n}\n\nfunction discoverLanIps(): string[] {\n return discoverLanIpsFromInterfaces(os.networkInterfaces())\n}\n\nexport function discoverLanIpsFromInterfaces(interfaces: NodeJS.Dict<NetworkInterfaceInfo[]>): string[] {\n const result = new Set<string>()\n const candidates: Array<{ name: string; address: string }> = []\n for (const [name, items] of Object.entries(interfaces)) {\n if (shouldIgnoreInterface(name)) {\n continue\n }\n for (const item of items ?? []) {\n if (!item.internal && item.address && item.family === 'IPv4' && isUsableLanIpv4(item.address, item.netmask)) {\n candidates.push({ name, address: item.address })\n }\n }\n }\n for (const candidate of candidates.sort(compareLanCandidate)) {\n result.add(candidate.address)\n }\n return [...result].slice(0, MAX_LAN_IPS)\n}\n\nasync function observePublicRoute(options: {\n relayBaseUrl: string\n installId: string\n linkId: string\n publicKeyPem: string\n relayBootstrapToken?: string\n fetchImpl?: typeof fetch\n}): Promise<{ publicIpv4s: string[]; publicIpv6s: string[] }> {\n const fetcher = options.fetchImpl ?? fetch\n const response = await fetcher(`${options.relayBaseUrl.replace(/\\/+$/u, '')}/api/v1/relay/public-route/observe`, {\n method: 'POST',\n headers: {\n authorization: `Bearer ${options.relayBootstrapToken}`,\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n install_id: options.installId,\n link_id: options.linkId,\n public_key_pem: options.publicKeyPem,\n }),\n })\n const payload = (await response.json().catch(() => null)) as Record<string, unknown> | null\n const record = typeof payload?.record === 'object' && payload.record !== null\n ? (payload.record as Record<string, unknown>)\n : null\n const observed = typeof payload?.observed === 'object' && payload.observed !== null\n ? (payload.observed as Record<string, unknown>)\n : null\n const values = [\n readIpRecord(record?.ipv4),\n readIpRecord(record?.ipv6),\n typeof observed?.ip === 'string' ? observed.ip : null,\n ].filter((value): value is string => Boolean(value))\n return {\n publicIpv4s: unique(values.filter(isUsablePublicIpv4)),\n publicIpv6s: unique(values.filter(isUsablePublicIpv6)),\n }\n}\n\nfunction readIpRecord(value: unknown): string | null {\n if (typeof value !== 'object' || value === null) {\n return null\n }\n const ip = (value as { ip?: unknown }).ip\n return typeof ip === 'string' && ip.trim() ? ip.trim() : null\n}\n\nfunction buildDirectUrl(ip: string, port: number): string {\n return `http://${ip.includes(':') ? `[${ip}]` : ip}:${port}`\n}\n\nfunction shouldIgnoreInterface(name: string): boolean {\n return !name.trim() || VIRTUAL_INTERFACE_NAME_PATTERN.test(name)\n}\n\nfunction compareLanCandidate(left: { name: string; address: string }, right: { name: string; address: string }): number {\n const priority = interfacePriority(left.name) - interfacePriority(right.name)\n return priority || left.name.localeCompare(right.name) || left.address.localeCompare(right.address)\n}\n\nfunction interfacePriority(name: string): number {\n if (/^(en|eth|wlan|wi-fi|wifi)/iu.test(name)) {\n return 0\n }\n return 1\n}\n\nfunction isUsableLanIpv4(address: string, netmask?: string): boolean {\n return isPrivateIpv4(address) && !isNetworkOrBroadcastIpv4Address(address, netmask)\n}\n\nfunction isUsablePublicIpv4(address: string): boolean {\n return isValidIpv4(address) && !isSpecialIpv4(address)\n}\n\nfunction isUsablePublicIpv6(address: string): boolean {\n const normalized = address.toLowerCase()\n return (\n normalized.includes(':') &&\n !normalized.startsWith('fe80:') &&\n !normalized.startsWith('fc') &&\n !normalized.startsWith('fd') &&\n !normalized.startsWith('ff') &&\n normalized !== '::' &&\n normalized !== '::1'\n )\n}\n\nfunction isPrivateIpv4(address: string): boolean {\n const parts = parseIpv4Segments(address)\n if (!parts) {\n return false\n }\n const [first, second] = parts\n return first === 10 || (first === 172 && second >= 16 && second <= 31) || (first === 192 && second === 168)\n}\n\nfunction isSpecialIpv4(address: string): boolean {\n const parts = parseIpv4Segments(address)\n if (!parts) {\n return true\n }\n const [first, second, third, fourth] = parts\n return (\n first === 0 ||\n first === 10 ||\n first === 127 ||\n first >= 224 ||\n (first === 100 && second >= 64 && second <= 127) ||\n (first === 169 && second === 254) ||\n (first === 172 && second >= 16 && second <= 31) ||\n (first === 192 && second === 168) ||\n (first === 192 && second === 0 && third === 2) ||\n (first === 198 && (second === 18 || second === 19)) ||\n (first === 198 && second === 51 && third === 100) ||\n (first === 203 && second === 0 && third === 113) ||\n (first === 255 && second === 255 && third === 255 && fourth === 255)\n )\n}\n\nfunction isNetworkOrBroadcastIpv4Address(address: string, netmask?: string): boolean {\n const addressParts = parseIpv4Segments(address)\n const netmaskParts = netmask ? parseIpv4Segments(netmask) : null\n if (!addressParts) {\n return true\n }\n if (!netmaskParts) {\n const last = addressParts[3]\n return last === 0 || last === 255\n }\n const addressInt = ipv4SegmentsToInt(addressParts)\n const netmaskInt = ipv4SegmentsToInt(netmaskParts)\n const hostMask = (~netmaskInt) >>> 0\n if (hostMask === 0) {\n return false\n }\n const networkInt = addressInt & netmaskInt\n const broadcastInt = (networkInt | hostMask) >>> 0\n return addressInt === networkInt || addressInt === broadcastInt\n}\n\nfunction isValidIpv4(address: string): boolean {\n return Boolean(parseIpv4Segments(address))\n}\n\nfunction parseIpv4Segments(address: string): [number, number, number, number] | null {\n if (!/^\\d{1,3}(?:\\.\\d{1,3}){3}$/u.test(address)) {\n return null\n }\n const parts = address.split('.').map((part) => Number.parseInt(part, 10))\n if (parts.length !== 4 || parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) {\n return null\n }\n return parts as [number, number, number, number]\n}\n\nfunction ipv4SegmentsToInt(parts: [number, number, number, number]): number {\n return (((parts[0] << 24) >>> 0) | (parts[1] << 16) | (parts[2] << 8) | parts[3]) >>> 0\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)]\n}\n","import { createPublicKey, verify, type JsonWebKey as NodeJsonWebKey } from 'node:crypto'\nimport { LinkConfig } from '../config/config.js'\nimport { LinkHttpError } from '../http/errors.js'\n\ninterface JwksResponse {\n keys?: ServerJwk[]\n}\n\ninterface JwtHeader {\n alg?: string\n kid?: string\n typ?: string\n}\n\nexport interface AppConnectClaims {\n token_type: 'hermes_app_connect'\n iss: string\n aud: string\n sub: string\n link_id: string\n exp: number\n iat?: number\n jti?: string\n}\n\ntype ServerJwk = NodeJsonWebKey & { kid?: string }\n\nlet cachedJwks: { expiresAt: number; keys: ServerJwk[] } | null = null\n\nexport async function verifyAppConnectToken(\n token: string,\n options: {\n config: LinkConfig\n linkId: string\n fetchImpl?: typeof fetch\n },\n): Promise<AppConnectClaims> {\n const segments = token.split('.')\n if (segments.length !== 3) {\n throw new LinkHttpError(401, 'app_connect_token_invalid', 'App connect token is malformed')\n }\n const [encodedHeader, encodedPayload, encodedSignature] = segments\n const header = decodeJson<JwtHeader>(encodedHeader)\n const payload = decodeJson<AppConnectClaims>(encodedPayload)\n if (header.alg !== 'ES256' || header.typ !== 'JWT') {\n throw new LinkHttpError(401, 'app_connect_token_invalid', 'App connect token algorithm is unsupported')\n }\n if (\n payload.token_type !== 'hermes_app_connect' ||\n payload.iss !== options.config.appConnectTokenIssuer ||\n payload.aud !== options.config.appConnectTokenAudience ||\n payload.link_id !== options.linkId ||\n !Number.isFinite(payload.exp) ||\n payload.exp <= Math.floor(Date.now() / 1000)\n ) {\n throw new LinkHttpError(401, 'app_connect_token_invalid', 'App connect token claims are invalid')\n }\n\n const jwks = await getJwks(options.config, options.fetchImpl ?? fetch)\n const key = jwks.find((item) => item.kid === header.kid) ?? jwks[0]\n if (!key) {\n throw new LinkHttpError(503, 'app_connect_jwks_unavailable', 'App connect token key is unavailable')\n }\n const publicKey = createPublicKey({ key, format: 'jwk' })\n const ok = verify(\n 'sha256',\n Buffer.from(`${encodedHeader}.${encodedPayload}`),\n { key: publicKey, dsaEncoding: 'ieee-p1363' },\n Buffer.from(base64UrlToBase64(encodedSignature), 'base64'),\n )\n if (!ok) {\n throw new LinkHttpError(401, 'app_connect_token_invalid', 'App connect token signature is invalid')\n }\n return payload\n}\n\nasync function getJwks(config: LinkConfig, fetcher: typeof fetch): Promise<ServerJwk[]> {\n if (cachedJwks && cachedJwks.expiresAt > Date.now()) {\n return cachedJwks.keys\n }\n const response = await fetcher(`${config.serverBaseUrl.replace(/\\/+$/u, '')}/api/v1/app-connect/jwks.json`, {\n headers: { accept: 'application/json' },\n })\n if (!response.ok) {\n throw new LinkHttpError(503, 'app_connect_jwks_unavailable', 'Unable to load app connect JWKS')\n }\n const payload = (await response.json()) as JwksResponse\n const keys = Array.isArray(payload.keys) ? payload.keys : []\n cachedJwks = {\n keys,\n expiresAt: Date.now() + 5 * 60 * 1000,\n }\n return keys\n}\n\nfunction decodeJson<T>(value: string): T {\n return JSON.parse(Buffer.from(base64UrlToBase64(value), 'base64').toString('utf8')) as T\n}\n\nfunction base64UrlToBase64(value: string): string {\n const normalized = value.replace(/-/g, '+').replace(/_/g, '/')\n return normalized + '='.repeat((4 - (normalized.length % 4)) % 4)\n}\n","import { appendFile, mkdir, open, readFile, rename, rm, stat } from 'node:fs/promises'\nimport path from 'node:path'\nimport { resolveRuntimePaths, type RuntimePaths } from './paths.js'\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error'\n\nexport interface LogEntry {\n ts: string\n level: LogLevel\n message: string\n fields?: Record<string, JsonValue>\n}\n\ntype JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue }\n\nexport interface FileLoggerOptions {\n paths?: RuntimePaths\n fileName?: string\n maxFileBytes?: number\n maxFiles?: number\n now?: () => Date\n}\n\nexport interface ReadLogOptions {\n paths?: RuntimePaths\n fileName?: string\n limit?: number\n maxFiles?: number\n maxBytesPerFile?: number\n}\n\nconst DEFAULT_LOG_FILE = 'hermeslink.log'\nconst DEFAULT_MAX_FILE_BYTES = 1024 * 1024\nconst DEFAULT_MAX_FILES = 5\nconst DEFAULT_READ_LIMIT = 200\nconst MAX_READ_LIMIT = 1000\nconst DEFAULT_MAX_BYTES_PER_FILE = 512 * 1024\n\nexport class FileLogger {\n readonly filePath: string\n private readonly paths: RuntimePaths\n private readonly maxFileBytes: number\n private readonly maxFiles: number\n private readonly now: () => Date\n private queue = Promise.resolve()\n\n constructor(options: FileLoggerOptions = {}) {\n this.paths = options.paths ?? resolveRuntimePaths()\n this.filePath = getLinkLogFile(this.paths, options.fileName)\n this.maxFileBytes = Math.max(256, Math.floor(options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES))\n this.maxFiles = Math.max(0, Math.floor(options.maxFiles ?? DEFAULT_MAX_FILES))\n this.now = options.now ?? (() => new Date())\n }\n\n debug(message: string, fields?: Record<string, unknown>): Promise<void> {\n return this.write('debug', message, fields)\n }\n\n info(message: string, fields?: Record<string, unknown>): Promise<void> {\n return this.write('info', message, fields)\n }\n\n warn(message: string, fields?: Record<string, unknown>): Promise<void> {\n return this.write('warn', message, fields)\n }\n\n error(message: string, fields?: Record<string, unknown>): Promise<void> {\n return this.write('error', message, fields)\n }\n\n write(level: LogLevel, message: string, fields?: Record<string, unknown>): Promise<void> {\n const entry: LogEntry = {\n ts: this.now().toISOString(),\n level,\n message,\n ...(fields ? { fields: sanitizeFields(fields) } : {}),\n }\n const next = this.queue.then(() => this.appendEntry(entry)).catch(() => undefined)\n this.queue = next\n return next\n }\n\n flush(): Promise<void> {\n return this.queue\n }\n\n private async appendEntry(entry: LogEntry): Promise<void> {\n await mkdir(this.paths.logsDir, { recursive: true, mode: 0o700 })\n const line = `${JSON.stringify(entry)}\\n`\n await this.rotateIfNeeded(Buffer.byteLength(line, 'utf8'))\n await appendFile(this.filePath, line, { mode: 0o600 })\n }\n\n private async rotateIfNeeded(nextBytes: number): Promise<void> {\n const current = await stat(this.filePath).catch(() => null)\n if (!current || current.size === 0 || current.size + nextBytes <= this.maxFileBytes) {\n return\n }\n if (this.maxFiles === 0) {\n await rm(this.filePath, { force: true }).catch(() => undefined)\n return\n }\n await rm(rotatedLogFile(this.filePath, this.maxFiles), { force: true }).catch(() => undefined)\n for (let index = this.maxFiles - 1; index >= 1; index -= 1) {\n await moveIfExists(rotatedLogFile(this.filePath, index), rotatedLogFile(this.filePath, index + 1))\n }\n await moveIfExists(this.filePath, rotatedLogFile(this.filePath, 1))\n }\n}\n\nexport function createFileLogger(options: FileLoggerOptions = {}): FileLogger {\n return new FileLogger(options)\n}\n\nexport function getLinkLogFile(paths: RuntimePaths = resolveRuntimePaths(), fileName = DEFAULT_LOG_FILE): string {\n return path.join(paths.logsDir, fileName)\n}\n\nexport async function readRecentLogEntries(options: ReadLogOptions = {}): Promise<LogEntry[]> {\n const paths = options.paths ?? resolveRuntimePaths()\n const filePath = getLinkLogFile(paths, options.fileName)\n const limit = clampLimit(options.limit)\n const maxFiles = Math.max(0, Math.floor(options.maxFiles ?? DEFAULT_MAX_FILES))\n const maxBytesPerFile = Math.max(1024, Math.floor(options.maxBytesPerFile ?? DEFAULT_MAX_BYTES_PER_FILE))\n const files = [filePath, ...Array.from({ length: maxFiles }, (_, index) => rotatedLogFile(filePath, index + 1))]\n const entries: LogEntry[] = []\n\n for (const file of files) {\n const raw = await readTail(file, maxBytesPerFile)\n if (!raw) {\n continue\n }\n const lines = raw.split(/\\r?\\n/u).filter(Boolean)\n for (let index = lines.length - 1; index >= 0 && entries.length < limit; index -= 1) {\n const entry = parseLogLine(lines[index])\n if (entry) {\n entries.push(entry)\n }\n }\n if (entries.length >= limit) {\n break\n }\n }\n\n return entries.reverse()\n}\n\nfunction clampLimit(value: number | undefined): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n return DEFAULT_READ_LIMIT\n }\n return Math.min(MAX_READ_LIMIT, Math.max(1, Math.floor(value)))\n}\n\nfunction sanitizeFields(fields: Record<string, unknown>): Record<string, JsonValue> {\n return sanitizeObject(fields, 0)\n}\n\nfunction sanitizeValue(value: unknown, depth: number): JsonValue {\n if (value === null || typeof value === 'boolean') {\n return value\n }\n if (typeof value === 'number') {\n return Number.isFinite(value) ? value : null\n }\n if (typeof value === 'string') {\n return value.length > 2000 ? `${value.slice(0, 2000)}...` : value\n }\n if (Array.isArray(value)) {\n if (depth >= 3) {\n return '[array]'\n }\n return value.slice(0, 20).map((item) => sanitizeValue(item, depth + 1))\n }\n if (typeof value === 'object' && value !== null) {\n if (depth >= 3) {\n return '[object]'\n }\n return sanitizeObject(value as Record<string, unknown>, depth + 1)\n }\n return String(value)\n}\n\nfunction sanitizeObject(value: Record<string, unknown>, depth: number): Record<string, JsonValue> {\n const result: Record<string, JsonValue> = {}\n for (const [key, child] of Object.entries(value).slice(0, 50)) {\n if (isSensitiveKey(key)) {\n result[key] = '[redacted]'\n continue\n }\n result[key] = sanitizeValue(child, depth)\n }\n return result\n}\n\nfunction isSensitiveKey(key: string): boolean {\n return /(authorization|cookie|token|secret|password|private[_-]?key|api[_-]?key)/iu.test(key)\n}\n\nfunction parseLogLine(line: string): LogEntry | null {\n try {\n const value = JSON.parse(line) as Partial<LogEntry>\n if (!value || typeof value.ts !== 'string' || !isLogLevel(value.level) || typeof value.message !== 'string') {\n return null\n }\n return {\n ts: value.ts,\n level: value.level,\n message: value.message,\n ...(value.fields && typeof value.fields === 'object' ? { fields: value.fields as Record<string, JsonValue> } : {}),\n }\n } catch {\n return null\n }\n}\n\nfunction isLogLevel(value: unknown): value is LogLevel {\n return value === 'debug' || value === 'info' || value === 'warn' || value === 'error'\n}\n\nasync function readTail(filePath: string, maxBytes: number): Promise<string | null> {\n const info = await stat(filePath).catch(() => null)\n if (!info || info.size <= 0) {\n return null\n }\n if (info.size <= maxBytes) {\n return await readFile(filePath, 'utf8').catch(() => null)\n }\n const handle = await open(filePath, 'r').catch(() => null)\n if (!handle) {\n return null\n }\n try {\n const length = Math.min(info.size, maxBytes)\n const buffer = Buffer.alloc(length)\n await handle.read(buffer, 0, length, info.size - length)\n return buffer.toString('utf8')\n } finally {\n await handle.close()\n }\n}\n\nasync function moveIfExists(from: string, to: string): Promise<void> {\n await rm(to, { force: true }).catch(() => undefined)\n await rename(from, to).catch((error: unknown) => {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error\n }\n })\n}\n\nfunction rotatedLogFile(filePath: string, index: number): string {\n return `${filePath}.${index}`\n}\n"],"mappings":"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","names":["path","mkdir","readFile","rm","writeFile","path","randomUUID","mkdir","readFile","os","path","isNodeError","runId","path","mkdir","isNodeError","randomUUID","readFile","run","writeFile","path","toRecord","rm","toRecord","readString","unique","path","isNodeError","mkdir","readdir","rename","rm","stat","os","path","path","os","readdir","isNodeError","stat","mkdir","rename","rm","randomUUID","mkdir","mkdir","randomUUID","path","rm","randomBytes","randomUUID","createHash","randomUUID","randomBytes","createHash","readErrorMessage","os","rm","path","readJsonResponse","readErrorMessage","decodeJson","appendFile","mkdir","open","readFile","rename","rm","stat","path","mkdir","appendFile","stat","rm","path","readFile","open","rename","readString","loadRequiredIdentity"]}