{"version":3,"file":"acp-agent-B2uqCKFc.mjs","names":["candidates: unknown[]","locations: ToolCallLocation[]","oldText: string | null","lines: string[]","inputSummary: string[]","out: Record<string, unknown>","json: string | null","content: ToolCallContent[]","candidates: unknown[]","entries: Array<{\n    content: string;\n    status: \"pending\" | \"in_progress\" | \"completed\";\n    priority: \"medium\";\n  }>","explicitChoices: Array<{ id: string; title: string }>","looseChoices: Array<{ id: string; title: string }>","id","title","ACP_MODE_TO_DROID_AUTONOMY: Record<AcpModeId, DroidAutonomyLevel>","entries: Array<{\n              content: string;\n              status: \"pending\" | \"in_progress\" | \"completed\";\n              priority: \"high\" | \"medium\" | \"low\";\n            }>","toolCallKind: ToolKind","merged: ToolCallContent[]","candidates: unknown[]","acpOptions: PermissionOption[]","selectedOption","isExitSpecMode","status","permission: Awaited<ReturnType<AgentSideConnection[\"requestPermission\"]>>","toolCallKind: ToolKind","ACP_MODES: AcpModeId[]","textParts: string[]","images: DroidUserMessageImage[]","prompt","currentData: string[]","parsed: unknown[]","url: URL","input: unknown","readBody","chunks: Buffer[]","results: Array<Record<string, unknown>>","mcpResponse: unknown","error: unknown","lastWebsearchAt: string | null","lastWebsearchOutcome: string | null","bodyBuffer: Buffer | null","upstreamResponse: Response","setCookie: string[] | undefined","cachedSettings: FactorySettings | null","results: SearchResult[]","results: SearchResult[] | null","chunks: Buffer[]","lastWebsearchAt: string | null","lastWebsearchSource: string | null","body: string | undefined","process: ChildProcess | null","sessionId: string | null","websearchProxy: WebsearchProxyHandle | NativeWebsearchProxyHandle | null","notificationHandlers: Array<(n: DroidNotification) => void | Promise<void>>","rawEventHandlers: Array<(e: unknown) => void | Promise<void>>","exitHandlers: Array<(code: number | null) => void>","requestHandler: ((method: string, params: unknown) => Promise<PermissionResponse>) | null","initResolve: ((result: InitSessionResult) => void) | null","initReject: ((error: Error) => void) | null","pendingIdleTimer: NodeJS.Timeout | null","process","msg: FactoryRequest","processingChain: Promise<void>","error: unknown","env: NodeJS.ProcessEnv","port: number | undefined","params: Record<string, unknown>","commands: AvailableCommand[]","session: Session","err: unknown","droid","started: { droid: DroidAdapter; init: InitSessionResult }","newSession","fs","dirents: Array<{ name: string; isDirectory?: () => boolean }>","scanDirs: string[]","records: FactorySessionRecord[]","entries: string[]","updatedAt: string | null","handle: FileHandle | null","contextJson: unknown","usage: FactorySessionSettings[\"tokenUsage\"] | undefined","inputTokens","outputTokens","cacheReadTokens","cacheCreationTokens","total","n","prompt","summaryRaw: string","err: unknown","newSession","available","lines: string[]","newSession","handlePermissionRequest","handleDroidNotification"],"sources":["../src/utils.ts","../src/acp/flags.ts","../src/acp/package-info.ts","../src/acp/permissions/paths.ts","../src/acp/permissions/diff.ts","../src/acp/text.ts","../src/acp/permissions/format.ts","../src/acp/permissions/content.ts","../src/acp/permissions/spec.ts","../src/acp/permissions/tool-kind.ts","../src/acp/constants.ts","../src/acp/notifications/handle-notification.ts","../src/acp/permissions/options.ts","../src/acp/permissions/acp-options.ts","../src/acp/permissions/auto-decision.ts","../src/acp/permissions/exit-spec.ts","../src/acp/permissions/decide.ts","../src/acp/permissions/handle-permission.ts","../src/acp/agent/messages.ts","../src/types.ts","../src/acp/prompt/convert.ts","../src/websearch-proxy.ts","../src/websearch-native.ts","../src/droid-adapter.ts","../src/acp/commands.ts","../src/acp/session/attach-session.ts","../src/acp/session/restart.ts","../src/acp/agent/slash/help.ts","../src/factory-sessions.ts","../src/factory-logs.ts","../src/acp/agent/slash/context.ts","../src/acp/agent/slash/compress.ts","../src/acp/agent/slash/model.ts","../src/acp/agent/slash/mode.ts","../src/acp/agent/slash/config.ts","../src/acp/agent/slash/status.ts","../src/acp/agent/slash/sessions/shared.ts","../src/acp/agent/slash/sessions/list.ts","../src/acp/history/transcript.ts","../src/acp/history/replay.ts","../src/acp/agent/slash/sessions/load.ts","../src/acp/agent/slash/sessions.ts","../src/acp/agent/slash/handle.ts","../src/acp/agent/prompt.ts","../src/acp/agent/state.ts","../src/acp/agent/sessions.ts","../src/acp/agent/droid-acp-agent.ts","../src/acp/agent/run-acp.ts"],"sourcesContent":["import { Readable, Writable } from \"node:stream\";\nimport { WritableStream, ReadableStream } from \"node:stream/web\";\n\nexport interface Logger {\n  log: (...args: unknown[]) => void;\n  error: (...args: unknown[]) => void;\n}\n\nexport class Pushable<T> implements AsyncIterable<T> {\n  private queue: T[] = [];\n  private resolvers: ((value: IteratorResult<T>) => void)[] = [];\n  private done = false;\n\n  push(item: T) {\n    if (this.resolvers.length > 0) {\n      const resolve = this.resolvers.shift()!;\n      resolve({ value: item, done: false });\n    } else {\n      this.queue.push(item);\n    }\n  }\n\n  end() {\n    this.done = true;\n    while (this.resolvers.length > 0) {\n      const resolve = this.resolvers.shift()!;\n      resolve({ value: undefined as T, done: true });\n    }\n  }\n\n  [Symbol.asyncIterator](): AsyncIterator<T> {\n    return {\n      next: (): Promise<IteratorResult<T>> => {\n        if (this.queue.length > 0) {\n          const value = this.queue.shift()!;\n          return Promise.resolve({ value, done: false });\n        }\n        if (this.done) {\n          return Promise.resolve({ value: undefined as T, done: true });\n        }\n        return new Promise<IteratorResult<T>>((resolve) => {\n          this.resolvers.push(resolve);\n        });\n      },\n    };\n  }\n}\n\nexport function nodeToWebWritable(nodeStream: Writable): WritableStream<Uint8Array> {\n  return new WritableStream<Uint8Array>({\n    write(chunk) {\n      return new Promise<void>((resolve, reject) => {\n        nodeStream.write(Buffer.from(chunk), (err) => {\n          if (err) {\n            reject(err);\n          } else {\n            resolve();\n          }\n        });\n      });\n    },\n  });\n}\n\nexport function nodeToWebReadable(nodeStream: Readable): ReadableStream<Uint8Array> {\n  return new ReadableStream<Uint8Array>({\n    start(controller) {\n      nodeStream.on(\"data\", (chunk: Buffer) => {\n        controller.enqueue(new Uint8Array(chunk));\n      });\n      nodeStream.on(\"end\", () => controller.close());\n      nodeStream.on(\"error\", (err) => controller.error(err));\n    },\n  });\n}\n\nexport function unreachable(value: never, logger: Logger = console) {\n  let valueAsString;\n  try {\n    valueAsString = JSON.stringify(value);\n  } catch {\n    valueAsString = value;\n  }\n  logger.error(`Unexpected case: ${valueAsString}`);\n}\n\nexport function sleep(time: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, time));\n}\n\nexport function isEnvEnabled(value: string | undefined): boolean {\n  if (!value) return false;\n  switch (value.trim().toLowerCase()) {\n    case \"1\":\n    case \"true\":\n    case \"yes\":\n    case \"on\":\n      return true;\n    default:\n      return false;\n  }\n}\n\n/** Check if running on Windows */\nexport const isWindows = process.platform === \"win32\";\n\n/**\n * Find the droid executable path.\n * Uses DROID_EXECUTABLE env var if set, otherwise defaults to \"droid\".\n * On Windows, also checks for \"droid.exe\" if not explicitly set.\n */\nexport function findDroidExecutable(): string {\n  if (process.env.DROID_EXECUTABLE) {\n    return process.env.DROID_EXECUTABLE;\n  }\n  // On Windows, the executable might be droid.exe, but shell: true handles this\n  return \"droid\";\n}\n","import { isEnvEnabled } from \"../utils.ts\";\n\nexport function isExperimentSessionsEnabled(): boolean {\n  return isEnvEnabled(process.env.DROID_ACP_EXPERIMENT_SESSIONS);\n}\n\nexport function isDebugEnabled(): boolean {\n  return isEnvEnabled(process.env.DROID_DEBUG);\n}\n","import { createRequire } from \"node:module\";\n\nconst nodeRequire = createRequire(import.meta.url);\n\nfunction readPackageJson(): { name: string; version: string } {\n  const candidates = [\"../../package.json\", \"../package.json\", \"./package.json\"];\n  for (const specifier of candidates) {\n    try {\n      const pkg = nodeRequire(specifier) as { name?: unknown; version?: unknown };\n      const name = typeof pkg.name === \"string\" ? pkg.name : null;\n      const version = typeof pkg.version === \"string\" ? pkg.version : null;\n      if (name && version) return { name, version };\n    } catch {\n      // ignore and try next\n    }\n  }\n\n  const envName =\n    typeof process.env.npm_package_name === \"string\" ? process.env.npm_package_name : null;\n  const envVersion =\n    typeof process.env.npm_package_version === \"string\" ? process.env.npm_package_version : null;\n  return {\n    name: envName ?? \"droid-acp\",\n    version: envVersion ?? \"unknown\",\n  };\n}\n\nconst packageJson = readPackageJson();\n\nexport const packageInfo = {\n  name: packageJson.name,\n  version: packageJson.version,\n} as const;\n","import os from \"node:os\";\nimport path from \"node:path\";\nimport type { ToolCallLocation } from \"@agentclientprotocol/sdk\";\n\nexport function extractFilePathFromRawInput(rawInput: unknown): string | null {\n  if (!rawInput || typeof rawInput !== \"object\") return null;\n  const obj = rawInput as Record<string, unknown>;\n  const candidates: unknown[] = [obj.file_path, obj.filePath, obj.path];\n  for (const v of candidates) {\n    if (typeof v === \"string\" && v.trim().length > 0) return v.trim();\n  }\n  return null;\n}\n\nexport function resolvePermissionFilePath(\n  cwd: string,\n  filePath: string,\n): { absPath: string; label: string } {\n  const expanded = (() => {\n    const trimmed = filePath.trim();\n    if (trimmed === \"~\") return os.homedir();\n    if (trimmed.startsWith(\"~/\")) return path.join(os.homedir(), trimmed.slice(2));\n    return trimmed;\n  })();\n\n  const absPath = path.isAbsolute(expanded) ? expanded : path.resolve(cwd, expanded);\n  const label = absPath.startsWith(cwd + path.sep) ? path.relative(cwd, absPath) : absPath;\n  return { absPath, label };\n}\n\nexport function permissionLocationsFromRawInput(params: {\n  toolName: string;\n  rawInput: unknown;\n  cwd: string;\n}): ToolCallLocation[] | undefined {\n  const wantsLocation = new Set([\"Edit\", \"Write\", \"Read\", \"LS\", \"Grep\", \"Glob\", \"Move\", \"Delete\"]);\n  if (!wantsLocation.has(params.toolName)) return undefined;\n\n  const rawInputObj =\n    params.rawInput && typeof params.rawInput === \"object\"\n      ? (params.rawInput as Record<string, unknown>)\n      : null;\n  if (!rawInputObj) return undefined;\n\n  const normalize = (v: unknown): string | null => {\n    if (typeof v !== \"string\") return null;\n    const trimmed = v.trim();\n    return trimmed.length > 0 ? trimmed : null;\n  };\n\n  const addLocation = (acc: ToolCallLocation[], value: string | null) => {\n    if (!value) return;\n    const resolved = resolvePermissionFilePath(params.cwd, value);\n    if (acc.some((l) => l.path === resolved.label)) return;\n    acc.push({ path: resolved.label });\n  };\n\n  const locations: ToolCallLocation[] = [];\n\n  if (params.toolName === \"Move\") {\n    addLocation(\n      locations,\n      normalize(\n        rawInputObj.from_path ?? rawInputObj.fromPath ?? rawInputObj.source ?? rawInputObj.from,\n      ),\n    );\n    addLocation(\n      locations,\n      normalize(\n        rawInputObj.to_path ?? rawInputObj.toPath ?? rawInputObj.destination ?? rawInputObj.to,\n      ),\n    );\n  }\n\n  if (locations.length === 0) {\n    addLocation(locations, extractFilePathFromRawInput(rawInputObj));\n  }\n\n  return locations.length > 0 ? locations : undefined;\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport type { ToolCallContent } from \"@agentclientprotocol/sdk\";\nimport { extractFilePathFromRawInput, resolvePermissionFilePath } from \"./paths.ts\";\n\nexport async function buildPermissionDiffContent(params: {\n  toolName: string;\n  rawInput: unknown;\n  cwd: string;\n}): Promise<ToolCallContent | null> {\n  const rawInputObj =\n    params.rawInput && typeof params.rawInput === \"object\"\n      ? (params.rawInput as Record<string, unknown>)\n      : null;\n  if (!rawInputObj) return null;\n\n  const filePath = extractFilePathFromRawInput(rawInputObj);\n  if (!filePath) return null;\n  const resolved = resolvePermissionFilePath(params.cwd, filePath);\n\n  const MAX_FILE_BYTES = 256 * 1024;\n\n  if (params.toolName === \"Edit\") {\n    const oldStr =\n      typeof rawInputObj.old_str === \"string\"\n        ? rawInputObj.old_str\n        : typeof rawInputObj.oldStr === \"string\"\n          ? rawInputObj.oldStr\n          : null;\n    const newStr =\n      typeof rawInputObj.new_str === \"string\"\n        ? rawInputObj.new_str\n        : typeof rawInputObj.newStr === \"string\"\n          ? rawInputObj.newStr\n          : null;\n    if (oldStr === null || newStr === null) return null;\n\n    // Best-effort: show a full-file diff when we can apply a single unambiguous replacement.\n    try {\n      const fileStat = await stat(resolved.absPath);\n      if (fileStat.isFile() && fileStat.size <= MAX_FILE_BYTES && oldStr.length > 0) {\n        const oldText = await readFile(resolved.absPath, \"utf8\");\n        const occurrences = oldText.split(oldStr).length - 1;\n        if (occurrences === 1) {\n          const newText = oldText.replace(oldStr, newStr);\n          return {\n            type: \"diff\",\n            path: resolved.label,\n            oldText,\n            newText,\n          };\n        }\n      }\n    } catch {\n      // Fall back to a snippet diff below.\n    }\n\n    // Fallback: show a focused snippet diff of the replacement only.\n    return {\n      type: \"diff\",\n      path: resolved.label,\n      oldText: oldStr,\n      newText: newStr,\n    };\n  }\n\n  if (params.toolName === \"Write\") {\n    const newText =\n      typeof rawInputObj.content === \"string\"\n        ? rawInputObj.content\n        : typeof rawInputObj.text === \"string\"\n          ? rawInputObj.text\n          : null;\n    if (newText === null) return null;\n\n    let oldText: string | null = null;\n    try {\n      const fileStat = await stat(resolved.absPath);\n      if (fileStat.isFile() && fileStat.size <= MAX_FILE_BYTES) {\n        oldText = await readFile(resolved.absPath, \"utf8\");\n      }\n    } catch {\n      oldText = null;\n    }\n\n    return {\n      type: \"diff\",\n      path: resolved.label,\n      oldText,\n      newText,\n    };\n  }\n\n  return null;\n}\n","export function sanitizeHistoryTextForDisplay(text: string): string {\n  let out = text;\n  out = out.replace(/<system-reminder>[\\s\\S]*?(<\\/system-reminder>|$)/gi, \"\");\n  out = out.replace(/<context[^>]*>[\\s\\S]*?(<\\/context>|$)/gi, \"\");\n  out = out.replace(/<\\/?context[^>]*>/gi, \"\");\n  out = out.replace(/<\\/?system-reminder>/gi, \"\");\n  out = out.replace(/\\r\\n/g, \"\\n\");\n  out = out.replace(/\\n{3,}/g, \"\\n\\n\");\n  return out.trim();\n}\n\nexport function sanitizeSessionTitle(title: string): string {\n  let out = title;\n  out = out.replace(/<system-reminder>[\\s\\S]*?(<\\/system-reminder>|$)/gi, \"\");\n  out = out.replace(/<\\/?context[^>]*>/gi, \"\");\n  out = out.replace(/<\\/?system-reminder>/gi, \"\");\n  out = out.replace(/^\\s*(User|Assistant)\\s*:\\s*/i, \"\");\n  out = out.replace(/\\s+/g, \" \").trim();\n  return out;\n}\n\nexport function formatTimestampForDisplay(isoTimestamp: string): string {\n  const d = new Date(isoTimestamp);\n  if (Number.isNaN(d.getTime())) return isoTimestamp;\n  const pad2 = (v: number) => String(v).padStart(2, \"0\");\n  return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;\n}\n\nexport function safeCodeFenceContent(text: string): string {\n  return text.replace(/```/g, \"``\\u200b`\");\n}\n\nexport function normalizeBase64DataUrl(\n  data: string,\n  fallbackMimeType: string,\n): { mimeType: string; base64: string } {\n  const trimmed = data.trim();\n  const match = trimmed.match(/^data:([^;,]+);base64,(.*)$/s);\n  if (match) {\n    const mimeType = match[1]?.trim() || fallbackMimeType;\n    const base64 = match[2]?.trim().replace(/\\s+/g, \"\");\n    return { mimeType, base64 };\n  }\n\n  return { mimeType: fallbackMimeType, base64: trimmed.replace(/\\s+/g, \"\") };\n}\n","import { isEnvEnabled } from \"../../utils.ts\";\nimport { safeCodeFenceContent } from \"../text.ts\";\nimport { extractFilePathFromRawInput, resolvePermissionFilePath } from \"./paths.ts\";\n\nexport function toolCallRawInputForClient(rawInput: unknown): unknown {\n  return isEnvEnabled(process.env.DROID_DEBUG) ? rawInput : undefined;\n}\n\nexport function formatPermissionDetailsMarkdown(params: {\n  toolName: string;\n  riskLevel: \"low\" | \"medium\" | \"high\";\n  rawInput: unknown;\n}): string {\n  const lines: string[] = [\n    \"**Details**\",\n    `- Tool: \\`${params.toolName}\\``,\n    `- Risk: \\`${params.riskLevel}\\``,\n  ];\n\n  const rawInputObj =\n    params.rawInput && typeof params.rawInput === \"object\"\n      ? (params.rawInput as Record<string, unknown>)\n      : null;\n\n  const command =\n    rawInputObj && typeof rawInputObj.command === \"string\" ? rawInputObj.command.trim() : null;\n\n  if (command && command.length > 0) {\n    lines.push(\"\", \"**Command**\", \"```bash\", safeCodeFenceContent(command), \"```\");\n    return lines.join(\"\\n\");\n  }\n\n  const inputSummary: string[] = [];\n  const pushField = (label: string, value: unknown) => {\n    if (typeof value !== \"string\") return;\n    const trimmed = value.trim();\n    if (!trimmed) return;\n    inputSummary.push(`- ${label}: \\`${trimmed}\\``);\n  };\n\n  if (rawInputObj) {\n    pushField(\"From\", rawInputObj.from_path ?? rawInputObj.fromPath ?? rawInputObj.from);\n    pushField(\"To\", rawInputObj.to_path ?? rawInputObj.toPath ?? rawInputObj.to);\n    pushField(\"Path\", rawInputObj.path);\n    pushField(\"File\", rawInputObj.file);\n    pushField(\"File path\", rawInputObj.file_path ?? rawInputObj.filePath);\n    pushField(\"URL\", rawInputObj.url);\n    pushField(\"Query\", rawInputObj.query);\n    pushField(\"Pattern\", rawInputObj.pattern);\n    pushField(\"Glob\", rawInputObj.glob);\n  }\n\n  if (inputSummary.length > 0) {\n    lines.push(\"\", \"**Input (summary)**\", ...inputSummary);\n  }\n\n  const shouldShowRawInput = isEnvEnabled(process.env.DROID_DEBUG);\n\n  if (shouldShowRawInput) {\n    const scrubbed = (() => {\n      if (!rawInputObj) return params.rawInput;\n      const out: Record<string, unknown> = {};\n      for (const [k, v] of Object.entries(rawInputObj)) {\n        if (typeof v === \"string\" && v.length > 1200) {\n          out[k] = `${v.slice(0, 1200)}… (truncated, ${v.length} chars)`;\n          continue;\n        }\n        out[k] = v;\n      }\n      return out;\n    })();\n\n    let json: string | null = null;\n    try {\n      json = JSON.stringify(scrubbed, null, 2);\n    } catch {\n      json = null;\n    }\n\n    if (json && json !== \"{}\") {\n      const maxChars = 12_000;\n      const truncated = json.length > maxChars ? `${json.slice(0, maxChars)}\\n… (truncated)` : json;\n      lines.push(\"\", \"**Input (raw)**\", \"```json\", safeCodeFenceContent(truncated), \"```\");\n    }\n  }\n\n  return lines.join(\"\\n\");\n}\n\nexport function formatPermissionToolCallTitle(params: {\n  stage?: \"permission\" | \"run\";\n  toolName: string;\n  riskLevel: \"low\" | \"medium\" | \"high\";\n  rawInput: unknown;\n  cwd: string;\n}): string {\n  const stage = params.stage ?? \"permission\";\n  const rawInputObj =\n    params.rawInput && typeof params.rawInput === \"object\"\n      ? (params.rawInput as Record<string, unknown>)\n      : null;\n\n  const filePath = extractFilePathFromRawInput(rawInputObj);\n  const resolvedPath = filePath ? resolvePermissionFilePath(params.cwd, filePath).label : null;\n\n  if (params.toolName === \"Bash\") {\n    const command =\n      rawInputObj && typeof rawInputObj.command === \"string\" ? rawInputObj.command.trim() : null;\n    const firstLine = command ? (command.split(/\\r?\\n/, 1)[0]?.trim() ?? \"\") : \"\";\n    const summary = firstLine.length > 0 ? firstLine : \"command\";\n    return stage === \"permission\" ? `Run (${params.riskLevel}): ${summary}` : `Run: ${summary}`;\n  }\n\n  if (params.toolName === \"Fetch\") {\n    const url = rawInputObj && typeof rawInputObj.url === \"string\" ? rawInputObj.url.trim() : null;\n    if (url && url.length > 0) return `Fetch: ${url}`;\n  }\n\n  if (resolvedPath) {\n    const prefix = params.toolName === \"LS\" ? \"List\" : params.toolName;\n    return stage === \"permission\"\n      ? `${prefix} (${params.riskLevel}): ${resolvedPath}`\n      : `${prefix}: ${resolvedPath}`;\n  }\n\n  if (params.toolName === \"Grep\" || params.toolName === \"Glob\") {\n    const pattern =\n      rawInputObj && typeof rawInputObj.pattern === \"string\" ? rawInputObj.pattern.trim() : null;\n    if (pattern && pattern.length > 0) {\n      return stage === \"permission\"\n        ? `${params.toolName} (${params.riskLevel}): ${pattern}`\n        : `${params.toolName}: ${pattern}`;\n    }\n  }\n\n  return stage === \"permission\"\n    ? `Permission required: ${params.toolName} (${params.riskLevel})`\n    : `Running ${params.toolName}`;\n}\n","import type { ToolCallContent } from \"@agentclientprotocol/sdk\";\nimport { buildPermissionDiffContent } from \"./diff.ts\";\nimport { formatPermissionDetailsMarkdown } from \"./format.ts\";\n\nexport async function buildPermissionToolCallContent(params: {\n  toolName: string;\n  riskLevel: \"low\" | \"medium\" | \"high\";\n  rawInput: unknown;\n  cwd: string;\n  planMarkdown: string | null;\n}): Promise<ToolCallContent[]> {\n  if (params.toolName === \"ExitSpecMode\" && params.planMarkdown) {\n    return [\n      {\n        type: \"content\",\n        content: { type: \"text\", text: params.planMarkdown },\n      },\n    ];\n  }\n\n  const content: ToolCallContent[] = [];\n  const diff = await buildPermissionDiffContent({\n    toolName: params.toolName,\n    rawInput: params.rawInput,\n    cwd: params.cwd,\n  });\n  if (diff) content.push(diff);\n\n  content.push({\n    type: \"content\",\n    content: {\n      type: \"text\",\n      text: formatPermissionDetailsMarkdown({\n        toolName: params.toolName,\n        riskLevel: params.riskLevel,\n        rawInput: params.rawInput,\n      }),\n    },\n  });\n\n  return content;\n}\n","export function extractSpecTitleAndPlan(rawInput: unknown): {\n  title: string | null;\n  plan: string | null;\n} {\n  if (!rawInput || typeof rawInput !== \"object\") return { title: null, plan: null };\n\n  const obj = rawInput as Record<string, unknown>;\n\n  const title =\n    typeof obj.title === \"string\"\n      ? obj.title\n      : typeof obj.specTitle === \"string\"\n        ? obj.specTitle\n        : typeof obj.name === \"string\"\n          ? obj.name\n          : null;\n\n  const candidates: unknown[] = [\n    obj.plan,\n    (obj as { planMarkdown?: unknown }).planMarkdown,\n    (obj as { markdown?: unknown }).markdown,\n    (obj as { content?: unknown }).content,\n    (obj as { text?: unknown }).text,\n  ];\n\n  const toMarkdown = (value: unknown): string | null => {\n    if (typeof value === \"string\") return value;\n    if (Array.isArray(value)) {\n      const parts = value.map((v) => (typeof v === \"string\" ? v : JSON.stringify(v, null, 2)));\n      const joined = parts.join(\"\\n\").trim();\n      return joined.length > 0 ? joined : null;\n    }\n    if (value && typeof value === \"object\") {\n      const v = value as Record<string, unknown>;\n      if (typeof v.markdown === \"string\") return v.markdown;\n      if (typeof v.text === \"string\") return v.text;\n      const json = JSON.stringify(v, null, 2);\n      return json && json !== \"{}\" ? json : null;\n    }\n    return null;\n  };\n\n  for (const c of candidates) {\n    const plan = toMarkdown(c);\n    if (plan) return { title, plan };\n  }\n\n  return { title, plan: null };\n}\n\nexport function planEntriesFromMarkdown(planMarkdown: string): Array<{\n  content: string;\n  status: \"pending\" | \"in_progress\" | \"completed\";\n  priority: \"medium\";\n}> {\n  const entries: Array<{\n    content: string;\n    status: \"pending\" | \"in_progress\" | \"completed\";\n    priority: \"medium\";\n  }> = [];\n  let inCodeFence = false;\n\n  for (const rawLine of planMarkdown.split(\"\\n\")) {\n    const line = rawLine.trim();\n    if (line.startsWith(\"```\")) {\n      inCodeFence = !inCodeFence;\n      continue;\n    }\n    if (inCodeFence) continue;\n    if (!line) continue;\n\n    const checkbox = line.match(/^- \\[([ xX~])\\]\\s+(.*)$/);\n    if (checkbox) {\n      const [, mark, content] = checkbox;\n      const status =\n        mark === \"x\" || mark === \"X\"\n          ? (\"completed\" as const)\n          : mark === \"~\"\n            ? (\"in_progress\" as const)\n            : (\"pending\" as const);\n      entries.push({ content, status, priority: \"medium\" as const });\n      continue;\n    }\n\n    const bullet = line.match(/^[-*]\\s+(.*)$/);\n    if (bullet) {\n      entries.push({\n        content: bullet[1],\n        status: \"pending\",\n        priority: \"medium\",\n      });\n      continue;\n    }\n\n    const numbered = line.match(/^\\d+\\.\\s+(.*)$/);\n    if (numbered) {\n      entries.push({\n        content: numbered[1],\n        status: \"pending\",\n        priority: \"medium\",\n      });\n      continue;\n    }\n  }\n\n  return entries.filter((e) => e.content.length > 0);\n}\n\nexport function extractPlanChoices(planMarkdown: string): Array<{ id: string; title: string }> {\n  const explicitChoices: Array<{ id: string; title: string }> = [];\n  const looseChoices: Array<{ id: string; title: string }> = [];\n  const seenExplicit = new Set<string>();\n  const seenLoose = new Set<string>();\n\n  for (const rawLine of planMarkdown.split(\"\\n\")) {\n    const line = rawLine.trim();\n    if (!line) continue;\n\n    const stripped = line\n      .replace(/^>\\s+/, \"\")\n      .replace(/^#+\\s*/, \"\")\n      .replace(/^[-*]\\s+/, \"\")\n      .trim()\n      .replace(/^[*_`]+/, \"\")\n      .trim();\n\n    const explicit = stripped.match(/^(?:Option)\\s*([A-Z])\\s*[：:–—.)-]\\s*(.+)$/i);\n    if (explicit) {\n      const id = explicit[1].toUpperCase();\n      if (seenExplicit.has(id)) continue;\n      seenExplicit.add(id);\n\n      const title = explicit[2].trim();\n      explicitChoices.push({ id, title });\n      continue;\n    }\n\n    // Looser fallback: allow \"A: ...\" / \"B) ...\" style lines (only if we find multiple).\n    const loose = stripped.match(/^([A-F])\\s*[：:–—.)-]\\s*(.+)$/);\n    if (!loose) continue;\n\n    const id = loose[1].toUpperCase();\n    if (seenLoose.has(id)) continue;\n    seenLoose.add(id);\n\n    const title = loose[2].trim();\n    looseChoices.push({ id, title });\n  }\n\n  if (explicitChoices.length > 0) return explicitChoices;\n  if (looseChoices.length >= 2) return looseChoices;\n  return [];\n}\n","import type { ToolKind } from \"@agentclientprotocol/sdk\";\n\nexport function toolKindFromToolName(toolName: string): ToolKind {\n  switch (toolName) {\n    case \"Read\":\n    case \"LS\":\n      return \"read\";\n    case \"Grep\":\n    case \"Glob\":\n      return \"search\";\n    case \"Edit\":\n    case \"Write\":\n      return \"edit\";\n    case \"Move\":\n      return \"move\";\n    case \"Delete\":\n      return \"delete\";\n    case \"Bash\":\n      return \"execute\";\n    case \"Fetch\":\n      return \"fetch\";\n    default:\n      return \"other\";\n  }\n}\n","import type { AcpModeId, DroidAutonomyLevel } from \"../types.ts\";\n\n// Mirrors Droid TUI context indicator (see bundled CLI: N_B / L93)\nexport const DROID_CONTEXT_INDICATOR_MIN_TOKENS = 11_000;\nexport const DROID_CONTEXT_INDICATOR_MAX_TOKENS = 300_000;\nexport const DROID_CONTEXT_INDICATOR_MAX_TOKENS_ANTHROPIC = 200_000;\n\nexport const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\nexport const ACP_MODE_TO_DROID_AUTONOMY: Record<AcpModeId, DroidAutonomyLevel> = {\n  off: \"normal\",\n  low: \"auto-low\",\n  medium: \"auto-medium\",\n  high: \"auto-high\",\n  spec: \"spec\",\n};\n\nexport function droidAutonomyToAcpModeId(value: string): AcpModeId | null {\n  switch (value) {\n    case \"normal\":\n      return \"off\";\n    case \"auto-low\":\n      return \"low\";\n    case \"auto-medium\":\n      return \"medium\";\n    case \"auto-high\":\n      return \"high\";\n    case \"spec\":\n      return \"spec\";\n    // legacy values\n    case \"suggest\":\n      return \"low\";\n    case \"full\":\n      return \"high\";\n    default:\n      return null;\n  }\n}\n","import type { AgentSideConnection, ToolCallContent, ToolKind } from \"@agentclientprotocol/sdk\";\nimport type { DroidNotification } from \"../../types.ts\";\nimport type { Logger } from \"../../utils.ts\";\nimport { isEnvEnabled } from \"../../utils.ts\";\nimport { isDebugEnabled } from \"../flags.ts\";\nimport type { Session } from \"../session-types.ts\";\nimport { buildPermissionToolCallContent } from \"../permissions/content.ts\";\nimport { toolCallRawInputForClient, formatPermissionToolCallTitle } from \"../permissions/format.ts\";\nimport { permissionLocationsFromRawInput } from \"../permissions/paths.ts\";\nimport { extractSpecTitleAndPlan } from \"../permissions/spec.ts\";\nimport { toolKindFromToolName } from \"../permissions/tool-kind.ts\";\nimport { droidAutonomyToAcpModeId } from \"../constants.ts\";\n\nexport async function handleNotification(\n  ctx: { client: AgentSideConnection; logger: Logger },\n  session: Session,\n  n: DroidNotification,\n): Promise<void> {\n  ctx.logger.log(\"notification:\", n.type);\n\n  // If the user cancelled the current turn, avoid emitting stale tool calls / messages\n  // from the previous droid process. We'll restart and resume shortly.\n  if (session.cancelled) {\n    return;\n  }\n\n  switch (n.type) {\n    case \"settings_updated\": {\n      const autonomyLevel =\n        typeof n.settings.autonomyLevel === \"string\"\n          ? droidAutonomyToAcpModeId(n.settings.autonomyLevel)\n          : null;\n\n      if (autonomyLevel && autonomyLevel !== session.mode) {\n        session.mode = autonomyLevel;\n        await ctx.client.sessionUpdate({\n          sessionId: session.id,\n          update: {\n            sessionUpdate: \"current_mode_update\",\n            currentModeId: autonomyLevel,\n          },\n        });\n      }\n\n      if (typeof n.settings.modelId === \"string\") {\n        session.model = n.settings.modelId;\n      }\n      break;\n    }\n\n    case \"message\":\n      if (n.role === \"assistant\") {\n        const suppressAssistantOutput =\n          session.capture?.purpose === \"compress_summary\" && !isEnvEnabled(process.env.DROID_DEBUG);\n\n        if (session.capture && n.text) {\n          const capture = session.capture;\n          capture.buffer += n.text;\n\n          if (capture.purpose === \"compress_summary\" && /<\\/summary>/i.test(capture.buffer)) {\n            session.capture = null;\n            clearTimeout(capture.timeoutId);\n            if (capture.finalizeTimeoutId) clearTimeout(capture.finalizeTimeoutId);\n            capture.resolve(capture.buffer);\n          }\n        }\n\n        // Handle tool use in message\n        if (n.toolUse && isDebugEnabled()) {\n          ctx.logger.log(\"[ToolUse] name:\", n.toolUse.name, \"suppressed:\", suppressAssistantOutput);\n        }\n        if (n.toolUse && !suppressAssistantOutput) {\n          if (n.toolUse.name === \"TodoWrite\") {\n            const todosRaw = (n.toolUse.input as { todos?: unknown })?.todos;\n            if (isDebugEnabled()) {\n              ctx.logger.log(\"[TodoWrite] Received input:\", typeof todosRaw, todosRaw);\n            }\n\n            const toStatus = (status: unknown): \"pending\" | \"in_progress\" | \"completed\" => {\n              switch (status) {\n                case \"pending\":\n                case \"in_progress\":\n                case \"completed\":\n                  return status;\n                default:\n                  return \"pending\";\n              }\n            };\n\n            let entries: Array<{\n              content: string;\n              status: \"pending\" | \"in_progress\" | \"completed\";\n              priority: \"high\" | \"medium\" | \"low\";\n            }> = [];\n\n            if (typeof todosRaw === \"string\") {\n              // Parse string format: \"1. [status] content\" or \"- [status] content\"\n              const lines = todosRaw.split(\"\\n\").filter((line) => line.trim().length > 0);\n              entries = lines\n                .map((line) => {\n                  // Match patterns like \"1. [in_progress] Task\" or \"- [pending] Task\"\n                  const match = line.match(/^(?:\\d+\\.|-)?\\s*\\[(\\w+)\\]\\s*(.+)$/);\n                  if (match) {\n                    const [, statusStr, content] = match;\n                    return {\n                      content: content.trim(),\n                      status: toStatus(statusStr),\n                      priority: \"medium\" as const,\n                    };\n                  }\n                  return null;\n                })\n                .filter((e): e is NonNullable<typeof e> => e !== null && e.content.length > 0);\n            } else if (Array.isArray(todosRaw)) {\n              // Handle array format (legacy)\n              entries = todosRaw\n                .map((t) => {\n                  const todo = t as { content?: unknown; status?: unknown };\n                  return {\n                    content: typeof todo.content === \"string\" ? todo.content : \"\",\n                    status: toStatus(todo.status),\n                    priority: \"medium\" as const,\n                  };\n                })\n                .filter((e) => e.content.length > 0);\n            }\n\n            if (entries.length > 0) {\n              if (isDebugEnabled()) {\n                ctx.logger.log(\n                  \"[TodoWrite] Sending plan_update with\",\n                  entries.length,\n                  \"entries:\",\n                  entries,\n                );\n              }\n              await ctx.client.sessionUpdate({\n                sessionId: session.id,\n                update: {\n                  sessionUpdate: \"plan\",\n                  entries,\n                },\n              });\n            }\n            break;\n          }\n\n          const toolCallId = n.toolUse.id;\n          const isExitSpecMode = n.toolUse.name === \"ExitSpecMode\";\n          const existingStatus = session.toolCallStatus.get(toolCallId);\n          if (existingStatus !== \"completed\" && existingStatus !== \"failed\") {\n            if (!session.activeToolCallIds.has(toolCallId)) {\n              session.activeToolCallIds.add(toolCallId);\n              session.toolNames.set(toolCallId, n.toolUse.name);\n\n              const initialStatus = isExitSpecMode ? \"pending\" : \"in_progress\";\n              session.toolCallStatus.set(toolCallId, initialStatus);\n\n              const toolName = n.toolUse.name;\n              const rawInput = n.toolUse.input;\n\n              const isReadOnlyTool =\n                toolName === \"Read\" ||\n                toolName === \"Grep\" ||\n                toolName === \"Glob\" ||\n                toolName === \"LS\";\n              const riskLevelRaw = (rawInput as { riskLevel?: unknown } | null | undefined)\n                ?.riskLevel;\n              const riskLevel =\n                riskLevelRaw === \"low\" || riskLevelRaw === \"medium\" || riskLevelRaw === \"high\"\n                  ? riskLevelRaw\n                  : isReadOnlyTool\n                    ? \"low\"\n                    : \"medium\";\n\n              const toolCallKind: ToolKind = isExitSpecMode\n                ? \"switch_mode\"\n                : toolKindFromToolName(toolName);\n              const toolCallLocations = permissionLocationsFromRawInput({\n                toolName,\n                rawInput,\n                cwd: session.cwd,\n              });\n\n              const spec = isExitSpecMode ? extractSpecTitleAndPlan(rawInput) : null;\n              const toolCallTitle = isExitSpecMode\n                ? spec?.title\n                  ? `Exit spec mode: ${spec.title}`\n                  : \"Exit spec mode\"\n                : formatPermissionToolCallTitle({\n                    stage: \"run\",\n                    toolName,\n                    riskLevel,\n                    rawInput,\n                    cwd: session.cwd,\n                  });\n\n              const toolCallContent = await buildPermissionToolCallContent({\n                toolName,\n                riskLevel,\n                rawInput,\n                cwd: session.cwd,\n                planMarkdown: isExitSpecMode ? (spec?.plan ?? null) : null,\n              });\n\n              session.toolCallRawInputById.set(toolCallId, rawInput);\n              session.toolCallContentById.set(toolCallId, toolCallContent);\n\n              await ctx.client.sessionUpdate({\n                sessionId: session.id,\n                update: {\n                  sessionUpdate: \"tool_call\",\n                  toolCallId,\n                  title: toolCallTitle,\n                  kind: toolCallKind,\n                  locations: toolCallLocations,\n                  status: initialStatus,\n                  rawInput: toolCallRawInputForClient(rawInput),\n                  content: toolCallContent,\n                },\n              });\n            } else {\n              const status = session.toolCallStatus.get(toolCallId);\n              if (status !== \"completed\" && status !== \"failed\" && status !== \"pending\") {\n                session.toolCallStatus.set(toolCallId, \"in_progress\");\n                await ctx.client.sessionUpdate({\n                  sessionId: session.id,\n                  update: {\n                    sessionUpdate: \"tool_call_update\",\n                    toolCallId,\n                    status: \"in_progress\",\n                  },\n                });\n              }\n            }\n          }\n        }\n\n        // Handle text content\n        if (n.text && !suppressAssistantOutput) {\n          await ctx.client.sessionUpdate({\n            sessionId: session.id,\n            update: {\n              sessionUpdate: \"agent_message_chunk\",\n              content: { type: \"text\", text: n.text },\n            },\n          });\n        }\n      }\n      break;\n\n    case \"tool_result\":\n      if (!session.activeToolCallIds.has(n.toolUseId)) {\n        session.activeToolCallIds.add(n.toolUseId);\n        const name = session.toolNames.get(n.toolUseId) ?? \"Tool\";\n        await ctx.client.sessionUpdate({\n          sessionId: session.id,\n          update: {\n            sessionUpdate: \"tool_call\",\n            toolCallId: n.toolUseId,\n            title: `Running ${name}`,\n            status: \"in_progress\",\n          },\n        });\n      }\n\n      const finalStatus = n.isError ? (\"failed\" as const) : (\"completed\" as const);\n\n      const preserved = (session.toolCallContentById.get(n.toolUseId) ?? []).filter(\n        (c) => c.type === \"diff\" || c.type === \"terminal\",\n      );\n      const merged: ToolCallContent[] = [\n        ...preserved,\n        {\n          type: \"content\",\n          content: {\n            type: \"text\",\n            text: n.content,\n          },\n        },\n      ];\n      session.toolCallContentById.set(n.toolUseId, merged);\n\n      // Send the tool response content + completion status\n      await ctx.client.sessionUpdate({\n        sessionId: session.id,\n        update: {\n          sessionUpdate: \"tool_call_update\",\n          toolCallId: n.toolUseId,\n          content: merged,\n          rawOutput: n.content,\n          status: finalStatus,\n        },\n      });\n\n      session.toolCallStatus.set(n.toolUseId, finalStatus);\n      session.activeToolCallIds.delete(n.toolUseId);\n      break;\n\n    case \"error\":\n      if (session.capture) {\n        const capture = session.capture;\n        session.capture = null;\n        clearTimeout(capture.timeoutId);\n        if (capture.finalizeTimeoutId) clearTimeout(capture.finalizeTimeoutId);\n        capture.reject(new Error(n.message));\n      }\n      await ctx.client.sessionUpdate({\n        sessionId: session.id,\n        update: {\n          sessionUpdate: \"agent_message_chunk\",\n          content: { type: \"text\", text: `Error: ${n.message}` },\n        },\n      });\n      if (session.promptResolve) {\n        session.promptResolve({ stopReason: \"end_turn\" });\n        session.promptResolve = null;\n      }\n      break;\n\n    case \"complete\":\n      if (session.capture) {\n        const capture = session.capture;\n        if (!capture.finalizeTimeoutId) {\n          capture.finalizeTimeoutId = setTimeout(() => {\n            if (session.capture !== capture) return;\n            session.capture = null;\n            clearTimeout(capture.timeoutId);\n            capture.resolve(capture.buffer);\n          }, 1000);\n        }\n        break;\n      }\n      if (session.promptResolve) {\n        session.promptResolve({ stopReason: \"end_turn\" });\n        session.promptResolve = null;\n      }\n      break;\n  }\n}\n","import type { PermissionOption } from \"@agentclientprotocol/sdk\";\nimport type { AcpModeId, DroidPermissionOption, PermissionRequest } from \"../../types.ts\";\n\nexport function extractDroidPermissionOptions(\n  params: PermissionRequest,\n): DroidPermissionOption[] | null {\n  const candidates: unknown[] = [];\n\n  const maybePush = (value: unknown) => {\n    if (Array.isArray(value)) candidates.push(value);\n  };\n\n  maybePush((params as unknown as { options?: unknown }).options);\n\n  const toolUses = (params as unknown as { toolUses?: unknown }).toolUses;\n  if (Array.isArray(toolUses)) {\n    for (const toolUse of toolUses) {\n      if (!toolUse || typeof toolUse !== \"object\") continue;\n      const tu = toolUse as Record<string, unknown>;\n      maybePush(tu.options);\n      const details = tu.details;\n      if (details && typeof details === \"object\") {\n        maybePush((details as Record<string, unknown>).options);\n      }\n    }\n  }\n\n  for (const candidate of candidates) {\n    const normalized = (candidate as unknown[])\n      .map((opt) => opt as { value?: unknown; label?: unknown })\n      .map((opt) => ({\n        value: typeof opt.value === \"string\" ? opt.value : null,\n        label: typeof opt.label === \"string\" ? opt.label : null,\n      }))\n      .filter((opt): opt is { value: string; label: string } => !!opt.value && !!opt.label)\n      .map((opt) => ({ value: opt.value, label: opt.label }));\n\n    if (normalized.length > 0) return normalized;\n  }\n\n  return null;\n}\n\nexport function mapExitSpecModeSelection(optionId: string): {\n  nextMode: AcpModeId | null;\n  droidSelectedOption: string;\n} {\n  // Preferred: optionId equals ACP mode id.\n  switch (optionId) {\n    case \"off\":\n      return { nextMode: \"off\", droidSelectedOption: \"proceed_once\" };\n    case \"low\":\n      return { nextMode: \"low\", droidSelectedOption: \"proceed_auto_run_low\" };\n    case \"medium\":\n      return { nextMode: \"medium\", droidSelectedOption: \"proceed_auto_run_medium\" };\n    case \"high\":\n      return { nextMode: \"high\", droidSelectedOption: \"proceed_auto_run_high\" };\n    case \"spec\":\n      return { nextMode: \"spec\", droidSelectedOption: \"cancel\" };\n    default:\n      break;\n  }\n\n  // Back-compat: accept Droid option ids directly (or other clients returning them).\n  switch (optionId) {\n    case \"proceed_once\":\n      return { nextMode: \"off\", droidSelectedOption: \"proceed_once\" };\n    case \"proceed_auto_run_low\":\n      return { nextMode: \"low\", droidSelectedOption: \"proceed_auto_run_low\" };\n    case \"proceed_auto_run_medium\":\n      return { nextMode: \"medium\", droidSelectedOption: \"proceed_auto_run_medium\" };\n    case \"proceed_auto_run_high\":\n      return { nextMode: \"high\", droidSelectedOption: \"proceed_auto_run_high\" };\n    case \"cancel\":\n      return { nextMode: \"spec\", droidSelectedOption: \"cancel\" };\n    default:\n      return { nextMode: null, droidSelectedOption: optionId };\n  }\n}\n\nexport function specApprovalOptions(\n  droidOptions: DroidPermissionOption[] | null,\n): PermissionOption[] {\n  const has = (value: string): boolean => droidOptions?.some((o) => o.value === value) === true;\n\n  const candidates: Array<{\n    modeId: AcpModeId;\n    droidValue: string;\n    name: string;\n    kind: PermissionOption[\"kind\"];\n  }> = [\n    {\n      modeId: \"off\",\n      droidValue: \"proceed_once\",\n      name: \"Proceed (manual)\",\n      kind: \"allow_once\",\n    },\n    {\n      modeId: \"low\",\n      droidValue: \"proceed_auto_run_low\",\n      name: \"Proceed (low)\",\n      kind: \"allow_once\",\n    },\n    {\n      modeId: \"medium\",\n      droidValue: \"proceed_auto_run_medium\",\n      name: \"Proceed (medium)\",\n      kind: \"allow_once\",\n    },\n    {\n      modeId: \"high\",\n      droidValue: \"proceed_auto_run_high\",\n      name: \"Proceed (high)\",\n      kind: \"allow_once\",\n    },\n    {\n      modeId: \"spec\",\n      droidValue: \"cancel\",\n      name: \"Stay in Spec\",\n      kind: \"reject_once\",\n    },\n  ];\n\n  const options = candidates\n    .filter((c) => !droidOptions || has(c.droidValue))\n    .map((c) => ({ optionId: c.modeId, name: c.name, kind: c.kind }));\n\n  if (options.length > 0) return options;\n\n  // Fallback: expose raw Droid options if we can't match.\n  return (\n    droidOptions?.map((o) => ({\n      optionId: o.value,\n      name: o.label,\n      kind: \"allow_once\" as const,\n    })) ?? [\n      { optionId: \"off\", name: \"Proceed (manual approvals)\", kind: \"allow_once\" },\n      { optionId: \"spec\", name: \"No, keep iterating (stay in Spec)\", kind: \"reject_once\" },\n    ]\n  );\n}\n","import type { PermissionOption } from \"@agentclientprotocol/sdk\";\nimport type { DroidPermissionOption } from \"../../types.ts\";\nimport { specApprovalOptions } from \"./options.ts\";\n\nexport function permissionKindFromOptionValue(value: string): PermissionOption[\"kind\"] {\n  switch (value) {\n    case \"proceed_once\":\n    case \"proceed_edit\":\n      return \"allow_once\";\n    case \"proceed_auto_run_low\":\n    case \"proceed_auto_run_medium\":\n    case \"proceed_auto_run_high\":\n    case \"proceed_auto_run\":\n    case \"proceed_always\":\n      return \"allow_always\";\n    case \"cancel\":\n      return \"reject_once\";\n    default:\n      return \"allow_once\";\n  }\n}\n\nexport function toAcpPermissionOption(opt: DroidPermissionOption): PermissionOption {\n  const value = opt.value;\n  let name = opt.label;\n  switch (value) {\n    case \"proceed_once\":\n      name = \"Allow once\";\n      break;\n    case \"proceed_always\": {\n      const labelLower = opt.label.toLowerCase();\n      if (labelLower.includes(\"low\")) {\n        name = \"Always (low)\";\n        break;\n      }\n      if (labelLower.includes(\"medium\")) {\n        name = \"Always (medium)\";\n        break;\n      }\n      if (labelLower.includes(\"high\")) {\n        name = \"Always (high)\";\n        break;\n      }\n      name = \"Always\";\n      break;\n    }\n    case \"proceed_auto_run_low\":\n      name = \"Auto-run (low)\";\n      break;\n    case \"proceed_auto_run_medium\":\n      name = \"Auto-run (medium)\";\n      break;\n    case \"proceed_auto_run_high\":\n      name = \"Auto-run (high)\";\n      break;\n    default:\n      break;\n  }\n  return {\n    optionId: value,\n    name,\n    kind: permissionKindFromOptionValue(value),\n  };\n}\n\nexport function buildAcpPermissionOptions(params: {\n  toolName: string;\n  droidOptions: DroidPermissionOption[] | null;\n}): PermissionOption[] {\n  if (params.toolName === \"ExitSpecMode\") {\n    return specApprovalOptions(params.droidOptions);\n  }\n  if (params.droidOptions) {\n    return params.droidOptions.map(toAcpPermissionOption);\n  }\n  return [\n    { optionId: \"proceed_once\", name: \"Allow once\", kind: \"allow_once\" },\n    { optionId: \"cancel\", name: \"Reject\", kind: \"reject_once\" },\n  ];\n}\n","import type { AcpModeId } from \"../../types.ts\";\nimport type { Logger } from \"../../utils.ts\";\n\nexport function computeAutoDecision(params: {\n  toolName: string;\n  sessionMode: AcpModeId;\n  riskLevel: \"low\" | \"medium\" | \"high\";\n  logger: Logger;\n}): string | null {\n  if (params.toolName === \"ExitSpecMode\") {\n    // Exiting spec triggers execution; always ask the user which mode to proceed with.\n    params.logger.log(\"Prompting (ExitSpecMode)\");\n    return null;\n  }\n\n  if (params.sessionMode === \"high\") {\n    params.logger.log(\"Auto-approved (high mode)\");\n    return \"proceed_always\";\n  }\n\n  if (params.sessionMode === \"medium\") {\n    const decision = params.riskLevel === \"high\" ? null : \"proceed_once\";\n    params.logger.log(\n      decision ? \"Auto-approved (medium mode, low/med risk)\" : \"Prompting (medium mode)\",\n    );\n    return decision;\n  }\n\n  if (params.sessionMode === \"low\") {\n    const decision = params.riskLevel === \"low\" ? \"proceed_once\" : null;\n    params.logger.log(decision ? \"Auto-approved (low mode, low risk)\" : \"Prompting (low mode)\");\n    return decision;\n  }\n\n  if (params.sessionMode === \"spec\") {\n    // Spec mode: allow low-risk operations (read/search) without prompting.\n    if (params.riskLevel === \"low\") {\n      params.logger.log(\"Auto-approved (spec mode, low risk)\");\n      return \"proceed_once\";\n    }\n    params.logger.log(\"Auto-rejected (spec mode, medium/high risk)\");\n    return \"cancel\";\n  }\n\n  // off mode: ask the user (no auto-approval)\n  params.logger.log(\"Prompting (off mode)\");\n  return null;\n}\n","import type { AgentSideConnection } from \"@agentclientprotocol/sdk\";\nimport type { Session } from \"../session-types.ts\";\nimport { toolCallRawInputForClient } from \"./format.ts\";\nimport { extractPlanChoices, planEntriesFromMarkdown } from \"./spec.ts\";\n\nexport async function maybeHandleExitSpecModePlanChoice(\n  ctx: {\n    client: AgentSideConnection;\n    sendAgentMessage: (session: Session, text: string) => Promise<void>;\n  },\n  session: Session,\n  params: {\n    toolCallId: string;\n    planTitle: string | null;\n    planMarkdown: string;\n  },\n): Promise<{ selectedOption: string } | null> {\n  const signature = `${params.planTitle ?? \"\"}\\n${params.planMarkdown}`;\n  if (session.specChoicePromptSignature !== signature) {\n    session.specChoicePromptSignature = signature;\n    session.specChoice = null;\n  }\n\n  if (session.specPlanDetailsSignature !== signature) {\n    session.specPlanDetailsSignature = signature;\n    session.specPlanDetailsToolCallId = `${params.toolCallId}:plan_details`;\n    await ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"tool_call\",\n        toolCallId: session.specPlanDetailsToolCallId,\n        title: params.planTitle ? `Plan details: ${params.planTitle}` : \"Plan details\",\n        kind: \"think\",\n        status: \"completed\",\n        content: [\n          {\n            type: \"content\",\n            content: { type: \"text\", text: params.planMarkdown },\n          },\n        ],\n      },\n    });\n  }\n\n  if (session.specChoice !== null) return null;\n\n  const choices = extractPlanChoices(params.planMarkdown);\n  if (choices.length === 0) return null;\n\n  const detailsHint = session.specPlanDetailsToolCallId\n    ? `Expand **${session.specPlanDetailsToolCallId}** to view the full plan details.`\n    : \"Expand the Plan details tool call to view the full plan details.\";\n  const choicePrompt = [\n    params.planTitle ? `**${params.planTitle}**` : \"**Choose an implementation option**\",\n    \"\",\n    detailsHint,\n    \"Choose one to continue iterating in spec mode.\",\n    ...choices.map((c) => `- Option ${c.id}: ${c.title}`),\n  ]\n    .filter((p) => p.length > 0)\n    .join(\"\\n\");\n\n  const response = await ctx.client.requestPermission({\n    sessionId: session.id,\n    toolCall: {\n      toolCallId: `${params.toolCallId}:choose_plan`,\n      title: params.planTitle ? `Choose plan: ${params.planTitle}` : \"Choose plan option\",\n      status: \"pending\",\n      kind: \"think\",\n      rawInput: toolCallRawInputForClient({ choices }),\n      content: [\n        {\n          type: \"content\",\n          content: { type: \"text\", text: choicePrompt },\n        },\n      ],\n    },\n    options: [\n      ...choices.map((c) => ({\n        optionId: `choose_plan:${c.id}`,\n        name: `Choose Option ${c.id}`,\n        kind: \"allow_once\" as const,\n      })),\n      { optionId: \"choose_plan:skip\", name: \"Skip\", kind: \"reject_once\" as const },\n    ],\n  });\n\n  const outcome =\n    response.outcome.outcome === \"selected\" ? response.outcome.optionId : \"choose_plan:skip\";\n  const match = outcome.match(/^choose_plan:([A-Z])$/);\n  if (!match) {\n    session.specChoice = \"skip\";\n    return null;\n  }\n\n  const choiceId = match[1];\n  session.specChoice = choiceId;\n\n  // Close the temporary \"choose plan\" permission prompt tool call.\n  await ctx.client.sessionUpdate({\n    sessionId: session.id,\n    update: {\n      sessionUpdate: \"tool_call_update\",\n      toolCallId: `${params.toolCallId}:choose_plan`,\n      status: \"completed\",\n    },\n  });\n\n  // Close the original ExitSpecMode tool call since we're explicitly staying in spec mode.\n  session.toolCallStatus.set(params.toolCallId, \"completed\");\n  session.activeToolCallIds.delete(params.toolCallId);\n  await ctx.client.sessionUpdate({\n    sessionId: session.id,\n    update: {\n      sessionUpdate: \"tool_call_update\",\n      toolCallId: params.toolCallId,\n      status: \"completed\",\n      content: [\n        {\n          type: \"content\",\n          content: {\n            type: \"text\",\n            text: `Continuing in spec mode with Option ${choiceId}.`,\n          },\n        },\n      ],\n    },\n  });\n\n  await ctx.sendAgentMessage(session, `Selected **Option ${choiceId}**. Continuing in spec mode.`);\n  setTimeout(() => {\n    session.droid.sendMessage(\n      `I choose Option ${choiceId}. Please continue refining the plan and key changes based on this option, and when you are ready to execute, prompt to exit spec mode.`,\n    );\n  }, 0);\n\n  return { selectedOption: \"cancel\" };\n}\n\nexport async function emitExitSpecModePlanUpdate(\n  ctx: { client: AgentSideConnection },\n  session: Session,\n  planMarkdown: string,\n): Promise<void> {\n  const entries = planEntriesFromMarkdown(planMarkdown);\n\n  if (entries.length > 0) {\n    await ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"plan\",\n        entries,\n      },\n    });\n    return;\n  }\n\n  if (planMarkdown.trim().length > 0) {\n    await ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"plan\",\n        entries: [\n          {\n            content: planMarkdown.trim(),\n            status: \"pending\",\n            priority: \"medium\",\n          },\n        ],\n      },\n    });\n  }\n}\n","import type {\n  AgentSideConnection,\n  PermissionOption,\n  ToolCallContent,\n  ToolCallLocation,\n  ToolKind,\n} from \"@agentclientprotocol/sdk\";\nimport type { DroidPermissionOption } from \"../../types.ts\";\nimport type { Logger } from \"../../utils.ts\";\nimport type { Session } from \"../session-types.ts\";\nimport { toolCallRawInputForClient } from \"./format.ts\";\nimport { buildAcpPermissionOptions, permissionKindFromOptionValue } from \"./acp-options.ts\";\nimport { mapExitSpecModeSelection } from \"./options.ts\";\nimport { computeAutoDecision } from \"./auto-decision.ts\";\nimport { extractSpecTitleAndPlan } from \"./spec.ts\";\nimport { emitExitSpecModePlanUpdate, maybeHandleExitSpecModePlanChoice } from \"./exit-spec.ts\";\n\nexport async function decidePermission(\n  ctx: {\n    client: AgentSideConnection;\n    logger: Logger;\n    sendAgentMessage: (session: Session, text: string) => Promise<void>;\n  },\n  session: Session,\n  params: {\n    toolCallId: string;\n    toolName: string;\n    toolCallTitle: string;\n    command: string;\n    riskLevel: \"low\" | \"medium\" | \"high\";\n    rawInput: unknown;\n    toolCallKind: ToolKind;\n    toolCallContent: ToolCallContent[];\n    toolCallLocations: ToolCallLocation[] | undefined;\n    droidOptions: DroidPermissionOption[] | null;\n  },\n): Promise<{ selectedOption: string }> {\n  if (session.cancelled) {\n    session.toolCallStatus.set(params.toolCallId, \"completed\");\n    session.activeToolCallIds.delete(params.toolCallId);\n    await ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"tool_call_update\",\n        toolCallId: params.toolCallId,\n        status: \"completed\",\n      },\n    });\n    return { selectedOption: \"cancel\" };\n  }\n\n  const droidOptions = params.droidOptions?.length ? params.droidOptions : null;\n  const acpOptions: PermissionOption[] = buildAcpPermissionOptions({\n    toolName: params.toolName,\n    droidOptions,\n  });\n\n  const spec = extractSpecTitleAndPlan(params.rawInput);\n  const planTitle = spec.title;\n  const planMarkdown = spec.plan;\n\n  if (params.toolName === \"ExitSpecMode\" && planMarkdown) {\n    const early = await maybeHandleExitSpecModePlanChoice(\n      { client: ctx.client, sendAgentMessage: ctx.sendAgentMessage },\n      session,\n      { toolCallId: params.toolCallId, planTitle, planMarkdown },\n    );\n    if (early) return early;\n  }\n\n  if (params.toolName === \"ExitSpecMode\" && planMarkdown) {\n    await emitExitSpecModePlanUpdate({ client: ctx.client }, session, planMarkdown);\n  }\n\n  const autoDecision = computeAutoDecision({\n    toolName: params.toolName,\n    sessionMode: session.mode,\n    riskLevel: params.riskLevel,\n    logger: ctx.logger,\n  });\n\n  if (autoDecision) {\n    const selectedOption =\n      droidOptions?.some((o) => o.value === autoDecision) === true\n        ? autoDecision\n        : autoDecision === \"cancel\"\n          ? \"cancel\"\n          : droidOptions\n            ? (droidOptions?.find((o) => permissionKindFromOptionValue(o.value) === \"allow_once\")\n                ?.value ??\n              droidOptions?.find((o) => o.value !== \"cancel\")?.value ??\n              \"proceed_once\")\n            : autoDecision;\n\n    const isExitSpecMode = params.toolName === \"ExitSpecMode\";\n    const status =\n      selectedOption === \"cancel\" || isExitSpecMode\n        ? (\"completed\" as const)\n        : (\"in_progress\" as const);\n\n    session.toolCallStatus.set(params.toolCallId, status);\n    if (status === \"completed\") {\n      session.activeToolCallIds.delete(params.toolCallId);\n    }\n    await ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"tool_call_update\",\n        toolCallId: params.toolCallId,\n        status,\n        content:\n          selectedOption === \"cancel\"\n            ? [\n                {\n                  type: \"content\",\n                  content: {\n                    type: \"text\",\n                    text: `Permission denied for \\`${params.toolName}\\` (${params.riskLevel}).`,\n                  },\n                },\n              ]\n            : undefined,\n      },\n    });\n    return { selectedOption };\n  }\n\n  let permission: Awaited<ReturnType<AgentSideConnection[\"requestPermission\"]>>;\n  try {\n    permission = await ctx.client.requestPermission({\n      sessionId: session.id,\n      toolCall: {\n        toolCallId: params.toolCallId,\n        title: params.toolCallTitle,\n        rawInput: toolCallRawInputForClient(params.rawInput),\n        kind: params.toolCallKind,\n        locations: params.toolCallLocations,\n        content: params.toolCallContent,\n      },\n      options: acpOptions,\n    });\n  } catch (error) {\n    ctx.logger.error(\"requestPermission failed:\", error);\n    session.toolCallStatus.set(params.toolCallId, \"completed\");\n    session.activeToolCallIds.delete(params.toolCallId);\n    await ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"tool_call_update\",\n        toolCallId: params.toolCallId,\n        status: \"completed\",\n        content: [\n          {\n            type: \"content\",\n            content: {\n              type: \"text\",\n              text: `Permission request failed for \\`${params.toolName}\\`. Cancelling the operation.`,\n            },\n          },\n        ],\n      },\n    });\n    return { selectedOption: \"cancel\" };\n  }\n\n  let selectedOption = \"cancel\";\n  if (permission.outcome.outcome === \"selected\") {\n    selectedOption = permission.outcome.optionId;\n  } else {\n    selectedOption = \"cancel\";\n  }\n\n  if (params.toolName === \"ExitSpecMode\") {\n    const mapped = mapExitSpecModeSelection(selectedOption);\n    selectedOption = mapped.droidSelectedOption;\n\n    if (mapped.nextMode) {\n      session.mode = mapped.nextMode;\n      await ctx.client.sessionUpdate({\n        sessionId: session.id,\n        update: {\n          sessionUpdate: \"current_mode_update\",\n          currentModeId: mapped.nextMode,\n        },\n      });\n    }\n  }\n\n  const isExitSpecMode = params.toolName === \"ExitSpecMode\";\n  const status =\n    selectedOption === \"cancel\" || isExitSpecMode\n      ? (\"completed\" as const)\n      : (\"in_progress\" as const);\n\n  session.toolCallStatus.set(params.toolCallId, status);\n  if (status === \"completed\") {\n    session.activeToolCallIds.delete(params.toolCallId);\n  }\n\n  // Close ExitSpecMode prompts explicitly so the UI doesn't leave them hanging.\n  if (isExitSpecMode) {\n    await ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"tool_call_update\",\n        toolCallId: params.toolCallId,\n        status,\n        content:\n          selectedOption === \"cancel\"\n            ? [\n                {\n                  type: \"content\",\n                  content: { type: \"text\", text: \"Staying in Spec mode.\" },\n                },\n              ]\n            : undefined,\n      },\n    });\n  } else if (selectedOption !== \"cancel\") {\n    // If the user explicitly rejected the permission prompt, the Client will already\n    // reflect that in the UI (e.g. \"Rejected\"). Avoid overwriting it with a \"completed\" status.\n    await ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"tool_call_update\",\n        toolCallId: params.toolCallId,\n        status,\n      },\n    });\n  }\n\n  return { selectedOption };\n}\n","import type { AgentSideConnection, ToolKind } from \"@agentclientprotocol/sdk\";\nimport type { PermissionRequest } from \"../../types.ts\";\nimport type { Logger } from \"../../utils.ts\";\nimport type { Session } from \"../session-types.ts\";\nimport { buildPermissionToolCallContent } from \"./content.ts\";\nimport { decidePermission } from \"./decide.ts\";\nimport { toolCallRawInputForClient, formatPermissionToolCallTitle } from \"./format.ts\";\nimport { extractDroidPermissionOptions } from \"./options.ts\";\nimport { permissionLocationsFromRawInput } from \"./paths.ts\";\nimport { extractSpecTitleAndPlan } from \"./spec.ts\";\nimport { toolKindFromToolName } from \"./tool-kind.ts\";\n\nexport async function handlePermission(\n  ctx: {\n    client: AgentSideConnection;\n    logger: Logger;\n    sendAgentMessage: (session: Session, text: string) => Promise<void>;\n  },\n  session: Session,\n  params: PermissionRequest,\n): Promise<{ selectedOption: string }> {\n  const toolUse = params.toolUses?.[0]?.toolUse;\n  if (!toolUse) {\n    return { selectedOption: \"proceed_once\" };\n  }\n\n  const toolCallId = toolUse.id;\n  const toolName = toolUse.name;\n  const rawInput = toolUse.input;\n  const spec = toolName === \"ExitSpecMode\" ? extractSpecTitleAndPlan(rawInput) : null;\n  const command =\n    typeof rawInput?.command === \"string\"\n      ? rawInput.command\n      : toolName === \"ExitSpecMode\" && typeof spec?.title === \"string\"\n        ? spec.title\n        : JSON.stringify(rawInput);\n  const commandSummary = command.length > 200 ? command.slice(0, 200) + \"…\" : command;\n  const isReadOnlyTool =\n    toolName === \"Read\" || toolName === \"Grep\" || toolName === \"Glob\" || toolName === \"LS\";\n  const riskLevelRaw = (rawInput as { riskLevel?: unknown } | null | undefined)?.riskLevel;\n  const riskLevel =\n    riskLevelRaw === \"low\" || riskLevelRaw === \"medium\" || riskLevelRaw === \"high\"\n      ? riskLevelRaw\n      : isReadOnlyTool\n        ? \"low\"\n        : \"medium\";\n\n  ctx.logger.log(\n    \"Permission request for tool:\",\n    toolCallId,\n    \"risk:\",\n    riskLevel,\n    \"mode:\",\n    session.mode,\n  );\n\n  const toolCallTitle =\n    toolName === \"ExitSpecMode\"\n      ? spec?.title\n        ? `Exit spec mode: ${spec.title}`\n        : \"Exit spec mode\"\n      : formatPermissionToolCallTitle({\n          toolName,\n          riskLevel,\n          rawInput,\n          cwd: session.cwd,\n        });\n\n  const toolCallKind: ToolKind =\n    toolName === \"ExitSpecMode\" ? \"switch_mode\" : toolKindFromToolName(toolName);\n\n  const toolCallLocations = permissionLocationsFromRawInput({\n    toolName,\n    rawInput,\n    cwd: session.cwd,\n  });\n\n  const toolCallContent = await buildPermissionToolCallContent({\n    toolName,\n    riskLevel,\n    rawInput,\n    cwd: session.cwd,\n    planMarkdown: toolName === \"ExitSpecMode\" ? (spec?.plan ?? null) : null,\n  });\n\n  // Emit tool_call (pending), de-duping if the tool call was already created from a tool_use block.\n  const alreadyTracked = session.activeToolCallIds.has(toolCallId);\n  session.activeToolCallIds.add(toolCallId);\n  session.toolNames.set(toolCallId, toolName);\n  session.toolCallStatus.set(toolCallId, \"pending\");\n  session.toolCallRawInputById.set(toolCallId, rawInput);\n  session.toolCallContentById.set(toolCallId, toolCallContent);\n  const rawInputForClient = toolCallRawInputForClient(rawInput);\n\n  if (alreadyTracked) {\n    void ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"tool_call_update\",\n        toolCallId,\n        title: toolCallTitle,\n        status: \"pending\",\n        kind: toolCallKind,\n        content: toolCallContent,\n        locations: toolCallLocations,\n        rawInput: rawInputForClient,\n      },\n    });\n  } else {\n    void ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: {\n        sessionUpdate: \"tool_call\",\n        toolCallId,\n        title: toolCallTitle,\n        status: \"pending\",\n        kind: toolCallKind,\n        content: toolCallContent,\n        locations: toolCallLocations,\n        rawInput: rawInputForClient,\n      },\n    });\n  }\n\n  return decidePermission(\n    {\n      client: ctx.client,\n      logger: ctx.logger,\n      sendAgentMessage: ctx.sendAgentMessage,\n    },\n    session,\n    {\n      toolCallId,\n      toolName,\n      toolCallTitle,\n      command: commandSummary,\n      riskLevel,\n      rawInput,\n      toolCallKind,\n      toolCallContent,\n      toolCallLocations,\n      droidOptions: extractDroidPermissionOptions(params),\n    },\n  );\n}\n","import type { AgentSideConnection } from \"@agentclientprotocol/sdk\";\nimport type { Session } from \"../session-types.ts\";\n\nexport async function sendAgentMessage(\n  client: AgentSideConnection,\n  session: Session,\n  text: string,\n): Promise<void> {\n  await client.sessionUpdate({\n    sessionId: session.id,\n    update: {\n      sessionUpdate: \"agent_message_chunk\",\n      content: { type: \"text\", text },\n    },\n  });\n}\n","/**\n * Factory API types for stream-jsonrpc protocol\n */\n\n// ACP mode ids exposed to the client (Zed).\nexport type AcpModeId = \"off\" | \"low\" | \"medium\" | \"high\" | \"spec\";\nexport const ACP_MODES: AcpModeId[] = [\"off\", \"low\", \"medium\", \"high\", \"spec\"];\n\n// Droid `autonomyLevel` values (see Factory docs: Settings → autonomyLevel).\nexport type DroidAutonomyLevel =\n  | \"normal\"\n  | \"spec\"\n  | \"auto-low\"\n  | \"auto-medium\"\n  | \"auto-high\"\n  // legacy values (keep for compatibility with older CLIs)\n  | \"suggest\"\n  | \"full\";\n\nexport interface FactoryRequest {\n  jsonrpc: \"2.0\";\n  factoryApiVersion: \"1.0.0\";\n  type: \"request\";\n  method: string;\n  params: Record<string, unknown>;\n  id: string;\n}\n\nexport interface FactoryResponse {\n  jsonrpc: \"2.0\";\n  type: \"response\";\n  factoryApiVersion: \"1.0.0\";\n  id: string;\n  result?: Record<string, unknown>;\n  error?: {\n    code: number;\n    message: string;\n  };\n}\n\nexport interface FactoryNotification {\n  jsonrpc: \"2.0\";\n  type: \"notification\";\n  factoryApiVersion: \"1.0.0\";\n  method: string;\n  params: Record<string, unknown>;\n}\n\nexport type FactoryMessage = FactoryRequest | FactoryResponse | FactoryNotification;\n\nexport interface AvailableModel {\n  id: string;\n  modelId?: string;\n  modelProvider: string;\n  displayName: string;\n  shortDisplayName?: string;\n  supportedReasoningEfforts: string[];\n  defaultReasoningEffort: string;\n  isCustom: boolean;\n  noImageSupport?: boolean;\n}\n\nexport interface InitSessionResult {\n  sessionId: string;\n  session?: { messages: unknown[] };\n  settings?: {\n    modelId: string;\n    reasoningEffort?: string;\n    autonomyLevel?: string;\n  };\n  availableModels: AvailableModel[];\n}\n\nexport type DroidNotification =\n  | { type: \"working_state\"; state: \"idle\" | \"streaming_assistant_message\" }\n  | {\n      type: \"settings_updated\";\n      settings: {\n        modelId?: string;\n        reasoningEffort?: string;\n        autonomyLevel?: string;\n        specModeModelId?: string;\n        specModeReasoningEffort?: string;\n      };\n    }\n  | { type: \"tool_result\"; toolUseId: string; content: string; isError: boolean }\n  | {\n      type: \"message\";\n      role: \"user\" | \"assistant\" | \"system\";\n      text?: string;\n      id: string;\n      toolUse?: { id: string; name: string; input?: unknown };\n    }\n  | { type: \"error\"; message: string }\n  | { type: \"complete\" };\n\nexport interface DroidPermissionOption {\n  value: string;\n  label: string;\n}\n\nexport interface PermissionRequest {\n  toolUses?: Array<{\n    toolUse: {\n      id: string;\n      name: string;\n      input?: {\n        command?: string;\n        riskLevel?: \"low\" | \"medium\" | \"high\";\n        [key: string]: unknown;\n      };\n    };\n    confirmationType?: string;\n    details?: unknown;\n  }>;\n  options?: DroidPermissionOption[];\n}\n\nexport interface PermissionResponse {\n  selectedOption: string;\n}\n","import type { PromptRequest } from \"@agentclientprotocol/sdk\";\nimport { normalizeBase64DataUrl } from \"../text.ts\";\n\nexport type DroidUserMessageImage = { type: \"base64\"; data: string; mediaType: string };\n\nexport function convertAcpPromptToDroidMessage(prompt: PromptRequest[\"prompt\"]): {\n  text: string;\n  images: DroidUserMessageImage[];\n} {\n  const textParts: string[] = [];\n  const images: DroidUserMessageImage[] = [];\n\n  for (const chunk of prompt) {\n    switch (chunk.type) {\n      case \"text\":\n        textParts.push(chunk.text);\n        break;\n\n      case \"image\": {\n        const mimeType = chunk.mimeType || \"application/octet-stream\";\n        if (chunk.data) {\n          const normalized = normalizeBase64DataUrl(chunk.data, mimeType);\n          images.push({\n            type: \"base64\",\n            data: normalized.base64,\n            mediaType: normalized.mimeType,\n          });\n        } else if (chunk.uri) {\n          textParts.push(`(image: ${chunk.uri})`);\n        }\n        break;\n      }\n\n      case \"resource\":\n        if (\"text\" in chunk.resource) {\n          const contextText = `\\n<context ref=\"${chunk.resource.uri}\">\\n${chunk.resource.text}\\n</context>`;\n          textParts.push(contextText);\n        } else if (\"blob\" in chunk.resource) {\n          const mimeType =\n            (chunk.resource as { mimeType?: string | null }).mimeType || \"application/octet-stream\";\n          const uri = (chunk.resource as { uri?: string }).uri;\n          if (mimeType.startsWith(\"image/\")) {\n            const data = (chunk.resource as { blob?: unknown }).blob;\n            if (typeof data === \"string\" && data.length > 0) {\n              const normalized = normalizeBase64DataUrl(data, mimeType);\n              images.push({\n                type: \"base64\",\n                data: normalized.base64,\n                mediaType: normalized.mimeType,\n              });\n            }\n          } else {\n            const note = uri\n              ? `\\n<context ref=\"${uri}\">\\n(binary resource: ${mimeType})\\n</context>`\n              : `\\n(binary resource: ${mimeType})`;\n            textParts.push(note);\n          }\n        }\n        break;\n\n      case \"resource_link\":\n        textParts.push(`@${chunk.uri}`);\n        break;\n\n      default:\n        break;\n    }\n  }\n\n  let text = textParts.join(\"\\n\").trim();\n  if (text.length === 0 && images.length > 0) {\n    text = \"Please see the attached image(s).\";\n  }\n\n  return { text, images };\n}\n","import { createServer } from \"node:http\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { AddressInfo } from \"node:net\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { Logger } from \"./utils.ts\";\n\nfunction parseSseJsonPayload(raw: string): unknown {\n  const lines = raw.split(/\\r?\\n/);\n  let currentData: string[] = [];\n  const flush = (acc: unknown[]): void => {\n    if (currentData.length === 0) return;\n    const joined = currentData.join(\"\\n\");\n    try {\n      acc.push(JSON.parse(joined));\n    } catch {\n      // Ignore non-JSON events.\n    }\n    currentData = [];\n  };\n\n  const parsed: unknown[] = [];\n  for (const line of lines) {\n    if (line.length === 0) {\n      flush(parsed);\n      continue;\n    }\n\n    if (line.startsWith(\"event:\")) {\n      continue;\n    }\n\n    if (line.startsWith(\"data:\")) {\n      const data = line.slice(\"data:\".length).replace(/^ /, \"\");\n      currentData.push(data);\n      continue;\n    }\n\n    // Ignore other SSE fields.\n  }\n  flush(parsed);\n\n  // Prefer the last JSON payload (often the final message).\n  return parsed.length > 0 ? parsed[parsed.length - 1] : null;\n}\n\nexport interface WebsearchProxyOptions {\n  upstreamBaseUrl: string;\n  websearchForwardUrl?: string;\n  websearchForwardMode?: \"http\" | \"mcp\";\n  smitheryApiKey?: string;\n  smitheryProfile?: string;\n  host?: string;\n  port?: number;\n  logger?: Logger;\n}\n\nexport interface WebsearchProxyHandle {\n  baseUrl: string;\n  close: () => Promise<void>;\n}\n\nfunction parseHttpUrl(value: string, name: string): URL {\n  let url: URL;\n  try {\n    url = new URL(value);\n  } catch {\n    throw new Error(`${name} must be a valid URL: ${value}`);\n  }\n\n  if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n    throw new Error(`${name} must be http(s): ${value}`);\n  }\n\n  return url;\n}\n\nfunction resolveForwardTarget(forward: URL, requestPathAndQuery: string): URL {\n  // If the forward URL looks like a base (no explicit path), keep the request path.\n  if (forward.pathname === \"/\" && forward.search === \"\" && forward.hash === \"\") {\n    return new URL(requestPathAndQuery, forward);\n  }\n\n  // Otherwise treat it as a full URL, but preserve the query string if caller didn't set one.\n  const target = new URL(forward.toString());\n  if (!target.search && requestPathAndQuery.includes(\"?\")) {\n    target.search = requestPathAndQuery.slice(requestPathAndQuery.indexOf(\"?\"));\n  }\n  return target;\n}\n\nfunction isBodylessMethod(method: string | undefined): boolean {\n  return method === \"GET\" || method === \"HEAD\";\n}\n\nfunction toNonEmptyString(value: unknown): string | null {\n  return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : null;\n}\n\nfunction parseWebsearchRequestBody(\n  bodyBuffer: Buffer,\n): { query: string; numResults: number } | null {\n  let input: unknown;\n  try {\n    input = JSON.parse(bodyBuffer.toString(\"utf8\"));\n  } catch {\n    return null;\n  }\n\n  const query = toNonEmptyString((input as { query?: unknown } | null | undefined)?.query);\n  if (!query) return null;\n\n  const numResultsRaw = (input as { numResults?: unknown } | null | undefined)?.numResults;\n  const numResults =\n    typeof numResultsRaw === \"number\" && Number.isFinite(numResultsRaw)\n      ? Math.max(1, numResultsRaw)\n      : 10;\n\n  return { query, numResults };\n}\n\nasync function readBody(req: IncomingMessage, maxBytes: number): Promise<Buffer> {\n  const chunks: Buffer[] = [];\n  let total = 0;\n\n  for await (const chunk of req) {\n    const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk as Uint8Array);\n    total += buf.length;\n    if (total > maxBytes) {\n      throw new Error(`Request body too large (${total} bytes)`);\n    }\n    chunks.push(buf);\n  }\n\n  return Buffer.concat(chunks);\n}\n\nfunction parseSearchResultsText(\n  text: string,\n  numResults: number,\n): Array<Record<string, unknown>> | null {\n  // First try JSON (some MCP servers return an array encoded in text).\n  try {\n    const json = JSON.parse(text) as unknown;\n    if (Array.isArray(json)) return (json as Array<Record<string, unknown>>).slice(0, numResults);\n  } catch {\n    // Fall through to plain-text parsing.\n  }\n\n  // Fallback: Smithery Exa MCP often returns plain text blocks:\n  // Title: ...\n  // URL: ...\n  // Text: ...\n  const matches = [...text.matchAll(/^Title:\\s*(.*)$/gm)];\n  if (matches.length === 0) return null;\n\n  const results: Array<Record<string, unknown>> = [];\n  for (let i = 0; i < matches.length && results.length < numResults; i += 1) {\n    const start = matches[i]?.index ?? 0;\n    const end = matches[i + 1]?.index ?? text.length;\n    const chunk = text.slice(start, end).trim();\n    const title = matches[i]?.[1]?.trim() ?? \"\";\n    const url = (chunk.match(/^URL:\\s*(.*)$/m)?.[1] ?? \"\").trim();\n    const snippet = (chunk.match(/^Text:\\s*(.*)$/m)?.[1] ?? \"\").trim();\n    results.push({ title, url, snippet, text: snippet });\n  }\n\n  return results;\n}\n\nasync function tryHandleWebsearchWithMcp(\n  res: ServerResponse,\n  logger: Logger,\n  mcpEndpoint: URL,\n  bodyBuffer: Buffer,\n): Promise<{ handled: boolean; error?: string }> {\n  const parsed = parseWebsearchRequestBody(bodyBuffer);\n  if (!parsed) return { handled: false };\n  const { query, numResults } = parsed;\n\n  const requestBody = {\n    jsonrpc: \"2.0\",\n    id: 1,\n    method: \"tools/call\",\n    params: {\n      name: \"web_search_exa\",\n      arguments: {\n        query,\n        numResults,\n      },\n    },\n  };\n\n  let mcpResponse: unknown;\n  try {\n    const response = await fetch(mcpEndpoint, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        // Smithery requires the client to accept both JSON and SSE.\n        Accept: \"application/json, text/event-stream\",\n      },\n      body: JSON.stringify(requestBody),\n    });\n\n    const contentType = response.headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n    if (contentType.includes(\"text/event-stream\")) {\n      const raw = await response.text();\n      const parsedSse = parseSseJsonPayload(raw);\n      if (!parsedSse) {\n        throw new Error(\"Invalid MCP SSE response: missing JSON payload\");\n      }\n      mcpResponse = parsedSse;\n    } else {\n      mcpResponse = await response.json();\n    }\n  } catch (error: unknown) {\n    const message = error instanceof Error ? error.message : String(error);\n    logger.error(\"[websearch] MCP request failed:\", message);\n    return { handled: false, error: message };\n  }\n\n  const resultContent = (mcpResponse as { result?: { content?: unknown } } | null | undefined)\n    ?.result?.content;\n  const contentBlocks = Array.isArray(resultContent) ? (resultContent as Array<unknown>) : [];\n  const textBlock = contentBlocks.find(\n    (c): c is { type: string; text: string } =>\n      !!c &&\n      typeof c === \"object\" &&\n      (c as { type?: unknown }).type === \"text\" &&\n      typeof (c as { text?: unknown }).text === \"string\",\n  );\n\n  if (!textBlock) {\n    const errorMessage =\n      (mcpResponse as { error?: { message?: unknown } } | null | undefined)?.error?.message ??\n      (mcpResponse as { error?: unknown } | null | undefined)?.error ??\n      null;\n    const message =\n      typeof errorMessage === \"string\"\n        ? errorMessage\n        : `Invalid MCP response: ${JSON.stringify(mcpResponse)}`;\n    logger.error(\"[websearch] MCP response missing text content:\", message);\n    return { handled: false, error: message };\n  }\n\n  const parsedItems = parseSearchResultsText(textBlock.text, numResults);\n  if (!parsedItems) {\n    logger.error(\"[websearch] Failed to parse MCP text payload\");\n    return { handled: false, error: \"Invalid MCP payload: unsupported format\" };\n  }\n\n  const results = parsedItems.slice(0, numResults).map((item) => {\n    const title = toNonEmptyString(item.title) ?? \"\";\n    const url = toNonEmptyString(item.url) ?? \"\";\n    const highlights = Array.isArray(item.highlights)\n      ? (item.highlights as unknown[]).filter((v): v is string => typeof v === \"string\")\n      : [];\n    const content =\n      toNonEmptyString(item.text) ??\n      toNonEmptyString(item.snippet) ??\n      (highlights.length > 0 ? highlights.join(\" \") : \"\");\n\n    return {\n      title,\n      url,\n      content,\n      snippet: content,\n      publishedDate: item.publishedDate ?? null,\n      author: item.author ?? null,\n      score: item.score ?? null,\n    };\n  });\n\n  res.writeHead(200, { \"Content-Type\": \"application/json\" });\n  res.end(JSON.stringify({ results }));\n  return { handled: true };\n}\n\nexport async function startWebsearchProxy(\n  options: WebsearchProxyOptions,\n): Promise<WebsearchProxyHandle> {\n  const logger = options.logger ?? console;\n  const host = options.host ?? \"127.0.0.1\";\n  const port = options.port ?? 0;\n\n  const upstreamBase = parseHttpUrl(options.upstreamBaseUrl, \"DROID_ACP_WEBSEARCH_UPSTREAM_URL\");\n  const forward = options.websearchForwardUrl\n    ? parseHttpUrl(options.websearchForwardUrl, \"DROID_ACP_WEBSEARCH_FORWARD_URL\")\n    : null;\n  const forwardMode = options.websearchForwardMode ?? \"http\";\n\n  const smitheryApiKey = toNonEmptyString(options.smitheryApiKey);\n  const smitheryProfile = toNonEmptyString(options.smitheryProfile);\n  const smitheryEndpoint =\n    smitheryApiKey && smitheryProfile\n      ? new URL(\n          `https://server.smithery.ai/exa/mcp?api_key=${encodeURIComponent(\n            smitheryApiKey,\n          )}&profile=${encodeURIComponent(smitheryProfile)}`,\n        )\n      : null;\n\n  let totalRequests = 0;\n  let websearchRequests = 0;\n  let lastWebsearchAt: string | null = null;\n  let lastWebsearchOutcome: string | null = null;\n\n  const server = createServer((req, res) => {\n    void (async () => {\n      totalRequests += 1;\n      const rawUrl = req.url;\n      if (!rawUrl) {\n        res.writeHead(400, { \"Content-Type\": \"application/json\" });\n        res.end(JSON.stringify({ error: \"Missing URL\" }));\n        return;\n      }\n\n      const requestUrl = new URL(rawUrl, `http://${req.headers.host ?? \"127.0.0.1\"}`);\n      const pathAndQuery = `${requestUrl.pathname}${requestUrl.search || \"\"}`;\n\n      if (requestUrl.pathname === \"/health\") {\n        res.writeHead(200, { \"Content-Type\": \"application/json\" });\n        res.end(\n          JSON.stringify({\n            status: \"ok\",\n            upstreamBaseUrl: upstreamBase.toString(),\n            websearchForwardUrl: forward?.toString() ?? null,\n            websearchForwardMode: forwardMode,\n            smitheryEnabled: Boolean(smitheryEndpoint),\n            requests: {\n              total: totalRequests,\n              websearch: websearchRequests,\n              lastWebsearchAt,\n              lastWebsearchOutcome,\n            },\n          }),\n        );\n        return;\n      }\n\n      const isWebsearchPath = requestUrl.pathname.startsWith(\"/api/tools/exa/search\");\n      const isWebsearch = isWebsearchPath && req.method === \"POST\";\n      const shouldUseForwardForWebsearch = isWebsearch && forward && forwardMode === \"http\";\n      const targetUrl = shouldUseForwardForWebsearch\n        ? resolveForwardTarget(forward, pathAndQuery)\n        : new URL(pathAndQuery, upstreamBase);\n\n      const headers = new Headers();\n      for (const [key, value] of Object.entries(req.headers)) {\n        if (value === undefined) continue;\n        if (key.toLowerCase() === \"host\") continue;\n        // Avoid forwarding compression negotiation headers. Node fetch may transparently decompress,\n        // which can lead to clients attempting a second decompression pass.\n        if (key.toLowerCase() === \"accept-encoding\") continue;\n        if (Array.isArray(value)) {\n          for (const v of value) headers.append(key, v);\n        } else {\n          headers.set(key, value);\n        }\n      }\n      headers.set(\"accept-encoding\", \"identity\");\n\n      const controller = new AbortController();\n      req.on(\"aborted\", () => controller.abort());\n\n      let bodyBuffer: Buffer | null = null;\n      if (isWebsearch) {\n        websearchRequests += 1;\n        lastWebsearchAt = new Date().toISOString();\n        try {\n          bodyBuffer = await readBody(req, 1_000_000);\n        } catch {\n          res.writeHead(413, { \"Content-Type\": \"application/json\" });\n          res.end(JSON.stringify({ error: \"Request body too large\" }));\n          lastWebsearchOutcome = \"rejected: body too large\";\n          return;\n        }\n\n        // Mode 1: forward as MCP to a custom MCP endpoint.\n        if (forward && forwardMode === \"mcp\") {\n          const r = await tryHandleWebsearchWithMcp(res, logger, forward, bodyBuffer);\n          if (r.handled) {\n            lastWebsearchOutcome = \"handled: mcp forward\";\n            return;\n          }\n          res.writeHead(502, { \"Content-Type\": \"application/json\" });\n          res.end(\n            JSON.stringify({\n              error: \"WebSearch MCP forward failed\",\n              message: r.error ?? \"Unknown error\",\n            }),\n          );\n          lastWebsearchOutcome = `error: mcp forward (${r.error ?? \"unknown\"})`;\n          return;\n        }\n\n        // Mode 2: Smithery Exa MCP (env-driven), compatible with droid-patch.\n        if (smitheryEndpoint) {\n          const r = await tryHandleWebsearchWithMcp(res, logger, smitheryEndpoint, bodyBuffer);\n          if (r.handled) {\n            lastWebsearchOutcome = \"handled: smithery exa mcp\";\n            return;\n          }\n          res.writeHead(502, { \"Content-Type\": \"application/json\" });\n          res.end(\n            JSON.stringify({\n              error: \"Smithery Exa MCP websearch failed\",\n              message: r.error ?? \"Unknown error\",\n            }),\n          );\n          lastWebsearchOutcome = `error: smithery exa mcp (${r.error ?? \"unknown\"})`;\n          return;\n        }\n\n        logger.log(\"[websearch] proxying\", pathAndQuery, \"->\", targetUrl.toString());\n        lastWebsearchOutcome = \"proxied: upstream\";\n      } else {\n        logger.log(\"[factory-proxy]\", req.method ?? \"GET\", pathAndQuery);\n      }\n\n      let upstreamResponse: Response;\n      try {\n        upstreamResponse = await fetch(targetUrl, {\n          method: req.method,\n          headers,\n          body: isBodylessMethod(req.method) ? undefined : bodyBuffer ? bodyBuffer : req,\n          redirect: \"manual\",\n          signal: controller.signal,\n          // Required by undici when streaming request bodies.\n          duplex: \"half\",\n        } as RequestInit);\n      } catch (error: unknown) {\n        const message = error instanceof Error ? error.message : String(error);\n        res.writeHead(502, { \"Content-Type\": \"application/json\" });\n        res.end(JSON.stringify({ error: \"Upstream request failed\", message }));\n        return;\n      }\n\n      const setCookie: string[] | undefined = (\n        upstreamResponse.headers as unknown as {\n          getSetCookie?: () => string[];\n        }\n      ).getSetCookie?.();\n      if (setCookie && setCookie.length > 0) {\n        res.setHeader(\"set-cookie\", setCookie);\n      }\n\n      for (const [key, value] of upstreamResponse.headers) {\n        if (key.toLowerCase() === \"set-cookie\") continue;\n        if (key.toLowerCase() === \"content-encoding\") continue;\n        if (key.toLowerCase() === \"content-length\") continue;\n        res.setHeader(key, value);\n      }\n\n      res.statusCode = upstreamResponse.status;\n\n      if (!upstreamResponse.body) {\n        res.end();\n        return;\n      }\n\n      try {\n        await pipeline(Readable.fromWeb(upstreamResponse.body), res);\n      } catch {\n        // Connection ended; nothing to do.\n      }\n    })();\n  });\n\n  await new Promise<void>((resolve, reject) => {\n    server.once(\"error\", reject);\n    server.listen(port, host, () => {\n      server.off(\"error\", reject);\n      resolve();\n    });\n  });\n\n  const address = server.address();\n  if (!address || typeof address === \"string\") {\n    server.close();\n    throw new Error(\"Failed to bind websearch proxy server\");\n  }\n  const actualPort = (address as AddressInfo).port;\n  const baseUrl = `http://${host}:${actualPort}`;\n\n  logger.log(\"[websearch] proxy listening on\", baseUrl);\n\n  return {\n    baseUrl,\n    close: () =>\n      new Promise<void>((resolve) => {\n        server.close(() => resolve());\n      }),\n  };\n}\n","/**\n * WebSearch Native Provider Mode (experimental)\n *\n * Uses model's native websearch capability based on ~/.factory/settings.json configuration.\n * Supported providers:\n * - Anthropic: web_search_20250305 server tool\n * - OpenAI: web_search tool via /responses endpoint\n */\n\nimport { createServer } from \"node:http\";\nimport { readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { AddressInfo } from \"node:net\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { Logger } from \"./utils.ts\";\n\nexport interface NativeWebsearchProxyOptions {\n  factoryApiUrl?: string;\n  host?: string;\n  port?: number;\n  logger?: Logger;\n}\n\nexport interface NativeWebsearchProxyHandle {\n  baseUrl: string;\n  close: () => Promise<void>;\n}\n\ninterface ModelConfig {\n  id: string;\n  displayName?: string;\n  provider: string;\n  baseUrl: string;\n  apiKey: string;\n  model: string;\n}\n\ninterface FactorySettings {\n  sessionDefaultSettings?: {\n    model?: string;\n  };\n  customModels?: ModelConfig[];\n}\n\ninterface SearchResult {\n  title: string;\n  url: string;\n  content: string;\n}\n\nlet cachedSettings: FactorySettings | null = null;\nlet settingsLastModified = 0;\n\nfunction getFactorySettings(logger: Logger): FactorySettings | null {\n  const settingsPath = join(homedir(), \".factory\", \"settings.json\");\n  try {\n    const stats = statSync(settingsPath);\n    if (cachedSettings && stats.mtimeMs === settingsLastModified) {\n      return cachedSettings;\n    }\n    cachedSettings = JSON.parse(readFileSync(settingsPath, \"utf-8\")) as FactorySettings;\n    settingsLastModified = stats.mtimeMs;\n    return cachedSettings;\n  } catch (e) {\n    logger.error(\"[websearch-native] Failed to load settings.json:\", (e as Error).message);\n    return null;\n  }\n}\n\nfunction getCurrentModelConfig(logger: Logger): ModelConfig | null {\n  const settings = getFactorySettings(logger);\n  if (!settings) return null;\n\n  const currentModelId = settings.sessionDefaultSettings?.model;\n  if (!currentModelId) return null;\n\n  const customModels = settings.customModels || [];\n  const modelConfig = customModels.find((m) => m.id === currentModelId);\n\n  if (modelConfig) {\n    logger.log(\n      \"[websearch-native] Model:\",\n      modelConfig.displayName || modelConfig.id,\n      \"| Provider:\",\n      modelConfig.provider,\n    );\n    return modelConfig;\n  }\n\n  if (!currentModelId.startsWith(\"custom:\")) return null;\n  logger.log(\"[websearch-native] Model not found:\", currentModelId);\n  return null;\n}\n\nasync function searchAnthropicNative(\n  query: string,\n  numResults: number,\n  modelConfig: ModelConfig,\n  logger: Logger,\n): Promise<SearchResult[] | null> {\n  const { baseUrl, apiKey, model } = modelConfig;\n\n  try {\n    const requestBody = {\n      model: model,\n      max_tokens: 4096,\n      stream: false,\n      system:\n        \"You are a web search assistant. Use the web_search tool to find relevant information and return the results.\",\n      tools: [{ type: \"web_search_20250305\", name: \"web_search\", max_uses: 1 }],\n      tool_choice: { type: \"tool\", name: \"web_search\" },\n      messages: [\n        {\n          role: \"user\",\n          content: `Search the web for: ${query}\\n\\nReturn up to ${numResults} relevant results.`,\n        },\n      ],\n    };\n\n    let endpoint = baseUrl;\n    if (!endpoint.endsWith(\"/v1/messages\")) {\n      endpoint = endpoint.replace(/\\/$/, \"\") + \"/v1/messages\";\n    }\n\n    logger.log(\"[websearch-native] Anthropic search:\", query, \"→\", endpoint);\n\n    const response = await fetch(endpoint, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        \"anthropic-version\": \"2023-06-01\",\n        \"x-api-key\": apiKey,\n      },\n      body: JSON.stringify(requestBody),\n    });\n\n    const data = (await response.json()) as {\n      error?: { message?: string };\n      content?: Array<{\n        type: string;\n        content?: Array<{\n          type: string;\n          title?: string;\n          url?: string;\n          snippet?: string;\n          page_content?: string;\n        }>;\n      }>;\n    };\n\n    if (data.error) {\n      logger.error(\"[websearch-native] Anthropic API error:\", data.error.message);\n      return null;\n    }\n\n    const results: SearchResult[] = [];\n    for (const block of data.content || []) {\n      if (block.type === \"web_search_tool_result\") {\n        for (const result of block.content || []) {\n          if (result.type === \"web_search_result\") {\n            results.push({\n              title: result.title || \"\",\n              url: result.url || \"\",\n              content: result.snippet || result.page_content || \"\",\n            });\n          }\n        }\n      }\n    }\n\n    logger.log(\"[websearch-native] Anthropic results:\", results.length);\n    return results.length > 0 ? results.slice(0, numResults) : null;\n  } catch (e) {\n    logger.error(\"[websearch-native] Anthropic error:\", (e as Error).message);\n    return null;\n  }\n}\n\nasync function searchOpenAINative(\n  query: string,\n  numResults: number,\n  modelConfig: ModelConfig,\n  logger: Logger,\n): Promise<SearchResult[] | null> {\n  const { baseUrl, apiKey, model } = modelConfig;\n\n  try {\n    const requestBody = {\n      model: model,\n      stream: false,\n      tools: [{ type: \"web_search\" }],\n      tool_choice: \"required\",\n      input: `Search the web for: ${query}\\n\\nReturn up to ${numResults} relevant results.`,\n    };\n\n    let endpoint = baseUrl;\n    if (!endpoint.endsWith(\"/responses\")) {\n      endpoint = endpoint.replace(/\\/$/, \"\") + \"/responses\";\n    }\n\n    logger.log(\"[websearch-native] OpenAI search:\", query, \"→\", endpoint);\n\n    const response = await fetch(endpoint, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        Authorization: `Bearer ${apiKey}`,\n      },\n      body: JSON.stringify(requestBody),\n    });\n\n    const data = (await response.json()) as {\n      error?: { message?: string };\n      output?: Array<{\n        type: string;\n        content?: Array<{\n          type: string;\n          annotations?: Array<{\n            type: string;\n            url?: string;\n            title?: string;\n          }>;\n        }>;\n      }>;\n    };\n\n    if (data.error) {\n      logger.error(\"[websearch-native] OpenAI API error:\", data.error.message);\n      return null;\n    }\n\n    const results: SearchResult[] = [];\n    for (const item of data.output || []) {\n      if (item.type === \"message\" && Array.isArray(item.content)) {\n        for (const content of item.content) {\n          if (content.type === \"output_text\" && Array.isArray(content.annotations)) {\n            for (const annotation of content.annotations) {\n              if (annotation.type === \"url_citation\" && annotation.url) {\n                results.push({\n                  title: annotation.title || \"\",\n                  url: annotation.url || \"\",\n                  content: annotation.title || \"\",\n                });\n              }\n            }\n          }\n        }\n      }\n    }\n\n    logger.log(\"[websearch-native] OpenAI results:\", results.length);\n    return results.length > 0 ? results.slice(0, numResults) : null;\n  } catch (e) {\n    logger.error(\"[websearch-native] OpenAI error:\", (e as Error).message);\n    return null;\n  }\n}\n\nasync function search(\n  query: string,\n  numResults: number,\n  logger: Logger,\n): Promise<{ results: SearchResult[]; source: string }> {\n  logger.log(\"[websearch-native] Search:\", query);\n\n  const modelConfig = getCurrentModelConfig(logger);\n  if (!modelConfig) {\n    logger.log(\"[websearch-native] No custom model configured\");\n    return { results: [], source: \"none\" };\n  }\n\n  const provider = modelConfig.provider;\n  let results: SearchResult[] | null = null;\n\n  if (provider === \"anthropic\") {\n    results = await searchAnthropicNative(query, numResults, modelConfig, logger);\n  } else if (provider === \"openai\") {\n    results = await searchOpenAINative(query, numResults, modelConfig, logger);\n  } else {\n    logger.log(\"[websearch-native] Unsupported provider:\", provider);\n  }\n\n  if (results && results.length > 0) {\n    return { results, source: `native-${provider}` };\n  }\n  return { results: [], source: \"none\" };\n}\n\nfunction parseRequestBody(body: string): { query: string; numResults: number } | null {\n  try {\n    const parsed = JSON.parse(body) as { query?: string; numResults?: number };\n    const query = typeof parsed.query === \"string\" ? parsed.query.trim() : \"\";\n    if (!query) return null;\n    const numResults =\n      typeof parsed.numResults === \"number\" && Number.isFinite(parsed.numResults)\n        ? Math.max(1, parsed.numResults)\n        : 10;\n    return { query, numResults };\n  } catch {\n    return null;\n  }\n}\n\nasync function readBody(req: IncomingMessage, maxBytes: number): Promise<string> {\n  const chunks: Buffer[] = [];\n  let total = 0;\n\n  for await (const chunk of req) {\n    const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk as Uint8Array);\n    total += buf.length;\n    if (total > maxBytes) {\n      throw new Error(`Request body too large (${total} bytes)`);\n    }\n    chunks.push(buf);\n  }\n\n  return Buffer.concat(chunks).toString(\"utf-8\");\n}\n\nexport async function startNativeWebsearchProxy(\n  options: NativeWebsearchProxyOptions,\n): Promise<NativeWebsearchProxyHandle> {\n  const logger = options.logger ?? console;\n  const host = options.host ?? \"127.0.0.1\";\n  const port = options.port ?? 0;\n  const factoryApiUrl = options.factoryApiUrl ?? \"https://api.factory.ai\";\n\n  let totalRequests = 0;\n  let websearchRequests = 0;\n  let lastWebsearchAt: string | null = null;\n  let lastWebsearchSource: string | null = null;\n\n  const server = createServer((req: IncomingMessage, res: ServerResponse) => {\n    void (async () => {\n      totalRequests += 1;\n      const rawUrl = req.url;\n      if (!rawUrl) {\n        res.writeHead(400, { \"Content-Type\": \"application/json\" });\n        res.end(JSON.stringify({ error: \"Missing URL\" }));\n        return;\n      }\n\n      const requestUrl = new URL(rawUrl, `http://${req.headers.host ?? \"127.0.0.1\"}`);\n\n      if (requestUrl.pathname === \"/health\") {\n        res.writeHead(200, { \"Content-Type\": \"application/json\" });\n        res.end(\n          JSON.stringify({\n            status: \"ok\",\n            mode: \"native-provider\",\n            requests: {\n              total: totalRequests,\n              websearch: websearchRequests,\n              lastWebsearchAt,\n              lastWebsearchSource,\n            },\n          }),\n        );\n        return;\n      }\n\n      if (requestUrl.pathname === \"/api/tools/exa/search\" && req.method === \"POST\") {\n        websearchRequests += 1;\n        lastWebsearchAt = new Date().toISOString();\n\n        try {\n          const body = await readBody(req, 1_000_000);\n          const parsed = parseRequestBody(body);\n\n          if (!parsed) {\n            res.writeHead(400, { \"Content-Type\": \"application/json\" });\n            res.end(JSON.stringify({ error: \"Invalid request body\", results: [] }));\n            return;\n          }\n\n          const result = await search(parsed.query, parsed.numResults, logger);\n          lastWebsearchSource = result.source;\n          logger.log(\"[websearch-native] Results:\", result.results.length, \"from\", result.source);\n\n          res.writeHead(200, { \"Content-Type\": \"application/json\" });\n          res.end(JSON.stringify({ results: result.results }));\n        } catch (e) {\n          logger.error(\"[websearch-native] Search error:\", (e as Error).message);\n          res.writeHead(500, { \"Content-Type\": \"application/json\" });\n          res.end(JSON.stringify({ error: String(e), results: [] }));\n        }\n        return;\n      }\n\n      // Proxy other requests to Factory API\n      const pathAndQuery = `${requestUrl.pathname}${requestUrl.search || \"\"}`;\n      const targetUrl = new URL(pathAndQuery, factoryApiUrl);\n\n      logger.log(\"[websearch-native] Proxy:\", req.method ?? \"GET\", pathAndQuery);\n\n      const headers = new Headers();\n      for (const [key, value] of Object.entries(req.headers)) {\n        if (value === undefined) continue;\n        if (key.toLowerCase() === \"host\") continue;\n        if (key.toLowerCase() === \"accept-encoding\") continue;\n        if (Array.isArray(value)) {\n          for (const v of value) headers.append(key, v);\n        } else {\n          headers.set(key, value);\n        }\n      }\n      headers.set(\"accept-encoding\", \"identity\");\n\n      try {\n        let body: string | undefined;\n        if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n          body = await readBody(req, 10_000_000);\n        }\n\n        const response = await fetch(targetUrl, {\n          method: req.method,\n          headers,\n          body,\n          redirect: \"manual\",\n        });\n\n        for (const [key, value] of response.headers) {\n          if (key.toLowerCase() === \"content-encoding\") continue;\n          if (key.toLowerCase() === \"content-length\") continue;\n          res.setHeader(key, value);\n        }\n        res.statusCode = response.status;\n\n        if (!response.body) {\n          res.end();\n          return;\n        }\n\n        const arrayBuffer = await response.arrayBuffer();\n        res.end(Buffer.from(arrayBuffer));\n      } catch (e) {\n        res.writeHead(502, { \"Content-Type\": \"application/json\" });\n        res.end(JSON.stringify({ error: \"Proxy failed: \" + (e as Error).message }));\n      }\n    })();\n  });\n\n  await new Promise<void>((resolve, reject) => {\n    server.once(\"error\", reject);\n    server.listen(port, host, () => {\n      server.off(\"error\", reject);\n      resolve();\n    });\n  });\n\n  const address = server.address();\n  if (!address || typeof address === \"string\") {\n    server.close();\n    throw new Error(\"Failed to bind native websearch proxy server\");\n  }\n  const actualPort = (address as AddressInfo).port;\n  const baseUrl = `http://${host}:${actualPort}`;\n\n  logger.log(\"[websearch-native] proxy listening on\", baseUrl);\n\n  return {\n    baseUrl,\n    close: () =>\n      new Promise<void>((resolve) => {\n        server.close(() => resolve());\n      }),\n  };\n}\n","import { spawn, type ChildProcess } from \"node:child_process\";\nimport { createInterface } from \"node:readline\";\nimport { randomUUID } from \"node:crypto\";\nimport { findDroidExecutable, isEnvEnabled, isWindows, type Logger } from \"./utils.ts\";\nimport { startWebsearchProxy, type WebsearchProxyHandle } from \"./websearch-proxy.ts\";\nimport { startNativeWebsearchProxy, type NativeWebsearchProxyHandle } from \"./websearch-native.ts\";\nimport type {\n  DroidAutonomyLevel,\n  DroidNotification,\n  FactoryRequest,\n  FactoryMessage,\n  InitSessionResult,\n  PermissionResponse,\n} from \"./types.ts\";\n\nexport interface DroidAdapterOptions {\n  cwd: string;\n  logger?: Logger;\n  resumeSessionId?: string;\n}\n\nexport interface DroidAdapter {\n  start(): Promise<InitSessionResult>;\n  sendMessage(text: string): void;\n  sendUserMessage(message: {\n    text: string;\n    images?: Array<{ type: \"base64\"; data: string; mediaType: string }>;\n  }): void;\n  getWebsearchProxyBaseUrl(): string | null;\n  setMode(level: DroidAutonomyLevel): void;\n  setModel(modelId: string): void;\n  onNotification(handler: (notification: DroidNotification) => void | Promise<void>): void;\n  onRawEvent(handler: (event: unknown) => void | Promise<void>): void;\n  onRequest(handler: (method: string, params: unknown) => Promise<PermissionResponse>): void;\n  onExit(handler: (code: number | null) => void): void;\n  stop(): Promise<void>;\n  isRunning(): boolean;\n  getSessionId(): string | null;\n}\n\nexport function createDroidAdapter(options: DroidAdapterOptions): DroidAdapter {\n  let process: ChildProcess | null = null;\n  let sessionId: string | null = null;\n  let websearchProxy: WebsearchProxyHandle | NativeWebsearchProxyHandle | null = null;\n  const machineId = randomUUID();\n  const logger = options.logger ?? console;\n\n  const notificationHandlers: Array<(n: DroidNotification) => void | Promise<void>> = [];\n  const rawEventHandlers: Array<(e: unknown) => void | Promise<void>> = [];\n  const exitHandlers: Array<(code: number | null) => void> = [];\n  let requestHandler: ((method: string, params: unknown) => Promise<PermissionResponse>) | null =\n    null;\n\n  let initResolve: ((result: InitSessionResult) => void) | null = null;\n  let initReject: ((error: Error) => void) | null = null;\n\n  // State for message ordering (handle out-of-order idle notification)\n  let isStreamingAssistant = false;\n  let pendingIdle = false;\n  let pendingIdleTimer: NodeJS.Timeout | null = null;\n\n  const send = (method: string, params: Record<string, unknown>) => {\n    if (!process?.stdin?.writable) return;\n    const msg: FactoryRequest = {\n      jsonrpc: \"2.0\",\n      factoryApiVersion: \"1.0.0\",\n      type: \"request\",\n      method,\n      params,\n      id: randomUUID(),\n    };\n    process.stdin.write(JSON.stringify(msg) + \"\\n\");\n    logger.log(\"Sent:\", method);\n  };\n\n  const emit = async (n: DroidNotification) => {\n    for (const h of notificationHandlers) {\n      await h(n);\n    }\n  };\n\n  // Process queue sequentially using promise chain\n  let processingChain: Promise<void> = Promise.resolve();\n\n  const queueLine = (line: string) => {\n    processingChain = processingChain.then(() => handleLine(line));\n  };\n\n  const handleLine = async (line: string) => {\n    try {\n      const msg = JSON.parse(line) as FactoryMessage;\n\n      // Emit raw event for debugging\n      for (const h of rawEventHandlers) {\n        await h(msg);\n      }\n\n      // Handle init response\n      if (\n        msg.type === \"response\" &&\n        \"result\" in msg &&\n        msg.result &&\n        \"sessionId\" in msg.result &&\n        initResolve\n      ) {\n        const r = msg.result as unknown as InitSessionResult;\n        sessionId = r.sessionId;\n        initResolve({\n          sessionId: r.sessionId,\n          session: r.session,\n          settings: r.settings,\n          availableModels: r.availableModels || [],\n        });\n        initResolve = null;\n        initReject = null;\n        return;\n      }\n\n      // Handle error response\n      if (msg.type === \"response\" && \"error\" in msg && msg.error && initReject) {\n        initReject(new Error(msg.error.message));\n        initResolve = null;\n        initReject = null;\n        return;\n      }\n\n      // Handle notifications\n      if (msg.type === \"notification\" && msg.method === \"droid.session_notification\") {\n        const notification = (msg.params as { notification?: Record<string, unknown> })\n          ?.notification;\n        if (!notification) return;\n\n        const notificationType = notification.type as string;\n\n        switch (notificationType) {\n          case \"settings_updated\": {\n            const settings = notification.settings as Record<string, unknown> | undefined;\n            if (settings) {\n              await emit({\n                type: \"settings_updated\",\n                settings: {\n                  modelId: typeof settings.modelId === \"string\" ? settings.modelId : undefined,\n                  reasoningEffort:\n                    typeof settings.reasoningEffort === \"string\"\n                      ? settings.reasoningEffort\n                      : undefined,\n                  autonomyLevel:\n                    typeof settings.autonomyLevel === \"string\" ? settings.autonomyLevel : undefined,\n                  specModeModelId:\n                    typeof settings.specModeModelId === \"string\"\n                      ? settings.specModeModelId\n                      : undefined,\n                  specModeReasoningEffort:\n                    typeof settings.specModeReasoningEffort === \"string\"\n                      ? settings.specModeReasoningEffort\n                      : undefined,\n                },\n              });\n            }\n            break;\n          }\n\n          case \"droid_working_state_changed\": {\n            const newState = notification.newState as string;\n            await emit({\n              type: \"working_state\",\n              state: newState as \"idle\" | \"streaming_assistant_message\",\n            });\n\n            if (newState === \"streaming_assistant_message\") {\n              isStreamingAssistant = true;\n              pendingIdle = false;\n              if (pendingIdleTimer) {\n                clearTimeout(pendingIdleTimer);\n                pendingIdleTimer = null;\n              }\n            } else if (newState === \"idle\") {\n              // Handle out-of-order idle notification\n              // Droid CLI sometimes sends idle before the final assistant message\n              if (isStreamingAssistant) {\n                pendingIdle = true;\n\n                // Droid can also transition through streaming→idle without emitting a final\n                // assistant create_message (e.g. after rejecting ExitSpecMode). In that case,\n                // ensure we still complete the prompt after a short grace period.\n                if (pendingIdleTimer) {\n                  clearTimeout(pendingIdleTimer);\n                }\n                pendingIdleTimer = setTimeout(() => {\n                  if (!pendingIdle) return;\n                  pendingIdle = false;\n                  isStreamingAssistant = false;\n                  pendingIdleTimer = null;\n                  void emit({ type: \"complete\" });\n                }, 250);\n              } else {\n                await emit({ type: \"complete\" });\n              }\n            }\n            break;\n          }\n\n          case \"create_message\": {\n            const message = notification.message as {\n              role: string;\n              id: string;\n              content?: Array<{\n                type: string;\n                text?: string;\n                id?: string;\n                toolUseId?: string;\n                tool_use_id?: string;\n                tool_call_id?: string;\n                callId?: string;\n                call_id?: string;\n                name?: string;\n                toolName?: string;\n                tool_name?: string;\n                input?: unknown;\n              }>;\n            };\n            if (message) {\n              const blocks = Array.isArray(message.content) ? message.content : [];\n\n              const textParts = blocks\n                .filter((c) => c.type === \"text\" && typeof c.text === \"string\")\n                .map((c) => c.text as string);\n\n              if (textParts.length > 0) {\n                await emit({\n                  type: \"message\",\n                  role: message.role as \"user\" | \"assistant\" | \"system\",\n                  text: textParts.join(\"\"),\n                  id: message.id,\n                });\n              }\n\n              const toolUses = blocks.filter((c) => c.type === \"tool_use\");\n              for (const toolUseContent of toolUses) {\n                const id =\n                  toolUseContent.id ??\n                  toolUseContent.toolUseId ??\n                  toolUseContent.tool_use_id ??\n                  toolUseContent.tool_call_id ??\n                  toolUseContent.callId ??\n                  toolUseContent.call_id ??\n                  randomUUID();\n                const name =\n                  toolUseContent.name ?? toolUseContent.toolName ?? toolUseContent.tool_name;\n                await emit({\n                  type: \"message\",\n                  role: message.role as \"user\" | \"assistant\" | \"system\",\n                  id: message.id,\n                  toolUse: {\n                    id,\n                    name: name || \"unknown\",\n                    input: toolUseContent.input,\n                  },\n                });\n              }\n\n              // If we were waiting for this assistant message, now complete\n              if (message.role === \"assistant\") {\n                isStreamingAssistant = false;\n                if (pendingIdleTimer) {\n                  clearTimeout(pendingIdleTimer);\n                  pendingIdleTimer = null;\n                }\n                if (pendingIdle) {\n                  await emit({ type: \"complete\" });\n                  pendingIdle = false;\n                }\n              }\n            }\n            break;\n          }\n\n          case \"tool_result\": {\n            const toolUseIdRaw =\n              (notification as Record<string, unknown>).toolUseId ??\n              (notification as Record<string, unknown>).tool_use_id ??\n              (notification as Record<string, unknown>).tool_call_id ??\n              (notification as Record<string, unknown>).callId ??\n              (notification as Record<string, unknown>).call_id ??\n              (notification as Record<string, unknown>).id;\n            const toolUseId = typeof toolUseIdRaw === \"string\" ? toolUseIdRaw : null;\n\n            const rawContent =\n              (notification as Record<string, unknown>).content ??\n              (notification as Record<string, unknown>).value;\n            const content =\n              typeof rawContent === \"string\"\n                ? rawContent\n                : JSON.stringify(rawContent ?? \"\", null, 2);\n\n            const isErrorRaw =\n              (notification as Record<string, unknown>).isError ??\n              (notification as Record<string, unknown>).is_error;\n            const isError = typeof isErrorRaw === \"boolean\" ? isErrorRaw : false;\n\n            if (!toolUseId) {\n              logger.error(\"Missing tool_use_id/toolUseId for tool_result notification\");\n              break;\n            }\n            await emit({\n              type: \"tool_result\",\n              toolUseId,\n              content,\n              isError,\n            });\n            break;\n          }\n\n          case \"error\": {\n            isStreamingAssistant = false;\n            pendingIdle = false;\n            const message =\n              typeof notification.message === \"string\"\n                ? (notification.message as string)\n                : JSON.stringify(notification.message ?? \"Unknown error\");\n            await emit({ type: \"error\", message });\n            break;\n          }\n        }\n      }\n\n      // Handle incoming requests (like permissions)\n      if (msg.type === \"request\") {\n        const requestId = msg.id;\n        const method = msg.method;\n        const params = msg.params;\n\n        if (requestHandler && method === \"droid.request_permission\") {\n          try {\n            const result = await requestHandler(method, params);\n            const response = {\n              jsonrpc: \"2.0\" as const,\n              factoryApiVersion: \"1.0.0\" as const,\n              type: \"response\" as const,\n              id: requestId,\n              result,\n            };\n            if (process?.stdin) {\n              process.stdin.write(JSON.stringify(response) + \"\\n\");\n            }\n          } catch (error: unknown) {\n            const errorMessage = error instanceof Error ? error.message : \"Internal error\";\n            const response = {\n              jsonrpc: \"2.0\" as const,\n              factoryApiVersion: \"1.0.0\" as const,\n              type: \"response\" as const,\n              id: requestId,\n              error: {\n                code: -32603,\n                message: errorMessage,\n              },\n            };\n            if (process?.stdin) {\n              process.stdin.write(JSON.stringify(response) + \"\\n\");\n            }\n          }\n        } else if (method === \"droid.request_permission\") {\n          // Auto-approve as fallback if no handler\n          const response = {\n            jsonrpc: \"2.0\" as const,\n            factoryApiVersion: \"1.0.0\" as const,\n            type: \"response\" as const,\n            id: requestId,\n            result: { selectedOption: \"proceed_once\" },\n          };\n          if (process?.stdin) {\n            process.stdin.write(JSON.stringify(response) + \"\\n\");\n          }\n          logger.log(\"Auto-approved permission request (fallback):\", requestId);\n        }\n      }\n    } catch (err) {\n      logger.error(\"Parse error:\", (err as Error).message);\n    }\n  };\n\n  const stopWebsearchProxy = () => {\n    if (!websearchProxy) return;\n    const proxy = websearchProxy;\n    websearchProxy = null;\n    proxy.close().catch((err: unknown) => logger.error(\"[websearch] proxy close failed:\", err));\n  };\n\n  return {\n    async start(): Promise<InitSessionResult> {\n      const executable = findDroidExecutable();\n      const args = [\n        \"exec\",\n        \"--input-format\",\n        \"stream-jsonrpc\",\n        \"--output-format\",\n        \"stream-jsonrpc\",\n        \"--cwd\",\n        options.cwd,\n      ];\n      if (typeof options.resumeSessionId === \"string\" && options.resumeSessionId.length > 0) {\n        args.push(\"--session-id\", options.resumeSessionId);\n      }\n\n      logger.log(\"Starting droid:\", executable, args.join(\" \"));\n\n      const env: NodeJS.ProcessEnv = {\n        ...globalThis.process.env,\n        FORCE_COLOR: \"0\",\n      };\n\n      const reasoningEffort = env.DROID_ACP_REASONING_EFFORT;\n      if (typeof reasoningEffort === \"string\" && reasoningEffort.trim().length > 0) {\n        args.push(\"--reasoning-effort\", reasoningEffort.trim());\n      }\n\n      // Experimental: Native websearch proxy mode (--websearch-proxy flag)\n      const useNativeWebsearch = isEnvEnabled(env.DROID_ACP_WEBSEARCH_NATIVE);\n\n      if (useNativeWebsearch) {\n        stopWebsearchProxy();\n        const host = env.DROID_ACP_WEBSEARCH_HOST ?? \"127.0.0.1\";\n        const portRaw = env.DROID_ACP_WEBSEARCH_PORT;\n        let port: number | undefined;\n        if (typeof portRaw === \"string\" && portRaw.length > 0) {\n          const parsed = Number.parseInt(portRaw, 10);\n          if (Number.isNaN(parsed) || parsed < 0 || parsed > 65535) {\n            throw new Error(`Invalid DROID_ACP_WEBSEARCH_PORT: ${portRaw}`);\n          }\n          port = parsed;\n        }\n        const factoryApiUrl =\n          env.DROID_ACP_WEBSEARCH_UPSTREAM_URL ??\n          env.FACTORY_API_BASE_URL ??\n          env.FACTORY_API_BASE_URL_OVERRIDE ??\n          \"https://api.factory.ai\";\n\n        logger.log(\"[websearch] Starting native provider proxy (experimental)...\");\n        websearchProxy = await startNativeWebsearchProxy({\n          factoryApiUrl,\n          host,\n          port,\n          logger,\n        });\n\n        if (!env.FACTORY_API_KEY) {\n          env.FACTORY_API_KEY = \"droid-acp-websearch\";\n        }\n        env.FACTORY_API_BASE_URL_OVERRIDE = websearchProxy.baseUrl;\n        env.FACTORY_API_BASE_URL = websearchProxy.baseUrl;\n      } else {\n        // Standard websearch proxy mode\n        const hasExplicitToggle = typeof env.DROID_ACP_WEBSEARCH === \"string\";\n        const smitheryConfigured =\n          typeof env.SMITHERY_API_KEY === \"string\" &&\n          env.SMITHERY_API_KEY.trim().length > 0 &&\n          typeof env.SMITHERY_PROFILE === \"string\" &&\n          env.SMITHERY_PROFILE.trim().length > 0;\n        const forwardConfigured =\n          typeof env.DROID_ACP_WEBSEARCH_FORWARD_URL === \"string\" &&\n          env.DROID_ACP_WEBSEARCH_FORWARD_URL.trim().length > 0;\n\n        const enableWebsearchProxy = hasExplicitToggle\n          ? isEnvEnabled(env.DROID_ACP_WEBSEARCH)\n          : smitheryConfigured || forwardConfigured;\n\n        if (enableWebsearchProxy) {\n          stopWebsearchProxy();\n\n          const upstreamBaseUrl =\n            env.DROID_ACP_WEBSEARCH_UPSTREAM_URL ??\n            env.FACTORY_API_BASE_URL ??\n            env.FACTORY_API_BASE_URL_OVERRIDE ??\n            \"https://api.factory.ai\";\n          const forwardModeRaw = env.DROID_ACP_WEBSEARCH_FORWARD_MODE;\n\n          const forwardUrlRaw =\n            typeof env.DROID_ACP_WEBSEARCH_FORWARD_URL === \"string\"\n              ? env.DROID_ACP_WEBSEARCH_FORWARD_URL.trim()\n              : \"\";\n          const forwardPrefixMatch = forwardUrlRaw.match(/^mcp:(.*)$/i);\n          const websearchForwardUrl = forwardUrlRaw.length > 0 ? forwardUrlRaw : undefined;\n          const forwardModeNormalized =\n            typeof forwardModeRaw === \"string\" ? forwardModeRaw.trim().toLowerCase() : \"\";\n          const websearchForwardMode =\n            forwardModeNormalized === \"mcp\"\n              ? (\"mcp\" as const)\n              : forwardModeNormalized === \"http\"\n                ? (\"http\" as const)\n                : forwardPrefixMatch\n                  ? (\"mcp\" as const)\n                  : (\"http\" as const);\n          const host = env.DROID_ACP_WEBSEARCH_HOST ?? \"127.0.0.1\";\n\n          const portRaw = env.DROID_ACP_WEBSEARCH_PORT;\n          let port: number | undefined;\n          if (typeof portRaw === \"string\" && portRaw.length > 0) {\n            const parsed = Number.parseInt(portRaw, 10);\n            if (Number.isNaN(parsed) || parsed < 0 || parsed > 65535) {\n              throw new Error(`Invalid DROID_ACP_WEBSEARCH_PORT: ${portRaw}`);\n            }\n            port = parsed;\n          }\n\n          websearchProxy = await startWebsearchProxy({\n            upstreamBaseUrl,\n            websearchForwardUrl: forwardPrefixMatch\n              ? forwardPrefixMatch[1]?.trim()\n              : websearchForwardUrl,\n            websearchForwardMode,\n            smitheryApiKey: env.SMITHERY_API_KEY,\n            smitheryProfile: env.SMITHERY_PROFILE,\n            host,\n            port,\n            logger,\n          });\n\n          // Droid requires an auth header for tool calls (including websearch) and will error early if missing.\n          // Since websearch is intercepted by the local proxy, any non-empty value is sufficient here.\n          if (!env.FACTORY_API_KEY) {\n            env.FACTORY_API_KEY = \"droid-acp-websearch\";\n          }\n\n          env.FACTORY_API_BASE_URL_OVERRIDE = websearchProxy.baseUrl;\n          env.FACTORY_API_BASE_URL = websearchProxy.baseUrl;\n        }\n      }\n\n      process = spawn(executable, args, {\n        stdio: [\"pipe\", \"pipe\", \"pipe\"],\n        env,\n        // Windows compatibility\n        shell: isWindows,\n        windowsHide: true,\n      });\n\n      if (process.stdout) {\n        createInterface({ input: process.stdout }).on(\"line\", queueLine);\n      }\n      if (process.stderr) {\n        createInterface({ input: process.stderr }).on(\"line\", (l) =>\n          logger.error(\"[droid stderr]\", l),\n        );\n      }\n\n      process.on(\"error\", (err) => {\n        if (initReject) initReject(err);\n      });\n      process.on(\"exit\", (code) => {\n        logger.log(\"Droid exit:\", code);\n        process = null;\n        stopWebsearchProxy();\n        exitHandlers.forEach((h) => h(code));\n      });\n\n      return new Promise((resolve, reject) => {\n        initResolve = resolve;\n        initReject = reject;\n        send(\"droid.initialize_session\", { machineId, cwd: options.cwd });\n\n        const initTimeout = parseInt(globalThis.process.env.DROID_INIT_TIMEOUT || \"60000\", 10);\n        setTimeout(() => {\n          if (initReject) {\n            initReject(new Error(\"Droid init timeout\"));\n            initResolve = null;\n            initReject = null;\n          }\n        }, initTimeout);\n      });\n    },\n\n    sendMessage(text: string) {\n      this.sendUserMessage({ text });\n    },\n\n    sendUserMessage(message: {\n      text: string;\n      images?: Array<{ type: \"base64\"; data: string; mediaType: string }>;\n    }) {\n      if (!sessionId) return;\n      const params: Record<string, unknown> = {\n        sessionId,\n        text: message.text,\n      };\n      if (Array.isArray(message.images) && message.images.length > 0) {\n        params.images = message.images;\n      }\n      send(\"droid.add_user_message\", params);\n    },\n\n    getWebsearchProxyBaseUrl(): string | null {\n      return websearchProxy?.baseUrl ?? null;\n    },\n\n    setMode(level: DroidAutonomyLevel) {\n      if (!sessionId) return;\n      send(\"droid.update_session_settings\", {\n        sessionId,\n        autonomyLevel: level,\n      });\n    },\n\n    setModel(modelId: string) {\n      if (!sessionId) return;\n      send(\"droid.update_session_settings\", {\n        sessionId,\n        modelId,\n      });\n    },\n\n    onNotification(handler) {\n      notificationHandlers.push(handler);\n    },\n\n    onRawEvent(handler) {\n      rawEventHandlers.push(handler);\n    },\n\n    onRequest(handler) {\n      requestHandler = handler;\n    },\n\n    onExit(handler) {\n      exitHandlers.push(handler);\n    },\n\n    async stop() {\n      if (process) {\n        process.stdin?.end();\n        process.kill(\"SIGTERM\");\n        process = null;\n      }\n      stopWebsearchProxy();\n    },\n\n    isRunning() {\n      return process !== null && !process.killed;\n    },\n\n    getSessionId() {\n      return sessionId;\n    },\n  };\n}\n","import type { AvailableCommand } from \"@agentclientprotocol/sdk\";\nimport { isExperimentSessionsEnabled } from \"./flags.ts\";\n\n// Available slash commands for ACP adapter\n// Note: Most commands are implemented via Droid's JSON-RPC API, but a few are implemented\n// in the adapter itself (e.g. /context, /compress, /sessions).\nexport function getAvailableCommands(): AvailableCommand[] {\n  const commands: AvailableCommand[] = [\n    {\n      name: \"help\",\n      description: \"Show available slash commands\",\n      input: null,\n    },\n    {\n      name: \"context\",\n      description: \"Show token usage (context indicator) for this session\",\n      input: null,\n    },\n    {\n      name: \"compress\",\n      description: \"Compress conversation history (summary + restart)\",\n      input: { hint: \"[optional instructions]\" },\n    },\n    {\n      name: \"compact\",\n      description: \"Alias for /compress\",\n      input: { hint: \"[optional instructions]\" },\n    },\n    {\n      name: \"model\",\n      description: \"Show or change the current model\",\n      input: { hint: \"[model_id]\" },\n    },\n    {\n      name: \"mode\",\n      description: \"Show or change the autonomy mode (off|low|medium|high|spec)\",\n      input: { hint: \"[mode]\" },\n    },\n    {\n      name: \"config\",\n      description: \"Show current session configuration\",\n      input: null,\n    },\n    {\n      name: \"status\",\n      description: \"Show current session status\",\n      input: null,\n    },\n  ];\n\n  if (isExperimentSessionsEnabled()) {\n    commands.push({\n      name: \"sessions\",\n      description: \"List or load previous sessions (local Droid history)\",\n      input: { hint: \"[load <#|id_prefix|session_id>|all]\" },\n    });\n  }\n\n  return commands;\n}\n","import type { AgentSideConnection } from \"@agentclientprotocol/sdk\";\nimport { getAvailableCommands } from \"../commands.ts\";\nimport { droidAutonomyToAcpModeId } from \"../constants.ts\";\nimport type { DroidAdapter } from \"../../droid-adapter.ts\";\nimport type { Session } from \"../session-types.ts\";\nimport type {\n  AcpModeId,\n  DroidNotification,\n  InitSessionResult,\n  PermissionRequest,\n} from \"../../types.ts\";\nimport type { Logger } from \"../../utils.ts\";\nimport { isEnvEnabled } from \"../../utils.ts\";\n\nexport function attachSession(params: {\n  sessionId: string;\n  cwd: string;\n  droid: DroidAdapter;\n  initResult: InitSessionResult;\n  title?: string | null;\n  client: AgentSideConnection;\n  logger: Logger;\n  sessions: Map<string, Session>;\n  handlers: {\n    handleNotification: (session: Session, n: DroidNotification) => Promise<void>;\n    handlePermission: (\n      session: Session,\n      params: PermissionRequest,\n    ) => Promise<{ selectedOption: string }>;\n  };\n}): { session: Session; initialMode: AcpModeId } {\n  const { sessionId, cwd, droid, initResult } = params;\n\n  const initialMode =\n    typeof initResult.settings?.autonomyLevel === \"string\"\n      ? (droidAutonomyToAcpModeId(initResult.settings.autonomyLevel) ?? \"off\")\n      : \"off\";\n\n  const now = new Date().toISOString();\n  const session: Session = {\n    id: sessionId,\n    droid,\n    droidSessionId: initResult.sessionId,\n    title: typeof params.title === \"string\" ? params.title : \"New Session\",\n    updatedAt: now,\n    pendingHistoryContext: null,\n    model: initResult.settings?.modelId || \"unknown\",\n    mode: initialMode,\n    keepAliveOnDroidExit: false,\n    cancelled: false,\n    restartPromise: null,\n    promptResolve: null,\n    capture: null,\n    lastSessionsListing: null,\n    toolCallContentById: new Map(),\n    toolCallRawInputById: new Map(),\n    activeToolCallIds: new Set(),\n    toolCallStatus: new Map(),\n    toolNames: new Map(),\n    availableModels: initResult.availableModels,\n    cwd,\n    specChoice: null,\n    specChoicePromptSignature: null,\n    specPlanDetailsSignature: null,\n    specPlanDetailsToolCallId: null,\n  };\n\n  // Set up notification handler\n  droid.onNotification((n) => {\n    const current = params.sessions.get(sessionId);\n    if (!current || current.droid !== droid) return;\n    void params.handlers.handleNotification(current, n);\n  });\n\n  // Forward raw events for debugging (enable with DROID_DEBUG=1)\n  if (process.env.DROID_DEBUG) {\n    droid.onRawEvent(async (event) => {\n      const current = params.sessions.get(sessionId);\n      if (!current || current.droid !== droid) return;\n      await params.client.sessionUpdate({\n        sessionId: current.id,\n        update: {\n          sessionUpdate: \"agent_message_chunk\",\n          content: {\n            type: \"text\",\n            text: `\\n\\`\\`\\`json\\n${JSON.stringify(event, null, 2)}\\n\\`\\`\\`\\n`,\n          },\n        },\n      });\n    });\n  }\n\n  // Handle permission requests\n  droid.onRequest(async (method, p) => {\n    const current = params.sessions.get(sessionId);\n    if (!current || current.droid !== droid) {\n      return { selectedOption: \"proceed_once\" };\n    }\n    if (method === \"droid.request_permission\") {\n      return params.handlers.handlePermission(current, p as PermissionRequest);\n    }\n    throw new Error(\"Method not supported\");\n  });\n\n  // Handle droid process exit\n  droid.onExit((code) => {\n    const current = params.sessions.get(sessionId);\n    if (!current || current.droid !== droid) {\n      params.logger.log(\"Droid exited (stale), ignoring:\", sessionId, \"code:\", code);\n      return;\n    }\n\n    if (current.keepAliveOnDroidExit) {\n      params.logger.log(\n        \"Droid exited (restart requested), keeping session:\",\n        sessionId,\n        \"code:\",\n        code,\n      );\n      current.keepAliveOnDroidExit = false;\n      if (current.promptResolve) {\n        current.promptResolve({ stopReason: \"end_turn\" });\n        current.promptResolve = null;\n      }\n      return;\n    }\n\n    params.logger.log(\"Droid exited, cleaning up session:\", sessionId, \"code:\", code);\n    if (current.promptResolve) {\n      current.promptResolve({ stopReason: \"end_turn\" });\n      current.promptResolve = null;\n    }\n    params.sessions.delete(sessionId);\n  });\n\n  params.sessions.set(sessionId, session);\n  params.logger.log(\"Session created:\", sessionId);\n\n  // Ensure clients can track sessions and populate \"History\" UIs.\n  setTimeout(() => {\n    void params.client.sessionUpdate({\n      sessionId,\n      update: {\n        sessionUpdate: \"session_info_update\",\n        title: session.title,\n        updatedAt: session.updatedAt,\n      },\n    });\n  }, 0);\n\n  // Optional diagnostics for Zed env + websearch proxy wiring.\n  // Enable with DROID_DEBUG=1.\n  const shouldEmitWebsearchStatus = isEnvEnabled(process.env.DROID_DEBUG);\n  if (shouldEmitWebsearchStatus) {\n    const websearchProxyBaseUrl = droid.getWebsearchProxyBaseUrl();\n    const parentFactoryApiKey = process.env.FACTORY_API_KEY;\n    const hasExplicitToggle = typeof process.env.DROID_ACP_WEBSEARCH === \"string\";\n    const smitheryConfigured =\n      typeof process.env.SMITHERY_API_KEY === \"string\" &&\n      process.env.SMITHERY_API_KEY.trim().length > 0 &&\n      typeof process.env.SMITHERY_PROFILE === \"string\" &&\n      process.env.SMITHERY_PROFILE.trim().length > 0;\n    const forwardConfigured =\n      typeof process.env.DROID_ACP_WEBSEARCH_FORWARD_URL === \"string\" &&\n      process.env.DROID_ACP_WEBSEARCH_FORWARD_URL.trim().length > 0;\n    const websearchEnabled = hasExplicitToggle\n      ? isEnvEnabled(process.env.DROID_ACP_WEBSEARCH)\n      : smitheryConfigured || forwardConfigured;\n    const willInjectDummyFactoryApiKey = websearchEnabled && !parentFactoryApiKey;\n\n    const forwardModeRaw = process.env.DROID_ACP_WEBSEARCH_FORWARD_MODE;\n    const forwardModeNormalized =\n      typeof forwardModeRaw === \"string\" ? forwardModeRaw.trim().toLowerCase() : \"\";\n    const forwardUrlRaw = process.env.DROID_ACP_WEBSEARCH_FORWARD_URL ?? \"\";\n    const forwardModeEffective =\n      forwardModeNormalized === \"mcp\"\n        ? \"mcp\"\n        : forwardModeNormalized === \"http\"\n          ? \"http\"\n          : /^mcp:/i.test(forwardUrlRaw.trim())\n            ? \"mcp\"\n            : \"http\";\n\n    setTimeout(() => {\n      void params.client.sessionUpdate({\n        sessionId,\n        update: {\n          sessionUpdate: \"agent_message_chunk\",\n          content: {\n            type: \"text\",\n            text:\n              [\n                \"[droid-acp] WebSearch status\",\n                `- DROID_ACP_WEBSEARCH: ${process.env.DROID_ACP_WEBSEARCH ?? \"<unset>\"}`,\n                `- enabled: ${websearchEnabled ? \"true\" : \"false\"}${hasExplicitToggle ? \"\" : \" (auto)\"}`,\n                `- DROID_ACP_WEBSEARCH_PORT: ${process.env.DROID_ACP_WEBSEARCH_PORT ?? \"<unset>\"}`,\n                `- DROID_ACP_WEBSEARCH_FORWARD_MODE: ${process.env.DROID_ACP_WEBSEARCH_FORWARD_MODE ?? \"<unset>\"}`,\n                `- forwardMode: ${forwardModeEffective}`,\n                `- DROID_ACP_WEBSEARCH_FORWARD_URL: ${process.env.DROID_ACP_WEBSEARCH_FORWARD_URL ?? \"<unset>\"}`,\n                `- FACTORY_API_KEY: ${parentFactoryApiKey ? \"set\" : \"<unset>\"}${willInjectDummyFactoryApiKey ? \" (droid child auto-inject dummy)\" : \"\"}`,\n                `- SMITHERY_API_KEY: ${process.env.SMITHERY_API_KEY ? \"set\" : \"<unset>\"}`,\n                `- SMITHERY_PROFILE: ${process.env.SMITHERY_PROFILE ? \"set\" : \"<unset>\"}`,\n                `- proxyBaseUrl: ${websearchProxyBaseUrl ?? \"<not running>\"}`,\n                websearchProxyBaseUrl ? `- health: ${websearchProxyBaseUrl}/health` : null,\n              ]\n                .filter((l): l is string => typeof l === \"string\")\n                .join(\"\\n\") + \"\\n\",\n          },\n        },\n      });\n    }, 0);\n  }\n\n  // Send available commands update after session response\n  setTimeout(() => {\n    void params.client.sessionUpdate({\n      sessionId,\n      update: {\n        sessionUpdate: \"available_commands_update\",\n        availableCommands: getAvailableCommands(),\n      },\n    });\n  }, 0);\n\n  return { session, initialMode };\n}\n","import type { AgentSideConnection } from \"@agentclientprotocol/sdk\";\nimport { createDroidAdapter, type DroidAdapter } from \"../../droid-adapter.ts\";\nimport type { InitSessionResult, PermissionRequest, DroidNotification } from \"../../types.ts\";\nimport { ACP_MODE_TO_DROID_AUTONOMY } from \"../constants.ts\";\nimport type { Session } from \"../session-types.ts\";\nimport { attachSession } from \"./attach-session.ts\";\nimport type { Logger } from \"../../utils.ts\";\n\nexport async function finalizeActiveToolCalls(params: {\n  client: AgentSideConnection;\n  session: Session;\n  message: string;\n}): Promise<void> {\n  const active = [...params.session.activeToolCallIds];\n  if (active.length === 0) return;\n\n  params.session.activeToolCallIds.clear();\n  for (const toolCallId of active) {\n    params.session.toolCallStatus.set(toolCallId, \"completed\");\n    await params.client.sessionUpdate({\n      sessionId: params.session.id,\n      update: {\n        sessionUpdate: \"tool_call_update\",\n        toolCallId,\n        status: \"completed\",\n        content: [\n          {\n            type: \"content\",\n            content: { type: \"text\", text: params.message },\n          },\n        ],\n      },\n    });\n  }\n}\n\nexport async function restartDroidSession(\n  ctx: {\n    client: AgentSideConnection;\n    logger: Logger;\n    sessions: Map<string, Session>;\n    handlers: {\n      handleNotification: (session: Session, n: DroidNotification) => Promise<void>;\n      handlePermission: (\n        session: Session,\n        params: PermissionRequest,\n      ) => Promise<{ selectedOption: string }>;\n    };\n  },\n  params: { sessionId: string; reason: string },\n): Promise<void> {\n  const session = ctx.sessions.get(params.sessionId);\n  if (!session) return;\n  if (session.restartPromise) return session.restartPromise;\n\n  const oldDroid = session.droid;\n  const cwd = session.cwd;\n  const title = session.title;\n  const oldMode = session.mode;\n  const oldModel = session.model;\n  const pendingHistoryContext = session.pendingHistoryContext;\n  const resumeSessionId = session.droidSessionId;\n\n  session.keepAliveOnDroidExit = true;\n  session.restartPromise = (async () => {\n    ctx.logger.log(\"Restarting droid session:\", params.sessionId, \"reason:\", params.reason);\n\n    // Stop the old process first so we can safely resume/replace it.\n    try {\n      await oldDroid.stop();\n    } catch (err: unknown) {\n      ctx.logger.error(\"Failed to stop droid (during restart):\", err);\n    }\n\n    const startFresh = async (): Promise<{ droid: DroidAdapter; init: InitSessionResult }> => {\n      const droid = createDroidAdapter({ cwd, logger: ctx.logger });\n      const init = await droid.start();\n      return { droid, init };\n    };\n\n    const startResumed = async (\n      sessionId: string,\n    ): Promise<{ droid: DroidAdapter; init: InitSessionResult }> => {\n      const droid = createDroidAdapter({ cwd, logger: ctx.logger, resumeSessionId: sessionId });\n      const init = await droid.start();\n      return { droid, init };\n    };\n\n    let started: { droid: DroidAdapter; init: InitSessionResult };\n    try {\n      started =\n        typeof resumeSessionId === \"string\" && resumeSessionId.length > 0\n          ? await startResumed(resumeSessionId)\n          : await startFresh();\n    } catch (err: unknown) {\n      ctx.logger.error(\"Failed to resume droid session, starting fresh:\", err);\n      started = await startFresh();\n    }\n\n    const { droid, init } = started;\n    const { session: newSession } = attachSession({\n      sessionId: params.sessionId,\n      cwd,\n      droid,\n      initResult: init,\n      title: typeof title === \"string\" ? title : null,\n      client: ctx.client,\n      logger: ctx.logger,\n      sessions: ctx.sessions,\n      handlers: ctx.handlers,\n    });\n\n    newSession.pendingHistoryContext = pendingHistoryContext;\n\n    // Best-effort: preserve the current mode/model across the restart.\n    newSession.mode = oldMode;\n    newSession.droid.setMode(ACP_MODE_TO_DROID_AUTONOMY[oldMode]);\n    await ctx.client.sessionUpdate({\n      sessionId: newSession.id,\n      update: {\n        sessionUpdate: \"current_mode_update\",\n        currentModeId: oldMode,\n      },\n    });\n\n    if (newSession.availableModels.some((m) => m.id === oldModel)) {\n      newSession.model = oldModel;\n      newSession.droid.setModel(oldModel);\n    }\n\n    newSession.cancelled = false;\n  })()\n    .catch((err: unknown) => {\n      ctx.logger.error(\"restartDroidSession failed:\", err);\n    })\n    .finally(() => {\n      const current = ctx.sessions.get(params.sessionId);\n      if (current) {\n        current.restartPromise = null;\n        current.keepAliveOnDroidExit = false;\n        current.cancelled = false;\n      }\n    });\n\n  return session.restartPromise;\n}\n\nexport async function getReadySession(\n  ctx: {\n    sessions: Map<string, Session>;\n    restartDroidSession: (params: { sessionId: string; reason: string }) => Promise<void>;\n  },\n  params: { sessionId: string; reason: string },\n): Promise<Session> {\n  const { sessionId } = params;\n  let session = ctx.sessions.get(sessionId);\n  if (!session) throw new Error(`Session not found: ${sessionId}`);\n\n  if (session.restartPromise) {\n    await session.restartPromise;\n    session = ctx.sessions.get(sessionId);\n    if (!session) throw new Error(`Session not found: ${sessionId}`);\n  }\n\n  if (session.cancelled || !session.droid.isRunning()) {\n    await ctx.restartDroidSession({ sessionId, reason: params.reason });\n    session = ctx.sessions.get(sessionId);\n    if (!session) throw new Error(`Session not found: ${sessionId}`);\n  }\n\n  return session;\n}\n","import { getAvailableCommands } from \"../../commands.ts\";\nimport type { Session } from \"../../session-types.ts\";\nimport { sendAgentMessage } from \"../messages.ts\";\nimport type { AgentRuntime } from \"../runtime.ts\";\n\nexport async function handleHelp(\n  ctx: AgentRuntime,\n  session: Session,\n  header?: string,\n): Promise<void> {\n  const commands = getAvailableCommands();\n  const helpText = [\n    header ? `${header}\\n` : null,\n    \"**Available Commands:**\\n\",\n    ...commands.map((cmd) => {\n      const inputHint = cmd.input && \"hint\" in cmd.input ? ` ${cmd.input.hint}` : \"\";\n      return `- /${cmd.name}${inputHint} - ${cmd.description}`;\n    }),\n  ]\n    .filter((l): l is string => typeof l === \"string\")\n    .join(\"\\n\");\n\n  await sendAgentMessage(ctx.client, session, helpText);\n}\n","import { createReadStream } from \"node:fs\";\nimport { promises as fs } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { createInterface } from \"node:readline\";\n\nexport interface FactorySessionRecord {\n  sessionId: string;\n  cwd: string;\n  title: string | null;\n  updatedAt: string | null;\n  jsonlPath: string;\n}\n\nexport interface FactorySessionSettings {\n  assistantActiveTimeMs?: number;\n  model?: string;\n  reasoningEffort?: string;\n  autonomyMode?: string;\n  tokenUsage?: {\n    inputTokens?: number;\n    outputTokens?: number;\n    cacheCreationTokens?: number;\n    cacheReadTokens?: number;\n    thinkingTokens?: number;\n  };\n}\n\nconst DEFAULT_PAGE_SIZE = 50;\nconst HEADER_SCAN_BYTES = 8192;\n\nexport function getFactoryDir(): string {\n  return process.env.DROID_ACP_FACTORY_DIR ?? path.join(os.homedir(), \".factory\");\n}\n\nfunction getFactorySessionsDir(): string {\n  return path.join(getFactoryDir(), \"sessions\");\n}\n\nfunction encodeCwdToFactorySessionsDirName(cwd: string): string {\n  // Droid stores sessions under ~/.factory/sessions/<cwd-with-path-separators-replaced-by-dashes>\n  // Example: /Users/me/project -> -Users-me-project\n  return cwd.replace(/[\\\\/]/g, \"-\");\n}\n\nasync function pathExists(targetPath: string): Promise<boolean> {\n  try {\n    await fs.access(targetPath);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nexport async function readFactorySessionStart(\n  jsonlPath: string,\n): Promise<{ cwd: string | null; title: string | null } | null> {\n  const handle = await fs.open(jsonlPath, \"r\");\n  try {\n    const buffer = Buffer.alloc(HEADER_SCAN_BYTES);\n    const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);\n    const chunk = buffer.toString(\"utf8\", 0, bytesRead);\n    const firstLine = chunk.split(/\\r?\\n/, 1)[0]?.trim();\n    if (!firstLine) return null;\n\n    const parsed = JSON.parse(firstLine) as unknown;\n    const obj = parsed as { type?: unknown; cwd?: unknown; title?: unknown };\n    if (obj.type !== \"session_start\") return null;\n\n    return {\n      cwd: typeof obj.cwd === \"string\" ? obj.cwd : null,\n      title: typeof obj.title === \"string\" ? obj.title : null,\n    };\n  } catch {\n    return null;\n  } finally {\n    await handle.close();\n  }\n}\n\nasync function factorySessionHasMessages(jsonlPath: string): Promise<boolean> {\n  const handle = await fs.open(jsonlPath, \"r\");\n  try {\n    const buffer = Buffer.alloc(HEADER_SCAN_BYTES);\n    const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);\n    if (bytesRead <= 0) return false;\n\n    const chunk = buffer.toString(\"utf8\", 0, bytesRead);\n    const newlineIndex = chunk.indexOf(\"\\n\");\n    if (newlineIndex === -1) {\n      const stat = await handle.stat();\n      return stat.size > bytesRead;\n    }\n\n    if (chunk.slice(newlineIndex + 1).trim().length > 0) return true;\n\n    const stat = await handle.stat();\n    return stat.size > newlineIndex + 1;\n  } catch {\n    return false;\n  } finally {\n    await handle.close();\n  }\n}\n\nexport async function resolveFactorySessionJsonlPath(params: {\n  sessionId: string;\n  cwd: string;\n}): Promise<string | null> {\n  const sessionsDir = getFactorySessionsDir();\n  const direct = path.join(\n    sessionsDir,\n    encodeCwdToFactorySessionsDirName(params.cwd),\n    `${params.sessionId}.jsonl`,\n  );\n  if (await pathExists(direct)) return direct;\n\n  // Fallback: scan all cwd directories (useful if the client passed a different cwd).\n  let dirents: Array<{ name: string; isDirectory?: () => boolean }> = [];\n  try {\n    dirents = (await fs.readdir(sessionsDir, { withFileTypes: true })) as typeof dirents;\n  } catch {\n    return null;\n  }\n\n  for (const d of dirents) {\n    if (typeof d.isDirectory === \"function\" && !d.isDirectory()) continue;\n    const candidate = path.join(sessionsDir, d.name, `${params.sessionId}.jsonl`);\n    if (await pathExists(candidate)) return candidate;\n  }\n\n  return null;\n}\n\nexport async function resolveFactorySessionSettingsJsonPath(params: {\n  sessionId: string;\n  cwd: string;\n}): Promise<string | null> {\n  const sessionsDir = getFactorySessionsDir();\n  const direct = path.join(\n    sessionsDir,\n    encodeCwdToFactorySessionsDirName(params.cwd),\n    `${params.sessionId}.settings.json`,\n  );\n  if (await pathExists(direct)) return direct;\n\n  // Fallback: scan all cwd directories (useful if the client passed a different cwd).\n  let dirents: Array<{ name: string; isDirectory?: () => boolean }> = [];\n  try {\n    dirents = (await fs.readdir(sessionsDir, { withFileTypes: true })) as typeof dirents;\n  } catch {\n    return null;\n  }\n\n  for (const d of dirents) {\n    if (typeof d.isDirectory === \"function\" && !d.isDirectory()) continue;\n    const candidate = path.join(sessionsDir, d.name, `${params.sessionId}.settings.json`);\n    if (await pathExists(candidate)) return candidate;\n  }\n\n  return null;\n}\n\nexport async function readFactorySessionSettings(\n  settingsJsonPath: string,\n): Promise<FactorySessionSettings | null> {\n  try {\n    const raw = await fs.readFile(settingsJsonPath, \"utf8\");\n    const parsed = JSON.parse(raw) as unknown;\n    if (!parsed || typeof parsed !== \"object\") return null;\n    const obj = parsed as Record<string, unknown>;\n\n    const tokenUsageRaw = obj.tokenUsage;\n    const tokenUsage =\n      tokenUsageRaw && typeof tokenUsageRaw === \"object\"\n        ? (tokenUsageRaw as Record<string, unknown>)\n        : null;\n\n    const toNumber = (v: unknown): number | undefined => {\n      if (typeof v !== \"number\") return undefined;\n      return Number.isFinite(v) ? v : undefined;\n    };\n\n    return {\n      assistantActiveTimeMs: toNumber(obj.assistantActiveTimeMs),\n      model: typeof obj.model === \"string\" ? obj.model : undefined,\n      reasoningEffort: typeof obj.reasoningEffort === \"string\" ? obj.reasoningEffort : undefined,\n      autonomyMode: typeof obj.autonomyMode === \"string\" ? obj.autonomyMode : undefined,\n      tokenUsage: tokenUsage\n        ? {\n            inputTokens: toNumber(tokenUsage.inputTokens),\n            outputTokens: toNumber(tokenUsage.outputTokens),\n            cacheCreationTokens: toNumber(tokenUsage.cacheCreationTokens),\n            cacheReadTokens: toNumber(tokenUsage.cacheReadTokens),\n            thinkingTokens: toNumber(tokenUsage.thinkingTokens),\n          }\n        : undefined,\n    };\n  } catch {\n    return null;\n  }\n}\n\nexport async function listFactorySessions(params: {\n  cwd?: string | null;\n  cursor?: string | null;\n  preferredCwd?: string | null;\n  pageSize?: number;\n  includeEmpty?: boolean;\n}): Promise<{ sessions: FactorySessionRecord[]; nextCursor: string | null }> {\n  const pageSize = params.pageSize ?? DEFAULT_PAGE_SIZE;\n  const sessionsDir = getFactorySessionsDir();\n  const cwdFilter = typeof params.cwd === \"string\" && params.cwd.length > 0 ? params.cwd : null;\n  const preferredCwd =\n    typeof params.preferredCwd === \"string\" && params.preferredCwd.length > 0\n      ? params.preferredCwd\n      : null;\n  const includeEmpty = params.includeEmpty === true;\n\n  const scanDirs: string[] = [];\n  if (cwdFilter) {\n    scanDirs.push(path.join(sessionsDir, encodeCwdToFactorySessionsDirName(cwdFilter)));\n  } else {\n    try {\n      const dirents = await fs.readdir(sessionsDir, { withFileTypes: true });\n      for (const d of dirents) {\n        if (!d.isDirectory()) continue;\n        scanDirs.push(path.join(sessionsDir, d.name));\n      }\n    } catch {\n      return { sessions: [], nextCursor: null };\n    }\n  }\n\n  const records: FactorySessionRecord[] = [];\n  for (const dir of scanDirs) {\n    if (!(await pathExists(dir))) continue;\n\n    let entries: string[] = [];\n    try {\n      entries = await fs.readdir(dir);\n    } catch {\n      continue;\n    }\n\n    for (const entry of entries) {\n      if (!entry.endsWith(\".jsonl\")) continue;\n      const sessionId = entry.slice(0, -\".jsonl\".length);\n      const jsonlPath = path.join(dir, entry);\n\n      let updatedAt: string | null = null;\n      try {\n        const stat = await fs.stat(jsonlPath);\n        updatedAt = stat.mtime.toISOString();\n      } catch {}\n\n      const header = await readFactorySessionStart(jsonlPath);\n      const cwd = header?.cwd ?? cwdFilter ?? \"\";\n      if (cwd.length === 0) continue;\n      if (cwdFilter && cwd !== cwdFilter) continue;\n      if (!includeEmpty && !(await factorySessionHasMessages(jsonlPath))) continue;\n\n      records.push({\n        sessionId,\n        cwd,\n        title: header?.title ?? null,\n        updatedAt,\n        jsonlPath,\n      });\n    }\n  }\n\n  records.sort((a, b) => {\n    const aPreferred = preferredCwd !== null && a.cwd === preferredCwd;\n    const bPreferred = preferredCwd !== null && b.cwd === preferredCwd;\n    if (aPreferred !== bPreferred) return aPreferred ? -1 : 1;\n\n    const aTime = a.updatedAt ? Date.parse(a.updatedAt) : 0;\n    const bTime = b.updatedAt ? Date.parse(b.updatedAt) : 0;\n    return bTime - aTime;\n  });\n\n  const offset = (() => {\n    if (typeof params.cursor !== \"string\" || params.cursor.length === 0) return 0;\n    const parsed = Number.parseInt(params.cursor, 10);\n    return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;\n  })();\n\n  const sessions = records.slice(offset, offset + pageSize);\n  const nextCursor = offset + pageSize < records.length ? String(offset + pageSize) : null;\n\n  return { sessions, nextCursor };\n}\n\nexport async function* streamFactorySessionJsonl(jsonlPath: string): AsyncGenerator<unknown> {\n  const stream = createReadStream(jsonlPath, { encoding: \"utf8\" });\n  const rl = createInterface({ input: stream, crlfDelay: Infinity });\n  for await (const line of rl) {\n    const trimmed = line.trim();\n    if (!trimmed) continue;\n    try {\n      yield JSON.parse(trimmed) as unknown;\n    } catch {\n      continue;\n    }\n  }\n}\n","import path from \"node:path\";\nimport { open, type FileHandle } from \"node:fs/promises\";\nimport { getFactoryDir } from \"./factory-sessions.ts\";\n\nexport interface FactoryAgentStreamingResult {\n  timestamp: string | null;\n  inputTokens: number;\n  outputTokens: number;\n  cacheReadInputTokens: number;\n  cacheCreationInputTokens: number;\n  modelId: string | null;\n}\n\nexport function getFactoryLogFilePath(): string {\n  return path.join(getFactoryDir(), \"logs\", \"droid-log-single.log\");\n}\n\nexport async function readLastAgentStreamingResult(params: {\n  sessionId: string;\n  logFilePath?: string;\n  maxBytes?: number;\n  chunkBytes?: number;\n}): Promise<FactoryAgentStreamingResult | null> {\n  const logFilePath = params.logFilePath ?? getFactoryLogFilePath();\n  const maxBytes = params.maxBytes ?? 4 * 1024 * 1024;\n  const chunkBytes = params.chunkBytes ?? 256 * 1024;\n\n  let handle: FileHandle | null = null;\n  try {\n    handle = await open(logFilePath, \"r\");\n    const stat = await handle.stat();\n    const size = stat.size;\n    if (size <= 0) return null;\n\n    let offset = size;\n    let scanned = 0;\n    let carry = \"\";\n\n    while (offset > 0 && scanned < maxBytes) {\n      const start = Math.max(0, offset - chunkBytes);\n      const readSize = offset - start;\n      const buffer = Buffer.alloc(readSize);\n      const { bytesRead } = await handle.read(buffer, 0, buffer.length, start);\n      if (bytesRead <= 0) break;\n\n      scanned += bytesRead;\n      offset = start;\n\n      const text = buffer.toString(\"utf8\", 0, bytesRead);\n      const combined = text + carry;\n      const lines = combined.split(/\\r?\\n/);\n\n      // The first line may be truncated due to chunk boundaries; keep it for the next iteration.\n      carry = lines[0] ?? \"\";\n\n      for (let i = lines.length - 1; i >= 1; i--) {\n        const line = lines[i];\n        if (!line) continue;\n        if (!line.includes(\"[Agent] Streaming result\")) continue;\n        if (!line.includes(`\"sessionId\":\"${params.sessionId}\"`)) continue;\n\n        const ctxIndex = line.indexOf(\"| Context:\");\n        if (ctxIndex === -1) continue;\n        const contextText = line.slice(ctxIndex + \"| Context:\".length).trim();\n\n        let contextJson: unknown;\n        try {\n          contextJson = JSON.parse(contextText);\n        } catch {\n          continue;\n        }\n\n        const obj = contextJson as Record<string, unknown>;\n        const tags = (obj.tags && typeof obj.tags === \"object\" ? obj.tags : null) as Record<\n          string,\n          unknown\n        > | null;\n\n        const toNumber = (v: unknown): number =>\n          typeof v === \"number\" && Number.isFinite(v) ? v : 0;\n        const modelId = typeof tags?.modelId === \"string\" ? tags.modelId : null;\n        const timestampMatch = line.match(/^\\[([^\\]]+)\\]/);\n\n        return {\n          timestamp: timestampMatch?.[1] ?? null,\n          inputTokens: toNumber(obj.count),\n          outputTokens: toNumber(obj.outputTokens),\n          cacheReadInputTokens: toNumber(obj.cacheReadInputTokens),\n          cacheCreationInputTokens: toNumber(obj.contextCount),\n          modelId,\n        };\n      }\n    }\n\n    return null;\n  } catch {\n    return null;\n  } finally {\n    await handle?.close().catch(() => {});\n  }\n}\n","import {\n  DROID_CONTEXT_INDICATOR_MAX_TOKENS,\n  DROID_CONTEXT_INDICATOR_MAX_TOKENS_ANTHROPIC,\n  DROID_CONTEXT_INDICATOR_MIN_TOKENS,\n} from \"../../constants.ts\";\nimport type { Session } from \"../../session-types.ts\";\nimport { formatTimestampForDisplay } from \"../../text.ts\";\nimport {\n  readFactorySessionSettings,\n  resolveFactorySessionSettingsJsonPath,\n  type FactorySessionSettings,\n} from \"../../../factory-sessions.ts\";\nimport { readLastAgentStreamingResult } from \"../../../factory-logs.ts\";\nimport { sendAgentMessage } from \"../messages.ts\";\nimport type { AgentRuntime } from \"../runtime.ts\";\n\nexport async function handleContext(ctx: AgentRuntime, session: Session): Promise<void> {\n  const settingsPath = await resolveFactorySessionSettingsJsonPath({\n    sessionId: session.droidSessionId,\n    cwd: session.cwd,\n  });\n  const settings = settingsPath ? await readFactorySessionSettings(settingsPath) : null;\n  const modelFromSettings = settings?.model ?? null;\n  const reasoningEffort = settings?.reasoningEffort ?? \"unknown\";\n\n  const streaming = await readLastAgentStreamingResult({ sessionId: session.droidSessionId });\n  if (!streaming) {\n    const usage: FactorySessionSettings[\"tokenUsage\"] | undefined = settings?.tokenUsage;\n    if (!usage) {\n      await sendAgentMessage(\n        ctx.client,\n        session,\n        \"No token usage data yet.\\n\\nSend at least one message first, then run `/context` again.\",\n      );\n      return;\n    }\n\n    const inputTokens = usage.inputTokens ?? 0;\n    const outputTokens = usage.outputTokens ?? 0;\n    const cacheReadTokens = usage.cacheReadTokens ?? 0;\n    const cacheCreationTokens = usage.cacheCreationTokens ?? 0;\n    const thinkingTokens = usage.thinkingTokens ?? 0;\n    const total = inputTokens + outputTokens + cacheReadTokens;\n    const n = (v: number) => v.toLocaleString();\n\n    await sendAgentMessage(\n      ctx.client,\n      session,\n      [\n        `**Context / Token Usage:**`,\n        `- Model: ${modelFromSettings ?? session.model}`,\n        `- Reasoning effort: ${reasoningEffort}`,\n        \"\",\n        \"Could not find the last per-call usage in `~/.factory/logs/droid-log-single.log`.\",\n        \"Showing cumulative session totals from `*.settings.json` instead (not a context %).\",\n        \"\",\n        `**Cumulative totals:**`,\n        `- total (input + output + cacheRead): ${n(total)} tokens`,\n        `- inputTokens: ${n(inputTokens)}`,\n        `- outputTokens: ${n(outputTokens)}`,\n        `- cacheReadTokens: ${n(cacheReadTokens)}`,\n        `- cacheCreationTokens: ${n(cacheCreationTokens)}`,\n        `- thinkingTokens: ${n(thinkingTokens)}`,\n      ].join(\"\\n\"),\n    );\n    return;\n  }\n\n  const modelId = modelFromSettings ?? streaming.modelId ?? session.model;\n  const provider = session.availableModels.find((m) => m.id === modelId)?.modelProvider;\n\n  const inputTokens = streaming.inputTokens;\n  const outputTokens = streaming.outputTokens;\n  const cacheReadTokens = streaming.cacheReadInputTokens;\n  const cacheCreationTokens = streaming.cacheCreationInputTokens;\n\n  const total = inputTokens + outputTokens + cacheReadTokens;\n  const n = (v: number) => v.toLocaleString();\n\n  const maxTokens =\n    provider === \"anthropic\"\n      ? DROID_CONTEXT_INDICATOR_MAX_TOKENS_ANTHROPIC\n      : DROID_CONTEXT_INDICATOR_MAX_TOKENS;\n  const denom = Math.max(1, maxTokens - DROID_CONTEXT_INDICATOR_MIN_TOKENS);\n  const numer = Math.max(0, total - DROID_CONTEXT_INDICATOR_MIN_TOKENS);\n  const pctRounded = Math.min(100, Math.round((numer / denom) * 100));\n  const contextPct = total > 0 && pctRounded === 0 ? \"<1%\" : `${pctRounded}%`;\n\n  const timeLine = streaming.timestamp\n    ? `- Time: ${formatTimestampForDisplay(streaming.timestamp)}`\n    : null;\n\n  await sendAgentMessage(\n    ctx.client,\n    session,\n    [\n      `**Context / Token Usage (last model call):**`,\n      `- Model: ${modelId}`,\n      `- Reasoning effort: ${reasoningEffort}`,\n      timeLine,\n      `- Context: ${contextPct} (total=${n(total)}, max=${n(maxTokens)})`,\n      \"\",\n      `**Breakdown (last call):**`,\n      `- inputTokens: ${n(inputTokens)}`,\n      `- outputTokens: ${n(outputTokens)}`,\n      `- cacheReadTokens: ${n(cacheReadTokens)}`,\n      `- cacheCreationTokens: ${n(cacheCreationTokens)} (not counted above)`,\n    ]\n      .filter((l): l is string => typeof l === \"string\")\n      .join(\"\\n\"),\n  );\n}\n","import { createDroidAdapter } from \"../../../droid-adapter.ts\";\nimport { ACP_MODE_TO_DROID_AUTONOMY } from \"../../constants.ts\";\nimport type { Session } from \"../../session-types.ts\";\nimport { attachSession } from \"../../session/attach-session.ts\";\nimport { sanitizeHistoryTextForDisplay } from \"../../text.ts\";\nimport { sendAgentMessage } from \"../messages.ts\";\nimport type { AgentRuntime } from \"../runtime.ts\";\n\nfunction extractSummaryText(text: string): string {\n  const match = text.match(/<summary>([\\s\\S]*?)<\\/summary>/i);\n  if (match) return match[1]?.trim() ?? \"\";\n  return text.trim();\n}\n\nfunction captureNextAssistantText(\n  session: Session,\n  prompt: string,\n  options?: { timeoutMs?: number },\n): Promise<string> {\n  if (session.capture) return Promise.reject(new Error(\"Capture already in progress\"));\n\n  return new Promise((resolve, reject) => {\n    const timeoutMs = options?.timeoutMs ?? 2 * 60 * 1000;\n    const timeoutId = setTimeout(() => {\n      if (!session.capture) return;\n      const capture = session.capture;\n      session.capture = null;\n      if (capture.finalizeTimeoutId) clearTimeout(capture.finalizeTimeoutId);\n      capture.reject(new Error(\"Timed out while waiting for summary\"));\n    }, timeoutMs);\n\n    session.capture = {\n      purpose: \"compress_summary\",\n      buffer: \"\",\n      timeoutId,\n      finalizeTimeoutId: null,\n      resolve: (t: string) => resolve(t),\n      reject: (e: Error) => reject(e),\n    };\n\n    session.droid.sendUserMessage({ text: prompt });\n  });\n}\n\nexport async function handleCompress(\n  ctx: AgentRuntime,\n  session: Session,\n  trimmedArgs: string,\n): Promise<void> {\n  if (!session.droid.isRunning()) {\n    await sendAgentMessage(ctx.client, session, \"Droid is not running.\");\n    return;\n  }\n  if (session.capture) {\n    await sendAgentMessage(ctx.client, session, \"Another operation is already in progress.\");\n    return;\n  }\n\n  const extra = trimmedArgs.length > 0 ? `\\n\\nExtra instructions: ${trimmedArgs}` : \"\";\n  const summaryPrompt = [\n    \"Create a compact handoff summary of our conversation so far.\",\n    \"\",\n    \"Requirements:\",\n    \"- Keep it short and information-dense.\",\n    \"- Include: goal, current state, key decisions, important files/paths, and next TODOs.\",\n    \"- Do NOT include tool call logs, <system-reminder>, or <context> blocks.\",\n    \"- Output must be ONLY a single <summary>...</summary> block.\",\n    extra,\n  ]\n    .join(\"\\n\")\n    .trim();\n\n  await sendAgentMessage(ctx.client, session, \"Compressing conversation history…\");\n\n  let summaryRaw: string;\n  try {\n    summaryRaw = await captureNextAssistantText(session, summaryPrompt, {\n      timeoutMs: 2 * 60 * 1000,\n    });\n  } catch (err: unknown) {\n    const msg = err instanceof Error ? err.message : String(err);\n    await sendAgentMessage(ctx.client, session, `Failed to generate summary: ${msg}`);\n    return;\n  }\n\n  const summaryText = extractSummaryText(summaryRaw);\n  const cleanedSummary = sanitizeHistoryTextForDisplay(summaryText);\n  if (cleanedSummary.length === 0) {\n    await sendAgentMessage(\n      ctx.client,\n      session,\n      \"Compression failed: summary was empty. Try again with fewer instructions.\",\n    );\n    return;\n  }\n\n  const oldDroid = session.droid;\n  const oldMode = session.mode;\n  const oldModel = session.model;\n  const title = session.title;\n  const cwd = session.cwd;\n\n  await sendAgentMessage(\n    ctx.client,\n    session,\n    \"Starting a fresh Droid session with summary context…\",\n  );\n\n  const newDroid = createDroidAdapter({ cwd, logger: ctx.logger });\n  const initResult = await newDroid.start();\n  const { session: newSession } = attachSession({\n    sessionId: session.id,\n    cwd,\n    droid: newDroid,\n    initResult,\n    title,\n    client: ctx.client,\n    logger: ctx.logger,\n    sessions: ctx.sessions,\n    handlers: ctx.getAttachHandlers(),\n  });\n\n  newSession.mode = oldMode;\n  newSession.droid.setMode(ACP_MODE_TO_DROID_AUTONOMY[oldMode]);\n  await ctx.client.sessionUpdate({\n    sessionId: newSession.id,\n    update: {\n      sessionUpdate: \"current_mode_update\",\n      currentModeId: oldMode,\n    },\n  });\n\n  if (newSession.availableModels.some((m) => m.id === oldModel)) {\n    newSession.model = oldModel;\n    newSession.droid.setModel(oldModel);\n  }\n\n  await oldDroid.stop();\n\n  newSession.pendingHistoryContext = cleanedSummary;\n\n  await sendAgentMessage(\n    ctx.client,\n    newSession,\n    \"Compression complete.\\n\\nYour next message will automatically include the summary context.\",\n  );\n}\n","import type { Session } from \"../../session-types.ts\";\nimport { sendAgentMessage } from \"../messages.ts\";\nimport type { AgentRuntime } from \"../runtime.ts\";\n\nexport async function handleModel(\n  ctx: AgentRuntime,\n  session: Session,\n  trimmedArgs: string,\n): Promise<void> {\n  if (trimmedArgs) {\n    const modelId = trimmedArgs;\n    const model = session.availableModels.find(\n      (m) => m.id === modelId || m.displayName.toLowerCase() === modelId.toLowerCase(),\n    );\n    if (model) {\n      session.model = model.id;\n      session.droid.setModel(model.id);\n      await sendAgentMessage(ctx.client, session, `Model changed to: **${model.displayName}**`);\n    } else {\n      const available = session.availableModels.map((m) => `- ${m.id} (${m.displayName})`);\n      await sendAgentMessage(\n        ctx.client,\n        session,\n        `Model \"${modelId}\" not found.\\n\\n**Available models:**\\n${available.join(\"\\n\")}`,\n      );\n    }\n    return;\n  }\n\n  const available = session.availableModels.map((m) => {\n    const current = m.id === session.model ? \" **(current)**\" : \"\";\n    return `- ${m.id} (${m.displayName})${current}`;\n  });\n  await sendAgentMessage(\n    ctx.client,\n    session,\n    `**Current model:** ${session.model}\\n\\n**Available models:**\\n${available.join(\"\\n\")}`,\n  );\n}\n","import { ACP_MODES, type AcpModeId } from \"../../../types.ts\";\nimport { ACP_MODE_TO_DROID_AUTONOMY } from \"../../constants.ts\";\nimport type { Session } from \"../../session-types.ts\";\nimport { sendAgentMessage } from \"../messages.ts\";\nimport type { AgentRuntime } from \"../runtime.ts\";\n\nexport async function handleMode(\n  ctx: AgentRuntime,\n  session: Session,\n  trimmedArgs: string,\n): Promise<void> {\n  const inputMode = trimmedArgs.toLowerCase() as AcpModeId;\n  if (trimmedArgs && ACP_MODES.includes(inputMode)) {\n    session.mode = inputMode;\n    session.droid.setMode(ACP_MODE_TO_DROID_AUTONOMY[inputMode]);\n    await sendAgentMessage(ctx.client, session, `Autonomy mode changed to: **${inputMode}**`);\n    await ctx.client.sessionUpdate({\n      sessionId: session.id,\n      update: { sessionUpdate: \"current_mode_update\", currentModeId: inputMode },\n    });\n    return;\n  }\n\n  const modeList = ACP_MODES.map((m) => {\n    const current = m === session.mode ? \" **(current)**\" : \"\";\n    return `- ${m}${current}`;\n  }).join(\"\\n\");\n  await sendAgentMessage(\n    ctx.client,\n    session,\n    `**Current mode:** ${session.mode}\\n\\n**Available modes:**\\n${modeList}`,\n  );\n}\n","import type { Session } from \"../../session-types.ts\";\nimport { sendAgentMessage } from \"../messages.ts\";\nimport type { AgentRuntime } from \"../runtime.ts\";\n\nexport async function handleConfig(ctx: AgentRuntime, session: Session): Promise<void> {\n  const config = [\n    `**Session Configuration:**`,\n    `- Session ID: ${session.id}`,\n    `- Working Directory: ${session.cwd}`,\n    `- Model: ${session.model}`,\n    `- Mode: ${session.mode}`,\n  ].join(\"\\n\");\n  await sendAgentMessage(ctx.client, session, config);\n}\n","import type { Session } from \"../../session-types.ts\";\nimport { sendAgentMessage } from \"../messages.ts\";\nimport type { AgentRuntime } from \"../runtime.ts\";\n\nexport async function handleStatus(ctx: AgentRuntime, session: Session): Promise<void> {\n  const status = [\n    `**Session Status:**`,\n    `- Active Tool Calls: ${session.activeToolCallIds.size}`,\n    `- Droid Running: ${session.droid.isRunning()}`,\n  ].join(\"\\n\");\n  await sendAgentMessage(ctx.client, session, status);\n}\n","import type { FactorySessionRecord } from \"../../../../factory-sessions.ts\";\nimport { sanitizeSessionTitle } from \"../../../text.ts\";\n\nexport function filterEmptySessions(sessions: FactorySessionRecord[]): FactorySessionRecord[] {\n  return sessions.filter((s) => {\n    const cleanedTitle = s.title ? sanitizeSessionTitle(s.title) : \"\";\n    if (!cleanedTitle) return false;\n    return cleanedTitle.toLowerCase() !== \"new session\";\n  });\n}\n","import { listFactorySessions } from \"../../../../factory-sessions.ts\";\nimport type { Session } from \"../../../session-types.ts\";\nimport { formatTimestampForDisplay, sanitizeSessionTitle } from \"../../../text.ts\";\nimport { sendAgentMessage } from \"../../messages.ts\";\nimport type { AgentRuntime } from \"../../runtime.ts\";\nimport { filterEmptySessions } from \"./shared.ts\";\n\nexport async function handleSessionsList(ctx: AgentRuntime, session: Session): Promise<void> {\n  const { sessions: raw } = await listFactorySessions({\n    cwd: session.cwd,\n    cursor: null,\n    pageSize: 20,\n  });\n  const sessions = filterEmptySessions(raw);\n\n  if (sessions.length === 0) {\n    await sendAgentMessage(\n      ctx.client,\n      session,\n      `No sessions found for:\\n\\n- cwd: ${session.cwd}\\n\\nTry: /sessions all`,\n    );\n    return;\n  }\n\n  session.lastSessionsListing = { scope: \"cwd\", sessions };\n\n  const lines = sessions.map((s, i) => {\n    const time = s.updatedAt ? ` — ${formatTimestampForDisplay(s.updatedAt)}` : \"\";\n    const cleanedTitle = s.title ? sanitizeSessionTitle(s.title) : \"\";\n    const title = cleanedTitle.length > 0 ? ` — ${cleanedTitle}` : \"\";\n    return `${i + 1}. ${s.sessionId}${title}${time}`;\n  });\n\n  await sendAgentMessage(\n    ctx.client,\n    session,\n    [\n      `**Sessions (${session.cwd})**`,\n      \"\",\n      ...lines,\n      \"\",\n      \"Use:\",\n      \"- /sessions load <#>\",\n      \"- /sessions <#>\",\n      \"- /sessions load <session_id_prefix>\",\n    ]\n      .join(\"\\n\")\n      .trim(),\n  );\n}\n\nexport async function handleSessionsAll(ctx: AgentRuntime, session: Session): Promise<void> {\n  const { sessions: raw } = await listFactorySessions({\n    cwd: null,\n    cursor: null,\n    pageSize: 20,\n    preferredCwd: session.cwd,\n  });\n  const sessions = filterEmptySessions(raw);\n\n  if (sessions.length === 0) {\n    await sendAgentMessage(ctx.client, session, \"No sessions found in local history.\");\n    return;\n  }\n\n  session.lastSessionsListing = { scope: \"all\", sessions };\n\n  const lines = sessions.map((s, i) => {\n    const time = s.updatedAt ? ` — ${formatTimestampForDisplay(s.updatedAt)}` : \"\";\n    const cleanedTitle = s.title ? sanitizeSessionTitle(s.title) : \"\";\n    const title = cleanedTitle.length > 0 ? ` — ${cleanedTitle}` : \"\";\n    return `${i + 1}. ${s.sessionId} (${s.cwd})${title}${time}`;\n  });\n\n  await sendAgentMessage(\n    ctx.client,\n    session,\n    [\n      \"**Recent Sessions**\",\n      \"\",\n      ...lines,\n      \"\",\n      \"Use:\",\n      \"- /sessions load <#>\",\n      \"- /sessions <#>\",\n      \"- /sessions load <session_id_prefix>\",\n    ]\n      .join(\"\\n\")\n      .trim(),\n  );\n}\n","import { streamFactorySessionJsonl } from \"../../factory-sessions.ts\";\nimport { sanitizeHistoryTextForDisplay } from \"../text.ts\";\n\nexport async function buildHistoryTranscriptFromJsonl(\n  jsonlPath: string,\n  maxChars: number,\n): Promise<string> {\n  const lines: string[] = [];\n  let includedSessionHistory = false;\n\n  for await (const entry of streamFactorySessionJsonl(jsonlPath)) {\n    const record = entry as { type?: unknown; message?: unknown };\n    if (record.type !== \"message\") continue;\n\n    const message = record.message as { role?: unknown; content?: unknown };\n    const role = message?.role;\n    const content = message?.content;\n    if (role !== \"user\" && role !== \"assistant\") continue;\n    if (!Array.isArray(content)) continue;\n\n    const rawText = content\n      .filter((c) => (c as Record<string, unknown>)?.type === \"text\")\n      .map((c) => ((c as Record<string, unknown>)?.text as string) ?? \"\")\n      .join(\"\");\n\n    if (role === \"user\") {\n      const sessionHistoryMatch = rawText.match(\n        /<context[^>]*\\sref=[\"']session_history[\"'][^>]*>([\\s\\S]*?)<\\/context>/i,\n      );\n      const embeddedHistory = sessionHistoryMatch?.[1] ? sessionHistoryMatch[1].trim() : \"\";\n      if (!includedSessionHistory && embeddedHistory.length > 0) {\n        const cleanedHistory = sanitizeHistoryTextForDisplay(embeddedHistory);\n        if (cleanedHistory.length > 0) {\n          includedSessionHistory = true;\n          lines.push(`[Previous session transcript]\\n${cleanedHistory}`);\n        }\n      }\n\n      const withoutSessionHistory = rawText.replace(\n        /<context[^>]*\\sref=[\"']session_history[\"'][^>]*>[\\s\\S]*?<\\/context>/gi,\n        \"\",\n      );\n      const cleanedUserText = sanitizeHistoryTextForDisplay(withoutSessionHistory);\n      if (cleanedUserText.length > 0) {\n        lines.push(`User: ${cleanedUserText}`);\n      }\n      continue;\n    }\n\n    const cleanedAssistantText = sanitizeHistoryTextForDisplay(rawText);\n    if (cleanedAssistantText.length > 0) {\n      lines.push(`Assistant: ${cleanedAssistantText}`);\n    }\n  }\n\n  const transcript = lines.join(\"\\n\\n\").trim();\n  if (transcript.length <= maxChars) return transcript;\n  return transcript.slice(transcript.length - maxChars);\n}\n","import type { AgentSideConnection } from \"@agentclientprotocol/sdk\";\nimport { streamFactorySessionJsonl } from \"../../factory-sessions.ts\";\nimport type { Logger } from \"../../utils.ts\";\nimport type { Session } from \"../session-types.ts\";\nimport { sanitizeHistoryTextForDisplay } from \"../text.ts\";\n\nexport async function replayHistoryFromJsonl(\n  ctx: { client: AgentSideConnection; logger: Logger },\n  session: Session,\n  jsonlPath: string,\n): Promise<void> {\n  ctx.logger.log(\"Replaying session history from:\", jsonlPath);\n\n  for await (const entry of streamFactorySessionJsonl(jsonlPath)) {\n    const record = entry as { type?: unknown; message?: unknown; id?: unknown };\n    if (record.type !== \"message\") continue;\n\n    const message = record.message as { role?: unknown; content?: unknown };\n    const role = message?.role;\n    const content = message?.content;\n    if (role !== \"user\" && role !== \"assistant\" && role !== \"system\") continue;\n    if (!Array.isArray(content)) continue;\n\n    const messageId = typeof record.id === \"string\" ? record.id : \"message\";\n    await replayHistoryMessage(ctx, session, { role, id: messageId, content });\n  }\n}\n\nexport async function replayHistoryFromInitMessages(\n  ctx: { client: AgentSideConnection; logger: Logger },\n  session: Session,\n  messages: unknown[],\n): Promise<void> {\n  ctx.logger.log(\"Replaying session history from init result (messages):\", messages.length);\n\n  for (const entry of messages) {\n    const message = entry as { role?: unknown; content?: unknown; id?: unknown };\n    const role = message?.role;\n    const content = message?.content;\n\n    if (role !== \"user\" && role !== \"assistant\" && role !== \"system\") continue;\n    if (!Array.isArray(content)) continue;\n\n    const id = typeof message.id === \"string\" ? message.id : \"message\";\n    await replayHistoryMessage(ctx, session, { role, id, content });\n  }\n}\n\nasync function replayHistoryMessage(\n  ctx: { client: AgentSideConnection; logger: Logger },\n  session: Session,\n  message: { role: \"user\" | \"assistant\" | \"system\"; id: string; content: unknown[] },\n): Promise<void> {\n  if (message.role === \"user\") {\n    for (const block of message.content) {\n      const b = block as Record<string, unknown>;\n      const blockType = b.type as string | undefined;\n      if (blockType === \"tool_result\") continue;\n\n      if (blockType === \"text\") {\n        const text = typeof b.text === \"string\" ? b.text : \"\";\n        const cleaned = sanitizeHistoryTextForDisplay(text);\n        if (cleaned.length > 0) {\n          await ctx.client.sessionUpdate({\n            sessionId: session.id,\n            update: {\n              sessionUpdate: \"user_message_chunk\",\n              content: { type: \"text\", text: cleaned },\n            },\n          });\n        }\n        continue;\n      }\n\n      if (blockType === \"image\") {\n        const source = b.source as { type?: unknown; data?: unknown } | undefined;\n        const data = typeof source?.data === \"string\" ? source.data : null;\n        const mimeType =\n          (typeof b.media_type === \"string\" ? b.media_type : null) ??\n          (typeof b.mediaType === \"string\" ? b.mediaType : null);\n        if (data && mimeType) {\n          await ctx.client.sessionUpdate({\n            sessionId: session.id,\n            update: {\n              sessionUpdate: \"user_message_chunk\",\n              content: { type: \"image\", data, mimeType },\n            },\n          });\n        }\n        continue;\n      }\n    }\n    return;\n  }\n\n  if (message.role === \"assistant\") {\n    const textParts = message.content\n      .filter((c) => (c as Record<string, unknown>)?.type === \"text\")\n      .map((c) => ((c as Record<string, unknown>)?.text as string) ?? \"\")\n      .filter((t) => typeof t === \"string\" && t.length > 0)\n      .map((t) => sanitizeHistoryTextForDisplay(t))\n      .filter((t) => t.length > 0);\n\n    if (textParts.length > 0) {\n      await ctx.client.sessionUpdate({\n        sessionId: session.id,\n        update: {\n          sessionUpdate: \"agent_message_chunk\",\n          content: { type: \"text\", text: textParts.join(\"\") },\n        },\n      });\n    }\n  }\n}\n","import {\n  listFactorySessions,\n  readFactorySessionStart,\n  resolveFactorySessionJsonlPath,\n  type FactorySessionRecord,\n} from \"../../../../factory-sessions.ts\";\nimport { createDroidAdapter } from \"../../../../droid-adapter.ts\";\nimport { UUID_RE } from \"../../../constants.ts\";\nimport { buildHistoryTranscriptFromJsonl } from \"../../../history/transcript.ts\";\nimport { replayHistoryFromJsonl } from \"../../../history/replay.ts\";\nimport { attachSession } from \"../../../session/attach-session.ts\";\nimport type { Session } from \"../../../session-types.ts\";\nimport { formatTimestampForDisplay, sanitizeSessionTitle } from \"../../../text.ts\";\nimport { sendAgentMessage } from \"../../messages.ts\";\nimport type { AgentRuntime } from \"../../runtime.ts\";\nimport { filterEmptySessions } from \"./shared.ts\";\n\nasync function getOrFetchListing(\n  ctx: AgentRuntime,\n  session: Session,\n): Promise<FactorySessionRecord[]> {\n  if (session.lastSessionsListing?.sessions) return session.lastSessionsListing.sessions;\n  const { sessions } = await listFactorySessions({ cwd: session.cwd, cursor: null, pageSize: 20 });\n  const filtered = filterEmptySessions(sessions);\n  session.lastSessionsListing = { scope: \"cwd\", sessions: filtered };\n  return filtered;\n}\n\nasync function resolveSessionLoadTarget(\n  ctx: AgentRuntime,\n  session: Session,\n  rawTarget: string,\n): Promise<string | null> {\n  const target = rawTarget.trim();\n  if (!target) return null;\n\n  const lower = target.toLowerCase();\n  if (lower === \"last\" || lower === \"latest\") {\n    const listing = await getOrFetchListing(ctx, session);\n    const first = listing[0];\n    if (!first) {\n      await sendAgentMessage(\n        ctx.client,\n        session,\n        `No sessions found for:\\n\\n- cwd: ${session.cwd}\\n\\nTry: /sessions all`,\n      );\n      return null;\n    }\n    return first.sessionId;\n  }\n\n  if (/^\\d+$/.test(target)) {\n    const index = Number.parseInt(target, 10);\n    if (!Number.isFinite(index) || index <= 0) {\n      await sendAgentMessage(ctx.client, session, `Invalid session index: ${target}`);\n      return null;\n    }\n\n    const listing = await getOrFetchListing(ctx, session);\n    const record = listing[index - 1];\n    if (!record) {\n      await sendAgentMessage(\n        ctx.client,\n        session,\n        `Session index out of range: ${index}\\n\\nRun \\`/sessions\\` to refresh the list.`,\n      );\n      return null;\n    }\n    return record.sessionId;\n  }\n\n  if (UUID_RE.test(target)) return target;\n\n  const listing = await getOrFetchListing(ctx, session);\n  const matches = listing.filter((s) => s.sessionId.toLowerCase().startsWith(target.toLowerCase()));\n  if (matches.length === 1) return matches[0].sessionId;\n\n  if (matches.length === 0) {\n    await sendAgentMessage(\n      ctx.client,\n      session,\n      `No session matches that id prefix: ${target}\\n\\nRun \\`/sessions\\` or \\`/sessions all\\` to list sessions.`,\n    );\n    return null;\n  }\n\n  const scope = session.lastSessionsListing?.scope ?? \"cwd\";\n  const formatLine = (s: FactorySessionRecord): string => {\n    const idx = listing.findIndex((x) => x.sessionId === s.sessionId);\n    const n = idx >= 0 ? `${idx + 1}. ` : \"\";\n    const time = s.updatedAt ? ` — ${formatTimestampForDisplay(s.updatedAt)}` : \"\";\n    const cleanedTitle = s.title ? sanitizeSessionTitle(s.title) : \"\";\n    const title = cleanedTitle.length > 0 ? ` — ${cleanedTitle}` : \"\";\n    const cwdSuffix = scope === \"all\" ? ` (${s.cwd})` : \"\";\n    return `${n}${s.sessionId}${cwdSuffix}${title}${time}`;\n  };\n\n  const lines = matches.slice(0, 10).map(formatLine);\n  await sendAgentMessage(\n    ctx.client,\n    session,\n    [\n      `Multiple sessions match that id prefix: ${target}`,\n      \"\",\n      ...lines.map((l) => `- ${l}`),\n      \"\",\n      \"Use: /sessions load <#>\",\n    ].join(\"\\n\"),\n  );\n  return null;\n}\n\nexport async function handleSessionsLoad(\n  ctx: AgentRuntime,\n  session: Session,\n  parts: string[],\n): Promise<void> {\n  const rawTarget = parts[1] ?? \"\";\n  if (rawTarget.length === 0) {\n    await sendAgentMessage(\n      ctx.client,\n      session,\n      \"Usage:\\n\\n- /sessions load <#>\\n- /sessions load <session_id_prefix>\\n- /sessions load <full_session_id>\",\n    );\n    return;\n  }\n\n  const targetSessionId = await resolveSessionLoadTarget(ctx, session, rawTarget);\n  if (!targetSessionId) return;\n\n  await sendAgentMessage(ctx.client, session, `Loading session: ${targetSessionId}…`);\n\n  const jsonlPath = await resolveFactorySessionJsonlPath({\n    sessionId: targetSessionId,\n    cwd: session.cwd,\n  });\n  if (!jsonlPath) {\n    await sendAgentMessage(\n      ctx.client,\n      session,\n      `Session history not found on disk for: ${targetSessionId}`,\n    );\n    return;\n  }\n\n  const header = await readFactorySessionStart(jsonlPath);\n  const cwd = header?.cwd ?? session.cwd;\n\n  try {\n    await session.droid.stop();\n  } catch {}\n\n  let droid = createDroidAdapter({ cwd, logger: ctx.logger, resumeSessionId: targetSessionId });\n  let initResult = await droid.start();\n  const resumed = initResult.sessionId === targetSessionId;\n  if (!resumed) {\n    try {\n      await droid.stop();\n    } catch {}\n    droid = createDroidAdapter({ cwd, logger: ctx.logger });\n    initResult = await droid.start();\n  }\n\n  const { session: newSession } = attachSession({\n    sessionId: session.id,\n    cwd,\n    droid,\n    initResult,\n    title: header?.title ? sanitizeSessionTitle(header.title) : null,\n    client: ctx.client,\n    logger: ctx.logger,\n    sessions: ctx.sessions,\n    handlers: ctx.getAttachHandlers(),\n  });\n\n  if (!resumed) {\n    const transcript = await buildHistoryTranscriptFromJsonl(jsonlPath, 12000);\n    if (transcript.length > 0) {\n      newSession.pendingHistoryContext = transcript;\n    }\n    await sendAgentMessage(\n      ctx.client,\n      newSession,\n      `\\n\\nNote: history is loaded from disk for ${targetSessionId}, but Droid could not resume this session id.\\n\\nYour next message will automatically include a transcript as context (so Droid can continue without a Factory login).`,\n    );\n  }\n\n  await replayHistoryFromJsonl({ client: ctx.client, logger: ctx.logger }, newSession, jsonlPath);\n}\n","import type { Session } from \"../../session-types.ts\";\nimport { isExperimentSessionsEnabled } from \"../../flags.ts\";\nimport { sendAgentMessage } from \"../messages.ts\";\nimport type { AgentRuntime } from \"../runtime.ts\";\nimport { handleSessionsAll, handleSessionsList } from \"./sessions/list.ts\";\nimport { handleSessionsLoad } from \"./sessions/load.ts\";\n\nexport async function handleSessions(\n  ctx: AgentRuntime,\n  session: Session,\n  trimmedArgs: string,\n): Promise<void> {\n  if (!isExperimentSessionsEnabled()) {\n    await sendAgentMessage(\n      ctx.client,\n      session,\n      \"Experimental feature disabled.\\n\\nEnable with `npx droid-acp --experiment-sessions` (or set `DROID_ACP_EXPERIMENT_SESSIONS=1`).\",\n    );\n    return;\n  }\n\n  const parts = trimmedArgs.split(/\\s+/).filter((p) => p.length > 0);\n  let sub = parts[0]?.toLowerCase();\n\n  if (sub && /^\\d+$/.test(sub)) {\n    parts.unshift(\"load\");\n    sub = \"load\";\n  }\n\n  if (!sub || sub === \"list\") {\n    await handleSessionsList(ctx, session);\n    return;\n  }\n\n  if (sub === \"all\") {\n    await handleSessionsAll(ctx, session);\n    return;\n  }\n\n  if (sub === \"load\") {\n    await handleSessionsLoad(ctx, session, parts);\n    return;\n  }\n\n  await sendAgentMessage(\n    ctx.client,\n    session,\n    \"Usage:\\n\\n- /sessions (list current cwd)\\n- /sessions all (list global)\\n- /sessions load <#|id_prefix|session_id>\\n- /sessions <#>\",\n  );\n}\n","import type { Session } from \"../../session-types.ts\";\nimport type { AgentRuntime } from \"../runtime.ts\";\nimport { handleHelp } from \"./help.ts\";\nimport { handleContext } from \"./context.ts\";\nimport { handleCompress } from \"./compress.ts\";\nimport { handleModel } from \"./model.ts\";\nimport { handleMode } from \"./mode.ts\";\nimport { handleConfig } from \"./config.ts\";\nimport { handleStatus } from \"./status.ts\";\nimport { handleSessions } from \"./sessions.ts\";\n\nexport async function handleSlashCommand(\n  ctx: AgentRuntime,\n  session: Session,\n  text: string,\n): Promise<boolean> {\n  const match = text.match(/^\\/(\\S+)(?:\\s+(.*))?$/);\n  if (!match) return false;\n\n  const [, command, args] = match;\n  const trimmedArgs = args?.trim() || \"\";\n  const name = command.toLowerCase();\n\n  switch (name) {\n    case \"help\":\n      await handleHelp(ctx, session);\n      return true;\n    case \"context\":\n      await handleContext(ctx, session);\n      return true;\n    case \"compress\":\n    case \"compact\":\n      await handleCompress(ctx, session, trimmedArgs);\n      return true;\n    case \"model\":\n      await handleModel(ctx, session, trimmedArgs);\n      return true;\n    case \"mode\":\n      await handleMode(ctx, session, trimmedArgs);\n      return true;\n    case \"config\":\n      await handleConfig(ctx, session);\n      return true;\n    case \"status\":\n      await handleStatus(ctx, session);\n      return true;\n    case \"sessions\":\n      await handleSessions(ctx, session, trimmedArgs);\n      return true;\n    default:\n      await handleHelp(ctx, session, `Unknown command: /${command}`);\n      return true;\n  }\n}\n","import type {\n  CancelNotification,\n  PromptRequest,\n  PromptResponse,\n  SetSessionModeRequest,\n  SetSessionModeResponse,\n  SetSessionModelRequest,\n  SetSessionModelResponse,\n} from \"@agentclientprotocol/sdk\";\nimport { ACP_MODES, type AcpModeId } from \"../../types.ts\";\nimport { ACP_MODE_TO_DROID_AUTONOMY } from \"../constants.ts\";\nimport { sanitizeSessionTitle } from \"../text.ts\";\nimport { convertAcpPromptToDroidMessage } from \"../prompt/convert.ts\";\nimport {\n  finalizeActiveToolCalls,\n  getReadySession,\n  restartDroidSession,\n} from \"../session/restart.ts\";\nimport type { AgentRuntime } from \"./runtime.ts\";\nimport { handleSlashCommand } from \"./slash/handle.ts\";\n\nfunction deriveSessionTitle(text: string): string | null {\n  const firstLine = text\n    .split(\"\\n\")\n    .map((l) => l.trim())\n    .find((l) => l.length > 0);\n  if (!firstLine) return null;\n  const cleaned = sanitizeSessionTitle(firstLine);\n  if (cleaned.length === 0) return null;\n  return cleaned.length > 80 ? `${cleaned.slice(0, 77)}...` : cleaned;\n}\n\nexport async function prompt(ctx: AgentRuntime, request: PromptRequest): Promise<PromptResponse> {\n  let session = ctx.sessions.get(request.sessionId);\n  if (!session) throw new Error(`Session not found: ${request.sessionId}`);\n  if (session.promptResolve) throw new Error(\"Another prompt is already in progress\");\n\n  session = await getReadySession(\n    {\n      sessions: ctx.sessions,\n      restartDroidSession: (p) =>\n        restartDroidSession(\n          {\n            client: ctx.client,\n            logger: ctx.logger,\n            sessions: ctx.sessions,\n            handlers: ctx.getAttachHandlers(),\n          },\n          p,\n        ),\n    },\n    { sessionId: request.sessionId, reason: \"prompt\" },\n  );\n\n  ctx.logger.log(\"prompt:\", request.sessionId);\n\n  const converted = convertAcpPromptToDroidMessage(request.prompt);\n  let text = converted.text;\n  const images = converted.images;\n\n  const derivedTitle = deriveSessionTitle(text);\n  const now = new Date().toISOString();\n  session.updatedAt = now;\n  if ((!session.title || session.title === \"New Session\") && derivedTitle) {\n    session.title = derivedTitle;\n  }\n\n  void ctx.client.sessionUpdate({\n    sessionId: session.id,\n    update: {\n      sessionUpdate: \"session_info_update\",\n      title: session.title,\n      updatedAt: session.updatedAt,\n    },\n  });\n\n  if (text.startsWith(\"/\")) {\n    const handled = await handleSlashCommand(ctx, session, text);\n    if (handled) return { stopReason: \"end_turn\" };\n  }\n\n  if (session.pendingHistoryContext) {\n    const historyContext = session.pendingHistoryContext;\n    session.pendingHistoryContext = null;\n    text = `${text}\\n\\n<context ref=\"session_history\">\\n${historyContext}\\n</context>`.trim();\n  }\n\n  return new Promise((resolve) => {\n    const timeoutId = setTimeout(\n      () => {\n        const current = ctx.sessions.get(request.sessionId);\n        if (current?.promptResolve) {\n          current.promptResolve({ stopReason: \"end_turn\" });\n          current.promptResolve = null;\n        }\n      },\n      5 * 60 * 1000,\n    );\n\n    session.promptResolve = resolve;\n    session.droid.sendUserMessage({\n      text,\n      images: images.length > 0 ? images : undefined,\n    });\n\n    const originalResolve = session.promptResolve;\n    session.promptResolve = (result) => {\n      clearTimeout(timeoutId);\n      originalResolve?.(result);\n    };\n  });\n}\n\nexport async function cancel(ctx: AgentRuntime, request: CancelNotification): Promise<void> {\n  const session = ctx.sessions.get(request.sessionId);\n  if (!session) return;\n\n  const hasInFlightWork =\n    session.promptResolve !== null ||\n    session.capture !== null ||\n    session.activeToolCallIds.size > 0;\n  if (!hasInFlightWork) {\n    ctx.logger.log(\"cancel (no-op):\", request.sessionId);\n    return;\n  }\n\n  ctx.logger.log(\"cancel:\", request.sessionId);\n  session.cancelled = true;\n\n  if (session.promptResolve) {\n    session.promptResolve({ stopReason: \"cancelled\" });\n    session.promptResolve = null;\n  }\n\n  if (session.capture) {\n    const capture = session.capture;\n    session.capture = null;\n    clearTimeout(capture.timeoutId);\n    if (capture.finalizeTimeoutId) clearTimeout(capture.finalizeTimeoutId);\n    capture.reject(new Error(\"Cancelled\"));\n  }\n\n  await finalizeActiveToolCalls({ client: ctx.client, session, message: \"Cancelled.\" });\n\n  void restartDroidSession(\n    {\n      client: ctx.client,\n      logger: ctx.logger,\n      sessions: ctx.sessions,\n      handlers: ctx.getAttachHandlers(),\n    },\n    { sessionId: request.sessionId, reason: \"cancel\" },\n  );\n}\n\nexport async function unstable_setSessionModel(\n  ctx: AgentRuntime,\n  request: SetSessionModelRequest,\n): Promise<SetSessionModelResponse | void> {\n  const session = ctx.sessions.get(request.sessionId);\n  if (!session) return;\n\n  ctx.logger.log(\"setSessionModel:\", request.modelId);\n  session.model = request.modelId;\n  session.droid.setModel(request.modelId);\n}\n\nexport async function setSessionMode(\n  ctx: AgentRuntime,\n  request: SetSessionModeRequest,\n): Promise<SetSessionModeResponse> {\n  const session = ctx.sessions.get(request.sessionId);\n  if (session) {\n    ctx.logger.log(\"setSessionMode:\", request.modeId);\n    const modeId = ACP_MODES.includes(request.modeId as AcpModeId)\n      ? (request.modeId as AcpModeId)\n      : null;\n    if (modeId) {\n      session.mode = modeId;\n      session.droid.setMode(ACP_MODE_TO_DROID_AUTONOMY[modeId]);\n    }\n  }\n  return {};\n}\n","import type { NewSessionResponse } from \"@agentclientprotocol/sdk\";\nimport type { AcpModeId, InitSessionResult } from \"../../types.ts\";\n\nexport function getModelsState(\n  initResult: InitSessionResult,\n): NonNullable<NewSessionResponse[\"models\"]> {\n  return {\n    availableModels: initResult.availableModels.map((m) => ({\n      modelId: m.id,\n      name: m.displayName,\n    })),\n    currentModelId: initResult.settings?.modelId || \"unknown\",\n  };\n}\n\nexport function getModesState(currentModeId: AcpModeId): NonNullable<NewSessionResponse[\"modes\"]> {\n  return {\n    currentModeId,\n    availableModes: [\n      { id: \"spec\", name: \"Spec\", description: \"Research and plan only - no code changes\" },\n      {\n        id: \"off\",\n        name: \"Auto Off\",\n        description: \"Read-only mode - safe for reviewing planned changes without execution\",\n      },\n      {\n        id: \"low\",\n        name: \"Auto Low\",\n        description: \"Low-risk operations - file creation/modification, no system changes\",\n      },\n      {\n        id: \"medium\",\n        name: \"Auto Medium\",\n        description: \"Development operations - npm install, git commit, build commands\",\n      },\n      {\n        id: \"high\",\n        name: \"Auto High\",\n        description: \"Production operations - git push, deployments, database migrations\",\n      },\n    ],\n  };\n}\n","import type {\n  ListSessionsRequest,\n  ListSessionsResponse,\n  LoadSessionRequest,\n  LoadSessionResponse,\n  NewSessionRequest,\n  NewSessionResponse,\n  ResumeSessionRequest,\n  ResumeSessionResponse,\n} from \"@agentclientprotocol/sdk\";\nimport {\n  listFactorySessions,\n  readFactorySessionStart,\n  resolveFactorySessionJsonlPath,\n} from \"../../factory-sessions.ts\";\nimport { createDroidAdapter } from \"../../droid-adapter.ts\";\nimport type { Session } from \"../session-types.ts\";\nimport { replayHistoryFromInitMessages, replayHistoryFromJsonl } from \"../history/replay.ts\";\nimport { sanitizeSessionTitle } from \"../text.ts\";\nimport { attachSession } from \"../session/attach-session.ts\";\nimport { isExperimentSessionsEnabled } from \"../flags.ts\";\nimport { getModesState, getModelsState } from \"./state.ts\";\nimport type { AgentRuntime } from \"./runtime.ts\";\n\nfunction loadDisabledError(action: string): Error {\n  return new Error(\n    `Session ${action} is experimental. Start droid-acp with --experiment-sessions (or set DROID_ACP_EXPERIMENT_SESSIONS=1).`,\n  );\n}\n\nfunction modelsStateFromSession(session: Session): NonNullable<LoadSessionResponse[\"models\"]> {\n  return {\n    availableModels: session.availableModels.map((m) => ({ modelId: m.id, name: m.displayName })),\n    currentModelId: session.model,\n  };\n}\n\nasync function stopAndDropSession(ctx: AgentRuntime, sessionId: string): Promise<void> {\n  const existing = ctx.sessions.get(sessionId);\n  if (!existing) return;\n  try {\n    await existing.droid.stop();\n  } catch {}\n  ctx.sessions.delete(sessionId);\n}\n\nexport async function newSession(\n  ctx: AgentRuntime,\n  request: NewSessionRequest,\n): Promise<NewSessionResponse> {\n  const cwd = request.cwd || process.cwd();\n  ctx.logger.log(\"newSession:\", cwd);\n\n  const droid = createDroidAdapter({ cwd, logger: ctx.logger });\n  const initResult = await droid.start();\n\n  const sessionId = initResult.sessionId;\n  const { initialMode } = attachSession({\n    sessionId,\n    cwd,\n    droid,\n    initResult,\n    client: ctx.client,\n    logger: ctx.logger,\n    sessions: ctx.sessions,\n    handlers: ctx.getAttachHandlers(),\n  });\n\n  return {\n    sessionId,\n    models: getModelsState(initResult),\n    modes: getModesState(initialMode),\n  };\n}\n\nexport async function loadSession(\n  ctx: AgentRuntime,\n  request: LoadSessionRequest,\n): Promise<LoadSessionResponse> {\n  if (!isExperimentSessionsEnabled()) throw loadDisabledError(\"load\");\n\n  const requestCwd = request.cwd || process.cwd();\n  ctx.logger.log(\"loadSession:\", request.sessionId, requestCwd);\n\n  const existing = ctx.sessions.get(request.sessionId);\n  if (existing?.droid.isRunning()) {\n    return { models: modelsStateFromSession(existing), modes: getModesState(existing.mode) };\n  }\n\n  await stopAndDropSession(ctx, request.sessionId);\n\n  const jsonlPath = await resolveFactorySessionJsonlPath({\n    sessionId: request.sessionId,\n    cwd: requestCwd,\n  });\n\n  const header = jsonlPath ? await readFactorySessionStart(jsonlPath) : null;\n  const cwd = header?.cwd ?? requestCwd;\n\n  const droid = createDroidAdapter({ cwd, logger: ctx.logger, resumeSessionId: request.sessionId });\n  const initResult = await droid.start();\n\n  if (initResult.sessionId !== request.sessionId) {\n    await droid.stop();\n    throw new Error(\n      `Failed to load session: expected ${request.sessionId} but got ${initResult.sessionId}`,\n    );\n  }\n\n  const { session, initialMode } = attachSession({\n    sessionId: request.sessionId,\n    cwd,\n    droid,\n    initResult,\n    title: header?.title ? sanitizeSessionTitle(header.title) : null,\n    client: ctx.client,\n    logger: ctx.logger,\n    sessions: ctx.sessions,\n    handlers: ctx.getAttachHandlers(),\n  });\n\n  if (jsonlPath) {\n    await replayHistoryFromJsonl({ client: ctx.client, logger: ctx.logger }, session, jsonlPath);\n  } else if (Array.isArray(initResult.session?.messages)) {\n    await replayHistoryFromInitMessages(\n      { client: ctx.client, logger: ctx.logger },\n      session,\n      initResult.session.messages,\n    );\n  } else {\n    throw new Error(`Session history not found for ${request.sessionId}`);\n  }\n\n  return { models: getModelsState(initResult), modes: getModesState(initialMode) };\n}\n\nexport async function unstable_listSessions(\n  ctx: AgentRuntime,\n  request: ListSessionsRequest,\n): Promise<ListSessionsResponse> {\n  if (!isExperimentSessionsEnabled()) throw loadDisabledError(\"list\");\n\n  ctx.logger.log(\"listSessions:\", request.cwd ?? \"<unset>\", \"cursor:\", request.cursor ?? \"<unset>\");\n\n  const { sessions, nextCursor } = await listFactorySessions({\n    cwd: request.cwd ?? null,\n    cursor: request.cursor ?? null,\n    preferredCwd: request.cwd ?? process.cwd(),\n  });\n  ctx.logger.log(\"listSessions result:\", sessions.length, \"nextCursor:\", nextCursor ?? \"<none>\");\n\n  return {\n    sessions: sessions.map((s) => ({\n      sessionId: s.sessionId,\n      cwd: s.cwd,\n      title: s.title ? sanitizeSessionTitle(s.title) : null,\n      updatedAt: s.updatedAt,\n    })),\n    nextCursor,\n  };\n}\n\nexport async function unstable_resumeSession(\n  ctx: AgentRuntime,\n  request: ResumeSessionRequest,\n): Promise<ResumeSessionResponse> {\n  if (!isExperimentSessionsEnabled()) throw loadDisabledError(\"resume\");\n\n  const cwd = request.cwd || process.cwd();\n  ctx.logger.log(\"resumeSession:\", request.sessionId, cwd);\n\n  const existing = ctx.sessions.get(request.sessionId);\n  if (existing?.droid.isRunning()) {\n    return { models: modelsStateFromSession(existing), modes: getModesState(existing.mode) };\n  }\n\n  await stopAndDropSession(ctx, request.sessionId);\n\n  const droid = createDroidAdapter({ cwd, logger: ctx.logger, resumeSessionId: request.sessionId });\n  const initResult = await droid.start();\n\n  if (initResult.sessionId !== request.sessionId) {\n    await droid.stop();\n    throw new Error(\n      `Failed to resume session: expected ${request.sessionId} but got ${initResult.sessionId}`,\n    );\n  }\n\n  const { initialMode } = attachSession({\n    sessionId: request.sessionId,\n    cwd,\n    droid,\n    initResult,\n    client: ctx.client,\n    logger: ctx.logger,\n    sessions: ctx.sessions,\n    handlers: ctx.getAttachHandlers(),\n  });\n\n  return { models: getModelsState(initResult), modes: getModesState(initialMode) };\n}\n","import {\n  type Agent,\n  AgentSideConnection,\n  type AuthenticateRequest,\n  type AuthenticateResponse,\n  type CancelNotification,\n  type InitializeRequest,\n  type InitializeResponse,\n  type ListSessionsRequest,\n  type ListSessionsResponse,\n  type LoadSessionRequest,\n  type LoadSessionResponse,\n  type NewSessionRequest,\n  type NewSessionResponse,\n  type PromptRequest,\n  type PromptResponse,\n  type ResumeSessionRequest,\n  type ResumeSessionResponse,\n  type SetSessionModeRequest,\n  type SetSessionModeResponse,\n  type SetSessionModelRequest,\n  type SetSessionModelResponse,\n} from \"@agentclientprotocol/sdk\";\nimport type { DroidNotification, PermissionRequest } from \"../../types.ts\";\nimport type { Logger } from \"../../utils.ts\";\nimport { isExperimentSessionsEnabled } from \"../flags.ts\";\nimport { packageInfo } from \"../package-info.ts\";\nimport { handleNotification as handleDroidNotification } from \"../notifications/handle-notification.ts\";\nimport { handlePermission as handlePermissionRequest } from \"../permissions/handle-permission.ts\";\nimport type { Session } from \"../session-types.ts\";\nimport { sendAgentMessage } from \"./messages.ts\";\nimport { cancel, prompt, setSessionMode, unstable_setSessionModel } from \"./prompt.ts\";\nimport {\n  loadSession,\n  newSession,\n  unstable_listSessions,\n  unstable_resumeSession,\n} from \"./sessions.ts\";\n\nexport class DroidAcpAgent implements Agent {\n  private sessions: Map<string, Session> = new Map();\n  private client: AgentSideConnection;\n  private logger: Logger;\n\n  constructor(client: AgentSideConnection, logger?: Logger) {\n    this.client = client;\n    this.logger = logger ?? console;\n    this.logger.log(\"DroidAcpAgent initialized\");\n  }\n\n  async initialize(_request: InitializeRequest): Promise<InitializeResponse> {\n    this.logger.log(\"initialize\");\n    const enableSessions = isExperimentSessionsEnabled();\n    return {\n      protocolVersion: 1,\n      agentCapabilities: {\n        loadSession: enableSessions,\n        promptCapabilities: { image: true, embeddedContext: true },\n        sessionCapabilities: enableSessions ? { list: {}, resume: {} } : {},\n      },\n      agentInfo: {\n        name: packageInfo.name,\n        title: \"Factory Droid\",\n        version: packageInfo.version,\n      },\n      authMethods: [\n        {\n          id: \"factory-api-key\",\n          name: \"Factory API Key\",\n          description: \"Set FACTORY_API_KEY environment variable\",\n        },\n      ],\n    };\n  }\n\n  async authenticate(request: AuthenticateRequest): Promise<AuthenticateResponse> {\n    this.logger.log(\"authenticate:\", request.methodId);\n    if (request.methodId === \"factory-api-key\") {\n      if (!process.env.FACTORY_API_KEY) {\n        throw new Error(\"FACTORY_API_KEY environment variable is not set\");\n      }\n      return {};\n    }\n    throw new Error(`Unknown auth method: ${request.methodId}`);\n  }\n\n  async newSession(request: NewSessionRequest): Promise<NewSessionResponse> {\n    return newSession(this.getRuntime(), request);\n  }\n\n  async loadSession(request: LoadSessionRequest): Promise<LoadSessionResponse> {\n    return loadSession(this.getRuntime(), request);\n  }\n\n  async unstable_listSessions(request: ListSessionsRequest): Promise<ListSessionsResponse> {\n    return unstable_listSessions(this.getRuntime(), request);\n  }\n\n  async unstable_resumeSession(request: ResumeSessionRequest): Promise<ResumeSessionResponse> {\n    return unstable_resumeSession(this.getRuntime(), request);\n  }\n\n  async prompt(request: PromptRequest): Promise<PromptResponse> {\n    return prompt(this.getRuntime(), request);\n  }\n\n  async cancel(request: CancelNotification): Promise<void> {\n    return cancel(this.getRuntime(), request);\n  }\n\n  async unstable_setSessionModel(\n    request: SetSessionModelRequest,\n  ): Promise<SetSessionModelResponse | void> {\n    return unstable_setSessionModel(this.getRuntime(), request);\n  }\n\n  async setSessionMode(request: SetSessionModeRequest): Promise<SetSessionModeResponse> {\n    return setSessionMode(this.getRuntime(), request);\n  }\n\n  async cleanup(): Promise<void> {\n    for (const [, session] of this.sessions) {\n      await session.droid.stop();\n    }\n    this.sessions.clear();\n  }\n\n  private getRuntime() {\n    return {\n      client: this.client,\n      logger: this.logger,\n      sessions: this.sessions,\n      getAttachHandlers: () => this.getAttachHandlers(),\n    };\n  }\n\n  private getAttachHandlers(): {\n    handleNotification: (session: Session, n: DroidNotification) => Promise<void>;\n    handlePermission: (\n      session: Session,\n      params: PermissionRequest,\n    ) => Promise<{ selectedOption: string }>;\n  } {\n    return {\n      handleNotification: (session, n) => this.handleNotification(session, n),\n      handlePermission: (session, params) => this.handlePermission(session, params),\n    };\n  }\n\n  private async handlePermission(\n    session: Session,\n    params: PermissionRequest,\n  ): Promise<{ selectedOption: string }> {\n    return handlePermissionRequest(\n      {\n        client: this.client,\n        logger: this.logger,\n        sendAgentMessage: (s, text) => sendAgentMessage(this.client, s, text),\n      },\n      session,\n      params,\n    );\n  }\n\n  private async handleNotification(session: Session, n: DroidNotification): Promise<void> {\n    await handleDroidNotification({ client: this.client, logger: this.logger }, session, n);\n  }\n}\n","import { AgentSideConnection, ndJsonStream } from \"@agentclientprotocol/sdk\";\nimport { nodeToWebReadable, nodeToWebWritable } from \"../../utils.ts\";\nimport { DroidAcpAgent } from \"./droid-acp-agent.ts\";\n\nexport function runAcp(): void {\n  const input = nodeToWebWritable(process.stdout);\n  const output = nodeToWebReadable(process.stdin);\n\n  const stream = ndJsonStream(input, output);\n  new AgentSideConnection((client) => new DroidAcpAgent(client), stream);\n}\n"],"mappings":"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"}