gdharness 1.3.53 → 1.3.55

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/build/keeper.js CHANGED
@@ -7451,721 +7451,200 @@ import process4 from "node:process";
7451
7451
  import { AsyncLocalStorage } from "node:async_hooks";
7452
7452
  var current = new AsyncLocalStorage;
7453
7453
 
7454
- // src/harnesses.ts
7455
- import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute2, join as join3, relative as relative2, resolve as resolve2 } from "node:path";
7454
+ // src/process-table.ts
7455
+ import { tmpdir as tmpdir4 } from "node:os";
7456
7456
 
7457
- // node_modules/yaml/dist/index.js
7458
- var composer = require_composer();
7459
- var Document = require_Document();
7460
- var Schema = require_Schema();
7461
- var errors = require_errors();
7462
- var Alias = require_Alias();
7463
- var identity = require_identity();
7464
- var Pair = require_Pair();
7465
- var Scalar = require_Scalar();
7466
- var YAMLMap = require_YAMLMap();
7467
- var YAMLSeq = require_YAMLSeq();
7468
- var cst = require_cst();
7469
- var lexer = require_lexer();
7470
- var lineCounter = require_line_counter();
7471
- var parser = require_parser();
7472
- var publicApi = require_public_api();
7473
- var visit = require_visit();
7474
- var $Composer = composer.Composer;
7475
- var $Document = Document.Document;
7476
- var $Schema = Schema.Schema;
7477
- var $YAMLError = errors.YAMLError;
7478
- var $YAMLParseError = errors.YAMLParseError;
7479
- var $YAMLWarning = errors.YAMLWarning;
7480
- var $Alias = Alias.Alias;
7481
- var $isAlias = identity.isAlias;
7482
- var $isCollection = identity.isCollection;
7483
- var $isDocument = identity.isDocument;
7484
- var $isMap = identity.isMap;
7485
- var $isNode = identity.isNode;
7486
- var $isPair = identity.isPair;
7487
- var $isScalar = identity.isScalar;
7488
- var $isSeq = identity.isSeq;
7489
- var $Pair = Pair.Pair;
7490
- var $Scalar = Scalar.Scalar;
7491
- var $YAMLMap = YAMLMap.YAMLMap;
7492
- var $YAMLSeq = YAMLSeq.YAMLSeq;
7493
- var $Lexer = lexer.Lexer;
7494
- var $LineCounter = lineCounter.LineCounter;
7495
- var $Parser = parser.Parser;
7496
- var $parse = publicApi.parse;
7497
- var $parseAllDocuments = publicApi.parseAllDocuments;
7498
- var $parseDocument = publicApi.parseDocument;
7499
- var $stringify = publicApi.stringify;
7500
- var $visit = visit.visit;
7501
- var $visitAsync = visit.visitAsync;
7457
+ // src/windows-ask.ts
7458
+ import { tmpdir as tmpdir3 } from "node:os";
7459
+ import process3 from "node:process";
7460
+ var SCRIPT = [
7461
+ "[Console]::OutputEncoding = [Text.Encoding]::UTF8",
7462
+ "$in = [Console]::In",
7463
+ "while ($null -ne ($line = $in.ReadLine())) {",
7464
+ ' $parts = $line.Split(" ", 2)',
7465
+ " try {",
7466
+ " $asked = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($parts[1]))",
7467
+ " $said = (& ([ScriptBlock]::Create($asked)) | Out-String -Width 1000000)",
7468
+ ' $tag = "OK"',
7469
+ " } catch {",
7470
+ " $said = $_.Exception.Message",
7471
+ ' $tag = "ERR"',
7472
+ " }",
7473
+ ' [Console]::Out.Write($parts[0] + " " + $tag + " " + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($said)) + "`n")',
7474
+ " [Console]::Out.Flush()",
7475
+ "}"
7476
+ ].join(`
7477
+ `);
7502
7478
 
