{"version":3,"file":"tool-operations.mjs","names":["toToon"],"sources":["../../src/tool-operations.ts"],"sourcesContent":["/**\n * Tool executors behind the agent extensions.\n *\n * Each executor returns the text a caller reads plus the structured details a\n * harness can attach to the call. The text is TOON-encoded so the model sees\n * the same compact shape the CLI's --toon flag prints. A run's output is the\n * exception: it follows the status block as plain text, not as one TOON string.\n */\nimport { stripVTControlCharacters } from \"node:util\";\nimport { encode as toToon } from \"@toon-format/toon\";\nimport { getAllHarnesses, getHarness, isHarnessId, listHarnesses } from \"./registry.ts\";\nimport {\n  addMcpServer,\n  listMcpServers,\n  readMasterMcpServers,\n  removeMcpServer,\n  syncMcpServers,\n} from \"./mcp-servers.ts\";\nimport type { McpConfigListing, SyncReport } from \"./mcp-servers.ts\";\nimport { readAgentsConfig, syncAgentsFiles } from \"./agents-sync.ts\";\nimport type { AgentsSyncReport } from \"./agents-sync.ts\";\nexport type { AgentsSyncReport } from \"./agents-sync.ts\";\nexport type { SyncReport } from \"./mcp-servers.ts\";\nexport type { PromptSyncReport } from \"./prompt-sync.ts\";\nexport type { HarnessInvocationModes } from \"./types.ts\";\nimport { syncPromptTemplates } from \"./prompt-sync.ts\";\nimport type { PromptSyncReport } from \"./prompt-sync.ts\";\nexport type { SkillsSyncReport } from \"./skills-sync.ts\";\nimport { syncSkills } from \"./skills-sync.ts\";\nimport type { SkillsSyncReport } from \"./skills-sync.ts\";\nimport { readOnlyVersionError, selectionError } from \"./harness.ts\";\nimport type { Harness } from \"./harness.ts\";\nimport type {\n  AvailableModel,\n  EnvOverride,\n  HarnessCapabilities,\n  HarnessDetection,\n  HarnessId,\n  HarnessInvocationModes,\n  InvokeResult,\n  ListModelsResult,\n  McpServerConfig,\n  PathCandidate,\n  PromptTemplateSyncTarget,\n  ResolvedPaths,\n  SkillsSyncTarget,\n  StorageDescriptor,\n} from \"./types.ts\";\n\n/** Text for the model plus details for the harness, shared by every tool surface. */\nexport interface ToolResult<Details> {\n  content: Array<{ type: \"text\"; text: string }>;\n  details: Details;\n  /** Set when the tool could not answer. */\n  isError?: boolean;\n}\n\n/** Install state of one harness on this machine, plus the runs harnesses_run takes for it. */\nexport interface HarnessStatus {\n  id: HarnessId;\n  name: string;\n  installed: boolean;\n  version: string | null;\n  /** Takes `tools: false`, an advisor without tools. */\n  advisor: boolean;\n  /** Takes `tools: true` with `readOnly: true`; false while the installed CLI is too old for it. */\n  readOnly: boolean;\n  /** Takes `tools: true`, the full agent. */\n  agent: boolean;\n}\n\n/** Every registered harness with its install state, as scanned by {@link detectHarnesses}. */\nexport interface HarnessListing {\n  harnesses: HarnessStatus[];\n}\n\n/** Full metadata for one harness, including paths resolved for this platform. */\nexport interface HarnessMetadata {\n  id: HarnessId;\n  name: string;\n  binaries: string[];\n  capabilities: HarnessCapabilities;\n  invocationModes: HarnessInvocationModes;\n  /** Network for what a read-only run starts here, MCP servers included; null when unknown. */\n  readOnlyNetwork: boolean | null;\n  modelListing: boolean;\n  modelSelection: boolean;\n  effortSelection: boolean;\n  config: PathCandidate[];\n  sessions: PathCandidate[];\n  instructions: PathCandidate[];\n  skills: PathCandidate[];\n  skillsSyncTarget: SkillsSyncTarget | null;\n  commands: PathCandidate[];\n  promptTemplates: PathCandidate[];\n  promptTemplateSyncTarget: PromptTemplateSyncTarget | null;\n  hooks: PathCandidate[];\n  temp: PathCandidate[];\n  envOverrides: EnvOverride[];\n  persistence: StorageDescriptor[];\n  detection: HarnessDetection;\n  resolved: ResolvedPaths;\n}\n\n/** Returned when the requested harness id is not registered. */\nexport interface UnknownHarness {\n  error: string;\n  known: HarnessId[];\n}\n\n/** Returned when a direct batch call bypasses the tool schema limits. */\nexport interface HarnessInfoInputError {\n  error: string;\n}\n\n/** One harness lookup result. */\nexport type HarnessInfoResult = HarnessMetadata | UnknownHarness;\n\n/** Scalar, batch, or rejected batch details from {@link harnessInfo}. */\nexport type HarnessInfoDetails = HarnessInfoResult | HarnessInfoResult[] | HarnessInfoInputError;\n\nimport { HARNESS_INFO_MAX_ITEMS, RUN_TIMEOUT_DEFAULT_SECONDS } from \"./tool-schemas.ts\";\nexport { HARNESS_INFO_MAX_ITEMS } from \"./tool-schemas.ts\";\n\n/** Default wall-clock budget for one harness run, in seconds. */\nexport const RUN_DEFAULT_TIMEOUT_SECONDS = RUN_TIMEOUT_DEFAULT_SECONDS;\n\n/** The run tool's per-stream cap: harness output is unbounded, model context is not. */\nexport const RUN_MAX_OUTPUT_CHARS = 8000;\n\n/** What the run tool and the CLI say about an advisor answer with a tool call written as text. */\nexport const TOOL_CALL_TEXT_WARNING =\n  \"The advisor wrote a tool call as text. Nothing ran it, so any result it reports from that call is unverified\";\n\nfunction text(data: unknown): Array<{ type: \"text\"; text: string }> {\n  return [{ type: \"text\", text: toToon(data) }];\n}\n\nfunction unknownHarness(id: string): ToolResult<UnknownHarness> {\n  const details: UnknownHarness = { error: `Unknown harness: ${id}`, known: listHarnesses() };\n  return { content: text(details), details, isError: true };\n}\n\nfunction errorMessage(error: unknown): string {\n  return error instanceof Error ? error.message : String(error);\n}\n\nfunction truncate(output: string): string {\n  if (output.length <= RUN_MAX_OUTPUT_CHARS) return output;\n  return `${output.slice(0, RUN_MAX_OUTPUT_CHARS)}\\n[truncated ${output.length - RUN_MAX_OUTPUT_CHARS} of ${output.length} characters]`;\n}\n\ntype RunInvocationOptions = Readonly<{\n  model?: string;\n  effort?: string;\n  structured: boolean;\n  tools: boolean;\n  readOnly: boolean;\n}>;\n\ntype InvocationMode = keyof HarnessInvocationModes;\n\nconst ALTERNATE_INVOCATION_MODE: Partial<Record<InvocationMode, InvocationMode>> = {\n  advisor: \"agent\",\n  advisorStructured: \"agentStructured\",\n  agent: \"advisor\",\n  agentStructured: \"advisorStructured\",\n};\n\nfunction selectedInvocationMode(\n  structured: boolean,\n  tools: boolean,\n  readOnly: boolean,\n): InvocationMode {\n  if (readOnly) return structured ? \"readOnlyStructured\" : \"readOnly\";\n  if (tools) return structured ? \"agentStructured\" : \"agent\";\n  return structured ? \"advisorStructured\" : \"advisor\";\n}\n\nfunction invocationRetry(\n  invocationModes: Readonly<HarnessInvocationModes>,\n  mode: InvocationMode,\n  options: RunInvocationOptions,\n): RunFailure[\"retry\"] {\n  const withoutStructured = selectedInvocationMode(false, options.tools, options.readOnly);\n  if (options.structured) {\n    if (invocationModes[withoutStructured]) return { structured: false };\n    const alternateWithoutStructured = ALTERNATE_INVOCATION_MODE[withoutStructured];\n    if (alternateWithoutStructured && invocationModes[alternateWithoutStructured]) {\n      return { structured: false, tools: !options.tools };\n    }\n  }\n\n  const alternateMode = ALTERNATE_INVOCATION_MODE[mode];\n  return alternateMode !== undefined && invocationModes[alternateMode]\n    ? { tools: !options.tools }\n    : undefined;\n}\n\n/** The run as its status block shows it: everything but the two streams. */\ntype RunStatus = Readonly<Omit<RunOutcome, \"args\" | \"stdout\" | \"stderr\">> & {\n  readonly args: readonly string[];\n};\n\ntype ListingStatus = Readonly<Omit<ModelsOutcome, \"args\" | \"models\" | \"stderr\">> & {\n  readonly args: readonly string[];\n  readonly models: readonly Readonly<AvailableModel>[];\n};\n\ntype RunStreams = Readonly<Partial<Pick<RunOutcome, \"stdout\" | \"stderr\">>>;\n\n// oxlint-disable-next-line no-control-regex -- Terminal control bytes are precisely what this boundary removes.\nconst OUTPUT_CONTROLS = /[\\u0000-\\u0008\\u000B-\\u001F\\u007F-\\u009F]/g;\n\n/**\n * Strips what TOON quoting used to escape: terminal sequences and control bytes; CRLF becomes LF.\n *\n * @param output - One capped stream.\n * @returns {string} The stream as plain text.\n */\nfunction plainOutput(output: string): string {\n  return stripVTControlCharacters(output).replaceAll(\"\\r\\n\", \"\\n\").replace(OUTPUT_CONTROLS, \" \");\n}\n\n/**\n * Lays a run or listing out as a TOON status block, then each stream as plain text:\n * quoting a markdown answer into TOON escaped every code block and cost a tenth more tokens.\n *\n * @param outcome - The run or listing without its output.\n * @param streams - The capped streams; empty ones are left out.\n * @returns {Array<{ type: \"text\"; text: string }>} The text handed to the model.\n */\nfunction runText(\n  outcome: RunStatus | ListingStatus,\n  streams: RunStreams,\n): Array<{ type: \"text\"; text: string }> {\n  const blocks = [toToon(outcome)];\n  for (const name of [\"stdout\", \"stderr\"] as const) {\n    const output = streams[name];\n    if (output !== undefined && output.length > 0) blocks.push(`${name}:\\n${plainOutput(output)}`);\n  }\n  return [{ type: \"text\", text: blocks.join(\"\\n\\n\") }];\n}\n\nfunction completedRun(\n  harness: Harness,\n  result: InvokeResult,\n  options: RunInvocationOptions,\n  templateArgs: readonly string[],\n): ToolResult<RunOutcome> {\n  const contentOutcome: Omit<RunOutcome, \"stdout\" | \"stderr\"> = {\n    id: harness.id,\n    command: result.command,\n    args: [...templateArgs],\n    ...(options.model === undefined ? {} : { model: options.model }),\n    ...(options.effort === undefined ? {} : { effort: options.effort }),\n    structured: options.structured,\n    tools: options.tools,\n    readOnly: options.readOnly,\n    exitCode: result.exitCode,\n    timedOut: result.timedOut,\n    aborted: result.aborted,\n    ...(result.idleMs === undefined ? {} : { idleMs: result.idleMs }),\n    ...(result.toolCallsAsText ? { warning: TOOL_CALL_TEXT_WARNING } : {}),\n  };\n  const stdout = truncate(result.stdout);\n  const stderr = truncate(result.stderr);\n  const details: RunOutcome = { ...contentOutcome, args: result.args, stdout, stderr };\n  if (result.timedOut || result.exitCode !== 0) {\n    return { content: runText(contentOutcome, { stdout, stderr }), details, isError: true };\n  }\n  return {\n    content: runText(contentOutcome, stdout.length > 0 ? { stdout } : { stderr }),\n    details,\n  };\n}\n\nfunction unsupportedInvocation(\n  harness: Harness,\n  id: string,\n  options: RunInvocationOptions,\n): ToolResult<RunFailure> {\n  const error = harness.invocationError(options) ?? `Invalid ${id} invocation`;\n  const invocationModes = harness.invocationModes;\n  const mode = selectedInvocationMode(options.structured, options.tools, options.readOnly);\n  if (\n    invocationModes[mode] ||\n    harness.invocation === null ||\n    selectionError(harness.id, harness.invocation, options) !== null\n  ) {\n    const details: RunFailure = { error };\n    return { content: text(details), details, isError: true };\n  }\n\n  const retry = invocationRetry(invocationModes, mode, options);\n  const details: RunFailure = {\n    error,\n    invocationModes,\n    ...(retry === undefined ? {} : { retry }),\n  };\n  return { content: text(details), details, isError: true };\n}\n\n/**\n * Scans every registered harness for its binaries and version, next to the modes it runs in.\n *\n * @returns {ToolResult<HarnessListing>} The complete installation listing.\n */\nexport function detectHarnesses(): ToolResult<HarnessListing> {\n  const details: HarnessListing = {\n    harnesses: getAllHarnesses().map((harness) => {\n      const installed = harness.isInstalled();\n      const version = installed ? harness.version : null;\n      const { advisor, readOnly, agent } = harness.invocationModes;\n      const belowFloor =\n        installed && readOnlyVersionError(harness.id, harness.invocation, version) !== null;\n      return {\n        id: harness.id,\n        name: harness.name,\n        installed,\n        version,\n        advisor,\n        readOnly: readOnly && !belowFloor,\n        agent,\n      };\n    }),\n  };\n\n  return { content: text(details), details };\n}\n\nfunction harnessInfoResult(id: string): HarnessInfoResult {\n  if (!isHarnessId(id)) return unknownHarness(id).details;\n\n  const harness = getHarness(id);\n  return {\n    id: harness.id,\n    name: harness.name,\n    binaries: harness.binaries,\n    capabilities: harness.capabilities,\n    invocationModes: harness.invocationModes,\n    readOnlyNetwork: harness.readOnlyNetwork(),\n    modelListing: harness.modelListing !== null,\n    modelSelection: harness.invocation?.modelArgs !== undefined,\n    effortSelection: harness.invocation?.effortArgs !== undefined,\n    config: harness.config,\n    sessions: harness.sessions,\n    instructions: harness.instructions,\n    skills: harness.skills,\n    skillsSyncTarget: harness.skillsSyncTarget,\n    commands: harness.commands,\n    promptTemplates: harness.promptTemplates,\n    promptTemplateSyncTarget: harness.promptTemplateSyncTarget,\n    hooks: harness.hooks,\n    temp: harness.temp,\n    envOverrides: harness.envOverrides,\n    persistence: harness.persistence,\n    detection: harness.detection,\n    resolved: harness.resolve(),\n  };\n}\n\n/**\n * One lookup as the model reads it: every path list once, in\n * {@link HarnessMetadata.resolved}, and the env overrides with their default\n * roots resolved the same way.\n */\ntype HarnessInfoText =\n  | Omit<\n      HarnessMetadata,\n      | \"config\"\n      | \"sessions\"\n      | \"instructions\"\n      | \"skills\"\n      | \"skillsSyncTarget\"\n      | \"commands\"\n      | \"promptTemplates\"\n      | \"promptTemplateSyncTarget\"\n      | \"hooks\"\n      | \"temp\"\n    >\n  | UnknownHarness;\n\n/**\n * Leaves the path templates out of the text: `resolved` already carries each\n * of them for this machine, so they only doubled every answer. Env overrides\n * have no resolved copy, so their own roots are resolved in place.\n *\n * @param result - One lookup result.\n * @returns {HarnessInfoText} The lookup with its path lists shown once.\n */\nfunction harnessInfoText(result: HarnessInfoResult): HarnessInfoText {\n  if (\"error\" in result) return result;\n  const {\n    id,\n    name,\n    binaries,\n    capabilities,\n    invocationModes,\n    readOnlyNetwork,\n    modelListing,\n    modelSelection,\n    effortSelection,\n    envOverrides,\n    persistence,\n    detection,\n    resolved,\n  } = result;\n  return {\n    id,\n    name,\n    binaries,\n    capabilities,\n    invocationModes,\n    readOnlyNetwork,\n    modelListing,\n    modelSelection,\n    effortSelection,\n    envOverrides: getHarness(id).resolveCandidates(envOverrides),\n    persistence,\n    detection,\n    resolved,\n  };\n}\n\n/** Full metadata for one harness, with paths resolved for the current platform. */\nexport function harnessInfo(id: string): ToolResult<HarnessInfoResult>;\n/** Full metadata for several harnesses, preserving input order and errors for each item. */\nexport function harnessInfo(\n  ids: readonly string[],\n): ToolResult<HarnessInfoResult[] | HarnessInfoInputError>;\nexport function harnessInfo(input: string | readonly string[]): ToolResult<HarnessInfoDetails>;\nexport function harnessInfo(input: string | readonly string[]): ToolResult<HarnessInfoDetails> {\n  if (typeof input === \"string\") {\n    const details = harnessInfoResult(input);\n    return {\n      content: text(harnessInfoText(details)),\n      details,\n      ...(\"error\" in details ? { isError: true } : {}),\n    };\n  }\n\n  if (input.length < 1 || input.length > HARNESS_INFO_MAX_ITEMS) {\n    const details: HarnessInfoInputError = {\n      error: `harnesses_info accepts between 1 and ${HARNESS_INFO_MAX_ITEMS} ids`,\n    };\n    return { content: text(details), details, isError: true };\n  }\n\n  const details = input.map(harnessInfoResult);\n  return {\n    content: text(details.map(harnessInfoText)),\n    details,\n    ...(details.some((result) => \"error\" in result) ? { isError: true } : {}),\n  };\n}\n\n/** Options accepted by {@link listHarnessModels}. */\nexport interface ModelsOptions {\n  search?: string;\n  cwd?: string;\n  /** Wall-clock budget in seconds; defaults to {@link RUN_DEFAULT_TIMEOUT_SECONDS}. */\n  timeoutSeconds?: number;\n  /** Cancel the owned command through the host request signal. */\n  signal?: AbortSignal;\n}\n\n/** One completed native model-listing query. */\nexport interface ModelsOutcome {\n  id: HarnessId;\n  command: string;\n  args: string[];\n  search?: string;\n  models: AvailableModel[];\n  exitCode: number | null;\n  timedOut: boolean;\n  aborted: boolean;\n  /** Milliseconds without output before the listing was stopped; absent when it exited on its own. */\n  idleMs?: number;\n  stderr: string;\n}\n\n/**\n * Lists the models currently available to one harness through its native CLI.\n *\n * @param id - Harness id to query.\n * @param options - Search, working-directory, and timeout options.\n * @returns {Promise<ToolResult<ModelsOutcome | RunFailure>>} The model listing or failure.\n */\nexport async function listHarnessModels(\n  id: string,\n  options: ModelsOptions = {},\n): Promise<ToolResult<ModelsOutcome | RunFailure>> {\n  if (!isHarnessId(id)) return unknownHarness(id);\n\n  const harness = getHarness(id);\n  const built = harness.buildModelListInvocation(options.search);\n  if (!built) {\n    const details: RunFailure = { error: `Harness ${id} does not support model listing` };\n    return { content: text(details), details, isError: true };\n  }\n\n  const timeoutSeconds = options.timeoutSeconds ?? RUN_DEFAULT_TIMEOUT_SECONDS;\n  let result: ListModelsResult;\n  try {\n    result = await harness.listModels({\n      search: options.search,\n      cwd: options.cwd,\n      timeoutMs: timeoutSeconds * 1000,\n      signal: options.signal,\n    });\n  } catch (error) {\n    const details: RunFailure = { error: `Failed to list ${id} models: ${errorMessage(error)}` };\n    return { content: text(details), details, isError: true };\n  }\n\n  return completedListing(harness.id, result, result.models, options.search);\n}\n\nfunction completedListing(\n  id: HarnessId,\n  result: InvokeResult,\n  models: readonly Readonly<AvailableModel>[],\n  search: string | undefined,\n): ToolResult<ModelsOutcome> {\n  const contentOutcome: Omit<ModelsOutcome, \"stderr\"> = {\n    id,\n    command: result.command,\n    args: [...result.args],\n    ...(search === undefined ? {} : { search }),\n    models: [...models],\n    exitCode: result.exitCode,\n    timedOut: result.timedOut,\n    aborted: result.aborted,\n    ...(result.idleMs === undefined ? {} : { idleMs: result.idleMs }),\n  };\n  const stderr = truncate(result.stderr);\n  const details: ModelsOutcome = { ...contentOutcome, stderr };\n  if (result.timedOut || result.exitCode !== 0) {\n    return { content: runText(contentOutcome, { stderr }), details, isError: true };\n  }\n  return { content: runText(contentOutcome, {}), details };\n}\n\n/** Options accepted by {@link runHarness}. */\nexport interface RunOptions {\n  cwd?: string;\n  /** Harness-native model id or selector. */\n  model?: string;\n  /** Reasoning effort in the harness's own words; rejected where `effortArgs` is missing. */\n  effort?: string;\n  /** Wall-clock budget in seconds; defaults to {@link RUN_DEFAULT_TIMEOUT_SECONDS}. */\n  timeoutSeconds?: number;\n  /** Cancel the owned command through the host request signal. */\n  signal?: AbortSignal;\n  /** Use the harness's structured (JSON) output mode instead of plain text. */\n  structured?: boolean;\n  /** Enable tools; defaults to a native advisor without tools invocation. */\n  tools?: boolean;\n  /** Require native enforcement of read-only tool access. Implies tools when `tools` is omitted; `tools: false` rejects the run. */\n  readOnly?: boolean;\n}\n\n/** One completed (or failed) harness run, with output capped for the model. */\nexport interface RunOutcome {\n  id: HarnessId;\n  command: string;\n  /** Expanded arguments; the model's text keeps \"{prompt}\" instead, it wrote the prompt itself. */\n  args: string[];\n  model?: string;\n  effort?: string;\n  structured: boolean;\n  tools: boolean;\n  readOnly: boolean;\n  exitCode: number | null;\n  timedOut: boolean;\n  aborted: boolean;\n  /** Milliseconds without output before the run was stopped; absent when it exited on its own. */\n  idleMs?: number;\n  /** Present when an advisor answer holds a tool call written as text. */\n  warning?: string;\n  stdout: string;\n  stderr: string;\n}\n\n/** Returned when the harness cannot be run at all. */\nexport interface RunFailure {\n  error: string;\n  known?: HarnessId[];\n  /** Modes accepted by the selected harness when invocation mode caused the failure. */\n  invocationModes?: HarnessInvocationModes;\n  /** Explicit mode change that makes the same invocation shape executable. */\n  retry?: { structured: false; tools?: boolean } | { tools: boolean };\n}\n\nfunction normalizedRunAccess(options: Readonly<RunOptions>): {\n  tools: boolean;\n  readOnly: boolean;\n} {\n  const readOnly = options.readOnly ?? false;\n  return { readOnly, tools: options.tools ?? readOnly };\n}\n\n/**\n * Runs one prompt through a harness's normalized non-interactive invocation.\n *\n * Tool use defaults to a native advisor without tools invocation. Harnesses that\n * cannot disable tools reject that mode; setting `tools` selects their full\n * agent invocation. `model` and `effort` are translated through the harness-specific recipe.\n * This layer also closes stdin, enforces the timeout, caps the echoed output,\n * and leaves the prompt out of the echoed invocation.\n *\n * @param id - Harness id to run.\n * @param prompt - Prompt sent to the selected harness.\n * @param options - Model, mode, working-directory, and timeout options.\n * @returns {Promise<ToolResult<RunOutcome | RunFailure>>} The capped run outcome or failure.\n */\nexport async function runHarness(\n  id: string,\n  prompt: string,\n  options: RunOptions = {},\n): Promise<ToolResult<RunOutcome | RunFailure>> {\n  if (!isHarnessId(id)) return unknownHarness(id);\n\n  const harness = getHarness(id);\n  const structured = options.structured ?? false;\n  const { tools, readOnly } = normalizedRunAccess(options);\n  const invocationOptions = {\n    model: options.model,\n    effort: options.effort,\n    structured,\n    tools,\n    readOnly,\n  };\n  const template = harness.buildInvocation(\"{prompt}\", invocationOptions);\n  if (!template) {\n    return unsupportedInvocation(harness, id, invocationOptions);\n  }\n\n  const timeoutSeconds = options.timeoutSeconds ?? RUN_DEFAULT_TIMEOUT_SECONDS;\n\n  let result: InvokeResult;\n  try {\n    result = await harness.invoke(prompt, {\n      cwd: options.cwd,\n      model: options.model,\n      effort: options.effort,\n      timeoutMs: timeoutSeconds * 1000,\n      signal: options.signal,\n      structured,\n      tools,\n      readOnly,\n    });\n  } catch (error) {\n    const details: RunFailure = { error: `Failed to run ${id}: ${errorMessage(error)}` };\n    return { content: text(details), details, isError: true };\n  }\n\n  return completedRun(harness, result, invocationOptions, template.args);\n}\n\n/** MCP server listings for one harness or all of them. */\nexport interface McpListing {\n  harnesses: Array<{ id: HarnessId; configs: McpConfigListing[] }>;\n}\n\n/** Marker used only at the tool and CLI boundary, leaving config reads lossless for edits. */\nconst MCP_REDACTED_VALUE = \"<redacted>\";\nconst MCP_CONFIG_ERROR = \"Unable to read or parse MCP config\";\n\nfunction redactMcpValues(values: Readonly<Record<string, string>>): Record<string, string> {\n  return Object.fromEntries(Object.keys(values).map((key) => [key, MCP_REDACTED_VALUE]));\n}\n\n/** Result of one MCP config mutation. */\nexport interface McpMutation {\n  id: HarnessId;\n  path: string;\n  action: \"added\" | \"replaced\" | \"removed\" | \"noop\";\n}\n\n/** Flat tool parameters describing one MCP server, shared by every surface. */\nexport interface McpServerParams {\n  name: string;\n  transport?: McpServerConfig[\"transport\"];\n  command?: string;\n  args?: string[];\n  env?: Record<string, string>;\n  url?: string;\n  headers?: Record<string, string>;\n}\n\n/**\n * Builds the normalized server shape from flat tool parameters.\n *\n * @param params - Flat MCP server parameters.\n * @returns {McpServerConfig} The normalized server configuration.\n */\nexport function toMcpServerConfig(params: McpServerParams): McpServerConfig {\n  const server: McpServerConfig = {\n    name: params.name,\n    transport: params.transport ?? (params.url ? \"http\" : \"stdio\"),\n  };\n  if (params.command !== undefined) server.command = params.command;\n  if (params.args !== undefined) server.args = params.args;\n  if (params.env !== undefined) server.env = params.env;\n  if (params.url !== undefined) server.url = params.url;\n  if (params.headers !== undefined) server.headers = params.headers;\n  return server;\n}\n\n/**\n * Lists configured MCP servers, normalized across harness config dialects.\n *\n * @param id - Optional harness id; omission lists every harness.\n * @returns {ToolResult<McpListing | UnknownHarness>} The normalized listing or id error.\n */\nexport function mcpList(id?: string): ToolResult<McpListing | UnknownHarness> {\n  if (id !== undefined && !isHarnessId(id)) return unknownHarness(id);\n\n  const targets = id !== undefined && isHarnessId(id) ? [getHarness(id)] : getAllHarnesses();\n  const details: McpListing = {\n    harnesses: targets\n      .map((harness) => ({\n        id: harness.id,\n        configs: listMcpServers(harness).map((listing) => ({\n          ...listing,\n          ...(listing.error === undefined ? {} : { error: MCP_CONFIG_ERROR }),\n          servers: listing.servers.map((server) => ({\n            ...server,\n            ...(server.env === undefined ? {} : { env: redactMcpValues(server.env) }),\n            ...(server.headers === undefined ? {} : { headers: redactMcpValues(server.headers) }),\n          })),\n        })),\n      }))\n      .filter((entry) => entry.configs.length > 0),\n  };\n\n  return { content: text(details), details };\n}\n\nfunction mcpMutate(\n  id: string,\n  mutate: (harness: Harness) => { path: string; action: McpMutation[\"action\"] },\n): ToolResult<McpMutation | RunFailure> {\n  if (!isHarnessId(id)) return unknownHarness(id);\n\n  try {\n    const { path, action } = mutate(getHarness(id));\n    const details: McpMutation = { id, path, action };\n    return { content: text(details), details, ...(action === \"noop\" ? { isError: true } : {}) };\n  } catch (error) {\n    const details: RunFailure = { error: errorMessage(error) };\n    return { content: text(details), details, isError: true };\n  }\n}\n\n/**\n * Adds or replaces one MCP server in a harness's config.\n *\n * @param id - Target harness id.\n * @param params - Server parameters to normalize and write.\n * @param scope - User or project config scope.\n * @returns {ToolResult<McpMutation | RunFailure>} The mutation outcome or failure.\n */\nexport function mcpAdd(\n  id: string,\n  params: McpServerParams,\n  scope: \"user\" | \"project\" = \"user\",\n): ToolResult<McpMutation | RunFailure> {\n  return mcpMutate(id, (harness) => {\n    const { path, replaced } = addMcpServer(harness, toMcpServerConfig(params), scope);\n    return { path, action: replaced ? \"replaced\" : \"added\" };\n  });\n}\n\n/**\n * Removes one MCP server from a harness's config.\n *\n * @param id - Target harness id.\n * @param name - Server name to remove.\n * @param scope - User or project config scope.\n * @returns {ToolResult<McpMutation | RunFailure>} The mutation outcome or failure.\n */\nexport function mcpRemove(\n  id: string,\n  name: string,\n  scope: \"user\" | \"project\" = \"user\",\n): ToolResult<McpMutation | RunFailure> {\n  return mcpMutate(id, (harness) => {\n    const { path, removed } = removeMcpServer(harness, name, scope);\n    return { path, action: removed ? \"removed\" : \"noop\" };\n  });\n}\n\n/**\n * Pushes the master MCP list from ~/.config/agntn/mcp.jsonc into harness configs.\n * A misspelled id in excludes or keep fails the run before the first write.\n *\n * @param id - Optional harness id; omission targets every harness.\n * @returns {ToolResult<SyncReport | RunFailure>} The sync report or failure.\n */\nexport function mcpSync(id?: string): ToolResult<SyncReport | RunFailure> {\n  if (id !== undefined && !isHarnessId(id)) return unknownHarness(id);\n\n  try {\n    const master = readMasterMcpServers();\n    const unknown = [\n      ...master.excludes\n        .filter((entry) => !isHarnessId(entry))\n        .map((entry) => `${entry} (excludes)`),\n      ...Object.keys(master.keep)\n        .filter((entry) => !isHarnessId(entry))\n        .map((entry) => `${entry} (keep)`),\n    ];\n    if (unknown.length > 0) {\n      const details: RunFailure = {\n        error: `Master MCP list names unknown harnesses: ${unknown.join(\", \")}`,\n        known: listHarnesses(),\n      };\n      return { content: text(details), details, isError: true };\n    }\n    const details = syncMcpServers(\n      id !== undefined && isHarnessId(id) ? [getHarness(id)] : getAllHarnesses(),\n    );\n    return { content: text(details), details };\n  } catch (error) {\n    const details: RunFailure = { error: errorMessage(error) };\n    return { content: text(details), details, isError: true };\n  }\n}\n\n/**\n * Links every harness's global instructions file to the master AGENTS.md.\n *\n * @param id - Optional harness id; omission targets every harness.\n * @param check - Report intended changes without writing them.\n * @returns {ToolResult<AgentsSyncReport | RunFailure>} The sync report or failure.\n */\nexport function agentsSync(id?: string, check = false): ToolResult<AgentsSyncReport | RunFailure> {\n  if (id !== undefined && !isHarnessId(id)) return unknownHarness(id);\n\n  try {\n    // Preflight before any write: a typo in excludes must fail the whole run,\n    // not silently adopt the harness it was meant to protect.\n    const unknown = readAgentsConfig().excludes.filter((entry) => !isHarnessId(entry));\n    if (unknown.length > 0) {\n      const details: RunFailure = {\n        error: `Agents config excludes unknown harnesses: ${unknown.join(\", \")}`,\n        known: listHarnesses(),\n      };\n      return { content: text(details), details, isError: true };\n    }\n    const details = syncAgentsFiles(\n      id !== undefined && isHarnessId(id) ? [getHarness(id)] : getAllHarnesses(),\n      check,\n    );\n    return { content: text(details), details };\n  } catch (error) {\n    const details: RunFailure = { error: errorMessage(error) };\n    return { content: text(details), details, isError: true };\n  }\n}\n\n/**\n * Synchronizes canonical Markdown prompt templates into harness destinations.\n *\n * @param id - Optional harness id; omission targets every harness.\n * @param check - Report intended changes without writing them.\n * @returns {ToolResult<PromptSyncReport | RunFailure>} The sync report or failure.\n */\nexport function promptsSync(id?: string, check = false): ToolResult<PromptSyncReport | RunFailure> {\n  if (id !== undefined && !isHarnessId(id)) return unknownHarness(id);\n\n  try {\n    const details = syncPromptTemplates(\n      id !== undefined && isHarnessId(id) ? [getHarness(id)] : getAllHarnesses(),\n      check,\n    );\n    return { content: text(details), details };\n  } catch (error) {\n    const details: RunFailure = { error: errorMessage(error) };\n    return { content: text(details), details, isError: true };\n  }\n}\n\n/**\n * Links harness skills directories to the canonical skills directory.\n *\n * @param id - Optional harness id; omission targets every harness.\n * @param check - Report intended changes without writing them.\n * @returns {ToolResult<SkillsSyncReport | RunFailure>} The sync report or failure.\n */\nexport function skillsSync(id?: string, check = false): ToolResult<SkillsSyncReport | RunFailure> {\n  if (id !== undefined && !isHarnessId(id)) return unknownHarness(id);\n\n  try {\n    const details = syncSkills(\n      id !== undefined && isHarnessId(id) ? [getHarness(id)] : getAllHarnesses(),\n      check,\n    );\n    return { content: text(details), details };\n  } catch (error) {\n    const details: RunFailure = { error: errorMessage(error) };\n    return { content: text(details), details, isError: true };\n  }\n}\n"],"mappings":"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"}