@agntn/harnesses 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { _ as getHarness, d as removeMcpServer, f as syncMcpServers, g as getAllHarnesses, i as syncAgentsFiles, n as syncPromptTemplates, o as addMcpServer, r as readAgentsConfig, s as listMcpServers, t as syncSkills, u as readMasterMcpServers, v as isHarnessId, y as listHarnesses } from "./skills-sync.mjs";
1
+ import { _ as getAllHarnesses, b as listHarnesses, c as listMcpServers, d as readMasterMcpServers, f as removeMcpServer, i as syncAgentsFiles, n as syncPromptTemplates, p as syncMcpServers, r as readAgentsConfig, s as addMcpServer, t as syncSkills, v as getHarness, y as isHarnessId } from "./skills-sync.mjs";
2
2
  import "./tool-schemas.mjs";
3
3
  import { stripVTControlCharacters } from "node:util";
4
4
  import { encode } from "@toon-format/toon";
@@ -242,7 +242,7 @@ async function listHarnessModels(id, options = {}) {
242
242
  return completedListing(harness.id, result, result.models, options.search);
243
243
  }
244
244
  function completedListing(id, result, models, search) {
245
- const details = {
245
+ const contentOutcome = {
246
246
  id,
247
247
  command: result.command,
248
248
  args: [...result.args],
@@ -251,13 +251,21 @@ function completedListing(id, result, models, search) {
251
251
  exitCode: result.exitCode,
252
252
  timedOut: result.timedOut,
253
253
  aborted: result.aborted,
254
- ...result.idleMs === void 0 ? {} : { idleMs: result.idleMs },
255
- stderr: truncate(result.stderr)
254
+ ...result.idleMs === void 0 ? {} : { idleMs: result.idleMs }
256
255
  };
257
- return {
258
- content: text(details),
256
+ const stderr = truncate(result.stderr);
257
+ const details = {
258
+ ...contentOutcome,
259
+ stderr
260
+ };
261
+ if (result.timedOut || result.exitCode !== 0) return {
262
+ content: runText(contentOutcome, { stderr }),
259
263
  details,
260
- ...result.timedOut || result.exitCode !== 0 ? { isError: true } : {}
264
+ isError: true
265
+ };
266
+ return {
267
+ content: runText(contentOutcome, {}),
268
+ details
261
269
  };
262
270
  }
263
271
  function normalizedRunAccess(options) {
@@ -1 +1 @@
1
- {"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 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. */\nexport interface HarnessStatus {\n id: HarnessId;\n name: string;\n installed: boolean;\n version: string | null;\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 modelListing: boolean;\n modelSelection: 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\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 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 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 the run out for the model: the TOON status block, then each stream under\n * its name as plain text, since quoting a markdown answer into one TOON string\n * escaped every code block and cost about a tenth more tokens.\n *\n * @param outcome - The run 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(outcome: RunStatus, streams: RunStreams): 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 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 };\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 const modelUnsupported =\n options.model !== undefined && harness.invocation?.modelArgs === undefined;\n if (invocationModes[mode] || harness.invocation === null || modelUnsupported) {\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.\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 return {\n id: harness.id,\n name: harness.name,\n installed,\n version: installed ? harness.version : null,\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 modelListing: harness.modelListing !== null,\n modelSelection: harness.invocation?.modelArgs !== 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 modelListing,\n modelSelection,\n envOverrides,\n persistence,\n detection,\n resolved,\n } = result;\n return {\n id,\n name,\n binaries,\n capabilities,\n invocationModes,\n modelListing,\n modelSelection,\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 details: ModelsOutcome = {\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 stderr: truncate(result.stderr),\n };\n\n return {\n content: text(details),\n details,\n ...(result.timedOut || result.exitCode !== 0 ? { isError: true } : {}),\n };\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 /** 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 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 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` is 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 = { model: options.model, structured, tools, readOnly };\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 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 *\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 // Preflight before any write: a typo in excludes must fail the whole run,\n // not silently leave the misspelled harness unprotected.\n const unknown = readMasterMcpServers().excludes.filter((entry) => !isHarnessId(entry));\n if (unknown.length > 0) {\n const details: RunFailure = {\n error: `Master MCP list excludes 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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"}
1
+ {"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 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. */\nexport interface HarnessStatus {\n id: HarnessId;\n name: string;\n installed: boolean;\n version: string | null;\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 modelListing: boolean;\n modelSelection: 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\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 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 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 };\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 const modelUnsupported =\n options.model !== undefined && harness.invocation?.modelArgs === undefined;\n if (invocationModes[mode] || harness.invocation === null || modelUnsupported) {\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.\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 return {\n id: harness.id,\n name: harness.name,\n installed,\n version: installed ? harness.version : null,\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 modelListing: harness.modelListing !== null,\n modelSelection: harness.invocation?.modelArgs !== 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 modelListing,\n modelSelection,\n envOverrides,\n persistence,\n detection,\n resolved,\n } = result;\n return {\n id,\n name,\n binaries,\n capabilities,\n invocationModes,\n modelListing,\n modelSelection,\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 /** 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 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 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` is 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 = { model: options.model, structured, tools, readOnly };\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 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 *\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 // Preflight before any write: a typo in excludes must fail the whole run,\n // not silently leave the misspelled harness unprotected.\n const unknown = readMasterMcpServers().excludes.filter((entry) => !isHarnessId(entry));\n if (unknown.length > 0) {\n const details: RunFailure = {\n error: `Master MCP list excludes 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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"}
@@ -1,6 +1,6 @@
1
1
  //#endregion
2
2
  //#region src/types.ts
3
- const version = "0.3.1";
3
+ const version = "0.4.0";
4
4
  //#endregion
5
5
  export { version as t };
6
6
 
@@ -1 +1 @@
1
- {"version":3,"file":"types.mjs","names":["pkg.version"],"sources":["../../package.json","../../src/types.ts"],"sourcesContent":["","import pkg from \"../package.json\" with { type: \"json\" };\n\nexport const version: string = pkg.version;\n\nexport type HarnessId =\n | \"antigravity\"\n | \"codex\"\n | \"gemini\"\n | \"grok\"\n | \"claude\"\n | \"opencode\"\n | \"cursor\"\n | \"freebuff\"\n | \"github-copilot\"\n | \"mastracode\"\n | \"omp\"\n | \"pi\"\n | \"prime-agent\";\nexport type EvidenceLevel = \"official\" | \"community\" | \"inferred\";\nexport type Platform = \"linux\" | \"darwin\" | \"win32\";\n\nexport interface PathCandidate {\n path: string;\n scope: \"user\" | \"project\" | \"system\" | \"data\";\n level: EvidenceLevel;\n platforms?: Platform[];\n note?: string;\n}\n\n/** The path lists of a harness descriptor, as named in {@link ResolvedPaths}. */\nexport type PathCategory =\n | \"config\"\n | \"sessions\"\n | \"instructions\"\n | \"skills\"\n | \"commands\"\n | \"promptTemplates\"\n | \"hooks\"\n | \"temp\";\n\n/**\n * An environment variable the harness reads to move one of its roots. `path`\n * is the default root, used while the variable is unset or empty.\n */\nexport interface EnvOverride extends PathCandidate {\n variable: string;\n /** Categories with entries under this root, which move with it. */\n relocates: PathCategory[];\n}\n\n/** The user-scope skills directory that skill synchronization links to the source. */\nexport interface SkillsSyncTarget extends PathCandidate {\n scope: \"user\";\n}\n\n/** One stable user-scope destination used by prompt template synchronization. */\nexport interface PromptTemplateSyncTarget extends PathCandidate {\n scope: \"user\";\n format: \"markdown\" | \"gemini-toml\";\n}\n\nexport interface StorageDescriptor {\n format: string;\n level: EvidenceLevel;\n note?: string;\n}\n\nexport interface HarnessCapabilities {\n mcp: boolean;\n vision: boolean;\n /** Audio reaches the model without conversion or MCP. */\n audio: boolean;\n /** Video reaches the model without conversion or MCP. */\n video: boolean;\n tools: boolean;\n streaming: boolean;\n}\n\n/** How to run one prompt through the harness non-interactively. */\nexport interface HarnessInvocation {\n /** Binary to spawn; defaults to the harness's first `binaries` entry. */\n binary?: string;\n /** Full agent argument template; every \"{prompt}\" is replaced with the prompt text. */\n args: string[];\n /** Structured full agent argument template. */\n jsonArgs?: string[];\n /** Advisor argument template without tools; absent when the CLI cannot disable tools. */\n noToolsArgs?: string[];\n /** Structured advisor argument template without tools. */\n noToolsJsonArgs?: string[];\n /** Agent argument template whose native sandbox enforces read-only tool access. */\n readOnlyArgs?: string[];\n /** Structured agent argument template with read-only tool access. */\n readOnlyJsonArgs?: string[];\n /** Lowest CLI version whose read-only enforcement was verified; older or unknown versions reject read-only runs. */\n readOnlyMinVersion?: string;\n /** Arguments appended when a model is selected; every \"{model}\" is replaced. */\n modelArgs?: string[];\n /**\n * Arguments appended to a plain text run so a CLI that holds its answer until\n * the end reports it as events instead; `invoke` folds them back into that text,\n * so a stopped run keeps what the model had already written.\n */\n streamArgs?: string[];\n level: EvidenceLevel;\n note?: string;\n}\n\n/** Invocation modes a harness supports without fallback or prompt-only restrictions. */\nexport interface HarnessInvocationModes {\n advisor: boolean;\n advisorStructured: boolean;\n readOnly: boolean;\n readOnlyStructured: boolean;\n agent: boolean;\n agentStructured: boolean;\n}\n\n/** How to ask one harness CLI for the models currently available to it. */\nexport interface HarnessModelListing {\n /** Arguments used when no search filter is supplied. */\n args: string[];\n /**\n * Optional argument template for a native search filter; every \"{search}\" is replaced.\n * Without it, a search runs `args` and keeps the ids containing the filter, ignoring case.\n */\n searchArgs?: string[];\n level: EvidenceLevel;\n note?: string;\n}\n\n/** One model normalized from a harness's native model-listing output. */\nexport interface AvailableModel {\n provider: string;\n id: string;\n /** Absent when the native listing prints only ids, like Grok's. */\n contextWindow?: number;\n maxOutputTokens?: number;\n thinking?: boolean;\n images?: boolean;\n /** Set on the model the harness picks when no model is given, when the listing marks one. */\n default?: boolean;\n}\n\n/** Options for querying the models available to one harness. */\nexport interface ListModelsOptions {\n search?: string;\n cwd?: string;\n env?: Record<string, string>;\n /** Milliseconds before cleanup starts. Unset or 0 disables the deadline. */\n timeoutMs?: number;\n /** Cancel with the same process cleanup as a timeout. */\n signal?: AbortSignal;\n}\n\nexport interface InvokeOptions {\n cwd?: string;\n env?: Record<string, string>;\n /** Harness-native model id or selector. */\n model?: string;\n /** Enable the spawned harness's tools; defaults to advisor without tools mode. */\n tools?: boolean;\n /** Require native enforcement of read-only tool access. Implies `tools: true` when `tools` is omitted; `tools: false` rejects the run. */\n readOnly?: boolean;\n /** Milliseconds before cleanup starts. Unset or 0 disables the deadline. */\n timeoutMs?: number;\n /** Cancel with the same process cleanup as a timeout. */\n signal?: AbortSignal;\n /** Use the harness's structured (JSON) output mode instead of plain text. */\n structured?: boolean;\n}\n\nexport interface InvokeResult {\n command: string;\n args: string[];\n stdout: string;\n stderr: string;\n /** Process exit code; null when terminated by a signal, timeout, or cancellation. */\n exitCode: number | null;\n timedOut: boolean;\n /** True when caller cancellation wins over the deadline or completion. */\n aborted: boolean;\n /** Milliseconds without output on either stream before a deadline or cancellation stopped the process. */\n idleMs?: number;\n}\n\n/** Result of one native model-listing command. */\nexport interface ListModelsResult extends InvokeResult {\n /** Empty on a successful no-match response or when the command itself failed. */\n models: AvailableModel[];\n}\n\n/** Normalized MCP server entry, shared across every harness dialect. */\nexport interface McpServerConfig {\n name: string;\n transport: \"stdio\" | \"http\" | \"sse\";\n command?: string;\n args?: string[];\n /**\n * Environment for stdio servers. A value that is exactly \"${NAME}\" refers to\n * the variable NAME of the harness environment: dialects with native\n * references keep it, the others resolve it when the entry is written.\n */\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n /** Present only when the harness tracks an on/off state per server. */\n enabled?: boolean;\n}\n\n/** How one harness config file stores its MCP servers. */\nexport interface McpConfigFile extends PathCandidate {\n format: \"json\" | \"toml\";\n /** Object path to the server map inside the file, e.g. [\"mcpServers\"]. */\n key: string[];\n /**\n * Shape of individual entries; \"standard\" is the {command, args, env, url}\n * family, \"prime\" is that family with env values as {\"env\": \"NAME\"} references\n * and \"mastracode\" is that family read by its keys alone, type ignored.\n */\n dialect: \"standard\" | \"antigravity\" | \"mastracode\" | \"opencode\" | \"prime\" | \"vscode\";\n}\n\nexport interface HarnessDetection {\n /** Environment variables that indicate running inside this agent. */\n envVars: string[];\n /** Project-level files or directories whose presence indicates this agent. */\n projectMarkers: string[];\n}\n\nexport interface ResolveOptions {\n homeDir?: string;\n projectRoot?: string;\n platform?: Platform;\n /** Replaces `os.tmpdir()` as the value of `${TMPDIR}`. */\n tempDir?: string;\n}\n\nexport interface ResolvedPaths {\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 roots, moved by a set `temp` override from {@link EnvOverride}. */\n temp: PathCandidate[];\n}\n"],"mappings":";;ACEA,MAAa,UAAkBA"}
1
+ {"version":3,"file":"types.mjs","names":["pkg.version"],"sources":["../../package.json","../../src/types.ts"],"sourcesContent":["","import pkg from \"../package.json\" with { type: \"json\" };\n\nexport const version: string = pkg.version;\n\nexport type HarnessId =\n | \"antigravity\"\n | \"codex\"\n | \"gemini\"\n | \"grok\"\n | \"claude\"\n | \"opencode\"\n | \"cursor\"\n | \"freebuff\"\n | \"github-copilot\"\n | \"mastracode\"\n | \"omp\"\n | \"pi\"\n | \"prime-agent\";\nexport type EvidenceLevel = \"official\" | \"community\" | \"inferred\";\nexport type Platform = \"linux\" | \"darwin\" | \"win32\";\n\nexport interface PathCandidate {\n path: string;\n scope: \"user\" | \"project\" | \"system\" | \"data\";\n level: EvidenceLevel;\n platforms?: Platform[];\n note?: string;\n}\n\n/** The path lists of a harness descriptor, as named in {@link ResolvedPaths}. */\nexport type PathCategory =\n | \"config\"\n | \"sessions\"\n | \"instructions\"\n | \"skills\"\n | \"commands\"\n | \"promptTemplates\"\n | \"hooks\"\n | \"temp\";\n\n/**\n * An environment variable the harness reads to move one of its roots. `path`\n * is the default root, used while the variable is unset or empty.\n */\nexport interface EnvOverride extends PathCandidate {\n variable: string;\n /** Categories with entries under this root, which move with it. */\n relocates: PathCategory[];\n}\n\n/** The user-scope skills directory that skill synchronization links to the source. */\nexport interface SkillsSyncTarget extends PathCandidate {\n scope: \"user\";\n}\n\n/** One stable user-scope destination used by prompt template synchronization. */\nexport interface PromptTemplateSyncTarget extends PathCandidate {\n scope: \"user\";\n format: \"markdown\" | \"gemini-toml\";\n}\n\nexport interface StorageDescriptor {\n format: string;\n level: EvidenceLevel;\n note?: string;\n}\n\nexport interface HarnessCapabilities {\n mcp: boolean;\n vision: boolean;\n /** Audio reaches the model without conversion or MCP. */\n audio: boolean;\n /** Video reaches the model without conversion or MCP. */\n video: boolean;\n tools: boolean;\n streaming: boolean;\n}\n\n/** How to run one prompt through the harness non-interactively. */\nexport interface HarnessInvocation {\n /** Binary to spawn; defaults to the harness's first `binaries` entry. */\n binary?: string;\n /** Full agent argument template; every \"{prompt}\" is replaced with the prompt text. */\n args: string[];\n /** Structured full agent argument template. */\n jsonArgs?: string[];\n /** Advisor argument template without tools; absent when the CLI cannot disable tools. */\n noToolsArgs?: string[];\n /** Structured advisor argument template without tools. */\n noToolsJsonArgs?: string[];\n /** Agent argument template whose native sandbox enforces read-only tool access. */\n readOnlyArgs?: string[];\n /** Structured agent argument template with read-only tool access. */\n readOnlyJsonArgs?: string[];\n /** Lowest CLI version whose read-only enforcement was verified; older or unknown versions reject read-only runs. */\n readOnlyMinVersion?: string;\n /** Arguments appended when a model is selected; every \"{model}\" is replaced. */\n modelArgs?: string[];\n /**\n * Arguments appended to a plain text run so a CLI that holds its answer until\n * the end reports it as events instead; `invoke` folds them back into that text,\n * so a stopped run keeps what the model had already written.\n */\n streamArgs?: string[];\n level: EvidenceLevel;\n note?: string;\n}\n\n/** Invocation modes a harness supports without fallback or prompt-only restrictions. */\nexport interface HarnessInvocationModes {\n advisor: boolean;\n advisorStructured: boolean;\n readOnly: boolean;\n readOnlyStructured: boolean;\n agent: boolean;\n agentStructured: boolean;\n}\n\n/** How to ask one harness CLI for the models currently available to it. */\nexport interface HarnessModelListing {\n /** Arguments used when no search filter is supplied. */\n args: string[];\n /**\n * Optional argument template for a native search filter; every \"{search}\" is replaced.\n * Without it, a search runs `args` and keeps the ids containing the filter, ignoring case.\n */\n searchArgs?: string[];\n level: EvidenceLevel;\n note?: string;\n}\n\n/** One model normalized from a harness's native model-listing output. */\nexport interface AvailableModel {\n provider: string;\n id: string;\n /** Absent when the native listing prints only ids, like Grok's. */\n contextWindow?: number;\n maxOutputTokens?: number;\n thinking?: boolean;\n images?: boolean;\n /** Set on the model the harness picks when no model is given, when the listing marks one. */\n default?: boolean;\n}\n\n/** Options for querying the models available to one harness. */\nexport interface ListModelsOptions {\n search?: string;\n cwd?: string;\n env?: Record<string, string>;\n /** Milliseconds before cleanup starts. Unset or 0 disables the deadline. */\n timeoutMs?: number;\n /** Cancel with the same process cleanup as a timeout. */\n signal?: AbortSignal;\n}\n\nexport interface InvokeOptions {\n cwd?: string;\n env?: Record<string, string>;\n /** Harness-native model id or selector. */\n model?: string;\n /** Enable the spawned harness's tools; defaults to advisor without tools mode. */\n tools?: boolean;\n /** Require native enforcement of read-only tool access. Implies `tools: true` when `tools` is omitted; `tools: false` rejects the run. */\n readOnly?: boolean;\n /** Milliseconds before cleanup starts. Unset or 0 disables the deadline. */\n timeoutMs?: number;\n /** Cancel with the same process cleanup as a timeout. */\n signal?: AbortSignal;\n /** Use the harness's structured (JSON) output mode instead of plain text. */\n structured?: boolean;\n}\n\nexport interface InvokeResult {\n command: string;\n args: string[];\n stdout: string;\n stderr: string;\n /** Process exit code; null when terminated by a signal, timeout, or cancellation. */\n exitCode: number | null;\n timedOut: boolean;\n /** True when caller cancellation wins over the deadline or completion. */\n aborted: boolean;\n /** Milliseconds without output on either stream before a deadline or cancellation stopped the process. */\n idleMs?: number;\n}\n\n/** Result of one native model-listing command. */\nexport interface ListModelsResult extends InvokeResult {\n /** Empty on a successful no-match response or when the command itself failed. */\n models: AvailableModel[];\n}\n\n/** Normalized MCP server entry, shared across every harness dialect. */\nexport interface McpServerConfig {\n name: string;\n transport: \"stdio\" | \"http\" | \"sse\";\n command?: string;\n args?: string[];\n /**\n * Environment for stdio servers. A value that is exactly \"${NAME}\" refers to\n * the variable NAME of the harness environment: dialects with native\n * references keep it, the others resolve it when the entry is written.\n */\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n /** Present only when the harness tracks an on/off state per server. */\n enabled?: boolean;\n}\n\n/** How one harness config file stores its MCP servers. */\nexport interface McpConfigFile extends PathCandidate {\n format: \"json\" | \"toml\";\n /** Object path to the server map inside the file, e.g. [\"mcpServers\"]. */\n key: string[];\n /**\n * Shape of individual entries; \"standard\" is the {command, args, env, url}\n * family, \"prime\" is that family with env values as {\"env\": \"NAME\"} references,\n * \"mastracode\" is that family read by its keys alone, type ignored, and \"pi\"\n * is that family without sse that keeps the entry fields it doesn't manage.\n */\n dialect: \"standard\" | \"antigravity\" | \"mastracode\" | \"opencode\" | \"pi\" | \"prime\" | \"vscode\";\n}\n\nexport interface HarnessDetection {\n /** Environment variables that indicate running inside this agent. */\n envVars: string[];\n /** Project-level files or directories whose presence indicates this agent. */\n projectMarkers: string[];\n}\n\nexport interface ResolveOptions {\n homeDir?: string;\n projectRoot?: string;\n platform?: Platform;\n /** Replaces `os.tmpdir()` as the value of `${TMPDIR}`. */\n tempDir?: string;\n}\n\nexport interface ResolvedPaths {\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 roots, moved by a set `temp` override from {@link EnvOverride}. */\n temp: PathCandidate[];\n}\n"],"mappings":";;ACEA,MAAa,UAAkBA"}
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as version } from "./_chunks/types.mjs";
3
- import { _ as getHarness, g as getAllHarnesses, v as isHarnessId, y as listHarnesses } from "./_chunks/skills-sync.mjs";
3
+ import { _ as getAllHarnesses, b as listHarnesses, v as getHarness, y as isHarnessId } from "./_chunks/skills-sync.mjs";
4
4
  import { o as listHarnessModels } from "./_chunks/tool-operations.mjs";
5
5
  import { t as exitOnClosedPipe } from "./_chunks/output.mjs";
6
6
  import { defineCommand, runMain } from "citty";
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as version, A as AvailableModel, B as InvokeResult, C as masterMcpPath, D as syncMcpServers, E as removeMcpServer, F as HarnessId, G as PathCandidate, H as ListModelsResult, I as HarnessInvocation, J as PromptTemplateSyncTarget, K as PathCategory, L as HarnessInvocationModes, M as EvidenceLevel, N as HarnessCapabilities, O as Harness, P as HarnessDetection, Q as StorageDescriptor, R as HarnessModelListing, S as listMcpServers, T as readMasterMcpServers, U as McpConfigFile, V as ListModelsOptions, W as McpServerConfig, X as ResolvedPaths, Y as ResolveOptions, Z as SkillsSyncTarget, _ as McpConfigListing, a as PromptSyncAction, b as SyncTargetResult, c as PromptTemplateTargetResult, d as AgentsConfig, f as AgentsSyncAction, g as syncAgentsFiles, h as readAgentsConfig, i as syncSkills, j as EnvOverride, k as HarnessConstructor, l as syncPromptTemplates, m as AgentsTargetResult, n as SkillsSyncReport, o as PromptSyncReport, p as AgentsSyncReport, q as Platform, r as SkillsSyncTargetResult, s as PromptSyncTargetResult, t as SkillsSyncAction, u as AgentsCompanionTargetResult, v as McpEnvError, w as parseJsonc, x as addMcpServer, y as SyncReport, z as InvokeOptions } from "./_chunks/skills-sync.mjs";
1
+ import { $ as StorageDescriptor, A as HarnessConstructor, B as InvokeOptions, C as listMcpServers, D as removeMcpServer, E as readMasterMcpServers, F as HarnessDetection, G as McpServerConfig, H as ListModelsOptions, I as HarnessId, J as Platform, K as PathCandidate, L as HarnessInvocation, M as EnvOverride, N as EvidenceLevel, O as syncMcpServers, P as HarnessCapabilities, Q as SkillsSyncTarget, R as HarnessInvocationModes, S as addMcpServer, T as parseJsonc, U as ListModelsResult, V as InvokeResult, W as McpConfigFile, X as ResolveOptions, Y as PromptTemplateSyncTarget, Z as ResolvedPaths, _ as McpConfigListing, a as PromptSyncAction, b as SyncReport, c as PromptTemplateTargetResult, d as AgentsConfig, et as version, f as AgentsSyncAction, g as syncAgentsFiles, h as readAgentsConfig, i as syncSkills, j as AvailableModel, k as Harness, l as syncPromptTemplates, m as AgentsTargetResult, n as SkillsSyncReport, o as PromptSyncReport, p as AgentsSyncReport, q as PathCategory, r as SkillsSyncTargetResult, s as PromptSyncTargetResult, t as SkillsSyncAction, u as AgentsCompanionTargetResult, v as McpEnvError, w as masterMcpPath, x as SyncTargetResult, y as McpTransportError, z as HarnessModelListing } from "./_chunks/skills-sync.mjs";
2
2
  //#region src/registry.d.ts
3
3
  export declare function registerHarness(HarnessClass: HarnessConstructor): Harness;
4
4
  export declare function getHarness(id: HarnessId): Harness;
@@ -324,5 +324,5 @@ interface OpenCodeProject {
324
324
  //#region src/index.d.ts
325
325
  export declare const harnessIds: readonly HarnessId[];
326
326
  //#endregion
327
- export { type AgentsCompanionTargetResult, type AgentsConfig, type AgentsSyncAction, type AgentsSyncReport, type AgentsTargetResult, type AvailableModel, type ClaudeAssistantEntry, type ClaudeBaseEntry, type ClaudeContentBlock, type ClaudeHistoryEntry, type ClaudeSessionEntry, type ClaudeSummaryEntry, type ClaudeTextBlock, type ClaudeThinkingBlock, type ClaudeToolResultBlock, type ClaudeToolUseBlock, type ClaudeUsage, type ClaudeUserEntry, type CodexHistoryEntry, type CodexLogEntry, type CodexThread, type EnvOverride, type EvidenceLevel, type GeminiConversationRecord, type GeminiMessageRecord, type GeminiThought, type GeminiTokensSummary, type GeminiToolCallRecord, Harness, type HarnessCapabilities, type HarnessConstructor, type HarnessDetection, type HarnessId, type HarnessInvocation, type HarnessInvocationModes, type HarnessModelListing, type InvokeOptions, type InvokeResult, type ListModelsOptions, type ListModelsResult, type McpConfigFile, type McpConfigListing, McpEnvError, type McpServerConfig, type OpenCodeAgentPart, type OpenCodeCompactionPart, type OpenCodeFilePart, type OpenCodeMessage, type OpenCodePart, type OpenCodePatchPart, type OpenCodeProject, type OpenCodeReasoningPart, type OpenCodeRetryPart, type OpenCodeSession, type OpenCodeSnapshotPart, type OpenCodeStepFinishPart, type OpenCodeStepStartPart, type OpenCodeSubtaskPart, type OpenCodeTextPart, type OpenCodeTodo, type OpenCodeToolPart, type PathCandidate, type PathCategory, type Platform, type PromptSyncAction, type PromptSyncReport, type PromptSyncTargetResult, type PromptTemplateSyncTarget, type PromptTemplateTargetResult, type ResolveOptions, type ResolvedPaths, type SkillsSyncAction, type SkillsSyncReport, type SkillsSyncTarget, type SkillsSyncTargetResult, type StorageDescriptor, type SyncReport, type SyncTargetResult, addMcpServer, listMcpServers, masterMcpPath, parseJsonc, readAgentsConfig, readMasterMcpServers, removeMcpServer, syncAgentsFiles, syncMcpServers, syncPromptTemplates, syncSkills, version };
327
+ export { type AgentsCompanionTargetResult, type AgentsConfig, type AgentsSyncAction, type AgentsSyncReport, type AgentsTargetResult, type AvailableModel, type ClaudeAssistantEntry, type ClaudeBaseEntry, type ClaudeContentBlock, type ClaudeHistoryEntry, type ClaudeSessionEntry, type ClaudeSummaryEntry, type ClaudeTextBlock, type ClaudeThinkingBlock, type ClaudeToolResultBlock, type ClaudeToolUseBlock, type ClaudeUsage, type ClaudeUserEntry, type CodexHistoryEntry, type CodexLogEntry, type CodexThread, type EnvOverride, type EvidenceLevel, type GeminiConversationRecord, type GeminiMessageRecord, type GeminiThought, type GeminiTokensSummary, type GeminiToolCallRecord, Harness, type HarnessCapabilities, type HarnessConstructor, type HarnessDetection, type HarnessId, type HarnessInvocation, type HarnessInvocationModes, type HarnessModelListing, type InvokeOptions, type InvokeResult, type ListModelsOptions, type ListModelsResult, type McpConfigFile, type McpConfigListing, McpEnvError, type McpServerConfig, McpTransportError, type OpenCodeAgentPart, type OpenCodeCompactionPart, type OpenCodeFilePart, type OpenCodeMessage, type OpenCodePart, type OpenCodePatchPart, type OpenCodeProject, type OpenCodeReasoningPart, type OpenCodeRetryPart, type OpenCodeSession, type OpenCodeSnapshotPart, type OpenCodeStepFinishPart, type OpenCodeStepStartPart, type OpenCodeSubtaskPart, type OpenCodeTextPart, type OpenCodeTodo, type OpenCodeToolPart, type PathCandidate, type PathCategory, type Platform, type PromptSyncAction, type PromptSyncReport, type PromptSyncTargetResult, type PromptTemplateSyncTarget, type PromptTemplateTargetResult, type ResolveOptions, type ResolvedPaths, type SkillsSyncAction, type SkillsSyncReport, type SkillsSyncTarget, type SkillsSyncTargetResult, type StorageDescriptor, type SyncReport, type SyncTargetResult, addMcpServer, listMcpServers, masterMcpPath, parseJsonc, readAgentsConfig, readMasterMcpServers, removeMcpServer, syncAgentsFiles, syncMcpServers, syncPromptTemplates, syncSkills, version };
328
328
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/registry.ts","../src/resolve.ts","../src/schemas/claude.ts","../src/schemas/gemini.ts","../src/schemas/codex.ts","../src/schemas/opencode.ts","../src/index.ts"],"mappings":";;wBAiBgB,gBAAgB,cAAc,qBAAqB;wBAMnD,WAAW,IAAI,YAAY;wBAM3B,iBAAiB;wBAIjB,YAAY,aAAa,MAAM;wBAI/B,mBAAmB;;;;;;;wBAUnB,wBAAwB;;;;;;;;wBAcxB,uBAAuB,eAAe;;;;;;;;;;wBAatC,cAAc,eAAe;;;wBChE7B,oBAAoB,kBAAkB,UAAS;;;;;;;wBAkB/C,eAAe,UAAS;;;;;;;wBAcxB,aAAa,UAAS;;;UC1CrB;EACf;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;KAGU,qBACR,kBACA,sBACA,qBACA;UAEa;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe,wBAAwB;EACvC;EACA;IACE;IACA,kBAAkB;;EAEpB;EACA;IACE;IACA;IACA;IACA;;;UAIa,6BAA6B;EAC5C;EACA;EACA;IACE;IACA;IACA;IACA;IACA,SAAS;IACT;IACA;IACA,OAAO;;;UAIM;EACf;EACA;EACA;;KAGU,qBAAqB,kBAAkB,uBAAuB;UAEzD;EACf;EACA;EACA;EACA;EACA,gBAAgB;IAGZ;IACA;IACA;;;;;UClGW;EACf;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA,MAAM;EACN;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,WAAW;EACX,YAAY;;UAGG;EACf;EACA;EACA;EACA;EACA,UAAU;EACV;EACA;EACA;;;;UC9Ce;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;;;UC7Be;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;KAGU,eACR,mBACA,wBACA,mBACA,mBACA,sBACA,wBACA,yBACA,uBACA,oBACA,oBACA,oBACA;UAEa;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;;;qBCtBW,qBAAqB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/registry.ts","../src/resolve.ts","../src/schemas/claude.ts","../src/schemas/gemini.ts","../src/schemas/codex.ts","../src/schemas/opencode.ts","../src/index.ts"],"mappings":";;wBAiBgB,gBAAgB,cAAc,qBAAqB;wBAMnD,WAAW,IAAI,YAAY;wBAM3B,iBAAiB;wBAIjB,YAAY,aAAa,MAAM;wBAI/B,mBAAmB;;;;;;;wBAUnB,wBAAwB;;;;;;;;wBAcxB,uBAAuB,eAAe;;;;;;;;;;wBAatC,cAAc,eAAe;;;wBChE7B,oBAAoB,kBAAkB,UAAS;;;;;;;wBAkB/C,eAAe,UAAS;;;;;;;wBAcxB,aAAa,UAAS;;;UC1CrB;EACf;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;KAGU,qBACR,kBACA,sBACA,qBACA;UAEa;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe,wBAAwB;EACvC;EACA;IACE;IACA,kBAAkB;;EAEpB;EACA;IACE;IACA;IACA;IACA;;;UAIa,6BAA6B;EAC5C;EACA;EACA;IACE;IACA;IACA;IACA;IACA,SAAS;IACT;IACA;IACA,OAAO;;;UAIM;EACf;EACA;EACA;;KAGU,qBAAqB,kBAAkB,uBAAuB;UAEzD;EACf;EACA;EACA;EACA;EACA,gBAAgB;IAGZ;IACA;IACA;;;;;UClGW;EACf;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA,MAAM;EACN;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,WAAW;EACX,YAAY;;UAGG;EACf;EACA;EACA;EACA;EACA,UAAU;EACV;EACA;EACA;;;;UC9Ce;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;;;UC7Be;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;KAGU,eACR,mBACA,wBACA,mBACA,mBACA,sBACA,wBACA,yBACA,uBACA,oBACA,oBACA,oBACA;UAEa;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;;;qBCrBW,qBAAqB"}
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { t as version } from "./_chunks/types.mjs";
2
- import { C as agntnDataDir, S as agntnConfigDir, _ as getHarness, a as McpEnvError, b as registerHarness, c as masterMcpPath, d as removeMcpServer, f as syncMcpServers, g as getAllHarnesses, h as detectProjectHarnesses, i as syncAgentsFiles, l as parseJsonc, m as detectHarnessFromEnv, n as syncPromptTemplates, o as addMcpServer, p as detectHarness, r as readAgentsConfig, s as listMcpServers, t as syncSkills, u as readMasterMcpServers, v as isHarnessId, w as resolvePathTemplate, x as Harness, y as listHarnesses } from "./_chunks/skills-sync.mjs";
2
+ import { C as agntnConfigDir, S as Harness, T as resolvePathTemplate, _ as getAllHarnesses, a as McpEnvError, b as listHarnesses, c as listMcpServers, d as readMasterMcpServers, f as removeMcpServer, g as detectProjectHarnesses, h as detectHarnessFromEnv, i as syncAgentsFiles, l as masterMcpPath, m as detectHarness, n as syncPromptTemplates, o as McpTransportError, p as syncMcpServers, r as readAgentsConfig, s as addMcpServer, t as syncSkills, u as parseJsonc, v as getHarness, w as agntnDataDir, x as registerHarness, y as isHarnessId } from "./_chunks/skills-sync.mjs";
3
3
  //#region src/index.ts
4
4
  const harnessIds = Object.freeze(listHarnesses());
5
5
  //#endregion
6
- export { Harness, McpEnvError, addMcpServer, agntnConfigDir, agntnDataDir, detectHarness, detectHarnessFromEnv, detectProjectHarnesses, getAllHarnesses, getHarness, harnessIds, isHarnessId, listHarnesses, listMcpServers, masterMcpPath, parseJsonc, readAgentsConfig, readMasterMcpServers, registerHarness, removeMcpServer, resolvePathTemplate, syncAgentsFiles, syncMcpServers, syncPromptTemplates, syncSkills, version };
6
+ export { Harness, McpEnvError, McpTransportError, addMcpServer, agntnConfigDir, agntnDataDir, detectHarness, detectHarnessFromEnv, detectProjectHarnesses, getAllHarnesses, getHarness, harnessIds, isHarnessId, listHarnesses, listMcpServers, masterMcpPath, parseJsonc, readAgentsConfig, readMasterMcpServers, registerHarness, removeMcpServer, resolvePathTemplate, syncAgentsFiles, syncMcpServers, syncPromptTemplates, syncSkills, version };
7
7
 
8
8
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["export { version } from \"./types.ts\";\nexport type {\n HarnessId,\n EvidenceLevel,\n Platform,\n PathCandidate,\n PathCategory,\n EnvOverride,\n PromptTemplateSyncTarget,\n SkillsSyncTarget,\n StorageDescriptor,\n HarnessCapabilities,\n HarnessDetection,\n HarnessInvocation,\n HarnessInvocationModes,\n HarnessModelListing,\n AvailableModel,\n ListModelsOptions,\n ListModelsResult,\n InvokeOptions,\n InvokeResult,\n McpServerConfig,\n McpConfigFile,\n ResolveOptions,\n ResolvedPaths,\n} from \"./types.ts\";\n\nexport { Harness } from \"./harness.ts\";\nexport type { HarnessConstructor } from \"./harness.ts\";\nexport {\n registerHarness,\n getHarness,\n isHarnessId,\n listHarnesses,\n getAllHarnesses,\n detectHarness,\n detectHarnessFromEnv,\n detectProjectHarnesses,\n} from \"./registry.ts\";\nexport { agntnDataDir, agntnConfigDir, resolvePathTemplate } from \"./resolve.ts\";\nexport {\n listMcpServers,\n addMcpServer,\n removeMcpServer,\n syncMcpServers,\n readMasterMcpServers,\n masterMcpPath,\n parseJsonc,\n McpEnvError,\n} from \"./mcp-servers.ts\";\nexport type { McpConfigListing, SyncReport, SyncTargetResult } from \"./mcp-servers.ts\";\nexport { syncAgentsFiles, readAgentsConfig } from \"./agents-sync.ts\";\nexport type {\n AgentsConfig,\n AgentsSyncAction,\n AgentsCompanionTargetResult,\n AgentsSyncReport,\n AgentsTargetResult,\n} from \"./agents-sync.ts\";\nexport { syncPromptTemplates } from \"./prompt-sync.ts\";\nexport type {\n PromptSyncAction,\n PromptSyncReport,\n PromptSyncTargetResult,\n PromptTemplateTargetResult,\n} from \"./prompt-sync.ts\";\nexport { syncSkills } from \"./skills-sync.ts\";\nexport type { SkillsSyncAction, SkillsSyncReport, SkillsSyncTargetResult } from \"./skills-sync.ts\";\n\nexport type {\n ClaudeContentBlock,\n ClaudeTextBlock,\n ClaudeThinkingBlock,\n ClaudeToolUseBlock,\n ClaudeToolResultBlock,\n ClaudeUsage,\n ClaudeBaseEntry,\n ClaudeUserEntry,\n ClaudeAssistantEntry,\n ClaudeSummaryEntry,\n ClaudeSessionEntry,\n ClaudeHistoryEntry,\n GeminiTokensSummary,\n GeminiToolCallRecord,\n GeminiThought,\n GeminiMessageRecord,\n GeminiConversationRecord,\n CodexHistoryEntry,\n CodexThread,\n CodexLogEntry,\n OpenCodeSession,\n OpenCodeMessage,\n OpenCodeTextPart,\n OpenCodeReasoningPart,\n OpenCodeToolPart,\n OpenCodeFilePart,\n OpenCodeSubtaskPart,\n OpenCodeStepStartPart,\n OpenCodeStepFinishPart,\n OpenCodeSnapshotPart,\n OpenCodePatchPart,\n OpenCodeAgentPart,\n OpenCodeRetryPart,\n OpenCodeCompactionPart,\n OpenCodePart,\n OpenCodeTodo,\n OpenCodeProject,\n} from \"./schemas/index.ts\";\n\nimport type { HarnessId } from \"./types.ts\";\nimport { listHarnesses } from \"./registry.ts\";\n\nexport const harnessIds: readonly HarnessId[] = Object.freeze(listHarnesses());\n"],"mappings":";;;AAgHA,MAAa,aAAmC,OAAO,OAAO,cAAc,CAAC"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["export { version } from \"./types.ts\";\nexport type {\n HarnessId,\n EvidenceLevel,\n Platform,\n PathCandidate,\n PathCategory,\n EnvOverride,\n PromptTemplateSyncTarget,\n SkillsSyncTarget,\n StorageDescriptor,\n HarnessCapabilities,\n HarnessDetection,\n HarnessInvocation,\n HarnessInvocationModes,\n HarnessModelListing,\n AvailableModel,\n ListModelsOptions,\n ListModelsResult,\n InvokeOptions,\n InvokeResult,\n McpServerConfig,\n McpConfigFile,\n ResolveOptions,\n ResolvedPaths,\n} from \"./types.ts\";\n\nexport { Harness } from \"./harness.ts\";\nexport type { HarnessConstructor } from \"./harness.ts\";\nexport {\n registerHarness,\n getHarness,\n isHarnessId,\n listHarnesses,\n getAllHarnesses,\n detectHarness,\n detectHarnessFromEnv,\n detectProjectHarnesses,\n} from \"./registry.ts\";\nexport { agntnDataDir, agntnConfigDir, resolvePathTemplate } from \"./resolve.ts\";\nexport {\n listMcpServers,\n addMcpServer,\n removeMcpServer,\n syncMcpServers,\n readMasterMcpServers,\n masterMcpPath,\n parseJsonc,\n McpEnvError,\n McpTransportError,\n} from \"./mcp-servers.ts\";\nexport type { McpConfigListing, SyncReport, SyncTargetResult } from \"./mcp-servers.ts\";\nexport { syncAgentsFiles, readAgentsConfig } from \"./agents-sync.ts\";\nexport type {\n AgentsConfig,\n AgentsSyncAction,\n AgentsCompanionTargetResult,\n AgentsSyncReport,\n AgentsTargetResult,\n} from \"./agents-sync.ts\";\nexport { syncPromptTemplates } from \"./prompt-sync.ts\";\nexport type {\n PromptSyncAction,\n PromptSyncReport,\n PromptSyncTargetResult,\n PromptTemplateTargetResult,\n} from \"./prompt-sync.ts\";\nexport { syncSkills } from \"./skills-sync.ts\";\nexport type { SkillsSyncAction, SkillsSyncReport, SkillsSyncTargetResult } from \"./skills-sync.ts\";\n\nexport type {\n ClaudeContentBlock,\n ClaudeTextBlock,\n ClaudeThinkingBlock,\n ClaudeToolUseBlock,\n ClaudeToolResultBlock,\n ClaudeUsage,\n ClaudeBaseEntry,\n ClaudeUserEntry,\n ClaudeAssistantEntry,\n ClaudeSummaryEntry,\n ClaudeSessionEntry,\n ClaudeHistoryEntry,\n GeminiTokensSummary,\n GeminiToolCallRecord,\n GeminiThought,\n GeminiMessageRecord,\n GeminiConversationRecord,\n CodexHistoryEntry,\n CodexThread,\n CodexLogEntry,\n OpenCodeSession,\n OpenCodeMessage,\n OpenCodeTextPart,\n OpenCodeReasoningPart,\n OpenCodeToolPart,\n OpenCodeFilePart,\n OpenCodeSubtaskPart,\n OpenCodeStepStartPart,\n OpenCodeStepFinishPart,\n OpenCodeSnapshotPart,\n OpenCodePatchPart,\n OpenCodeAgentPart,\n OpenCodeRetryPart,\n OpenCodeCompactionPart,\n OpenCodePart,\n OpenCodeTodo,\n OpenCodeProject,\n} from \"./schemas/index.ts\";\n\nimport type { HarnessId } from \"./types.ts\";\nimport { listHarnesses } from \"./registry.ts\";\n\nexport const harnessIds: readonly HarnessId[] = Object.freeze(listHarnesses());\n"],"mappings":";;;AAiHA,MAAa,aAAmC,OAAO,OAAO,cAAc,CAAC"}
@@ -1,4 +1,4 @@
1
- import { A as AvailableModel, F as HarnessId, G as PathCandidate, J as PromptTemplateSyncTarget, L as HarnessInvocationModes, N as HarnessCapabilities, P as HarnessDetection, Q as StorageDescriptor, W as McpServerConfig, X as ResolvedPaths, Z as SkillsSyncTarget, _ as McpConfigListing, j as EnvOverride, n as SkillsSyncReport, o as PromptSyncReport, p as AgentsSyncReport, y as SyncReport } from "./_chunks/skills-sync.mjs";
1
+ import { $ as StorageDescriptor, F as HarnessDetection, G as McpServerConfig, I as HarnessId, K as PathCandidate, M as EnvOverride, P as HarnessCapabilities, Q as SkillsSyncTarget, R as HarnessInvocationModes, Y as PromptTemplateSyncTarget, Z as ResolvedPaths, _ as McpConfigListing, b as SyncReport, j as AvailableModel, n as SkillsSyncReport, o as PromptSyncReport, p as AgentsSyncReport } from "./_chunks/skills-sync.mjs";
2
2
  import { n as HARNESS_INFO_MAX_ITEMS } from "./_chunks/tool-schemas.mjs";
3
3
  //#region src/tool-operations.d.ts
4
4
  /** Text for the model plus details for the harness, shared by every tool surface. */
@@ -1 +1 @@
1
- {"version":3,"file":"tool-operations.d.mts","names":[],"sources":["../src/tool-operations.ts"],"mappings":";;;;iBAiDiB,WAAW;EAC1B,SAAS;IAAQ;IAAc;;EAC/B,SAAS;;EAET;;;iBAIe;EACf,IAAI;EACJ;EACA;EACA;;;iBAIe;EACf,WAAW;;;iBAII;EACf,IAAI;EACJ;EACA;EACA,cAAc;EACd,iBAAiB;EACjB;EACA;EACA,QAAQ;EACR,UAAU;EACV,cAAc;EACd,QAAQ;EACR,kBAAkB;EAClB,UAAU;EACV,iBAAiB;EACjB,0BAA0B;EAC1B,OAAO;EACP,MAAM;EACN,cAAc;EACd,aAAa;EACb,WAAW;EACX,UAAU;;;iBAIK;EACf;EACA,OAAO;;;iBAIQ;EACf;;;YAIU,oBAAoB,kBAAkB;;YAGtC,qBAAqB,oBAAoB,sBAAsB;;qBAM9D;;qBAGA;;;;;;wBAoKG,mBAAmB,WAAW;;wBAyG9B,YAAY,aAAa,WAAW;;wBAEpC,YACd,yBACC,WAAW,sBAAsB;wBACpB,YAAY,oCAAoC,WAAW;;iBA2B1D;EACf;EACA;;EAEA;;EAEA,SAAS;;;iBAIM;EACf,IAAI;EACJ;EACA;EACA;EACA,QAAQ;EACR;EACA;EACA;;EAEA;EACA;;;;;;;;;wBAUoB,kBACpB,YACA,UAAS,gBACR,QAAQ,WAAW,gBAAgB;;iBAsDrB;EACf;;EAEA;;EAEA;;EAEA,SAAS;;EAET;;EAEA;;EAEA;;;iBAIe;EACf,IAAI;EACJ;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;;;iBAIe;EACf;EACA,QAAQ;;EAER,kBAAkB;;EAElB;IAAU;IAAmB;;IAAsB;;;;;;;;;;;;;;;;;wBAyB/B,WACpB,YACA,gBACA,UAAS,aACR,QAAQ,WAAW,aAAa;;iBAkClB;EACf,WAAW;IAAQ,IAAI;IAAW,SAAS;;;;iBAY5B;EACf,IAAI;EACJ;EACA;;;iBAIe;EACf;EACA,YAAY;EACZ;EACA;EACA,MAAM;EACN;EACA,UAAU;;;;;;;;wBASI,kBAAkB,QAAQ,kBAAkB;;;;;;;wBAmB5C,QAAQ,cAAc,WAAW,aAAa;;;;;;;;;wBAgD9C,OACd,YACA,QAAQ,iBACR,6BACC,WAAW,cAAc;;;;;;;;;wBAeZ,UACd,YACA,cACA,6BACC,WAAW,cAAc;;;;;;;wBAaZ,QAAQ,cAAc,WAAW,aAAa;;;;;;;;wBA+B9C,WAAW,aAAa,kBAAgB,WAAW,mBAAmB;;;;;;;;wBAgCtE,YAAY,aAAa,kBAAgB,WAAW,mBAAmB;;;;;;;;wBAsBvE,WAAW,aAAa,kBAAgB,WAAW,mBAAmB"}
1
+ {"version":3,"file":"tool-operations.d.mts","names":[],"sources":["../src/tool-operations.ts"],"mappings":";;;;iBAiDiB,WAAW;EAC1B,SAAS;IAAQ;IAAc;;EAC/B,SAAS;;EAET;;;iBAIe;EACf,IAAI;EACJ;EACA;EACA;;;iBAIe;EACf,WAAW;;;iBAII;EACf,IAAI;EACJ;EACA;EACA,cAAc;EACd,iBAAiB;EACjB;EACA;EACA,QAAQ;EACR,UAAU;EACV,cAAc;EACd,QAAQ;EACR,kBAAkB;EAClB,UAAU;EACV,iBAAiB;EACjB,0BAA0B;EAC1B,OAAO;EACP,MAAM;EACN,cAAc;EACd,aAAa;EACb,WAAW;EACX,UAAU;;;iBAIK;EACf;EACA,OAAO;;;iBAIQ;EACf;;;YAIU,oBAAoB,kBAAkB;;YAGtC,qBAAqB,oBAAoB,sBAAsB;;qBAM9D;;qBAGA;;;;;;wBA2KG,mBAAmB,WAAW;;wBAyG9B,YAAY,aAAa,WAAW;;wBAEpC,YACd,yBACC,WAAW,sBAAsB;wBACpB,YAAY,oCAAoC,WAAW;;iBA2B1D;EACf;EACA;;EAEA;;EAEA,SAAS;;;iBAIM;EACf,IAAI;EACJ;EACA;EACA;EACA,QAAQ;EACR;EACA;EACA;;EAEA;EACA;;;;;;;;;wBAUoB,kBACpB,YACA,UAAS,gBACR,QAAQ,WAAW,gBAAgB;;iBAqDrB;EACf;;EAEA;;EAEA;;EAEA,SAAS;;EAET;;EAEA;;EAEA;;;iBAIe;EACf,IAAI;EACJ;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;;;iBAIe;EACf;EACA,QAAQ;;EAER,kBAAkB;;EAElB;IAAU;IAAmB;;IAAsB;;;;;;;;;;;;;;;;;wBAyB/B,WACpB,YACA,gBACA,UAAS,aACR,QAAQ,WAAW,aAAa;;iBAkClB;EACf,WAAW;IAAQ,IAAI;IAAW,SAAS;;;;iBAY5B;EACf,IAAI;EACJ;EACA;;;iBAIe;EACf;EACA,YAAY;EACZ;EACA;EACA,MAAM;EACN;EACA,UAAU;;;;;;;;wBASI,kBAAkB,QAAQ,kBAAkB;;;;;;;wBAmB5C,QAAQ,cAAc,WAAW,aAAa;;;;;;;;;wBAgD9C,OACd,YACA,QAAQ,iBACR,6BACC,WAAW,cAAc;;;;;;;;;wBAeZ,UACd,YACA,cACA,6BACC,WAAW,cAAc;;;;;;;wBAaZ,QAAQ,cAAc,WAAW,aAAa;;;;;;;;wBA+B9C,WAAW,aAAa,kBAAgB,WAAW,mBAAmB;;;;;;;;wBAgCtE,YAAY,aAAa,kBAAgB,WAAW,mBAAmB;;;;;;;;wBAsBvE,WAAW,aAAa,kBAAgB,WAAW,mBAAmB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agntn/harnesses",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Metadata registry for AI coding harnesses: binaries, configs, sessions, and capabilities.",
5
5
  "homepage": "https://harnesses.agntn.dev",
6
6
  "bugs": "https://github.com/agntn/harnesses/issues",
@@ -79,7 +79,7 @@
79
79
  }
80
80
  },
81
81
  "engines": {
82
- "node": ">=24"
82
+ "node": ">=26"
83
83
  },
84
84
  "omp": {
85
85
  "extensions": [
@@ -72,8 +72,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
72
72
  approval: HARNESS_TOOL_APPROVALS.harnesses_detect,
73
73
  async execute(_toolCallId, _params): Promise<AgentToolResult<HarnessTools.HarnessListing>> {
74
74
  const { detectHarnesses } = await loadToolOperations();
75
- const { content, details } = detectHarnesses();
76
- return { content, details };
75
+ return detectHarnesses();
77
76
  },
78
77
  ...statusRenderers("harnesses_detect"),
79
78
  });
@@ -90,8 +89,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
90
89
  params: HarnessSchemas.InfoParams,
91
90
  ): Promise<AgentToolResult<HarnessTools.HarnessInfoDetails>> {
92
91
  const { harnessInfo } = await loadToolOperations();
93
- const { content, details } = harnessInfo(params.id);
94
- return { content, details };
92
+ return harnessInfo(params.id);
95
93
  },