7503
- // src/paths.ts
7504
- import { realpathSync, statSync as statSync2 } from "node:fs";
7505
- import { basename, dirname, isAbsolute, join as join2, relative, resolve, sep } from "node:path";
7506
- function realAsFarAsItExists(path) {
7507
- const missing = [];
7508
- let at = path;
7509
- for (;; ) {
7510
- try {
7511
- return join2(realpathSync.native(at), ...missing);
7512
- } catch {
7513
- const parent = dirname(at);
7514
- if (parent === at) {
7515
- return path;
7516
- }
7517
- missing.unshift(basename(at));
7518
- at = parent;
7519
- }
7479
+ class WindowsAskFailure extends Error {
7480
+ constructor(how) {
7481
+ super(`PowerShell ${how}`);
7520
7482
  }
7521
7483
  }
7522
-
7523
- // src/harnesses.ts
7524
- var SERVER_KEY = "gdharness";
7525
- function tomlArray(values) {
7526
- return `[${values.map((value) => `"${value}"`).join(", ")}]`;
7484
+ var helper = null;
7485
+ var buffered = "";
7486
+ var next = 1;
7487
+ var out = null;
7488
+ var queued = [];
7489
+ var held = false;
7490
+ function holding(child, wanted) {
7491
+ if (held === wanted) {
7492
+ return;
7493
+ }
7494
+ held = wanted;
7495
+ const stdout = child.stdout;
7496
+ if (wanted) {
7497
+ stdout.ref?.();
7498
+ } else {
7499
+ stdout.unref?.();
7500
+ }
7527
7501
  }
7528
- function tomlEnv(launch) {
7529
- const pairs = Object.entries(launch.env).map(([name, value]) => `${name} = "${value}"`);
7530
- return `env = { ${pairs.join(", ")} }`;
7502
+ function running() {
7503
+ if (helper?.exitCode === null && helper.signalCode === null) {
7504
+ return helper;
7505
+ }
7506
+ const child = spawnHidden("powershell.exe", [
7507
+ "-NoProfile",
7508
+ "-NonInteractive",
7509
+ "-ExecutionPolicy",
7510
+ "Bypass",
7511
+ "-EncodedCommand",
7512
+ Buffer.from(SCRIPT, "utf16le").toString("base64")
7513
+ ], { cwd: tmpdir3() });
7514
+ buffered = "";
7515
+ child.stdout.setEncoding("utf8");
7516
+ child.stdout.on("data", (chunk) => {
7517
+ buffered += chunk;
7518
+ for (let end = buffered.indexOf(`
7519
+ `);end !== -1; end = buffered.indexOf(`
7520
+ `)) {
7521
+ answered(buffered.slice(0, end).trim());
7522
+ buffered = buffered.slice(end + 1);
7523
+ }
7524
+ });
7525
+ child.stderr.resume();
7526
+ child.stdin.on("error", () => {});
7527
+ const gone = () => {
7528
+ if (helper !== child) {
7529
+ return;
7530
+ }
7531
+ helper = null;
7532
+ if (out !== null) {
7533
+ clearTimeout(out.timer);
7534
+ out.question.reject(new WindowsAskFailure("exited before it answered"));
7535
+ out = null;
7536
+ }
7537
+ sendNext();
7538
+ };
7539
+ child.once("exit", gone);
7540
+ child.once("error", gone);
7541
+ child.unref();
7542
+ child.stdin.unref?.();
7543
+ child.stderr.unref?.();
7544
+ held = true;
7545
+ holding(child, false);
7546
+ helper = child;
7547
+ return child;
7531
7548
  }
7532
- function jsonSnippet(launch, container, shape) {
7533
- return JSON.stringify({ [container]: { [SERVER_KEY]: entryFor(shape, launch) } }, null, 2);
7549
+ function answered(line) {
7550
+ const [id, tag, body] = line.split(" ");
7551
+ if (out === null || out.id !== Number(id)) {
7552
+ return;
7553
+ }
7554
+ const { question, timer } = out;
7555
+ clearTimeout(timer);
7556
+ out = null;
7557
+ const said = Buffer.from(body ?? "", "base64").toString("utf8");
7558
+ if (tag === "OK") {
7559
+ question.resolve(said);
7560
+ } else {
7561
+ question.reject(new WindowsAskFailure(`refused the question: ${said.trim() || "no reason given"}`));
7562
+ }
7563
+ sendNext();
7534
7564
  }
7535
- var HARNESSES = [
7536
- {
7537
- id: "claude-code",
7538
- name: "Claude Code",
7539
- scope: "project",
7540
- file: ".mcp.json",
7541
- container: "mcpServers",
7542
- shape: "plain",
7543
- home: ".claude",
7544
- marker: ".claude",
7545
- skills: { dir: join3(".claude", "skills"), shared: false }
7546
- },
7547
- {
7548
- id: "copilot-cli",
7549
- name: "Copilot CLI",
7550
- scope: "project",
7551
- file: ".mcp.json",
7552
- container: "mcpServers",
7553
- shape: "plain",
7554
- home: ".copilot",
7555
- skills: { dir: join3(".github", "skills"), shared: true },
7556
- manual: "Trust the folder when Copilot CLI first asks, or it reads no config here."
7557
- },
7558
- {
7559
- id: "qoder",
7560
- name: "Qoder",
7561
- scope: "project",
7562
- file: ".mcp.json",
7563
- container: "mcpServers",
7564
- shape: "plain",
7565
- home: ".qoder",
7566
- marker: ".qoder"
7567
- },
7568
- {
7569
- id: "command-code",
7570
- name: "Command Code",
7571
- scope: "project",
7572
- file: ".mcp.json",
7573
- container: "mcpServers",
7574
- shape: "plain",
7575
- home: ".commandcode"
7576
- },
7577
- {
7578
- id: "cursor",
7579
- name: "Cursor",
7580
- scope: "project",
7581
- file: join3(".cursor", "mcp.json"),
7582
- container: "mcpServers",
7583
- shape: "plain",
7584
- home: ".cursor",
7585
- skills: { dir: join3(".cursor", "skills"), shared: true },
7586
- manual: "Cursor asks before each tool call by default, and the server can be toggled off."
7587
- },
7588
- {
7589
- id: "vscode",
7590
- name: "VS Code",
7591
- scope: "project",
7592
- file: join3(".vscode", "mcp.json"),
7593
- container: "servers",
7594
- shape: "typed",
7595
- home: ".vscode",
7596
- skills: { dir: join3(".github", "skills"), shared: true },
7597
- manual: "VS Code asks you to trust a server the first time it starts one."
7598
- },
7599
- {
7600
- id: "opencode",
7601
- name: "opencode",
7602
- scope: "project",
7603
- file: "opencode.json",
7604
- container: "mcp",
7605
- shape: "opencode",
7606
- home: join3(".config", "opencode"),
7607
- marker: ".opencode",
7608
- skills: { dir: join3(".opencode", "skills"), shared: true }
7609
- },
7610
- {
7611
- id: "junie",
7612
- name: "Junie",
7613
- scope: "project",
7614
- file: join3(".junie", "mcp", "mcp.json"),
7615
- container: "mcpServers",
7616
- shape: "plain",
7617
- home: ".junie",
7618
- skills: { dir: join3(".junie", "skills"), shared: true }
7619
- },
7620
- {
7621
- id: "kiro",
7622
- name: "Kiro",
7623
- scope: "project",
7624
- file: join3(".kiro", "settings", "mcp.json"),
7625
- container: "mcpServers",
7626
- shape: "plain",
7627
- home: ".kiro",
7628
- skills: { dir: join3(".kiro", "skills"), shared: false }
7629
- },
7630
- {
7631
- id: "gemini",
7632
- name: "Gemini CLI",
7633
- scope: "project",
7634
- file: join3(".gemini", "settings.json"),
7635
- container: "mcpServers",
7636
- shape: "plain",
7637
- home: ".gemini",
7638
- skills: { dir: join3(".gemini", "skills"), shared: true }
7639
- },
7640
- {
7641
- id: "roo",
7642
- name: "Roo Code",
7643
- scope: "project",
7644
- file: join3(".roo", "mcp.json"),
7645
- container: "mcpServers",
7646
- shape: "plain"
7647
- },
7648
- {
7649
- id: "kilo",
7650
- name: "Kilo Code",
7651
- scope: "project",
7652
- file: join3(".kilocode", "mcp.json"),
7653
- container: "mcpServers",
7654
- shape: "plain"
7655
- },
7656
- {
7657
- id: "amazon-q",
7658
- name: "Amazon Q Developer CLI",
7659
- scope: "project",
7660
- file: join3(".amazonq", "mcp.json"),
7661
- container: "mcpServers",
7662
- shape: "plain",
7663
- home: join3(".aws", "amazonq")
7664
- },
7665
- {
7666
- id: "zed",
7667
- name: "Zed",
7668
- scope: "project",
7669
- file: join3(".zed", "settings.json"),
7670
- container: "context_servers",
7671
- shape: "plain"
7672
- },
7673
- {
7674
- id: "amp",
7675
- name: "Amp",
7676
- scope: "project",
7677
- file: join3(".amp", "settings.json"),
7678
- container: "amp.mcpServers",
7679
- shape: "plain",
7680
- home: join3(".config", "amp")
7681
- },
7682
- {
7683
- id: "warp",
7684
- name: "Warp",
7685
- scope: "project",
7686
- file: join3(".warp", ".mcp.json"),
7687
- container: "mcpServers",
7688
- shape: "plain",
7689
- home: ".warp",
7690
- manual: "Warp starts a project server only once you toggle it on, on its MCP servers page."
7691
- },
7692
- {
7693
- id: "trae",
7694
- name: "Trae",
7695
- scope: "project",
7696
- file: join3(".trae", "mcp.json"),
7697
- container: "mcpServers",
7698
- shape: "plain",
7699
- home: ".trae"
7700
- },
7701
- {
7702
- id: "factory",
7703
- name: "Factory Droid",
7704
- scope: "project",
7705
- file: join3(".factory", "mcp.json"),
7706
- container: "mcpServers",
7707
- shape: "typed",
7708
- home: ".factory"
7709
- },
7710
- {
7711
- id: "tabnine",
7712
- name: "Tabnine",
7713
- scope: "project",
7714
- file: join3(".tabnine", "mcp_servers.json"),
7715
- container: "mcpServers",
7716
- shape: "plain",
7717
- home: ".tabnine"
7718
- },
7719
- {
7720
- id: "firebender",
7721
- name: "Firebender",
7722
- scope: "project",
7723
- file: "firebender.json",
7724
- container: "mcpServers",
7725
- shape: "plain"
7726
- },
7727
- {
7728
- id: "pi",
7729
- name: "pi",
7730
- scope: "project",
7731
- file: join3(".pi", "mcp.json"),
7732
- container: "mcpServers",
7733
- shape: "plain",
7734
- home: ".pi"
7735
- },
7736
- {
7737
- id: "mistral-vibe",
7738
- name: "Mistral Vibe",
7739
- scope: "project",
7740
- file: join3(".vibe", "config.toml"),
7741
- container: "mcp_servers",
7742
- shape: "plain",
7743
- toml: {
7744
- header: "[[mcp_servers]]",
7745
- identity: `name = "${SERVER_KEY}"`,
7746
- block: (launch) => [
7747
- "[[mcp_servers]]",
7748
- `name = "${SERVER_KEY}"`,
7749
- 'transport = "stdio"',
7750
- `command = "${launch.command}"`,
7751
- `args = ${tomlArray(launch.args)}`,
7752
- tomlEnv(launch)
7753
- ].join(`
7754
- `)
7565
+ function sendNext() {
7566
+ const question = queued.shift();
7567
+ if (question === undefined) {
7568
+ if (helper !== null) {
7569
+ holding(helper, false);
7755
7570
  }
7756
- },
7757
- {
7758
- id: "vtcode",
7759
- name: "VT Code",
7760
- scope: "project",
7761
- file: "vtcode.toml",
7762
- container: "mcp.providers",
7763
- shape: "plain",
7764
- marker: ".vtcode",
7765
- toml: {
7766
- header: "[[mcp.providers]]",
7767
- identity: `name = "${SERVER_KEY}"`,
7768
- enable: { header: "[mcp]", line: "enabled = true" },
7769
- block: (launch) => [
7770
- "[[mcp.providers]]",
7771
- `name = "${SERVER_KEY}"`,
7772
- "enabled = true",
7773
- `command = "${launch.command}"`,
7774
- `args = ${tomlArray(launch.args)}`,
7775
- tomlEnv(launch)
7776
- ].join(`
7777
- `)
7571
+ return;
7572
+ }
7573
+ const child = running();
7574
+ holding(child, true);
7575
+ const id = next;
7576
+ next += 1;
7577
+ const timer = setTimeout(() => {
7578
+ if (out?.id !== id) {
7579
+ return;
7778
7580
  }
7779
- },
7780
- {
7781
- id: "fast-agent",
7782
- name: "fast-agent",
7783
- scope: "project",
7784
- file: "fastagent.config.yaml",
7785
- container: "mcp",
7786
- shape: "plain",
7787
- yaml: {
7788
- path: ["mcp", "servers", SERVER_KEY],
7789
- entry: (launch) => ({ command: launch.command, args: [...launch.args], env: { ...launch.env } })
7581
+ out = null;
7582
+ question.reject(new WindowsAskFailure(`did not answer within ${question.withinMs}ms`));
7583
+ if (helper === child) {
7584
+ helper = null;
7790
7585
  }
7791
- },
7792
- {
7793
- id: "codex",
7794
- name: "Codex CLI",
7795
- scope: "home",
7796
- file: join3(".codex", "config.toml"),
7797
- container: "mcp_servers",
7798
- shape: "plain",
7799
- manual: "Codex reads its config at startup, so restart it.",
7800
- toml: {
7801
- header: `[mcp_servers.${SERVER_KEY}]`,
7802
- block: (launch) => [
7803
- `[mcp_servers.${SERVER_KEY}]`,
7804
- `command = "${launch.command}"`,
7805
- `args = ${tomlArray(launch.args)}`,
7806
- tomlEnv(launch)
7807
- ].join(`
7808
- `)
7586
+ child.kill();
7587
+ sendNext();
7588
+ }, question.withinMs);
7589
+ out = { id, question, timer };
7590
+ child.stdin.write(`${id} ${Buffer.from(question.script, "utf8").toString("base64")}
7591
+ `);
7592
+ }
7593
+ function askWindows(script, withinMs) {
7594
+ if (process3.platform !== "win32") {
7595
+ return Promise.reject(new WindowsAskFailure("is asked only on Windows"));
7596
+ }
7597
+ return new Promise((resolve, reject) => {
7598
+ queued.push({ script, withinMs, resolve, reject });
7599
+ if (out === null) {
7600
+ sendNext();
7809
7601
  }
7810
- },
7811
- {
7812
- id: "cline",
7813
- name: "Cline",
7814
- scope: "home",
7815
- file: join3(".cline", "data", "settings", "cline_mcp_settings.json"),
7816
- container: "mcpServers",
7817
- shape: "plain",
7818
- marker: ".cline",
7819
- skills: { dir: join3(".cline", "skills"), shared: false }
7820
- },
7821
- {
7822
- id: "goose",
7823
- name: "Goose",
7824
- scope: "home",
7825
- file: {
7826
- win32: { appData: join3("Block", "goose", "config", "config.yaml") },
7827
- darwin: join3(".config", "goose", "config.yaml"),
7828
- linux: join3(".config", "goose", "config.yaml")
7829
- },
7830
- container: "extensions",
7831
- shape: "plain",
7832
- yaml: {
7833
- path: ["extensions", SERVER_KEY],
7834
- entry: (launch) => ({
7835
- name: SERVER_KEY,
7836
- type: "stdio",
7837
- enabled: true,
7838
- cmd: launch.command,
7839
- args: [...launch.args],
7840
- envs: { ...launch.env },
7841
- timeout: 300
7842
- })
7843
- }
7844
- },
7845
- {
7846
- id: "windsurf",
7847
- name: "Windsurf",
7848
- scope: "home",
7849
- file: join3(".codeium", "windsurf", "mcp_config.json"),
7850
- container: "mcpServers",
7851
- shape: "plain",
7852
- skills: { dir: join3(".windsurf", "skills"), shared: true }
7853
- },
7854
- {
7855
- id: "hermes",
7856
- name: "Hermes",
7857
- scope: "home",
7858
- file: join3(".hermes", "config.yaml"),
7859
- container: "mcp_servers",
7860
- shape: "plain",
7861
- skills: { dir: join3(".hermes", "skills"), shared: true },
7862
- yaml: {
7863
- path: ["mcp_servers", SERVER_KEY],
7864
- entry: (launch) => ({
7865
- command: launch.command,
7866
- args: [...launch.args],
7867
- env: { ...launch.env },
7868
- enabled: true
7869
- })
7870
- }
7871
- },
7872
- {
7873
- id: "openclaw",
7874
- name: "OpenClaw",
7875
- scope: "home",
7876
- file: join3(".openclaw", "openclaw.json"),
7877
- container: "mcpServers",
7878
- shape: "plain"
7879
- },
7880
- {
7881
- id: "claude-desktop",
7882
- name: "Claude Desktop",
7883
- scope: "home",
7884
- file: {
7885
- win32: { appData: join3("Claude", "claude_desktop_config.json") },
7886
- darwin: join3("Library", "Application Support", "Claude", "claude_desktop_config.json"),
7887
- linux: join3(".config", "Claude", "claude_desktop_config.json")
7888
- },
7889
- container: "mcpServers",
7890
- shape: "plain"
7891
- },
7892
- {
7893
- id: "zeroclaw",
7894
- name: "ZeroClaw",
7895
- scope: "home",
7896
- file: join3(".zeroclaw", "config.toml"),
7897
- container: "mcp.servers",
7898
- shape: "plain",
7899
- toml: {
7900
- header: "[[mcp.servers]]",
7901
- identity: `name = "${SERVER_KEY}"`,
7902
- enable: { header: "[mcp]", line: "enabled = true" },
7903
- block: (launch) => [
7904
- "[[mcp.servers]]",
7905
- `name = "${SERVER_KEY}"`,
7906
- `command = "${launch.command}"`,
7907
- `args = ${tomlArray(launch.args)}`,
7908
- tomlEnv(launch)
7909
- ].join(`
7910
- `)
7911
- }
7912
- },
7913
- {
7914
- id: "deepcode",
7915
- name: "Deep Code",
7916
- scope: "home",
7917
- file: join3(".deepcode", "settings.json"),
7918
- container: "mcpServers",
7919
- shape: "plain"
7920
- },
7921
- {
7922
- id: "nanobot",
7923
- name: "nanobot",
7924
- scope: "home",
7925
- file: join3(".nanobot", "config.json"),
7926
- container: "mcpServers",
7927
- shape: "plain",
7928
- snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
7929
- },
7930
- {
7931
- id: "autohand",
7932
- name: "Autohand",
7933
- scope: "home",
7934
- file: join3(".autohand", "config.json"),
7935
- container: "mcpServers",
7936
- shape: "plain",
7937
- snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
7938
- }
7939
- ];
7940
- var OURS = ["GODOT_PATH", "GDHARNESS_PROJECT"];
7941
- function environmentFor(launch, held) {
7942
- const kept = {};
7943
- if (typeof held === "object" && held !== null && !Array.isArray(held)) {
7944
- for (const [name, value] of Object.entries(held)) {
7945
- if (typeof value === "string" && !OURS.includes(name)) {
7946
- kept[name] = value;
7947
- }
7948
- }
7949
- }
7950
- return { ...kept, ...launch.env };
7951
- }
7952
- function entryFor(shape, launch, held) {
7953
- const before = typeof held === "object" && held !== null && !Array.isArray(held) ? { ...held } : {};
7954
- if (shape === "opencode") {
7955
- return {
7956
- ...before,
7957
- type: "local",
7958
- command: [launch.command, ...launch.args],
7959
- environment: environmentFor(launch, before["environment"]),
7960
- enabled: true
7961
- };
7962
- }
7963
- return {
7964
- ...before,
7965
- ...shape === "typed" ? { type: "stdio" } : {},
7966
- command: launch.command,
7967
- args: [...launch.args],
7968
- env: environmentFor(launch, before["env"])
7969
- };
7602
+ });
7970
7603
  }
7971
7604
 
7972
- // src/log-read.ts
7973
- var LOG_LIMIT_BYTES = 128 * 1024 * 1024;
7974
-
7975
7605
  // src/process-table.ts
7976
- import { tmpdir as tmpdir4 } from "node:os";
7606
+ var SOURCE2 = String.raw`
7607
+ using System;
7608
+ using System.Collections.Generic;
7609
+ using System.Globalization;
7610
+ using System.Runtime.InteropServices;
7611
+ using System.Text;
7977
7612
 
7978
- // src/windows-ask.ts
7979
- import { tmpdir as tmpdir3 } from "node:os";
7980
- import process3 from "node:process";
7981
- var SCRIPT = [
7982
- "[Console]::OutputEncoding = [Text.Encoding]::UTF8",
7983
- "$in = [Console]::In",
7984
- "while ($null -ne ($line = $in.ReadLine())) {",
7985
- ' $parts = $line.Split(" ", 2)',
7986
- " try {",
7987
- " $asked = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($parts[1]))",
7988
- " $said = (& ([ScriptBlock]::Create($asked)) | Out-String -Width 1000000)",
7989
- ' $tag = "OK"',
7990
- " } catch {",
7991
- " $said = $_.Exception.Message",
7992
- ' $tag = "ERR"',
7993
- " }",
7994
- ' [Console]::Out.Write($parts[0] + " " + $tag + " " + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($said)) + "`n")',
7995
- " [Console]::Out.Flush()",
7996
- "}"
7997
- ].join(`
7998
- `);
7613
+ public static class GdhProcessTable
7614
+ {
7615
+ [DllImport("ntdll.dll")]
7616
+ private static extern int NtQuerySystemInformation(int infoClass, IntPtr info, int length, out int needed);
7999
7617
 
8000
- class WindowsAskFailure extends Error {
8001
- constructor(how) {
8002
- super(`PowerShell ${how}`);
8003
- }
8004
- }
8005
- var helper = null;
8006
- var buffered = "";
8007
- var next = 1;
8008
- var out = null;
8009
- var queued = [];
8010
- var held = false;
8011
- function holding(child, wanted) {
8012
- if (held === wanted) {
8013
- return;
8014
- }
8015
- held = wanted;
8016
- const stdout = child.stdout;
8017
- if (wanted) {
8018
- stdout.ref?.();
8019
- } else {
8020
- stdout.unref?.();
8021
- }
8022
- }
8023
- function running() {
8024
- if (helper?.exitCode === null && helper.signalCode === null) {
8025
- return helper;
8026
- }
8027
- const child = spawnHidden("powershell.exe", [
8028
- "-NoProfile",
8029
- "-NonInteractive",
8030
- "-ExecutionPolicy",
8031
- "Bypass",
8032
- "-EncodedCommand",
8033
- Buffer.from(SCRIPT, "utf16le").toString("base64")
8034
- ], { cwd: tmpdir3() });
8035
- buffered = "";
8036
- child.stdout.setEncoding("utf8");
8037
- child.stdout.on("data", (chunk) => {
8038
- buffered += chunk;
8039
- for (let end = buffered.indexOf(`
8040
- `);end !== -1; end = buffered.indexOf(`
8041
- `)) {
8042
- answered(buffered.slice(0, end).trim());
8043
- buffered = buffered.slice(end + 1);
8044
- }
8045
- });
8046
- child.stderr.resume();
8047
- child.stdin.on("error", () => {});
8048
- const gone = () => {
8049
- if (helper !== child) {
8050
- return;
8051
- }
8052
- helper = null;
8053
- if (out !== null) {
8054
- clearTimeout(out.timer);
8055
- out.question.reject(new WindowsAskFailure("exited before it answered"));
8056
- out = null;
8057
- }
8058
- sendNext();
8059
- };
8060
- child.once("exit", gone);
8061
- child.once("error", gone);
8062
- child.unref();
8063
- child.stdin.unref?.();
8064
- child.stderr.unref?.();
8065
- held = true;
8066
- holding(child, false);
8067
- helper = child;
8068
- return child;
8069
- }
8070
- function answered(line) {
8071
- const [id, tag, body] = line.split(" ");
8072
- if (out === null || out.id !== Number(id)) {
8073
- return;
8074
- }
8075
- const { question, timer } = out;
8076
- clearTimeout(timer);
8077
- out = null;
8078
- const said = Buffer.from(body ?? "", "base64").toString("utf8");
8079
- if (tag === "OK") {
8080
- question.resolve(said);
8081
- } else {
8082
- question.reject(new WindowsAskFailure(`refused the question: ${said.trim() || "no reason given"}`));
8083
- }
8084
- sendNext();
8085
- }
8086
- function sendNext() {
8087
- const question = queued.shift();
8088
- if (question === undefined) {
8089
- if (helper !== null) {
8090
- holding(helper, false);
8091
- }
8092
- return;
8093
- }
8094
- const child = running();
8095
- holding(child, true);
8096
- const id = next;
8097
- next += 1;
8098
- const timer = setTimeout(() => {
8099
- if (out?.id !== id) {
8100
- return;
8101
- }
8102
- out = null;
8103
- question.reject(new WindowsAskFailure(`did not answer within ${question.withinMs}ms`));
8104
- if (helper === child) {
8105
- helper = null;
8106
- }
8107
- child.kill();
8108
- sendNext();
8109
- }, question.withinMs);
8110
- out = { id, question, timer };
8111
- child.stdin.write(`${id} ${Buffer.from(question.script, "utf8").toString("base64")}
8112
- `);
8113
- }
8114
- function askWindows(script, withinMs) {
8115
- if (process3.platform !== "win32") {
8116
- return Promise.reject(new WindowsAskFailure("is asked only on Windows"));
8117
- }
8118
- return new Promise((resolve, reject) => {
8119
- queued.push({ script, withinMs, resolve, reject });
8120
- if (out === null) {
8121
- sendNext();
8122
- }
8123
- });
8124
- }
8125
-
8126
- // src/process-table.ts
8127
- var SOURCE2 = String.raw`
8128
- using System;
8129
- using System.Collections.Generic;
8130
- using System.Globalization;
8131
- using System.Runtime.InteropServices;
8132
- using System.Text;
8133
-
8134
- public static class GdhProcessTable
8135
- {
8136
- [DllImport("ntdll.dll")]
8137
- private static extern int NtQuerySystemInformation(int infoClass, IntPtr info, int length, out int needed);
8138
-
8139
- [DllImport("ntdll.dll")]
8140
- private static extern int NtQueryInformationProcess(IntPtr process, int infoClass, IntPtr info, int length, out int needed);
8141
-
8142
- [DllImport("kernel32.dll")]
8143
- private static extern IntPtr OpenProcess(int access, bool inherit, int pid);
8144
-
8145
- [DllImport("kernel32.dll")]
8146
- private static extern bool CloseHandle(IntPtr handle);
8147
-
8148
- [DllImport("kernel32.dll")]
8149
- private static extern bool GetProcessTimes(IntPtr process, out long created, out long exited, out long kernel, out long user);
8150
-
8151
- [DllImport("kernel32.dll")]
8152
- private static extern uint WaitForSingleObject(IntPtr handle, uint milliseconds);
8153
-
8154
- [DllImport("kernel32.dll")]
8155
- private static extern bool GetExitCodeProcess(IntPtr process, out int code);
8156
-
8157
- [StructLayout(LayoutKind.Sequential)]
8158
- private struct MemoryStatus
8159
- {
8160
- public uint Length;
8161
- public uint MemoryLoad;
8162
- public ulong TotalPhys;
8163
- public ulong AvailPhys;
8164
- public ulong TotalPageFile;
8165
- public ulong AvailPageFile;
8166
- public ulong TotalVirtual;
8167
- public ulong AvailVirtual;
8168
- public ulong AvailExtendedVirtual;
7618
+ [DllImport("ntdll.dll")]
7619
+ private static extern int NtQueryInformationProcess(IntPtr process, int infoClass, IntPtr info, int length, out int needed);
7620
+
7621
+ [DllImport("kernel32.dll")]
7622
+ private static extern IntPtr OpenProcess(int access, bool inherit, int pid);
7623
+
7624
+ [DllImport("kernel32.dll")]
7625
+ private static extern bool CloseHandle(IntPtr handle);
7626
+
7627
+ [DllImport("kernel32.dll")]
7628
+ private static extern bool GetProcessTimes(IntPtr process, out long created, out long exited, out long kernel, out long user);
7629
+
7630
+ [DllImport("kernel32.dll")]
7631
+ private static extern uint WaitForSingleObject(IntPtr handle, uint milliseconds);
7632
+
7633
+ [DllImport("kernel32.dll")]
7634
+ private static extern bool GetExitCodeProcess(IntPtr process, out int code);
7635
+
7636
+ [StructLayout(LayoutKind.Sequential)]
7637
+ private struct MemoryStatus
7638
+ {
7639
+ public uint Length;
7640
+ public uint MemoryLoad;
7641
+ public ulong TotalPhys;
7642
+ public ulong AvailPhys;
7643
+ public ulong TotalPageFile;
7644
+ public ulong AvailPageFile;
7645
+ public ulong TotalVirtual;
7646
+ public ulong AvailVirtual;
7647
+ public ulong AvailExtendedVirtual;
8169
7648
  }
8170
7649
 
8171
7650
  [DllImport("kernel32.dll")]
@@ -8385,90 +7864,638 @@ public static class GdhProcessTable
8385
7864
  }
8386
7865
  return "";
8387
7866
  }
8388
-
8389
- /// <summary>The processor seconds the pid has used; empty when it is not running.</summary>
8390
- public static string ProcessorSeconds(int pid)
8391
- {
8392
- foreach (Entry entry in Snapshot())
8393
- {
8394
- if (entry.Pid == pid)
8395
- {
8396
- return (entry.Processor / 1e7).ToString("R", CultureInfo.InvariantCulture);
8397
- }
8398
- }
8399
- return "";
7867
+
7868
+ /// <summary>The processor seconds the pid has used; empty when it is not running.</summary>
7869
+ public static string ProcessorSeconds(int pid)
7870
+ {
7871
+ foreach (Entry entry in Snapshot())
7872
+ {
7873
+ if (entry.Pid == pid)
7874
+ {
7875
+ return (entry.Processor / 1e7).ToString("R", CultureInfo.InvariantCulture);
7876
+ }
7877
+ }
7878
+ return "";
7879
+ }
7880
+
7881
+ /// <summary>"pid seconds" on a line for each running one of the comma-separated pids, from one snapshot.</summary>
7882
+ public static string ProcessorSecondsOf(string pids)
7883
+ {
7884
+ HashSet<int> wanted = new HashSet<int>();
7885
+ foreach (string one in pids.Split(','))
7886
+ {
7887
+ int pid;
7888
+ if (int.TryParse(one, NumberStyles.Integer, CultureInfo.InvariantCulture, out pid))
7889
+ {
7890
+ wanted.Add(pid);
7891
+ }
7892
+ }
7893
+ StringBuilder said = new StringBuilder();
7894
+ foreach (Entry entry in Snapshot())
7895
+ {
7896
+ if (wanted.Contains(entry.Pid))
7897
+ {
7898
+ said.Append(Number(entry.Pid)).Append(' ')
7899
+ .Append((entry.Processor / 1e7).ToString("R", CultureInfo.InvariantCulture)).Append('\n');
7900
+ }
7901
+ }
7902
+ return said.ToString();
7903
+ }
7904
+
7905
+ /// <summary>How many more bytes Windows will commit.</summary>
7906
+ public static string CommitLeft()
7907
+ {
7908
+ MemoryStatus status = new MemoryStatus();
7909
+ status.Length = (uint)Marshal.SizeOf(typeof(MemoryStatus));
7910
+ if (!GlobalMemoryStatusEx(ref status))
7911
+ {
7912
+ throw new InvalidOperationException("GlobalMemoryStatusEx failed with " + Number(Marshal.GetLastWin32Error()));
7913
+ }
7914
+ return status.AvailPageFile.ToString(CultureInfo.InvariantCulture);
7915
+ }
7916
+
7917
+ /// <summary>
7918
+ /// "pid started command" for each dated child of the pid, holding a handle to each: Windows tells
7919
+ /// a process's exit code only to whoever holds a handle to it, and the handle keeps its number
7920
+ /// from going to anything else.
7921
+ /// </summary>
7922
+ public static string HoldChildren(int parent)
7923
+ {
7924
+ StringBuilder said = new StringBuilder();
7925
+ foreach (Entry entry in Snapshot())
7926
+ {
7927
+ if (entry.Parent != parent || entry.Pid <= 0 || entry.Created <= UnixEpoch || held.ContainsKey(entry.Pid))
7928
+ {
7929
+ continue;
7930
+ }
7931
+ IntPtr handle = Open(entry, QueryLimitedInformation | Synchronize);
7932
+ if (handle == IntPtr.Zero)
7933
+ {
7934
+ continue;
7935
+ }
7936
+ held[entry.Pid] = handle;
7937
+ said.Append(Number(entry.Pid)).Append(' ').Append(Milliseconds(entry.Created)).Append(' ')
7938
+ .Append(CommandLineOf(handle)).Append('\n');
7939
+ }
7940
+ return said.ToString();
7941
+ }
7942
+
7943
+ /// <summary>"exit code" once a child held by HoldChildren has ended; empty for one not held.</summary>
7944
+ public static string WaitFor(int pid)
7945
+ {
7946
+ IntPtr handle;
7947
+ if (!held.TryGetValue(pid, out handle))
7948
+ {
7949
+ return "";
7950
+ }
7951
+ WaitForSingleObject(handle, 0xFFFFFFFF);
7952
+ int code;
7953
+ return GetExitCodeProcess(handle, out code) ? "exit " + Number(code) : "";
7954
+ }
7955
+ }
7956
+ `;
7957
+ var TABLE = new CompiledHelper("process table", "gdharness-processes", SOURCE2);
7958
+
7959
+ class ProcessTableUnbuilt extends Error {
7960
+ }
7961
+ function ensureProcessTable(directory = tmpdir4(), wait = true) {
7962
+ return TABLE.ensure(directory, HELPER_COMPILE_MS, wait);
7963
+ }
7964
+ async function loadingTheTable() {
7965
+ const failed = await ensureProcessTable();
7966
+ if (failed !== null) {
7967
+ throw new ProcessTableUnbuilt(failed);
7968
+ }
7969
+ return `$null = [Reflection.Assembly]::LoadFrom('${TABLE.assembly().replaceAll("'", "''")}')`;
7970
+ }
7971
+ async function askProcessTable(call, withinMs) {
7972
+ return askWindows(`${await loadingTheTable()}; [GdhProcessTable]::${call}`, withinMs);
7973
+ }
7974
+
7975
+ // src/engine-spent.ts
7976
+ var watched = new Set;
7977
+
7978
+ // src/harnesses.ts
7979
+ import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute2, join as join3, relative as relative2, resolve as resolve2 } from "node:path";
7980
+
7981
+ // node_modules/yaml/dist/index.js
7982
+ var composer = require_composer();
7983
+ var Document = require_Document();
7984
+ var Schema = require_Schema();
7985
+ var errors = require_errors();
7986
+ var Alias = require_Alias();
7987
+ var identity = require_identity();
7988
+ var Pair = require_Pair();
7989
+ var Scalar = require_Scalar();
7990
+ var YAMLMap = require_YAMLMap();
7991
+ var YAMLSeq = require_YAMLSeq();
7992
+ var cst = require_cst();
7993
+ var lexer = require_lexer();
7994
+ var lineCounter = require_line_counter();
7995
+ var parser = require_parser();
7996
+ var publicApi = require_public_api();
7997
+ var visit = require_visit();
7998
+ var $Composer = composer.Composer;
7999
+ var $Document = Document.Document;
8000
+ var $Schema = Schema.Schema;
8001
+ var $YAMLError = errors.YAMLError;
8002
+ var $YAMLParseError = errors.YAMLParseError;
8003
+ var $YAMLWarning = errors.YAMLWarning;
8004
+ var $Alias = Alias.Alias;
8005
+ var $isAlias = identity.isAlias;
8006
+ var $isCollection = identity.isCollection;
8007
+ var $isDocument = identity.isDocument;
8008
+ var $isMap = identity.isMap;
8009
+ var $isNode = identity.isNode;
8010
+ var $isPair = identity.isPair;
8011
+ var $isScalar = identity.isScalar;
8012
+ var $isSeq = identity.isSeq;
8013
+ var $Pair = Pair.Pair;
8014
+ var $Scalar = Scalar.Scalar;
8015
+ var $YAMLMap = YAMLMap.YAMLMap;
8016
+ var $YAMLSeq = YAMLSeq.YAMLSeq;
8017
+ var $Lexer = lexer.Lexer;
8018
+ var $LineCounter = lineCounter.LineCounter;
8019
+ var $Parser = parser.Parser;
8020
+ var $parse = publicApi.parse;
8021
+ var $parseAllDocuments = publicApi.parseAllDocuments;
8022
+ var $parseDocument = publicApi.parseDocument;
8023
+ var $stringify = publicApi.stringify;
8024
+ var $visit = visit.visit;
8025
+ var $visitAsync = visit.visitAsync;
8026
+
8027
+ // src/paths.ts
8028
+ import { realpathSync, statSync as statSync2 } from "node:fs";
8029
+ import { basename, dirname, isAbsolute, join as join2, relative, resolve, sep } from "node:path";
8030
+ function realAsFarAsItExists(path) {
8031
+ const missing = [];
8032
+ let at = path;
8033
+ for (;; ) {
8034
+ try {
8035
+ return join2(realpathSync.native(at), ...missing);
8036
+ } catch {
8037
+ const parent = dirname(at);
8038
+ if (parent === at) {
8039
+ return path;
8040
+ }
8041
+ missing.unshift(basename(at));
8042
+ at = parent;
8043
+ }
8044
+ }
8045
+ }
8046
+
8047
+ // src/harnesses.ts
8048
+ var SERVER_KEY = "gdharness";
8049
+ function tomlArray(values) {
8050
+ return `[${values.map((value) => `"${value}"`).join(", ")}]`;
8051
+ }
8052
+ function tomlEnv(launch) {
8053
+ const pairs = Object.entries(launch.env).map(([name, value]) => `${name} = "${value}"`);
8054
+ return `env = { ${pairs.join(", ")} }`;
8055
+ }
8056
+ function jsonSnippet(launch, container, shape) {
8057
+ return JSON.stringify({ [container]: { [SERVER_KEY]: entryFor(shape, launch) } }, null, 2);
8058
+ }
8059
+ var HARNESSES = [
8060
+ {
8061
+ id: "claude-code",
8062
+ name: "Claude Code",
8063
+ scope: "project",
8064
+ file: ".mcp.json",
8065
+ container: "mcpServers",
8066
+ shape: "plain",
8067
+ home: ".claude",
8068
+ marker: ".claude",
8069
+ skills: { dir: join3(".claude", "skills"), shared: false }
8070
+ },
8071
+ {
8072
+ id: "copilot-cli",
8073
+ name: "Copilot CLI",
8074
+ scope: "project",
8075
+ file: ".mcp.json",
8076
+ container: "mcpServers",
8077
+ shape: "plain",
8078
+ home: ".copilot",
8079
+ skills: { dir: join3(".github", "skills"), shared: true },
8080
+ manual: "Trust the folder when Copilot CLI first asks, or it reads no config here."
8081
+ },
8082
+ {
8083
+ id: "qoder",
8084
+ name: "Qoder",
8085
+ scope: "project",
8086
+ file: ".mcp.json",
8087
+ container: "mcpServers",
8088
+ shape: "plain",
8089
+ home: ".qoder",
8090
+ marker: ".qoder"
8091
+ },
8092
+ {
8093
+ id: "command-code",
8094
+ name: "Command Code",
8095
+ scope: "project",
8096
+ file: ".mcp.json",
8097
+ container: "mcpServers",
8098
+ shape: "plain",
8099
+ home: ".commandcode"
8100
+ },
8101
+ {
8102
+ id: "cursor",
8103
+ name: "Cursor",
8104
+ scope: "project",
8105
+ file: join3(".cursor", "mcp.json"),
8106
+ container: "mcpServers",
8107
+ shape: "plain",
8108
+ home: ".cursor",
8109
+ skills: { dir: join3(".cursor", "skills"), shared: true },
8110
+ manual: "Cursor asks before each tool call by default, and the server can be toggled off."
8111
+ },
8112
+ {
8113
+ id: "vscode",
8114
+ name: "VS Code",
8115
+ scope: "project",
8116
+ file: join3(".vscode", "mcp.json"),
8117
+ container: "servers",
8118
+ shape: "typed",
8119
+ home: ".vscode",
8120
+ skills: { dir: join3(".github", "skills"), shared: true },
8121
+ manual: "VS Code asks you to trust a server the first time it starts one."
8122
+ },
8123
+ {
8124
+ id: "opencode",
8125
+ name: "opencode",
8126
+ scope: "project",
8127
+ file: "opencode.json",
8128
+ container: "mcp",
8129
+ shape: "opencode",
8130
+ home: join3(".config", "opencode"),
8131
+ marker: ".opencode",
8132
+ skills: { dir: join3(".opencode", "skills"), shared: true }
8133
+ },
8134
+ {
8135
+ id: "junie",
8136
+ name: "Junie",
8137
+ scope: "project",
8138
+ file: join3(".junie", "mcp", "mcp.json"),
8139
+ container: "mcpServers",
8140
+ shape: "plain",
8141
+ home: ".junie",
8142
+ skills: { dir: join3(".junie", "skills"), shared: true }
8143
+ },
8144
+ {
8145
+ id: "kiro",
8146
+ name: "Kiro",
8147
+ scope: "project",
8148
+ file: join3(".kiro", "settings", "mcp.json"),
8149
+ container: "mcpServers",
8150
+ shape: "plain",
8151
+ home: ".kiro",
8152
+ skills: { dir: join3(".kiro", "skills"), shared: false }
8153
+ },
8154
+ {
8155
+ id: "gemini",
8156
+ name: "Gemini CLI",
8157
+ scope: "project",
8158
+ file: join3(".gemini", "settings.json"),
8159
+ container: "mcpServers",
8160
+ shape: "plain",
8161
+ home: ".gemini",
8162
+ skills: { dir: join3(".gemini", "skills"), shared: true }
8163
+ },
8164
+ {
8165
+ id: "roo",
8166
+ name: "Roo Code",
8167
+ scope: "project",
8168
+ file: join3(".roo", "mcp.json"),
8169
+ container: "mcpServers",
8170
+ shape: "plain"
8171
+ },
8172
+ {
8173
+ id: "kilo",
8174
+ name: "Kilo Code",
8175
+ scope: "project",
8176
+ file: join3(".kilocode", "mcp.json"),
8177
+ container: "mcpServers",
8178
+ shape: "plain"
8179
+ },
8180
+ {
8181
+ id: "amazon-q",
8182
+ name: "Amazon Q Developer CLI",
8183
+ scope: "project",
8184
+ file: join3(".amazonq", "mcp.json"),
8185
+ container: "mcpServers",
8186
+ shape: "plain",
8187
+ home: join3(".aws", "amazonq")
8188
+ },
8189
+ {
8190
+ id: "zed",
8191
+ name: "Zed",
8192
+ scope: "project",
8193
+ file: join3(".zed", "settings.json"),
8194
+ container: "context_servers",
8195
+ shape: "plain"
8196
+ },
8197
+ {
8198
+ id: "amp",
8199
+ name: "Amp",
8200
+ scope: "project",
8201
+ file: join3(".amp", "settings.json"),
8202
+ container: "amp.mcpServers",
8203
+ shape: "plain",
8204
+ home: join3(".config", "amp")
8205
+ },
8206
+ {
8207
+ id: "warp",
8208
+ name: "Warp",
8209
+ scope: "project",
8210
+ file: join3(".warp", ".mcp.json"),
8211
+ container: "mcpServers",
8212
+ shape: "plain",
8213
+ home: ".warp",
8214
+ manual: "Warp starts a project server only once you toggle it on, on its MCP servers page."
8215
+ },
8216
+ {
8217
+ id: "trae",
8218
+ name: "Trae",
8219
+ scope: "project",
8220
+ file: join3(".trae", "mcp.json"),
8221
+ container: "mcpServers",
8222
+ shape: "plain",
8223
+ home: ".trae"
8224
+ },
8225
+ {
8226
+ id: "factory",
8227
+ name: "Factory Droid",
8228
+ scope: "project",
8229
+ file: join3(".factory", "mcp.json"),
8230
+ container: "mcpServers",
8231
+ shape: "typed",
8232
+ home: ".factory"
8233
+ },
8234
+ {
8235
+ id: "tabnine",
8236
+ name: "Tabnine",
8237
+ scope: "project",
8238
+ file: join3(".tabnine", "mcp_servers.json"),
8239
+ container: "mcpServers",
8240
+ shape: "plain",
8241
+ home: ".tabnine"
8242
+ },
8243
+ {
8244
+ id: "firebender",
8245
+ name: "Firebender",
8246
+ scope: "project",
8247
+ file: "firebender.json",
8248
+ container: "mcpServers",
8249
+ shape: "plain"
8250
+ },
8251
+ {
8252
+ id: "pi",
8253
+ name: "pi",
8254
+ scope: "project",
8255
+ file: join3(".pi", "mcp.json"),
8256
+ container: "mcpServers",
8257
+ shape: "plain",
8258
+ home: ".pi"
8259
+ },
8260
+ {
8261
+ id: "mistral-vibe",
8262
+ name: "Mistral Vibe",
8263
+ scope: "project",
8264
+ file: join3(".vibe", "config.toml"),
8265
+ container: "mcp_servers",
8266
+ shape: "plain",
8267
+ toml: {
8268
+ header: "[[mcp_servers]]",
8269
+ identity: `name = "${SERVER_KEY}"`,
8270
+ block: (launch) => [
8271
+ "[[mcp_servers]]",
8272
+ `name = "${SERVER_KEY}"`,
8273
+ 'transport = "stdio"',
8274
+ `command = "${launch.command}"`,
8275
+ `args = ${tomlArray(launch.args)}`,
8276
+ tomlEnv(launch)
8277
+ ].join(`
8278
+ `)
8279
+ }
8280
+ },
8281
+ {
8282
+ id: "vtcode",
8283
+ name: "VT Code",
8284
+ scope: "project",
8285
+ file: "vtcode.toml",
8286
+ container: "mcp.providers",
8287
+ shape: "plain",
8288
+ marker: ".vtcode",
8289
+ toml: {
8290
+ header: "[[mcp.providers]]",
8291
+ identity: `name = "${SERVER_KEY}"`,
8292
+ enable: { header: "[mcp]", line: "enabled = true" },
8293
+ block: (launch) => [
8294
+ "[[mcp.providers]]",
8295
+ `name = "${SERVER_KEY}"`,
8296
+ "enabled = true",
8297
+ `command = "${launch.command}"`,
8298
+ `args = ${tomlArray(launch.args)}`,
8299
+ tomlEnv(launch)
8300
+ ].join(`
8301
+ `)
8302
+ }
8303
+ },
8304
+ {
8305
+ id: "fast-agent",
8306
+ name: "fast-agent",
8307
+ scope: "project",
8308
+ file: "fastagent.config.yaml",
8309
+ container: "mcp",
8310
+ shape: "plain",
8311
+ yaml: {
8312
+ path: ["mcp", "servers", SERVER_KEY],
8313
+ entry: (launch) => ({ command: launch.command, args: [...launch.args], env: { ...launch.env } })
8314
+ }
8315
+ },
8316
+ {
8317
+ id: "codex",
8318
+ name: "Codex CLI",
8319
+ scope: "home",
8320
+ file: join3(".codex", "config.toml"),
8321
+ container: "mcp_servers",
8322
+ shape: "plain",
8323
+ manual: "Codex reads its config at startup, so restart it.",
8324
+ toml: {
8325
+ header: `[mcp_servers.${SERVER_KEY}]`,
8326
+ block: (launch) => [
8327
+ `[mcp_servers.${SERVER_KEY}]`,
8328
+ `command = "${launch.command}"`,
8329
+ `args = ${tomlArray(launch.args)}`,
8330
+ tomlEnv(launch)
8331
+ ].join(`
8332
+ `)
8400
8333
  }
8401
-
8402
- /// <summary>How many more bytes Windows will commit.</summary>
8403
- public static string CommitLeft()
8404
- {
8405
- MemoryStatus status = new MemoryStatus();
8406
- status.Length = (uint)Marshal.SizeOf(typeof(MemoryStatus));
8407
- if (!GlobalMemoryStatusEx(ref status))
8408
- {
8409
- throw new InvalidOperationException("GlobalMemoryStatusEx failed with " + Number(Marshal.GetLastWin32Error()));
8410
- }
8411
- return status.AvailPageFile.ToString(CultureInfo.InvariantCulture);
8334
+ },
8335
+ {
8336
+ id: "cline",
8337
+ name: "Cline",
8338
+ scope: "home",
8339
+ file: join3(".cline", "data", "settings", "cline_mcp_settings.json"),
8340
+ container: "mcpServers",
8341
+ shape: "plain",
8342
+ marker: ".cline",
8343
+ skills: { dir: join3(".cline", "skills"), shared: false }
8344
+ },
8345
+ {
8346
+ id: "goose",
8347
+ name: "Goose",
8348
+ scope: "home",
8349
+ file: {
8350
+ win32: { appData: join3("Block", "goose", "config", "config.yaml") },
8351
+ darwin: join3(".config", "goose", "config.yaml"),
8352
+ linux: join3(".config", "goose", "config.yaml")
8353
+ },
8354
+ container: "extensions",
8355
+ shape: "plain",
8356
+ yaml: {
8357
+ path: ["extensions", SERVER_KEY],
8358
+ entry: (launch) => ({
8359
+ name: SERVER_KEY,
8360
+ type: "stdio",
8361
+ enabled: true,
8362
+ cmd: launch.command,
8363
+ args: [...launch.args],
8364
+ envs: { ...launch.env },
8365
+ timeout: 300
8366
+ })
8412
8367
  }
8413
-
8414
- /// <summary>
8415
- /// "pid started command" for each dated child of the pid, holding a handle to each: Windows tells
8416
- /// a process's exit code only to whoever holds a handle to it, and the handle keeps its number
8417
- /// from going to anything else.
8418
- /// </summary>
8419
- public static string HoldChildren(int parent)
8420
- {
8421
- StringBuilder said = new StringBuilder();
8422
- foreach (Entry entry in Snapshot())
8423
- {
8424
- if (entry.Parent != parent || entry.Pid <= 0 || entry.Created <= UnixEpoch || held.ContainsKey(entry.Pid))
8425
- {
8426
- continue;
8427
- }
8428
- IntPtr handle = Open(entry, QueryLimitedInformation | Synchronize);
8429
- if (handle == IntPtr.Zero)
8430
- {
8431
- continue;
8432
- }
8433
- held[entry.Pid] = handle;
8434
- said.Append(Number(entry.Pid)).Append(' ').Append(Milliseconds(entry.Created)).Append(' ')
8435
- .Append(CommandLineOf(handle)).Append('\n');
8436
- }
8437
- return said.ToString();
8368
+ },
8369
+ {
8370
+ id: "windsurf",
8371
+ name: "Windsurf",
8372
+ scope: "home",
8373
+ file: join3(".codeium", "windsurf", "mcp_config.json"),
8374
+ container: "mcpServers",
8375
+ shape: "plain",
8376
+ skills: { dir: join3(".windsurf", "skills"), shared: true }
8377
+ },
8378
+ {
8379
+ id: "hermes",
8380
+ name: "Hermes",
8381
+ scope: "home",
8382
+ file: join3(".hermes", "config.yaml"),
8383
+ container: "mcp_servers",
8384
+ shape: "plain",
8385
+ skills: { dir: join3(".hermes", "skills"), shared: true },
8386
+ yaml: {
8387
+ path: ["mcp_servers", SERVER_KEY],
8388
+ entry: (launch) => ({
8389
+ command: launch.command,
8390
+ args: [...launch.args],
8391
+ env: { ...launch.env },
8392
+ enabled: true
8393
+ })
8438
8394
  }
8439
-
8440
- /// <summary>"exit code" once a child held by HoldChildren has ended; empty for one not held.</summary>
8441
- public static string WaitFor(int pid)
8442
- {
8443
- IntPtr handle;
8444
- if (!held.TryGetValue(pid, out handle))
8445
- {
8446
- return "";
8447
- }
8448
- WaitForSingleObject(handle, 0xFFFFFFFF);
8449
- int code;
8450
- return GetExitCodeProcess(handle, out code) ? "exit " + Number(code) : "";
8395
+ },
8396
+ {
8397
+ id: "openclaw",
8398
+ name: "OpenClaw",
8399
+ scope: "home",
8400
+ file: join3(".openclaw", "openclaw.json"),
8401
+ container: "mcpServers",
8402
+ shape: "plain"
8403
+ },
8404
+ {
8405
+ id: "claude-desktop",
8406
+ name: "Claude Desktop",
8407
+ scope: "home",
8408
+ file: {
8409
+ win32: { appData: join3("Claude", "claude_desktop_config.json") },
8410
+ darwin: join3("Library", "Application Support", "Claude", "claude_desktop_config.json"),
8411
+ linux: join3(".config", "Claude", "claude_desktop_config.json")
8412
+ },
8413
+ container: "mcpServers",
8414
+ shape: "plain"
8415
+ },
8416
+ {
8417
+ id: "zeroclaw",
8418
+ name: "ZeroClaw",
8419
+ scope: "home",
8420
+ file: join3(".zeroclaw", "config.toml"),
8421
+ container: "mcp.servers",
8422
+ shape: "plain",
8423
+ toml: {
8424
+ header: "[[mcp.servers]]",
8425
+ identity: `name = "${SERVER_KEY}"`,
8426
+ enable: { header: "[mcp]", line: "enabled = true" },
8427
+ block: (launch) => [
8428
+ "[[mcp.servers]]",
8429
+ `name = "${SERVER_KEY}"`,
8430
+ `command = "${launch.command}"`,
8431
+ `args = ${tomlArray(launch.args)}`,
8432
+ tomlEnv(launch)
8433
+ ].join(`
8434
+ `)
8451
8435
  }
8452
- }
8453
- `;
8454
- var TABLE = new CompiledHelper("process table", "gdharness-processes", SOURCE2);
8455
-
8456
- class ProcessTableUnbuilt extends Error {
8457
- }
8458
- function ensureProcessTable(directory = tmpdir4(), wait = true) {
8459
- return TABLE.ensure(directory, HELPER_COMPILE_MS, wait);
8460
- }
8461
- async function loadingTheTable() {
8462
- const failed = await ensureProcessTable();
8463
- if (failed !== null) {
8464
- throw new ProcessTableUnbuilt(failed);
8436
+ },
8437
+ {
8438
+ id: "deepcode",
8439
+ name: "Deep Code",
8440
+ scope: "home",
8441
+ file: join3(".deepcode", "settings.json"),
8442
+ container: "mcpServers",
8443
+ shape: "plain"
8444
+ },
8445
+ {
8446
+ id: "nanobot",
8447
+ name: "nanobot",
8448
+ scope: "home",
8449
+ file: join3(".nanobot", "config.json"),
8450
+ container: "mcpServers",
8451
+ shape: "plain",
8452
+ snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
8453
+ },
8454
+ {
8455
+ id: "autohand",
8456
+ name: "Autohand",
8457
+ scope: "home",
8458
+ file: join3(".autohand", "config.json"),
8459
+ container: "mcpServers",
8460
+ shape: "plain",
8461
+ snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
8465
8462
  }
8466
- return `$null = [Reflection.Assembly]::LoadFrom('${TABLE.assembly().replaceAll("'", "''")}')`;
8463
+ ];
8464
+ var OURS = ["GODOT_PATH", "GDHARNESS_PROJECT"];
8465
+ function environmentFor(launch, held) {
8466
+ const kept = {};
8467
+ if (typeof held === "object" && held !== null && !Array.isArray(held)) {
8468
+ for (const [name, value] of Object.entries(held)) {
8469
+ if (typeof value === "string" && !OURS.includes(name)) {
8470
+ kept[name] = value;
8471
+ }
8472
+ }
8473
+ }
8474
+ return { ...kept, ...launch.env };
8467
8475
  }
8468
- async function askProcessTable(call, withinMs) {
8469
- return askWindows(`${await loadingTheTable()}; [GdhProcessTable]::${call}`, withinMs);
8476
+ function entryFor(shape, launch, held) {
8477
+ const before = typeof held === "object" && held !== null && !Array.isArray(held) ? { ...held } : {};
8478
+ if (shape === "opencode") {
8479
+ return {
8480
+ ...before,
8481
+ type: "local",
8482
+ command: [launch.command, ...launch.args],
8483
+ environment: environmentFor(launch, before["environment"]),
8484
+ enabled: true
8485
+ };
8486
+ }
8487
+ return {
8488
+ ...before,
8489
+ ...shape === "typed" ? { type: "stdio" } : {},
8490
+ command: launch.command,
8491
+ args: [...launch.args],
8492
+ env: environmentFor(launch, before["env"])
8493
+ };
8470
8494
  }
8471
8495
 
8496
+ // src/log-read.ts
8497
+ var LOG_LIMIT_BYTES = 128 * 1024 * 1024;
8498
+
8472
8499
  // src/gdscript-source.ts
8473
8500
  var DECLARING = new Set(["var", "const", "func", "signal", "enum", "class", "for", "class_name"]);
8474
8501
  var NAME = "[\\p{L}_][\\p{L}\\p{N}_]*";