@ai-ecoverse/mcpcat 0.14.1 → 0.14.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.
@@ -49,6 +49,101 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
49
49
  mod
50
50
  ));
51
51
 
52
+ // src/config/lock.ts
53
+ var lock_exports = {};
54
+ __export(lock_exports, {
55
+ acquireLock: () => acquireLock
56
+ });
57
+ function isEexist(err) {
58
+ if (err instanceof Error && "code" in err)
59
+ return err.code === "EEXIST";
60
+ if (err instanceof Error) return err.message.includes("EEXIST");
61
+ return false;
62
+ }
63
+ async function removeStaleLockDir(fs, lockPath) {
64
+ try {
65
+ const s = await fs.stat(lockPath);
66
+ if (Date.now() - s.mtimeMs > LOCK_STALE_MS) {
67
+ try {
68
+ await fs.rmdir(lockPath);
69
+ } catch {
70
+ }
71
+ return true;
72
+ }
73
+ } catch {
74
+ }
75
+ return false;
76
+ }
77
+ async function removeStaleLockFile(fs, lockPath) {
78
+ try {
79
+ const s = await fs.stat(lockPath);
80
+ if (Date.now() - s.mtimeMs > LOCK_STALE_MS) {
81
+ try {
82
+ await fs.unlink(lockPath);
83
+ } catch {
84
+ }
85
+ return true;
86
+ }
87
+ } catch {
88
+ }
89
+ return false;
90
+ }
91
+ async function acquireLock(fs, configPath) {
92
+ const useFile = typeof fs.createExclusive === "function";
93
+ const lockPath = `${configPath}.lock`;
94
+ const start = Date.now();
95
+ const parentDir = lockPath.slice(0, lockPath.lastIndexOf("/"));
96
+ if (parentDir) {
97
+ try {
98
+ await fs.mkdir(parentDir);
99
+ } catch {
100
+ }
101
+ }
102
+ while (true) {
103
+ try {
104
+ if (useFile) {
105
+ await fs.createExclusive(lockPath);
106
+ } else {
107
+ await fs.mkdirExclusive(lockPath);
108
+ }
109
+ break;
110
+ } catch (err) {
111
+ if (!isEexist(err)) throw err;
112
+ if (useFile) {
113
+ await removeStaleLockFile(fs, lockPath);
114
+ } else {
115
+ await removeStaleLockDir(fs, lockPath);
116
+ }
117
+ }
118
+ if (Date.now() - start > LOCK_MAX_WAIT_MS) {
119
+ throw new Error(`mcpcat: could not acquire lock ${lockPath} within ${LOCK_MAX_WAIT_MS}ms`);
120
+ }
121
+ await new Promise((r) => setTimeout(r, LOCK_POLL_MS));
122
+ }
123
+ let released = false;
124
+ return async () => {
125
+ if (released) return;
126
+ released = true;
127
+ try {
128
+ if (useFile && fs.unlink) {
129
+ await fs.unlink(lockPath);
130
+ } else {
131
+ await fs.rmdir(lockPath);
132
+ }
133
+ } catch {
134
+ }
135
+ };
136
+ }
137
+ var LOCK_STALE_MS, LOCK_POLL_MS, LOCK_MAX_WAIT_MS;
138
+ var init_lock = __esm({
139
+ "src/config/lock.ts"() {
140
+ "use strict";
141
+ LOCK_STALE_MS = 1e4;
142
+ LOCK_POLL_MS = 50;
143
+ LOCK_MAX_WAIT_MS = 5e3;
144
+ }
145
+ });
146
+
52
147
  // node_modules/isexe/windows.js