96
94
  ...statusRenderers("harnesses_info"),
97
95
  });
@@ -109,24 +107,12 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
109
107
  signal,
110
108
  ): Promise<AgentToolResult<HarnessTools.ModelsOutcome | HarnessTools.RunFailure>> {
111
109
  const { listHarnessModels } = await loadToolOperations();
112
- const { content, details, isError } = await listHarnessModels(params.id, {
110
+ return listHarnessModels(params.id, {
113
111
  search: params.search,
114
112
  cwd: params.cwd,
115
113
  timeoutSeconds: params.timeoutSeconds,
116
114
  signal,
117
115
  });
118
- if (isError) {
119
- const message =
120
- "error" in details
121
- ? details.error
122
- : details.aborted
123
- ? `Harness ${details.id} model listing aborted`
124
- : details.timedOut
125
- ? `Harness ${details.id} model listing timed out`
126
- : details.stderr || `Harness ${details.id} exited with code ${details.exitCode}`;
127
- throw new Error(message);
128
- }
129
- return { content, details };
130
116
  },
131
117
  ...statusRenderers("harnesses_models"),
132
118
  });
@@ -144,7 +130,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
144
130
  signal,
145
131
  ): Promise<AgentToolResult<HarnessTools.RunOutcome | HarnessTools.RunFailure>> {
146
132
  const { runHarness } = await loadToolOperations();
147
- const { content, details, isError } = await runHarness(params.id, params.prompt, {
133
+ return runHarness(params.id, params.prompt, {
148
134
  cwd: params.cwd,
149
135
  model: params.model,
150
136
  timeoutSeconds: params.timeoutSeconds,
@@ -153,16 +139,6 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
153
139
  tools: params.tools,
154
140
  readOnly: params.readOnly,
155
141
  });
156
- if (isError) {
157
- if ("error" in details) throw new Error(details.error);
158
- const message =
159
- content[0]?.text ??
160
- (details.timedOut
161
- ? `Harness ${details.id} timed out`
162
- : details.stderr || `Harness ${details.id} exited with code ${details.exitCode}`);
163
- throw new Error(message);
164
- }
165
- return { content, details };
166
142
  },
167
143
  ...statusRenderers("harnesses_run"),
168
144
  });
