dsh-plugin-capabilities 0.1.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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/agents.ts", "../node_modules/smol-toml/dist/date.js", "../node_modules/smol-toml/dist/error.js", "../node_modules/smol-toml/dist/util.js", "../node_modules/smol-toml/dist/primitive.js", "../node_modules/smol-toml/dist/extract.js", "../node_modules/smol-toml/dist/struct.js", "../node_modules/smol-toml/dist/parse.js", "../src/profile.ts", "../src/http.ts", "../src/skills.ts", "../src/mcp.ts", "../src/routes.ts", "../src/index.ts"],
4
+ "sourcesContent": ["/**\n * Foreign-agent config readers: MCP servers from Claude Code (~/.claude.json,\n * ~/.claude/settings.json) and Codex (~/.codex/config.toml). Pure reads of\n * well-known paths; anything missing or malformed yields an empty list.\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { parse as parseToml } from 'smol-toml'\nimport type { McpTransport } from './mcp.ts'\n\n/** One MCP server discovered in a foreign agent's config. */\nexport interface ImportedServer {\n agent: 'claude-code' | 'codex'\n name: string\n transport: McpTransport\n command?: string\n args?: string[]\n env?: Record<string, string>\n url?: string\n headers?: Record<string, string>\n}\n\n/** Keep only string-valued entries of a record (configs may hold numbers). */\nfunction stringEntries(value: unknown): Record<string, string> | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n const out: Record<string, string> = {}\n for (const [key, entry] of Object.entries(value)) {\n if (typeof entry === 'string') out[key] = entry\n }\n return Object.keys(out).length > 0 ? out : undefined\n}\n\nfunction stringArray(value: unknown): string[] | undefined {\n if (!Array.isArray(value)) return undefined\n const out = value.filter((entry): entry is string => typeof entry === 'string')\n return out.length > 0 ? out : undefined\n}\n\n/** Map one Claude mcpServers entry; returns null for unsupported shapes (sse). */\nfunction mapClaudeEntry(name: string, entry: unknown): ImportedServer | null {\n if (typeof entry !== 'object' || entry === null) return null\n const record = entry as Record<string, unknown>\n const type = typeof record.type === 'string' ? record.type : 'stdio'\n if (type === 'stdio' || (type === 'stdio' && record.command !== undefined)) {\n if (typeof record.command !== 'string' || record.command === '') return null\n return {\n agent: 'claude-code', name, transport: 'stdio',\n command: record.command,\n args: stringArray(record.args),\n env: stringEntries(record.env),\n }\n }\n if (type === 'http' || type === 'streamable-http') {\n if (typeof record.url !== 'string' || record.url === '') return null\n return {\n agent: 'claude-code', name, transport: 'streamable-http',\n url: record.url,\n headers: stringEntries(record.headers),\n }\n }\n // 'sse' and anything else: dsh's mcp-client speaks stdio + streamable-http only.\n return null\n}\n\n/** MCP servers from Claude Code's user-scope config files. */\nexport function scanClaudeMcp(home: string = homedir()): ImportedServer[] {\n const merged: Record<string, unknown> = {}\n for (const file of [join(home, '.claude', 'settings.json'), join(home, '.claude.json')]) {\n if (!existsSync(file)) continue\n try {\n const parsed = JSON.parse(readFileSync(file, 'utf8')) as { mcpServers?: unknown }\n if (typeof parsed.mcpServers === 'object' && parsed.mcpServers !== null) {\n Object.assign(merged, parsed.mcpServers)\n }\n } catch {\n // Broken or partial config: skip the file, keep earlier merges.\n }\n }\n const out: ImportedServer[] = []\n for (const [name, entry] of Object.entries(merged)) {\n const mapped = mapClaudeEntry(name, entry)\n if (mapped !== null) out.push(mapped)\n }\n return out\n}\n\n/** MCP servers from Codex's config.toml ([mcp_servers.<name>] tables). */\nexport function scanCodexMcp(home: string = homedir()): ImportedServer[] {\n const file = join(home, '.codex', 'config.toml')\n if (!existsSync(file)) return []\n let root: Record<string, unknown>\n try {\n root = parseToml(readFileSync(file, 'utf8')) as Record<string, unknown>\n } catch {\n return []\n }\n const table = root.mcp_servers\n if (typeof table !== 'object' || table === null) return []\n const out: ImportedServer[] = []\n for (const [name, entry] of Object.entries(table)) {\n if (typeof entry !== 'object' || entry === null) continue\n const record = entry as Record<string, unknown>\n if (typeof record.command === 'string' && record.command !== '') {\n out.push({\n agent: 'codex', name, transport: 'stdio',\n command: record.command,\n args: stringArray(record.args),\n env: stringEntries(record.env),\n })\n } else if (typeof record.url === 'string' && record.url !== '') {\n out.push({ agent: 'codex', name, transport: 'streamable-http', url: record.url })\n }\n }\n return out\n}\n\n/** All foreign-agent MCP servers, deduplicated by (agent, name). */\nexport function scanAllMcp(home: string = homedir()): ImportedServer[] {\n const seen = new Set<string>()\n return [...scanClaudeMcp(home), ...scanCodexMcp(home)]\n .filter(server => {\n const key = `${server.agent}/${server.name}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\n/** Other agents' skill roots that exist on this machine. */\nexport function agentSkillRoots(home: string = homedir()): string[] {\n return [join(home, '.claude', 'skills'), join(home, '.codex', 'skills')]\n .filter(path => existsSync(path))\n}\n", "/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nlet DATE_TIME_RE = /^(\\d{4}-\\d{2}-\\d{2})?[T ]?(?:(\\d{2}):\\d{2}(?::\\d{2}(?:\\.\\d+)?)?)?(Z|[-+]\\d{2}:\\d{2})?$/i;\nexport class TomlDate extends Date {\n #hasDate = false;\n #hasTime = false;\n #offset = null;\n constructor(date) {\n let hasDate = true;\n let hasTime = true;\n let offset = 'Z';\n if (typeof date === 'string') {\n let match = date.match(DATE_TIME_RE);\n if (match) {\n if (!match[1]) {\n hasDate = false;\n date = `0000-01-01T${date}`;\n }\n hasTime = !!match[2];\n // Make sure to use T instead of a space. Breaks in case of extreme values otherwise.\n hasTime && date[10] === ' ' && (date = date.replace(' ', 'T'));\n // Do not allow rollover hours.\n if (match[2] && +match[2] > 23) {\n date = '';\n }\n else {\n offset = match[3] || null;\n date = date.toUpperCase();\n if (!offset && hasTime)\n date += 'Z';\n }\n }\n else {\n date = '';\n }\n }\n super(date);\n if (!isNaN(this.getTime())) {\n this.#hasDate = hasDate;\n this.#hasTime = hasTime;\n this.#offset = offset;\n }\n }\n isDateTime() {\n return this.#hasDate && this.#hasTime;\n }\n isLocal() {\n return !this.#hasDate || !this.#hasTime || !this.#offset;\n }\n isDate() {\n return this.#hasDate && !this.#hasTime;\n }\n isTime() {\n return this.#hasTime && !this.#hasDate;\n }\n isValid() {\n return this.#hasDate || this.#hasTime;\n }\n toISOString() {\n let iso = super.toISOString();\n // Local Date\n if (this.isDate())\n return iso.slice(0, 10);\n // Local Time\n if (this.isTime())\n return iso.slice(11, 23);\n // Local DateTime\n if (this.#offset === null)\n return iso.slice(0, -1);\n // Offset DateTime\n if (this.#offset === 'Z')\n return iso;\n // This part is quite annoying: JS strips the original timezone from the ISO string representation\n // Instead of using a \"modified\" date and \"Z\", we restore the representation \"as authored\"\n let offset = (+(this.#offset.slice(1, 3)) * 60) + +(this.#offset.slice(4, 6));\n offset = this.#offset[0] === '-' ? offset : -offset;\n let offsetDate = new Date(this.getTime() - (offset * 60e3));\n return offsetDate.toISOString().slice(0, -1) + this.#offset;\n }\n static wrapAsOffsetDateTime(jsDate, offset = 'Z') {\n let date = new TomlDate(jsDate);\n date.#offset = offset;\n return date;\n }\n static wrapAsLocalDateTime(jsDate) {\n let date = new TomlDate(jsDate);\n date.#offset = null;\n return date;\n }\n static wrapAsLocalDate(jsDate) {\n let date = new TomlDate(jsDate);\n date.#hasTime = false;\n date.#offset = null;\n return date;\n }\n static wrapAsLocalTime(jsDate) {\n let date = new TomlDate(jsDate);\n date.#hasDate = false;\n date.#offset = null;\n return date;\n }\n}\n", "/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nfunction getLineColFromPtr(string, ptr) {\n let lines = string.slice(0, ptr).split(/\\r\\n|\\n|\\r/g);\n return [lines.length, lines.pop().length + 1];\n}\nfunction makeCodeBlock(string, line, column) {\n let lines = string.split(/\\r\\n|\\n|\\r/g);\n let codeblock = '';\n let numberLen = (Math.log10(line + 1) | 0) + 1;\n for (let i = line - 1; i <= line + 1; i++) {\n let l = lines[i - 1];\n if (!l)\n continue;\n codeblock += i.toString().padEnd(numberLen, ' ');\n codeblock += ': ';\n codeblock += l;\n codeblock += '\\n';\n if (i === line) {\n codeblock += ' '.repeat(numberLen + column + 2);\n codeblock += '^\\n';\n }\n }\n return codeblock;\n}\nexport class TomlError extends Error {\n line;\n column;\n codeblock;\n constructor(message, options) {\n const [line, column] = getLineColFromPtr(options.toml, options.ptr);\n const codeblock = makeCodeBlock(options.toml, line, column);\n super(`Invalid TOML document: ${message}\\n\\n${codeblock}`, options);\n this.line = line;\n this.column = column;\n this.codeblock = codeblock;\n }\n}\n", "/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nimport { TomlError } from './error.js';\n/** @internal */\nexport function indexOfNewline(str, start = 0) {\n let idx = str.indexOf('\\n', start);\n if (str.charCodeAt(idx - 1) === 0xd /* \\r */)\n idx--;\n return idx;\n}\n/** @internal */\nexport function skipComment(ctx) {\n for (; ctx.p < ctx.s.length; ctx.p++) {\n let c = ctx.s.charCodeAt(ctx.p);\n if (c === 0xa /* \\n */)\n break;\n if (c === 0xd /* \\r */ && ctx.s.charCodeAt(ctx.p + 1) === 0xa /* \\n */) {\n ctx.p++;\n break;\n }\n if ((c < 0x20 && c !== 0x9 /* \\t */) || c === 0x7f) {\n throw new TomlError('control characters are not allowed in comments', {\n toml: ctx.s,\n ptr: ctx.p,\n });\n }\n }\n}\n/** @internal */\nexport function skipVoid(ctx, banNewLines, banComments) {\n let c;\n while (1) {\n while ((c = ctx.s.charCodeAt(ctx.p)) === 0x20 ||\n c === 0x9 /* \\t */ ||\n (!banNewLines &&\n (c === 0xa /* \\n */ || (c === 0xd /* \\r */ && ctx.s.charCodeAt(ctx.p + 1) === 0xa /* \\n */))))\n ctx.p++;\n if (banComments || c !== 0x23 /* # */)\n break;\n skipComment(ctx);\n }\n}\n/** @internal */\nexport function skipUntil(ctx, sep, end) {\n let ptr = ctx.p;\n if (!end) {\n ptr = indexOfNewline(ctx.s, ptr);\n ctx.p = ptr < 0 ? ctx.s.length : ptr;\n return;\n }\n for (; ctx.p < ctx.s.length; ctx.p++) {\n let c = ctx.s.charCodeAt(ctx.p);\n if (c === 0x23 /* # */) {\n skipComment(ctx);\n }\n else if (c === end || c === sep) {\n return;\n }\n }\n throw new TomlError('cannot find end of structure', {\n toml: ctx.s,\n ptr,\n });\n}\n", "/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nimport { TomlDate } from './date.js';\nimport { TomlError } from './error.js';\nimport { skipComment, skipUntil } from './util.js';\n// let CTRL_REGEX = /[\\x00-\\x08\\x0f-\\x1f\\x7f]/\nlet INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\\d(_?\\d)*))$/;\nlet FLOAT_REGEX = /^[+-]?\\d(_?\\d)*(\\.\\d(_?\\d)*)?([eE][+-]?\\d(_?\\d)*)?$/;\nlet LEADING_ZERO = /^[+-]?0[0-9_]/;\n/** @internal */\nexport function parseString(ctx) {\n let start = ctx.p;\n let c = ctx.s.charCodeAt(ctx.p++);\n let first = c;\n let isLiteral = c === 0x27; /* ' */\n let isMultiline = c === ctx.s.charCodeAt(ctx.p) && c === ctx.s.charCodeAt(ctx.p + 1);\n if (isMultiline) {\n // Trim initial newline\n if ((c = ctx.s.charCodeAt(ctx.p += 2)) === 0xa /* \\n */)\n ctx.p++;\n else if (c === 0xd /* \\r */ && ctx.s.charCodeAt(ctx.p + 1) === 0xa /* \\n */)\n ctx.p += 2;\n }\n /*\n The fast path does not seem to bring significant performance gains, so it's commented out.\n Kept for reference and/or future fafoing.\n\n Without: spec 5.08 \u00B5s/iter 3.88 ipc (99.44% cache) 23.90 branch misses 28.61k cycles 111.01k instructions\n 5MB 115.73 ms/iter 2.51 ipc (98.36% cache) 3.12M branch misses 619.30M cycles 1.56G instructions\n\n With: spec 5.09 \u00B5s/iter 3.90 ipc (99.46% cache) 24.42 branch misses 28.57k cycles 111.49k instructions\n 5MB 113.89 ms/iter 2.47 ipc (98.38% cache) 3.12M branch misses 611.94M cycles 1.51G instructions\n\n if (c === \"'\") {\n // Literal strings fast path - no transform needs to occur; just grab the str and that's it\n let endPtr = str.indexOf(isMultiline ? \"'''\" : \"'\", ptr)\n if (endPtr < 0) {\n throw new TomlError(\"unfinished string literal\", { toml: str, ptr })\n }\n\n if (isMultiline) {\n // If the string ends with 4-5 quotes, then the first 1-2 are part of the string\n if (str[endPtr + 3] === \"'\") endPtr++\n if (str[endPtr + 3] === \"'\") endPtr++\n }\n\n let string = str.slice(ptr, endPtr)\n if (CTRL_REGEX.test(string)) {\n let match = string.match(CTRL_REGEX)!\n throw new TomlError('control characters are not allowed in strings', { toml: str, ptr: ptr + (match.index ?? 0) })\n }\n return [string, endPtr + (isMultiline ? 3 : 1)]\n }\n */\n let parsed = '';\n let sliceStart = ctx.p;\n // states:\n // 0 - decoding\n // 1 - decoding escape\n // 2 - whitespace escape (no newline encountered yet, must fail on non-whitespace)\n // 3 - whitespace escape (newline encountered, allowed to transition back to normal decode)\n let state = 0;\n for (; ctx.p < ctx.s.length; ctx.p++) {\n c = ctx.s.charCodeAt(ctx.p);\n // Deal with newlines first, since that simplifies control character checking and handling across all states\n if (isMultiline && (c === 0xa /* \\n */ || (c === 0xd /* \\r */ && ctx.s.charCodeAt(ctx.p + 1) === 0xa /* \\n */))) {\n state = state && 3;\n }\n // Control characters are banned in TOML, so we throw an error if we encounter them\n else if ((c < 0x20 && c !== 0x9 /* \\t */) || c === 0x7f) {\n throw new TomlError('control characters are not allowed in strings', {\n toml: ctx.s,\n ptr: ctx.p,\n });\n }\n // The string might terminate while we're parsing through a newline escape.\n // It must have encountered a newline; otherwise, it'll simply fail in another branch.\n else if ((!state || state === 3) && c === first && (!isMultiline || (ctx.s.charCodeAt(ctx.p + 1) === first && ctx.s.charCodeAt(ctx.p + 2) === first))) {\n if (isMultiline) {\n // If the string ends with 4-5 quotes, then the first 1-2 are part of the string\n if (ctx.s.charCodeAt(ctx.p + 3) === first)\n ctx.p++;\n if (ctx.s.charCodeAt(ctx.p + 3) === first)\n ctx.p++;\n }\n // If we're in a newline escape still, then there's nothing to add.\n if (!state)\n parsed += ctx.s.slice(sliceStart, ctx.p);\n ctx.p += isMultiline ? 3 : 1;\n return parsed;\n }\n else if (!state) {\n if (!isLiteral && c === 0x5c /* \\ */) {\n parsed += ctx.s.slice(sliceStart, (sliceStart = ctx.p));\n state = 1;\n }\n }\n else if (state === 1) {\n if (c === 0x78 /* x */ || c === 0x75 /* u */ || c === 0x55 /* U */) { // Unicode escape\n let value = 0;\n let len = c === 0x78 /* x */ ? 2 : c === 0x75 /* u */ ? 4 : 8;\n for (let j = 0; j < len; j++, ctx.p++) {\n let hex = ctx.s.charCodeAt(ctx.p + 1);\n let digit = \n /* 0-9 */ hex >= 0x30 && hex <= 0x39 ? hex - 0x30 :\n /* A-F */ hex >= 0x41 && hex <= 0x46 ? hex - 0x41 + 10 :\n /* a-f */ hex >= 0x61 && hex <= 0x66 ? hex - 0x61 + 10 : -1;\n if (digit < 0)\n throw new TomlError('invalid non-hex character in unicode escape', { toml: ctx.s, ptr: ctx.p + 1 });\n value = (value << 4) | digit;\n }\n // Because JS does bitwise on signed 32bit integers, all 0xfzzzzzzz values are actually seen as negative\n if (value < 0 || value > 0x10ffff || (value >= 0xd800 && value <= 0xdfff)) {\n throw new TomlError('invalid unicode escape', { toml: ctx.s, ptr: ctx.p });\n }\n parsed += String.fromCodePoint(value);\n sliceStart = ctx.p + 1;\n state = 0;\n }\n else if (c === 0x20 || c === 0x9 /* \\t */) { // If it was a newline, it'd have been handled earlier\n state = 2;\n }\n else {\n if (c === 0x62 /* b */)\n parsed += '\\b';\n else if (c === 0x74 /* t */)\n parsed += '\\t';\n else if (c === 0x6e /* n */)\n parsed += '\\n';\n else if (c === 0x66 /* f */)\n parsed += '\\f';\n else if (c === 0x72 /* r */)\n parsed += '\\r';\n else if (c === 0x65 /* e */)\n parsed += '\\x1b';\n else if (c === 0x22 /* \" */)\n parsed += '\"';\n else if (c === 0x5c /* \\ */)\n parsed += '\\\\';\n else\n throw new TomlError('unrecognized escape sequence', { toml: ctx.s, ptr: ctx.p });\n sliceStart = ctx.p + 1;\n state = 0;\n }\n }\n else if (c !== 0x20 && c !== 0x9 /* \\t */) {\n if (state === 2) {\n throw new TomlError('invalid escape: only line-ending whitespace may be escaped', {\n toml: ctx.s,\n ptr: sliceStart,\n });\n }\n // State cannot be zero, or we'd have branched earlier already.\n // If it's a backslash, immediately transition to the escape state so it can be processed.\n state = !isLiteral && c === 0x5c /* \\ */ ? 1 : 0;\n sliceStart = ctx.p;\n }\n }\n throw new TomlError('unfinished string', { toml: ctx.s, ptr: start });\n}\nfunction sliceAndTrimEndOf(ctx, start, end) {\n let value = ctx.s.slice(start, end);\n let commentIdx = value.indexOf('#');\n if (commentIdx > 0) {\n // The call to skipComment allows to \"validate\" the comment\n // (absence of control characters)\n skipComment({ s: value, p: commentIdx, d: 0 });\n value = value.slice(0, commentIdx);\n }\n return value.trimEnd();\n}\n/** @internal */\nexport function parseValue(ctx, integersAsBigInt, end) {\n let ptr = ctx.p;\n let err = { toml: ctx.s, ptr };\n skipUntil(ctx, 0x2c /* , */, end);\n let value = sliceAndTrimEndOf(ctx, ptr, ctx.p);\n if (!value)\n throw new TomlError('incomplete declaration: value expected', err);\n if (value === '-inf')\n return -Infinity;\n if (value === 'inf' || value === '+inf')\n return Infinity;\n if (value === 'nan' || value === '+nan' || value === '-nan')\n return NaN;\n // Avoid FP representation of -0\n if (value === '-0')\n return integersAsBigInt ? 0n : 0;\n // Numbers\n let isInt = INT_REGEX.test(value);\n if (isInt || FLOAT_REGEX.test(value)) {\n if (LEADING_ZERO.test(value)) {\n throw new TomlError('leading zeroes are not allowed', err);\n }\n value = value.replace(/_/g, '');\n let numeric = +value;\n if (isNaN(numeric)) {\n throw new TomlError('invalid number', err);\n }\n if (isInt) {\n if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {\n throw new TomlError('integer value cannot be represented losslessly', err);\n }\n if (isInt || integersAsBigInt === true)\n numeric = BigInt(value);\n }\n return numeric;\n }\n const date = new TomlDate(value);\n if (!date.isValid())\n throw new TomlError('invalid value', err);\n return date;\n}\n", "/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nimport { parseString, parseValue } from './primitive.js';\nimport { parseArray, parseInlineTable } from './struct.js';\nimport { TomlError } from './error.js';\n/** @internal */\nexport function extractValue(ctx, end, integersAsBigInt) {\n let ptr = ctx.p;\n let c = ctx.s.charCodeAt(ptr);\n // Structs\n if (c === 0x5b /* [ */ || c === 0x7b /* { */) {\n if (!ctx.d--) {\n throw new TomlError('document contains excessively nested structures. aborting.', {\n toml: ctx.s,\n ptr,\n });\n }\n let value = c === 0x5b /* [ */\n ? parseArray(ctx, integersAsBigInt)\n : parseInlineTable(ctx, integersAsBigInt);\n ctx.d++;\n return value;\n }\n // Strings\n if (c === 0x22 /* \" */ || c === 0x27 /* ' */) {\n return parseString(ctx);\n }\n // Booleans\n // We can fast-path because the first character is enough to know the only possible value\n if (c === 0x74 /* t */) { // Only possible valid value is `true`\n if (ctx.s.charCodeAt(++ctx.p) !== 0x72 || ctx.s.charCodeAt(++ctx.p) !== 0x75 || ctx.s.charCodeAt(++ctx.p) !== 0x65)\n throw new TomlError('invalid value', { toml: ctx.s, ptr });\n ctx.p++;\n return true;\n }\n if (c === 0x66 /* f */) { // Only possible valid value is `false`\n if (ctx.s.charCodeAt(++ctx.p) !== 0x61 || ctx.s.charCodeAt(++ctx.p) !== 0x6c || ctx.s.charCodeAt(++ctx.p) !== 0x73 || ctx.s.charCodeAt(++ctx.p) !== 0x65)\n throw new TomlError('invalid value', { toml: ctx.s, ptr });\n ctx.p++;\n return false;\n }\n // Legacy logic for numbers and dates. Slow and needs to be rewritten.\n return parseValue(ctx, integersAsBigInt, end);\n}\n", "/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nimport { parseString } from './primitive.js';\nimport { extractValue } from './extract.js';\nimport { indexOfNewline, skipVoid } from './util.js';\nimport { TomlError } from './error.js';\nlet KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \\t]*$/;\n/** @internal */\nexport function parseKey(ctx, end = '=') {\n let start = ctx.p;\n let dot = start - 1;\n let parsed = [];\n let endPtr = ctx.s.indexOf(end, start);\n if (endPtr < 0) {\n throw new TomlError('incomplete key-value: cannot find end of key', {\n toml: ctx.s,\n ptr: start,\n });\n }\n do {\n let c = ctx.s.charCodeAt(ctx.p = ++dot);\n // If it's whitespace, ignore\n if (c !== 0x20 && c !== 0x9 /* \\t */) {\n // If it's a string\n if (c === 0x22 /* \" */ || c === 0x27 /* ' */) {\n if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2)) {\n throw new TomlError('multiline strings are not allowed in keys', {\n toml: ctx.s,\n ptr: ctx.p,\n });\n }\n let part = parseString(ctx);\n dot = ctx.s.indexOf('.', ctx.p);\n let strEnd = ctx.s.slice(ctx.p, dot < 0 || dot > endPtr ? endPtr : dot);\n let newLine = indexOfNewline(strEnd);\n if (newLine > -1) {\n throw new TomlError('newlines are not allowed in keys', {\n toml: ctx.s,\n ptr: newLine,\n });\n }\n if (strEnd.trimStart()) {\n throw new TomlError('found extra tokens after the string part', {\n toml: ctx.s,\n ptr: ctx.p,\n });\n }\n if (endPtr < ctx.p) {\n endPtr = ctx.s.indexOf(end, ctx.p);\n if (endPtr < 0) {\n throw new TomlError('incomplete key-value: cannot find end of key', {\n toml: ctx.s,\n ptr: start,\n });\n }\n }\n parsed.push(part);\n }\n else {\n // Normal raw key part consumption and validation\n dot = ctx.s.indexOf('.', ctx.p);\n let part = ctx.s.slice(ctx.p, dot < 0 || dot > endPtr ? endPtr : dot);\n if (!KEY_PART_RE.test(part)) {\n throw new TomlError('only letter, numbers, dashes and underscores are allowed in keys', {\n toml: ctx.s,\n ptr: ctx.p,\n });\n }\n parsed.push(part.trimEnd());\n }\n }\n // Until there's no more dot\n } while (dot + 1 && dot < endPtr);\n ctx.p = endPtr + 1;\n skipVoid(ctx, true, true);\n return parsed;\n}\n/** @internal */\nexport function parseInlineTable(ctx, integersAsBigInt) {\n let res = {};\n let seen = new Set();\n let c;\n ctx.p++;\n while (ctx.p < ctx.s.length) {\n skipVoid(ctx);\n if ((c = ctx.s.charCodeAt(ctx.p)) === 0x7d /* } */) {\n ctx.p++;\n return res;\n }\n let k;\n let t = res;\n let hasOwn = false;\n let p = ctx.p;\n let key = parseKey(ctx);\n for (let i = 0; i < key.length; i++) {\n if (i)\n t = hasOwn ? t[k] : (t[k] = {});\n k = key[i];\n if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== 'object' || seen.has(t[k]))) {\n throw new TomlError('trying to redefine an already defined value', {\n toml: ctx.s,\n ptr: p,\n });\n }\n if (!hasOwn && k === '__proto__') {\n Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });\n }\n }\n if (hasOwn) {\n throw new TomlError('trying to redefine an already defined value', {\n toml: ctx.s,\n ptr: ctx.p,\n });\n }\n let value = extractValue(ctx, 0x7d /* } */, integersAsBigInt);\n seen.add(t[k] = value);\n skipVoid(ctx);\n if ((c = ctx.s.charCodeAt(ctx.p++)) === 0x7d /* } */) {\n return res;\n }\n if (c !== 0x2c /* , */) {\n throw new TomlError('expected comma or end of structure', { toml: ctx.s, ptr: ctx.p - 1 });\n }\n }\n throw new TomlError('unfinished table encountered', {\n toml: ctx.s,\n ptr: ctx.p,\n });\n}\n/** @internal */\nexport function parseArray(ctx, integersAsBigInt) {\n let res = [];\n let c;\n ctx.p++;\n while (ctx.p < ctx.s.length) {\n skipVoid(ctx);\n if ((c = ctx.s.charCodeAt(ctx.p)) === 0x5d /* ] */) {\n ctx.p++;\n return res;\n }\n res.push(extractValue(ctx, 0x5d /* ] */, integersAsBigInt));\n skipVoid(ctx);\n if ((c = ctx.s.charCodeAt(ctx.p++)) === 0x5d /* ] */) {\n return res;\n }\n if (c !== 0x2c /* , */) {\n throw new TomlError('expected comma or end of structure', { toml: ctx.s, ptr: ctx.p - 1 });\n }\n }\n throw new TomlError('unfinished array encountered', {\n toml: ctx.s,\n ptr: ctx.p,\n });\n}\n", "/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nimport { parseKey } from './struct.js';\nimport { extractValue } from './extract.js';\nimport { skipVoid } from './util.js';\nimport { TomlError } from './error.js';\nfunction peekTable(key, table, meta, type) {\n let t = table;\n let m = meta;\n let k;\n let hasOwn = false;\n let state;\n for (let i = 0; i < key.length; i++) {\n if (i) {\n t = hasOwn ? t[k] : (t[k] = {});\n m = (state = m[k]).c;\n if (type === 0 /* Type.DOTTED */ && (state.t === 1 /* Type.EXPLICIT */ || state.t === 2 /* Type.ARRAY */)) {\n return null;\n }\n if (state.t === 2 /* Type.ARRAY */) {\n let l = t.length - 1;\n t = t[l];\n m = m[l].c;\n }\n }\n k = key[i];\n if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 /* Type.DOTTED */ && m[k]?.d) {\n return null;\n }\n if (!hasOwn) {\n if (k === '__proto__') {\n Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });\n Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });\n }\n m[k] = {\n t: i < key.length - 1 && type === 2 /* Type.ARRAY */\n ? 3 /* Type.ARRAY_DOTTED */ : type,\n d: false,\n i: 0,\n c: {},\n };\n }\n }\n state = m[k];\n if (state.t !== type && !(type === 1 /* Type.EXPLICIT */ && state.t === 3 /* Type.ARRAY_DOTTED */)) {\n // Bad key type!\n return null;\n }\n if (type === 2 /* Type.ARRAY */) {\n if (!state.d) {\n state.d = true;\n t[k] = [];\n }\n t[k].push(t = {});\n state.c[state.i++] = (state = { t: 1 /* Type.EXPLICIT */, d: false, i: 0, c: {} });\n }\n if (state.d) {\n // Redefining a table!\n return null;\n }\n state.d = true;\n if (type === 1 /* Type.EXPLICIT */) {\n t = hasOwn ? t[k] : (t[k] = {});\n }\n else if (type === 0 /* Type.DOTTED */ && hasOwn) {\n return null;\n }\n return [k, t, state.c];\n}\nexport function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) {\n let ctx = { s: toml, p: 0, d: maxDepth };\n let res = {};\n let meta = {};\n let tmp;\n let tbl = res;\n let m = meta;\n skipVoid(ctx);\n while (ctx.p < toml.length) {\n if (toml.charCodeAt(ctx.p) === 0x5b /* [ */) {\n let isTableArray = toml.charCodeAt(++ctx.p) === 0x5b; /* [ */\n tmp = ctx.p += +isTableArray;\n let k = parseKey(ctx, ']');\n if (isTableArray) {\n if (toml.charCodeAt(ctx.p - 1) !== 0x5d /* ] */) {\n throw new TomlError('expected end of table declaration', {\n toml: toml,\n ptr: ctx.p - 1,\n });\n }\n ctx.p++;\n }\n let p = peekTable(k, res, meta, isTableArray ? 2 /* Type.ARRAY */ : 1 /* Type.EXPLICIT */);\n if (!p) {\n throw new TomlError('trying to redefine an already defined table or value', {\n toml: toml,\n ptr: tmp,\n });\n }\n m = p[2];\n tbl = p[1];\n }\n else {\n tmp = ctx.p;\n let k = parseKey(ctx);\n let p = peekTable(k, tbl, m, 0 /* Type.DOTTED */);\n if (!p) {\n throw new TomlError('trying to redefine an already defined table or value', {\n toml: toml,\n ptr: tmp,\n });\n }\n p[1][p[0]] = extractValue(ctx, void 0, integersAsBigInt);\n }\n skipVoid(ctx, true);\n if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 0xa /* \\n */ && tmp !== 0xd /* \\r */) {\n throw new TomlError('each key-value declaration must be followed by an end-of-line', {\n toml: toml,\n ptr: ctx.p,\n });\n }\n skipVoid(ctx);\n }\n return res;\n}\n", "/** Profile discovery (pure reads; same contract as dsh-plugin-install). */\n\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\n/** Profile that boots this UI: `--profile <name>` on the CLI invocation. */\nexport function argvProfile(argv: readonly string[] = process.argv): string | undefined {\n const flag = argv.indexOf('--profile')\n if (flag !== -1 && flag + 1 < argv.length && !argv[flag + 1].startsWith('-')) return argv[flag + 1]\n return undefined\n}\n\n/** Directory of a profile under DSH_HOME (default `~/.dsh`). */\nexport function profileDir(profile: string, dshHome: string | undefined = process.env.DSH_HOME): string {\n const home = dshHome ?? join(homedir(), '.dsh')\n return join(home, 'profiles', profile)\n}\n", "/** HTTP helpers: JSON body reading, same-origin check, JSON responses. */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http'\n\n/** Read and JSON-parse a request body, bounded to 1 MiB (skill bodies live here). */\nexport async function readJsonBody(request: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = []\n let received = 0\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n received += buffer.length\n if (received > 1024 * 1024) throw new Error('request body too large')\n chunks.push(buffer)\n }\n return JSON.parse(Buffer.concat(chunks).toString('utf8'))\n}\n\n/**\n * True when the request is a same-origin POST a browser page could have made.\n * CSRF fence (the loopback server already trusts its local peer for reads).\n */\nexport function sameOrigin(request: IncomingMessage): boolean {\n const origin = request.headers.origin\n const host = request.headers.host\n if (origin === undefined || host === undefined) return false\n try {\n const parsed = new URL(origin)\n return (parsed.protocol === 'http:' || parsed.protocol === 'https:') && parsed.host === host\n } catch {\n return false\n }\n}\n\n/** Write a JSON response. */\nexport function sendJson(response: ServerResponse, status: number, body: unknown): void {\n const payload = JSON.stringify(body)\n response.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'no-store',\n })\n response.end(payload)\n}\n", "/**\n * Skill catalog plumbing: frontmatter serialization for user-root SKILL.md\n * files plus create/update/delete against `$DSH_HOME/skills`. Discovery is the\n * host's business \u2014 the filesystem provider watches the directory, so writes\n * land in the catalog without any restart.\n */\n\nimport { existsSync, mkdirSync, rmSync, statSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\n/** Host skill name grammar (dsh-skill's SKILL_NAME). */\nexport const SKILL_NAME_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n\n/** One skill write request from the browser. */\nexport interface SkillInput {\n name: string\n description: string\n whenToUse?: string\n modelInvocable: boolean\n userInvocable: boolean\n content: string\n}\n\n/** The user-owned skill root this plugin writes into (provider rank 400). */\nexport function userSkillsDir(dshHome: string | undefined = process.env.DSH_HOME): string {\n return join(dshHome ?? join(homedir(), '.dsh'), 'skills')\n}\n\n/** YAML double-quoted scalar (JSON string syntax is valid YAML 1.2). */\nfunction quote(value: string): string {\n return JSON.stringify(value)\n}\n\n/** Frontmatter + body for one skill file. Policy keys only when non-default. */\nexport function serializeSkill(input: SkillInput): string {\n const lines = [\n `name: ${input.name}`,\n `description: ${quote(input.description)}`,\n ]\n if (input.whenToUse !== undefined && input.whenToUse !== '') lines.push(`whenToUse: ${quote(input.whenToUse)}`)\n if (!input.modelInvocable) lines.push('disable-model-invocation: true')\n if (!input.userInvocable) lines.push('user-invocable: false')\n const body = input.content.replace(/\\r\\n/g, '\\n').trim()\n return `---\\n${lines.join('\\n')}\\n---\\n\\n${body}\\n`\n}\n\n/** Validate one write request; returns the rejection reason or null. */\nexport function validateSkillInput(input: SkillInput): string | null {\n if (!SKILL_NAME_RE.test(input.name)) return 'name must be kebab-case (a-z, 0-9, dashes)'\n if (input.description.trim() === '') return 'description is required'\n if (input.description.length > 1024) return 'description too long (max 1024)'\n if (input.whenToUse !== undefined && input.whenToUse.length > 2048) return 'whenToUse too long (max 2048)'\n if (input.content.length > 256 * 1024) return 'content too large (max 256 KiB)'\n return null\n}\n\n/** Directory holding one user skill's SKILL.md; name grammar blocks traversal. */\nfunction skillDir(name: string, dshHome?: string): string {\n return join(userSkillsDir(dshHome), name)\n}\n\n/** Create or update a user skill. Returns the written path. */\nexport function writeSkill(input: SkillInput, dshHome?: string): string {\n const dir = skillDir(input.name, dshHome)\n mkdirSync(dir, { recursive: true })\n const file = join(dir, 'SKILL.md')\n writeFileSync(file, serializeSkill(input), 'utf8')\n return file\n}\n\n/** Delete a user skill directory. Returns false when it does not exist. */\nexport function deleteSkill(name: string, dshHome?: string): boolean {\n if (!SKILL_NAME_RE.test(name)) return false\n const dir = skillDir(name, dshHome)\n if (!existsSync(dir) || !statSync(dir).isDirectory()) return false\n // Only ever remove the exact directory this name resolves to under the\n // skills root; the regex already pins it to one safe path segment.\n rmSync(dir, { recursive: true, force: true })\n return true\n}\n", "/**\n * MCP server rows in the profile's own patch layer: one\n * `@deepseek-ai/dsh-mcp-client` row per server. The YAML document API keeps\n * foreign rows and comments intact across edits. Row changes need a dsh\n * restart to compose \u2014 callers surface that as a pending-restart notice.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { parseDocument, Document, type YAMLMap, type YAMLSeq } from 'yaml'\n/** The plugin every managed row instantiates. */\nexport const MCP_PLUGIN = '@deepseek-ai/dsh-mcp-client'\n\n/** MCP serverName grammar (dsh-mcp-client's contract). */\nexport const SERVER_NAME_RE = /^[A-Za-z0-9_-]{1,32}$/\n\n/** Transport choices the client supports. */\nexport type McpTransport = 'stdio' | 'streamable-http'\n\n/** One managed row, as shown to the browser. */\nexport interface McpRow {\n id: string\n serverName: string\n transport: McpTransport\n disabled: boolean\n command?: string\n args?: string[]\n env?: Record<string, string>\n cwd?: string\n url?: string\n headers?: Record<string, string>\n}\n\n/** Write request for one server row (id empty = create). */\nexport type McpInput = Omit<McpRow, 'disabled'> & { disabled?: boolean }\n\n/** Load the profile patch as a YAML document; `[]` for a missing file. */\nfunction loadPatch(profileDirPath: string): Document {\n const path = join(profileDirPath, 'cordis.patch.yml')\n const text = existsSync(path) ? readFileSync(path, 'utf8') : '[]'\n return parseDocument(text)\n}\n\nfunction savePatch(profileDirPath: string, doc: Document): void {\n mkdirSync(profileDirPath, { recursive: true })\n writeFileSync(join(profileDirPath, 'cordis.patch.yml'), String(doc), 'utf8')\n}\n\n/** Wrap a plain value into a YAML node (yaml v2 exposes no standalone createNode). */\nfunction toNode<T>(value: unknown): T {\n return new Document(value as never).contents as T\n}\n\n/** The patch row sequence; an empty file's null root becomes an empty seq. */\nfunction rowSeq(doc: Document): YAMLSeq<YAMLMap> {\n if (doc.contents === null) doc.contents = toNode<YAMLSeq<YAMLMap>>([])\n return doc.contents as YAMLSeq<YAMLMap>\n}\n\n/** Rows whose `name` is the MCP client plugin. */\nfunction mcpRows(doc: Document): YAMLMap[] {\n return (rowSeq(doc).items ?? []).filter(item => item.get('name') === MCP_PLUGIN)\n}\n\nfunction isStringMap(value: unknown): value is Record<string, string> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false\n return Object.values(value).every(entry => typeof entry === 'string')\n}\n\n/** Read every mcp-client row in the profile layer. */\nexport function listMcp(profileDirPath: string): McpRow[] {\n const doc = loadPatch(profileDirPath)\n return mcpRows(doc).map(item => {\n // config is a YAMLMap node \u2014 materialize it before property access.\n const configNode = item.get('config') as unknown\n const plain = (typeof configNode === 'object' && configNode !== null && typeof (configNode as { toJS?: unknown }).toJS === 'function'\n ? (configNode as { toJS(document: Document): unknown }).toJS(doc)\n : {}) as Record<string, unknown>\n return {\n id: String(item.get('id') ?? ''),\n serverName: String(plain.serverName ?? ''),\n transport: plain.transport === 'streamable-http' ? 'streamable-http' : 'stdio',\n disabled: item.get('disabled') === true,\n ...(typeof plain.command === 'string' && plain.command !== '' ? { command: plain.command } : {}),\n ...(Array.isArray(plain.args) ? { args: plain.args.map(String) } : {}),\n ...(isStringMap(plain.env) ? { env: plain.env } : {}),\n ...(typeof plain.cwd === 'string' && plain.cwd !== '' ? { cwd: plain.cwd } : {}),\n ...(typeof plain.url === 'string' && plain.url !== '' ? { url: plain.url } : {}),\n ...(isStringMap(plain.headers) ? { headers: plain.headers } : {}),\n }\n })\n}\n\n/** Validate one write request; returns the rejection reason or null. */\nexport function validateMcpInput(input: McpInput): string | null {\n if (!SERVER_NAME_RE.test(input.serverName)) return 'serverName must be 1-32 chars of A-Z a-z 0-9 _ -'\n if (input.id.includes('/') || input.id.includes('..')) return 'invalid id'\n if (input.transport === 'stdio') {\n if (input.command === undefined || input.command.trim() === '') return 'stdio transport requires a command'\n } else if (input.url === undefined || !/^https?:\\/\\//.test(input.url)) {\n return 'http transport requires an http(s) url'\n }\n return null\n}\n\n/** Add or replace one server row. Returns the (possibly deduplicated) id. */\nexport function upsertMcp(profileDirPath: string, input: McpInput): string {\n const doc = loadPatch(profileDirPath)\n const seq = rowSeq(doc)\n\n const existing = input.id !== ''\n ? mcpRows(doc).find(item => item.get('id') === input.id)\n : undefined\n\n let id = input.id !== '' ? input.id : `mcp-${input.serverName}`\n if (existing === undefined) {\n const taken = new Set(\n (seq.items ?? []).map(item => String(item.get('id') ?? '')).filter(id => id !== ''),\n )\n let suffix = 2\n while (taken.has(id)) id = `mcp-${input.serverName}-${suffix++}`\n }\n\n const config: Record<string, unknown> = input.transport === 'stdio'\n ? {\n serverName: input.serverName,\n transport: input.transport,\n command: input.command,\n ...(input.args !== undefined && input.args.length > 0 ? { args: input.args } : {}),\n ...(input.env !== undefined && Object.keys(input.env).length > 0 ? { env: input.env } : {}),\n ...(input.cwd !== undefined && input.cwd !== '' ? { cwd: input.cwd } : {}),\n }\n : {\n serverName: input.serverName,\n transport: input.transport,\n url: input.url,\n ...(input.headers !== undefined && Object.keys(input.headers).length > 0 ? { headers: input.headers } : {}),\n }\n const row: Record<string, unknown> = { id, name: MCP_PLUGIN, config }\n if (input.disabled === true) row.disabled = true\n\n const node = toNode<YAMLMap>(row)\n if (existing === undefined) seq.add(node)\n else seq.items[seq.items.indexOf(existing)] = node\n\n savePatch(profileDirPath, doc)\n return id\n}\n\n/** Flip one row's disabled flag (absent = enabled). Returns false when missing. */\nexport function setMcpDisabled(profileDirPath: string, id: string, disabled: boolean): boolean {\n const doc = loadPatch(profileDirPath)\n const item = mcpRows(doc).find(row => row.get('id') === id)\n if (item === undefined) return false\n if (disabled) item.set('disabled', true)\n else item.delete('disabled')\n savePatch(profileDirPath, doc)\n return true\n}\n\n/** Remove one server row. Returns false when missing. */\nexport function removeMcp(profileDirPath: string, id: string): boolean {\n const doc = loadPatch(profileDirPath)\n const item = mcpRows(doc).find(row => row.get('id') === id)\n if (item === undefined) return false\n const seq = rowSeq(doc)\n seq.items.splice(seq.items.indexOf(item), 1)\n savePatch(profileDirPath, doc)\n return true\n}\n", "/** HTTP routes bridging the Settings UI to the capabilities manager. */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { scanAllMcp } from './agents.ts'\nimport { readJsonBody, sameOrigin, sendJson } from './http.ts'\nimport { deleteSkill, validateSkillInput, writeSkill, type SkillInput } from './skills.ts'\nimport { listMcp, removeMcp, setMcpDisabled, upsertMcp, validateMcpInput, type McpInput } from './mcp.ts'\nimport type { CapabilitiesHost } from './types.ts'\n\n/** Only this source is writable from the Settings page (provider rank 400). */\nconst EDITABLE_SOURCE = 'user-dsh'\n\n/** Register the manager's routes; returns the disposer removing them all. */\nexport function mountCapabilitiesRoutes(host: CapabilitiesHost, config: { profileDirPath: string }): () => void {\n const disposers = [\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/skills',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'GET') {\n response.writeHead(405, { allow: 'GET' })\n response.end()\n return\n }\n try {\n const skills = await host.skills.list()\n sendJson(response, 200, {\n skills: skills.map(skill => ({ ...skill, editable: skill.source === EDITABLE_SOURCE })),\n })\n } catch (error) {\n sendJson(response, 500, { error: error instanceof Error ? error.message : String(error) })\n }\n },\n }),\n\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/skill',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'GET') {\n response.writeHead(405, { allow: 'GET' })\n response.end()\n return\n }\n const url = new URL(request.url ?? '/', 'http://localhost')\n const name = url.searchParams.get('name') ?? ''\n try {\n const definition = await host.skills.get(name)\n sendJson(response, 200, { name: definition.name, content: definition.content })\n } catch (error) {\n sendJson(response, 500, { error: error instanceof Error ? error.message : String(error) })\n }\n },\n }),\n\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/skill/save',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'POST') {\n response.writeHead(405, { allow: 'POST' })\n response.end()\n return\n }\n if (!sameOrigin(request)) {\n sendJson(response, 403, { error: 'untrusted origin' })\n return\n }\n try {\n const body = (await readJsonBody(request)) as Partial<SkillInput>\n const input: SkillInput = {\n name: typeof body.name === 'string' ? body.name : '',\n description: typeof body.description === 'string' ? body.description : '',\n whenToUse: typeof body.whenToUse === 'string' ? body.whenToUse : undefined,\n modelInvocable: body.modelInvocable !== false,\n userInvocable: body.userInvocable !== false,\n content: typeof body.content === 'string' ? body.content : '',\n }\n const invalid = validateSkillInput(input)\n if (invalid !== null) {\n sendJson(response, 400, { error: invalid })\n return\n }\n writeSkill(input)\n sendJson(response, 200, { ok: true, name: input.name })\n } catch (error) {\n sendJson(response, 500, { error: error instanceof Error ? error.message : String(error) })\n }\n },\n }),\n\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/skill/delete',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'POST') {\n response.writeHead(405, { allow: 'POST' })\n response.end()\n return\n }\n if (!sameOrigin(request)) {\n sendJson(response, 403, { error: 'untrusted origin' })\n return\n }\n try {\n const body = (await readJsonBody(request)) as { name?: unknown }\n const name = typeof body.name === 'string' ? body.name : ''\n const removed = deleteSkill(name)\n sendJson(response, removed ? 200 : 404, removed ? { ok: true, name } : { error: 'skill not found' })\n } catch (error) {\n sendJson(response, 500, { error: error instanceof Error ? error.message : String(error) })\n }\n },\n }),\n\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/mcp',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'GET') {\n response.writeHead(405, { allow: 'GET' })\n response.end()\n return\n }\n sendJson(response, 200, { servers: listMcp(config.profileDirPath), restartNeeded: true })\n },\n }),\n\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/mcp/save',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'POST') {\n response.writeHead(405, { allow: 'POST' })\n response.end()\n return\n }\n if (!sameOrigin(request)) {\n sendJson(response, 403, { error: 'untrusted origin' })\n return\n }\n try {\n const input = (await readJsonBody(request)) as McpInput\n const invalid = validateMcpInput(input)\n if (invalid !== null) {\n sendJson(response, 400, { error: invalid })\n return\n }\n const id = upsertMcp(config.profileDirPath, input)\n sendJson(response, 200, { ok: true, id, restartNeeded: true })\n } catch (error) {\n sendJson(response, 500, { error: error instanceof Error ? error.message : String(error) })\n }\n },\n }),\n\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/mcp/toggle',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'POST') {\n response.writeHead(405, { allow: 'POST' })\n response.end()\n return\n }\n if (!sameOrigin(request)) {\n sendJson(response, 403, { error: 'untrusted origin' })\n return\n }\n try {\n const body = (await readJsonBody(request)) as { id?: unknown; disabled?: unknown }\n if (typeof body.id !== 'string' || typeof body.disabled !== 'boolean') {\n sendJson(response, 400, { error: 'id and disabled are required' })\n return\n }\n const ok = setMcpDisabled(config.profileDirPath, body.id, body.disabled)\n sendJson(response, ok ? 200 : 404, ok ? { ok: true, restartNeeded: true } : { error: 'server row not found' })\n } catch (error) {\n sendJson(response, 500, { error: error instanceof Error ? error.message : String(error) })\n }\n },\n }),\n\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/mcp/remove',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'POST') {\n response.writeHead(405, { allow: 'POST' })\n response.end()\n return\n }\n if (!sameOrigin(request)) {\n sendJson(response, 403, { error: 'untrusted origin' })\n return\n }\n try {\n const body = (await readJsonBody(request)) as { id?: unknown }\n if (typeof body.id !== 'string') {\n sendJson(response, 400, { error: 'id is required' })\n return\n }\n const ok = removeMcp(config.profileDirPath, body.id)\n sendJson(response, ok ? 200 : 404, ok ? { ok: true, restartNeeded: true } : { error: 'server row not found' })\n } catch (error) {\n sendJson(response, 500, { error: error instanceof Error ? error.message : String(error) })\n }\n },\n }),\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/import/scan',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'GET') {\n response.writeHead(405, { allow: 'GET' })\n response.end()\n return\n }\n try {\n sendJson(response, 200, {\n servers: scanAllMcp(),\n // Profile serverNames, so the browser can grey out existing ones.\n existing: listMcp(config.profileDirPath).map(row => row.serverName),\n })\n } catch (error) {\n sendJson(response, 500, { error: error instanceof Error ? error.message : String(error) })\n }\n },\n }),\n\n host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/import/apply',\n handler: async (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'POST') {\n response.writeHead(405, { allow: 'POST' })\n response.end()\n return\n }\n if (!sameOrigin(request)) {\n sendJson(response, 403, { error: 'untrusted origin' })\n return\n }\n try {\n const body = (await readJsonBody(request)) as { items?: unknown }\n const wanted = new Set(\n (Array.isArray(body.items) ? body.items : [])\n .filter((item): item is { agent: string; name: string } =>\n typeof item === 'object' && item !== null && typeof (item as { agent?: unknown }).agent === 'string' && typeof (item as { name?: unknown }).name === 'string')\n .map(item => `${item.agent}/${item.name}`),\n )\n const results: Array<{ name: string; ok: boolean; error?: string }> = []\n for (const server of scanAllMcp()) {\n if (!wanted.has(`${server.agent}/${server.name}`)) continue\n const existing = listMcp(config.profileDirPath).some(row => row.serverName === server.name)\n if (existing) {\n results.push({ name: server.name, ok: false, error: 'already in profile' })\n continue\n }\n const input: McpInput = {\n id: '',\n serverName: server.name,\n transport: server.transport,\n ...(server.transport === 'stdio'\n ? { command: server.command, args: server.args, env: server.env }\n : { url: server.url, headers: server.headers }),\n }\n const invalid = validateMcpInput(input)\n if (invalid !== null) {\n results.push({ name: server.name, ok: false, error: invalid })\n continue\n }\n upsertMcp(config.profileDirPath, input)\n results.push({ name: server.name, ok: true })\n }\n sendJson(response, 200, { ok: results.every(item => item.ok), results, restartNeeded: true })\n } catch (error) {\n sendJson(response, 500, { error: error instanceof Error ? error.message : String(error) })\n }\n },\n }),\n ]\n\n return () => { for (const dispose of disposers) dispose() }\n}\n", "/** dsh-plugin-capabilities host entry: mount the manager's HTTP routes once\n * the profile composes both the web server and the skill registry, and mount\n * a host-plane filesystem skill provider so the Settings page sees a live\n * catalog (the web composition deliberately leaves the host row to presets). */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport { agentSkillRoots } from './agents.ts'\nimport { argvProfile, profileDir } from './profile.ts'\nimport { mountCapabilitiesRoutes } from './routes.ts'\nimport type { CapabilitiesHost } from './types.ts'\n\nexport const name = 'dsh-plugin-capabilities'\n\n/** Optional cordis.yml configuration; profile defaults to the booted one. */\nexport interface Config {\n /** Profile whose patch layer holds the MCP rows; defaults to argv or `web`. */\n profile?: string\n}\n\nexport const inject = ['webServer', 'skills']\n\n/** The provider plugin's structural shape (name/apply export). */\ninterface FilesystemSkillPlugin {\n name: string\n apply(context: Context, config?: unknown): void\n}\n\nexport function apply(ctx: Context, config?: Config): void {\n const profile = config?.profile ?? argvProfile() ?? 'web'\n ctx.inject(['webServer', 'skills'], (hostCtx: Context) => {\n // The web bundle disables the host-plane `skill-filesystem` row on\n // purpose (presets own per-session discovery). The Settings manager\n // mounts its own host-plane provider as a CHILD of this plugin: it dies\n // with us, registers into the registry's global layer, and preset layers\n // keep their semantics (nearest layer still wins duplicate names). Other\n // agents' skill roots (~/.claude/skills, ~/.codex/skills) join as custom\n // dirs \u2014 zero-copy, live-synced both ways. A failed load only means an\n // empty catalog \u2014 the routes keep serving.\n void (async () => {\n try {\n const mod = (await import('@deepseek-ai/dsh-skill-filesystem')) as unknown as\n (FilesystemSkillPlugin & { default?: FilesystemSkillPlugin })\n const plugin = mod.default ?? mod\n const roots = agentSkillRoots()\n hostCtx.plugin(plugin, roots.length > 0 ? { customSkillDirs: roots } : {})\n } catch {\n // Unresolvable provider: skills list stays empty; MCP tab unaffected.\n }\n })()\n\n ctx.effect(\n () => mountCapabilitiesRoutes(hostCtx as unknown as CapabilitiesHost, { profileDirPath: profileDir(profile) }),\n 'dsh-plugin-capabilities: http routes',\n )\n })\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["name", "homedir", "join", "existsSync", "homedir", "join", "name", "existsSync", "mkdirSync", "readFileSync", "writeFileSync", "join", "id", "name"]
7
+ }
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "dsh-plugin-capabilities",
3
+ "version": "0.1.0",
4
+ "description": "Manage skills and MCP servers from the Web UI Settings. 在设置页管理 dsh 的技能与 MCP 服务器。",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "types": "lib/types/index.d.ts",
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/qinyre/dsh-plugin-capabilities.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/qinyre/dsh-plugin-capabilities/issues"
15
+ },
16
+ "homepage": "https://github.com/qinyre/dsh-plugin-capabilities#readme",
17
+ "keywords": ["deepseek", "harness", "dsh", "dsh-plugin", "skills", "mcp"],
18
+ "dsh": {
19
+ "bundle": {
20
+ "patch": "./cordis.patch.yml"
21
+ },
22
+ "client": {
23
+ "inject": [
24
+ "@deepseek-ai/dsh-client-locale",
25
+ "@deepseek-ai/dsh-client-ui-slots"
26
+ ],
27
+ "platform": "web"
28
+ }
29
+ },
30
+ "exports": {
31
+ ".": {
32
+ "types": "./lib/types/index.d.ts",
33
+ "default": "./lib/index.js"
34
+ },
35
+ "./client": "./lib/client.js",
36
+ "./cordis.patch.yml": "./cordis.patch.yml",
37
+ "./package.json": "./package.json"
38
+ },
39
+ "files": ["lib", "src", "cordis.patch.yml", "LICENSE"],
40
+ "scripts": {
41
+ "build": "node scripts/build-node.mjs && node scripts/build-client.mjs && node scripts/verify-bundle.mjs",
42
+ "prepare": "node scripts/build-node.mjs && node scripts/build-client.mjs && node scripts/verify-bundle.mjs",
43
+ "typecheck": "tsc -p tsconfig.json --noEmit",
44
+ "test": "vitest run",
45
+ "bundle-check": "node scripts/verify-bundle.mjs"
46
+ },
47
+ "peerDependencies": {
48
+ "@deepseek-ai/cordis": "^4.0.1"
49
+ },
50
+ "dependencies": {
51
+ "@deepseek-ai/dsh-skill-filesystem": "^0.1.0-rc.6",
52
+ "smol-toml": "^1.3.1",
53
+ "yaml": "^2.6.0"
54
+ },
55
+ "devDependencies": {
56
+ "@deepseek-ai/cordis": "^4.0.1",
57
+ "@types/node": "^22.0.0",
58
+ "@types/react": "~18.3.1",
59
+ "esbuild": "^0.24.0",
60
+ "react": "^18.3.1",
61
+ "typescript": "^5.6.0",
62
+ "vitest": "^2.1.1"
63
+ }
64
+ }
@@ -0,0 +1,105 @@
1
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
2
+ import { tmpdir } from 'node:os'
3
+ import { join } from 'node:path'
4
+ import { afterAll, describe, expect, it } from 'vitest'
5
+ import { agentSkillRoots, scanAllMcp, scanClaudeMcp, scanCodexMcp } from './agents.ts'
6
+
7
+ const home = mkdtempSync(join(tmpdir(), 'dsh-caps-agents-'))
8
+ afterAll(() => rmSync(home, { recursive: true, force: true }))
9
+
10
+ const CLAUDE_JSON = {
11
+ mcpServers: {
12
+ 'open-websearch': {
13
+ type: 'stdio',
14
+ command: 'cmd',
15
+ args: ['/c', 'npx', '-y', 'open-websearch@latest'],
16
+ env: { MODE: 'stdio', SYSTEMROOT: 'C:/Windows' },
17
+ startup_timeout_sec: 30,
18
+ },
19
+ context7: { command: 'npx', args: ['-y', '@upstash/context7-mcp'] },
20
+ 'web-remote': { type: 'http', url: 'https://example.com/mcp', headers: { Authorization: 'Bearer x' } },
21
+ 'legacy-sse': { type: 'sse', url: 'https://example.com/sse' },
22
+ broken: { type: 'stdio' },
23
+ },
24
+ }
25
+
26
+ const CODEX_TOML = `
27
+ [mcp_servers.context7]
28
+ command = "cmd"
29
+ args = ["/c", "npx", "-y", "@upstash/context7-mcp"]
30
+
31
+ [mcp_servers.context7.env]
32
+ SYSTEMROOT = "C:/Windows"
33
+
34
+ [mcp_servers.remote-thing]
35
+ url = "https://example.com/mcp"
36
+ `
37
+
38
+ describe('scanClaudeMcp', () => {
39
+ it('maps stdio entries with and without an explicit type, and http entries', () => {
40
+ writeFileSync(join(home, '.claude.json'), JSON.stringify(CLAUDE_JSON))
41
+ const servers = scanClaudeMcp(home)
42
+ const names = servers.map(server => server.name)
43
+ expect(names).toContain('open-websearch')
44
+ expect(names).toContain('context7')
45
+ expect(names).toContain('web-remote')
46
+ expect(names).not.toContain('legacy-sse')
47
+ expect(names).not.toContain('broken')
48
+
49
+ const stdio = servers.find(server => server.name === 'open-websearch')
50
+ expect(stdio).toMatchObject({ agent: 'claude-code', transport: 'stdio', command: 'cmd' })
51
+ expect(stdio?.args).toEqual(['/c', 'npx', '-y', 'open-websearch@latest'])
52
+ expect(stdio?.env).toEqual({ MODE: 'stdio', SYSTEMROOT: 'C:/Windows' })
53
+
54
+ const http = servers.find(server => server.name === 'web-remote')
55
+ expect(http).toMatchObject({ transport: 'streamable-http', url: 'https://example.com/mcp' })
56
+ expect(http?.headers).toEqual({ Authorization: 'Bearer x' })
57
+ })
58
+ it('merges ~/.claude/settings.json under ~/.claude.json and skips broken files', () => {
59
+ mkdirSync(join(home, '.claude'), { recursive: true })
60
+ writeFileSync(join(home, '.claude', 'settings.json'), JSON.stringify({ mcpServers: { extra: { command: 'x' } } }))
61
+ const names = scanClaudeMcp(home).map(server => server.name)
62
+ expect(names).toContain('extra')
63
+ expect(names).toContain('context7')
64
+ writeFileSync(join(home, '.claude.json'), '{ broken json')
65
+ expect(scanClaudeMcp(home).map(server => server.name)).toEqual(['extra'])
66
+ })
67
+ it('returns empty for a home with no configs', () => {
68
+ expect(scanClaudeMcp(join(home, 'empty'))).toEqual([])
69
+ })
70
+ })
71
+
72
+ describe('scanCodexMcp', () => {
73
+ it('parses [mcp_servers.*] tables: stdio with env, and url-only http', () => {
74
+ mkdirSync(join(home, '.codex'), { recursive: true })
75
+ writeFileSync(join(home, '.codex', 'config.toml'), CODEX_TOML)
76
+ const servers = scanCodexMcp(home)
77
+ expect(servers).toHaveLength(2)
78
+ const stdio = servers.find(server => server.name === 'context7')
79
+ expect(stdio).toMatchObject({ agent: 'codex', transport: 'stdio', command: 'cmd' })
80
+ expect(stdio?.env).toEqual({ SYSTEMROOT: 'C:/Windows' })
81
+ const http = servers.find(server => server.name === 'remote-thing')
82
+ expect(http).toMatchObject({ transport: 'streamable-http', url: 'https://example.com/mcp' })
83
+ })
84
+ it('returns empty for missing or malformed toml', () => {
85
+ expect(scanCodexMcp(join(home, 'empty'))).toEqual([])
86
+ writeFileSync(join(home, '.codex', 'config.toml'), 'not [ valid toml')
87
+ expect(scanCodexMcp(home)).toEqual([])
88
+ })
89
+ })
90
+
91
+ describe('scanAllMcp + agentSkillRoots', () => {
92
+ it('dedupes by (agent, name) and keeps both agents', () => {
93
+ writeFileSync(join(home, '.claude.json'), JSON.stringify(CLAUDE_JSON))
94
+ writeFileSync(join(home, '.codex', 'config.toml'), CODEX_TOML)
95
+ const all = scanAllMcp(home)
96
+ expect(all.filter(server => server.name === 'context7')).toHaveLength(2)
97
+ const keys = all.map(server => `${server.agent}/${server.name}`)
98
+ expect(new Set(keys).size).toBe(keys.length)
99
+ })
100
+ it('lists only existing agent skill roots', () => {
101
+ expect(agentSkillRoots(home)).toEqual([])
102
+ mkdirSync(join(home, '.claude', 'skills'), { recursive: true })
103
+ expect(agentSkillRoots(home)).toEqual([join(home, '.claude', 'skills')])
104
+ })
105
+ })
package/src/agents.ts ADDED
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Foreign-agent config readers: MCP servers from Claude Code (~/.claude.json,
3
+ * ~/.claude/settings.json) and Codex (~/.codex/config.toml). Pure reads of
4
+ * well-known paths; anything missing or malformed yields an empty list.
5
+ */
6
+
7
+ import { existsSync, readFileSync } from 'node:fs'
8
+ import { homedir } from 'node:os'
9
+ import { join } from 'node:path'
10
+ import { parse as parseToml } from 'smol-toml'
11
+ import type { McpTransport } from './mcp.ts'
12
+
13
+ /** One MCP server discovered in a foreign agent's config. */
14
+ export interface ImportedServer {
15
+ agent: 'claude-code' | 'codex'
16
+ name: string
17
+ transport: McpTransport
18
+ command?: string
19
+ args?: string[]
20
+ env?: Record<string, string>
21
+ url?: string
22
+ headers?: Record<string, string>
23
+ }
24
+
25
+ /** Keep only string-valued entries of a record (configs may hold numbers). */
26
+ function stringEntries(value: unknown): Record<string, string> | undefined {
27
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined
28
+ const out: Record<string, string> = {}
29
+ for (const [key, entry] of Object.entries(value)) {
30
+ if (typeof entry === 'string') out[key] = entry
31
+ }
32
+ return Object.keys(out).length > 0 ? out : undefined
33
+ }
34
+
35
+ function stringArray(value: unknown): string[] | undefined {
36
+ if (!Array.isArray(value)) return undefined
37
+ const out = value.filter((entry): entry is string => typeof entry === 'string')
38
+ return out.length > 0 ? out : undefined
39
+ }
40
+
41
+ /** Map one Claude mcpServers entry; returns null for unsupported shapes (sse). */
42
+ function mapClaudeEntry(name: string, entry: unknown): ImportedServer | null {
43
+ if (typeof entry !== 'object' || entry === null) return null
44
+ const record = entry as Record<string, unknown>
45
+ const type = typeof record.type === 'string' ? record.type : 'stdio'
46
+ if (type === 'stdio' || (type === 'stdio' && record.command !== undefined)) {
47
+ if (typeof record.command !== 'string' || record.command === '') return null
48
+ return {
49
+ agent: 'claude-code', name, transport: 'stdio',
50
+ command: record.command,
51
+ args: stringArray(record.args),
52
+ env: stringEntries(record.env),
53
+ }
54
+ }
55
+ if (type === 'http' || type === 'streamable-http') {
56
+ if (typeof record.url !== 'string' || record.url === '') return null
57
+ return {
58
+ agent: 'claude-code', name, transport: 'streamable-http',
59
+ url: record.url,
60
+ headers: stringEntries(record.headers),
61
+ }
62
+ }
63
+ // 'sse' and anything else: dsh's mcp-client speaks stdio + streamable-http only.
64
+ return null
65
+ }
66
+
67
+ /** MCP servers from Claude Code's user-scope config files. */
68
+ export function scanClaudeMcp(home: string = homedir()): ImportedServer[] {
69
+ const merged: Record<string, unknown> = {}
70
+ for (const file of [join(home, '.claude', 'settings.json'), join(home, '.claude.json')]) {
71
+ if (!existsSync(file)) continue
72
+ try {
73
+ const parsed = JSON.parse(readFileSync(file, 'utf8')) as { mcpServers?: unknown }
74
+ if (typeof parsed.mcpServers === 'object' && parsed.mcpServers !== null) {
75
+ Object.assign(merged, parsed.mcpServers)
76
+ }
77
+ } catch {
78
+ // Broken or partial config: skip the file, keep earlier merges.
79
+ }
80
+ }
81
+ const out: ImportedServer[] = []
82
+ for (const [name, entry] of Object.entries(merged)) {
83
+ const mapped = mapClaudeEntry(name, entry)
84
+ if (mapped !== null) out.push(mapped)
85
+ }
86
+ return out
87
+ }
88
+
89
+ /** MCP servers from Codex's config.toml ([mcp_servers.<name>] tables). */
90
+ export function scanCodexMcp(home: string = homedir()): ImportedServer[] {
91
+ const file = join(home, '.codex', 'config.toml')
92
+ if (!existsSync(file)) return []
93
+ let root: Record<string, unknown>
94
+ try {
95
+ root = parseToml(readFileSync(file, 'utf8')) as Record<string, unknown>
96
+ } catch {
97
+ return []
98
+ }
99
+ const table = root.mcp_servers
100
+ if (typeof table !== 'object' || table === null) return []
101
+ const out: ImportedServer[] = []
102
+ for (const [name, entry] of Object.entries(table)) {
103
+ if (typeof entry !== 'object' || entry === null) continue
104
+ const record = entry as Record<string, unknown>
105
+ if (typeof record.command === 'string' && record.command !== '') {
106
+ out.push({
107
+ agent: 'codex', name, transport: 'stdio',
108
+ command: record.command,
109
+ args: stringArray(record.args),
110
+ env: stringEntries(record.env),
111
+ })
112
+ } else if (typeof record.url === 'string' && record.url !== '') {
113
+ out.push({ agent: 'codex', name, transport: 'streamable-http', url: record.url })
114
+ }
115
+ }
116
+ return out
117
+ }
118
+
119
+ /** All foreign-agent MCP servers, deduplicated by (agent, name). */
120
+ export function scanAllMcp(home: string = homedir()): ImportedServer[] {
121
+ const seen = new Set<string>()
122
+ return [...scanClaudeMcp(home), ...scanCodexMcp(home)]
123
+ .filter(server => {
124
+ const key = `${server.agent}/${server.name}`
125
+ if (seen.has(key)) return false
126
+ seen.add(key)
127
+ return true
128
+ })
129
+ }
130
+
131
+ /** Other agents' skill roots that exist on this machine. */
132
+ export function agentSkillRoots(home: string = homedir()): string[] {
133
+ return [join(home, '.claude', 'skills'), join(home, '.codex', 'skills')]
134
+ .filter(path => existsSync(path))
135
+ }