buddy-agent-harness 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/dist/index.d.mts +39 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +151 -6
- package/dist/index.mjs.map +1 -1
- package/dist/skill-scripts/doctor.mjs +1 -1
- package/dist/skill-scripts/init.mjs +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/skills/doctor/SKILL.md +1 -1
- package/skills/doctor/scripts/doctor.mjs +1 -1
- package/skills/init/SKILL.md +1 -1
- package/skills/init/scripts/doctor.mjs +1 -1
- package/skills/init/scripts/init.mjs +1 -1
- package/skills/repair/SKILL.md +1 -1
- package/skills/repair/scripts/doctor.mjs +1 -1
- package/src/diagnose-mcp/mcp-secrets.ts +17 -0
- package/src/index.ts +2 -0
- package/src/mcp-inventory/mcp-inventory.ts +165 -0
package/dist/index.d.mts
CHANGED
|
@@ -598,5 +598,43 @@ type InitializeResult = {
|
|
|
598
598
|
};
|
|
599
599
|
export declare function initializeHarnesses({ root, harnesses: preferred, copy, force }: InitializeOptions): InitializeResult;
|
|
600
600
|
//#endregion
|
|
601
|
-
|
|
601
|
+
//#region src/mcp-inventory/mcp-inventory.d.ts
|
|
602
|
+
/** One configured MCP server, redacted of everything that could carry a credential. */
|
|
603
|
+
type McpServerEntry = {
|
|
604
|
+
harness: HarnessName;
|
|
605
|
+
scope: HarnessScopeName;
|
|
606
|
+
/** The absolute path of the config file this entry was read from. */
|
|
607
|
+
configFile: string;
|
|
608
|
+
/** The name the server is declared under. */
|
|
609
|
+
name: string;
|
|
610
|
+
transport: McpTransport | undefined;
|
|
611
|
+
/** The command's basename, never its full path. */
|
|
612
|
+
command: string | undefined;
|
|
613
|
+
/** `args`, with any credential-bearing `--flag=value` pair dropped. */
|
|
614
|
+
args: readonly string[];
|
|
615
|
+
/** The URL's origin and path, never its query string. */
|
|
616
|
+
url: string | undefined;
|
|
617
|
+
enabled: boolean;
|
|
618
|
+
};
|
|
619
|
+
type ListMcpServersOptions = {
|
|
620
|
+
/** The project directory to read project-scope configuration from. */
|
|
621
|
+
projectDir: string;
|
|
622
|
+
/** Overrides `os.homedir()`, for a test that must not touch the real one. */
|
|
623
|
+
homeDir?: string;
|
|
624
|
+
/** Overrides `process.env`, for a test — read only for `CODEX_HOME` and `COPILOT_HOME`. */
|
|
625
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
626
|
+
};
|
|
627
|
+
/**
|
|
628
|
+
* Every MCP server configured for a project, across every supported harness and every scope that
|
|
629
|
+
* harness documents — without ever surfacing a credential.
|
|
630
|
+
*
|
|
631
|
+
* Reuses `diagnoseMcp`'s own parsing (`parseTarget`), model (`McpServer`), and redaction
|
|
632
|
+
* (`nonSecretArgs`, and the URL/command trimming this module adds) rather than re-reading or
|
|
633
|
+
* re-parsing any of the supported harnesses' MCP files. A harness with no file present, or one whose
|
|
634
|
+
* file does not parse, contributes no entries; this function reports an inventory, not a diagnosis,
|
|
635
|
+
* so it has nothing to say about why a file is missing or broken.
|
|
636
|
+
*/
|
|
637
|
+
export declare function listMcpServers(options: ListMcpServersOptions): McpServerEntry[];
|
|
638
|
+
//#endregion
|
|
639
|
+
export type { BridgeFinding, BridgeKind, BridgeProblem, BridgeReport, BridgeStatus, ConfigurationFault, ConfigurationProblem, DiagnoseMcpOptions, DiagnoseOptions, DiagnoseResult, DivergenceDirection, DivergenceReport, DoctorProblem, DoctorReport, Harness, HarnessName, HarnessScope, HarnessScopeName, InitializeOptions, InitializeResult, InstructionBridge, InstructionKind, InstructionProblem, InstructionReport, InstructionStatus, ListMcpServersOptions, McpConfig, McpDirection, McpField, McpProblem, McpServer, McpServerEntry, McpTransport, Repair };
|
|
602
640
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/cli.ts","../src/harness-registry/instruction-bridge.ts","../src/harness-registry/mcp-config.ts","../src/harness-registry/nonstandard-artifact.ts","../src/harness-registry/harness-registry.ts","../src/diagnose-bridges/diagnose-instructions.ts","../src/diagnose-bridges/locator.ts","../src/diagnose-bridges/doctor-guidance.ts","../src/diagnose-bridges/git-bridge-state.ts","../src/diagnose-bridges/diagnose-bridges.ts","../src/diagnose-configuration/diagnose-configuration.ts","../src/diagnose-bridges/doctor.command.ts","../src/diagnose-mcp/diagnose-mcp.ts","../src/diagnose-mcp/mcp-model.ts","../src/diagnose-mcp/mcp-baseline.ts","../src/diagnose-mcp/mcp-sources.ts","../src/initialize-harnesses/init.command.ts","../src/skill-projection/skill-projection.ts","../src/initialize-harnesses/initialize-harnesses.ts"],"mappings":";;;;;;;;;;;;;wBAiDsB,IAAI,iBAAiB;;;;;;;;;;;;;;;KCrC/B;;;;;;EAOT;;EAEA;;;EAIA;;EAEA;;EAEA;;;;;;;;;;;;;;;;;;;;KCbS;;EAEX;;;;;;EAMA;;;;;EAKA;;;;;;EAMA;;;;;;;;;;;;;;;;;KCtBW;KAgBA;;;;;EAKX;;EAEA;EACA,MAAM;;;;KC/BK;;KAUA;;;;;;;;;;;;;;;;;;;;;;;;;KA0BA;EACX;EACA;EACA,oBAAoB;EACpB,YAAY;EACZ,uBAAuB;;KAGZ;EACX,MAAM;;EAEN,SAAS;;;;;EAKT,OAAO;;EAEP,aAAa;;;;;;;;;;;;;;;;;;;;;;qBAuBD,0BAA0B;;;;KCzE3B;;;;;;KAMA;KAEA;EACX,SAAS;;EAET;EACA,MAAM;EACN,QAAQ;;;;;;;;;;wBAkFO,qBACf,cACA,oBAAoB,WACpB;EACI,cAAc;EAAqB,UAAU;;;;;;;;;;;;;;;;;;;;KC5FtC;EAAa;EAAc;;KAE3B;;EAEX;;EAEA;;EAEA;;EAEA,WAAW;;;;;;;;;;KCbA;;;;;;;;;;;KAqBA;;;;;;;;;KAUA;;;;;;;;;KAoBA;KAOA;;KAOA,gBAAgB,gBAAgB,qBAAqB,qBAAqB,aAAa;;KAGvF,uBAAuB;;;;;;;;;;;;;;;;;;KAmBvB;;EAEX;;EAEA;;KAGW;EACX,SAAS;;EAET;;;;;;;EAOA,OAAO,IAAI,SAAS,cAAc;;;;;;EAMlC,YAAY,IAAI;;qBAyLJ,wBAAwB;qBA4CxB,6BAA6B;qBAuM7B,wBAAwB;qBAOxB;WACZ;WACA;;;;;;;;;;wBAmCe,kBAAkB;;;;KC/kBtB;;KAGA;;;;;;cAwBC;mBAIA;;mBAFK;EAEjB,YAAY;;;;;;EASZ,WAAW,eAAe;;;;;;;EAa1B,UAAU;;;;;;;;;EAaV,gBAAgB;;EAMhB,UAAU,gBAAgB;;;;;EAS1B,YAAY,gBAAgB,oBAAoB;;UAYxC;;;;;UAmBA;;;;KC5GG;KACA;KAEA;EACX,SAAS;;EAET;EACA,MAAM;EACN,QAAQ;;KAGG;EACX;;;;;EAKA,SAAS;EACT;;EAEA,QAAQ;;KAGG;EACX;EACA,WAAW;;KAGA;EACX;EACA,YAAY;;EAEZ;;KAGW;EACX,SAAS;;;;;EAKT,cAAc;EACd,YAAY;EACZ,UAAU;;;;;;;wBA2EK,kBAAkB,MAAM,WAAW,WAAgB,OAAO,kBAAkB;;;;;;;;;;;;;;;;;KC1GhF;;EAEX;EACA,SAAS;EACT;;EAEA,QAAQ;;;;KCfG;EACX;EACA,SAAS;EACT,cAAc;EACd,aAAa;;;;;EAKb;IAAY;IAAc,SAAS;IAAe;;;;;;;;;;EASlD,OAAO;;;;;;wBAOQ,kBACf,aACA,QAAQ,gBACR,gBAAe,yBACb;qBAgCU,eAAe,MAAI;;;;;;;;;;;;;;;;;;KC7CpB;EACX;EACA,KAAK;;EAEL;;wBAgCe,cAAc,MAAM,KAAK,OAAO,qBAAqB;;;;;;;;;;;;;;;;KClDzD;KAEA;EACX,YAAY;EACZ;EACA;EACA,MAAM,SAAS;EACf;EACA,UAAU,SAAS;EACnB;EACA;EACA;EACA;;;cAIY;KAaD,mBAAmB;;;;KCnCnB;;;;qBCAC;;;qBCAA,aAAa,MAAI;qBAoDjB,gBAAgB,MAAI;wBAMjB,WAAW;EAAgB,WAAW,gBAAgB;;;;;;;;;KCV1D;;;KCpDA;EACX;EACA,YAAY;EACZ;EACA,QAAQ;;KAEG;EACX;EACA,WAAW;EACX,QAAQ;EACR,QAAQ;;EAER,SAAS;;EAET;IAAc,MAAM;IAAa,YAAY;;EAC7C;EACA;;wBAGe,sBACf,MACA,WAAW,WACX,MACA,SACE,oBAAoB"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/cli.ts","../src/harness-registry/instruction-bridge.ts","../src/harness-registry/mcp-config.ts","../src/harness-registry/nonstandard-artifact.ts","../src/harness-registry/harness-registry.ts","../src/diagnose-bridges/diagnose-instructions.ts","../src/diagnose-bridges/locator.ts","../src/diagnose-bridges/doctor-guidance.ts","../src/diagnose-bridges/git-bridge-state.ts","../src/diagnose-bridges/diagnose-bridges.ts","../src/diagnose-configuration/diagnose-configuration.ts","../src/diagnose-bridges/doctor.command.ts","../src/diagnose-mcp/diagnose-mcp.ts","../src/diagnose-mcp/mcp-model.ts","../src/diagnose-mcp/mcp-baseline.ts","../src/diagnose-mcp/mcp-sources.ts","../src/initialize-harnesses/init.command.ts","../src/skill-projection/skill-projection.ts","../src/initialize-harnesses/initialize-harnesses.ts","../src/mcp-inventory/mcp-inventory.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { cli, command, exitCodes, z } from "clibuilder";
|
|
4
4
|
import { homedir, platform } from "node:os";
|
|
5
|
-
import { dirname, join, posix, relative, resolve, sep } from "node:path";
|
|
5
|
+
import { basename, dirname, join, posix, relative, resolve, sep } from "node:path";
|
|
6
6
|
import { encode } from "@toon-format/toon";
|
|
7
7
|
import { parse } from "smol-toml";
|
|
8
8
|
import { execFileSync } from "node:child_process";
|
|
@@ -1831,9 +1831,25 @@ function credentialFields(server) {
|
|
|
1831
1831
|
...server.url && urlHoldsCredential(server.url) ? ["url"] : []
|
|
1832
1832
|
];
|
|
1833
1833
|
}
|
|
1834
|
+
/**
|
|
1835
|
+
* `args` with any `--flag=value` pair dropped whose flag names a credential and whose value is a
|
|
1836
|
+
* literal rather than a reference — the same test `credentialKey` and `holdsLiteral` apply to `env`
|
|
1837
|
+
* and `headers`, applied here to the one field that carries names and values in a single string
|
|
1838
|
+
* instead of a map.
|
|
1839
|
+
*
|
|
1840
|
+
* A positional argument, or a flag with no `=`, passes through unfiltered: `-y` and a package name
|
|
1841
|
+
* are not a place a credential's value is written, and there is no key in either to test.
|
|
1842
|
+
*/
|
|
1843
|
+
function nonSecretArgs(args) {
|
|
1844
|
+
return (args ?? []).filter((arg) => {
|
|
1845
|
+
const at = arg.indexOf("=");
|
|
1846
|
+
if (at === -1) return true;
|
|
1847
|
+
return !(credentialKey(arg.slice(0, at)) && holdsLiteral(arg.slice(at + 1)));
|
|
1848
|
+
});
|
|
1849
|
+
}
|
|
1834
1850
|
//#endregion
|
|
1835
1851
|
//#region src/diagnose-mcp/diagnose-mcp.ts
|
|
1836
|
-
function read(root, path) {
|
|
1852
|
+
function read$1(root, path) {
|
|
1837
1853
|
const absolute = join(root, path);
|
|
1838
1854
|
return existsSync(absolute) ? readFileSync(absolute, "utf8") : void 0;
|
|
1839
1855
|
}
|
|
@@ -1884,7 +1900,7 @@ function diagnoseMcp({ root, git, cli }) {
|
|
|
1884
1900
|
const targets = /* @__PURE__ */ new Map();
|
|
1885
1901
|
const configs = [];
|
|
1886
1902
|
for (const config of targetsOf(root)) {
|
|
1887
|
-
const parsed = parseTarget(config, read(root, config.path));
|
|
1903
|
+
const parsed = parseTarget(config, read$1(root, config.path));
|
|
1888
1904
|
if (parsed.kind === "unreadable") {
|
|
1889
1905
|
add({ file: config.path }, "mcp-target-unreadable");
|
|
1890
1906
|
continue;
|
|
@@ -1894,7 +1910,7 @@ function diagnoseMcp({ root, git, cli }) {
|
|
|
1894
1910
|
targets.set(config.path, parsed.servers);
|
|
1895
1911
|
configs.push(config);
|
|
1896
1912
|
}
|
|
1897
|
-
const golden = parseGoldenSet(read(root, goldenSetPath));
|
|
1913
|
+
const golden = parseGoldenSet(read$1(root, goldenSetPath));
|
|
1898
1914
|
if (golden.kind === "unreadable") {
|
|
1899
1915
|
add({
|
|
1900
1916
|
file: goldenSetPath,
|
|
@@ -1906,7 +1922,7 @@ function diagnoseMcp({ root, git, cli }) {
|
|
|
1906
1922
|
reportSecrets(goldenSetPath, golden.servers);
|
|
1907
1923
|
const baseline = new McpBaseline({
|
|
1908
1924
|
git,
|
|
1909
|
-
record: parseProjectionRecord(read(root, projectionRecordPath))
|
|
1925
|
+
record: parseProjectionRecord(read$1(root, projectionRecordPath))
|
|
1910
1926
|
});
|
|
1911
1927
|
for (const config of configs) {
|
|
1912
1928
|
const servers = targets.get(config.path);
|
|
@@ -2723,6 +2739,135 @@ async function run(argv) {
|
|
|
2723
2739
|
}
|
|
2724
2740
|
}
|
|
2725
2741
|
//#endregion
|
|
2726
|
-
|
|
2742
|
+
//#region src/mcp-inventory/mcp-inventory.ts
|
|
2743
|
+
/**
|
|
2744
|
+
* A public, redaction-safe inventory of configured MCP servers: what `diagnoseMcp` already knows how
|
|
2745
|
+
* to read, reshaped for a consumer that wants a list rather than a drift diagnosis.
|
|
2746
|
+
*
|
|
2747
|
+
* This is a **different question** than `doctor` answers, not a wider version of it. `doctor`
|
|
2748
|
+
* compares project-scope configuration against a golden set the user authors, and stays
|
|
2749
|
+
* project-scope only by design — see `apps/web/src/content/docs/agent-configuration/mcp-servers.md`
|
|
2750
|
+
* for why reading a user's home directory is a wider blast radius than diagnosis needs. An inventory
|
|
2751
|
+
* has no golden set to compare against and nothing to diagnose; it answers "what MCP servers does
|
|
2752
|
+
* this project, and this machine, already have configured", which is a question a consumer can only
|
|
2753
|
+
* answer by reading both scopes. Adding user scope here changes nothing about what `doctor` reads:
|
|
2754
|
+
* `diagnoseMcp` still touches `harness.project.mcpConfig` alone.
|
|
2755
|
+
*
|
|
2756
|
+
* Every field that could carry a credential is reduced before it leaves this module, the same
|
|
2757
|
+
* discipline `mcp-secrets.ts` documents for `doctor`'s own findings: `command` is trimmed to its
|
|
2758
|
+
* basename, `args` drops any `--flag=value` pair `nonSecretArgs` flags, and `url` is trimmed to its
|
|
2759
|
+
* origin and path. `env` and `headers` are not returned at all — a name alone does not say whether
|
|
2760
|
+
* the value behind it is a literal or a reference, and the safe answer is not to carry the map.
|
|
2761
|
+
*/
|
|
2762
|
+
/** Where a harness keeps its **user-scope** MCP configuration, as that harness documents it.
|
|
2763
|
+
*
|
|
2764
|
+
* Unlike `harnessRegistry`, this table is read only from here: it is not wired into `doctor`, and
|
|
2765
|
+
* adding a harness to it never changes what `doctor` reads. Codex and Copilot CLI each let their
|
|
2766
|
+
* whole configuration directory move via an environment variable — `CODEX_HOME` and `COPILOT_HOME`
|
|
2767
|
+
* — so those two resolve through `env` before falling back to the home directory; the rest do not
|
|
2768
|
+
* document one.
|
|
2769
|
+
*/
|
|
2770
|
+
function userScopeConfig(harness, home, env) {
|
|
2771
|
+
switch (harness) {
|
|
2772
|
+
case "claude-code": return {
|
|
2773
|
+
file: join(home, ".claude.json"),
|
|
2774
|
+
config: {
|
|
2775
|
+
path: ".claude.json",
|
|
2776
|
+
key: "mcpServers",
|
|
2777
|
+
format: "json"
|
|
2778
|
+
}
|
|
2779
|
+
};
|
|
2780
|
+
case "cursor": return {
|
|
2781
|
+
file: join(home, ".cursor", "mcp.json"),
|
|
2782
|
+
config: {
|
|
2783
|
+
path: ".cursor/mcp.json",
|
|
2784
|
+
key: "mcpServers",
|
|
2785
|
+
format: "json"
|
|
2786
|
+
}
|
|
2787
|
+
};
|
|
2788
|
+
case "codex": return {
|
|
2789
|
+
file: join(env["CODEX_HOME"] || join(home, ".codex"), "config.toml"),
|
|
2790
|
+
config: {
|
|
2791
|
+
path: "config.toml",
|
|
2792
|
+
key: "mcp_servers",
|
|
2793
|
+
format: "toml"
|
|
2794
|
+
}
|
|
2795
|
+
};
|
|
2796
|
+
case "copilot-cli": return {
|
|
2797
|
+
file: join(env["COPILOT_HOME"] || join(home, ".copilot"), "mcp-config.json"),
|
|
2798
|
+
config: {
|
|
2799
|
+
path: "mcp-config.json",
|
|
2800
|
+
key: "mcpServers",
|
|
2801
|
+
format: "json"
|
|
2802
|
+
}
|
|
2803
|
+
};
|
|
2804
|
+
case "gemini-cli": return {
|
|
2805
|
+
file: join(home, ".gemini", "settings.json"),
|
|
2806
|
+
config: {
|
|
2807
|
+
path: ".gemini/settings.json",
|
|
2808
|
+
key: "mcpServers",
|
|
2809
|
+
format: "json",
|
|
2810
|
+
shared: true
|
|
2811
|
+
}
|
|
2812
|
+
};
|
|
2813
|
+
default: return;
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
function read(file) {
|
|
2817
|
+
return existsSync(file) ? readFileSync(file, "utf8") : void 0;
|
|
2818
|
+
}
|
|
2819
|
+
/** A URL trimmed to its origin and path, dropping any query string a token could ride in on. */
|
|
2820
|
+
function safeUrl(value) {
|
|
2821
|
+
if (!value) return void 0;
|
|
2822
|
+
try {
|
|
2823
|
+
const url = new URL(value);
|
|
2824
|
+
return `${url.origin}${url.pathname}`;
|
|
2825
|
+
} catch {
|
|
2826
|
+
return;
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
function toEntry(harness, scope, file, name, server) {
|
|
2830
|
+
return {
|
|
2831
|
+
harness,
|
|
2832
|
+
scope,
|
|
2833
|
+
configFile: file,
|
|
2834
|
+
name,
|
|
2835
|
+
transport: server.transport,
|
|
2836
|
+
command: server.command ? basename(server.command) : void 0,
|
|
2837
|
+
args: nonSecretArgs(server.args),
|
|
2838
|
+
url: safeUrl(server.url),
|
|
2839
|
+
enabled: server.enabled !== false
|
|
2840
|
+
};
|
|
2841
|
+
}
|
|
2842
|
+
function entriesFrom(harness, scope, file, config) {
|
|
2843
|
+
const parsed = parseTarget(config, read(file));
|
|
2844
|
+
if (parsed.kind !== "servers") return [];
|
|
2845
|
+
return [...parsed.servers].map(([name, server]) => toEntry(harness, scope, file, name, server));
|
|
2846
|
+
}
|
|
2847
|
+
/**
|
|
2848
|
+
* Every MCP server configured for a project, across every supported harness and every scope that
|
|
2849
|
+
* harness documents — without ever surfacing a credential.
|
|
2850
|
+
*
|
|
2851
|
+
* Reuses `diagnoseMcp`'s own parsing (`parseTarget`), model (`McpServer`), and redaction
|
|
2852
|
+
* (`nonSecretArgs`, and the URL/command trimming this module adds) rather than re-reading or
|
|
2853
|
+
* re-parsing any of the supported harnesses' MCP files. A harness with no file present, or one whose
|
|
2854
|
+
* file does not parse, contributes no entries; this function reports an inventory, not a diagnosis,
|
|
2855
|
+
* so it has nothing to say about why a file is missing or broken.
|
|
2856
|
+
*/
|
|
2857
|
+
function listMcpServers(options) {
|
|
2858
|
+
const home = options.homeDir ?? homedir();
|
|
2859
|
+
const env = options.env ?? process.env;
|
|
2860
|
+
const entries = [];
|
|
2861
|
+
for (const harness of harnessRegistry) {
|
|
2862
|
+
if (harness.deprecated) continue;
|
|
2863
|
+
const project = harness.project.mcpConfig;
|
|
2864
|
+
if (project) entries.push(...entriesFrom(harness.name, "project", join(options.projectDir, project.path), project));
|
|
2865
|
+
const user = userScopeConfig(harness.name, home, env);
|
|
2866
|
+
if (user) entries.push(...entriesFrom(harness.name, "user", user.file, user.config));
|
|
2867
|
+
}
|
|
2868
|
+
return entries;
|
|
2869
|
+
}
|
|
2870
|
+
//#endregion
|
|
2871
|
+
export { activate, bridgeRepairs, buildDoctorReport, diagnoseBridges, diagnoseInstructions, diagnoseMcp, doctorCommand, doctorRepairs, doctorSkill, goldenSetPath, harnessCommand, harnessRegistry, initCommand, initializeHarnesses, instructionRepairs, listMcpServers, renderDoctorSkill, run };
|
|
2727
2872
|
|
|
2728
2873
|
//# sourceMappingURL=index.mjs.map
|