@ken-jo/agent-connector 0.5.0 → 0.6.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.
Files changed (116) hide show
  1. package/README.md +3 -3
  2. package/dist/{action-LEYTHNIU.js → action-EKK6FMPY.js} +8 -8
  3. package/dist/{audit-HPKCUCES.js → audit-H7PQWIVH.js} +5 -5
  4. package/dist/{chunk-BXPSDNIB.js → chunk-34RRWEWU.js} +2 -2
  5. package/dist/{chunk-SFY6YLVK.js → chunk-4YOYR3T5.js} +5 -6
  6. package/dist/{chunk-SFY6YLVK.js.map → chunk-4YOYR3T5.js.map} +1 -1
  7. package/dist/{chunk-6WN37NVN.js → chunk-6FRAVOVF.js} +2 -2
  8. package/dist/{chunk-2Y2MZRLP.js → chunk-CWUPIT72.js} +2 -2
  9. package/dist/{chunk-6XMV2OOA.js → chunk-CZOXXS77.js} +3 -3
  10. package/dist/{chunk-IRUYJD23.js → chunk-IVJUPNLD.js} +2 -8
  11. package/dist/chunk-IVJUPNLD.js.map +1 -0
  12. package/dist/{chunk-FKW5A6HE.js → chunk-IY3SSCNK.js} +4 -4
  13. package/dist/{chunk-U2XJWG7N.js → chunk-JUBEM3OR.js} +2 -2
  14. package/dist/{chunk-UM5S7DKK.js → chunk-KOFCNA5T.js} +11 -2
  15. package/dist/{chunk-UM5S7DKK.js.map → chunk-KOFCNA5T.js.map} +1 -1
  16. package/dist/{chunk-4KIXXJ7B.js → chunk-KY2VQGD7.js} +2 -2
  17. package/dist/{chunk-M6OS4OLU.js → chunk-R4FABNAL.js} +2 -2
  18. package/dist/{chunk-T5AI3AW3.js → chunk-SA6CSOH5.js} +19 -19
  19. package/dist/{chunk-G5HAIYRM.js → chunk-XJSVJD5T.js} +37 -29
  20. package/dist/chunk-XJSVJD5T.js.map +1 -0
  21. package/dist/{chunk-WZMSSIDN.js → chunk-XSR3GF55.js} +14 -6
  22. package/dist/chunk-XSR3GF55.js.map +1 -0
  23. package/dist/{claude-code-LJ6DVXWQ.js → claude-code-VEERATN5.js} +4 -4
  24. package/dist/cli/sdk.js +4 -4
  25. package/dist/cli.js +1 -1
  26. package/dist/{cline-JAPJNOZQ.js → cline-UW6WCQRK.js} +2 -2
  27. package/dist/cline-UW6WCQRK.js.map +1 -0
  28. package/dist/{codebuff-3VODFPD4.js → codebuff-R7QBLCSJ.js} +11 -11
  29. package/dist/codebuff-R7QBLCSJ.js.map +1 -0
  30. package/dist/{codex-RXIS5BHM.js → codex-S2RADR5K.js} +2 -2
  31. package/dist/{crush-YB3SK6NK.js → crush-AJNQRFVE.js} +2 -2
  32. package/dist/{define-connector-odRHEC4H.d.ts → define-connector-iosc34CA.d.ts} +1 -1
  33. package/dist/{detect-USP5JMWM.js → detect-ZC344YOJ.js} +4 -4
  34. package/dist/{doctor-VSW5KHBM.js → doctor-ABYQF2YX.js} +13 -13
  35. package/dist/{goose-3X7ID7YW.js → goose-SXFRT7UF.js} +2 -2
  36. package/dist/grok-build-EP2ZUFXZ.js +682 -0
  37. package/dist/grok-build-EP2ZUFXZ.js.map +1 -0
  38. package/dist/{grok-cli-4VFVF2CQ.js → grok-cli-UUNPOUYY.js} +4 -3
  39. package/dist/grok-cli-UUNPOUYY.js.map +1 -0
  40. package/dist/{hook-QRW3ON6C.js → hook-M3KQSEO3.js} +8 -8
  41. package/dist/index.d.ts +3 -3
  42. package/dist/index.js +2 -2
  43. package/dist/{install-ASTAUZKB.js → install-4X4JDKGY.js} +10 -10
  44. package/dist/{introspect-gTx6GzpW.d.ts → introspect-z3eKVWHN.d.ts} +1 -1
  45. package/dist/{kilo-SW7BH6EG.js → kilo-FVBFSS4Y.js} +1 -1
  46. package/dist/kilo-FVBFSS4Y.js.map +1 -0
  47. package/dist/{kilo-T4OXNUYY.js → kilo-N5T6KXAG.js} +2 -2
  48. package/dist/{kilo-cli-I2S3W245.js → kilo-cli-JOAEWYI4.js} +2 -2
  49. package/dist/{leaderboard-3XSVSGAJ.js → leaderboard-Q4YZ3LI7.js} +3 -3
  50. package/dist/{mux-BO2L5CTW.js → mux-WSZWWZOX.js} +27 -21
  51. package/dist/mux-WSZWWZOX.js.map +1 -0
  52. package/dist/{package-VWBPHCLA.js → package-FY2QZWRM.js} +6 -6
  53. package/dist/runtime/index.d.ts +1 -1
  54. package/dist/runtime/index.js +6 -6
  55. package/dist/sdk/index.d.ts +4 -4
  56. package/dist/sdk/index.js +3 -3
  57. package/dist/sdk/test.d.ts +2 -2
  58. package/dist/sdk/test.js +6 -6
  59. package/dist/{serve-IQGHE4SJ.js → serve-XT76DWUN.js} +8 -8
  60. package/dist/{status-BVLY6XDL.js → status-DHVWBRLI.js} +8 -8
  61. package/dist/{statusline-PRODZV2J.js → statusline-SY5UBQOJ.js} +7 -7
  62. package/dist/{telemetry-UU4SHJ23.js → telemetry-TJIFAKWX.js} +5 -5
  63. package/dist/{types-DWXnnx-N.d.ts → types-CAKApZpX.d.ts} +4 -4
  64. package/dist/{uninstall-WI5YLDCT.js → uninstall-VQO36IQ4.js} +10 -10
  65. package/dist/{upgrade-L45BTG6X.js → upgrade-QEYZOA7S.js} +10 -10
  66. package/dist/{usage-K3NQTAJP.js → usage-LV7UGO64.js} +3 -3
  67. package/dist/{usage-event-J5CQ6LNT.js → usage-event-MQMKMK2R.js} +7 -7
  68. package/dist/{windsurf-R6D2JUTN.js → windsurf-ZWVFNJ73.js} +1 -1
  69. package/dist/windsurf-ZWVFNJ73.js.map +1 -0
  70. package/dist/{zed-DQV3ZUCU.js → zed-JCOKXOLA.js} +2 -2
  71. package/package.json +1 -1
  72. package/dist/chunk-G5HAIYRM.js.map +0 -1
  73. package/dist/chunk-IRUYJD23.js.map +0 -1
  74. package/dist/chunk-WZMSSIDN.js.map +0 -1
  75. package/dist/cline-JAPJNOZQ.js.map +0 -1
  76. package/dist/codebuff-3VODFPD4.js.map +0 -1
  77. package/dist/grok-cli-4VFVF2CQ.js.map +0 -1
  78. package/dist/kilo-SW7BH6EG.js.map +0 -1
  79. package/dist/mux-BO2L5CTW.js.map +0 -1
  80. package/dist/roo-code-SUWI4BBN.js +0 -229
  81. package/dist/roo-code-SUWI4BBN.js.map +0 -1
  82. package/dist/roo-code-VI2ZKTZC.js +0 -361
  83. package/dist/roo-code-VI2ZKTZC.js.map +0 -1
  84. package/dist/windsurf-R6D2JUTN.js.map +0 -1
  85. /package/dist/{action-LEYTHNIU.js.map → action-EKK6FMPY.js.map} +0 -0
  86. /package/dist/{audit-HPKCUCES.js.map → audit-H7PQWIVH.js.map} +0 -0
  87. /package/dist/{chunk-BXPSDNIB.js.map → chunk-34RRWEWU.js.map} +0 -0
  88. /package/dist/{chunk-6WN37NVN.js.map → chunk-6FRAVOVF.js.map} +0 -0
  89. /package/dist/{chunk-2Y2MZRLP.js.map → chunk-CWUPIT72.js.map} +0 -0
  90. /package/dist/{chunk-6XMV2OOA.js.map → chunk-CZOXXS77.js.map} +0 -0
  91. /package/dist/{chunk-FKW5A6HE.js.map → chunk-IY3SSCNK.js.map} +0 -0
  92. /package/dist/{chunk-U2XJWG7N.js.map → chunk-JUBEM3OR.js.map} +0 -0
  93. /package/dist/{chunk-4KIXXJ7B.js.map → chunk-KY2VQGD7.js.map} +0 -0
  94. /package/dist/{chunk-M6OS4OLU.js.map → chunk-R4FABNAL.js.map} +0 -0
  95. /package/dist/{chunk-T5AI3AW3.js.map → chunk-SA6CSOH5.js.map} +0 -0
  96. /package/dist/{claude-code-LJ6DVXWQ.js.map → claude-code-VEERATN5.js.map} +0 -0
  97. /package/dist/{codex-RXIS5BHM.js.map → codex-S2RADR5K.js.map} +0 -0
  98. /package/dist/{crush-YB3SK6NK.js.map → crush-AJNQRFVE.js.map} +0 -0
  99. /package/dist/{detect-USP5JMWM.js.map → detect-ZC344YOJ.js.map} +0 -0
  100. /package/dist/{doctor-VSW5KHBM.js.map → doctor-ABYQF2YX.js.map} +0 -0
  101. /package/dist/{goose-3X7ID7YW.js.map → goose-SXFRT7UF.js.map} +0 -0
  102. /package/dist/{hook-QRW3ON6C.js.map → hook-M3KQSEO3.js.map} +0 -0
  103. /package/dist/{install-ASTAUZKB.js.map → install-4X4JDKGY.js.map} +0 -0
  104. /package/dist/{kilo-T4OXNUYY.js.map → kilo-N5T6KXAG.js.map} +0 -0
  105. /package/dist/{kilo-cli-I2S3W245.js.map → kilo-cli-JOAEWYI4.js.map} +0 -0
  106. /package/dist/{leaderboard-3XSVSGAJ.js.map → leaderboard-Q4YZ3LI7.js.map} +0 -0
  107. /package/dist/{package-VWBPHCLA.js.map → package-FY2QZWRM.js.map} +0 -0
  108. /package/dist/{serve-IQGHE4SJ.js.map → serve-XT76DWUN.js.map} +0 -0
  109. /package/dist/{status-BVLY6XDL.js.map → status-DHVWBRLI.js.map} +0 -0
  110. /package/dist/{statusline-PRODZV2J.js.map → statusline-SY5UBQOJ.js.map} +0 -0
  111. /package/dist/{telemetry-UU4SHJ23.js.map → telemetry-TJIFAKWX.js.map} +0 -0
  112. /package/dist/{uninstall-WI5YLDCT.js.map → uninstall-VQO36IQ4.js.map} +0 -0
  113. /package/dist/{upgrade-L45BTG6X.js.map → upgrade-QEYZOA7S.js.map} +0 -0
  114. /package/dist/{usage-K3NQTAJP.js.map → usage-LV7UGO64.js.map} +0 -0
  115. /package/dist/{usage-event-J5CQ6LNT.js.map → usage-event-MQMKMK2R.js.map} +0 -0
  116. /package/dist/{zed-DQV3ZUCU.js.map → zed-JCOKXOLA.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/usage/readers/roo-code.ts"],"sourcesContent":["/**\n * usage/readers/roo-code — Roo Code (VS Code extension) task-log reader.\n *\n * Faithful port of tokscale sessions/roocode.rs (parse_roo_kilo_file, source\n * \"roocode\"). Roo Code (rooveterinaryinc.roo-cline) is a Cline-fork VS Code\n * extension that persists per-task logs under its VS Code globalStorage:\n * <vscodeUserDir>/globalStorage/rooveterinaryinc.roo-cline/tasks/<taskId>/\n * ui_messages.json (the UI message stream — token source)\n * api_conversation_history.json (sibling — model/agent source)\n *\n * roo-code is NOT in paths.ts hostRoots (the framework's per-platform table\n * targets CLIs with ~/.<tool> roots, not VS Code extension globalStorage), so\n * this reader resolves the cross-OS VS Code \"User\" dir itself, mirroring the\n * roo-code platform adapter (adapters/roo-code/index.ts vscodeUserDir):\n * - macOS → ~/Library/Application Support/Code/User\n * - Windows → %APPDATA%/Code/User (else ~/AppData/Roaming/Code/User)\n * - Linux → ~/.config/Code/User\n * An AGENT_CONNECTOR_ROO_CODE_DIR override (verbatim, non-empty, ~-expanded)\n * points directly at a `tasks` parent when set, matching the env convention in\n * paths.ts hostRoots.\n *\n * Tokens (ui_messages.json): the file is a JSON ARRAY of entries; only entries\n * with type==\"say\" AND say==\"api_req_started\" carry usage. Each such entry's\n * `text` field is a JSON-in-string payload:\n * tokensIn → input\n * tokensOut → output\n * cacheReads → cacheRead\n * cacheWrites → cacheWrite\n * cost (f64) → cost\n * apiProtocol → providerId (preserved verbatim, e.g. \"bedrock/anthropic\")\n * reasoning is ALWAYS 0 (Roo Code does not report it). A malformed text payload,\n * a missing text, or an unparseable `ts` skips just that entry.\n *\n * model / agent (api_conversation_history.json): scan every\n * <environment_details>…</environment_details> block for <model>, <slug>, <name>\n * tags; the LAST <model> wins (default \"unknown\"); agent prefers <slug> then\n * <name> (optional). When the sibling file is absent/unreadable: model \"unknown\",\n * no agent — exactly the Rust read_task_metadata fallback.\n *\n * session id is the taskId — the parent directory name of ui_messages.json\n * (port of extract_session_id), defaulting to \"unknown\". provider from\n * apiProtocol (trimmed, default \"unknown\"). No project attribution (Roo Code's\n * logs carry no cwd). No dedup — one row per api_req_started event. Confidence is\n * \"host-reported\".\n *\n * Fail-open: no root → []; unreadable/malformed file, entry, or payload → skipped\n * (never throws). Read-only.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { homedir, platform as osPlatform } from \"node:os\";\nimport { basename, dirname, isAbsolute, join, resolve } from \"node:path\";\n\nimport type { UsageReader, UsageRecord } from \"../types.js\";\nimport { emptyTokens } from \"../aggregate.js\";\nimport { readJsonFile } from \"../jsonl.js\";\nimport { expandHome, walkFiles } from \"../paths.js\";\n\nconst PLATFORM_ID = \"roo-code\" as const;\nconst DEFAULT_MODEL = \"unknown\";\nconst DEFAULT_PROVIDER = \"unknown\";\nconst DEFAULT_SESSION = \"unknown\";\n\n/** Roo Code extension id → its VS Code globalStorage folder. */\nconst ROO_EXTENSION_ID = \"rooveterinaryinc.roo-cline\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Storage-root resolution (mirrors adapters/roo-code vscodeUserDir + the\n// AGENT_CONNECTOR_<PLATFORM>_DIR env convention in paths.ts hostRoots)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Resolve the cross-OS VS Code per-user \"User\" dir (the globalStorage parent). */\nfunction vscodeUserDir(): string {\n const home = homedir();\n switch (osPlatform()) {\n case \"darwin\":\n return join(home, \"Library\", \"Application Support\", \"Code\", \"User\");\n case \"win32\": {\n const appData = process.env.APPDATA ?? join(home, \"AppData\", \"Roaming\");\n return join(appData, \"Code\", \"User\");\n }\n default:\n return join(home, \".config\", \"Code\", \"User\");\n }\n}\n\n/**\n * The `tasks` root holding per-task subdirectories. Honors an\n * AGENT_CONNECTOR_ROO_CODE_DIR override (verbatim, non-empty, ~-expanded,\n * resolved against CWD when relative), else the extension's globalStorage tasks\n * dir under the resolved VS Code user dir.\n */\nfunction tasksRoot(): string {\n const raw = process.env.AGENT_CONNECTOR_ROO_CODE_DIR;\n if (raw != null && raw.trim() !== \"\") {\n const expanded = expandHome(raw.trim());\n return isAbsolute(expanded) ? expanded : resolve(expanded);\n }\n return join(vscodeUserDir(), \"globalStorage\", ROO_EXTENSION_ID, \"tasks\");\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Value coercion (ports of utils.rs extract_i64 / extract_f64 / parse_timestamp_str)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Port of extract_i64: number / numeric-string → integer, else undefined. */\nfunction extractI64(v: unknown): number | undefined {\n if (typeof v === \"number\") {\n if (!Number.isFinite(v)) return undefined;\n return Math.trunc(v);\n }\n if (typeof v === \"string\") {\n const trimmed = v.trim();\n if (!/^[+-]?\\d+$/.test(trimmed)) return undefined; // Rust parses as i64 (integer-only)\n const n = Number(trimmed);\n return Number.isFinite(n) ? Math.trunc(n) : undefined;\n }\n return undefined;\n}\n\n/** A non-negative integer from a payload field (0 on absence/garbage, clamped ≥ 0). */\nfunction tokenField(v: unknown): number {\n const n = extractI64(v);\n return n === undefined ? 0 : Math.max(0, n);\n}\n\n/** Port of extract_f64: number / numeric-string → f64, else undefined. */\nfunction extractF64(v: unknown): number | undefined {\n if (typeof v === \"number\") return Number.isFinite(v) ? v : undefined;\n if (typeof v === \"string\") {\n const n = Number(v.trim());\n return Number.isFinite(n) ? n : undefined;\n }\n return undefined;\n}\n\n/**\n * Port of utils.rs parse_timestamp_str / parse_entry_timestamp: an RFC3339 string\n * → epoch ms; an integer (string or number) → ms (×1000 when below the 1e12 ms\n * threshold); rejects ≤ 0. Returns null when unusable so the entry is skipped.\n */\nfunction parseEntryTimestamp(v: unknown): number | null {\n let s: string;\n if (typeof v === \"string\") s = v;\n else if (typeof v === \"number\" && Number.isFinite(v)) s = String(Math.trunc(v));\n else return null;\n\n return parseTimestampStr(s);\n}\n\nfunction parseTimestampStr(value: string): number | null {\n const ms = Date.parse(value);\n if (!Number.isNaN(ms)) return ms; // RFC3339 / any Date-parseable form\n\n if (/^[+-]?\\d+$/.test(value.trim())) {\n const numeric = Number(value.trim());\n if (!Number.isFinite(numeric) || numeric <= 0) return null;\n return numeric >= 1_000_000_000_000 ? numeric : numeric * 1000;\n }\n return null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// session id (port of extract_session_id)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Session id = the parent directory (taskId) of ui_messages.json, else \"unknown\". */\nfunction extractSessionId(path: string): string {\n const parent = basename(dirname(path));\n return parent !== \"\" ? parent : DEFAULT_SESSION;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// model / agent (ports of read_task_metadata / extract_model_and_agent / extract_tag_value)\n// ─────────────────────────────────────────────────────────────────────────\n\ninterface TaskMetadata {\n model: string;\n agent?: string;\n}\n\n/** Read the sibling api_conversation_history.json for model/agent (fail-open). */\nfunction readTaskMetadata(uiMessagesPath: string): TaskMetadata {\n const historyPath = join(dirname(uiMessagesPath), \"api_conversation_history.json\");\n let content: string;\n try {\n content = readFileSync(historyPath, \"utf8\");\n } catch {\n return { model: DEFAULT_MODEL }; // missing/unreadable → (\"unknown\", None)\n }\n return extractModelAndAgent(content);\n}\n\n/**\n * Scan every <environment_details>…</environment_details> block, extracting\n * <model>, <slug>, <name>. The LAST non-empty value of each tag wins (port of the\n * Rust last_* accumulation). model defaults to \"unknown\"; agent prefers slug then\n * name (and is omitted when neither is present).\n */\nfunction extractModelAndAgent(content: string): TaskMetadata {\n const ENV_START = \"<environment_details>\";\n const ENV_END = \"</environment_details>\";\n\n let offset = 0;\n let lastModel: string | undefined;\n let lastSlug: string | undefined;\n let lastName: string | undefined;\n\n for (;;) {\n const startRel = content.indexOf(ENV_START, offset);\n if (startRel < 0) break;\n const startIdx = startRel + ENV_START.length;\n\n const endRel = content.indexOf(ENV_END, startIdx);\n if (endRel < 0) break;\n\n const block = content.slice(startIdx, endRel);\n\n const model = extractTagValue(block, \"model\");\n if (model !== undefined) lastModel = model;\n const slug = extractTagValue(block, \"slug\");\n if (slug !== undefined) lastSlug = slug;\n const name = extractTagValue(block, \"name\");\n if (name !== undefined) lastName = name;\n\n offset = endRel + ENV_END.length;\n }\n\n const agent = lastSlug ?? lastName;\n const result: TaskMetadata = { model: lastModel ?? DEFAULT_MODEL };\n if (agent !== undefined) result.agent = agent;\n return result;\n}\n\n/** First <tag>…</tag> value in `block`, trimmed; undefined when absent or empty. */\nfunction extractTagValue(block: string, tag: string): string | undefined {\n const open = `<${tag}>`;\n const close = `</${tag}>`;\n\n const openIdx = block.indexOf(open);\n if (openIdx < 0) return undefined;\n const start = openIdx + open.length;\n const endRel = block.indexOf(close, start);\n if (endRel < 0) return undefined;\n\n const value = block.slice(start, endRel).trim();\n return value === \"\" ? undefined : value;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// api_req_started payload (port of parse_api_req_started_payload + provider_from_api_protocol)\n// ─────────────────────────────────────────────────────────────────────────\n\ninterface ApiReqStartedPayload {\n cost: number;\n tokensIn: number;\n tokensOut: number;\n cacheReads: number;\n cacheWrites: number;\n apiProtocol?: string;\n}\n\n/** Parse the JSON-in-string `text` payload of an api_req_started entry. */\nfunction parseApiReqStartedPayload(text: string): ApiReqStartedPayload | undefined {\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch {\n return undefined;\n }\n if (typeof value !== \"object\" || value === null) return undefined;\n const obj = value as Record<string, unknown>;\n\n // cost: extract_f64(.cost).unwrap_or(0.0).max(0.0)\n const cost = Math.max(0, extractF64(obj[\"cost\"]) ?? 0);\n const apiProtocolRaw = typeof obj[\"apiProtocol\"] === \"string\" ? (obj[\"apiProtocol\"] as string) : undefined;\n\n const payload: ApiReqStartedPayload = {\n cost,\n tokensIn: tokenField(obj[\"tokensIn\"]),\n tokensOut: tokenField(obj[\"tokensOut\"]),\n cacheReads: tokenField(obj[\"cacheReads\"]),\n cacheWrites: tokenField(obj[\"cacheWrites\"]),\n };\n if (apiProtocolRaw !== undefined) payload.apiProtocol = apiProtocolRaw;\n return payload;\n}\n\n/** Provider from apiProtocol: trimmed, non-empty, else \"unknown\" (verbatim — no inference). */\nfunction providerFromApiProtocol(apiProtocol: string | undefined): string {\n if (apiProtocol === undefined) return DEFAULT_PROVIDER;\n const trimmed = apiProtocol.trim();\n return trimmed === \"\" ? DEFAULT_PROVIDER : trimmed;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// File parse (port of parse_roo_kilo_file with source \"roocode\")\n// ─────────────────────────────────────────────────────────────────────────\n\n/** The fields we read off a ui_messages.json entry (all optional / unknown). */\ninterface UiMessageEntry {\n type?: unknown;\n say?: unknown;\n text?: unknown;\n ts?: unknown;\n}\n\n/** Parse one task's ui_messages.json into usage records. */\nfunction parseRooCodeFile(path: string): UsageRecord[] {\n const data = readJsonFile(path);\n if (!Array.isArray(data)) return []; // malformed / non-array → no rows\n\n const sessionId = extractSessionId(path);\n const { model, agent } = readTaskMetadata(path);\n\n const out: UsageRecord[] = [];\n for (const raw of data) {\n if (typeof raw !== \"object\" || raw === null) continue;\n const entry = raw as UiMessageEntry;\n\n if (entry.type !== \"say\" || entry.say !== \"api_req_started\") continue;\n\n if (typeof entry.text !== \"string\") continue; // None => skip\n const ts = parseEntryTimestamp(entry.ts);\n if (ts === null) continue; // unparseable ts => skip\n\n const payload = parseApiReqStartedPayload(entry.text);\n if (payload === undefined) continue; // malformed payload => skip\n\n const providerId = providerFromApiProtocol(payload.apiProtocol);\n\n const tokens = emptyTokens();\n tokens.input = payload.tokensIn;\n tokens.output = payload.tokensOut;\n tokens.cacheRead = payload.cacheReads;\n tokens.cacheWrite = payload.cacheWrites;\n // reasoning stays 0 (Roo Code does not report it).\n\n const record: UsageRecord = {\n platformId: PLATFORM_ID,\n modelId: model,\n providerId,\n sessionId,\n tokens,\n ts,\n messageCount: 1,\n confidence: \"host-reported\",\n };\n if (payload.cost > 0) record.cost = payload.cost;\n if (agent !== undefined) record.agent = agent;\n out.push(record);\n }\n\n return out;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Reader singleton\n// ─────────────────────────────────────────────────────────────────────────\n\n/** The Roo Code (VS Code extension) usage reader singleton. */\nconst rooCodeReader: UsageReader = {\n platformId: PLATFORM_ID,\n kind: \"local\",\n async read({ sinceMs }: { sinceMs?: number }): Promise<UsageRecord[]> {\n const root = tasksRoot();\n if (!existsSync(root)) return []; // no tasks dir → fail-open\n\n // <root>/<taskId>/ui_messages.json\n const files = walkFiles(root, (name, abs) => {\n return name === \"ui_messages.json\" && /[\\\\/]ui_messages\\.json$/.test(abs);\n });\n\n const records: UsageRecord[] = [];\n for (const file of files) {\n let rows: UsageRecord[];\n try {\n rows = parseRooCodeFile(file);\n } catch {\n continue; // fail-open per file\n }\n for (const row of rows) {\n if (sinceMs !== undefined && row.ts < sinceMs) continue;\n records.push(row);\n }\n }\n return records;\n },\n};\n\nexport default rooCodeReader;\n"],"mappings":";;;;;;;;;;;;;AAiDA,SAAS,YAAY,oBAAoB;AACzC,SAAS,SAAS,YAAY,kBAAkB;AAChD,SAAS,UAAU,SAAS,YAAY,MAAM,eAAe;AAO7D,IAAM,cAAc;AACpB,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AAGxB,IAAM,mBAAmB;AAQzB,SAAS,gBAAwB;AAC/B,QAAM,OAAO,QAAQ;AACrB,UAAQ,WAAW,GAAG;AAAA,IACpB,KAAK;AACH,aAAO,KAAK,MAAM,WAAW,uBAAuB,QAAQ,MAAM;AAAA,IACpE,KAAK,SAAS;AACZ,YAAM,UAAU,QAAQ,IAAI,WAAW,KAAK,MAAM,WAAW,SAAS;AACtE,aAAO,KAAK,SAAS,QAAQ,MAAM;AAAA,IACrC;AAAA,IACA;AACE,aAAO,KAAK,MAAM,WAAW,QAAQ,MAAM;AAAA,EAC/C;AACF;AAQA,SAAS,YAAoB;AAC3B,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,OAAO,QAAQ,IAAI,KAAK,MAAM,IAAI;AACpC,UAAM,WAAW,WAAW,IAAI,KAAK,CAAC;AACtC,WAAO,WAAW,QAAQ,IAAI,WAAW,QAAQ,QAAQ;AAAA,EAC3D;AACA,SAAO,KAAK,cAAc,GAAG,iBAAiB,kBAAkB,OAAO;AACzE;AAOA,SAAS,WAAW,GAAgC;AAClD,MAAI,OAAO,MAAM,UAAU;AACzB,QAAI,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO;AAChC,WAAO,KAAK,MAAM,CAAC;AAAA,EACrB;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,UAAM,UAAU,EAAE,KAAK;AACvB,QAAI,CAAC,aAAa,KAAK,OAAO,EAAG,QAAO;AACxC,UAAM,IAAI,OAAO,OAAO;AACxB,WAAO,OAAO,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI;AAAA,EAC9C;AACA,SAAO;AACT;AAGA,SAAS,WAAW,GAAoB;AACtC,QAAM,IAAI,WAAW,CAAC;AACtB,SAAO,MAAM,SAAY,IAAI,KAAK,IAAI,GAAG,CAAC;AAC5C;AAGA,SAAS,WAAW,GAAgC;AAClD,MAAI,OAAO,MAAM,SAAU,QAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAC3D,MAAI,OAAO,MAAM,UAAU;AACzB,UAAM,IAAI,OAAO,EAAE,KAAK,CAAC;AACzB,WAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAAA,EAClC;AACA,SAAO;AACT;AAOA,SAAS,oBAAoB,GAA2B;AACtD,MAAI;AACJ,MAAI,OAAO,MAAM,SAAU,KAAI;AAAA,WACtB,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,EAAG,KAAI,OAAO,KAAK,MAAM,CAAC,CAAC;AAAA,MACzE,QAAO;AAEZ,SAAO,kBAAkB,CAAC;AAC5B;AAEA,SAAS,kBAAkB,OAA8B;AACvD,QAAM,KAAK,KAAK,MAAM,KAAK;AAC3B,MAAI,CAAC,OAAO,MAAM,EAAE,EAAG,QAAO;AAE9B,MAAI,aAAa,KAAK,MAAM,KAAK,CAAC,GAAG;AACnC,UAAM,UAAU,OAAO,MAAM,KAAK,CAAC;AACnC,QAAI,CAAC,OAAO,SAAS,OAAO,KAAK,WAAW,EAAG,QAAO;AACtD,WAAO,WAAW,OAAoB,UAAU,UAAU;AAAA,EAC5D;AACA,SAAO;AACT;AAOA,SAAS,iBAAiB,MAAsB;AAC9C,QAAM,SAAS,SAAS,QAAQ,IAAI,CAAC;AACrC,SAAO,WAAW,KAAK,SAAS;AAClC;AAYA,SAAS,iBAAiB,gBAAsC;AAC9D,QAAM,cAAc,KAAK,QAAQ,cAAc,GAAG,+BAA+B;AACjF,MAAI;AACJ,MAAI;AACF,cAAU,aAAa,aAAa,MAAM;AAAA,EAC5C,QAAQ;AACN,WAAO,EAAE,OAAO,cAAc;AAAA,EAChC;AACA,SAAO,qBAAqB,OAAO;AACrC;AAQA,SAAS,qBAAqB,SAA+B;AAC3D,QAAM,YAAY;AAClB,QAAM,UAAU;AAEhB,MAAI,SAAS;AACb,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,aAAS;AACP,UAAM,WAAW,QAAQ,QAAQ,WAAW,MAAM;AAClD,QAAI,WAAW,EAAG;AAClB,UAAM,WAAW,WAAW,UAAU;AAEtC,UAAM,SAAS,QAAQ,QAAQ,SAAS,QAAQ;AAChD,QAAI,SAAS,EAAG;AAEhB,UAAM,QAAQ,QAAQ,MAAM,UAAU,MAAM;AAE5C,UAAM,QAAQ,gBAAgB,OAAO,OAAO;AAC5C,QAAI,UAAU,OAAW,aAAY;AACrC,UAAM,OAAO,gBAAgB,OAAO,MAAM;AAC1C,QAAI,SAAS,OAAW,YAAW;AACnC,UAAM,OAAO,gBAAgB,OAAO,MAAM;AAC1C,QAAI,SAAS,OAAW,YAAW;AAEnC,aAAS,SAAS,QAAQ;AAAA,EAC5B;AAEA,QAAM,QAAQ,YAAY;AAC1B,QAAM,SAAuB,EAAE,OAAO,aAAa,cAAc;AACjE,MAAI,UAAU,OAAW,QAAO,QAAQ;AACxC,SAAO;AACT;AAGA,SAAS,gBAAgB,OAAe,KAAiC;AACvE,QAAM,OAAO,IAAI,GAAG;AACpB,QAAM,QAAQ,KAAK,GAAG;AAEtB,QAAM,UAAU,MAAM,QAAQ,IAAI;AAClC,MAAI,UAAU,EAAG,QAAO;AACxB,QAAM,QAAQ,UAAU,KAAK;AAC7B,QAAM,SAAS,MAAM,QAAQ,OAAO,KAAK;AACzC,MAAI,SAAS,EAAG,QAAO;AAEvB,QAAM,QAAQ,MAAM,MAAM,OAAO,MAAM,EAAE,KAAK;AAC9C,SAAO,UAAU,KAAK,SAAY;AACpC;AAgBA,SAAS,0BAA0B,MAAgD;AACjF,MAAI;AACJ,MAAI;AACF,YAAQ,KAAK,MAAM,IAAI;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MAAM;AAGZ,QAAM,OAAO,KAAK,IAAI,GAAG,WAAW,IAAI,MAAM,CAAC,KAAK,CAAC;AACrD,QAAM,iBAAiB,OAAO,IAAI,aAAa,MAAM,WAAY,IAAI,aAAa,IAAe;AAEjG,QAAM,UAAgC;AAAA,IACpC;AAAA,IACA,UAAU,WAAW,IAAI,UAAU,CAAC;AAAA,IACpC,WAAW,WAAW,IAAI,WAAW,CAAC;AAAA,IACtC,YAAY,WAAW,IAAI,YAAY,CAAC;AAAA,IACxC,aAAa,WAAW,IAAI,aAAa,CAAC;AAAA,EAC5C;AACA,MAAI,mBAAmB,OAAW,SAAQ,cAAc;AACxD,SAAO;AACT;AAGA,SAAS,wBAAwB,aAAyC;AACxE,MAAI,gBAAgB,OAAW,QAAO;AACtC,QAAM,UAAU,YAAY,KAAK;AACjC,SAAO,YAAY,KAAK,mBAAmB;AAC7C;AAeA,SAAS,iBAAiB,MAA6B;AACrD,QAAM,OAAO,aAAa,IAAI;AAC9B,MAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,QAAO,CAAC;AAElC,QAAM,YAAY,iBAAiB,IAAI;AACvC,QAAM,EAAE,OAAO,MAAM,IAAI,iBAAiB,IAAI;AAE9C,QAAM,MAAqB,CAAC;AAC5B,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM;AAC7C,UAAM,QAAQ;AAEd,QAAI,MAAM,SAAS,SAAS,MAAM,QAAQ,kBAAmB;AAE7D,QAAI,OAAO,MAAM,SAAS,SAAU;AACpC,UAAM,KAAK,oBAAoB,MAAM,EAAE;AACvC,QAAI,OAAO,KAAM;AAEjB,UAAM,UAAU,0BAA0B,MAAM,IAAI;AACpD,QAAI,YAAY,OAAW;AAE3B,UAAM,aAAa,wBAAwB,QAAQ,WAAW;AAE9D,UAAM,SAAS,YAAY;AAC3B,WAAO,QAAQ,QAAQ;AACvB,WAAO,SAAS,QAAQ;AACxB,WAAO,YAAY,QAAQ;AAC3B,WAAO,aAAa,QAAQ;AAG5B,UAAM,SAAsB;AAAA,MAC1B,YAAY;AAAA,MACZ,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,YAAY;AAAA,IACd;AACA,QAAI,QAAQ,OAAO,EAAG,QAAO,OAAO,QAAQ;AAC5C,QAAI,UAAU,OAAW,QAAO,QAAQ;AACxC,QAAI,KAAK,MAAM;AAAA,EACjB;AAEA,SAAO;AACT;AAOA,IAAM,gBAA6B;AAAA,EACjC,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM,KAAK,EAAE,QAAQ,GAAiD;AACpE,UAAM,OAAO,UAAU;AACvB,QAAI,CAAC,WAAW,IAAI,EAAG,QAAO,CAAC;AAG/B,UAAM,QAAQ,UAAU,MAAM,CAAC,MAAM,QAAQ;AAC3C,aAAO,SAAS,sBAAsB,0BAA0B,KAAK,GAAG;AAAA,IAC1E,CAAC;AAED,UAAM,UAAyB,CAAC;AAChC,eAAW,QAAQ,OAAO;AACxB,UAAI;AACJ,UAAI;AACF,eAAO,iBAAiB,IAAI;AAAA,MAC9B,QAAQ;AACN;AAAA,MACF;AACA,iBAAW,OAAO,MAAM;AACtB,YAAI,YAAY,UAAa,IAAI,KAAK,QAAS;AAC/C,gBAAQ,KAAK,GAAG;AAAA,MAClB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAEA,IAAO,mBAAQ;","names":[]}