@@ -179,8 +155,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
179
155
  params: HarnessSchemas.McpListParams,
180
156
  ): Promise<AgentToolResult<HarnessTools.McpListing | HarnessTools.UnknownHarness>> {
181
157
  const { mcpList } = await loadToolOperations();
182
- const { content, details } = mcpList(params.id);
183
- return { content, details };
158
+ return mcpList(params.id);
184
159
  },
185
160
  ...statusRenderers("harnesses_mcp_list"),
186
161
  });
@@ -197,8 +172,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
197
172
  params: HarnessSchemas.McpAddParams,
198
173
  ): Promise<AgentToolResult<HarnessTools.McpMutation | HarnessTools.RunFailure>> {
199
174
  const { mcpAdd } = await loadToolOperations();
200
- const { content, details } = mcpAdd(params.id, params, params.scope ?? "user");
201
- return { content, details };
175
+ return mcpAdd(params.id, params, params.scope ?? "user");
202
176
  },
203
177
  ...statusRenderers("harnesses_mcp_add"),
204
178
  });
@@ -215,8 +189,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
215
189
  params: HarnessSchemas.McpSyncParams,
216
190
  ): Promise<AgentToolResult<HarnessTools.SyncReport | HarnessTools.RunFailure>> {
217
191
  const { mcpSync } = await loadToolOperations();
218
- const { content, details } = mcpSync(params.id);
219
- return { content, details };
192
+ return mcpSync(params.id);
220
193
  },
