dsh-plugin-capabilities 0.1.2 → 0.1.3

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.
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  ![「MCP」标签页](docs/images/screenshot-mcp.png)
19
19
 
20
- 「MCP」页管理 profile patch 中的 MCP 服务器行,每行对应一个 `@deepseek-ai/dsh-mcp-client` 实例。stdio 服务器填写命令与参数,streamable-http 服务器填写 URL,编辑、停用、移除都在页面上完成。YAML 读写采用文档级 API,文件中的其他行与注释不受影响。
20
+ 「MCP」页管理 profile patch 中的 MCP 服务器行,每行对应一个 `@deepseek-ai/dsh-mcp-client` 实例。stdio 服务器填写命令与参数,streamable-http 服务器填写 URL,编辑、停用、移除都在页面上完成。YAML 读写采用文档级 API,文件中的其他行与注释不受影响。新行写在一个 `- insert:` 块里——加载器只会挂载 insert 形式的行,裸的 `- id:` 条目是对已有行的覆盖,目标不存在时会被跳过;0.1.3 之前写入的裸行会在下一次保存时自动迁入 insert 块。
21
21
 
22
22
  也可以从其他 agent 导入:一键扫描 Claude Code(`~/.claude.json`、`~/.claude/settings.json`)与 Codex(`~/.codex/config.toml`)的 MCP 配置,勾选所需条目后转为本 profile 的服务器行。stdio 与 http 两种传输都会处理,已存在的同名服务器置灰跳过。需要注意的是,Claude 配置里的 `${VAR}` 环境变量引用按字面值导入,如有需要请在导入后手动改回。
23
23
 
package/lib/index.js CHANGED
@@ -904,7 +904,10 @@ var SERVER_NAME_RE = /^[A-Za-z0-9_-]{1,32}$/;
904
904
  function loadPatch(profileDirPath) {
905
905
  const path = join4(profileDirPath, "cordis.patch.yml");
906
906
  const text = existsSync3(path) ? readFileSync2(path, "utf8") : "[]";
907
- return parseDocument(text);
907
+ const doc = parseDocument(text);
908
+ const contents = doc.contents;
909
+ if (contents !== null && contents.flow === true && contents.items.length === 0) contents.flow = false;
910
+ return doc;
908
911
  }