@@ -1,361 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- resolveEnvRefsDeep
4
- } from "./chunk-BEFVJ2OE.js";
5
- import {
6
- BaseAdapter,
7
- renderCommandMd,
8
- renderSkillMd
9
- } from "./chunk-JTN3AKZO.js";
10
- import {
11
- buildWrappedStdio
12
- } from "./chunk-QSY74NAP.js";
13
- import "./chunk-UMQ6NBQR.js";
14
- import "./chunk-GZGLCCEE.js";
15
-
16
- // src/adapters/roo-code/index.ts
17
- import { existsSync } from "fs";
18
- import { homedir, platform as osPlatform } from "os";
19
- import { join } from "path";
20
- var HOST = "roo-code";
21
- var MCP_ROOT_KEY = "mcpServers";
22
- var ROO_EXTENSION_ID = "rooveterinaryinc.roo-cline";
23
- var MCP_SETTINGS_FILE = "mcp_settings.json";
24
- var LEGACY_MCP_SETTINGS_FILE = "cline_mcp_settings.json";
25
- function vscodeUserDir() {
26
- const home = homedir();
27
- switch (osPlatform()) {
28
- case "darwin":
29
- return join(home, "Library", "Application Support", "Code", "User");
30
- case "win32": {
31
- const appData = process.env.APPDATA ?? join(home, "AppData", "Roaming");
32
- return join(appData, "Code", "User");
33
- }
34
- default:
35
- return join(home, ".config", "Code", "User");
36
- }
37
- }
38
- var RooCodeAdapter = class extends BaseAdapter {
39
- id = HOST;
40
- name = "Roo Code";
41
- paradigm = "mcp-only";
42
- capabilities = {
43
- // Memory surface: AGENTS.md-first managed block (project <projectDir>/AGENTS.md
44
- // via the base default — Roo's "Agent Rules standard" support is default-on;
45
- // user scope → ~/.roo/rules/agent-connector.md below).
46
- supportsMemory: true,
47
- // Roo Code has no lifecycle hook system — every hook capability is false.
48
- preToolUse: false,
49
- postToolUse: false,
50
- preCompact: false,
51
- sessionStart: false,
52
- sessionEnd: false,
53
- userPromptSubmit: false,
54
- stop: false,
55
- notification: false,
56
- canModifyArgs: false,
57
- canModifyOutput: false,
58
- canInjectSessionContext: false,
59
- // Roo Code registers stdio, SSE, and Streamable HTTP MCP servers.
60
- transports: ["stdio", "sse", "http"],
61
- // Content surfaces: Roo Code reads custom slash commands and AgentSkills from
62
- // its `.roo` config dir (BOTH user ~/.roo and project <projectDir>/.roo).
63
- // command → <configDir>/commands/<name>.md (md+optional frontmatter)
64
- // skill → <configDir>/skills/<name>/SKILL.md (+ resources)
65
- supportsCommands: true,
66
- supportsSkills: true
67
- };
68
- // ── Detection ────────────────────────────────────────────────────────────
69
- detectInstalled(projectDir) {
70
- const userSettings = this.userSettingsPath();
71
- const userExtDir = join(
72
- vscodeUserDir(),
73
- "globalStorage",
74
- ROO_EXTENSION_ID
75
- );
76
- const userLegacySettings = join(
77
- userExtDir,
78
- "settings",
79
- LEGACY_MCP_SETTINGS_FILE
80
- );
81
- const projectMcp = join(projectDir, ".roo", "mcp.json");
82
- const userMatch = existsSync(userSettings) || existsSync(userLegacySettings) || existsSync(userExtDir);
83
- const projectMatch = existsSync(projectMcp);
84
- const installed = userMatch || projectMatch;
85
- const scope = userMatch || !projectMatch ? "user" : "project";
86
- const configPath = scope === "user" ? userSettings : projectMcp;
87
- const reason = installed ? userMatch ? `found Roo Code globalStorage under ${userExtDir}` : `found Roo Code project config at ${projectMcp}` : `no Roo Code config at ${userExtDir} or ${projectMcp}`;
88
- return {
89
- id: this.id,
90
- name: this.name,
91
- installed,
92
- paradigm: this.paradigm,
93
- capabilities: this.capabilities,
94
- configPath,
95
- scope,
96
- reason,
97
- confidence: installed ? "high" : "low"
98
- };
99
- }
100
- // ── Native paths ─────────────────────────────────────────────────────────
101
- /** Absolute path to the user-scope MCP settings file (VS Code globalStorage). */
102
- userSettingsPath() {
103
- return join(
104
- vscodeUserDir(),
105
- "globalStorage",
106
- ROO_EXTENSION_ID,
107
- "settings",
108
- MCP_SETTINGS_FILE
109
- );
110
- }
111
- // ── Memory surface: global rules dir at user scope ──────────────────────
112
- // Project scope stays on the AGENTS.md base default ("Agent Rules standard",
113
- // default-on). User scope targets a dedicated agent-connector.md in Roo's
114
- // documented ~/.roo/rules/ dir (files concatenated; AC-created → cleanly
115
- // deletable on uninstall).
116
- memoryTargets(ctx) {
117
- if (this.memoryOverride(ctx)?.path || ctx.scope !== "user") {
118
- return super.memoryTargets(ctx);
119
- }
120
- return [
121
- {
122
- path: join(homedir(), ".roo", "rules", "agent-connector.md"),
123
- reason: "roo-code global rules dir (~/.roo/rules; agent-connector-owned file)"
124
- }
125
- ];
126
- }
127
- getConfigDir(ctx) {
128
- return ctx.scope === "project" ? join(ctx.projectDir, ".roo") : join(
129
- vscodeUserDir(),
130
- "globalStorage",
131
- ROO_EXTENSION_ID,
132
- "settings"
133
- );
134
- }
135
- getServerConfigPath(ctx) {
136
- return ctx.scope === "project" ? join(ctx.projectDir, ".roo", "mcp.json") : this.userSettingsPath();
137
- }
138
- /**
139
- * Roo Code has no hook file — hooks are not a thing here. The hook "config
140
- * path" is the same MCP settings file so the generic doctor/backup behave
141
- * sensibly.
142
- */
143
- getHookConfigPath(ctx) {
144
- return this.getServerConfigPath(ctx);
145
- }
146
- // ── MCP server install / uninstall ───────────────────────────────────────
147
- installServer(ctx) {
148
- const { connector } = ctx;
149
- const override = connector.platforms[HOST]?.server;
150
- if (!connector.server || override === false) {
151
- return [
152
- {
153
- platform: this.id,
154
- action: "skip",
155
- detail: connector.server ? "server registration disabled for roo-code" : "connector declares no MCP server"
156
- }
157
- ];
158
- }
159
- const server = override && typeof override === "object" ? { ...connector.server, ...override } : connector.server;
160
- const serverPath = this.getServerConfigPath(ctx);
161
- const entry = this.renderServerEntry(ctx, server);
162
- return [
163
- this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun)
164
- ];
165
- }
166
- uninstallServer(ctx) {
167
- const serverPath = this.getServerConfigPath(ctx);
168
- return [
169
- this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun)
170
- ];
171
- }
172
- /** Render a normalized ServerDef into Roo Code's native mcpServers entry. */
173
- renderServerEntry(ctx, server) {
174
- const transport = server.transport;
175
- if (transport === "stdio") {
176
- let command = server.command ?? "";
177
- let args = [...server.args ?? []];
178
- ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));
179
- const entry2 = {
180
- command: resolveEnvRefsDeep(command),
181
- // Honor the per-call server's enabled flag (mirror droid) rather than
182
- // hardcoding enabled — a server marked enabled:false installs disabled.
183
- disabled: server.enabled === false
184
- };
185
- if (args.length > 0) entry2.args = resolveEnvRefsDeep(args);
186
- const env = this.renderEnv(server.env);
187
- if (env) entry2.env = env;
188
- return entry2;
189
- }
190
- const entry = {
191
- url: resolveEnvRefsDeep(server.url ?? ""),
192
- type: transport === "http" ? "streamable-http" : "sse",
193
- disabled: server.enabled === false
194
- };
195
- const headers = this.renderEnv(server.headers);
196
- if (headers) entry.headers = headers;
197
- return entry;
198
- }
199
- /**
200
- * Render env/header values. Roo Code documents no native interpolation token,
201
- * so resolve `${env:VAR}` references to literals at install time.
202
- */
203
- renderEnv(env) {
204
- if (!env || Object.keys(env).length === 0) return void 0;
205
- return resolveEnvRefsDeep({ ...env });
206
- }
207
- // ── Hooks (unavailable — Roo Code is mcp-only) ───────────────────────────
208
- installHooks(_ctx) {
209
- return [
210
- {
211
- platform: this.id,
212
- action: "skip",
213
- detail: "hooks unavailable (Roo Code is mcp-only)"
214
- }
215
- ];
216
- }
217
- uninstallHooks(_ctx) {
218
- return [
219
- {
220
- platform: this.id,
221
- action: "skip",
222
- detail: "hooks unavailable (Roo Code is mcp-only)"
223
- }
224
- ];
225
- }
226
- // ── Content surfaces: commands / skills ──────────────────────────────────
227
- // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin
228
- // pointer, no telemetry wrap. Each method is idempotent (byte-identical →
229
- // skip) via writeContentFile and reversible via removeContentFile. Honors
230
- // platforms["roo-code"] per-surface false to skip. BOTH scopes are supported:
231
- // user → ~/.roo, project → <projectDir>/.roo.
232
- //
233
- // Native locations (the `.roo` content root, NOT the globalStorage MCP dir):
234
- // command → <rooDir>/commands/<name>.md md+optional frontmatter
235
- // (description, argument-hint, + `mode` when cmd.extra carries it)
236
- // skill → <rooDir>/skills/<name>/SKILL.md (+ resources)
237
- /**
238
- * The `.roo` content root for the active scope: ~/.roo (user) or
239
- * <projectDir>/.roo (project). Distinct from getConfigDir's user-scope path
240
- * (the VS Code globalStorage `settings` dir, which holds MCP settings only).
241
- */
242
- rooDir(ctx) {
243
- return ctx.scope === "project" ? join(ctx.projectDir, ".roo") : join(homedir(), ".roo");
244
- }
245
- commandPath(ctx, name) {
246
- return join(this.rooDir(ctx), "commands", `${name}.md`);
247
- }
248
- skillDir(ctx, name) {
249
- return join(this.rooDir(ctx), "skills", name);
250
- }
251
- // ── Commands ─────────────────────────────────────────────────────────────
252
- installCommands(ctx) {
253
- const { connector } = ctx;
254
- if (connector.platforms[this.id]?.commands === false) {
255
- return [{ platform: this.id, action: "skip", detail: "commands disabled for roo-code" }];
256
- }
257
- if (connector.commands.length === 0) {
258
- return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
259
- }
260
- return connector.commands.map(
261
- (cmd) => this.writeContentFile(
262
- this.commandPath(ctx, cmd.name),
263
- renderCommandMd(cmd, { includeToolsAndModel: false }),
264
- ctx.dryRun
265
- )
266
- );
267
- }
268
- uninstallCommands(ctx) {
269
- const { connector } = ctx;
270
- if (connector.commands.length === 0) {
271
- return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
272
- }
273
- return connector.commands.map(
274
- (cmd) => this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun)
275
- );
276
- }
277
- // ── Skills ───────────────────────────────────────────────────────────────
278
- installSkills(ctx) {
279
- const { connector } = ctx;
280
- if (connector.platforms[this.id]?.skills === false) {
281
- return [{ platform: this.id, action: "skip", detail: "skills disabled for roo-code" }];
282
- }
283
- if (connector.skills.length === 0) {
284
- return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
285
- }
286
- const changes = [];
287
- for (const skill of connector.skills) {
288
- const dir = this.skillDir(ctx, skill.name);
289
- changes.push(
290
- this.writeContentFile(join(dir, "SKILL.md"), renderSkillMd(skill), ctx.dryRun)
291
- );
292
- for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
293
- const target = this.resolveWithin(dir, rel);
294
- if (target === null) {
295
- changes.push({
296
- platform: this.id,
297
- action: "warn",
298
- detail: `skill resource "${rel}" escapes the skill dir; skipped`
299
- });
300
- continue;
301
- }
302
- changes.push(this.writeContentFile(target, contents, ctx.dryRun));
303
- }
304
- }
305
- return changes;
306
- }
307
- uninstallSkills(ctx) {
308
- const { connector } = ctx;
309
- if (connector.skills.length === 0) {
310
- return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
311
- }
312
- const changes = [];
313
- for (const skill of connector.skills) {
314
- const dir = this.skillDir(ctx, skill.name);
315
- changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
316
- for (const rel of Object.keys(skill.resources ?? {})) {
317
- const target = this.resolveWithin(dir, rel);
318
- if (target === null) continue;
319
- changes.push(this.removeContentFile(target, ctx.dryRun));
320
- }
321
- changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
322
- }
323
- return changes;
324
- }
325
- // ── Diagnostics ──────────────────────────────────────────────────────────
326
- getHealthChecks(ctx) {
327
- const mcpPath = this.getServerConfigPath(ctx);
328
- const connectorId = ctx.connector.id;
329
- return [
330
- {
331
- name: `${this.name}: MCP settings present`,
332
- check: () => existsSync(mcpPath) ? { status: "OK", detail: mcpPath } : { status: "FAIL", detail: `not found: ${mcpPath}` }
333
- },
334
- {
335
- name: `${this.name}: server entry registered`,
336
- check: () => {
337
- if (!ctx.connector.server) {
338
- return { status: "OK", detail: "no MCP server declared" };
339
- }
340
- const cfg = this.readJson(mcpPath);
341
- const bucket = cfg?.[MCP_ROOT_KEY];
342
- if (!cfg || !bucket) {
343
- return { status: "FAIL", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };
344
- }
345
- return connectorId in bucket ? { status: "OK", detail: `${MCP_ROOT_KEY}.${connectorId} present` } : {
346
- status: "FAIL",
347
- detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`
348
- };
349
- }
350
- }
351
- ];
352
- }
353
- };
354
- var adapter = new RooCodeAdapter();
355
- var roo_code_default = adapter;
356
- export {
357
- RooCodeAdapter,
358
- adapter,
359
- roo_code_default as default
360
- };
361
- //# sourceMappingURL=roo-code-VI2ZKTZC.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/roo-code/index.ts"],"sourcesContent":["/**\n * adapters/roo-code — Roo Code (VS Code extension) platform adapter.\n *\n * Roo Code (rooveterinaryinc.roo-cline) is a Cline-fork VS Code extension and an\n * **mcp-only** host from agent-connector's perspective: it exposes no lifecycle\n * hook system, so MCP server registration is the only thing we install and hooks\n * are reported unavailable. This mirrors the Warp reference adapter exactly.\n *\n * MCP config (vsix 3.54.0):\n * - user scope → <vscodeUserDir>/globalStorage/rooveterinaryinc.roo-cline/\n * settings/mcp_settings.json (renamed in 3.54.0 from the\n * older `cline_mcp_settings.json`; we PROBE both on detection\n * — the extension migrates the old name at startup — and\n * WRITE the new `mcp_settings.json`)\n * - project scope → <projectDir>/.roo/mcp.json\n * Both are JSON, root key \"mcpServers\".\n *\n * VS Code user-dir resolution (cross-OS):\n * - macOS → ~/Library/Application Support/Code/User\n * - Linux → ~/.config/Code/User\n * - Windows → %APPDATA%/Code/User (falls back to ~/AppData/Roaming/Code/User)\n * We deliberately target stable VS Code (\"Code\"), the documented home for the\n * published Roo Code extension's globalStorage. Insiders/forks would live under\n * a sibling dir but are out of scope for the default path.\n *\n * Env interpolation: Roo Code's settings file documents no native `${env:VAR}`\n * token (the entries are plain command/args/env literals), so we resolve every\n * `${env:VAR}` reference to a literal at install time — the no-native-token path.\n *\n * The hook \"config path\" is the SAME MCP settings file (there is no hook file),\n * so the generic doctor/backup behave sensibly.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir, platform as osPlatform } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, InstallContext, MemoryTarget } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildWrappedStdio,\n} from \"../../core/spawn.js\";\nimport { renderCommandMd, renderSkillMd } from \"../claude-code/render.js\";\n\nconst HOST: PlatformId = \"roo-code\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/** Roo Code extension id → its VS Code globalStorage folder. */\nconst ROO_EXTENSION_ID = \"rooveterinaryinc.roo-cline\";\n/** User-scope MCP settings filename — renamed in vsix 3.54.0. */\nconst MCP_SETTINGS_FILE = \"mcp_settings.json\";\n/** Legacy filename (pre-3.54.0) — probed on detection for older installs. */\nconst LEGACY_MCP_SETTINGS_FILE = \"cline_mcp_settings.json\";\n\n/**\n * Native MCP server entry shapes Roo Code accepts under `mcpServers`.\n * We write the minimal stdio shape { command, args, env, disabled }; Roo Code\n * also accepts optional `alwaysAllow` / `timeout`, which we intentionally omit.\n *\n * For remote (url-based) servers we ALWAYS emit `type`. Roo Code's config schema\n * (RooCodeInc/Roo-Code McpHub.ts `createServerTypeSchema` + `validateServerConfig`,\n * verified against v3.54.0) is STRICTER than its Cline parent: a url config with\n * NO `type` is REJECTED outright — \"Configuration with 'url' must explicitly\n * specify 'type' as 'sse' or 'streamable-http'.\" Note the value differs from\n * Cline: Roo Code uses the HYPHENATED `\"streamable-http\"` (Cline uses the\n * camelCase `\"streamableHttp\"`), so this is NOT byte-identical to the cline\n * adapter despite the fork lineage.\n */\ninterface RooStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n disabled: boolean;\n}\ninterface RooHttpServer {\n url: string;\n type: \"sse\" | \"streamable-http\";\n headers?: Record<string, string>;\n disabled: boolean;\n}\n\n/**\n * Resolve the cross-OS VS Code per-user data directory (the \"User\" folder that\n * contains `globalStorage`). See module header for the per-platform mapping.\n */\nfunction vscodeUserDir(): string {\n const home = homedir();\n switch (osPlatform()) {\n case \"darwin\":\n return join(home, \"Library\", \"Application Support\", \"Code\", \"User\");\n case \"win32\": {\n const appData =\n process.env.APPDATA ?? join(home, \"AppData\", \"Roaming\");\n return join(appData, \"Code\", \"User\");\n }\n default:\n // Linux / other POSIX: XDG-style config dir.\n return join(home, \".config\", \"Code\", \"User\");\n }\n}\n\nexport class RooCodeAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Roo Code\";\n readonly paradigm: HookParadigm = \"mcp-only\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block (project <projectDir>/AGENTS.md\n // via the base default — Roo's \"Agent Rules standard\" support is default-on;\n // user scope → ~/.roo/rules/agent-connector.md below).\n supportsMemory: true,\n // Roo Code has no lifecycle hook system — every hook capability is false.\n preToolUse: false,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Roo Code registers stdio, SSE, and Streamable HTTP MCP servers.\n transports: [\"stdio\", \"sse\", \"http\"],\n // Content surfaces: Roo Code reads custom slash commands and AgentSkills from\n // its `.roo` config dir (BOTH user ~/.roo and project <projectDir>/.roo).\n // command → <configDir>/commands/<name>.md (md+optional frontmatter)\n // skill → <configDir>/skills/<name>/SKILL.md (+ resources)\n supportsCommands: true,\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userSettings = this.userSettingsPath();\n const userExtDir = join(\n vscodeUserDir(),\n \"globalStorage\",\n ROO_EXTENSION_ID,\n );\n // Probe the legacy filename too (3.54.0 migrates it at startup) so an older\n // install is still recognized; we WRITE the new mcp_settings.json.\n const userLegacySettings = join(\n userExtDir,\n \"settings\",\n LEGACY_MCP_SETTINGS_FILE,\n );\n const projectMcp = join(projectDir, \".roo\", \"mcp.json\");\n\n const userMatch =\n existsSync(userSettings) ||\n existsSync(userLegacySettings) ||\n existsSync(userExtDir);\n const projectMatch = existsSync(projectMcp);\n const installed = userMatch || projectMatch;\n\n // Prefer the user scope/path when present; otherwise surface the project one.\n const scope = userMatch || !projectMatch ? \"user\" : \"project\";\n const configPath = scope === \"user\" ? userSettings : projectMcp;\n const reason = installed\n ? userMatch\n ? `found Roo Code globalStorage under ${userExtDir}`\n : `found Roo Code project config at ${projectMcp}`\n : `no Roo Code config at ${userExtDir} or ${projectMcp}`;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /** Absolute path to the user-scope MCP settings file (VS Code globalStorage). */\n private userSettingsPath(): string {\n return join(\n vscodeUserDir(),\n \"globalStorage\",\n ROO_EXTENSION_ID,\n \"settings\",\n MCP_SETTINGS_FILE,\n );\n }\n\n // ── Memory surface: global rules dir at user scope ──────────────────────\n // Project scope stays on the AGENTS.md base default (\"Agent Rules standard\",\n // default-on). User scope targets a dedicated agent-connector.md in Roo's\n // documented ~/.roo/rules/ dir (files concatenated; AC-created → cleanly\n // deletable on uninstall).\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"user\") {\n return super.memoryTargets(ctx);\n }\n return [\n {\n path: join(homedir(), \".roo\", \"rules\", \"agent-connector.md\"),\n reason: \"roo-code global rules dir (~/.roo/rules; agent-connector-owned file)\",\n },\n ];\n }\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".roo\")\n : join(\n vscodeUserDir(),\n \"globalStorage\",\n ROO_EXTENSION_ID,\n \"settings\",\n );\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".roo\", \"mcp.json\")\n : this.userSettingsPath();\n }\n\n /**\n * Roo Code has no hook file — hooks are not a thing here. The hook \"config\n * path\" is the same MCP settings file so the generic doctor/backup behave\n * sensibly.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for roo-code\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n const entry = this.renderServerEntry(ctx, server);\n\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /** Render a normalized ServerDef into Roo Code's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): RooStdioServer | RooHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n // Roo Code documents no native interpolation token, so resolve every\n // ${env:VAR} to a literal at install time.\n const entry: RooStdioServer = {\n command: resolveEnvRefsDeep(command),\n // Honor the per-call server's enabled flag (mirror droid) rather than\n // hardcoding enabled — a server marked enabled:false installs disabled.\n disabled: server.enabled === false,\n };\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // sse / http (and any other remote transport) — Roo Code registers a URL.\n // We ALWAYS emit `type`: Roo Code REJECTS a url config that omits it (and an\n // untyped url has no sse-default fallback like Cline's). Map our \"http\"\n // transport to Roo Code's HYPHENATED \"streamable-http\" (NOT Cline's camelCase\n // \"streamableHttp\") so a Streamable-HTTP server registers correctly.\n const entry: RooHttpServer = {\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n type: transport === \"http\" ? \"streamable-http\" : \"sse\",\n disabled: server.enabled === false,\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Roo Code documents no native interpolation token,\n * so resolve `${env:VAR}` references to literals at install time.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n // ── Hooks (unavailable — Roo Code is mcp-only) ───────────────────────────\n\n installHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Roo Code is mcp-only)\",\n },\n ];\n }\n\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Roo Code is mcp-only)\",\n },\n ];\n }\n\n // ── Content surfaces: commands / skills ──────────────────────────────────\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\n // skip) via writeContentFile and reversible via removeContentFile. Honors\n // platforms[\"roo-code\"] per-surface false to skip. BOTH scopes are supported:\n // user → ~/.roo, project → <projectDir>/.roo.\n //\n // Native locations (the `.roo` content root, NOT the globalStorage MCP dir):\n // command → <rooDir>/commands/<name>.md md+optional frontmatter\n // (description, argument-hint, + `mode` when cmd.extra carries it)\n // skill → <rooDir>/skills/<name>/SKILL.md (+ resources)\n\n /**\n * The `.roo` content root for the active scope: ~/.roo (user) or\n * <projectDir>/.roo (project). Distinct from getConfigDir's user-scope path\n * (the VS Code globalStorage `settings` dir, which holds MCP settings only).\n */\n private rooDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".roo\")\n : join(homedir(), \".roo\");\n }\n private commandPath(ctx: InstallContext, name: string): string {\n return join(this.rooDir(ctx), \"commands\", `${name}.md`);\n }\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.rooDir(ctx), \"skills\", name);\n }\n\n // ── Commands ─────────────────────────────────────────────────────────────\n\n override installCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.commands === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for roo-code\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n // Roo Code additionally honors a `mode` frontmatter key; it is passed\n // through only when cmd.extra carries it (renderCommandMd merges extra\n // verbatim). includeToolsAndModel:false suppresses allowed-tools/model so\n // the shape stays (description, argument-hint + verbatim extra).\n return connector.commands.map((cmd) =>\n this.writeContentFile(\n this.commandPath(ctx, cmd.name),\n renderCommandMd(cmd, { includeToolsAndModel: false }),\n ctx.dryRun,\n ),\n );\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\n );\n }\n\n // ── Skills ───────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for roo-code\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), renderSkillMd(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n return [\n {\n name: `${this.name}: MCP settings present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n // Only assert what the connector declares: a server-less connector —\n // e.g. a catalog-only bundle of agents/skills/commands — never writes\n // an mcpServers entry, so its absence is healthy.\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(mcpPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`,\n };\n },\n },\n ];\n }\n}\n\nexport const adapter = new RooCodeAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/windsurf/index.ts"],"sourcesContent":["/**\n * adapters/windsurf — Windsurf (Codeium / Cognition's Cascade agent) adapter.\n *\n * Windsurf is an mcp-only host from agent-connector's perspective: there is no\n * user-installable hook/plugin layer (it is a GUI editor). AC registers the MCP\n * server PLUS three content surfaces (memory, workflows, skills — see below). The\n * MCP config is a Claude-Desktop-style OBJECT map keyed by server name (exactly\n * like the cursor adapter's `mcpServers`), NOT an array.\n *\n * MCP config (primary-verified — docs.devin.ai/desktop/cascade/mcp, formerly\n * docs.windsurf.com):\n * - user/global scope ONLY → ~/.codeium/windsurf/mcp_config.json\n * (Windows %USERPROFILE%\\.codeium\\windsurf\\mcp_config.json — homedir()\n * covers it). The docs specify NO project/workspace config path, so a\n * project-scope install returns a skip ChangeRecord.\n * - root key \"mcpServers\" — a JSON object/map keyed by server name.\n *\n * Server entry shapes (primary-verified):\n * - stdio: { command, args?, env? }\n * - remote: { serverUrl, headers? } — the docs use `serverUrl` (an `url`\n * alias is mentioned but `serverUrl` is the documented primary). There is\n * NO `type` discriminator and NO `disabled` field — stdio vs remote is\n * distinguished by `command` vs `serverUrl`. `headers` is emitted only when\n * the connector's remote server provides them.\n *\n * Native interpolation: Windsurf supports `${env:VAR}` / `${file:/path}`\n * tokens, but AC does not need to emit those — values are resolved to literals\n * at install time (the safe path, same as droid/crush/amazon-q).\n *\n * Memory / rules (primary-verified — docs.windsurf.com/windsurf/cascade/rules,\n * llms-full.txt): a `.windsurf/rules/` workspace directory holds `.md` rule\n * files, each declaring an activation mode \"in its frontmatter via the `trigger`\n * field\". `trigger: always_on` means \"full rule content is included in the\n * system prompt on every message\" (the docs' literal Activation-Modes table).\n * AC owns a DEDICATED file there (`.windsurf/rules/agent-connector.md`) that MUST\n * LEAD with that always-on frontmatter, so — like the continue adapter and unlike\n * the cline/amazon-q managed-block targets — we write the WHOLE file\n * (frontmatter + body) via the content-file writers and own it end-to-end\n * (install creates, uninstall deletes). The connector's memory `content` is\n * host-agnostic (MemoryDef forbids its own frontmatter), so the always-on\n * directive is an adapter-level wrapper. WORKSPACE/PROJECT SCOPE: `global_rules.md`\n * is a single SHARED global file (not an AC-owned dir), so user scope skip-warns.\n *\n * Content surfaces — workflows (slash commands) + skills, BOTH project AND user\n * scope:\n * - workflows → project `<projectDir>/.windsurf/workflows/<name>.md`,\n * user `~/.codeium/windsurf/global_workflows/<name>.md` (the user dir is\n * `global_workflows`, NOT `workflows`). Each becomes a `/<name>` slash\n * command. Windsurf caps each workflow file at 12,000 chars — over-budget\n * files are still written but warned.\n * - skills → project `<projectDir>/.windsurf/skills/<name>/SKILL.md`,\n * user `~/.codeium/windsurf/skills/<name>/SKILL.md` (the dir is `skills` in\n * BOTH scopes). Same SKILL.md convention cline/claude-code/qwen-code use.\n * Both reuse the shared claude-code renderers (renderCommandMd/renderSkillMd).\n *\n * Hook \"config path\" is aliased to the MCP file (no separate hook file) so the\n * base doctor/backup helpers behave sensibly (the amazon-q / roo-code idiom).\n */\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport { renderCommandMd, renderSkillMd } from \"../claude-code/render.js\";\nimport type { Adapter, InstallContext } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildWrappedStdio,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"windsurf\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Windsurf caps each workflow (slash-command) file at 12,000 characters\n * (docs.windsurf.com). We still write an over-budget file but emit a warn so the\n * author can trim it, mirroring base.ts's memory soft-budget warn. Skills have no\n * documented size cap, so they are not guarded.\n */\nconst WORKFLOW_MAX_CHARS = 12000;\n\n/**\n * Native MCP server entry shapes Windsurf accepts under `mcpServers` (an OBJECT\n * map keyed by server name, Claude-Desktop-style):\n * - stdio: { command, args?, env? } — transport inferred from `command`.\n * - remote: { serverUrl, headers? } — `serverUrl` (NOT `url`); NO `type`\n * discriminator and NO `disabled` flag. `headers` only when provided.\n */\ninterface WindsurfStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface WindsurfRemoteServer {\n serverUrl: string;\n headers?: Record<string, string>;\n}\n\nexport class WindsurfAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Windsurf\";\n readonly paradigm: HookParadigm = \"mcp-only\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: WIRED. Windsurf reads `.windsurf/rules/*.md` (NOT\n // AGENTS.md), so the AGENTS.md-first BaseAdapter default does not apply — the\n // installMemory/uninstallMemory overrides below write a DEDICATED\n // agent-connector-owned file (<projectDir>/.windsurf/rules/agent-connector.md)\n // that LEADS with `trigger: always_on` frontmatter (full content in the\n // system prompt on every message). Workspace/project scope only; user scope\n // skip-warns (global_rules.md is a shared global file, not an AC-owned dir).\n supportsMemory: true,\n //\n // mcp-only: Windsurf is a GUI editor with no user-installable hook/plugin\n // layer. Every hook flag is false.\n preToolUse: false,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n // No hook layer → no arg/output rewrite, no context injection.\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Windsurf registers stdio + remote (http/sse) MCP servers; the remote\n // entry is distinguished by `serverUrl` (vs stdio's `command`).\n transports: [\"stdio\", \"http\", \"sse\"],\n // Content surfaces: WIRED in BOTH scopes. Windsurf reads user-authored\n // WORKFLOWS (each becomes a `/<name>` slash command) and Agent SKILLS (the\n // same SKILL.md frontmatter convention cline/claude-code/qwen-code use):\n // workflows → project .windsurf/workflows/<name>.md,\n // user ~/.codeium/windsurf/global_workflows/<name>.md\n // skills → project .windsurf/skills/<name>/SKILL.md,\n // user ~/.codeium/windsurf/skills/<name>/SKILL.md\n // The install overrides below branch the path on ctx.scope and write at both.\n // Subagents stay UNSET (no documented user-authored dir): base skip-warns.\n supportsCommands: true,\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(_projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".codeium\", \"windsurf\");\n const userMcp = join(userDir, \"mcp_config.json\");\n const installed = existsSync(userDir) || existsSync(userMcp);\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath: userMcp,\n scope: \"user\",\n reason: installed\n ? `found Windsurf config under ${userDir}`\n : `no Windsurf config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /**\n * Windsurf's MCP config is USER/GLOBAL scope only — the docs specify no\n * project/workspace path. getConfigDir always resolves the user dir\n * (homedir() covers USERPROFILE on Windows); a project-scope install is\n * handled by installServer returning a skip, never a write under projectDir.\n */\n getConfigDir(_ctx: InstallContext): string {\n return join(homedir(), \".codeium\", \"windsurf\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp_config.json\");\n }\n\n /**\n * Windsurf has no separate hook file — hook config path aliases the MCP file\n * so the generic doctor/backup helpers behave sensibly (amazon-q idiom).\n */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n // ── Memory surface: the `.windsurf/rules` content tree ────────────────────\n // A DEDICATED agent-connector-owned file that MUST LEAD with `trigger:\n // always_on` frontmatter (full content in the system prompt on every message).\n // Because of that leading frontmatter we do NOT use the base managed-block\n // engine — we own the whole file via the content-file writers: install\n // writes/updates it idempotently, uninstall deletes it. WORKSPACE/PROJECT scope\n // only (global_rules.md is a shared global file, not an AC-owned dir).\n\n /** <projectDir>/.windsurf/rules/agent-connector.md — the dedicated owned file. */\n private memoryFilePath(ctx: InstallContext): string {\n return join(ctx.projectDir, \".windsurf\", \"rules\", \"agent-connector.md\");\n }\n\n /** True when `<projectDir>/.windsurf/rules` exists and is a regular FILE. */\n private rulesDirIsFile(ctx: InstallContext): boolean {\n const p = join(ctx.projectDir, \".windsurf\", \"rules\");\n if (!existsSync(p)) return false;\n try {\n return statSync(p).isFile();\n } catch {\n return false;\n }\n }\n\n /**\n * Compose the dedicated rule file: `trigger: always_on` frontmatter (the\n * always-on activation directive) + every declared memory entry's content,\n * joined with a blank line. The connector's content is host-agnostic markdown\n * (MemoryDef forbids its own frontmatter), so the directive is ours to add.\n */\n private renderMemoryFile(ctx: InstallContext): string {\n const body = (ctx.connector.memory ?? [])\n .map((m) => m.content.trim())\n .filter((c) => c.length > 0)\n .join(\"\\n\\n\");\n return this.renderFrontmatterMd({ trigger: \"always_on\" }, body);\n }\n\n override installMemory(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const entries = connector.memory ?? [];\n if (connector.platforms[this.id]?.memory === false) {\n return [{ platform: this.id, action: \"skip\", detail: `memory disabled for ${this.id}` }];\n }\n if (entries.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no memory\" }];\n }\n // Windsurf's verified per-rule `.windsurf/rules` dir is WORKSPACE scope only.\n if (ctx.scope !== \"project\") {\n return [\n {\n platform: this.id,\n action: \"warn\",\n detail:\n `no ${ctx.scope}-scope rules dir verified for windsurf ` +\n `(.windsurf/rules is workspace-scope; global_rules.md is a shared file); ` +\n `${entries.length} skipped`,\n },\n ];\n }\n // Rules-path collision: never write under a `.windsurf/rules` that is a FILE.\n if (this.rulesDirIsFile(ctx)) {\n return [\n {\n platform: this.id,\n action: \"warn\",\n path: join(ctx.projectDir, \".windsurf\", \"rules\"),\n detail:\n \"existing .windsurf/rules is a file, not a directory; left untouched — \" +\n \"convert it to a .windsurf/rules/ directory to receive agent-connector memory\",\n },\n ];\n }\n return [this.writeContentFile(this.memoryFilePath(ctx), this.renderMemoryFile(ctx), ctx.dryRun)];\n }\n\n override uninstallMemory(ctx: InstallContext): ChangeRecord[] {\n // Only the project-scope dedicated file was ever written; a `.windsurf/rules`\n // that is a FILE was never ours (installMemory warned), so leave it.\n if (ctx.scope !== \"project\" || this.rulesDirIsFile(ctx)) {\n const path = this.memoryFilePath(ctx);\n return [\n { platform: this.id, action: \"skip\", path, detail: `${basename(path)} absent` },\n ];\n }\n return [this.removeContentFile(this.memoryFilePath(ctx), ctx.dryRun)];\n }\n\n // ── Content surfaces: commands (workflows) + skills ───────────────────────\n // CONTENT-ONLY native-file writers, structured like installMemory: dedicated-\n // file ownership, dryRun honored via writeContentFile/removeContentFile. Both\n // reuse the shared claude-code renderers (renderCommandMd / renderSkillMd) — no\n // new markdown serializer. BOTH scopes write (the project dir AND the\n // ~/.codeium/windsurf user/global dirs are documented surfaces):\n //\n // commands (workflows)\n // - project → <projectDir>/.windsurf/workflows/<name>.md\n // - user → ~/.codeium/windsurf/global_workflows/<name>.md\n // (NOTE: the user dir is `global_workflows`, NOT `workflows`.)\n // skills\n // - project → <projectDir>/.windsurf/skills/<name>/SKILL.md\n // - user → ~/.codeium/windsurf/skills/<name>/SKILL.md\n // (the dir is `skills` in BOTH scopes; same SKILL.md convention\n // cline/claude-code/qwen-code use.)\n //\n // renderCommandMd emits Claude-flavored frontmatter keys (argument-hint, model,\n // allowed-tools); Windsurf ignores unknown frontmatter keys, so they are inert/\n // tolerated — no Windsurf-specific renderer is needed.\n\n /** Workflow file: project `.windsurf/workflows`, user `~/.codeium/windsurf/global_workflows`. */\n private commandPath(ctx: InstallContext, name: string): string {\n const dir =\n ctx.scope === \"project\"\n ? join(ctx.projectDir, \".windsurf\", \"workflows\")\n : join(homedir(), \".codeium\", \"windsurf\", \"global_workflows\");\n return join(dir, `${name}.md`);\n }\n\n /** Skill dir: project `.windsurf/skills/<name>`, user `~/.codeium/windsurf/skills/<name>`. */\n private skillDir(ctx: InstallContext, name: string): string {\n const base =\n ctx.scope === \"project\"\n ? join(ctx.projectDir, \".windsurf\", \"skills\")\n : join(homedir(), \".codeium\", \"windsurf\", \"skills\");\n return join(base, name);\n }\n\n // ── Commands (workflows) ──────────────────────────────────────────────────\n\n override installCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.commands === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for windsurf\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const cmd of connector.commands) {\n const rendered = renderCommandMd(cmd);\n changes.push(this.writeContentFile(this.commandPath(ctx, cmd.name), rendered, ctx.dryRun));\n // Windsurf caps each workflow file at 12,000 characters (docs.windsurf.com).\n // Still write the file — warn so the author can trim it (Windsurf may reject\n // or truncate the overflow), mirroring base.ts's memory soft-budget warn.\n if (rendered.length > WORKFLOW_MAX_CHARS) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: this.commandPath(ctx, cmd.name),\n detail:\n `workflow \"${cmd.name}\" is ${rendered.length} chars ` +\n `(Windsurf caps each workflow at ${WORKFLOW_MAX_CHARS}); ` +\n `the host may reject or truncate it — trim the command`,\n });\n }\n }\n return changes;\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\n );\n }\n\n // ── Skills ────────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for windsurf\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), renderSkillMd(skill), ctx.dryRun),\n );\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue;\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for windsurf\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Windsurf has no project-level MCP config (user scope only — the docs\n // document only ~/.codeium/windsurf/mcp_config.json). A project-scope\n // install is reported as a skip rather than written into the project tree.\n if (ctx.scope === \"project\") {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail:\n \"Windsurf has no project-level MCP config (user scope only); \" +\n \"re-run with --scope user\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n\n // NEVER clobber a malformed `mcpServers`. The base upsert tolerates a\n // missing file / missing key (it creates the object), but a PRESENT-but-\n // non-object `mcpServers` (e.g. an array or string from a hand-edit) would\n // get a named property bolted on and silently corrupted — so skip-and-warn.\n const malformed = this.malformedRootKey(serverPath);\n if (malformed) return [malformed];\n\n const entry = this.renderServerEntry(ctx, server);\n\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n const malformed = this.malformedRootKey(serverPath);\n if (malformed) return [malformed];\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /**\n * Guard for a PRESENT-but-non-object `mcpServers` root key: returns a\n * skip-warn ChangeRecord when the existing config parses but its `mcpServers`\n * value is not a plain object (an array / string / number / null). Returns\n * undefined when the file is absent, unparseable (the base upsert's own\n * overwrite guard handles that), or `mcpServers` is absent / a plain object.\n */\n private malformedRootKey(configPath: string): ChangeRecord | undefined {\n const cfg = this.readJson<Record<string, unknown>>(configPath);\n if (!cfg || !(MCP_ROOT_KEY in cfg)) return undefined;\n const root = cfg[MCP_ROOT_KEY];\n if (root !== null && typeof root === \"object\" && !Array.isArray(root)) {\n return undefined;\n }\n return {\n platform: this.id,\n action: \"warn\",\n path: configPath,\n detail: `existing ${MCP_ROOT_KEY} in ${configPath} is not an object map; left untouched (back it up / fix it, then re-run)`,\n };\n }\n\n /** Render a normalized ServerDef into Windsurf's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): WindsurfStdioServer | WindsurfRemoteServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n // Windsurf supports ${env:VAR} natively, but AC resolves references to\n // literals at install time (the safe path, same as amazon-q/droid/crush).\n const entry: WindsurfStdioServer = {\n command: resolveEnvRefsDeep(command),\n };\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // http / sse (and any other remote transport) — Windsurf registers a remote\n // URL under `serverUrl` (NOT `url`). NO `type` discriminator, NO `disabled`.\n // `headers` only when the connector's remote server provides them.\n const entry: WindsurfRemoteServer = {\n serverUrl: resolveEnvRefsDeep(server.url ?? \"\"),\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Windsurf has a native ${env:VAR} token, but AC\n * resolves references to literals at install time (the safe path).\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n // ── Hooks (unavailable — Windsurf is mcp-only) ────────────────────────────\n\n installHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Windsurf is mcp-only)\",\n },\n ];\n }\n\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Windsurf is mcp-only)\",\n },\n ];\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n return [\n {\n name: `${this.name}: mcp_config.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(mcpPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`,\n };\n },\n },\n ];\n }\n}\n\nexport const adapter = new WindsurfAdapter();\nexport default adapter;\n"],"mappings":";;;;;;;;;;;;;;;;AA2DA,SAAS,YAAY,gBAAgB;AACrC,SAAS,eAAe;AACxB,SAAS,UAAU,YAAY;AAoB/B,IAAM,OAAmB;AACzB,IAAM,eAAe;AAQrB,IAAM,qBAAqB;AAmBpB,IAAM,kBAAN,cAA8B,YAA+B;AAAA,EACzD,KAAiB;AAAA,EACjB,OAAO;AAAA,EACP,WAAyB;AAAA,EAEzB,eAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQ5C,gBAAgB;AAAA;AAAA;AAAA;AAAA,IAIhB,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,MAAM;AAAA,IACN,cAAc;AAAA;AAAA,IAEd,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,yBAAyB;AAAA;AAAA;AAAA,IAGzB,YAAY,CAAC,SAAS,QAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUnC,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,EAClB;AAAA;AAAA,EAIA,gBAAgB,aAAuC;AACrD,UAAM,UAAU,KAAK,QAAQ,GAAG,YAAY,UAAU;AACtD,UAAM,UAAU,KAAK,SAAS,iBAAiB;AAC/C,UAAM,YAAY,WAAW,OAAO,KAAK,WAAW,OAAO;AAC3D,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX;AAAA,MACA,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,MACnB,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,YACJ,+BAA+B,OAAO,KACtC,yBAAyB,OAAO;AAAA,MACpC,YAAY,YAAY,SAAS;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,MAA8B;AACzC,WAAO,KAAK,QAAQ,GAAG,YAAY,UAAU;AAAA,EAC/C;AAAA,EAEA,oBAAoB,KAA6B;AAC/C,WAAO,KAAK,KAAK,aAAa,GAAG,GAAG,iBAAiB;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB,KAA6B;AAC7C,WAAO,KAAK,oBAAoB,GAAG;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,eAAe,KAA6B;AAClD,WAAO,KAAK,IAAI,YAAY,aAAa,SAAS,oBAAoB;AAAA,EACxE;AAAA;AAAA,EAGQ,eAAe,KAA8B;AACnD,UAAM,IAAI,KAAK,IAAI,YAAY,aAAa,OAAO;AACnD,QAAI,CAAC,WAAW,CAAC,EAAG,QAAO;AAC3B,QAAI;AACF,aAAO,SAAS,CAAC,EAAE,OAAO;AAAA,IAC5B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,iBAAiB,KAA6B;AACpD,UAAM,QAAQ,IAAI,UAAU,UAAU,CAAC,GACpC,IAAI,CAAC,MAAM,EAAE,QAAQ,KAAK,CAAC,EAC3B,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1B,KAAK,MAAM;AACd,WAAO,KAAK,oBAAoB,EAAE,SAAS,YAAY,GAAG,IAAI;AAAA,EAChE;AAAA,EAES,cAAc,KAAqC;AAC1D,UAAM,EAAE,UAAU,IAAI;AACtB,UAAM,UAAU,UAAU,UAAU,CAAC;AACrC,QAAI,UAAU,UAAU,KAAK,EAAE,GAAG,WAAW,OAAO;AAClD,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,uBAAuB,KAAK,EAAE,GAAG,CAAC;AAAA,IACzF;AACA,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,+BAA+B,CAAC;AAAA,IACvF;AAEA,QAAI,IAAI,UAAU,WAAW;AAC3B,aAAO;AAAA,QACL;AAAA,UACE,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR,QACE,MAAM,IAAI,KAAK,kHAEZ,QAAQ,MAAM;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,GAAG,GAAG;AAC5B,aAAO;AAAA,QACL;AAAA,UACE,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR,MAAM,KAAK,IAAI,YAAY,aAAa,OAAO;AAAA,UAC/C,QACE;AAAA,QAEJ;AAAA,MACF;AAAA,IACF;AACA,WAAO,CAAC,KAAK,iBAAiB,KAAK,eAAe,GAAG,GAAG,KAAK,iBAAiB,GAAG,GAAG,IAAI,MAAM,CAAC;AAAA,EACjG;AAAA,EAES,gBAAgB,KAAqC;AAG5D,QAAI,IAAI,UAAU,aAAa,KAAK,eAAe,GAAG,GAAG;AACvD,YAAM,OAAO,KAAK,eAAe,GAAG;AACpC,aAAO;AAAA,QACL,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,MAAM,QAAQ,GAAG,SAAS,IAAI,CAAC,UAAU;AAAA,MAChF;AAAA,IACF;AACA,WAAO,CAAC,KAAK,kBAAkB,KAAK,eAAe,GAAG,GAAG,IAAI,MAAM,CAAC;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBQ,YAAY,KAAqB,MAAsB;AAC7D,UAAM,MACJ,IAAI,UAAU,YACV,KAAK,IAAI,YAAY,aAAa,WAAW,IAC7C,KAAK,QAAQ,GAAG,YAAY,YAAY,kBAAkB;AAChE,WAAO,KAAK,KAAK,GAAG,IAAI,KAAK;AAAA,EAC/B;AAAA;AAAA,EAGQ,SAAS,KAAqB,MAAsB;AAC1D,UAAM,OACJ,IAAI,UAAU,YACV,KAAK,IAAI,YAAY,aAAa,QAAQ,IAC1C,KAAK,QAAQ,GAAG,YAAY,YAAY,QAAQ;AACtD,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB;AAAA;AAAA,EAIS,gBAAgB,KAAqC;AAC5D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,UAAU,IAAI,GAAG,aAAa,OAAO;AACjD,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,iCAAiC,CAAC;AAAA,IACzF;AACA,QAAI,UAAU,SAAS,WAAW,GAAG;AACnC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,iCAAiC,CAAC;AAAA,IACzF;AACA,UAAM,UAA0B,CAAC;AACjC,eAAW,OAAO,UAAU,UAAU;AACpC,YAAM,WAAW,gBAAgB,GAAG;AACpC,cAAQ,KAAK,KAAK,iBAAiB,KAAK,YAAY,KAAK,IAAI,IAAI,GAAG,UAAU,IAAI,MAAM,CAAC;AAIzF,UAAI,SAAS,SAAS,oBAAoB;AACxC,gBAAQ,KAAK;AAAA,UACX,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR,MAAM,KAAK,YAAY,KAAK,IAAI,IAAI;AAAA,UACpC,QACE,aAAa,IAAI,IAAI,QAAQ,SAAS,MAAM,0CACT,kBAAkB;AAAA,QAEzD,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAES,kBAAkB,KAAqC;AAC9D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,SAAS,WAAW,GAAG;AACnC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,iCAAiC,CAAC;AAAA,IACzF;AACA,WAAO,UAAU,SAAS;AAAA,MAAI,CAAC,QAC7B,KAAK,kBAAkB,KAAK,YAAY,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM;AAAA,IACpE;AAAA,EACF;AAAA;AAAA,EAIS,cAAc,KAAqC;AAC1D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,UAAU,IAAI,GAAG,WAAW,OAAO;AAC/C,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,+BAA+B,CAAC;AAAA,IACvF;AACA,QAAI,UAAU,OAAO,WAAW,GAAG;AACjC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,+BAA+B,CAAC;AAAA,IACvF;AACA,UAAM,UAA0B,CAAC;AACjC,eAAW,SAAS,UAAU,QAAQ;AACpC,YAAM,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI;AACzC,cAAQ;AAAA,QACN,KAAK,iBAAiB,KAAK,KAAK,UAAU,GAAG,cAAc,KAAK,GAAG,IAAI,MAAM;AAAA,MAC/E;AACA,iBAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,MAAM,aAAa,CAAC,CAAC,GAAG;AACnE,cAAM,SAAS,KAAK,cAAc,KAAK,GAAG;AAC1C,YAAI,WAAW,MAAM;AACnB,kBAAQ,KAAK;AAAA,YACX,UAAU,KAAK;AAAA,YACf,QAAQ;AAAA,YACR,QAAQ,mBAAmB,GAAG;AAAA,UAChC,CAAC;AACD;AAAA,QACF;AACA,gBAAQ,KAAK,KAAK,iBAAiB,QAAQ,UAAU,IAAI,MAAM,CAAC;AAAA,MAClE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAES,gBAAgB,KAAqC;AAC5D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,OAAO,WAAW,GAAG;AACjC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,+BAA+B,CAAC;AAAA,IACvF;AACA,UAAM,UAA0B,CAAC;AACjC,eAAW,SAAS,UAAU,QAAQ;AACpC,YAAM,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI;AACzC,cAAQ,KAAK,KAAK,kBAAkB,KAAK,KAAK,UAAU,GAAG,IAAI,MAAM,CAAC;AACtE,iBAAW,OAAO,OAAO,KAAK,MAAM,aAAa,CAAC,CAAC,GAAG;AACpD,cAAM,SAAS,KAAK,cAAc,KAAK,GAAG;AAC1C,YAAI,WAAW,KAAM;AACrB,gBAAQ,KAAK,KAAK,kBAAkB,QAAQ,IAAI,MAAM,CAAC;AAAA,MACzD;AACA,cAAQ,KAAK,KAAK,iBAAiB,KAAK,IAAI,MAAM,CAAC;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAIA,cAAc,KAAqC;AACjD,UAAM,EAAE,UAAU,IAAI;AACtB,UAAM,WAAW,UAAU,UAAU,IAAI,GAAG;AAC5C,QAAI,CAAC,UAAU,UAAU,aAAa,OAAO;AAC3C,aAAO;AAAA,QACL;AAAA,UACE,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR,QAAQ,UAAU,SACd,8CACA;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAKA,QAAI,IAAI,UAAU,WAAW;AAC3B,aAAO;AAAA,QACL;AAAA,UACE,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR,QACE;AAAA,QAEJ;AAAA,MACF;AAAA,IACF;AAGA,UAAM,SACJ,YAAY,OAAO,aAAa,WAC5B,EAAE,GAAG,UAAU,QAAQ,GAAG,SAAS,IACnC,UAAU;AAEhB,UAAM,aAAa,KAAK,oBAAoB,GAAG;AAM/C,UAAM,YAAY,KAAK,iBAAiB,UAAU;AAClD,QAAI,UAAW,QAAO,CAAC,SAAS;AAEhC,UAAM,QAAQ,KAAK,kBAAkB,KAAK,MAAM;AAEhD,WAAO;AAAA,MACL,KAAK,mBAAmB,YAAY,cAAc,UAAU,IAAI,OAAO,IAAI,MAAM;AAAA,IACnF;AAAA,EACF;AAAA,EAEA,gBAAgB,KAAqC;AACnD,UAAM,aAAa,KAAK,oBAAoB,GAAG;AAC/C,UAAM,YAAY,KAAK,iBAAiB,UAAU;AAClD,QAAI,UAAW,QAAO,CAAC,SAAS;AAChC,WAAO;AAAA,MACL,KAAK,qBAAqB,YAAY,cAAc,IAAI,UAAU,IAAI,IAAI,MAAM;AAAA,IAClF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,iBAAiB,YAA8C;AACrE,UAAM,MAAM,KAAK,SAAkC,UAAU;AAC7D,QAAI,CAAC,OAAO,EAAE,gBAAgB,KAAM,QAAO;AAC3C,UAAM,OAAO,IAAI,YAAY;AAC7B,QAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;AACrE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,QAAQ,YAAY,YAAY,OAAO,UAAU;AAAA,IACnD;AAAA,EACF;AAAA;AAAA,EAGQ,kBACN,KACA,QAC4C;AAC5C,UAAM,YAAuB,OAAO;AAEpC,QAAI,cAAc,SAAS;AACzB,UAAI,UAAU,OAAO,WAAW;AAChC,UAAI,OAAO,CAAC,GAAI,OAAO,QAAQ,CAAC,CAAE;AAIlC,OAAC,EAAE,SAAS,KAAK,IAAI,kBAAkB,KAAK,QAAQ,KAAK,IAAI,SAAS,IAAI;AAI1E,YAAMA,SAA6B;AAAA,QACjC,SAAS,mBAAmB,OAAO;AAAA,MACrC;AACA,UAAI,KAAK,SAAS,EAAG,CAAAA,OAAM,OAAO,mBAAmB,IAAI;AACzD,YAAM,MAAM,KAAK,UAAU,OAAO,GAAG;AACrC,UAAI,IAAK,CAAAA,OAAM,MAAM;AACrB,aAAOA;AAAA,IACT;AAKA,UAAM,QAA8B;AAAA,MAClC,WAAW,mBAAmB,OAAO,OAAO,EAAE;AAAA,IAChD;AACA,UAAM,UAAU,KAAK,UAAU,OAAO,OAAO;AAC7C,QAAI,QAAS,OAAM,UAAU;AAC7B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,UACN,KACoC;AACpC,QAAI,CAAC,OAAO,OAAO,KAAK,GAAG,EAAE,WAAW,EAAG,QAAO;AAClD,WAAO,mBAAmB,EAAE,GAAG,IAAI,CAAC;AAAA,EACtC;AAAA;AAAA,EAIA,aAAa,MAAsC;AACjD,WAAO;AAAA,MACL;AAAA,QACE,UAAU,KAAK;AAAA,QACf,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAe,MAAsC;AACnD,WAAO;AAAA,MACL;AAAA,QACE,UAAU,KAAK;AAAA,QACf,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAIS,gBAAgB,KAA6C;AACpE,UAAM,UAAU,KAAK,oBAAoB,GAAG;AAC5C,UAAM,cAAc,IAAI,UAAU;AAClC,WAAO;AAAA,MACL;AAAA,QACE,MAAM,GAAG,KAAK,IAAI;AAAA,QAClB,OAAO,MACL,WAAW,OAAO,IACd,EAAE,QAAQ,MAAM,QAAQ,QAAQ,IAChC,EAAE,QAAQ,QAAQ,QAAQ,cAAc,OAAO,GAAG;AAAA,MAC1D;AAAA,MACA;AAAA,QACE,MAAM,GAAG,KAAK,IAAI;AAAA,QAClB,OAAO,MAAM;AACX,cAAI,CAAC,IAAI,UAAU,QAAQ;AACzB,mBAAO,EAAE,QAAQ,MAAM,QAAQ,yBAAyB;AAAA,UAC1D;AACA,gBAAM,MAAM,KAAK,SAAmD,OAAO;AAC3E,gBAAM,SAAS,MAAM,YAAY;AACjC,cAAI,CAAC,OAAO,CAAC,QAAQ;AACnB,mBAAO,EAAE,QAAQ,QAAQ,QAAQ,MAAM,YAAY,OAAO,OAAO,GAAG;AAAA,UACtE;AACA,iBAAO,eAAe,SAClB,EAAE,QAAQ,MAAM,QAAQ,GAAG,YAAY,IAAI,WAAW,WAAW,IACjE;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ,MAAM,YAAY,IAAI,WAAW,OAAO,OAAO;AAAA,UACzD;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,UAAU,IAAI,gBAAgB;AAC3C,IAAO,mBAAQ;","names":["entry"]}