53
148
  var require_windows = __commonJS({
54
149
  "node_modules/isexe/windows.js"(exports, module) {
@@ -6345,7 +6440,7 @@ var McpOAuthProvider = class {
6345
6440
  };
6346
6441
 
6347
6442
  // src/auth/jerk-token-source.ts
6348
- var MIN_VERSION = [0, 13, 0];
6443
+ var MIN_VERSION = [0, 14, 1];
6349
6444
  var VERSION_TIMEOUT_MS = 2e3;
6350
6445
  var cachedAvailable;
6351
6446
  function parseVersion(raw) {
@@ -6471,6 +6566,192 @@ var JerkTokenSource = class {
6471
6566
  }
6472
6567
  };
6473
6568
 
6569
+ // src/auth/pi-store.ts
6570
+ init_lock();
6571
+
6572
+ // src/config/paths.ts
6573
+ function userConfigDir(platform2) {
6574
+ const piDir = platform2.env.PI_CODING_AGENT_DIR;
6575
+ if (piDir) return piDir;
6576
+ const home = platform2.env.HOME ?? platform2.env.USERPROFILE ?? "/";
6577
+ return `${home}/.pi/agent`;
6578
+ }
6579
+ function userConfigPath(platform2) {
6580
+ return `${userConfigDir(platform2)}/mcp.json`;
6581
+ }
6582
+ function projectConfigPath(platform2) {
6583
+ return `${platform2.cwd}/.pi/mcp.json`;
6584
+ }
6585
+ function stateDir(platform2) {
6586
+ if (platform2.env.XDG_STATE_HOME) return `${platform2.env.XDG_STATE_HOME}/mcpcat`;
6587
+ const home = platform2.env.HOME ?? platform2.env.USERPROFILE ?? "/";
6588
+ if (platform2.env.LOCALAPPDATA) return `${platform2.env.LOCALAPPDATA}\\mcpcat\\state`;
6589
+ if (platform2.env.SLICC_KERNEL) return `${home}/.local/state/mcpcat`;
6590
+ return `${home}/Library/Application Support/mcpcat`;
6591
+ }
6592
+
6593
+ // src/auth/token-source.ts
6594
+ function mcpNamespace(server) {
6595
+ return `mcp__${server.replace(/-/g, "_")}`;
6596
+ }
6597
+ function storeKey(name, serverUrl) {
6598
+ const ns = mcpNamespace(name);
6599
+ const url = String(new URL(serverUrl));
6600
+ return `${ns}|${url}`;
6601
+ }
6602
+ function isKernel(platform2) {
6603
+ return platform2.kind === "kernel";
6604
+ }
6605
+
6606
+ // src/auth/pi-store.ts
6607
+ var AUTH_FILE = "mcp-auth.json";
6608
+ var FILE_MODE = 384;
6609
+ var DIR_MODE = 448;
6610
+ function parseStates(raw) {
6611
+ if (!raw?.trim()) return {};
6612
+ const parsed = JSON.parse(raw);
6613
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
6614
+ }
6615
+ function serializeStates(states) {
6616
+ return `${JSON.stringify(states, null, 2)}
6617
+ `;
6618
+ }
6619
+ function legacyKey(serverUrl) {
6620
+ return String(new URL(serverUrl));
6621
+ }
6622
+ var PiFileTokenSource = class {
6623
+ platform;
6624
+ authPath;
6625
+ dirPath;
6626
+ constructor(platform2) {
6627
+ this.platform = platform2;
6628
+ this.dirPath = userConfigDir(platform2);
6629
+ this.authPath = `${this.dirPath}/${AUTH_FILE}`;
6630
+ }
6631
+ get path() {
6632
+ return this.authPath;
6633
+ }
6634
+ async loadWithoutLock(name, serverUrl) {
6635
+ const key = storeKey(name, serverUrl);
6636
+ const legacy = legacyKey(serverUrl);
6637
+ try {
6638
+ const raw = await this.readRaw();
6639
+ const states = parseStates(raw);
6640
+ return states[key] ?? states[legacy];
6641
+ } catch {
6642
+ return void 0;
6643
+ }
6644
+ }
6645
+ async getToken(name, serverUrl) {
6646
+ const state = await this.load(name, serverUrl);
6647
+ if (!state?.tokens?.access_token) return void 0;
6648
+ return {
6649
+ accessToken: state.tokens.access_token,
6650
+ expiresAt: state.tokensExpireAt
6651
+ };
6652
+ }
6653
+ async load(name, serverUrl) {
6654
+ const key = storeKey(name, serverUrl);
6655
+ const legacy = legacyKey(serverUrl);
6656
+ const release = await this.acquireLock();
6657
+ try {
6658
+ const raw = await this.readRaw();
6659
+ const states = parseStates(raw);
6660
+ if (states[key]) return states[key];
6661
+ if (states[legacy]) {
6662
+ states[key] = states[legacy];
6663
+ delete states[legacy];
6664
+ await this.writeStates(states);
6665
+ return states[key];
6666
+ }
6667
+ return void 0;
6668
+ } finally {
6669
+ await release();
6670
+ }
6671
+ }
6672
+ async save(name, serverUrl, state) {
6673
+ const key = storeKey(name, serverUrl);
6674
+ const release = await this.acquireLock();
6675
+ try {
6676
+ const raw = await this.readRaw();
6677
+ const states = parseStates(raw);
6678
+ states[key] = state;
6679
+ await this.writeStates(states);
6680
+ } finally {
6681
+ await release();
6682
+ }
6683
+ }
6684
+ async remove(name, serverUrl) {
6685
+ const key = storeKey(name, serverUrl);
6686
+ const legacy = legacyKey(serverUrl);
6687
+ const release = await this.acquireLock();
6688
+ try {
6689
+ const raw = await this.readRaw();
6690
+ const states = parseStates(raw);
6691
+ const stored = key in states ? key : legacy in states ? legacy : void 0;
6692
+ if (!stored) return false;
6693
+ delete states[stored];
6694
+ await this.writeStates(states);
6695
+ return true;
6696
+ } finally {
6697
+ await release();
6698
+ }
6699
+ }
6700
+ async acquireLock() {
6701
+ await this.ensureDir();
6702
+ return acquireLock(this.platform.fs, this.authPath);
6703
+ }
6704
+ async ensureDir() {
6705
+ const fs = this.platform.fs;
6706
+ try {
6707
+ await fs.mkdir(this.dirPath, { mode: DIR_MODE });
6708
+ } catch {
6709
+ }
6710
+ if (fs.chmod) {
6711
+ try {
6712
+ await fs.chmod(this.dirPath, DIR_MODE);
6713
+ } catch {
6714
+ }
6715
+ const piDir = this.dirPath.slice(0, this.dirPath.lastIndexOf("/"));
6716
+ if (piDir) {
6717
+ try {
6718
+ await fs.chmod(piDir, DIR_MODE);
6719
+ } catch {
6720
+ }
6721
+ }
6722
+ }
6723
+ }
6724
+ async readRaw() {
6725
+ try {
6726
+ const data = await this.platform.fs.readFile(this.authPath);
6727
+ return new TextDecoder().decode(data);
6728
+ } catch {
6729
+ return void 0;
6730
+ }
6731
+ }
6732
+ async writeStates(states) {
6733
+ const fs = this.platform.fs;
6734
+ const content = serializeStates(states);
6735
+ const tmpPath = `${this.authPath}.tmp.${Date.now()}`;
6736
+ try {
6737
+ await fs.writeFile(tmpPath, content, { mode: FILE_MODE });
6738
+ await fs.rename(tmpPath, this.authPath);
6739
+ } catch (renameErr) {
6740
+ try {
6741
+ if (fs.unlink) await fs.unlink(tmpPath);
6742
+ } catch {
6743
+ }
6744
+ throw renameErr;
6745
+ }
6746
+ if (fs.chmod) {
6747
+ try {
6748
+ await fs.chmod(this.authPath, FILE_MODE);
6749
+ } catch {
6750
+ }
6751
+ }
6752
+ }
6753
+ };
6754
+
6474
6755
  // src/auth/auth-provider.ts
6475
6756
  var CIMD_URL = "https://mcpcat.sliccy.ai/oauth/client.json";
6476
6757
  var CLIENT_NAME = "mcpcat";
@@ -6492,10 +6773,12 @@ var SourceBackedStore = class {
6492
6773
  source;
6493
6774
  name;
6494
6775
  serverUrl;
6495
- constructor(source, name, serverUrl) {
6776
+ platform;
6777
+ constructor(source, name, serverUrl, platform2) {
6496
6778
  this.source = source;
6497
6779
  this.name = name;
6498
6780
  this.serverUrl = serverUrl;
6781
+ this.platform = platform2;
6499
6782
  }
6500
6783
  async load() {
6501
6784
  return this.source.load(this.name, this.serverUrl);
@@ -6503,6 +6786,17 @@ var SourceBackedStore = class {
6503
6786
  async save(state) {
6504
6787
  await this.source.save(this.name, this.serverUrl, state);
6505
6788
  }
6789
+ async withRefreshLock(fn) {
6790
+ if (!(this.source instanceof PiFileTokenSource)) return fn();
6791
+ const refreshPath = `${this.source.path}.refresh`;
6792
+ const { acquireLock: acquireLock2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
6793
+ const release = await acquireLock2(this.platform.fs, refreshPath);
6794
+ try {
6795
+ return await fn();
6796
+ } finally {
6797
+ await release();
6798
+ }
6799
+ }
6506
6800
  };
6507
6801
  function cimdFn(redirectUrl) {
6508
6802
  return (metadata) => {
@@ -6531,10 +6825,9 @@ function createMcpAuthProvider(options) {
6531
6825
  function createJerkAuthProvider(options) {
6532
6826
  const { name, serverUrl, source } = options;
6533
6827
  let currentToken;
6828
+ const _fetched = false;
6534
6829
  return {
6535
6830
  async token() {
6536
- const result = await source.getToken(name, serverUrl);
6537
- currentToken = result?.accessToken;
6538
6831
  return currentToken;
6539
6832
  },
6540
6833
  async onUnauthorized(context) {
@@ -6565,10 +6858,10 @@ function createJerkAuthProvider(options) {
6565
6858
  }
6566
6859
  function createPiAuthProvider(options) {
6567
6860
  const { name, serverUrl, source, oauth, platform: platform2 } = options;
6568
- const store = new SourceBackedStore(source, name, serverUrl);
6861
+ const store = new SourceBackedStore(source, name, serverUrl, platform2);
6569
6862
  let refreshing;
6570
6863
  const refresh = async (staleToken) => {
6571
- refreshing ??= (async () => {
6864
+ refreshing ??= store.withRefreshLock(async () => {
6572
6865
  const state = await store.load();
6573
6866
  if (state?.tokens?.access_token !== staleToken) return;
6574
6867
  if (!state?.tokens?.refresh_token) throw new McpOAuthAuthorizationRequiredError();
@@ -6591,7 +6884,7 @@ function createPiAuthProvider(options) {
6591
6884
  fetch: timedFetch(platform2.fetch)
6592
6885
  });
6593
6886
  if (result === "REDIRECT") throw new McpOAuthAuthorizationRequiredError();
6594
- })().finally(() => {
6887
+ }).finally(() => {
6595
6888
  refreshing = void 0;
6596
6889
  });
6597
6890
  return refreshing;
@@ -7718,11 +8011,45 @@ var StreamableHttpTransport = class extends TransportEvents {
7718
8011
  }
7719
8012
  };
7720
8013
 
7721
- // src/client/platform-stdio-transport.ts
7722
- var DEFAULT_MAX_MESSAGE_BYTES2 = 4 * 1024 * 1024;
7723
- var DEFAULT_MAX_STDERR_BYTES2 = 64 * 1024;
7724
- var DEFAULT_CLOSE_TIMEOUT_MS2 = 2e3;
7725
- var STDIN_CLOSE_GRACE_MS2 = 500;
8014
+ // src/client/stdio-registry.ts
8015
+ var GRACE_MS = 2e3;
8016
+ var registry = /* @__PURE__ */ new Set();
8017
+ function trackStdio(proc) {
8018
+ registry.add(proc);
8019
+ void proc.wait().then(
8020
+ () => registry.delete(proc),
8021
+ () => registry.delete(proc)
8022
+ );
8023
+ }
8024
+ async function killAllStdio() {
8025
+ const procs = [...registry];
8026
+ if (procs.length === 0) return;
8027
+ await Promise.all(
8028
+ procs.map(async (proc) => {
8029
+ try {
8030
+ await proc.kill("SIGTERM");
8031
+ } catch {
8032
+ }
8033
+ const exited = await Promise.race([
8034
+ proc.wait().then(() => true),
8035
+ new Promise((r) => setTimeout(() => r(false), GRACE_MS))
8036
+ ]);
8037
+ if (!exited) {
8038
+ try {
8039
+ await proc.kill("SIGKILL");
8040
+ } catch {
8041
+ }
8042
+ }
8043
+ })
8044
+ );
8045
+ registry.clear();
8046
+ }
8047
+
8048
+ // src/client/platform-stdio-transport.ts
8049
+ var DEFAULT_MAX_MESSAGE_BYTES2 = 4 * 1024 * 1024;
8050
+ var DEFAULT_MAX_STDERR_BYTES2 = 64 * 1024;
8051
+ var DEFAULT_CLOSE_TIMEOUT_MS2 = 2e3;
8052
+ var STDIN_CLOSE_GRACE_MS2 = 500;
7726
8053
  var PlatformStdioTransport = class {
7727
8054
  options;
7728
8055
  process;
@@ -7774,16 +8101,21 @@ var PlatformStdioTransport = class {
7774
8101
  if (this.started) throw new Error("MCP stdio transport already started");
7775
8102
  if (this.closed) throw new Error("MCP connection closed");
7776
8103
  this.started = true;
7777
- const env = this.options.inheritEnv === false ? { ...this.options.env ?? {} } : {
7778
- ...this.options.platform.env,
7779
- ...this.options.env
7780
- };
7781
- this.process = await this.options.platform.spawn({
7782
- argv: [this.options.command, ...this.options.args ?? []],
7783
- env,
7784
- cwd: this.options.cwd
7785
- });
7786
- void this.readStdout();
8104
+ if (this.options.existingProcess) {
8105
+ this.process = this.options.existingProcess;
8106
+ } else {
8107
+ const env = this.options.inheritEnv === false ? { ...this.options.env ?? {} } : {
8108
+ ...this.options.platform.env,
8109
+ ...this.options.env
8110
+ };
8111
+ this.process = await this.options.platform.spawn({
8112
+ argv: [this.options.command, ...this.options.args ?? []],
8113
+ env,
8114
+ cwd: this.options.cwd
8115
+ });
8116
+ trackStdio(this.process);
8117
+ }
8118
+ void this.readStdout(this.options.pendingStdout);
7787
8119
  void this.readStderr();
7788
8120
  void this.waitForExit();
7789
8121
  }
@@ -7816,22 +8148,22 @@ var PlatformStdioTransport = class {
7816
8148
  }
7817
8149
  const exited = await Promise.race([done, delay(grace)]);
7818
8150
  if (!exited) {
7819
- proc.kill("SIGTERM");
8151
+ await proc.kill("SIGTERM");
7820
8152
  const exitedAfterTerm = await Promise.race([done, delay(closeTimeoutMs)]);
7821
8153
  if (!exitedAfterTerm) {
7822
- proc.kill("SIGKILL");
8154
+ await proc.kill("SIGKILL");
7823
8155
  await done;
7824
8156
  }
7825
8157
  }
7826
- proc.kill("SIGTERM");
8158
+ await proc.kill("SIGTERM");
7827
8159
  this.emitClose();
7828
8160
  }
7829
- async readStdout() {
8161
+ async readStdout(pending) {
7830
8162
  const proc = this.process;
7831
8163
  if (!proc) return;
7832
8164
  const reader = proc.stdout.getReader();
7833
8165
  const maxBytes = this.options.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES2;
7834
- let buffer = "";
8166
+ let buffer = pending ?? "";
7835
8167
  try {
7836
8168
  for (; ; ) {
7837
8169
  const { done, value } = await reader.read();
@@ -7891,6 +8223,10 @@ var PlatformStdioTransport = class {
7891
8223
  await proc.wait();
7892
8224
  } catch {
7893
8225
  }
8226
+ try {
8227
+ await proc.kill("SIGTERM");
8228
+ } catch {
8229
+ }
7894
8230
  if (!this.closed) {
7895
8231
  this.emitClose();
7896
8232
  }
@@ -8232,7 +8568,9 @@ function buildTransport(options) {
8232
8568
  cwd: options.cwd,
8233
8569
  inheritEnv: true,
8234
8570
  platform: options.platform,
8235
- onStderr: buildStderrHandler(options)
8571
+ onStderr: buildStderrHandler(options),
8572
+ existingProcess: options.existingProcess?.proc,
8573
+ pendingStdout: options.existingProcess?.pendingStdout
8236
8574
  });
8237
8575
  }
8238
8576
  return new StdioTransport({
@@ -8419,6 +8757,9 @@ function createStdioJsonRpc(proc, platform2, options) {
8419
8757
  reader.releaseLock();
8420
8758
  } catch {
8421
8759
  }
8760
+ },
8761
+ pendingBuffer() {
8762
+ return readBuffer;
8422
8763
  }
8423
8764
  };
8424
8765
  }
@@ -8471,13 +8812,13 @@ function buildConnectionMethods(rpc, discoverResult2, proc) {
8471
8812
  async close() {
8472
8813
  rpc.close();
8473
8814
  try {
8474
- proc.kill("SIGTERM");
8815
+ await proc.kill("SIGTERM");
8475
8816
  } catch {
8476
8817
  }
8477
8818
  }
8478
8819
  };
8479
8820
  }
8480
- async function createStdioStatelessConnection(options) {
8821
+ async function probeStdioStateless(options) {
8481
8822
  const inheritedEnv = {
8482
8823
  ...options.platform.env,
8483
8824
  ...options.env
@@ -8487,22 +8828,30 @@ async function createStdioStatelessConnection(options) {
8487
8828
  env: inheritedEnv,
8488
8829
  cwd: options.cwd
8489
8830
  });
8490
- void readStderr(proc, options.verbose);
8831
+ trackStdio(proc);
8491
8832
  const rpc = createStdioJsonRpc(proc, options.platform, {
8492
8833
  version: options.version,
8493
8834
  timeoutMs: options.timeoutMs,
8494
8835
  signal: options.signal,
8495
8836
  verbose: options.verbose
8496
8837
  });
8497
- const discoverRaw = await rpc.request("server/discover", {
8498
- protocolVersion: PROTOCOL_VERSION
8499
- });
8838
+ let discoverRaw;
8839
+ try {
8840
+ discoverRaw = await rpc.request("server/discover", {
8841
+ protocolVersion: PROTOCOL_VERSION
8842
+ });
8843
+ } catch (err) {
8844
+ const pending = rpc.pendingBuffer();
8845
+ rpc.close();
8846
+ return { proc, pendingStdout: pending, error: err };
8847
+ }
8848
+ void readStderr(proc, options.verbose);
8500
8849
  const discoverResult2 = discoverRaw;
8501
8850
  const supported = (discoverResult2?.supportedVersions ?? []).filter(
8502
8851
  (v) => typeof v === "string"
8503
8852
  );
8504
8853
  if (!supported.includes(PROTOCOL_VERSION)) {
8505
- proc.kill("SIGTERM");
8854
+ await proc.kill("SIGTERM");
8506
8855
  throw new Error(
8507
8856
  `Server does not support ${PROTOCOL_VERSION} (advertised: ${supported.join(", ") || "none"})`
8508
8857
  );
@@ -8536,25 +8885,37 @@ async function connect(platform2, options) {
8536
8885
  platform: platform2
8537
8886
  };
8538
8887
  if (options.command) {
8888
+ let fallbackProcess;
8539
8889
  if (!options.protocolVersion || options.protocolVersion.startsWith("2026")) {
8540
- try {
8541
- return await createStdioStatelessConnection({
8542
- command: options.command,
8543
- args: options.args,
8544
- env: options.env,
8545
- cwd: options.cwd,
8546
- platform: platform2,
8547
- version: options.version,
8548
- timeoutMs: options.timeoutMs,
8549
- signal: options.signal,
8550
- verbose: options.verbose
8551
- });
8552
- } catch (err) {
8553
- const isMethodNotFound = err instanceof StatelessRpcError && err.code === -32601;
8554
- const isUnsupported = err instanceof Error && err.message.includes("does not support");
8555
- if (options.protocolVersion?.startsWith("2026")) throw err;
8556
- if (!isMethodNotFound && !isUnsupported) throw err;
8890
+ const result = await probeStdioStateless({
8891
+ command: options.command,
8892
+ args: options.args,
8893
+ env: options.env,
8894
+ cwd: options.cwd,
8895
+ platform: platform2,
8896
+ version: options.version,
8897
+ timeoutMs: options.timeoutMs,
8898
+ signal: options.signal,
8899
+ verbose: options.verbose
8900
+ });
8901
+ if (!("proc" in result)) return result;
8902
+ const isMethodNotFound = result.error instanceof StatelessRpcError && result.error.code === -32601;
8903
+ const isUnsupported = result.error.message.includes("does not support");
8904
+ if (options.protocolVersion?.startsWith("2026")) {
8905
+ try {
8906
+ await result.proc.kill("SIGTERM");
8907
+ } catch {
8908
+ }
8909
+ throw result.error;
8910
+ }
8911
+ if (!isMethodNotFound && !isUnsupported) {
8912
+ try {
8913
+ await result.proc.kill("SIGTERM");
8914
+ } catch {
8915
+ }
8916
+ throw result.error;
8557
8917
  }
8918
+ fallbackProcess = { proc: result.proc, pendingStdout: result.pendingStdout };
8558
8919
  }
8559
8920
  return createPiConnection({
8560
8921
  command: options.command,
@@ -8562,6 +8923,7 @@ async function connect(platform2, options) {
8562
8923
  env: options.env,
8563
8924
  cwd: options.cwd,
8564
8925
  roots: options.roots,
8926
+ existingProcess: fallbackProcess,
8565
8927
  ...shared
8566
8928
  });
8567
8929
  }
@@ -9571,27 +9933,6 @@ async function loadConfig(input) {
9571
9933
  };
9572
9934
  }
9573
9935
 
9574
- // src/config/paths.ts
9575
- function userConfigDir(platform2) {
9576
- const piDir = platform2.env.PI_CODING_AGENT_DIR;
9577
- if (piDir) return piDir;
9578
- const home = platform2.env.HOME ?? platform2.env.USERPROFILE ?? "/";
9579
- return `${home}/.pi/agent`;
9580
- }
9581
- function userConfigPath(platform2) {
9582
- return `${userConfigDir(platform2)}/mcp.json`;
9583
- }
9584
- function projectConfigPath(platform2) {
9585
- return `${platform2.cwd}/.pi/mcp.json`;
9586
- }
9587
- function stateDir(platform2) {
9588
- if (platform2.env.XDG_STATE_HOME) return `${platform2.env.XDG_STATE_HOME}/mcpcat`;
9589
- const home = platform2.env.HOME ?? platform2.env.USERPROFILE ?? "/";
9590
- if (platform2.env.LOCALAPPDATA) return `${platform2.env.LOCALAPPDATA}\\mcpcat\\state`;
9591
- if (platform2.env.SLICC_KERNEL) return `${home}/.local/state/mcpcat`;
9592
- return `${home}/Library/Application Support/mcpcat`;
9593
- }
9594
-
9595
9936
  // src/config/index.ts
9596
9937
  var MergedConfigSource = class _MergedConfigSource {
9597
9938
  entries;
@@ -9631,65 +9972,8 @@ var MergedConfigSource = class _MergedConfigSource {
9631
9972
  }
9632
9973
  };
9633
9974
 
9634
- // src/config/lock.ts
9635
- var LOCK_STALE_MS = 1e4;
9636
- var LOCK_POLL_MS = 50;
9637
- var LOCK_MAX_WAIT_MS = 5e3;
9638
- function isEexist(err) {
9639
- if (err instanceof Error && "code" in err)
9640
- return err.code === "EEXIST";
9641
- if (err instanceof Error) return err.message.includes("EEXIST");
9642
- return false;
9643
- }
9644
- async function removeStaleLock(fs, lockPath) {
9645
- try {
9646
- const s = await fs.stat(lockPath);
9647
- if (Date.now() - s.mtimeMs > LOCK_STALE_MS) {
9648
- try {
9649
- await fs.rmdir(lockPath);
9650
- } catch {
9651
- }
9652
- return true;
9653
- }
9654
- } catch {
9655
- }
9656
- return false;
9657
- }
9658
- async function acquireLock(fs, configPath) {
9659
- const lockPath = `${configPath}.lock`;
9660
- const start = Date.now();
9661
- const parentDir = lockPath.slice(0, lockPath.lastIndexOf("/"));
9662
- if (parentDir) {
9663
- try {
9664
- await fs.mkdir(parentDir);
9665
- } catch {
9666
- }
9667
- }
9668
- while (true) {
9669
- try {
9670
- await fs.mkdirExclusive(lockPath);
9671
- break;
9672
- } catch (err) {
9673
- if (!isEexist(err)) throw err;
9674
- await removeStaleLock(fs, lockPath);
9675
- }
9676
- if (Date.now() - start > LOCK_MAX_WAIT_MS) {
9677
- throw new Error(`mcpcat: could not acquire lock ${lockPath} within ${LOCK_MAX_WAIT_MS}ms`);
9678
- }
9679
- await new Promise((r) => setTimeout(r, LOCK_POLL_MS));
9680
- }
9681
- let released = false;
9682
- return async () => {
9683
- if (released) return;
9684
- released = true;
9685
- try {
9686
- await fs.rmdir(lockPath);
9687
- } catch {
9688
- }
9689
- };
9690
- }
9691
-
9692
9975
  // src/config/edit.ts
9976
+ init_lock();
9693
9977
  function isRecord2(value) {
9694
9978
  return typeof value === "object" && value !== null && !Array.isArray(value);
9695
9979
  }
@@ -11914,7 +12198,7 @@ function capOutput(value, limit) {
11914
12198
  ${value.slice(value.length - half)}`;
11915
12199
  }
11916
12200
  var inflightProcs = /* @__PURE__ */ new Set();
11917
- async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd) {
12201
+ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs, maxOutput, cwd, signal) {
11918
12202
  let proc;
11919
12203
  try {
11920
12204
  proc = await platform2.spawn({
@@ -11953,23 +12237,41 @@ async function runCommand(platform2, cmdPath, argv, childEnv, stdin, timeoutMs,
11953
12237
  const timer = new Promise(
11954
12238
  (resolve) => setTimeout(() => resolve("timeout"), timeoutMs)
11955
12239
  );
12240
+ const abortPromise = signal ? new Promise((resolve) => {
12241
+ if (signal.aborted) {
12242
+ resolve("timeout");
12243
+ return;
12244
+ }
12245
+ signal.addEventListener("abort", () => resolve("timeout"), { once: true });
12246
+ }) : null;
11956
12247
  const work = Promise.all([
11957
12248
  readStream3(proc.stdout, stdoutChunks),
11958
12249
  readStream3(proc.stderr, stderrChunks),
11959
12250
  proc.wait()
11960
12251
  ]);
11961
- const result = await Promise.race([work, timer]);
12252
+ const racers = [
12253
+ work,
12254
+ timer
12255
+ ];
12256
+ if (abortPromise !== null) racers.push(abortPromise);
12257
+ const result = await Promise.race(racers);
11962
12258
  if (result === "timeout") {
11963
- proc.kill("SIGTERM");
11964
- await new Promise((resolve) => setTimeout(resolve, 5e3));
11965
- try {
11966
- proc.kill("SIGKILL");
11967
- } catch {
12259
+ await proc.kill("SIGTERM");
12260
+ if (!signal?.aborted) {
12261
+ await new Promise((resolve) => setTimeout(resolve, 5e3));
12262
+ try {
12263
+ await proc.kill("SIGKILL");
12264
+ } catch {
12265
+ }
11968
12266
  }
11969
12267
  inflightProcs.delete(proc);
11970
12268
  return { stdout: "", stderr: "timed out", exitCode: 124 };
11971
12269
  }
11972
12270
  inflightProcs.delete(proc);
12271
+ try {
12272
+ await proc.kill("SIGTERM");
12273
+ } catch {
12274
+ }
11973
12275
  const [, , exitResult] = result;
11974
12276
  const dec = new TextDecoder();
11975
12277
  return {
@@ -11988,25 +12290,31 @@ function concat(chunks) {
11988
12290
  }
11989
12291
  return out;
11990
12292
  }
12293
+ var KILL_GRACE_MS = 2e3;
11991
12294
  async function killInflight() {
11992
- for (const proc of inflightProcs) {
11993
- try {
11994
- proc.kill("SIGTERM");
11995
- } catch {
11996
- }
11997
- }
11998
- if (inflightProcs.size > 0) {
11999
- await new Promise((resolve) => setTimeout(resolve, 5e3));
12000
- for (const proc of inflightProcs) {
12295
+ const procs = [...inflightProcs];
12296
+ if (procs.length === 0) return;
12297
+ await Promise.all(
12298
+ procs.map(async (proc) => {
12001
12299
  try {
12002
- proc.kill("SIGKILL");
12300
+ await proc.kill("SIGTERM");
12003
12301
  } catch {
12004
12302
  }
12005
- }
12006
- }
12303
+ const exited = await Promise.race([
12304
+ proc.wait().then(() => true),
12305
+ new Promise((r) => setTimeout(() => r(false), KILL_GRACE_MS))
12306
+ ]);
12307
+ if (!exited) {
12308
+ try {
12309
+ await proc.kill("SIGKILL");
12310
+ } catch {
12311
+ }
12312
+ }
12313
+ })
12314
+ );
12007
12315
  inflightProcs.clear();
12008
12316
  }
12009
- async function runHelpForCli(platform2, filePath, childEnv, cwd) {
12317
+ async function runHelpForCli(platform2, filePath, childEnv, cwd, signal) {
12010
12318
  const dashed = await runCommand(
12011
12319
  platform2,
12012
12320
  filePath,
@@ -12015,9 +12323,11 @@ async function runHelpForCli(platform2, filePath, childEnv, cwd) {
12015
12323
  void 0,
12016
12324
  1e4,
12017
12325
  MAX_OUTPUT_DEFAULT,
12018
- cwd
12326
+ cwd,
12327
+ signal
12019
12328
  );
12020
12329
  if (dashed.exitCode === 0 && dashed.stdout.trim()) return dashed.stdout;
12330
+ if (signal?.aborted) return "";
12021
12331
  const plain = await runCommand(
12022
12332
  platform2,
12023
12333
  filePath,
@@ -12026,7 +12336,8 @@ async function runHelpForCli(platform2, filePath, childEnv, cwd) {
12026
12336
  void 0,
12027
12337
  1e4,
12028
12338
  MAX_OUTPUT_DEFAULT,
12029
- cwd
12339
+ cwd,
12340
+ signal
12030
12341
  );
12031
12342
  if (plain.exitCode === 0 && plain.stdout.trim()) return plain.stdout;
12032
12343
  return dashed.stdout.trim() ? dashed.stdout : "";
@@ -12053,7 +12364,7 @@ async function expandGroupCommands(platform2, filePath, commands, childEnv, cwd)
12053
12364
  }
12054
12365
  return current;
12055
12366
  }
12056
- async function discoverCli(platform2, filePath, explicitName, childEnv, cwd) {
12367
+ async function discoverCli(platform2, filePath, explicitName, childEnv, cwd, signal) {
12057
12368
  const mcp = await runCommand(
12058
12369
  platform2,
12059
12370
  filePath,
@@ -12062,10 +12373,11 @@ async function discoverCli(platform2, filePath, explicitName, childEnv, cwd) {
12062
12373
  void 0,
12063
12374
  1e4,
12064
12375
  MAX_OUTPUT_DEFAULT,
12065
- cwd
12376
+ cwd,
12377
+ signal
12066
12378
  );
12067
12379
  const override = mcp.exitCode === 0 ? parseMcpOverride(mcp.stdout) : null;
12068
- const helpText2 = override ? "" : await runHelpForCli(platform2, filePath, childEnv, cwd);
12380
+ const helpText2 = override || signal?.aborted ? "" : await runHelpForCli(platform2, filePath, childEnv, cwd, signal);
12069
12381
  if (!override && !helpText2.trim()) {
12070
12382
  throw new Error(`${filePath} did not print help or --mcp descriptor`);
12071
12383
  }
@@ -12185,6 +12497,32 @@ function createToolExecutor(platform2, clis, allTools, childEnv, options, serveC
12185
12497
  }
12186
12498
  return { invoke, rpcTools };
12187
12499
  }
12500
+ async function discoverWithSignal(platform2, commands, childEnv, cwd) {
12501
+ const clis = [];
12502
+ let earlyShutdown = false;
12503
+ let inflightDone;
12504
+ const earlyAbort = new AbortController();
12505
+ const onShutdown = () => {
12506
+ earlyShutdown = true;
12507
+ earlyAbort.abort();
12508
+ inflightDone = killInflight();
12509
+ };
12510
+ platform2.onSignal?.("SIGTERM", onShutdown);
12511
+ platform2.onSignal?.("SIGINT", onShutdown);
12512
+ for (const cmd of commands) {
12513
+ try {
12514
+ const cli = await discoverCli(platform2, cmd.path, cmd.name, childEnv, cwd, earlyAbort.signal);
12515
+ clis.push(cli);
12516
+ } catch (err) {
12517
+ if (earlyShutdown) return { exitCode: 143, inflightDone };
12518
+ await platform2.write(2, `mcpcat serve: ${err.message}
12519
+ `);
12520
+ return { exitCode: 2 };
12521
+ }
12522
+ }
12523
+ if (earlyShutdown) return { exitCode: 143, inflightDone };
12524
+ return { clis };
12525
+ }
12188
12526
  async function runServe(platform2, options, version) {
12189
12527
  let resolvedBearer;
12190
12528
  let generatedBearer = false;
@@ -12228,17 +12566,17 @@ async function runServe(platform2, options, version) {
12228
12566
  }
12229
12567
  const serveCwd = options.cwd ?? platform2.cwd;
12230
12568
  const childEnv = buildChildEnv(platform2, options.envAllow);
12231
- const clis = [];
12232
- for (const cmd of options.commands) {
12233
- try {
12234
- const cli = await discoverCli(platform2, cmd.path, cmd.name, childEnv, serveCwd);
12235
- clis.push(cli);
12236
- } catch (err) {
12237
- await platform2.write(2, `mcpcat serve: ${err.message}
12238
- `);
12239
- return 2;
12569
+ const discovery = await discoverWithSignal(platform2, options.commands, childEnv, serveCwd);
12570
+ if ("exitCode" in discovery) {
12571
+ if (discovery.inflightDone !== void 0) {
12572
+ try {
12573
+ await discovery.inflightDone;
12574
+ } catch {
12575
+ }
12240
12576
  }
12577
+ return discovery.exitCode;
12241
12578
  }
12579
+ const { clis } = discovery;
12242
12580
  const allTools = clis.flatMap((cli) => buildTools(cli.name, cli.commands));
12243
12581
  for (const spec of options.toolTemplates) {
12244
12582
  const tool = parseToolTemplate(spec);
@@ -12464,6 +12802,7 @@ async function runProxyHttp(platform2, options, proxy, resolvedBearer, generated
12464
12802
  if (platform2.onSignal) {
12465
12803
  platform2.onSignal("SIGINT", shutdown);
12466
12804
  platform2.onSignal("SIGTERM", shutdown);
12805
+ platform2.onSignal("SIGHUP", shutdown);
12467
12806
  }
12468
12807
  const handler = (request) => handleProxyMcpRequest(
12469
12808
  request,
@@ -12623,11 +12962,12 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
12623
12962
  await platform2.write(2, `mcpcat serve: listening on ${listenUrl}
12624
12963
  `);
12625
12964
  let shutdownRequested = false;
12965
+ let inflightDone;
12626
12966
  const shutdown = () => {
12627
12967
  if (shutdownRequested) return;
12628
12968
  shutdownRequested = true;
12629
12969
  listener.close();
12630
- void killInflight();
12970
+ inflightDone = killInflight();
12631
12971
  if (tokenFilePath) {
12632
12972
  platform2.fs.unlink?.(tokenFilePath).catch(() => {
12633
12973
  });
@@ -12636,6 +12976,7 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
12636
12976
  if (platform2.onSignal) {
12637
12977
  platform2.onSignal("SIGINT", shutdown);
12638
12978
  platform2.onSignal("SIGTERM", shutdown);
12979
+ platform2.onSignal("SIGHUP", shutdown);
12639
12980
  }
12640
12981
  const handler = (request) => handleMcpRequest(
12641
12982
  request,
@@ -12663,6 +13004,12 @@ async function runHttpServer(platform2, options, tools, call, serverName, versio
12663
13004
  } catch {
12664
13005
  if (!shutdownRequested) throw new Error("listener closed unexpectedly");
12665
13006
  }
13007
+ if (inflightDone !== void 0) {
13008
+ try {
13009
+ await inflightDone;
13010
+ } catch {
13011
+ }
13012
+ }
12666
13013
  return 0;
12667
13014
  }
12668
13015
  async function handleMcpRequest(request, tools, call, serverName, version, serverOrigins, allowedOrigins, allowedHosts, resolvedBearer) {
@@ -12934,124 +13281,6 @@ async function signIn(options) {
12934
13281
  }
12935
13282
  }
12936
13283
 
12937
- // src/auth/token-source.ts
12938
- function mcpNamespace(server) {
12939
- return `mcp__${server.replace(/-/g, "_")}`;
12940
- }
12941
- function storeKey(name, serverUrl) {
12942
- const ns = mcpNamespace(name);
12943
- const url = String(new URL(serverUrl));
12944
- return `${ns}|${url}`;
12945
- }
12946
- function isKernel(platform2) {
12947
- return platform2.kind === "kernel";
12948
- }
12949
-
12950
- // src/auth/pi-store.ts
12951
- var AUTH_FILE = "mcp-auth.json";
12952
- var FILE_MODE = 384;
12953
- function parseStates(raw) {
12954
- if (!raw?.trim()) return {};
12955
- const parsed = JSON.parse(raw);
12956
- return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
12957
- }
12958
- function serializeStates(states) {
12959
- return `${JSON.stringify(states, null, 2)}
12960
- `;
12961
- }
12962
- function legacyKey(serverUrl) {
12963
- return String(new URL(serverUrl));
12964
- }
12965
- var PiFileTokenSource = class {
12966
- platform;
12967
- authPath;
12968
- dirPath;
12969
- constructor(platform2) {
12970
- this.platform = platform2;
12971
- this.dirPath = userConfigDir(platform2);
12972
- this.authPath = `${this.dirPath}/${AUTH_FILE}`;
12973
- }
12974
- get path() {
12975
- return this.authPath;
12976
- }
12977
- async getToken(name, serverUrl) {
12978
- const state = await this.load(name, serverUrl);
12979
- if (!state?.tokens?.access_token) return void 0;
12980
- return {
12981
- accessToken: state.tokens.access_token,
12982
- expiresAt: state.tokensExpireAt
12983
- };
12984
- }
12985
- async load(name, serverUrl) {
12986
- const key = storeKey(name, serverUrl);
12987
- const legacy = legacyKey(serverUrl);
12988
- const release = await this.acquireLock();
12989
- try {
12990
- const raw = await this.readRaw();
12991
- const states = parseStates(raw);
12992
- if (states[key]) return states[key];
12993
- if (states[legacy]) {
12994
- states[key] = states[legacy];
12995
- delete states[legacy];
12996
- await this.writeStates(states);
12997
- return states[key];
12998
- }
12999
- return void 0;
13000
- } finally {
13001
- await release();
13002
- }
13003
- }
13004
- async save(name, serverUrl, state) {
13005
- const key = storeKey(name, serverUrl);
13006
- const release = await this.acquireLock();
13007
- try {
13008
- const raw = await this.readRaw();
13009
- const states = parseStates(raw);
13010
- states[key] = state;
13011
- await this.writeStates(states);
13012
- } finally {
13013
- await release();
13014
- }
13015
- }
13016
- async remove(name, serverUrl) {
13017
- const key = storeKey(name, serverUrl);
13018
- const legacy = legacyKey(serverUrl);
13019
- const release = await this.acquireLock();
13020
- try {
13021
- const raw = await this.readRaw();
13022
- const states = parseStates(raw);
13023
- const stored = key in states ? key : legacy in states ? legacy : void 0;
13024
- if (!stored) return false;
13025
- delete states[stored];
13026
- await this.writeStates(states);
13027
- return true;
13028
- } finally {
13029
- await release();
13030
- }
13031
- }
13032
- async acquireLock() {
13033
- await this.ensureDir();
13034
- return acquireLock(this.platform.fs, this.authPath);
13035
- }
13036
- async ensureDir() {
13037
- try {
13038
- await this.platform.fs.mkdir(this.dirPath);
13039
- } catch {
13040
- }
13041
- }
13042
- async readRaw() {
13043
- try {
13044
- const data = await this.platform.fs.readFile(this.authPath);
13045
- return new TextDecoder().decode(data);
13046
- } catch {
13047
- return void 0;
13048
- }
13049
- }
13050
- async writeStates(states) {
13051
- await this.platform.fs.writeFile(this.authPath, serializeStates(states), { mode: FILE_MODE });
13052
- }
13053
- };
13054
-
13055
13284
  // src/cli/auth-verbs.ts
13056
13285
  var resolvedSource;
13057
13286
  async function createTokenSource(platform2) {
@@ -14745,6 +14974,17 @@ async function runCall(platform2, conn, toolName, dataArg, toolArgs, opts) {
14745
14974
  return EXIT_USAGE;
14746
14975
  }
14747
14976
  fin = mergeArgs(base, c.value);
14977
+ } else if (!dataArg && !opts.noValidate) {
14978
+ const tools = await conn.listTools();
14979
+ const tool = tools.find((t) => t.name === toolName);
14980
+ const schema = tool?.inputSchema;
14981
+ const required = Array.isArray(schema?.required) ? schema.required : [];
14982
+ for (const r of required) {
14983
+ if (!Object.hasOwn(base, r)) {
14984
+ await writeErr(platform2, opts.json ?? false, "usage", `missing required flag --${r}`);
14985
+ return EXIT_USAGE;
14986
+ }
14987
+ }
14748
14988
  }
14749
14989
  return renderCallResult(
14750
14990
  platform2,
@@ -14962,7 +15202,10 @@ async function probeServer(_name, config, platform2) {
14962
15202
  const opts = { version: "probe" };
14963
15203
  if ("url" in config && config.url) {
14964
15204
  opts.url = config.url;
14965
- if ("headers" in config) opts.headers = config.headers;
15205
+ if ("headers" in config) {
15206
+ const expanded = expandHeaders(config.headers, platform2.env);
15207
+ if (expanded) opts.headers = expanded;
15208
+ }
14966
15209
  } else if ("command" in config && config.command) {
14967
15210
  opts.command = config.command;
14968
15211
  if ("args" in config) opts.args = config.args;
@@ -15096,6 +15339,10 @@ async function dispatchMultiTarget(platform2, parsed, version) {
15096
15339
  } catch {
15097
15340
  }
15098
15341
  }
15342
+ try {
15343
+ await Promise.race([killAllStdio(), new Promise((r) => setTimeout(r, 3e3))]);
15344
+ } catch {
15345
+ }
15099
15346
  platform2.exit(exitCode);
15100
15347
  }
15101
15348
  platform2.onSignal?.("SIGTERM", () => void killTreeAndExit(143));
@@ -15324,11 +15571,25 @@ function classifyError(err) {
15324
15571
  }
15325
15572
  async function resolveAuthProvider(platform2, hasAuthHeader, url, target, config) {
15326
15573
  if (hasAuthHeader || !url) return void 0;
15327
- const source = await createTokenSource(platform2);
15574
+ const piSource = new PiFileTokenSource(platform2);
15328
15575
  const entry = config.entry(target);
15329
15576
  const oauth = entry && "url" in entry.config ? entry.config.oauth : void 0;
15330
15577
  const name = entry ? target : `url:${new URL(url).origin}${new URL(url).pathname}`;
15331
- return createMcpAuthProvider({ name, serverUrl: url, source, oauth, platform: platform2 });
15578
+ const provider = createMcpAuthProvider({
15579
+ name,
15580
+ serverUrl: url,
15581
+ source: piSource,
15582
+ oauth,
15583
+ platform: platform2
15584
+ });
15585
+ const credentialSecrets = [];
15586
+ const state = await piSource.loadWithoutLock(name, url);
15587
+ if (state?.tokens?.access_token) credentialSecrets.push(state.tokens.access_token);
15588
+ if (state?.tokens?.refresh_token) credentialSecrets.push(state.tokens.refresh_token);
15589
+ if (state?.clientInformation && "client_secret" in state.clientInformation && state.clientInformation.client_secret) {
15590
+ credentialSecrets.push(state.clientInformation.client_secret);
15591
+ }
15592
+ return { provider, credentialSecrets };
15332
15593
  }
15333
15594
  function classifyConnectionError(err, target, interrupted) {
15334
15595
  if (err instanceof McpAuthError || err instanceof AuthStepUpError || err instanceof JerkSignInRequiredError) {
@@ -15374,7 +15635,7 @@ async function handleInputRequired(platform2, conn, err, respondData, json) {
15374
15635
  `);
15375
15636
  return EXIT_INPUT_REQUIRED;
15376
15637
  }
15377
- const isTty = platform2.isatty(0);
15638
+ const isTty = platform2.isatty(0) && platform2.isatty(2);
15378
15639
  const elicitResult = await handleElicitation(platform2, inputReq, isTty, respondData);
15379
15640
  if ("exitCode" in elicitResult) {
15380
15641
  await platform2.write(2, `${err.requestJson}
@@ -15420,6 +15681,10 @@ async function runClientVerb(platform2, version, parsed) {
15420
15681
  } catch {
15421
15682
  }
15422
15683
  }
15684
+ try {
15685
+ await Promise.race([killAllStdio(), new Promise((r) => setTimeout(r, 3e3))]);
15686
+ } catch {
15687
+ }
15423
15688
  platform2.exit(exitCode);
15424
15689
  }
15425
15690
  platform2.onSignal?.("SIGINT", () => {
@@ -15467,13 +15732,20 @@ async function runClientVerb(platform2, version, parsed) {
15467
15732
  };
15468
15733
  const mergedHeaders = { ...configHeaders, ...expanded };
15469
15734
  const hasAuthHeader = "Authorization" in mergedHeaders;
15470
- const authProvider = await resolveAuthProvider(
15735
+ const authResolved = await resolveAuthProvider(
15471
15736
  platform2,
15472
15737
  hasAuthHeader,
15473
15738
  resolved.url,
15474
15739
  target,
15475
15740
  config
15476
15741
  );
15742
+ const authProvider = authResolved?.provider;
15743
+ if (authResolved?.credentialSecrets) {
15744
+ for (const s of authResolved.credentialSecrets) {
15745
+ allSecrets.add(s);
15746
+ verbose.secrets.add(s);
15747
+ }
15748
+ }
15477
15749
  const roots = buildRoots(parsed.roots, !!resolved.command, platform2.cwd);
15478
15750
  let respondData;
15479
15751
  if (parsed.respondArg) {
@@ -15570,7 +15842,18 @@ function isSpawnNotFound(err) {
15570
15842
  // src/platform/host.ts
15571
15843
  import { spawn as cpSpawn } from "node:child_process";
15572
15844
  import { constants } from "node:fs";
15573
- import { access, mkdir, readFile as readFile3, rename, rmdir, stat, unlink, writeFile } from "node:fs/promises";
15845
+ import {
15846
+ access,
15847
+ chmod,
15848
+ mkdir,
15849
+ open,
15850
+ readFile as readFile3,
15851
+ rename,
15852
+ rmdir,
15853
+ stat,
15854
+ unlink,
15855
+ writeFile
15856
+ } from "node:fs/promises";
15574
15857
  import { createServer as createServer2 } from "node:net";
15575
15858
  import { Readable, Writable } from "node:stream";
15576
15859
  import * as tty from "node:tty";
@@ -15672,6 +15955,13 @@ var hostFs = {
15672
15955
  },
15673
15956
  async unlink(path) {
15674
15957
  await unlink(path);
15958
+ },
15959
+ async createExclusive(path) {
15960
+ const fh = await open(path, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY);
15961
+ await fh.close();
15962
+ },
15963
+ async chmod(path, mode) {
15964
+ await chmod(path, mode);
15675
15965
  }
15676
15966
  };
15677
15967
  function createStdinStream() {
@@ -15792,5 +16082,5 @@ try {
15792
16082
  });
15793
16083
  } catch {
15794
16084
  }
15795
- var code = await run(platform, "0.14.1", args);
16085
+ var code = await run(platform, "0.14.3", args);
15796
16086
  process.exit(code);