909
912
  function savePatch(profileDirPath, doc) {
910
913
  mkdirSync2(profileDirPath, { recursive: true });
@@ -914,34 +917,87 @@ function toNode(value) {
914
917
  return new Document(value).contents;
915
918
  }
916
919
  function rowSeq(doc) {
917
- if (doc.contents === null) doc.contents = toNode([]);
920
+ if (doc.contents === null) {
921
+ doc.contents = toNode([]);
922
+ doc.contents.flow = false;
923
+ }
918
924
  return doc.contents;
919
925
  }
920
- function mcpRows(doc) {
921
- return (rowSeq(doc).items ?? []).filter((item) => item.get("name") === MCP_PLUGIN);
926
+ function isSeqNode(value) {
927
+ return typeof value === "object" && value !== null && Array.isArray(value.items);
928
+ }
929
+ function insertListOf(item) {
930
+ if (item.has("id")) return void 0;
931
+ const node = item.get("insert");
932
+ return isSeqNode(node) ? node : void 0;
933
+ }
934
+ function mcpRowItems(doc) {
935
+ const found = [];
936
+ for (const item of rowSeq(doc).items ?? []) {
937
+ if (item.get("name") === MCP_PLUGIN) found.push({ node: item });
938
+ const list = insertListOf(item);
939
+ for (const row of list?.items ?? []) {
940
+ if (row.get("name") === MCP_PLUGIN) found.push({ node: row, list });
941
+ }
942
+ }
943
+ return found;
944
+ }
945
+ function rowToMcp(doc, item) {
946
+ const configNode = item.get("config");
947
+ const plain = typeof configNode === "object" && configNode !== null && typeof configNode.toJS === "function" ? configNode.toJS(doc) : {};
948
+ return {
949
+ id: String(item.get("id") ?? ""),
950
+ serverName: String(plain.serverName ?? ""),
951
+ transport: plain.transport === "streamable-http" ? "streamable-http" : "stdio",
952
+ disabled: item.get("disabled") === true,
953
+ ...typeof plain.command === "string" && plain.command !== "" ? { command: plain.command } : {},
954
+ ...Array.isArray(plain.args) ? { args: plain.args.map(String) } : {},
955
+ ...isStringMap(plain.env) ? { env: plain.env } : {},
956
+ ...typeof plain.cwd === "string" && plain.cwd !== "" ? { cwd: plain.cwd } : {},
957
+ ...typeof plain.url === "string" && plain.url !== "" ? { url: plain.url } : {},
958
+ ...isStringMap(plain.headers) ? { headers: plain.headers } : {}
959
+ };
922
960
  }
923
961
  function isStringMap(value) {
924
962
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
925
963
  return Object.values(value).every((entry) => typeof entry === "string");
926
964
  }
965
+ function managedInsert(doc) {
966
+ const seq = rowSeq(doc);
967
+ const bare = [];
968
+ let target;
969
+ for (const item of seq.items ?? []) {
970
+ if (item.get("name") === MCP_PLUGIN) bare.push(item);
971
+ const list = insertListOf(item);
972
+ if (list !== void 0 && list.items.some((row) => row.get("name") === MCP_PLUGIN)) target ??= list;
973
+ }
974
+ if (target === void 0) {
975
+ const entry = toNode({ insert: [] });
976
+ seq.add(entry);
977
+ target = entry.get("insert");
978
+ target.flow = false;
979
+ }
980
+ for (const row of bare) {
981
+ seq.items.splice(seq.items.indexOf(row), 1);
982
+ target.add(row);
983
+ }
984
+ return target;
985
+ }
986
+ function takenIds(doc) {
987
+ const taken = /* @__PURE__ */ new Set();
988
+ for (const item of rowSeq(doc).items ?? []) {
989
+ const id = String(item.get("id") ?? "");
990
+ if (id !== "") taken.add(id);
991
+ for (const row of insertListOf(item)?.items ?? []) {
992
+ const rowId = String(row.get("id") ?? "");
993
+ if (rowId !== "") taken.add(rowId);
994
+ }
995
+ }
996
+ return taken;
997
+ }
927
998
  function listMcp(profileDirPath) {
928
999
  const doc = loadPatch(profileDirPath);
929
- return mcpRows(doc).map((item) => {
930
- const configNode = item.get("config");
931
- const plain = typeof configNode === "object" && configNode !== null && typeof configNode.toJS === "function" ? configNode.toJS(doc) : {};
932
- return {
933
- id: String(item.get("id") ?? ""),
934
- serverName: String(plain.serverName ?? ""),
935
- transport: plain.transport === "streamable-http" ? "streamable-http" : "stdio",
936
- disabled: item.get("disabled") === true,
937
- ...typeof plain.command === "string" && plain.command !== "" ? { command: plain.command } : {},
938
- ...Array.isArray(plain.args) ? { args: plain.args.map(String) } : {},
939
- ...isStringMap(plain.env) ? { env: plain.env } : {},
940
- ...typeof plain.cwd === "string" && plain.cwd !== "" ? { cwd: plain.cwd } : {},
941
- ...typeof plain.url === "string" && plain.url !== "" ? { url: plain.url } : {},
942
- ...isStringMap(plain.headers) ? { headers: plain.headers } : {}
943
- };
944
- });
1000
+ return mcpRowItems(doc).map(({ node }) => rowToMcp(doc, node));
945
1001
  }
946
1002
  function validateMcpInput(input) {
947
1003
  if (!SERVER_NAME_RE.test(input.serverName)) return "serverName must be 1-32 chars of A-Z a-z 0-9 _ -";
@@ -957,13 +1013,11 @@ function validateMcpInput(input) {
957
1013
  function upsertMcp(profileDirPath, input) {
958
1014
  const inputId = input.id ?? "";
959
1015
  const doc = loadPatch(profileDirPath);
960
- const seq = rowSeq(doc);
961
- const existing = inputId !== "" ? mcpRows(doc).find((item) => item.get("id") === inputId) : void 0;
1016
+ const list = managedInsert(doc);
1017
+ const existing = inputId !== "" ? mcpRowItems(doc).find(({ node: node2 }) => String(node2.get("id") ?? "") === inputId) : void 0;
962
1018
  let id = inputId !== "" ? inputId : `mcp-${input.serverName}`;
963
1019
  if (existing === void 0) {
964
- const taken = new Set(
965
- (seq.items ?? []).map((item) => String(item.get("id") ?? "")).filter((id2) => id2 !== "")
966
- );
1020
+ const taken = takenIds(doc);
967
1021
  let suffix = 2;
968
1022
  while (taken.has(id)) id = `mcp-${input.serverName}-${suffix++}`;
969
1023
  }
@@ -983,26 +1037,37 @@ function upsertMcp(profileDirPath, input) {
983
1037
  const row = { id, name: MCP_PLUGIN, config };
984
1038
  if (input.disabled === true) row.disabled = true;
985
1039
  const node = toNode(row);
986
- if (existing === void 0) seq.add(node);
987
- else seq.items[seq.items.indexOf(existing)] = node;
1040
+ if (existing === void 0) {
1041
+ list.add(node);
1042
+ } else if (existing.list !== void 0) {
1043
+ existing.list.items.splice(existing.list.items.indexOf(existing.node), 1, node);
1044
+ } else {
1045
+ rowSeq(doc).items.splice(rowSeq(doc).items.indexOf(existing.node), 1, node);
1046
+ }
988
1047
  savePatch(profileDirPath, doc);
989
1048
  return id;
990
1049
  }
991
1050
  function setMcpDisabled(profileDirPath, id, disabled) {
992
1051
  const doc = loadPatch(profileDirPath);
993
- const item = mcpRows(doc).find((row) => row.get("id") === id);
994
- if (item === void 0) return false;
995
- if (disabled) item.set("disabled", true);
996
- else item.delete("disabled");
1052
+ managedInsert(doc);
1053
+ const hit = mcpRowItems(doc).find(({ node }) => String(node.get("id") ?? "") === id);
1054
+ if (hit === void 0) return false;
1055
+ if (disabled) hit.node.set("disabled", true);
1056
+ else hit.node.delete("disabled");
997
1057
  savePatch(profileDirPath, doc);
998
1058
  return true;
999
1059
  }
1000
1060
  function removeMcp(profileDirPath, id) {
1001
1061
  const doc = loadPatch(profileDirPath);
1002
- const item = mcpRows(doc).find((row) => row.get("id") === id);
1003
- if (item === void 0) return false;
1062
+ managedInsert(doc);
1063
+ const hit = mcpRowItems(doc).find(({ node }) => String(node.get("id") ?? "") === id);
1064
+ if (hit === void 0 || hit.list === void 0) return false;
1065
+ hit.list.items.splice(hit.list.items.indexOf(hit.node), 1);
1004
1066
  const seq = rowSeq(doc);
1005
- seq.items.splice(seq.items.indexOf(item), 1);
1067
+ const owner = (seq.items ?? []).find((item) => insertListOf(item) === hit.list);
1068
+ if (owner !== void 0 && hit.list.items.length === 0 && owner.items.length === 1) {
1069
+ seq.items.splice(seq.items.indexOf(owner), 1);
1070
+ }
1006
1071
  savePatch(profileDirPath, doc);
1007
1072
  return true;
1008
1073
  }
package/lib/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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/restart.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 * Self-restart for standalone `dsh web`: relaunch the exact invocation that\n * booted this host, then stop this process \u2014 so MCP row changes compose\n * without leaving the UI. The desktop shell owns restarts there\n * (DSH_DESKTOP=1 refuses this path \u2014 a supervised sidecar must never\n * replace itself, or the supervisor respawns a second process).\n *\n * The replacement is spawned directly with windowsHide: CREATE_NO_WINDOW\n * gives it a hidden console its own console children inherit (no popping\n * windows), unlike a DETACHED_PROCESS spawn which leaves children to create\n * visible consoles. No helper process and no powershell wrapper \u2014 on at\n * least one machine a node\u2192node\u2192powershell\u2192node chain was silently blocked\n * by host software before the inner node could even start, while direct\n * node\u2192node spawns are the most battle-tested pattern there is.\n */\n\nimport { spawn } from 'node:child_process'\nimport { openSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { dirname, resolve } from 'node:path'\nimport type { IncomingMessage } from 'node:http'\n\n/** The boot invocation to replay: entry from argv, execArgv preserved. */\nexport function dshLaunch(argv: readonly string[] = process.argv, execArgv: readonly string[] = process.execArgv): {\n file: string\n args: string[]\n cwd: string | undefined\n viaShell: boolean\n} {\n const entry = argv[1]\n if (entry !== undefined && /[\\\\/](?:bin\\.(?:js|ts)|dsh)$/.test(entry)) {\n // Source launches (`pnpm dsh`) pass a relative entry that the child would\n // resolve against its OWN cwd \u2014 absolutize, and keep cwd near the entry\n // so execArgv module hooks (tsx/esm) stay resolvable.\n const abs = resolve(entry)\n return { file: process.execPath, args: [...execArgv, abs, ...argv.slice(2)], cwd: dirname(abs), viaShell: false }\n }\n // Bare `dsh` on Windows is a .cmd shim only a shell can start.\n return { file: 'dsh', args: [...argv.slice(2)], cwd: undefined, viaShell: process.platform === 'win32' }\n}\n\n/**\n * Relaunch this exact dsh invocation, then stop this process. The replacement\n * boots slowly (module loading) while this process dies within 500 ms, so\n * port handover needs no delay even for fixed-port launches. Replacement\n * output is logged under tmpdir for post-mortem.\n */\nexport function scheduleRestart(launch: ReturnType<typeof dshLaunch>): {\n pid: number\n replacementPid: number | undefined\n logOut: string\n logErr: string\n} {\n const stamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)\n const logOut = `${tmpdir()}${tmpdir().endsWith('/') ? '' : '\\\\'}dsh-plugin-capabilities-restart-${stamp}.out.log`\n const logErr = logOut.replace('.out.log', '.err.log')\n const child = spawn(launch.file, launch.args, {\n cwd: launch.cwd,\n stdio: ['ignore', openSync(logOut, 'a'), openSync(logErr, 'a')],\n env: process.env,\n shell: launch.viaShell,\n windowsHide: true,\n })\n child.unref()\n setTimeout(() => process.kill(process.pid, 'SIGTERM'), 500)\n return { pid: process.pid, replacementPid: child.pid, logOut, logErr }\n}\n\n/**\n * A restart request is process control: only a direct same-origin loopback\n * request qualifies. Any forwarding trace means the loopback peer is a\n * proxy, not the user's browser.\n */\nexport function trustedRestartRequest(request: IncomingMessage, socketAddress?: string): boolean {\n const address = socketAddress ?? (request.socket.remoteAddress ?? '')\n if (address !== '127.0.0.1' && address !== '::1' && address !== '::ffff:127.0.0.1') return false\n if (request.headers.forwarded !== undefined\n || request.headers['x-forwarded-for'] !== undefined\n || request.headers['x-real-ip'] !== undefined) return false\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/** Restart ownership: the desktop shell supervises the sidecar and restarts it. */\nexport function restartOwnedByShell(env: NodeJS.ProcessEnv = process.env): boolean {\n return env.DSH_DESKTOP === '1'\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 // The route casts raw JSON to McpInput; a create request may omit `id`.\n const id = input.id ?? ''\n if (id.includes('/') || 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 inputId = input.id ?? ''\n const doc = loadPatch(profileDirPath)\n const seq = rowSeq(doc)\n\n const existing = inputId !== ''\n ? mcpRows(doc).find(item => item.get('id') === inputId)\n : undefined\n\n let id = inputId !== '' ? inputId : `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 { dshLaunch, restartOwnedByShell, scheduleRestart, trustedRestartRequest } from './restart.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 host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/restart',\n handler: (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'POST') {\n response.writeHead(405, { allow: 'POST' })\n response.end()\n return\n }\n // \u8FDB\u7A0B\u63A7\u5236\uFF1A\u4EC5\u76F4\u63A5\u7684\u540C\u6E90\u56DE\u73AF\u8BF7\u6C42\uFF1B\u684C\u9762\u6A21\u5F0F\u4E0B\u91CD\u542F\u5F52\u58F3\u5C42\u6240\u6709\u3002\n if (!trustedRestartRequest(request)) {\n sendJson(response, 403, { error: 'untrusted origin' })\n return\n }\n if (restartOwnedByShell()) {\n sendJson(response, 409, { error: 'restart is owned by the desktop shell' })\n return\n }\n const { pid, replacementPid, logOut } = scheduleRestart(dshLaunch())\n sendJson(response, 200, { ok: true, pid, replacementPid, logOut })\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"]
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 * Self-restart for standalone `dsh web`: relaunch the exact invocation that\n * booted this host, then stop this process \u2014 so MCP row changes compose\n * without leaving the UI. The desktop shell owns restarts there\n * (DSH_DESKTOP=1 refuses this path \u2014 a supervised sidecar must never\n * replace itself, or the supervisor respawns a second process).\n *\n * The replacement is spawned directly with windowsHide: CREATE_NO_WINDOW\n * gives it a hidden console its own console children inherit (no popping\n * windows), unlike a DETACHED_PROCESS spawn which leaves children to create\n * visible consoles. No helper process and no powershell wrapper \u2014 on at\n * least one machine a node\u2192node\u2192powershell\u2192node chain was silently blocked\n * by host software before the inner node could even start, while direct\n * node\u2192node spawns are the most battle-tested pattern there is.\n */\n\nimport { spawn } from 'node:child_process'\nimport { openSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { dirname, resolve } from 'node:path'\nimport type { IncomingMessage } from 'node:http'\n\n/** The boot invocation to replay: entry from argv, execArgv preserved. */\nexport function dshLaunch(argv: readonly string[] = process.argv, execArgv: readonly string[] = process.execArgv): {\n file: string\n args: string[]\n cwd: string | undefined\n viaShell: boolean\n} {\n const entry = argv[1]\n if (entry !== undefined && /[\\\\/](?:bin\\.(?:js|ts)|dsh)$/.test(entry)) {\n // Source launches (`pnpm dsh`) pass a relative entry that the child would\n // resolve against its OWN cwd \u2014 absolutize, and keep cwd near the entry\n // so execArgv module hooks (tsx/esm) stay resolvable.\n const abs = resolve(entry)\n return { file: process.execPath, args: [...execArgv, abs, ...argv.slice(2)], cwd: dirname(abs), viaShell: false }\n }\n // Bare `dsh` on Windows is a .cmd shim only a shell can start.\n return { file: 'dsh', args: [...argv.slice(2)], cwd: undefined, viaShell: process.platform === 'win32' }\n}\n\n/**\n * Relaunch this exact dsh invocation, then stop this process. The replacement\n * boots slowly (module loading) while this process dies within 500 ms, so\n * port handover needs no delay even for fixed-port launches. Replacement\n * output is logged under tmpdir for post-mortem.\n */\nexport function scheduleRestart(launch: ReturnType<typeof dshLaunch>): {\n pid: number\n replacementPid: number | undefined\n logOut: string\n logErr: string\n} {\n const stamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)\n const logOut = `${tmpdir()}${tmpdir().endsWith('/') ? '' : '\\\\'}dsh-plugin-capabilities-restart-${stamp}.out.log`\n const logErr = logOut.replace('.out.log', '.err.log')\n const child = spawn(launch.file, launch.args, {\n cwd: launch.cwd,\n stdio: ['ignore', openSync(logOut, 'a'), openSync(logErr, 'a')],\n env: process.env,\n shell: launch.viaShell,\n windowsHide: true,\n })\n child.unref()\n setTimeout(() => process.kill(process.pid, 'SIGTERM'), 500)\n return { pid: process.pid, replacementPid: child.pid, logOut, logErr }\n}\n\n/**\n * A restart request is process control: only a direct same-origin loopback\n * request qualifies. Any forwarding trace means the loopback peer is a\n * proxy, not the user's browser.\n */\nexport function trustedRestartRequest(request: IncomingMessage, socketAddress?: string): boolean {\n const address = socketAddress ?? (request.socket.remoteAddress ?? '')\n if (address !== '127.0.0.1' && address !== '::1' && address !== '::ffff:127.0.0.1') return false\n if (request.headers.forwarded !== undefined\n || request.headers['x-forwarded-for'] !== undefined\n || request.headers['x-real-ip'] !== undefined) return false\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/** Restart ownership: the desktop shell supervises the sidecar and restarts it. */\nexport function restartOwnedByShell(env: NodeJS.ProcessEnv = process.env): boolean {\n return env.DSH_DESKTOP === '1'\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 * The loader's patch grammar distinguishes creates from overrides: a bare\n * `- id: \u2026` entry only overrides an existing row (target missing \u2192 skipped\n * with a warning), while new rows must live in an anonymous `- insert:`\n * list. Managed rows therefore always sit inside one insert entry, and any\n * legacy bare rows (written before this contract was understood) are\n * absorbed into it on the next write.\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 const doc = parseDocument(text)\n const contents = doc.contents as YAMLSeq | null\n // The default-empty file parses as a flow `[]`; the patch layer is\n // human-edited block YAML, so flip the flag before anything appends.\n if (contents !== null && contents.flow === true && contents.items.length === 0) contents.flow = false\n return doc\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) {\n doc.contents = toNode<YAMLSeq<YAMLMap>>([])\n // An empty seq defaults to flow style (`[]`); the file must stay block.\n ;(doc.contents as YAMLSeq).flow = false\n }\n return doc.contents as YAMLSeq<YAMLMap>\n}\n\nfunction isSeqNode(value: unknown): value is YAMLSeq<YAMLMap> {\n return typeof value === 'object' && value !== null && Array.isArray((value as YAMLSeq).items)\n}\n\n/** A patch entry's insert list when it is the anonymous create form. */\nfunction insertListOf(item: YAMLMap): YAMLSeq<YAMLMap> | undefined {\n if (item.has('id')) return undefined\n const node = item.get('insert')\n return isSeqNode(node) ? node : undefined\n}\n\n/** Every managed row: legacy bare entries (no list) and insert-list rows. */\nfunction mcpRowItems(doc: Document): { node: YAMLMap, list?: YAMLSeq<YAMLMap> }[] {\n const found: { node: YAMLMap, list?: YAMLSeq<YAMLMap> }[] = []\n for (const item of rowSeq(doc).items ?? []) {\n if (item.get('name') === MCP_PLUGIN) found.push({ node: item })\n const list = insertListOf(item)\n for (const row of list?.items ?? []) {\n if (row.get('name') === MCP_PLUGIN) found.push({ node: row, list })\n }\n }\n return found\n}\n\n/** Map one row node to its browser-facing shape. */\nfunction rowToMcp(doc: Document, item: YAMLMap): McpRow {\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\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/**\n * The insert list that owns managed rows, creating it when absent and\n * absorbing legacy bare rows into it. Absorbed rows were inert under the\n * loader's override-only reading of bare entries, so the move is not just\n * cosmetic \u2014 it is what makes them compose.\n */\nfunction managedInsert(doc: Document): YAMLSeq<YAMLMap> {\n const seq = rowSeq(doc)\n const bare: YAMLMap[] = []\n let target: YAMLSeq<YAMLMap> | undefined\n for (const item of seq.items ?? []) {\n if (item.get('name') === MCP_PLUGIN) bare.push(item)\n const list = insertListOf(item)\n if (list !== undefined && list.items.some(row => row.get('name') === MCP_PLUGIN)) target ??= list\n }\n if (target === undefined) {\n const entry = toNode<YAMLMap>({ insert: [] })\n seq.add(entry)\n target = entry.get('insert') as YAMLSeq<YAMLMap>\n target.flow = false\n }\n for (const row of bare) {\n seq.items.splice(seq.items.indexOf(row), 1)\n target.add(row)\n }\n return target\n}\n\n/** Every id in use: top-level patch entries and rows inside insert lists. */\nfunction takenIds(doc: Document): Set<string> {\n const taken = new Set<string>()\n for (const item of rowSeq(doc).items ?? []) {\n const id = String(item.get('id') ?? '')\n if (id !== '') taken.add(id)\n for (const row of insertListOf(item)?.items ?? []) {\n const rowId = String(row.get('id') ?? '')\n if (rowId !== '') taken.add(rowId)\n }\n }\n return taken\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 mcpRowItems(doc).map(({ node }) => rowToMcp(doc, node))\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 // The route casts raw JSON to McpInput; a create request may omit `id`.\n const id = input.id ?? ''\n if (id.includes('/') || 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 inputId = input.id ?? ''\n const doc = loadPatch(profileDirPath)\n const list = managedInsert(doc)\n\n const existing = inputId !== ''\n ? mcpRowItems(doc).find(({ node }) => String(node.get('id') ?? '') === inputId)\n : undefined\n\n let id = inputId !== '' ? inputId : `mcp-${input.serverName}`\n if (existing === undefined) {\n const taken = takenIds(doc)\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) {\n list.add(node)\n } else if (existing.list !== undefined) {\n existing.list.items.splice(existing.list.items.indexOf(existing.node), 1, node)\n } else {\n // Bare rows were absorbed above; reaching here means a foreign-shaped row.\n rowSeq(doc).items.splice(rowSeq(doc).items.indexOf(existing.node), 1, node)\n }\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 managedInsert(doc)\n const hit = mcpRowItems(doc).find(({ node }) => String(node.get('id') ?? '') === id)\n if (hit === undefined) return false\n if (disabled) hit.node.set('disabled', true)\n else hit.node.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 managedInsert(doc)\n const hit = mcpRowItems(doc).find(({ node }) => String(node.get('id') ?? '') === id)\n if (hit === undefined || hit.list === undefined) return false\n hit.list.items.splice(hit.list.items.indexOf(hit.node), 1)\n\n // An insert entry left with no rows is dead weight; drop it when the\n // insert list is all it holds.\n const seq = rowSeq(doc)\n const owner = (seq.items ?? []).find(item => insertListOf(item) === hit.list)\n if (owner !== undefined && hit.list.items.length === 0 && owner.items.length === 1) {\n seq.items.splice(seq.items.indexOf(owner), 1)\n }\n\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 { dshLaunch, restartOwnedByShell, scheduleRestart, trustedRestartRequest } from './restart.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 host.webServer.register({\n kind: 'exact',\n path: '/dsh-plugin-capabilities/restart',\n handler: (request: IncomingMessage, response: ServerResponse) => {\n if (request.method !== 'POST') {\n response.writeHead(405, { allow: 'POST' })\n response.end()\n return\n }\n // \u8FDB\u7A0B\u63A7\u5236\uFF1A\u4EC5\u76F4\u63A5\u7684\u540C\u6E90\u56DE\u73AF\u8BF7\u6C42\uFF1B\u684C\u9762\u6A21\u5F0F\u4E0B\u91CD\u542F\u5F52\u58F3\u5C42\u6240\u6709\u3002\n if (!trustedRestartRequest(request)) {\n sendJson(response, 403, { error: 'untrusted origin' })\n return\n }\n if (restartOwnedByShell()) {\n sendJson(response, 409, { error: 'restart is owned by the desktop shell' })\n return\n }\n const { pid, replacementPid, logOut } = scheduleRestart(dshLaunch())\n sendJson(response, 200, { ok: true, pid, replacementPid, logOut })\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", "node", "name"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-capabilities",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Manage skills and MCP servers from the Web UI Settings. 在设置页管理 dsh 的技能与 MCP 服务器。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -14,7 +14,14 @@
14
14
  "url": "https://github.com/qinyre/dsh-plugin-capabilities/issues"
15
15
  },
16
16
  "homepage": "https://github.com/qinyre/dsh-plugin-capabilities#readme",
17
- "keywords": ["deepseek", "harness", "dsh", "dsh-plugin", "skills", "mcp"],
17
+ "keywords": [
18
+ "deepseek",
19
+ "harness",
20
+ "dsh",
21
+ "dsh-plugin",
22
+ "skills",
23
+ "mcp"
24
+ ],
18
25
  "dsh": {
19
26
  "bundle": {
20
27
  "patch": "./cordis.patch.yml"
@@ -36,7 +43,12 @@
36
43
  "./cordis.patch.yml": "./cordis.patch.yml",
37
44
  "./package.json": "./package.json"
38
45
  },
39
- "files": ["lib", "src", "cordis.patch.yml", "LICENSE"],
46
+ "files": [
47
+ "lib",
48
+ "src",
49
+ "cordis.patch.yml",
50
+ "LICENSE"
51
+ ],
40
52
  "scripts": {
41
53
  "build": "node scripts/build-node.mjs && node scripts/build-client.mjs && node scripts/verify-bundle.mjs",
42
54
  "prepare": "node scripts/build-node.mjs && node scripts/build-client.mjs && node scripts/verify-bundle.mjs",
package/src/mcp.test.ts CHANGED
@@ -44,6 +44,41 @@ describe('profile patch CRUD', () => {
44
44
  expect(rows[0].env).toEqual({ GITHUB_TOKEN: 'secret' })
45
45
  })
46
46
 
47
+ it('writes rows inside an anonymous insert list, never as bare entries', () => {
48
+ // The loader skips bare `- id:` entries whose target does not exist;
49
+ // only `- insert:` rows mount. This is the contract that made 0.1.2
50
+ // rows invisible to the agent.
51
+ const text = readFileSync(patch(), 'utf8')
52
+ expect(text).toContain('- insert:')
53
+ expect(text).not.toMatch(/^- id: mcp-/m)
54
+ expect(text).toMatch(/^ {4}- id: mcp-github$/m)
55
+ })
56
+
57
+ it('absorbs legacy bare rows into the insert list on the next write', () => {
58
+ writeFileSync(patch(), [
59
+ '- id: dsh-market',
60
+ ' config:',
61
+ ' allowRestart: false',
62
+ '- id: mcp-open-websearch',
63
+ ' name: "@deepseek-ai/dsh-mcp-client"',
64
+ ' config:',
65
+ ' serverName: open-websearch',
66
+ ' transport: stdio',
67
+ ' command: npx',
68
+ '',
69
+ ].join('\n'))
70
+
71
+ expect(listMcp(profile)).toHaveLength(1)
72
+ expect(listMcp(profile)[0]).toMatchObject({ id: 'mcp-open-websearch', serverName: 'open-websearch' })
73
+
74
+ upsertMcp(profile, { id: '', serverName: 'context7', transport: 'stdio', command: 'npx' })
75
+ const text = readFileSync(patch(), 'utf8')
76
+ expect(text).not.toMatch(/^- id: mcp-open-websearch/m)
77
+ expect(text).toMatch(/^ {4}- id: mcp-open-websearch$/m)
78
+ expect(text).toContain('dsh-market')
79
+ expect(listMcp(profile)).toHaveLength(2)
80
+ })
81
+
47
82
  it('preserves foreign rows and comments across edits', () => {
48
83
  writeFileSync(patch(), [
49
84
  '# user comment',
@@ -90,4 +125,11 @@ describe('profile patch CRUD', () => {
90
125
  expect(listMcp(profile).find(row => row.id === 'mcp-github')).toBeUndefined()
91
126
  expect(removeMcp(profile, 'mcp-github')).toBe(false)
92
127
  })
128
+
129
+ it('drops the insert entry once its last row is removed', () => {
130
+ for (const row of listMcp(profile)) removeMcp(profile, row.id)
131
+ const text = readFileSync(patch(), 'utf8')
132
+ expect(text).not.toContain('- insert:')
133
+ expect(listMcp(profile)).toHaveLength(0)
134
+ })
93
135
  })
package/src/mcp.ts CHANGED
@@ -3,6 +3,13 @@
3
3
  * `@deepseek-ai/dsh-mcp-client` row per server. The YAML document API keeps
4
4
  * foreign rows and comments intact across edits. Row changes need a dsh
5
5
  * restart to compose — callers surface that as a pending-restart notice.
6
+ *
7
+ * The loader's patch grammar distinguishes creates from overrides: a bare
8
+ * `- id: …` entry only overrides an existing row (target missing → skipped
9
+ * with a warning), while new rows must live in an anonymous `- insert:`
10
+ * list. Managed rows therefore always sit inside one insert entry, and any
11
+ * legacy bare rows (written before this contract was understood) are
12
+ * absorbed into it on the next write.
6
13
  */
7
14
 
8
15
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
@@ -38,7 +45,12 @@ export type McpInput = Omit<McpRow, 'disabled'> & { disabled?: boolean }
38
45
  function loadPatch(profileDirPath: string): Document {
39
46
  const path = join(profileDirPath, 'cordis.patch.yml')
40
47
  const text = existsSync(path) ? readFileSync(path, 'utf8') : '[]'
41
- return parseDocument(text)
48
+ const doc = parseDocument(text)
49
+ const contents = doc.contents as YAMLSeq | null
50
+ // The default-empty file parses as a flow `[]`; the patch layer is
51
+ // human-edited block YAML, so flip the flag before anything appends.
52
+ if (contents !== null && contents.flow === true && contents.items.length === 0) contents.flow = false
53
+ return doc
42
54
  }
43
55
 
44
56
  function savePatch(profileDirPath: string, doc: Document): void {
@@ -53,13 +65,57 @@ function toNode<T>(value: unknown): T {
53
65
 
54
66
  /** The patch row sequence; an empty file's null root becomes an empty seq. */
55
67
  function rowSeq(doc: Document): YAMLSeq<YAMLMap> {
56
- if (doc.contents === null) doc.contents = toNode<YAMLSeq<YAMLMap>>([])
68
+ if (doc.contents === null) {
69
+ doc.contents = toNode<YAMLSeq<YAMLMap>>([])
70
+ // An empty seq defaults to flow style (`[]`); the file must stay block.
71
+ ;(doc.contents as YAMLSeq).flow = false
72
+ }
57
73
  return doc.contents as YAMLSeq<YAMLMap>
58
74
  }
59
75
 
60
- /** Rows whose `name` is the MCP client plugin. */
61
- function mcpRows(doc: Document): YAMLMap[] {
62
- return (rowSeq(doc).items ?? []).filter(item => item.get('name') === MCP_PLUGIN)
76
+ function isSeqNode(value: unknown): value is YAMLSeq<YAMLMap> {
77
+ return typeof value === 'object' && value !== null && Array.isArray((value as YAMLSeq).items)
78
+ }
79
+
80
+ /** A patch entry's insert list when it is the anonymous create form. */
81
+ function insertListOf(item: YAMLMap): YAMLSeq<YAMLMap> | undefined {
82
+ if (item.has('id')) return undefined
83
+ const node = item.get('insert')
84
+ return isSeqNode(node) ? node : undefined
85
+ }
86
+
87
+ /** Every managed row: legacy bare entries (no list) and insert-list rows. */
88
+ function mcpRowItems(doc: Document): { node: YAMLMap, list?: YAMLSeq<YAMLMap> }[] {
89
+ const found: { node: YAMLMap, list?: YAMLSeq<YAMLMap> }[] = []
90
+ for (const item of rowSeq(doc).items ?? []) {
91
+ if (item.get('name') === MCP_PLUGIN) found.push({ node: item })
92
+ const list = insertListOf(item)
93
+ for (const row of list?.items ?? []) {
94
+ if (row.get('name') === MCP_PLUGIN) found.push({ node: row, list })
95
+ }
96
+ }
97
+ return found
98
+ }
99
+
100
+ /** Map one row node to its browser-facing shape. */
101
+ function rowToMcp(doc: Document, item: YAMLMap): McpRow {
102
+ // config is a YAMLMap node — materialize it before property access.
103
+ const configNode = item.get('config') as unknown
104
+ const plain = (typeof configNode === 'object' && configNode !== null && typeof (configNode as { toJS?: unknown }).toJS === 'function'
105
+ ? (configNode as { toJS(document: Document): unknown }).toJS(doc)
106
+ : {}) as Record<string, unknown>
107
+ return {
108
+ id: String(item.get('id') ?? ''),
109
+ serverName: String(plain.serverName ?? ''),
110
+ transport: plain.transport === 'streamable-http' ? 'streamable-http' : 'stdio',
111
+ disabled: item.get('disabled') === true,
112
+ ...(typeof plain.command === 'string' && plain.command !== '' ? { command: plain.command } : {}),
113
+ ...(Array.isArray(plain.args) ? { args: plain.args.map(String) } : {}),
114
+ ...(isStringMap(plain.env) ? { env: plain.env } : {}),
115
+ ...(typeof plain.cwd === 'string' && plain.cwd !== '' ? { cwd: plain.cwd } : {}),
116
+ ...(typeof plain.url === 'string' && plain.url !== '' ? { url: plain.url } : {}),
117
+ ...(isStringMap(plain.headers) ? { headers: plain.headers } : {}),
118
+ }
63
119
  }
64
120
 
65
121
  function isStringMap(value: unknown): value is Record<string, string> {
@@ -67,28 +123,52 @@ function isStringMap(value: unknown): value is Record<string, string> {
67
123
  return Object.values(value).every(entry => typeof entry === 'string')
68
124
  }
69
125
 
126
+ /**
127
+ * The insert list that owns managed rows, creating it when absent and
128
+ * absorbing legacy bare rows into it. Absorbed rows were inert under the
129
+ * loader's override-only reading of bare entries, so the move is not just
130
+ * cosmetic — it is what makes them compose.
131
+ */
132
+ function managedInsert(doc: Document): YAMLSeq<YAMLMap> {
133
+ const seq = rowSeq(doc)
134
+ const bare: YAMLMap[] = []
135
+ let target: YAMLSeq<YAMLMap> | undefined
136
+ for (const item of seq.items ?? []) {
137
+ if (item.get('name') === MCP_PLUGIN) bare.push(item)
138
+ const list = insertListOf(item)
139
+ if (list !== undefined && list.items.some(row => row.get('name') === MCP_PLUGIN)) target ??= list
140
+ }
141
+ if (target === undefined) {
142
+ const entry = toNode<YAMLMap>({ insert: [] })
143
+ seq.add(entry)
144
+ target = entry.get('insert') as YAMLSeq<YAMLMap>
145
+ target.flow = false
146
+ }
147
+ for (const row of bare) {
148
+ seq.items.splice(seq.items.indexOf(row), 1)
149
+ target.add(row)
150
+ }
151
+ return target
152
+ }
153
+
154
+ /** Every id in use: top-level patch entries and rows inside insert lists. */
155
+ function takenIds(doc: Document): Set<string> {
156
+ const taken = new Set<string>()
157
+ for (const item of rowSeq(doc).items ?? []) {
158
+ const id = String(item.get('id') ?? '')
159
+ if (id !== '') taken.add(id)
160
+ for (const row of insertListOf(item)?.items ?? []) {
161
+ const rowId = String(row.get('id') ?? '')
162
+ if (rowId !== '') taken.add(rowId)
163
+ }
164
+ }
165
+ return taken
166
+ }
167
+
70
168
  /** Read every mcp-client row in the profile layer. */
71
169
  export function listMcp(profileDirPath: string): McpRow[] {
72
170
  const doc = loadPatch(profileDirPath)
73
- return mcpRows(doc).map(item => {
74
- // config is a YAMLMap node — materialize it before property access.
75
- const configNode = item.get('config') as unknown
76
- const plain = (typeof configNode === 'object' && configNode !== null && typeof (configNode as { toJS?: unknown }).toJS === 'function'
77
- ? (configNode as { toJS(document: Document): unknown }).toJS(doc)
78
- : {}) as Record<string, unknown>
79
- return {
80
- id: String(item.get('id') ?? ''),
81
- serverName: String(plain.serverName ?? ''),
82
- transport: plain.transport === 'streamable-http' ? 'streamable-http' : 'stdio',
83
- disabled: item.get('disabled') === true,
84
- ...(typeof plain.command === 'string' && plain.command !== '' ? { command: plain.command } : {}),
85
- ...(Array.isArray(plain.args) ? { args: plain.args.map(String) } : {}),
86
- ...(isStringMap(plain.env) ? { env: plain.env } : {}),
87
- ...(typeof plain.cwd === 'string' && plain.cwd !== '' ? { cwd: plain.cwd } : {}),
88
- ...(typeof plain.url === 'string' && plain.url !== '' ? { url: plain.url } : {}),
89
- ...(isStringMap(plain.headers) ? { headers: plain.headers } : {}),
90
- }
91
- })
171
+ return mcpRowItems(doc).map(({ node }) => rowToMcp(doc, node))
92
172
  }
93
173
 
94
174
  /** Validate one write request; returns the rejection reason or null. */
@@ -109,17 +189,15 @@ export function validateMcpInput(input: McpInput): string | null {
109
189
  export function upsertMcp(profileDirPath: string, input: McpInput): string {
110
190
  const inputId = input.id ?? ''
111
191
  const doc = loadPatch(profileDirPath)
112
- const seq = rowSeq(doc)
192
+ const list = managedInsert(doc)
113
193
 
114
194
  const existing = inputId !== ''
115
- ? mcpRows(doc).find(item => item.get('id') === inputId)
195
+ ? mcpRowItems(doc).find(({ node }) => String(node.get('id') ?? '') === inputId)
116
196
  : undefined
117
197
 
118
198
  let id = inputId !== '' ? inputId : `mcp-${input.serverName}`
119
199
  if (existing === undefined) {
120
- const taken = new Set(
121
- (seq.items ?? []).map(item => String(item.get('id') ?? '')).filter(id => id !== ''),
122
- )
200
+ const taken = takenIds(doc)
123
201
  let suffix = 2
124
202
  while (taken.has(id)) id = `mcp-${input.serverName}-${suffix++}`
125
203
  }
@@ -143,8 +221,14 @@ export function upsertMcp(profileDirPath: string, input: McpInput): string {
143
221
  if (input.disabled === true) row.disabled = true
144
222
 
145
223
  const node = toNode<YAMLMap>(row)
146
- if (existing === undefined) seq.add(node)
147
- else seq.items[seq.items.indexOf(existing)] = node
224
+ if (existing === undefined) {
225
+ list.add(node)
226
+ } else if (existing.list !== undefined) {
227
+ existing.list.items.splice(existing.list.items.indexOf(existing.node), 1, node)
228
+ } else {
229
+ // Bare rows were absorbed above; reaching here means a foreign-shaped row.
230
+ rowSeq(doc).items.splice(rowSeq(doc).items.indexOf(existing.node), 1, node)
231
+ }
148
232
 
149
233
  savePatch(profileDirPath, doc)
150
234
  return id
@@ -153,10 +237,11 @@ export function upsertMcp(profileDirPath: string, input: McpInput): string {
153
237
  /** Flip one row's disabled flag (absent = enabled). Returns false when missing. */
154
238
  export function setMcpDisabled(profileDirPath: string, id: string, disabled: boolean): boolean {
155
239
  const doc = loadPatch(profileDirPath)
156
- const item = mcpRows(doc).find(row => row.get('id') === id)
157
- if (item === undefined) return false
158
- if (disabled) item.set('disabled', true)
159
- else item.delete('disabled')
240
+ managedInsert(doc)
241
+ const hit = mcpRowItems(doc).find(({ node }) => String(node.get('id') ?? '') === id)
242
+ if (hit === undefined) return false
243
+ if (disabled) hit.node.set('disabled', true)
244
+ else hit.node.delete('disabled')
160
245
  savePatch(profileDirPath, doc)
161
246
  return true
162
247
  }
@@ -164,10 +249,19 @@ export function setMcpDisabled(profileDirPath: string, id: string, disabled: boo
164
249
  /** Remove one server row. Returns false when missing. */
165
250
  export function removeMcp(profileDirPath: string, id: string): boolean {
166
251
  const doc = loadPatch(profileDirPath)
167
- const item = mcpRows(doc).find(row => row.get('id') === id)
168
- if (item === undefined) return false
252
+ managedInsert(doc)
253
+ const hit = mcpRowItems(doc).find(({ node }) => String(node.get('id') ?? '') === id)
254
+ if (hit === undefined || hit.list === undefined) return false
255
+ hit.list.items.splice(hit.list.items.indexOf(hit.node), 1)
256
+
257
+ // An insert entry left with no rows is dead weight; drop it when the
258
+ // insert list is all it holds.
169
259
  const seq = rowSeq(doc)
170
- seq.items.splice(seq.items.indexOf(item), 1)
260
+ const owner = (seq.items ?? []).find(item => insertListOf(item) === hit.list)
261
+ if (owner !== undefined && hit.list.items.length === 0 && owner.items.length === 1) {
262
+ seq.items.splice(seq.items.indexOf(owner), 1)
263
+ }
264
+
171
265
  savePatch(profileDirPath, doc)
172
266
  return true
173
267
  }