@moxt-ai/mobius 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/acp/activity.d.ts +29 -0
- package/dist/acp/activity.d.ts.map +1 -0
- package/dist/acp/activity.js +253 -0
- package/dist/acp/activity.js.map +1 -0
- package/dist/acp/create-client.d.ts +3 -0
- package/dist/acp/create-client.d.ts.map +1 -0
- package/dist/acp/create-client.js +3 -0
- package/dist/acp/create-client.js.map +1 -0
- package/dist/acp/run-prompt.d.ts +15 -0
- package/dist/acp/run-prompt.d.ts.map +1 -0
- package/dist/acp/run-prompt.js +21 -0
- package/dist/acp/run-prompt.js.map +1 -0
- package/dist/acp/session-manager.d.ts +25 -0
- package/dist/acp/session-manager.d.ts.map +1 -0
- package/dist/acp/session-manager.js +301 -0
- package/dist/acp/session-manager.js.map +1 -0
- package/dist/audit/audit-store.d.ts +12 -0
- package/dist/audit/audit-store.d.ts.map +1 -0
- package/dist/audit/audit-store.js +35 -0
- package/dist/audit/audit-store.js.map +1 -0
- package/dist/authorization/authorize-binding.d.ts +6 -0
- package/dist/authorization/authorize-binding.d.ts.map +1 -0
- package/dist/authorization/authorize-binding.js +30 -0
- package/dist/authorization/authorize-binding.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1792 -0
- package/dist/cli.js.map +7 -0
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +85 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1784 -0
- package/dist/index.js.map +7 -0
- package/dist/pairing/pair-local-machine.d.ts +13 -0
- package/dist/pairing/pair-local-machine.d.ts.map +1 -0
- package/dist/pairing/pair-local-machine.js +302 -0
- package/dist/pairing/pair-local-machine.js.map +1 -0
- package/dist/relay-connection/connect.d.ts +2 -0
- package/dist/relay-connection/connect.d.ts.map +1 -0
- package/dist/relay-connection/connect.js +61 -0
- package/dist/relay-connection/connect.js.map +1 -0
- package/dist/run-daemon.d.ts +4 -0
- package/dist/run-daemon.d.ts.map +1 -0
- package/dist/run-daemon.js +274 -0
- package/dist/run-daemon.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/acp/create-client.ts", "../src/config.ts", "../src/acp/session-manager.ts", "../../protocol/src/messages.ts", "../../protocol/src/version.ts", "../../protocol/src/codecs/messages.ts", "../src/acp/activity.ts", "../src/acp/run-prompt.ts", "../src/audit/audit-store.ts", "../src/authorization/authorize-binding.ts", "../src/pairing/pair-local-machine.ts", "../src/run-daemon.ts", "../src/relay-connection/connect.ts"],
|
|
4
|
+
"sourcesContent": ["import { type ClientApp, client } from \"@agentclientprotocol/sdk\";\n\nexport const createAcpClient = (): ClientApp => client({ name: \"mobius\" });\n", "import { fileURLToPath } from \"node:url\";\n\nconst repositoryRoot = fileURLToPath(new URL(\"../../../\", import.meta.url));\n\nfunction adapterEntrypoint(packageName: string): string {\n return fileURLToPath(new URL(\"./index.js\", import.meta.resolve(packageName)));\n}\n\nexport class LocalAgentDefinition {\n readonly arguments: readonly string[];\n readonly command: string;\n readonly id: string;\n readonly label: string;\n\n constructor(\n id: string,\n label: string,\n command: string,\n arguments_: readonly string[],\n ) {\n this.id = id;\n this.label = label;\n this.command = command;\n this.arguments = arguments_;\n }\n}\n\nexport interface DaemonConfig {\n readonly agents: readonly LocalAgentDefinition[];\n readonly approvedRoot: string;\n readonly auditDatabasePath: string;\n readonly bindingId: string;\n readonly channelId: string;\n readonly relayUrl: URL;\n}\n\nexport interface DaemonConnectionConfig {\n readonly approvedRoot: string;\n readonly auditDatabasePath: string;\n readonly channelId: string;\n readonly relayUrl: URL;\n}\n\nexport function loadLocalAgents(): readonly LocalAgentDefinition[] {\n // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.\n const overridePath = process.env[\"MOBIUS_ACP_AGENT_PATH\"]?.trim();\n if (overridePath !== undefined && overridePath.length > 0) {\n return [\n new LocalAgentDefinition(\"codex\", \"Codex\", process.execPath, [\n overridePath,\n \"--agent-name\",\n \"Codex\",\n ]),\n new LocalAgentDefinition(\"claude\", \"Claude Code\", process.execPath, [\n overridePath,\n \"--agent-name\",\n \"Claude Code\",\n ]),\n ];\n }\n\n return [\n new LocalAgentDefinition(\"codex\", \"Codex\", process.execPath, [\n adapterEntrypoint(\"@agentclientprotocol/codex-acp\"),\n ]),\n new LocalAgentDefinition(\"claude\", \"Claude Code\", process.execPath, [\n adapterEntrypoint(\"@agentclientprotocol/claude-agent-acp\"),\n ]),\n ];\n}\n\nexport function createDaemonConfig(\n connection: DaemonConnectionConfig,\n): DaemonConfig {\n return {\n agents: loadLocalAgents(),\n approvedRoot: connection.approvedRoot,\n auditDatabasePath: connection.auditDatabasePath,\n bindingId: \"workspace\",\n channelId: connection.channelId,\n relayUrl: connection.relayUrl,\n };\n}\n\nexport function findLocalAgent(\n agents: readonly LocalAgentDefinition[],\n agentId: string,\n): LocalAgentDefinition {\n for (const agent of agents) {\n if (agent.id === agentId) {\n return agent;\n }\n }\n throw new Error(\"The requested local agent is not approved\");\n}\n\nexport function loadDaemonConfig(): DaemonConfig {\n const relayUrl = new URL(\n // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.\n process.env[\"MOBIUS_RELAY_URL\"] ??\n \"ws://127.0.0.1:8787/v1/channels/local/daemon\",\n );\n relayUrl.searchParams.set(\n \"token\",\n // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.\n process.env[\"MOBIUS_RELAY_TOKEN\"] ?? \"local-development-token\",\n );\n\n if (relayUrl.protocol !== \"ws:\" && relayUrl.protocol !== \"wss:\") {\n throw new Error(\"MOBIUS_RELAY_URL must use ws or wss\");\n }\n\n return createDaemonConfig({\n // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.\n approvedRoot: process.env[\"MOBIUS_APPROVED_ROOT\"] ?? repositoryRoot,\n auditDatabasePath:\n // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.\n process.env[\"MOBIUS_AUDIT_DATABASE\"] ??\n fileURLToPath(new URL(\"../../../.mobius/daemon.sqlite\", import.meta.url)),\n // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.\n channelId: process.env[\"MOBIUS_CHANNEL_ID\"] ?? \"local\",\n relayUrl,\n });\n}\n", "import { spawn } from \"node:child_process\";\nimport { once } from \"node:events\";\n\nimport {\n type ActiveSession,\n type ClientConnection,\n methods,\n ndJsonStream,\n PROTOCOL_VERSION,\n} from \"@agentclientprotocol/sdk\";\n\nimport type { LocalAgentDefinition } from \"../config.ts\";\nimport {\n type AcpActivity,\n AcpActivityTracker,\n isProgressMessage,\n} from \"./activity.ts\";\nimport { createAcpClient } from \"./create-client.ts\";\n\nconst PROCESS_STOP_TIMEOUT_MILLISECONDS = 1_000;\n\nexport interface AcpTurnOptions {\n readonly agent: LocalAgentDefinition;\n readonly cwd: string;\n readonly onActivity: (activity: AcpActivity) => Promise<void>;\n readonly onText: (text: string) => Promise<void>;\n readonly prompt: string;\n readonly sessionId: string;\n readonly signal: AbortSignal;\n}\n\nexport interface AcpPromptResult {\n readonly stopReason: string;\n}\n\nexport class AcpExecutionError extends Error {\n readonly code = \"acp_execution_failed\";\n\n constructor(message: string, options: ErrorOptions = {}) {\n super(message, options);\n this.name = \"AcpExecutionError\";\n }\n}\n\nfunction readableWebStream(\n input: NodeJS.ReadableStream,\n): ReadableStream<Uint8Array> {\n let streamOpen = true;\n return new ReadableStream<Uint8Array>({\n start(controller) {\n input.on(\"data\", (chunk: unknown) => {\n if (!streamOpen) {\n return;\n }\n if (chunk instanceof Uint8Array) {\n controller.enqueue(new Uint8Array(chunk));\n return;\n }\n streamOpen = false;\n controller.error(new Error(\"ACP process produced a non-binary chunk\"));\n });\n input.once(\"end\", () => {\n if (!streamOpen) {\n return;\n }\n streamOpen = false;\n controller.close();\n });\n input.once(\"error\", (error) => {\n if (!streamOpen) {\n return;\n }\n streamOpen = false;\n controller.error(error);\n });\n },\n cancel() {\n streamOpen = false;\n },\n });\n}\n\nfunction writableWebStream(\n output: NodeJS.WritableStream,\n): WritableStream<Uint8Array> {\n return new WritableStream<Uint8Array>({\n write(chunk) {\n return new Promise<void>((resolve, reject) => {\n output.write(chunk, (error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n });\n },\n });\n}\n\nasync function stopAgentProcess(\n child: ReturnType<typeof spawn>,\n): Promise<void> {\n child.stdin?.end();\n if (child.exitCode !== null) {\n return;\n }\n\n child.kill(\"SIGTERM\");\n try {\n await once(child, \"exit\", {\n signal: AbortSignal.timeout(PROCESS_STOP_TIMEOUT_MILLISECONDS),\n });\n } catch {\n if (child.exitCode === null) {\n child.kill(\"SIGKILL\");\n await once(child, \"exit\");\n }\n }\n}\n\nfunction rejectWhenAborted(signal: AbortSignal): Promise<never> {\n return new Promise((_resolve, reject) => {\n const rejectAbort = (): void => {\n reject(signal.reason ?? new Error(\"ACP request was cancelled\"));\n };\n signal.addEventListener(\"abort\", rejectAbort, { once: true });\n if (signal.aborted) {\n rejectAbort();\n }\n });\n}\n\nclass AcpProcessSession {\n readonly #agentId: string;\n readonly #child: ReturnType<typeof spawn>;\n readonly #connection: ClientConnection;\n readonly #processExit: Promise<void>;\n readonly #session: ActiveSession;\n #turnRunning = false;\n\n private constructor(\n agentId: string,\n child: ReturnType<typeof spawn>,\n connection: ClientConnection,\n session: ActiveSession,\n processExit: Promise<void>,\n ) {\n this.#agentId = agentId;\n this.#child = child;\n this.#connection = connection;\n this.#session = session;\n this.#processExit = processExit;\n }\n\n static async start(\n agent: LocalAgentDefinition,\n cwd: string,\n signal: AbortSignal,\n ): Promise<AcpProcessSession> {\n signal.throwIfAborted();\n const child = spawn(agent.command, [...agent.arguments], {\n cwd,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n child.stderr.setEncoding(\"utf8\");\n child.stderr.on(\"data\", (chunk: string) => {\n process.stderr.write(`[${agent.id}-acp] ${chunk}`);\n });\n\n const processExit = new Promise<void>((resolve) => {\n child.once(\"error\", resolve);\n child.once(\"exit\", resolve);\n });\n const stream = ndJsonStream(\n writableWebStream(child.stdin),\n readableWebStream(child.stdout),\n );\n const connection = createAcpClient().connect(stream);\n\n try {\n await Promise.race([\n connection.agent.request(\n methods.agent.initialize,\n {\n clientCapabilities: {},\n protocolVersion: PROTOCOL_VERSION,\n },\n { cancellationSignal: signal },\n ),\n processExit.then(() => {\n throw new AcpExecutionError(\"ACP agent exited during initialization\");\n }),\n rejectWhenAborted(signal),\n ]);\n const session = await Promise.race([\n connection.agent\n .buildSession(cwd)\n .start({ cancellationSignal: signal }),\n processExit.then(() => {\n throw new AcpExecutionError(\n \"ACP agent exited while starting a session\",\n );\n }),\n rejectWhenAborted(signal),\n ]);\n return new AcpProcessSession(\n agent.id,\n child,\n connection,\n session,\n processExit,\n );\n } catch (error) {\n connection.close(error);\n await stopAgentProcess(child);\n throw new AcpExecutionError(\"ACP agent initialization failed\", {\n cause: error,\n });\n }\n }\n\n readonly belongsTo = (agentId: string): boolean => this.#agentId === agentId;\n\n readonly cancel = async (): Promise<void> => {\n if (!this.#turnRunning) {\n return;\n }\n await this.#connection.agent.notify(methods.agent.session.cancel, {\n sessionId: this.#session.sessionId,\n });\n };\n\n readonly prompt = async (\n prompt: string,\n onActivity: (activity: AcpActivity) => Promise<void>,\n onText: (text: string) => Promise<void>,\n signal: AbortSignal,\n ): Promise<AcpPromptResult> => {\n if (this.#turnRunning) {\n throw new AcpExecutionError(\n \"Another prompt is already running in this conversation\",\n );\n }\n this.#turnRunning = true;\n const activities = new AcpActivityTracker(onActivity);\n\n const runTurn = async (): Promise<AcpPromptResult> => {\n const completion = this.#session.prompt(prompt, {\n cancellationSignal: signal,\n });\n for (;;) {\n const message = await this.#session.nextUpdate();\n if (message.kind === \"stop\") {\n await completion;\n await activities.finish();\n return { stopReason: message.stopReason };\n }\n const update = message.update;\n if (update.sessionUpdate === \"agent_message_chunk\") {\n if (update.content.type === \"text\") {\n if (isProgressMessage(update)) {\n await activities.recordNarrative(\n \"progress\",\n update.messageId ?? \"current\",\n update.content.text,\n );\n } else {\n await activities.finishNarrative();\n await onText(update.content.text);\n }\n }\n continue;\n }\n if (update.sessionUpdate === \"agent_thought_chunk\") {\n if (update.content.type === \"text\") {\n await activities.recordNarrative(\n \"reasoning\",\n update.messageId ?? \"current\",\n update.content.text,\n );\n }\n continue;\n }\n if (update.sessionUpdate === \"tool_call\") {\n await activities.recordToolCall(update);\n continue;\n }\n if (update.sessionUpdate === \"tool_call_update\") {\n await activities.recordToolCallUpdate(update);\n continue;\n }\n if (update.sessionUpdate === \"plan\") {\n await activities.recordPlan(update);\n continue;\n }\n if (update.sessionUpdate === \"plan_update\") {\n await activities.recordPlanUpdate(update);\n continue;\n }\n if (update.sessionUpdate === \"plan_removed\") {\n await activities.removePlan(update);\n }\n }\n };\n\n try {\n return await Promise.race([\n runTurn(),\n this.#processExit.then(() => {\n throw new AcpExecutionError(\"ACP agent exited during a prompt\");\n }),\n rejectWhenAborted(signal),\n ]);\n } catch (error) {\n await activities.finish();\n throw new AcpExecutionError(\"ACP agent execution failed\", {\n cause: error,\n });\n } finally {\n this.#turnRunning = false;\n }\n };\n\n readonly close = async (): Promise<void> => {\n this.#session.dispose();\n this.#connection.close();\n await stopAgentProcess(this.#child);\n };\n}\n\nexport class AcpSessionManager {\n readonly #activeSessionIds = new Set<string>();\n readonly #cancellationRequests = new Set<string>();\n readonly #sessions = new Map<string, AcpProcessSession>();\n\n readonly cancelPrompt = async (sessionId: string): Promise<void> => {\n this.#cancellationRequests.add(sessionId);\n const runtime = this.#sessions.get(sessionId);\n if (runtime !== undefined) {\n await runtime.cancel();\n }\n };\n\n readonly runPrompt = async (\n options: AcpTurnOptions,\n ): Promise<AcpPromptResult> => {\n if (this.#activeSessionIds.has(options.sessionId)) {\n throw new AcpExecutionError(\n \"Another prompt is already running in this conversation\",\n );\n }\n this.#activeSessionIds.add(options.sessionId);\n\n let runtime = this.#sessions.get(options.sessionId);\n if (runtime !== undefined && !runtime.belongsTo(options.agent.id)) {\n this.#activeSessionIds.delete(options.sessionId);\n throw new AcpExecutionError(\n \"The agent cannot change after a conversation has started\",\n );\n }\n try {\n if (this.#cancellationRequests.has(options.sessionId)) {\n return { stopReason: \"cancelled\" };\n }\n if (runtime === undefined) {\n runtime = await AcpProcessSession.start(\n options.agent,\n options.cwd,\n options.signal,\n );\n this.#sessions.set(options.sessionId, runtime);\n }\n if (this.#cancellationRequests.has(options.sessionId)) {\n return { stopReason: \"cancelled\" };\n }\n return await runtime.prompt(\n options.prompt,\n options.onActivity,\n options.onText,\n options.signal,\n );\n } catch (error) {\n if (runtime !== undefined) {\n this.#sessions.delete(options.sessionId);\n await runtime.close();\n }\n if (error instanceof AcpExecutionError) {\n throw error;\n }\n throw new AcpExecutionError(\"ACP agent execution failed\", {\n cause: error,\n });\n } finally {\n this.#activeSessionIds.delete(options.sessionId);\n this.#cancellationRequests.delete(options.sessionId);\n }\n };\n\n readonly close = async (): Promise<void> => {\n const sessions = [...this.#sessions.values()];\n this.#sessions.clear();\n await Promise.all(sessions.map(async (session) => await session.close()));\n };\n}\n", "export const SESSION_PROMPT_KIND = \"session.prompt\";\nexport const SESSION_CANCEL_KIND = \"session.cancel\";\nexport const RUNTIME_STATUS_KIND = \"runtime.status\";\nexport const SESSION_STARTED_KIND = \"session.started\";\nexport const AGENT_MESSAGE_DELTA_KIND = \"agent.message.delta\";\nexport const AGENT_ACTIVITY_KIND = \"agent.activity\";\nexport const AGENT_ACTIVITY_DETAIL_LIMIT = 24_000;\nexport const AGENT_ACTIVITY_LOCATION_LIMIT = 12;\nexport const AGENT_ACTIVITY_LOCATION_LENGTH_LIMIT = 1_024;\nexport const SESSION_COMPLETED_KIND = \"session.completed\";\nexport const SESSION_FAILED_KIND = \"session.failed\";\n\nexport interface SessionPromptCommand {\n readonly agentId: string;\n readonly bindingId: string;\n readonly commandId: string;\n readonly kind: typeof SESSION_PROMPT_KIND;\n readonly prompt: string;\n readonly protocolVersion: number;\n readonly sessionId: string;\n}\n\nexport interface SessionCancelCommand {\n readonly commandId: string;\n readonly kind: typeof SESSION_CANCEL_KIND;\n readonly protocolVersion: number;\n readonly sessionId: string;\n}\n\nexport interface RuntimeStatusEvent {\n readonly kind: typeof RUNTIME_STATUS_KIND;\n readonly online: boolean;\n readonly protocolVersion: number;\n readonly runtimeId: string;\n}\n\nexport interface SessionStartedEvent {\n readonly commandId: string;\n readonly kind: typeof SESSION_STARTED_KIND;\n readonly processAttemptId: string;\n readonly protocolVersion: number;\n readonly sessionId: string;\n}\n\nexport interface AgentMessageDeltaEvent {\n readonly commandId: string;\n readonly kind: typeof AGENT_MESSAGE_DELTA_KIND;\n readonly protocolVersion: number;\n readonly sessionId: string;\n readonly text: string;\n}\n\nexport interface AgentActivityEvent {\n readonly activityId: string;\n readonly activityType: string;\n readonly commandId: string;\n readonly input: string;\n readonly kind: typeof AGENT_ACTIVITY_KIND;\n readonly locations: readonly string[];\n readonly name: string;\n readonly output: string;\n readonly protocolVersion: number;\n readonly sequence: number;\n readonly sessionId: string;\n readonly status: string;\n readonly title: string;\n readonly toolKind: string;\n}\n\nexport interface SessionCompletedEvent {\n readonly commandId: string;\n readonly kind: typeof SESSION_COMPLETED_KIND;\n readonly protocolVersion: number;\n readonly sessionId: string;\n readonly stopReason: string;\n}\n\nexport interface SessionFailedEvent {\n readonly code: string;\n readonly commandId: string;\n readonly kind: typeof SESSION_FAILED_KIND;\n readonly message: string;\n readonly protocolVersion: number;\n readonly sessionId: string;\n}\n", "export const MOBIUS_PROTOCOL_VERSION = 1;\n", "import {\n AGENT_ACTIVITY_DETAIL_LIMIT,\n AGENT_ACTIVITY_KIND,\n AGENT_ACTIVITY_LOCATION_LENGTH_LIMIT,\n AGENT_ACTIVITY_LOCATION_LIMIT,\n AGENT_MESSAGE_DELTA_KIND,\n type AgentActivityEvent,\n type AgentMessageDeltaEvent,\n RUNTIME_STATUS_KIND,\n type RuntimeStatusEvent,\n SESSION_CANCEL_KIND,\n SESSION_COMPLETED_KIND,\n SESSION_FAILED_KIND,\n SESSION_PROMPT_KIND,\n SESSION_STARTED_KIND,\n type SessionCancelCommand,\n type SessionCompletedEvent,\n type SessionFailedEvent,\n type SessionPromptCommand,\n type SessionStartedEvent,\n} from \"../messages.ts\";\nimport { MOBIUS_PROTOCOL_VERSION } from \"../version.ts\";\n\nconst IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;\nconst MAX_PROMPT_LENGTH = 10_000;\nconst MAX_EVENT_TEXT_LENGTH = 100_000;\nconst ACTIVITY_TYPES = new Set([\"plan\", \"progress\", \"reasoning\", \"tool\"]);\nconst ACTIVITY_STATUSES = new Set([\n \"pending\",\n \"running\",\n \"completed\",\n \"failed\",\n]);\nconst TOOL_KINDS = new Set([\n \"\",\n \"delete\",\n \"edit\",\n \"execute\",\n \"fetch\",\n \"move\",\n \"other\",\n \"read\",\n \"search\",\n \"switch_mode\",\n \"think\",\n]);\n\nexport class ProtocolMessageError extends Error {\n readonly code = \"invalid_protocol_message\";\n\n constructor(message: string, options: ErrorOptions = {}) {\n super(message, options);\n this.name = \"ProtocolMessageError\";\n }\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseJson(encoded: string): Readonly<Record<string, unknown>> {\n let value: unknown;\n try {\n value = JSON.parse(encoded);\n } catch (error) {\n throw new ProtocolMessageError(\"Message is not valid JSON\", {\n cause: error,\n });\n }\n\n if (!isRecord(value)) {\n throw new ProtocolMessageError(\"Message must be a JSON object\");\n }\n\n return value;\n}\n\nfunction assertExactKeys(\n value: Readonly<Record<string, unknown>>,\n allowedKeys: readonly string[],\n): void {\n for (const key of Object.keys(value)) {\n if (!allowedKeys.includes(key)) {\n throw new ProtocolMessageError(`Unexpected message field: ${key}`);\n }\n }\n}\n\nfunction readString(\n value: Readonly<Record<string, unknown>>,\n key: string,\n maximumLength: number,\n): string {\n const field = value[key];\n if (\n typeof field !== \"string\" ||\n field.length === 0 ||\n field.length > maximumLength\n ) {\n throw new ProtocolMessageError(`Invalid string field: ${key}`);\n }\n return field;\n}\n\nfunction readText(\n value: Readonly<Record<string, unknown>>,\n key: string,\n maximumLength: number,\n): string {\n const field = value[key];\n if (typeof field !== \"string\" || field.length > maximumLength) {\n throw new ProtocolMessageError(`Invalid text field: ${key}`);\n }\n return field;\n}\n\nfunction readAllowedString(\n value: Readonly<Record<string, unknown>>,\n key: string,\n allowedValues: ReadonlySet<string>,\n): string {\n const field = readText(value, key, 64);\n if (!allowedValues.has(field)) {\n throw new ProtocolMessageError(`Invalid value field: ${key}`);\n }\n return field;\n}\n\nfunction readSequence(\n value: Readonly<Record<string, unknown>>,\n key: string,\n): number {\n const field = value[key];\n if (typeof field !== \"number\" || !Number.isSafeInteger(field) || field < 0) {\n throw new ProtocolMessageError(`Invalid integer field: ${key}`);\n }\n return field;\n}\n\nfunction readLocations(\n value: Readonly<Record<string, unknown>>,\n): readonly string[] {\n const field = value[\"locations\"];\n if (!Array.isArray(field) || field.length > AGENT_ACTIVITY_LOCATION_LIMIT) {\n throw new ProtocolMessageError(\"Invalid locations field\");\n }\n const locations: string[] = [];\n const unique = new Set<string>();\n for (const location of field) {\n if (\n typeof location !== \"string\" ||\n location.length === 0 ||\n location.length > AGENT_ACTIVITY_LOCATION_LENGTH_LIMIT\n ) {\n throw new ProtocolMessageError(\"Invalid activity location\");\n }\n if (unique.has(location)) {\n throw new ProtocolMessageError(\"Duplicate activity location\");\n }\n unique.add(location);\n locations.push(location);\n }\n return locations;\n}\n\nfunction readIdentifier(\n value: Readonly<Record<string, unknown>>,\n key: string,\n): string {\n const field = readString(value, key, 128);\n if (!IDENTIFIER_PATTERN.test(field)) {\n throw new ProtocolMessageError(`Invalid identifier field: ${key}`);\n }\n return field;\n}\n\nfunction readBoolean(\n value: Readonly<Record<string, unknown>>,\n key: string,\n): boolean {\n const field = value[key];\n if (typeof field !== \"boolean\") {\n throw new ProtocolMessageError(`Invalid boolean field: ${key}`);\n }\n return field;\n}\n\nfunction assertProtocolVersion(value: Readonly<Record<string, unknown>>): void {\n // biome-ignore lint/complexity/useLiteralKeys: TypeScript requires index-signature access here.\n if (value[\"protocolVersion\"] !== MOBIUS_PROTOCOL_VERSION) {\n throw new ProtocolMessageError(\"Unsupported protocol version\");\n }\n}\n\nfunction assertKind(\n value: Readonly<Record<string, unknown>>,\n expectedKind: string,\n): void {\n // biome-ignore lint/complexity/useLiteralKeys: TypeScript requires index-signature access here.\n if (value[\"kind\"] !== expectedKind) {\n throw new ProtocolMessageError(`Expected message kind: ${expectedKind}`);\n }\n}\n\nexport function decodeMessageKind(encoded: string): string {\n return readString(parseJson(encoded), \"kind\", 64);\n}\n\nexport function decodeSessionPromptCommand(\n encoded: string,\n): SessionPromptCommand {\n const value = parseJson(encoded);\n assertExactKeys(value, [\n \"agentId\",\n \"bindingId\",\n \"commandId\",\n \"kind\",\n \"prompt\",\n \"protocolVersion\",\n \"sessionId\",\n ]);\n assertProtocolVersion(value);\n assertKind(value, SESSION_PROMPT_KIND);\n\n const prompt = readString(value, \"prompt\", MAX_PROMPT_LENGTH);\n if (prompt.trim().length === 0) {\n throw new ProtocolMessageError(\"Prompt must contain visible text\");\n }\n\n return {\n agentId: readIdentifier(value, \"agentId\"),\n bindingId: readIdentifier(value, \"bindingId\"),\n commandId: readIdentifier(value, \"commandId\"),\n kind: SESSION_PROMPT_KIND,\n prompt,\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: readIdentifier(value, \"sessionId\"),\n };\n}\n\nexport function decodeSessionCancelCommand(\n encoded: string,\n): SessionCancelCommand {\n const value = parseJson(encoded);\n assertExactKeys(value, [\"commandId\", \"kind\", \"protocolVersion\", \"sessionId\"]);\n assertProtocolVersion(value);\n assertKind(value, SESSION_CANCEL_KIND);\n\n return {\n commandId: readIdentifier(value, \"commandId\"),\n kind: SESSION_CANCEL_KIND,\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: readIdentifier(value, \"sessionId\"),\n };\n}\n\nexport function decodeRuntimeStatusEvent(encoded: string): RuntimeStatusEvent {\n const value = parseJson(encoded);\n assertExactKeys(value, [\"kind\", \"online\", \"protocolVersion\", \"runtimeId\"]);\n assertProtocolVersion(value);\n assertKind(value, RUNTIME_STATUS_KIND);\n\n return {\n kind: RUNTIME_STATUS_KIND,\n online: readBoolean(value, \"online\"),\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n runtimeId: readIdentifier(value, \"runtimeId\"),\n };\n}\n\nexport function decodeSessionStartedEvent(\n encoded: string,\n): SessionStartedEvent {\n const value = parseJson(encoded);\n assertExactKeys(value, [\n \"commandId\",\n \"kind\",\n \"processAttemptId\",\n \"protocolVersion\",\n \"sessionId\",\n ]);\n assertProtocolVersion(value);\n assertKind(value, SESSION_STARTED_KIND);\n\n return {\n commandId: readIdentifier(value, \"commandId\"),\n kind: SESSION_STARTED_KIND,\n processAttemptId: readIdentifier(value, \"processAttemptId\"),\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: readIdentifier(value, \"sessionId\"),\n };\n}\n\nexport function decodeAgentMessageDeltaEvent(\n encoded: string,\n): AgentMessageDeltaEvent {\n const value = parseJson(encoded);\n assertExactKeys(value, [\n \"commandId\",\n \"kind\",\n \"protocolVersion\",\n \"sessionId\",\n \"text\",\n ]);\n assertProtocolVersion(value);\n assertKind(value, AGENT_MESSAGE_DELTA_KIND);\n\n return {\n commandId: readIdentifier(value, \"commandId\"),\n kind: AGENT_MESSAGE_DELTA_KIND,\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: readIdentifier(value, \"sessionId\"),\n text: readString(value, \"text\", MAX_EVENT_TEXT_LENGTH),\n };\n}\n\nexport function decodeAgentActivityEvent(encoded: string): AgentActivityEvent {\n const value = parseJson(encoded);\n assertExactKeys(value, [\n \"activityId\",\n \"activityType\",\n \"commandId\",\n \"input\",\n \"kind\",\n \"locations\",\n \"name\",\n \"output\",\n \"protocolVersion\",\n \"sequence\",\n \"sessionId\",\n \"status\",\n \"title\",\n \"toolKind\",\n ]);\n assertProtocolVersion(value);\n assertKind(value, AGENT_ACTIVITY_KIND);\n\n return {\n activityId: readIdentifier(value, \"activityId\"),\n activityType: readAllowedString(value, \"activityType\", ACTIVITY_TYPES),\n commandId: readIdentifier(value, \"commandId\"),\n input: readText(value, \"input\", AGENT_ACTIVITY_DETAIL_LIMIT),\n kind: AGENT_ACTIVITY_KIND,\n locations: readLocations(value),\n name: readText(value, \"name\", 128),\n output: readText(value, \"output\", AGENT_ACTIVITY_DETAIL_LIMIT),\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sequence: readSequence(value, \"sequence\"),\n sessionId: readIdentifier(value, \"sessionId\"),\n status: readAllowedString(value, \"status\", ACTIVITY_STATUSES),\n title: readString(value, \"title\", 500),\n toolKind: readAllowedString(value, \"toolKind\", TOOL_KINDS),\n };\n}\n\nexport function decodeSessionCompletedEvent(\n encoded: string,\n): SessionCompletedEvent {\n const value = parseJson(encoded);\n assertExactKeys(value, [\n \"commandId\",\n \"kind\",\n \"protocolVersion\",\n \"sessionId\",\n \"stopReason\",\n ]);\n assertProtocolVersion(value);\n assertKind(value, SESSION_COMPLETED_KIND);\n\n return {\n commandId: readIdentifier(value, \"commandId\"),\n kind: SESSION_COMPLETED_KIND,\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: readIdentifier(value, \"sessionId\"),\n stopReason: readString(value, \"stopReason\", 64),\n };\n}\n\nexport function decodeSessionFailedEvent(encoded: string): SessionFailedEvent {\n const value = parseJson(encoded);\n assertExactKeys(value, [\n \"code\",\n \"commandId\",\n \"kind\",\n \"message\",\n \"protocolVersion\",\n \"sessionId\",\n ]);\n assertProtocolVersion(value);\n assertKind(value, SESSION_FAILED_KIND);\n\n return {\n code: readIdentifier(value, \"code\"),\n commandId: readIdentifier(value, \"commandId\"),\n kind: SESSION_FAILED_KIND,\n message: readString(value, \"message\", 500),\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: readIdentifier(value, \"sessionId\"),\n };\n}\n\nexport function encodeSessionPromptCommand(\n message: SessionPromptCommand,\n): string {\n return JSON.stringify(message);\n}\n\nexport function encodeSessionCancelCommand(\n message: SessionCancelCommand,\n): string {\n return JSON.stringify(message);\n}\n\nexport function encodeRuntimeStatusEvent(message: RuntimeStatusEvent): string {\n return JSON.stringify(message);\n}\n\nexport function encodeSessionStartedEvent(\n message: SessionStartedEvent,\n): string {\n return JSON.stringify(message);\n}\n\nexport function encodeAgentMessageDeltaEvent(\n message: AgentMessageDeltaEvent,\n): string {\n return JSON.stringify(message);\n}\n\nexport function encodeAgentActivityEvent(message: AgentActivityEvent): string {\n return JSON.stringify(message);\n}\n\nexport function encodeSessionCompletedEvent(\n message: SessionCompletedEvent,\n): string {\n return JSON.stringify(message);\n}\n\nexport function encodeSessionFailedEvent(message: SessionFailedEvent): string {\n return JSON.stringify(message);\n}\n", "import type {\n ContentChunk,\n Plan,\n PlanEntry,\n PlanRemoved,\n PlanUpdate,\n ToolCall,\n ToolCallLocation,\n ToolCallUpdate,\n} from \"@agentclientprotocol/sdk\";\nimport {\n AGENT_ACTIVITY_DETAIL_LIMIT,\n AGENT_ACTIVITY_LOCATION_LENGTH_LIMIT,\n AGENT_ACTIVITY_LOCATION_LIMIT,\n} from \"@moxt-ai/mobius-protocol\";\n\nconst TRUNCATION_MARKER = \"\\n\u2026 output truncated by Mobius\";\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport class AcpActivity {\n readonly activityId: string;\n readonly activityType: string;\n readonly input: string;\n readonly locations: readonly string[];\n readonly name: string;\n readonly output: string;\n readonly sequence: number;\n readonly status: string;\n readonly title: string;\n readonly toolKind: string;\n\n constructor(\n activityId: string,\n activityType: string,\n input: string,\n locations: readonly string[],\n name: string,\n output: string,\n sequence: number,\n status: string,\n title: string,\n toolKind: string,\n ) {\n this.activityId = activityId;\n this.activityType = activityType;\n this.input = input;\n this.locations = locations;\n this.name = name;\n this.output = output;\n this.sequence = sequence;\n this.status = status;\n this.title = title;\n this.toolKind = toolKind;\n }\n\n readonly complete = (): AcpActivity =>\n (this.activityType === \"progress\" || this.activityType === \"reasoning\") &&\n (this.status === \"pending\" || this.status === \"running\")\n ? new AcpActivity(\n this.activityId,\n this.activityType,\n this.input,\n this.locations,\n this.name,\n this.output,\n this.sequence,\n \"completed\",\n this.title,\n this.toolKind,\n )\n : this;\n}\n\nclass ActivityIdentity {\n readonly id: string;\n readonly sequence: number;\n\n constructor(id: string, sequence: number) {\n this.id = id;\n this.sequence = sequence;\n }\n}\n\nfunction truncate(value: string, maximumLength: number): string {\n if (value.length <= maximumLength) {\n return value;\n }\n return `${value.slice(0, maximumLength - TRUNCATION_MARKER.length)}${TRUNCATION_MARKER}`;\n}\n\nfunction formatUnknown(value: unknown): string {\n if (typeof value === \"string\") {\n return truncate(value, AGENT_ACTIVITY_DETAIL_LIMIT);\n }\n try {\n const encoded = JSON.stringify(value, null, 2);\n return truncate(encoded ?? \"\", AGENT_ACTIVITY_DETAIL_LIMIT);\n } catch {\n return truncate(String(value), AGENT_ACTIVITY_DETAIL_LIMIT);\n }\n}\n\nfunction readContentOutput(content: unknown): string {\n if (!Array.isArray(content) || content.length === 0) {\n return \"\";\n }\n return formatUnknown(content);\n}\n\nfunction normalizeLocations(\n locations: readonly ToolCallLocation[],\n): readonly string[] {\n const normalized: string[] = [];\n const unique = new Set<string>();\n for (const location of locations) {\n if (normalized.length === AGENT_ACTIVITY_LOCATION_LIMIT) {\n break;\n }\n const suffix =\n typeof location.line === \"number\" ? `:${location.line.toString()}` : \"\";\n const value = truncate(\n `${location.path}${suffix}`,\n AGENT_ACTIVITY_LOCATION_LENGTH_LIMIT,\n );\n if (value.length > 0 && !unique.has(value)) {\n unique.add(value);\n normalized.push(value);\n }\n }\n return normalized;\n}\n\nfunction normalizeToolStatus(status: string, fallback: string): string {\n if (status === \"pending\") {\n return \"pending\";\n }\n if (status === \"in_progress\") {\n return \"running\";\n }\n if (status === \"completed\" || status === \"failed\") {\n return status;\n }\n return fallback;\n}\n\nfunction normalizeTitle(title: string, fallback: string): string {\n const normalized = title.trim();\n return truncate(normalized.length === 0 ? fallback : normalized, 500);\n}\n\nfunction formatPlanEntries(entries: readonly PlanEntry[]): string {\n const lines: string[] = [];\n for (const entry of entries) {\n lines.push(`[${entry.status}] ${entry.content}`);\n }\n return truncate(lines.join(\"\\n\"), AGENT_ACTIVITY_DETAIL_LIMIT);\n}\n\nfunction planStatus(entries: readonly PlanEntry[]): string {\n if (entries.length === 0) {\n return \"completed\";\n }\n if (entries.every((entry) => entry.status === \"completed\")) {\n return \"completed\";\n }\n if (entries.some((entry) => entry.status === \"in_progress\")) {\n return \"running\";\n }\n return \"pending\";\n}\n\nfunction contentPhase(content: ContentChunk): string {\n const metadata = content._meta;\n if (metadata === undefined || metadata === null) {\n return \"\";\n }\n const codex = metadata[\"codex\"];\n if (!isRecord(codex)) {\n return \"\";\n }\n const phase = codex[\"phase\"];\n return typeof phase === \"string\" ? phase : \"\";\n}\n\nexport function isProgressMessage(content: ContentChunk): boolean {\n return contentPhase(content) === \"commentary\";\n}\n\nexport class AcpActivityTracker {\n readonly #activities = new Map<string, AcpActivity>();\n readonly #identities = new Map<string, ActivityIdentity>();\n readonly #onActivity: (activity: AcpActivity) => Promise<void>;\n #activeNarrativeKey = \"\";\n #nextSequence = 0;\n\n constructor(onActivity: (activity: AcpActivity) => Promise<void>) {\n this.#onActivity = onActivity;\n }\n\n readonly recordNarrative = async (\n activityType: string,\n messageId: string,\n text: string,\n ): Promise<void> => {\n const key = `${activityType}:${messageId}`;\n if (this.#activeNarrativeKey !== key) {\n await this.finishNarrative();\n }\n const previous = this.#activities.get(key);\n const identity = this.#identity(key);\n const activity = new AcpActivity(\n identity.id,\n activityType,\n \"\",\n [],\n \"\",\n truncate(`${previous?.output ?? \"\"}${text}`, AGENT_ACTIVITY_DETAIL_LIMIT),\n identity.sequence,\n \"running\",\n activityType === \"reasoning\" ? \"Reasoning\" : \"Progress update\",\n activityType === \"reasoning\" ? \"think\" : \"\",\n );\n await this.#record(key, activity);\n this.#activeNarrativeKey = key;\n };\n\n readonly recordPlan = async (plan: Plan): Promise<void> => {\n await this.finishNarrative();\n await this.#recordPlanEntries(\"plan:default\", plan.entries);\n };\n\n readonly recordPlanUpdate = async (update: PlanUpdate): Promise<void> => {\n await this.finishNarrative();\n const plan = update.plan;\n const key = `plan:${plan.planId}`;\n if (plan.type === \"items\") {\n await this.#recordPlanEntries(key, plan.entries);\n return;\n }\n const identity = this.#identity(key);\n const output =\n plan.type === \"markdown\" ? plan.content : `Plan file: ${plan.uri}`;\n await this.#record(\n key,\n new AcpActivity(\n identity.id,\n \"plan\",\n \"\",\n [],\n \"\",\n truncate(output, AGENT_ACTIVITY_DETAIL_LIMIT),\n identity.sequence,\n \"running\",\n \"Plan\",\n \"\",\n ),\n );\n };\n\n readonly removePlan = async (update: PlanRemoved): Promise<void> => {\n await this.finishNarrative();\n const key = `plan:${update.planId}`;\n const previous = this.#activities.get(key);\n if (previous !== undefined) {\n await this.#record(\n key,\n new AcpActivity(\n previous.activityId,\n previous.activityType,\n previous.input,\n previous.locations,\n previous.name,\n previous.output,\n previous.sequence,\n \"completed\",\n previous.title,\n previous.toolKind,\n ),\n );\n }\n };\n\n readonly recordToolCall = async (update: ToolCall): Promise<void> => {\n await this.finishNarrative();\n const key = `tool:${update.toolCallId}`;\n const identity = this.#identity(key);\n const output =\n update.rawOutput === undefined\n ? readContentOutput(update.content)\n : formatUnknown(update.rawOutput);\n await this.#record(\n key,\n new AcpActivity(\n identity.id,\n \"tool\",\n update.rawInput === undefined ? \"\" : formatUnknown(update.rawInput),\n normalizeLocations(update.locations ?? []),\n truncate(update.name ?? \"\", 128),\n output,\n identity.sequence,\n normalizeToolStatus(update.status ?? \"pending\", \"pending\"),\n normalizeTitle(update.title, \"Tool call\"),\n update.kind ?? \"other\",\n ),\n );\n };\n\n readonly recordToolCallUpdate = async (\n update: ToolCallUpdate,\n ): Promise<void> => {\n await this.finishNarrative();\n const key = `tool:${update.toolCallId}`;\n const previous = this.#activities.get(key);\n const identity = this.#identity(key);\n const output =\n update.rawOutput !== undefined\n ? formatUnknown(update.rawOutput)\n : update.content !== undefined && update.content !== null\n ? readContentOutput(update.content)\n : (previous?.output ?? \"\");\n await this.#record(\n key,\n new AcpActivity(\n identity.id,\n \"tool\",\n update.rawInput === undefined\n ? (previous?.input ?? \"\")\n : formatUnknown(update.rawInput),\n update.locations === undefined || update.locations === null\n ? (previous?.locations ?? [])\n : normalizeLocations(update.locations),\n update.name === undefined || update.name === null\n ? (previous?.name ?? \"\")\n : truncate(update.name, 128),\n output,\n identity.sequence,\n update.status === undefined || update.status === null\n ? (previous?.status ?? \"pending\")\n : normalizeToolStatus(update.status, previous?.status ?? \"pending\"),\n update.title === undefined || update.title === null\n ? (previous?.title ?? \"Tool call\")\n : normalizeTitle(update.title, \"Tool call\"),\n update.kind === undefined || update.kind === null\n ? (previous?.toolKind ?? \"other\")\n : update.kind,\n ),\n );\n };\n\n readonly finishNarrative = async (): Promise<void> => {\n const key = this.#activeNarrativeKey;\n if (key.length === 0) {\n return;\n }\n this.#activeNarrativeKey = \"\";\n const activity = this.#activities.get(key);\n if (activity === undefined) {\n return;\n }\n const completed = activity.complete();\n if (completed !== activity) {\n await this.#record(key, completed);\n }\n };\n\n readonly finish = async (): Promise<void> => {\n await this.finishNarrative();\n const entries = [...this.#activities.entries()].sort(\n (left, right) => left[1].sequence - right[1].sequence,\n );\n for (const [key, activity] of entries) {\n const completed = activity.complete();\n if (completed !== activity) {\n await this.#record(key, completed);\n }\n }\n };\n\n readonly #identity = (key: string): ActivityIdentity => {\n const existing = this.#identities.get(key);\n if (existing !== undefined) {\n return existing;\n }\n const identity = new ActivityIdentity(\n `activity-${crypto.randomUUID()}`,\n this.#nextSequence,\n );\n this.#nextSequence += 1;\n this.#identities.set(key, identity);\n return identity;\n };\n\n readonly #record = async (\n key: string,\n activity: AcpActivity,\n ): Promise<void> => {\n this.#activities.set(key, activity);\n await this.#onActivity(activity);\n };\n\n readonly #recordPlanEntries = async (\n key: string,\n entries: readonly PlanEntry[],\n ): Promise<void> => {\n const identity = this.#identity(key);\n await this.#record(\n key,\n new AcpActivity(\n identity.id,\n \"plan\",\n \"\",\n [],\n \"\",\n formatPlanEntries(entries),\n identity.sequence,\n planStatus(entries),\n \"Plan\",\n \"\",\n ),\n );\n };\n}\n", "import { LocalAgentDefinition } from \"../config.ts\";\nimport type { AcpActivity } from \"./activity.ts\";\nimport {\n AcpExecutionError,\n type AcpPromptResult,\n AcpSessionManager,\n} from \"./session-manager.ts\";\n\nexport interface RunAcpPromptOptions {\n readonly agentArguments: readonly string[];\n readonly agentCommand: string;\n readonly cwd: string;\n readonly onActivity: (activity: AcpActivity) => Promise<void>;\n readonly onText: (text: string) => Promise<void>;\n readonly prompt: string;\n readonly signal: AbortSignal;\n}\n\nexport type { AcpPromptResult };\nexport { AcpExecutionError };\n\nexport async function runAcpPrompt(\n options: RunAcpPromptOptions,\n): Promise<AcpPromptResult> {\n const sessions = new AcpSessionManager();\n try {\n return await sessions.runPrompt({\n agent: new LocalAgentDefinition(\n \"test-agent\",\n \"Test agent\",\n options.agentCommand,\n options.agentArguments,\n ),\n cwd: options.cwd,\n onActivity: options.onActivity,\n onText: options.onText,\n prompt: options.prompt,\n sessionId: crypto.randomUUID(),\n signal: options.signal,\n });\n } finally {\n await sessions.close();\n }\n}\n", "import { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\n\nexport interface AuditRecord {\n readonly commandId: string;\n readonly event: string;\n readonly sessionId: string;\n}\n\nexport class AuditStore {\n private readonly database: DatabaseSync;\n\n constructor(path: string) {\n mkdirSync(dirname(path), { recursive: true });\n this.database = new DatabaseSync(path);\n this.database.exec(`\n CREATE TABLE IF NOT EXISTS audit_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n recorded_at TEXT NOT NULL,\n event TEXT NOT NULL,\n command_id TEXT NOT NULL,\n session_id TEXT NOT NULL\n ) STRICT\n `);\n }\n\n record(record: AuditRecord): void {\n this.database\n .prepare(\n `\n INSERT INTO audit_events (\n recorded_at,\n event,\n command_id,\n session_id\n ) VALUES (?, ?, ?, ?)\n `,\n )\n .run(\n new Date().toISOString(),\n record.event,\n record.commandId,\n record.sessionId,\n );\n }\n\n close(): void {\n this.database.close();\n }\n}\n", "import { realpath, stat } from \"node:fs/promises\";\n\nexport class LocalAuthorizationError extends Error {\n readonly code = \"local_authorization_failed\";\n\n constructor(message: string, options: ErrorOptions = {}) {\n super(message, options);\n this.name = \"LocalAuthorizationError\";\n }\n}\n\nexport async function authorizeBinding(\n requestedBindingId: string,\n approvedBindingId: string,\n approvedRoot: string,\n): Promise<string> {\n if (requestedBindingId !== approvedBindingId) {\n throw new LocalAuthorizationError(\"The runtime binding is not authorized\");\n }\n\n try {\n const resolvedRoot = await realpath(approvedRoot);\n const metadata = await stat(resolvedRoot);\n if (!metadata.isDirectory()) {\n throw new LocalAuthorizationError(\"The approved root is not a directory\");\n }\n return resolvedRoot;\n } catch (error) {\n if (error instanceof LocalAuthorizationError) {\n throw error;\n }\n throw new LocalAuthorizationError(\"The approved root cannot be resolved\", {\n cause: error,\n });\n }\n}\n", "import { randomUUID } from \"node:crypto\";\nimport {\n mkdir,\n open,\n realpath,\n rename,\n stat,\n writeFile,\n} from \"node:fs/promises\";\nimport { homedir, hostname } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\n\nimport {\n createDaemonConfig,\n type DaemonConfig,\n loadLocalAgents,\n} from \"../config.ts\";\n\nconst PAIRING_TIMEOUT_MILLISECONDS = 20_000;\nconst PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;\nconst IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;\nconst TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;\nconst MAX_CONNECTION_FILE_LENGTH = 16 * 1024;\nconst CLAIM_RESPONSE_KEYS: readonly string[] = [\"channelId\", \"daemonToken\"];\nconst SAVED_CONNECTION_KEYS: readonly string[] = [\n \"approvedRoot\",\n \"channelId\",\n \"daemonToken\",\n \"relayOrigin\",\n];\n\ninterface PairCommandOptions {\n readonly code: string;\n readonly relayOrigin: URL;\n readonly root: string;\n}\n\ninterface ClaimPairingResponse {\n readonly channelId: string;\n readonly daemonToken: string;\n}\n\ninterface SavedConnection {\n readonly approvedRoot: string;\n readonly channelId: string;\n readonly daemonToken: string;\n readonly relayOrigin: URL;\n}\n\nexport interface PairedDaemon {\n readonly channelUrl: string;\n readonly config: DaemonConfig;\n readonly connectionPath: string;\n}\n\nexport class PairingClientError extends Error {\n readonly code: string;\n\n constructor(code: string, message: string, options: ErrorOptions = {}) {\n super(message, options);\n this.code = code;\n this.name = \"PairingClientError\";\n }\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction hasExactKeys(\n value: Readonly<Record<string, unknown>>,\n expectedKeys: readonly string[],\n): boolean {\n const keys = Object.keys(value);\n return (\n keys.length === expectedKeys.length &&\n expectedKeys.every((key) => Object.hasOwn(value, key))\n );\n}\n\nfunction readSingleOption(\n arguments_: readonly string[],\n option: string,\n): string {\n const values: string[] = [];\n for (let index = 0; index < arguments_.length; index += 1) {\n if (arguments_[index] !== option) {\n continue;\n }\n const value = arguments_[index + 1];\n if (value === undefined || value.startsWith(\"--\")) {\n throw new PairingClientError(\n \"invalid_arguments\",\n `${option} requires a value`,\n );\n }\n values.push(value);\n index += 1;\n }\n if (values.length !== 1) {\n throw new PairingClientError(\n \"invalid_arguments\",\n `${option} must be provided exactly once`,\n );\n }\n return values[0] ?? \"\";\n}\n\nfunction assertKnownArguments(arguments_: readonly string[]): void {\n for (let index = 0; index < arguments_.length; index += 2) {\n const option = arguments_[index];\n if (option !== \"--url\" && option !== \"--code\" && option !== \"--root\") {\n throw new PairingClientError(\n \"invalid_arguments\",\n `Unknown pairing option: ${option ?? \"missing option\"}`,\n );\n }\n }\n}\n\nfunction parseRelayOrigin(value: string): URL {\n let url: URL;\n try {\n url = new URL(value);\n } catch (error) {\n throw new PairingClientError(\n \"invalid_relay_url\",\n \"The relay URL is invalid\",\n { cause: error },\n );\n }\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n throw new PairingClientError(\n \"invalid_relay_url\",\n \"The relay URL must use http or https\",\n );\n }\n if (url.username.length > 0 || url.password.length > 0) {\n throw new PairingClientError(\n \"invalid_relay_url\",\n \"The relay URL cannot contain credentials\",\n );\n }\n if (\n url.protocol === \"http:\" &&\n url.hostname !== \"127.0.0.1\" &&\n url.hostname !== \"localhost\"\n ) {\n throw new PairingClientError(\n \"invalid_relay_url\",\n \"A remote relay must use https\",\n );\n }\n url.hash = \"\";\n url.pathname = \"/\";\n url.search = \"\";\n return url;\n}\n\nfunction parsePairingCode(value: string): string {\n const code = value.trim().toUpperCase();\n if (!PAIRING_CODE_PATTERN.test(code)) {\n throw new PairingClientError(\n \"invalid_pairing_code\",\n \"The pairing code must match the code shown in the browser\",\n );\n }\n return code;\n}\n\nfunction parsePairCommand(arguments_: readonly string[]): PairCommandOptions {\n assertKnownArguments(arguments_);\n return {\n code: parsePairingCode(readSingleOption(arguments_, \"--code\")),\n relayOrigin: parseRelayOrigin(readSingleOption(arguments_, \"--url\")),\n root: readSingleOption(arguments_, \"--root\"),\n };\n}\n\nfunction parseChannelArgument(arguments_: readonly string[]): string {\n if (arguments_.length !== 2 || arguments_[0] !== \"--channel\") {\n throw new PairingClientError(\n \"invalid_arguments\",\n \"Usage: mobius start --channel <channel-id>\",\n );\n }\n const channelId = arguments_[1] ?? \"\";\n if (!IDENTIFIER_PATTERN.test(channelId)) {\n throw new PairingClientError(\n \"invalid_channel_id\",\n \"The saved channel ID is invalid\",\n );\n }\n return channelId;\n}\n\nasync function resolveApprovedRoot(path: string): Promise<string> {\n const requestedRoot = resolve(path);\n try {\n const approvedRoot = await realpath(requestedRoot);\n const metadata = await stat(approvedRoot);\n if (!metadata.isDirectory()) {\n throw new PairingClientError(\n \"invalid_workspace\",\n \"The approved workspace root is not a directory\",\n );\n }\n return approvedRoot;\n } catch (error) {\n if (error instanceof PairingClientError) {\n throw error;\n }\n throw new PairingClientError(\n \"invalid_workspace\",\n \"The approved workspace root cannot be resolved\",\n { cause: error },\n );\n }\n}\n\nasync function readJsonResponse(response: Response): Promise<unknown> {\n if (response.headers.get(\"cf-mitigated\") === \"challenge\") {\n throw new PairingClientError(\n \"relay_challenge\",\n \"Cloudflare is protecting this temporary preview. Claim the deployment or use an authenticated deployment, then pair again\",\n );\n }\n const encoded = await response.text();\n try {\n return JSON.parse(encoded);\n } catch (error) {\n throw new PairingClientError(\n \"invalid_relay_response\",\n \"The relay returned an invalid response\",\n { cause: error },\n );\n }\n}\n\nfunction readRelayError(value: unknown): PairingClientError {\n if (isRecord(value)) {\n const error = value[\"error\"];\n if (isRecord(error)) {\n const code = error[\"code\"];\n const message = error[\"message\"];\n if (typeof code === \"string\" && typeof message === \"string\") {\n return new PairingClientError(code, message);\n }\n }\n }\n return new PairingClientError(\n \"pairing_failed\",\n \"The relay could not pair this machine\",\n );\n}\n\nfunction decodeClaimResponse(value: unknown): ClaimPairingResponse {\n if (!isRecord(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {\n throw new PairingClientError(\n \"invalid_relay_response\",\n \"The relay returned an invalid pairing response\",\n );\n }\n const channelId = value[\"channelId\"];\n const daemonToken = value[\"daemonToken\"];\n if (\n typeof channelId !== \"string\" ||\n !IDENTIFIER_PATTERN.test(channelId) ||\n typeof daemonToken !== \"string\" ||\n !TOKEN_PATTERN.test(daemonToken)\n ) {\n throw new PairingClientError(\n \"invalid_relay_response\",\n \"The relay returned an invalid pairing response\",\n );\n }\n return { channelId, daemonToken };\n}\n\nasync function claimPairing(\n options: PairCommandOptions,\n approvedRoot: string,\n): Promise<ClaimPairingResponse> {\n const agents = loadLocalAgents().map((agent) => ({\n id: agent.id,\n label: agent.label,\n }));\n const endpoint = new URL(\"/v1/pairings/claim\", options.relayOrigin);\n let response: Response;\n try {\n response = await fetch(endpoint, {\n body: JSON.stringify({\n agents,\n machineName: hostname(),\n pairingCode: options.code,\n workspaceName: basename(approvedRoot) || \"Local workspace\",\n }),\n headers: { \"content-type\": \"application/json\" },\n method: \"POST\",\n signal: AbortSignal.timeout(PAIRING_TIMEOUT_MILLISECONDS),\n });\n } catch (error) {\n throw new PairingClientError(\n \"relay_unavailable\",\n \"The pairing relay could not be reached\",\n { cause: error },\n );\n }\n\n const value = await readJsonResponse(response);\n if (!response.ok) {\n throw readRelayError(value);\n }\n return decodeClaimResponse(value);\n}\n\nfunction readStateDirectory(): string {\n // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.\n const configured = process.env[\"MOBIUS_STATE_DIRECTORY\"]?.trim();\n if (configured !== undefined && configured.length > 0) {\n return resolve(configured);\n }\n return join(homedir(), \".mobius\");\n}\n\nasync function persistConnection(\n channelId: string,\n relayOrigin: URL,\n daemonToken: string,\n approvedRoot: string,\n): Promise<string> {\n const connectionsDirectory = join(readStateDirectory(), \"connections\");\n await mkdir(connectionsDirectory, { mode: 0o700, recursive: true });\n const connectionPath = join(connectionsDirectory, `${channelId}.json`);\n const temporaryPath = join(\n connectionsDirectory,\n `.${channelId}.${randomUUID()}.tmp`,\n );\n await writeFile(\n temporaryPath,\n `${JSON.stringify(\n {\n approvedRoot,\n channelId,\n daemonToken,\n relayOrigin: relayOrigin.toString(),\n },\n null,\n 2,\n )}\\n`,\n { flag: \"wx\", mode: 0o600 },\n );\n await rename(temporaryPath, connectionPath);\n return connectionPath;\n}\n\nfunction decodeSavedConnection(\n value: unknown,\n expectedChannelId: string,\n): SavedConnection {\n if (!isRecord(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {\n throw new PairingClientError(\n \"invalid_connection\",\n \"The saved connection is invalid\",\n );\n }\n const approvedRoot = value[\"approvedRoot\"];\n const channelId = value[\"channelId\"];\n const daemonToken = value[\"daemonToken\"];\n const relayOrigin = value[\"relayOrigin\"];\n if (\n typeof approvedRoot !== \"string\" ||\n typeof channelId !== \"string\" ||\n channelId !== expectedChannelId ||\n !IDENTIFIER_PATTERN.test(channelId) ||\n typeof daemonToken !== \"string\" ||\n !TOKEN_PATTERN.test(daemonToken) ||\n typeof relayOrigin !== \"string\"\n ) {\n throw new PairingClientError(\n \"invalid_connection\",\n \"The saved connection is invalid\",\n );\n }\n return {\n approvedRoot,\n channelId,\n daemonToken,\n relayOrigin: parseRelayOrigin(relayOrigin),\n };\n}\n\nasync function readSavedConnection(\n channelId: string,\n): Promise<SavedConnection> {\n const connectionPath = join(\n readStateDirectory(),\n \"connections\",\n `${channelId}.json`,\n );\n let encoded = \"\";\n const handle = await open(connectionPath, \"r\");\n try {\n const metadata = await handle.stat();\n if (!metadata.isFile() || metadata.size > MAX_CONNECTION_FILE_LENGTH) {\n throw new PairingClientError(\n \"invalid_connection\",\n \"The saved connection is invalid\",\n );\n }\n encoded = await handle.readFile({ encoding: \"utf8\" });\n } finally {\n await handle.close();\n }\n\n let value: unknown;\n try {\n value = JSON.parse(encoded);\n } catch (error) {\n throw new PairingClientError(\n \"invalid_connection\",\n \"The saved connection is invalid\",\n { cause: error },\n );\n }\n const connection = decodeSavedConnection(value, channelId);\n return {\n approvedRoot: await resolveApprovedRoot(connection.approvedRoot),\n channelId: connection.channelId,\n daemonToken: connection.daemonToken,\n relayOrigin: connection.relayOrigin,\n };\n}\n\nfunction buildPairedDaemon(\n connection: SavedConnection,\n connectionPath: string,\n): PairedDaemon {\n const relayUrl = new URL(\n `/v1/channels/${encodeURIComponent(connection.channelId)}/daemon`,\n connection.relayOrigin,\n );\n relayUrl.protocol = relayUrl.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n relayUrl.searchParams.set(\"token\", connection.daemonToken);\n const auditDatabasePath = join(\n readStateDirectory(),\n \"audit\",\n `${connection.channelId}.sqlite`,\n );\n\n return {\n channelUrl: new URL(\n `/channels/${encodeURIComponent(connection.channelId)}`,\n connection.relayOrigin,\n ).toString(),\n config: createDaemonConfig({\n approvedRoot: connection.approvedRoot,\n auditDatabasePath,\n channelId: connection.channelId,\n relayUrl,\n }),\n connectionPath,\n };\n}\n\nexport async function pairLocalMachine(\n arguments_: readonly string[],\n): Promise<PairedDaemon> {\n const options = parsePairCommand(arguments_);\n const approvedRoot = await resolveApprovedRoot(options.root);\n const claim = await claimPairing(options, approvedRoot);\n const connectionPath = await persistConnection(\n claim.channelId,\n options.relayOrigin,\n claim.daemonToken,\n approvedRoot,\n );\n return buildPairedDaemon(\n {\n approvedRoot,\n channelId: claim.channelId,\n daemonToken: claim.daemonToken,\n relayOrigin: options.relayOrigin,\n },\n connectionPath,\n );\n}\n\nexport async function resumeLocalMachine(\n arguments_: readonly string[],\n): Promise<PairedDaemon> {\n const channelId = parseChannelArgument(arguments_);\n const connectionPath = join(\n readStateDirectory(),\n \"connections\",\n `${channelId}.json`,\n );\n return buildPairedDaemon(\n await readSavedConnection(channelId),\n connectionPath,\n );\n}\n", "import { randomUUID } from \"node:crypto\";\n\nimport {\n AGENT_ACTIVITY_KIND,\n AGENT_MESSAGE_DELTA_KIND,\n decodeMessageKind,\n decodeSessionCancelCommand,\n decodeSessionPromptCommand,\n encodeAgentActivityEvent,\n encodeAgentMessageDeltaEvent,\n encodeSessionCompletedEvent,\n encodeSessionFailedEvent,\n encodeSessionStartedEvent,\n MOBIUS_PROTOCOL_VERSION,\n SESSION_CANCEL_KIND,\n SESSION_COMPLETED_KIND,\n SESSION_FAILED_KIND,\n SESSION_PROMPT_KIND,\n SESSION_STARTED_KIND,\n type SessionCancelCommand,\n type SessionPromptCommand,\n} from \"@moxt-ai/mobius-protocol\";\n\nimport { AcpSessionManager } from \"./acp/session-manager.ts\";\nimport type { AuditStore } from \"./audit/audit-store.ts\";\nimport { authorizeBinding } from \"./authorization/authorize-binding.ts\";\nimport { type DaemonConfig, findLocalAgent } from \"./config.ts\";\nimport { connectRelay } from \"./relay-connection/connect.ts\";\n\nconst RELAY_RECONNECT_DELAY_MILLISECONDS = 500;\n\nclass ActiveDaemonTurn {\n readonly command: SessionPromptCommand;\n readonly #connectionController: AbortController;\n #cancellationRequested = false;\n\n constructor(\n command: SessionPromptCommand,\n connectionController: AbortController,\n ) {\n this.command = command;\n this.#connectionController = connectionController;\n }\n\n readonly abortConnection = (): void => {\n this.#connectionController.abort();\n };\n\n readonly matches = (cancellation: SessionCancelCommand): boolean =>\n cancellation.commandId === this.command.commandId &&\n cancellation.sessionId === this.command.sessionId;\n\n readonly requestCancellation = (): boolean => {\n if (this.#cancellationRequested) {\n return false;\n }\n this.#cancellationRequested = true;\n return true;\n };\n\n get signal(): AbortSignal {\n return this.#connectionController.signal;\n }\n}\n\nfunction send(socket: WebSocket, message: string): void {\n if (socket.readyState !== WebSocket.OPEN) {\n throw new Error(\"Relay connection is not open\");\n }\n socket.send(message);\n}\n\nfunction reportFailure(\n socket: WebSocket,\n command: SessionPromptCommand,\n code: string,\n message: string,\n): void {\n if (socket.readyState !== WebSocket.OPEN) {\n return;\n }\n send(\n socket,\n encodeSessionFailedEvent({\n code,\n commandId: command.commandId,\n kind: SESSION_FAILED_KIND,\n message,\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: command.sessionId,\n }),\n );\n}\n\nasync function executePrompt(\n socket: WebSocket,\n command: SessionPromptCommand,\n config: DaemonConfig,\n audit: AuditStore,\n sessions: AcpSessionManager,\n signal: AbortSignal,\n): Promise<void> {\n try {\n const approvedRoot = await authorizeBinding(\n command.bindingId,\n config.bindingId,\n config.approvedRoot,\n );\n const agent = findLocalAgent(config.agents, command.agentId);\n const processAttemptId = randomUUID();\n audit.record({\n commandId: command.commandId,\n event: \"session_authorized\",\n sessionId: command.sessionId,\n });\n send(\n socket,\n encodeSessionStartedEvent({\n commandId: command.commandId,\n kind: SESSION_STARTED_KIND,\n processAttemptId,\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: command.sessionId,\n }),\n );\n\n const result = await sessions.runPrompt({\n agent,\n cwd: approvedRoot,\n onActivity: (activity) => {\n send(\n socket,\n encodeAgentActivityEvent({\n activityId: activity.activityId,\n activityType: activity.activityType,\n commandId: command.commandId,\n input: activity.input,\n kind: AGENT_ACTIVITY_KIND,\n locations: activity.locations,\n name: activity.name,\n output: activity.output,\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sequence: activity.sequence,\n sessionId: command.sessionId,\n status: activity.status,\n title: activity.title,\n toolKind: activity.toolKind,\n }),\n );\n return Promise.resolve();\n },\n onText: (text) => {\n send(\n socket,\n encodeAgentMessageDeltaEvent({\n commandId: command.commandId,\n kind: AGENT_MESSAGE_DELTA_KIND,\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: command.sessionId,\n text,\n }),\n );\n return Promise.resolve();\n },\n prompt: command.prompt,\n sessionId: command.sessionId,\n signal,\n });\n\n send(\n socket,\n encodeSessionCompletedEvent({\n commandId: command.commandId,\n kind: SESSION_COMPLETED_KIND,\n protocolVersion: MOBIUS_PROTOCOL_VERSION,\n sessionId: command.sessionId,\n stopReason: result.stopReason,\n }),\n );\n audit.record({\n commandId: command.commandId,\n event:\n result.stopReason === \"cancelled\"\n ? \"session_cancelled\"\n : \"session_completed\",\n sessionId: command.sessionId,\n });\n } catch (error) {\n audit.record({\n commandId: command.commandId,\n event: \"session_failed\",\n sessionId: command.sessionId,\n });\n reportFailure(\n socket,\n command,\n \"agent_execution_failed\",\n \"The local agent could not complete the request\",\n );\n console.error(\"Mobius daemon command failed\", error);\n }\n}\n\nfunction waitForRelayRetry(signal: AbortSignal): Promise<void> {\n if (signal.aborted) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n const timeout = setTimeout(finish, RELAY_RECONNECT_DELAY_MILLISECONDS);\n\n function finish(): void {\n clearTimeout(timeout);\n signal.removeEventListener(\"abort\", finish);\n resolve();\n }\n\n signal.addEventListener(\"abort\", finish, { once: true });\n });\n}\n\nasync function runRelayConnection(\n config: DaemonConfig,\n audit: AuditStore,\n sessions: AcpSessionManager,\n signal: AbortSignal,\n): Promise<void> {\n const socket = await connectRelay(config.relayUrl, signal);\n const activeTurns = new Map<string, ActiveDaemonTurn>();\n\n await new Promise<void>((resolve, reject) => {\n let finished = false;\n\n const cleanup = (): void => {\n signal.removeEventListener(\"abort\", stop);\n socket.removeEventListener(\"close\", handleClose);\n socket.removeEventListener(\"error\", handleError);\n socket.removeEventListener(\"message\", handleMessage);\n for (const turn of activeTurns.values()) {\n turn.abortConnection();\n }\n activeTurns.clear();\n };\n\n const resolveConnection = (): void => {\n if (finished) {\n return;\n }\n finished = true;\n cleanup();\n resolve();\n };\n\n const rejectConnection = (): void => {\n if (finished) {\n return;\n }\n finished = true;\n cleanup();\n reject(new Error(\"Relay WebSocket failed\"));\n };\n\n const stop = (): void => {\n socket.close(1000, \"Daemon stopped\");\n resolveConnection();\n };\n\n signal.addEventListener(\"abort\", stop, { once: true });\n const handleClose = (): void => {\n resolveConnection();\n };\n const handleError = (): void => {\n if (signal.aborted) {\n resolveConnection();\n return;\n }\n rejectConnection();\n };\n const handleMessage = (event: MessageEvent<unknown>): void => {\n const encoded: unknown = event.data;\n if (typeof encoded !== \"string\") {\n socket.close(1003, \"Text message required\");\n return;\n }\n\n try {\n const kind = decodeMessageKind(encoded);\n if (kind === SESSION_CANCEL_KIND) {\n const cancellation = decodeSessionCancelCommand(encoded);\n const turn = activeTurns.get(cancellation.commandId);\n if (turn === undefined || !turn.matches(cancellation)) {\n console.warn(\n \"Mobius daemon ignored cancellation for an inactive turn\",\n );\n return;\n }\n if (!turn.requestCancellation()) {\n return;\n }\n audit.record({\n commandId: cancellation.commandId,\n event: \"session_cancellation_requested\",\n sessionId: cancellation.sessionId,\n });\n void sessions.cancelPrompt(cancellation.sessionId).catch((error) => {\n console.error(\n \"Mobius daemon could not cancel the agent turn\",\n error,\n );\n });\n return;\n }\n if (kind !== SESSION_PROMPT_KIND) {\n socket.close(1008, \"Unsupported protocol message\");\n return;\n }\n const command = decodeSessionPromptCommand(encoded);\n if (activeTurns.has(command.commandId)) {\n reportFailure(\n socket,\n command,\n \"duplicate_command\",\n \"The command is already running\",\n );\n return;\n }\n\n const turn = new ActiveDaemonTurn(command, new AbortController());\n activeTurns.set(command.commandId, turn);\n void executePrompt(\n socket,\n command,\n config,\n audit,\n sessions,\n turn.signal,\n )\n .catch((error: unknown) => {\n console.error(\"Mobius daemon turn failed\", error);\n })\n .finally(() => {\n activeTurns.delete(command.commandId);\n });\n } catch (error) {\n console.error(\"Mobius daemon rejected a message\", error);\n socket.close(1008, \"Invalid protocol message\");\n }\n };\n socket.addEventListener(\"close\", handleClose);\n socket.addEventListener(\"error\", handleError);\n socket.addEventListener(\"message\", handleMessage);\n\n if (signal.aborted) {\n stop();\n }\n });\n}\n\nexport async function runDaemon(\n config: DaemonConfig,\n audit: AuditStore,\n signal: AbortSignal,\n): Promise<void> {\n const sessions = new AcpSessionManager();\n let retryAnnounced = false;\n\n try {\n while (!signal.aborted) {\n try {\n await runRelayConnection(config, audit, sessions, signal);\n retryAnnounced = false;\n } catch {\n if (signal.aborted) {\n return;\n }\n if (!retryAnnounced) {\n console.warn(\"Mobius daemon is waiting for the relay\");\n retryAnnounced = true;\n }\n }\n\n await waitForRelayRetry(signal);\n }\n } finally {\n await sessions.close();\n }\n}\n", "const CONNECTION_TIMEOUT_MILLISECONDS = 15_000;\n\nclass RelayConnectionError extends Error {\n readonly code: string;\n\n constructor(code: string, message: string, options: ErrorOptions = {}) {\n super(message, options);\n this.code = code;\n this.name = \"RelayConnectionError\";\n }\n}\n\nexport function connectRelay(\n url: URL,\n signal: AbortSignal,\n): Promise<WebSocket> {\n signal.throwIfAborted();\n\n return new Promise((resolve, reject) => {\n const socket = new WebSocket(url);\n let finished = false;\n const timeout = setTimeout(onTimeout, CONNECTION_TIMEOUT_MILLISECONDS);\n\n const cleanup = (): void => {\n clearTimeout(timeout);\n signal.removeEventListener(\"abort\", onAbort);\n socket.removeEventListener(\"close\", onClose);\n socket.removeEventListener(\"error\", onError);\n socket.removeEventListener(\"open\", onOpen);\n };\n const fail = (error: RelayConnectionError): void => {\n if (finished) {\n return;\n }\n finished = true;\n cleanup();\n socket.close();\n reject(error);\n };\n const onAbort = (): void => {\n fail(\n new RelayConnectionError(\n \"relay_connection_cancelled\",\n \"Relay connection was cancelled\",\n { cause: signal.reason },\n ),\n );\n };\n const onClose = (): void => {\n fail(\n new RelayConnectionError(\n \"relay_connection_closed\",\n \"Relay connection closed before it was ready\",\n ),\n );\n };\n const onError = (): void => {\n fail(\n new RelayConnectionError(\n \"relay_connection_failed\",\n \"Relay connection failed\",\n ),\n );\n };\n const onOpen = (): void => {\n if (finished) {\n return;\n }\n finished = true;\n cleanup();\n resolve(socket);\n };\n function onTimeout(): void {\n fail(\n new RelayConnectionError(\n \"relay_connection_timeout\",\n \"Relay connection timed out\",\n ),\n );\n }\n\n signal.addEventListener(\"abort\", onAbort, { once: true });\n socket.addEventListener(\"close\", onClose, { once: true });\n socket.addEventListener(\"error\", onError, { once: true });\n socket.addEventListener(\"open\", onOpen, { once: true });\n\n if (signal.aborted) {\n onAbort();\n }\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["isRecord", "resolve", "realpath", "stat", "IDENTIFIER_PATTERN", "isRecord", "realpath", "stat", "randomUUID", "resolve", "randomUUID", "resolve", "turn"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type DaemonConfig } from "../config.ts";
|
|
2
|
+
export interface PairedDaemon {
|
|
3
|
+
readonly channelUrl: string;
|
|
4
|
+
readonly config: DaemonConfig;
|
|
5
|
+
readonly connectionPath: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class PairingClientError extends Error {
|
|
8
|
+
readonly code: string;
|
|
9
|
+
constructor(code: string, message: string, options?: ErrorOptions);
|
|
10
|
+
}
|
|
11
|
+
export declare function pairLocalMachine(arguments_: readonly string[]): Promise<PairedDaemon>;
|
|
12
|
+
export declare function resumeLocalMachine(arguments_: readonly string[]): Promise<PairedDaemon>;
|
|
13
|
+
//# sourceMappingURL=pair-local-machine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pair-local-machine.d.ts","sourceRoot":"","sources":["../../src/pairing/pair-local-machine.ts"],"names":[],"mappings":"AAYA,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,cAAc,CAAC;AAiCtB,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,EAIpE;CACF;AAkZD,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,OAAO,CAAC,YAAY,CAAC,CAmBvB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,OAAO,CAAC,YAAY,CAAC,CAWvB"}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, open, realpath, rename, stat, writeFile, } from "node:fs/promises";
|
|
3
|
+
import { homedir, hostname } from "node:os";
|
|
4
|
+
import { basename, join, resolve } from "node:path";
|
|
5
|
+
import { createDaemonConfig, loadLocalAgents, } from "../config.js";
|
|
6
|
+
const PAIRING_TIMEOUT_MILLISECONDS = 20_000;
|
|
7
|
+
const PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
|
|
8
|
+
const IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
|
|
9
|
+
const TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
|
|
10
|
+
const MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
|
|
11
|
+
const CLAIM_RESPONSE_KEYS = ["channelId", "daemonToken"];
|
|
12
|
+
const SAVED_CONNECTION_KEYS = [
|
|
13
|
+
"approvedRoot",
|
|
14
|
+
"channelId",
|
|
15
|
+
"daemonToken",
|
|
16
|
+
"relayOrigin",
|
|
17
|
+
];
|
|
18
|
+
export class PairingClientError extends Error {
|
|
19
|
+
code;
|
|
20
|
+
constructor(code, message, options = {}) {
|
|
21
|
+
super(message, options);
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.name = "PairingClientError";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function isRecord(value) {
|
|
27
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28
|
+
}
|
|
29
|
+
function hasExactKeys(value, expectedKeys) {
|
|
30
|
+
const keys = Object.keys(value);
|
|
31
|
+
return (keys.length === expectedKeys.length &&
|
|
32
|
+
expectedKeys.every((key) => Object.hasOwn(value, key)));
|
|
33
|
+
}
|
|
34
|
+
function readSingleOption(arguments_, option) {
|
|
35
|
+
const values = [];
|
|
36
|
+
for (let index = 0; index < arguments_.length; index += 1) {
|
|
37
|
+
if (arguments_[index] !== option) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const value = arguments_[index + 1];
|
|
41
|
+
if (value === undefined || value.startsWith("--")) {
|
|
42
|
+
throw new PairingClientError("invalid_arguments", `${option} requires a value`);
|
|
43
|
+
}
|
|
44
|
+
values.push(value);
|
|
45
|
+
index += 1;
|
|
46
|
+
}
|
|
47
|
+
if (values.length !== 1) {
|
|
48
|
+
throw new PairingClientError("invalid_arguments", `${option} must be provided exactly once`);
|
|
49
|
+
}
|
|
50
|
+
return values[0] ?? "";
|
|
51
|
+
}
|
|
52
|
+
function assertKnownArguments(arguments_) {
|
|
53
|
+
for (let index = 0; index < arguments_.length; index += 2) {
|
|
54
|
+
const option = arguments_[index];
|
|
55
|
+
if (option !== "--url" && option !== "--code" && option !== "--root") {
|
|
56
|
+
throw new PairingClientError("invalid_arguments", `Unknown pairing option: ${option ?? "missing option"}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function parseRelayOrigin(value) {
|
|
61
|
+
let url;
|
|
62
|
+
try {
|
|
63
|
+
url = new URL(value);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
throw new PairingClientError("invalid_relay_url", "The relay URL is invalid", { cause: error });
|
|
67
|
+
}
|
|
68
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
69
|
+
throw new PairingClientError("invalid_relay_url", "The relay URL must use http or https");
|
|
70
|
+
}
|
|
71
|
+
if (url.username.length > 0 || url.password.length > 0) {
|
|
72
|
+
throw new PairingClientError("invalid_relay_url", "The relay URL cannot contain credentials");
|
|
73
|
+
}
|
|
74
|
+
if (url.protocol === "http:" &&
|
|
75
|
+
url.hostname !== "127.0.0.1" &&
|
|
76
|
+
url.hostname !== "localhost") {
|
|
77
|
+
throw new PairingClientError("invalid_relay_url", "A remote relay must use https");
|
|
78
|
+
}
|
|
79
|
+
url.hash = "";
|
|
80
|
+
url.pathname = "/";
|
|
81
|
+
url.search = "";
|
|
82
|
+
return url;
|
|
83
|
+
}
|
|
84
|
+
function parsePairingCode(value) {
|
|
85
|
+
const code = value.trim().toUpperCase();
|
|
86
|
+
if (!PAIRING_CODE_PATTERN.test(code)) {
|
|
87
|
+
throw new PairingClientError("invalid_pairing_code", "The pairing code must match the code shown in the browser");
|
|
88
|
+
}
|
|
89
|
+
return code;
|
|
90
|
+
}
|
|
91
|
+
function parsePairCommand(arguments_) {
|
|
92
|
+
assertKnownArguments(arguments_);
|
|
93
|
+
return {
|
|
94
|
+
code: parsePairingCode(readSingleOption(arguments_, "--code")),
|
|
95
|
+
relayOrigin: parseRelayOrigin(readSingleOption(arguments_, "--url")),
|
|
96
|
+
root: readSingleOption(arguments_, "--root"),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function parseChannelArgument(arguments_) {
|
|
100
|
+
if (arguments_.length !== 2 || arguments_[0] !== "--channel") {
|
|
101
|
+
throw new PairingClientError("invalid_arguments", "Usage: mobius start --channel <channel-id>");
|
|
102
|
+
}
|
|
103
|
+
const channelId = arguments_[1] ?? "";
|
|
104
|
+
if (!IDENTIFIER_PATTERN.test(channelId)) {
|
|
105
|
+
throw new PairingClientError("invalid_channel_id", "The saved channel ID is invalid");
|
|
106
|
+
}
|
|
107
|
+
return channelId;
|
|
108
|
+
}
|
|
109
|
+
async function resolveApprovedRoot(path) {
|
|
110
|
+
const requestedRoot = resolve(path);
|
|
111
|
+
try {
|
|
112
|
+
const approvedRoot = await realpath(requestedRoot);
|
|
113
|
+
const metadata = await stat(approvedRoot);
|
|
114
|
+
if (!metadata.isDirectory()) {
|
|
115
|
+
throw new PairingClientError("invalid_workspace", "The approved workspace root is not a directory");
|
|
116
|
+
}
|
|
117
|
+
return approvedRoot;
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (error instanceof PairingClientError) {
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
throw new PairingClientError("invalid_workspace", "The approved workspace root cannot be resolved", { cause: error });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function readJsonResponse(response) {
|
|
127
|
+
if (response.headers.get("cf-mitigated") === "challenge") {
|
|
128
|
+
throw new PairingClientError("relay_challenge", "Cloudflare is protecting this temporary preview. Claim the deployment or use an authenticated deployment, then pair again");
|
|
129
|
+
}
|
|
130
|
+
const encoded = await response.text();
|
|
131
|
+
try {
|
|
132
|
+
return JSON.parse(encoded);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid response", { cause: error });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function readRelayError(value) {
|
|
139
|
+
if (isRecord(value)) {
|
|
140
|
+
const error = value["error"];
|
|
141
|
+
if (isRecord(error)) {
|
|
142
|
+
const code = error["code"];
|
|
143
|
+
const message = error["message"];
|
|
144
|
+
if (typeof code === "string" && typeof message === "string") {
|
|
145
|
+
return new PairingClientError(code, message);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return new PairingClientError("pairing_failed", "The relay could not pair this machine");
|
|
150
|
+
}
|
|
151
|
+
function decodeClaimResponse(value) {
|
|
152
|
+
if (!isRecord(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
|
|
153
|
+
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
154
|
+
}
|
|
155
|
+
const channelId = value["channelId"];
|
|
156
|
+
const daemonToken = value["daemonToken"];
|
|
157
|
+
if (typeof channelId !== "string" ||
|
|
158
|
+
!IDENTIFIER_PATTERN.test(channelId) ||
|
|
159
|
+
typeof daemonToken !== "string" ||
|
|
160
|
+
!TOKEN_PATTERN.test(daemonToken)) {
|
|
161
|
+
throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
|
|
162
|
+
}
|
|
163
|
+
return { channelId, daemonToken };
|
|
164
|
+
}
|
|
165
|
+
async function claimPairing(options, approvedRoot) {
|
|
166
|
+
const agents = loadLocalAgents().map((agent) => ({
|
|
167
|
+
id: agent.id,
|
|
168
|
+
label: agent.label,
|
|
169
|
+
}));
|
|
170
|
+
const endpoint = new URL("/v1/pairings/claim", options.relayOrigin);
|
|
171
|
+
let response;
|
|
172
|
+
try {
|
|
173
|
+
response = await fetch(endpoint, {
|
|
174
|
+
body: JSON.stringify({
|
|
175
|
+
agents,
|
|
176
|
+
machineName: hostname(),
|
|
177
|
+
pairingCode: options.code,
|
|
178
|
+
workspaceName: basename(approvedRoot) || "Local workspace",
|
|
179
|
+
}),
|
|
180
|
+
headers: { "content-type": "application/json" },
|
|
181
|
+
method: "POST",
|
|
182
|
+
signal: AbortSignal.timeout(PAIRING_TIMEOUT_MILLISECONDS),
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
throw new PairingClientError("relay_unavailable", "The pairing relay could not be reached", { cause: error });
|
|
187
|
+
}
|
|
188
|
+
const value = await readJsonResponse(response);
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
throw readRelayError(value);
|
|
191
|
+
}
|
|
192
|
+
return decodeClaimResponse(value);
|
|
193
|
+
}
|
|
194
|
+
function readStateDirectory() {
|
|
195
|
+
// biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
|
|
196
|
+
const configured = process.env["MOBIUS_STATE_DIRECTORY"]?.trim();
|
|
197
|
+
if (configured !== undefined && configured.length > 0) {
|
|
198
|
+
return resolve(configured);
|
|
199
|
+
}
|
|
200
|
+
return join(homedir(), ".mobius");
|
|
201
|
+
}
|
|
202
|
+
async function persistConnection(channelId, relayOrigin, daemonToken, approvedRoot) {
|
|
203
|
+
const connectionsDirectory = join(readStateDirectory(), "connections");
|
|
204
|
+
await mkdir(connectionsDirectory, { mode: 0o700, recursive: true });
|
|
205
|
+
const connectionPath = join(connectionsDirectory, `${channelId}.json`);
|
|
206
|
+
const temporaryPath = join(connectionsDirectory, `.${channelId}.${randomUUID()}.tmp`);
|
|
207
|
+
await writeFile(temporaryPath, `${JSON.stringify({
|
|
208
|
+
approvedRoot,
|
|
209
|
+
channelId,
|
|
210
|
+
daemonToken,
|
|
211
|
+
relayOrigin: relayOrigin.toString(),
|
|
212
|
+
}, null, 2)}\n`, { flag: "wx", mode: 0o600 });
|
|
213
|
+
await rename(temporaryPath, connectionPath);
|
|
214
|
+
return connectionPath;
|
|
215
|
+
}
|
|
216
|
+
function decodeSavedConnection(value, expectedChannelId) {
|
|
217
|
+
if (!isRecord(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
|
|
218
|
+
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
219
|
+
}
|
|
220
|
+
const approvedRoot = value["approvedRoot"];
|
|
221
|
+
const channelId = value["channelId"];
|
|
222
|
+
const daemonToken = value["daemonToken"];
|
|
223
|
+
const relayOrigin = value["relayOrigin"];
|
|
224
|
+
if (typeof approvedRoot !== "string" ||
|
|
225
|
+
typeof channelId !== "string" ||
|
|
226
|
+
channelId !== expectedChannelId ||
|
|
227
|
+
!IDENTIFIER_PATTERN.test(channelId) ||
|
|
228
|
+
typeof daemonToken !== "string" ||
|
|
229
|
+
!TOKEN_PATTERN.test(daemonToken) ||
|
|
230
|
+
typeof relayOrigin !== "string") {
|
|
231
|
+
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
approvedRoot,
|
|
235
|
+
channelId,
|
|
236
|
+
daemonToken,
|
|
237
|
+
relayOrigin: parseRelayOrigin(relayOrigin),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
async function readSavedConnection(channelId) {
|
|
241
|
+
const connectionPath = join(readStateDirectory(), "connections", `${channelId}.json`);
|
|
242
|
+
let encoded = "";
|
|
243
|
+
const handle = await open(connectionPath, "r");
|
|
244
|
+
try {
|
|
245
|
+
const metadata = await handle.stat();
|
|
246
|
+
if (!metadata.isFile() || metadata.size > MAX_CONNECTION_FILE_LENGTH) {
|
|
247
|
+
throw new PairingClientError("invalid_connection", "The saved connection is invalid");
|
|
248
|
+
}
|
|
249
|
+
encoded = await handle.readFile({ encoding: "utf8" });
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
await handle.close();
|
|
253
|
+
}
|
|
254
|
+
let value;
|
|
255
|
+
try {
|
|
256
|
+
value = JSON.parse(encoded);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
throw new PairingClientError("invalid_connection", "The saved connection is invalid", { cause: error });
|
|
260
|
+
}
|
|
261
|
+
const connection = decodeSavedConnection(value, channelId);
|
|
262
|
+
return {
|
|
263
|
+
approvedRoot: await resolveApprovedRoot(connection.approvedRoot),
|
|
264
|
+
channelId: connection.channelId,
|
|
265
|
+
daemonToken: connection.daemonToken,
|
|
266
|
+
relayOrigin: connection.relayOrigin,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function buildPairedDaemon(connection, connectionPath) {
|
|
270
|
+
const relayUrl = new URL(`/v1/channels/${encodeURIComponent(connection.channelId)}/daemon`, connection.relayOrigin);
|
|
271
|
+
relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
272
|
+
relayUrl.searchParams.set("token", connection.daemonToken);
|
|
273
|
+
const auditDatabasePath = join(readStateDirectory(), "audit", `${connection.channelId}.sqlite`);
|
|
274
|
+
return {
|
|
275
|
+
channelUrl: new URL(`/channels/${encodeURIComponent(connection.channelId)}`, connection.relayOrigin).toString(),
|
|
276
|
+
config: createDaemonConfig({
|
|
277
|
+
approvedRoot: connection.approvedRoot,
|
|
278
|
+
auditDatabasePath,
|
|
279
|
+
channelId: connection.channelId,
|
|
280
|
+
relayUrl,
|
|
281
|
+
}),
|
|
282
|
+
connectionPath,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
export async function pairLocalMachine(arguments_) {
|
|
286
|
+
const options = parsePairCommand(arguments_);
|
|
287
|
+
const approvedRoot = await resolveApprovedRoot(options.root);
|
|
288
|
+
const claim = await claimPairing(options, approvedRoot);
|
|
289
|
+
const connectionPath = await persistConnection(claim.channelId, options.relayOrigin, claim.daemonToken, approvedRoot);
|
|
290
|
+
return buildPairedDaemon({
|
|
291
|
+
approvedRoot,
|
|
292
|
+
channelId: claim.channelId,
|
|
293
|
+
daemonToken: claim.daemonToken,
|
|
294
|
+
relayOrigin: options.relayOrigin,
|
|
295
|
+
}, connectionPath);
|
|
296
|
+
}
|
|
297
|
+
export async function resumeLocalMachine(arguments_) {
|
|
298
|
+
const channelId = parseChannelArgument(arguments_);
|
|
299
|
+
const connectionPath = join(readStateDirectory(), "connections", `${channelId}.json`);
|
|
300
|
+
return buildPairedDaemon(await readSavedConnection(channelId), connectionPath);
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=pair-local-machine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pair-local-machine.js","sourceRoot":"","sources":["../../src/pairing/pair-local-machine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/relay-connection/connect.ts"],"names":[],"mappings":"AAYA,wBAAgB,YAAY,CAC1B,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,SAAS,CAAC,CA2EpB"}
|