fix: support Windows agent command shims
This commit is contained in:
Vendored
+5
-5
@@ -5,7 +5,6 @@ import { fileURLToPath } from "node:url";
|
||||
import { Command } from "commander";
|
||||
|
||||
// src/agents.ts
|
||||
import { spawn } from "node:child_process";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { constants } from "node:fs";
|
||||
import { copyFile, cp, mkdir as mkdir2, readFile as readFile2, readdir, rename as rename2, rm, stat, writeFile as writeFile2 } from "node:fs/promises";
|
||||
@@ -13,6 +12,7 @@ import os2 from "node:os";
|
||||
import path2 from "node:path";
|
||||
import { createInterface } from "node:readline/promises";
|
||||
import { applyEdits, modify, parse } from "jsonc-parser";
|
||||
import spawn from "cross-spawn";
|
||||
|
||||
// src/config.ts
|
||||
import { createHash } from "node:crypto";
|
||||
@@ -397,10 +397,10 @@ var SpawnCommandRunner = class {
|
||||
const child = spawn(command, args, { shell: false, windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
child.stdout.setEncoding("utf8").on("data", (chunk) => {
|
||||
child.stdout?.setEncoding("utf8").on("data", (chunk) => {
|
||||
stdout += String(chunk);
|
||||
});
|
||||
child.stderr.setEncoding("utf8").on("data", (chunk) => {
|
||||
child.stderr?.setEncoding("utf8").on("data", (chunk) => {
|
||||
stderr += String(chunk);
|
||||
});
|
||||
child.once("error", (error) => reject(new Error(`Could not run ${command}: ${errorMessage(error)}`)));
|
||||
@@ -737,7 +737,7 @@ async function serveBridge(options, tokenStore, discoveryStore, serviceToken = p
|
||||
}
|
||||
}
|
||||
function createProxyServer(upstream) {
|
||||
const server = new Server({ name: "crafttable-mcp-stdio-bridge", version: "0.1.2" }, {
|
||||
const server = new Server({ name: "crafttable-mcp-stdio-bridge", version: "0.1.3" }, {
|
||||
capabilities: {
|
||||
tools: {},
|
||||
resources: {}
|
||||
@@ -880,7 +880,7 @@ function keyringError(error) {
|
||||
}
|
||||
|
||||
// src/cli.ts
|
||||
var program = new Command().name("crafttable-mcp").description("OAuth client and stdio bridge for CraftTable MCP").version("0.1.2");
|
||||
var program = new Command().name("crafttable-mcp").description("OAuth client and stdio bridge for CraftTable MCP").version("0.1.3");
|
||||
withConnection(program.command("login").description("Log in through the system browser")).option("--no-browser", "print the authorization URL instead of opening it").option("--timeout <milliseconds>", "OAuth callback timeout", "600000").action(async (flags) => {
|
||||
const options = connectionOptions(flags);
|
||||
const timeoutMs = positiveInteger(flags.timeout, "OAuth callback timeout");
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Generated
+14
-2
@@ -1,17 +1,18 @@
|
||||
{
|
||||
"name": "@game-crafttable/mcp-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@game-crafttable/mcp-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "latest",
|
||||
"@napi-rs/keyring": "^1.3.0",
|
||||
"commander": "^14.0.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"open": "^10.2.0"
|
||||
},
|
||||
@@ -20,6 +21,7 @@
|
||||
"crafttable-mcp-client": "dist/cli.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cross-spawn": "^6.0.6",
|
||||
"@types/node": "latest",
|
||||
"esbuild": "latest",
|
||||
"tsx": "latest",
|
||||
@@ -757,6 +759,16 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cross-spawn": {
|
||||
"version": "6.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz",
|
||||
"integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "26.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz",
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@game-crafttable/mcp-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"description": "OAuth CLI and stdio bridge for the CraftTable MCP server",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,11 +29,13 @@
|
||||
"@modelcontextprotocol/sdk": "latest",
|
||||
"@napi-rs/keyring": "^1.3.0",
|
||||
"commander": "^14.0.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"open": "^10.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "latest",
|
||||
"@types/cross-spawn": "^6.0.6",
|
||||
"esbuild": "latest",
|
||||
"tsx": "latest",
|
||||
"typescript": "latest"
|
||||
|
||||
+3
-3
@@ -1,4 +1,3 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { constants } from "node:fs";
|
||||
import { copyFile, cp, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
||||
@@ -6,6 +5,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { createInterface } from "node:readline/promises";
|
||||
import { applyEdits, modify, parse } from "jsonc-parser";
|
||||
import spawn from "cross-spawn";
|
||||
import type { ClientOptions } from "./config.js";
|
||||
import { errorMessage } from "./config.js";
|
||||
|
||||
@@ -383,8 +383,8 @@ export class SpawnCommandRunner implements CommandRunner {
|
||||
const child = spawn(command, args, { shell: false, windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
child.stdout.setEncoding("utf8").on("data", (chunk) => { stdout += String(chunk); });
|
||||
child.stderr.setEncoding("utf8").on("data", (chunk) => { stderr += String(chunk); });
|
||||
child.stdout?.setEncoding("utf8").on("data", (chunk) => { stdout += String(chunk); });
|
||||
child.stderr?.setEncoding("utf8").on("data", (chunk) => { stderr += String(chunk); });
|
||||
child.once("error", (error) => reject(new Error(`Could not run ${command}: ${errorMessage(error)}`)));
|
||||
child.once("close", (code) => resolve({ code: code ?? 1, stdout, stderr }));
|
||||
});
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ export function createProxyServer(upstream: {
|
||||
listResourceTemplates: (params?: { cursor?: string }) => Promise<unknown>;
|
||||
readResource: (params: { uri: string }) => Promise<unknown>;
|
||||
}): Server {
|
||||
const server = new Server({ name: "crafttable-mcp-stdio-bridge", version: "0.1.2" }, {
|
||||
const server = new Server({ name: "crafttable-mcp-stdio-bridge", version: "0.1.3" }, {
|
||||
capabilities: {
|
||||
tools: {},
|
||||
resources: {},
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ type ConnectionFlags = { url?: string; clientId?: string; callbackPort?: string
|
||||
const program = new Command()
|
||||
.name("crafttable-mcp")
|
||||
.description("OAuth client and stdio bridge for CraftTable MCP")
|
||||
.version("0.1.2");
|
||||
.version("0.1.3");
|
||||
|
||||
withConnection(program.command("login").description("Log in through the system browser"))
|
||||
.option("--no-browser", "print the authorization URL instead of opening it")
|
||||
|
||||
+14
-1
@@ -4,7 +4,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
import { parse } from "jsonc-parser";
|
||||
import { configureAgents, type CommandResult, type CommandRunner, defaultSkillPath, launchCommand, unconfigureAgents } from "../src/agents.js";
|
||||
import { configureAgents, type CommandResult, type CommandRunner, defaultSkillPath, launchCommand, SpawnCommandRunner, unconfigureAgents } from "../src/agents.js";
|
||||
import { resolveClientOptions } from "../src/config.js";
|
||||
|
||||
class FakeRunner implements CommandRunner {
|
||||
@@ -45,6 +45,19 @@ test("Agent Skill paths use each client's user-level discovery directory", () =>
|
||||
assert.equal(defaultSkillPath("opencode", env), path.join("C:\\Config", "opencode", "skills", "crafttable"));
|
||||
});
|
||||
|
||||
test("command runner launches Windows command shims", { skip: process.platform !== "win32" }, async () => {
|
||||
const directory = await mkdtemp(path.join(os.tmpdir(), "crafttable-mcp-shim-test-"));
|
||||
const shim = path.join(directory, "fixture.cmd");
|
||||
await writeFile(shim, "@echo off\r\necho shim:%1\r\n", "utf8");
|
||||
try {
|
||||
const result = await new SpawnCommandRunner().run(shim, ["ok"]);
|
||||
assert.equal(result.code, 0);
|
||||
assert.match(result.stdout, /shim:"?ok"?/);
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("Codex and Claude adapters add, detect idempotency, replace conflicts, remove, and dry-run", async () => {
|
||||
const directory = await mkdtemp(path.join(os.tmpdir(), "crafttable-mcp-cli-agent-test-"));
|
||||
const skillSource = await createSkillFixture(directory);
|
||||
|
||||
Reference in New Issue
Block a user