221
194
  ...statusRenderers("harnesses_mcp_sync"),
222
195
  });
@@ -233,8 +206,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
233
206
  params: HarnessSchemas.AgentsSyncParams,
234
207
  ): Promise<AgentToolResult<HarnessTools.AgentsSyncReport | HarnessTools.RunFailure>> {
235
208
  const { agentsSync } = await loadToolOperations();
236
- const { content, details } = agentsSync(params.id, params.check === true);
237
- return { content, details };
209
+ return agentsSync(params.id, params.check === true);
238
210
  },
239
211
  ...statusRenderers("harnesses_agents_sync"),
240
212
  });
@@ -251,8 +223,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
251
223
  params: Readonly<HarnessSchemas.PromptsSyncParams>,
252
224
  ): Promise<AgentToolResult<HarnessTools.PromptSyncReport | HarnessTools.RunFailure>> {
253
225
  const { promptsSync } = await loadToolOperations();
254
- const { content, details, isError } = promptsSync(params.id, params.check === true);
255
- return { content, details, isError };
226
+ return promptsSync(params.id, params.check === true);
256
227
  },
257
228
  ...statusRenderers("harnesses_prompts_sync"),
258
229
  });
@@ -269,8 +240,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
269
240
  params: Readonly<HarnessSchemas.SkillsSyncParams>,
270
241
  ): Promise<AgentToolResult<HarnessTools.SkillsSyncReport | HarnessTools.RunFailure>> {
271
242
  const { skillsSync } = await loadToolOperations();
272
- const { content, details, isError } = skillsSync(params.id, params.check === true);
273
- return { content, details, isError };
243
+ return skillsSync(params.id, params.check === true);
274
244
  },
275
245
  ...statusRenderers("harnesses_skills_sync"),
276
246
  });
@@ -287,8 +257,7 @@ export default function harnessesExtension(pi: ExtensionAPI): void {
287
257
  params: HarnessSchemas.McpRemoveParams,
288
258
  ): Promise<AgentToolResult<HarnessTools.McpMutation | HarnessTools.RunFailure>> {
289
259
  const { mcpRemove } = await loadToolOperations();
290
- const { content, details } = mcpRemove(params.id, params.name, params.scope ?? "user");
291
- return { content, details };
260
+ return mcpRemove(params.id, params.name, params.scope ?? "user");
292
261
  },
293
262
  ...statusRenderers("harnesses_mcp_remove"),
294
263
  });