@yitom/agy-acp-map 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -300,7 +300,7 @@ Engineering feasibility ≠ legal permission. 即便只用官方 CLI I/O,仍
300
300
 
301
301
  ## ACP V1 vs V2 Draft Specifications / 协议版本说明
302
302
 
303
- - **ACP V1 (Stable)**: Production-grade implementation fully conforming to canonical ACP v1 JSON-RPC specifications. Includes capability purity (extensions encapsulated under `_meta`), deterministic keyset cursor pagination on `session/list`, atomic session deletion, and strict session/resume semantics (`sessionId` + `cwd` required, cwd matching, omitted `additionalDirectories` reset to empty).
303
+ - **ACP V1 (Stable)**: Production-grade implementation fully conforming to canonical ACP v1 JSON-RPC specifications. `initialize` returns a minimal Zed-verified shape (`protocolVersion`, `agentInfo`, `agentCapabilities`, `authMethods: []`; models arrive via `session/new` `configOptions`). Includes deterministic keyset cursor pagination on `session/list`, atomic session deletion, and strict session/resume semantics (`sessionId` + `cwd` required, cwd matching, omitted `additionalDirectories` reset to empty).
304
304
  - **ACP V2 (Draft)**: Experimental v2 draft support built on `@agentclientprotocol/sdk@1.4.0` (`@agentclientprotocol/sdk/experimental/v2`). Conforms to the SDK's schema where `session/prompt` acknowledges prompt acceptance with an immediate `{}` (empty object) response, and subsequent progress is streamed via `session/update` notifications (`state_update: running -> chunks -> state_update: idle`).
305
305
  - **Prompt Validation**: All content blocks (`text`, `resource`, `resource_link`, `image`, `audio`) are validated synchronously before sending ACK, preventing background silent failures.
306
306
 
@@ -311,6 +311,57 @@ Engineering feasibility ≠ legal permission. 即便只用官方 CLI I/O,仍
311
311
  - **Zed / Editor Configuration**: When configuring the bridge in Zed on Windows, point directly to `bun` or `node` with `dist/bin.js` (or a windowless shim) rather than a `.cmd` or `.bat` wrapper. Batch scripts cause `cmd.exe` to flash a console window on launch before passing control to Node/Bun.
312
312
  - **If a custom Zed server still flashes**: use the native wrapper as the custom command itself, for example `command: "<repo>\\dist\\agy-headless.exe"` with args `["<path-to-bun-or-node>", "<repo>\\src\\sdk-server.ts"]` (or `dist\\bin.js`). You can also set `AGY_HEADLESS_LAUNCHER` to an absolute wrapper path. Packaging the bridge on npm improves distribution, but npm packaging alone does not change Windows process creation flags.
313
313
 
314
+ ## Zed via npm (global install) / Zed 全局安装用法
315
+
316
+ No Bun / TypeScript needed at runtime — the published package ships compiled
317
+ `dist/` artifacts (`bin.js` for Node, `agy-headless.exe`, plus the optional
318
+ single-file `agy-acp-win-x64.exe`). A **global** install is recommended so Zed
319
+ gets a stable absolute path (repo moves would break a local path):
320
+
321
+ ```powershell
322
+ npm install -g @yitom/agy-acp-map
323
+ npm root -g # e.g. C:\Users\<you>\AppData\Roaming\npm\node_modules
324
+ ```
325
+
326
+ Recommended Zed `agent_servers` entry (zero console flash: GUI shim starts
327
+ plain `node`, only `node` is required on the machine):
328
+
329
+ ```jsonc
330
+ "agy-acp-map-local": {
331
+ "type": "custom",
332
+ "command": "C:\\Users\\<you>\\AppData\\Roaming\\npm\\node_modules\\@yitom\\agy-acp-map\\dist\\agy-headless.exe",
333
+ "args": ["node", "C:\\Users\\<you>\\AppData\\Roaming\\npm\\node_modules\\@yitom\\agy-acp-map\\dist\\bin.js"],
334
+ "env": {}
335
+ }
336
+ ```
337
+
338
+ Fallback without the shim (works, but `node.exe` flashes one console frame on
339
+ launch because Zed spawns agents without `CREATE_NO_WINDOW`):
340
+
341
+ ```jsonc
342
+ "agy-acp-map-local": {
343
+ "type": "custom",
344
+ "command": "node",
345
+ "args": ["C:\\Users\\<you>\\AppData\\Roaming\\npm\\node_modules\\@yitom\\agy-acp-map\\dist\\bin.js"],
346
+ "env": {}
347
+ }
348
+ ```
349
+
350
+ Do NOT point Zed at the `agy-acp` / `agy-acp.cmd` global bin wrappers (extra
351
+ `cmd.exe` flash), at `src/*.ts` sources (needs Bun, dev only), or at
352
+ `bun`/`node` without an absolute `dist` path. `initialize` intentionally
353
+ returns a minimal response (`protocolVersion`, `agentInfo`,
354
+ `agentCapabilities`, `authMethods: []`); models arrive via `session/new`
355
+ `configOptions`, so the Zed model picker keeps working.
356
+
357
+ Troubleshooting: the bridge hides nothing from disk — append-only file log at
358
+ `%TEMP%\agy-acp.log` (override with `AGY_ACP_LOG`; ~1MB rotation). If Zed says
359
+ `Server exited with status exit code: 0` right after launch, check the tail of
360
+ that file: `START` with no following `V1 initialize called` means Zed never
361
+ sent bytes (spawn/config issue); `V1 initialize called` followed by
362
+ `stdin END` means Zed rejected the handshake (capture the exchange and compare
363
+ against a known-good agent such as `opencode acp`).
364
+
314
365
  ## Bun + TypeScript / Windows
315
366
 
316
367
  - Runtime is **Bun** (not Node). Entry: `bun src/server.ts` (or `bun run start`).
@@ -0,0 +1,4 @@
1
+ [diffend] Oversized file quarantined before diffing.
2
+ name: package/dist/agy-acp-win-x64.exe
3
+ size: 86637568 bytes
4
+ sha256: a382550f80df362aea3dc5491aeeb3c12cc3a23dbd2ec4e24e3e93740d7b2352
Binary file
package/dist/bin.js CHANGED
@@ -9302,8 +9302,8 @@ var legacyClientNotificationMethods = new Set([
9302
9302
 
9303
9303
  // src/core/session-core.ts
9304
9304
  import { randomUUID as randomUUID3 } from "node:crypto";
9305
- import * as fs8 from "node:fs";
9306
- import path9 from "node:path";
9305
+ import * as fs9 from "node:fs";
9306
+ import path10 from "node:path";
9307
9307
  // node_modules/@agentclientprotocol/sdk/dist/acp.js
9308
9308
  function emptyObjectResponse2(response) {
9309
9309
  return response ?? {};
@@ -11747,8 +11747,10 @@ function isAgyExecutable(bin) {
11747
11747
  }
11748
11748
  function findHeadlessLauncher() {
11749
11749
  const moduleDir = import.meta.dir ?? path5.dirname(process.argv[1] ?? "");
11750
+ const execDir = path5.dirname(process.execPath ?? "");
11750
11751
  const candidates = [
11751
11752
  process.env.AGY_HEADLESS_LAUNCHER,
11753
+ execDir ? path5.join(execDir, "agy-headless.exe") : undefined,
11752
11754
  path5.resolve(moduleDir, "..", "..", "dist", "agy-headless.exe"),
11753
11755
  path5.resolve(moduleDir, "agy-headless.exe"),
11754
11756
  path5.resolve(process.cwd(), "dist", "agy-headless.exe")
@@ -12486,7 +12488,7 @@ class SessionHistoryStore {
12486
12488
  var AGENT_INFO = {
12487
12489
  name: "agy-acp",
12488
12490
  title: "agy ACP (stream-json)",
12489
- version: "0.1.4"
12491
+ version: "0.1.6"
12490
12492
  };
12491
12493
  var BRIDGE_CAPABILITIES = {
12492
12494
  prompt: true,
@@ -12552,6 +12554,46 @@ class AsyncSerialQueue {
12552
12554
  }
12553
12555
  }
12554
12556
 
12557
+ // src/lib/debug-log.ts
12558
+ import fs8 from "node:fs";
12559
+ import os4 from "node:os";
12560
+ import path9 from "node:path";
12561
+ function resolveLogPath() {
12562
+ const override = process.env.AGY_ACP_LOG;
12563
+ if (override && override !== "undefined" && override !== "null")
12564
+ return override;
12565
+ return path9.join(os4.tmpdir(), "agy-acp.log");
12566
+ }
12567
+ var logPath = null;
12568
+ try {
12569
+ logPath = resolveLogPath();
12570
+ } catch {
12571
+ logPath = null;
12572
+ }
12573
+ function writeLine(line) {
12574
+ if (!logPath)
12575
+ return;
12576
+ try {
12577
+ let truncate = false;
12578
+ try {
12579
+ const st = fs8.statSync(logPath);
12580
+ if (st.size > 1024 * 1024)
12581
+ truncate = true;
12582
+ } catch {}
12583
+ fs8.appendFileSync(logPath, line + `
12584
+ `, "utf8");
12585
+ if (truncate) {
12586
+ try {
12587
+ const text = fs8.readFileSync(logPath, "utf8");
12588
+ fs8.writeFileSync(logPath, text.slice(-512 * 1024), "utf8");
12589
+ } catch {}
12590
+ }
12591
+ } catch {}
12592
+ }
12593
+ function debugLog(msg) {
12594
+ writeLine(`${new Date().toISOString()} pid=${process.pid} ${msg}`);
12595
+ }
12596
+
12555
12597
  // src/core/session-core.ts
12556
12598
  class AgySessionCore {
12557
12599
  sessions = new Map;
@@ -12610,8 +12652,8 @@ class AgySessionCore {
12610
12652
  const rawBin = process.env.AGY_BIN;
12611
12653
  let bin = rawBin && rawBin !== "undefined" && rawBin !== "null" ? rawBin : "agy";
12612
12654
  if (bin === "agy" || bin === "agy.exe") {
12613
- const geminiBin = path9.join(process.env.USERPROFILE || process.env.HOME || "", ".gemini", "bin", process.platform === "win32" ? "agy.exe" : "agy");
12614
- if (fs8.existsSync(geminiBin)) {
12655
+ const geminiBin = path10.join(process.env.USERPROFILE || process.env.HOME || "", ".gemini", "bin", process.platform === "win32" ? "agy.exe" : "agy");
12656
+ if (fs9.existsSync(geminiBin)) {
12615
12657
  bin = geminiBin;
12616
12658
  }
12617
12659
  }
@@ -12746,10 +12788,11 @@ class AgySessionCore {
12746
12788
  }
12747
12789
  async createSession(params, protocolVersion = 1) {
12748
12790
  const cwd = params?.cwd;
12749
- if (!cwd || typeof cwd !== "string" || !path9.isAbsolute(cwd)) {
12791
+ debugLog(`createSession v${protocolVersion} cwd=${cwd}`);
12792
+ if (!cwd || typeof cwd !== "string" || !path10.isAbsolute(cwd)) {
12750
12793
  throw new RequestError(-32602, "cwd must be an absolute path");
12751
12794
  }
12752
- if (!fs8.existsSync(cwd) || !fs8.statSync(cwd).isDirectory()) {
12795
+ if (!fs9.existsSync(cwd) || !fs9.statSync(cwd).isDirectory()) {
12753
12796
  throw new RequestError(-32602, `cwd does not exist or is not a directory: ${cwd}`);
12754
12797
  }
12755
12798
  if (params?.additionalDirectories !== undefined) {
@@ -12757,7 +12800,7 @@ class AgySessionCore {
12757
12800
  throw new RequestError(-32602, "additionalDirectories must be an array");
12758
12801
  }
12759
12802
  for (const d of params.additionalDirectories) {
12760
- if (typeof d !== "string" || !path9.isAbsolute(d)) {
12803
+ if (typeof d !== "string" || !path10.isAbsolute(d)) {
12761
12804
  throw new RequestError(-32602, `additionalDirectory must be an absolute path: ${d}`);
12762
12805
  }
12763
12806
  }
@@ -12824,10 +12867,10 @@ class AgySessionCore {
12824
12867
  if (!cwd || typeof cwd !== "string") {
12825
12868
  throw new RequestError(-32602, "cwd is required for session/resume");
12826
12869
  }
12827
- if (!path9.isAbsolute(cwd)) {
12870
+ if (!path10.isAbsolute(cwd)) {
12828
12871
  throw new RequestError(-32602, "cwd must be an absolute path");
12829
12872
  }
12830
- if (!fs8.existsSync(cwd) || !fs8.statSync(cwd).isDirectory()) {
12873
+ if (!fs9.existsSync(cwd) || !fs9.statSync(cwd).isDirectory()) {
12831
12874
  throw new RequestError(-32602, `cwd does not exist or is not a directory: ${cwd}`);
12832
12875
  }
12833
12876
  if (params?.replayFrom !== undefined && params?.replayFrom !== null) {
@@ -12849,7 +12892,7 @@ class AgySessionCore {
12849
12892
  throw new RequestError(-32602, "additionalDirectories must be an array");
12850
12893
  }
12851
12894
  for (const d of params.additionalDirectories) {
12852
- if (typeof d !== "string" || !path9.isAbsolute(d)) {
12895
+ if (typeof d !== "string" || !path10.isAbsolute(d)) {
12853
12896
  throw new RequestError(-32602, `additionalDirectory must be an absolute path: ${d}`);
12854
12897
  }
12855
12898
  }
@@ -12865,7 +12908,7 @@ class AgySessionCore {
12865
12908
  if (recordedVersion !== protocolVersion) {
12866
12909
  throw new RequestError(-32602, `Session ${sessionId} was created with ACP v${recordedVersion} and cannot be resumed with v${protocolVersion}`);
12867
12910
  }
12868
- if (record.cwd && path9.resolve(record.cwd) !== path9.resolve(cwd)) {
12911
+ if (record.cwd && path10.resolve(record.cwd) !== path10.resolve(cwd)) {
12869
12912
  throw new RequestError(-32602, `cwd does not match session cwd: expected ${record.cwd}, got ${cwd}`);
12870
12913
  }
12871
12914
  const richRoots = richRootsFromSession({
@@ -12909,7 +12952,7 @@ class AgySessionCore {
12909
12952
  if (session.protocolVersion !== protocolVersion) {
12910
12953
  throw new RequestError(-32602, `Session ${sessionId} was created with ACP v${session.protocolVersion} and cannot be resumed with v${protocolVersion}`);
12911
12954
  }
12912
- if (path9.resolve(session.cwd) !== path9.resolve(cwd)) {
12955
+ if (path10.resolve(session.cwd) !== path10.resolve(cwd)) {
12913
12956
  throw new RequestError(-32602, `cwd does not match session cwd: expected ${session.cwd}, got ${cwd}`);
12914
12957
  }
12915
12958
  session.additionalDirectories = additionalDirectories;
@@ -12977,7 +13020,7 @@ class AgySessionCore {
12977
13020
  async listSessions(params) {
12978
13021
  const filterCwd = params?.cwd;
12979
13022
  if (filterCwd !== undefined && filterCwd !== null) {
12980
- if (typeof filterCwd !== "string" || !path9.isAbsolute(filterCwd)) {
13023
+ if (typeof filterCwd !== "string" || !path10.isAbsolute(filterCwd)) {
12981
13024
  throw new RequestError(-32602, "cwd must be an absolute path");
12982
13025
  }
12983
13026
  }
@@ -13204,8 +13247,8 @@ class AgySessionCore {
13204
13247
  if (process.env.AGY_ACP_KEEP_STAGING !== "1" && session.stagedFiles.length) {
13205
13248
  for (const f of session.stagedFiles) {
13206
13249
  try {
13207
- if (fs8.existsSync(f))
13208
- fs8.unlinkSync(f);
13250
+ if (fs9.existsSync(f))
13251
+ fs9.unlinkSync(f);
13209
13252
  } catch {}
13210
13253
  }
13211
13254
  session.stagedFiles = [];
@@ -13330,18 +13373,6 @@ class AgySessionCore {
13330
13373
  }
13331
13374
  }
13332
13375
 
13333
- // src/v1/types.ts
13334
- var V1_AGENT_CAPABILITIES = {
13335
- loadSession: true,
13336
- sessionCapabilities: {
13337
- list: {},
13338
- resume: {},
13339
- close: {},
13340
- delete: {},
13341
- additionalDirectories: {}
13342
- }
13343
- };
13344
-
13345
13376
  // src/v1/config.ts
13346
13377
  function buildV1ConfigOptions(discovery, session) {
13347
13378
  const models = catalogChoices(discovery.availableModels, session?.model);
@@ -13379,22 +13410,16 @@ class AgyAcpV1Service {
13379
13410
  this.core = core;
13380
13411
  }
13381
13412
  async initialize() {
13382
- const discovery = await this.core.getDiscovery();
13383
- const configOptions = buildV1ConfigOptions(discovery);
13413
+ debugLog("V1 initialize called");
13414
+ debugLog("V1 initialize called (minimal response)");
13384
13415
  return {
13385
13416
  protocolVersion: 1,
13386
- agentInfo: AGENT_INFO,
13387
- agentCapabilities: V1_AGENT_CAPABILITIES,
13388
- _meta: {
13389
- bridgeCapabilities: {
13390
- ...BRIDGE_CAPABILITIES,
13391
- availableModels: discovery.availableModels,
13392
- availableAgents: discovery.availableAgents,
13393
- configOptions
13394
- },
13395
- availableModels: discovery.availableModels,
13396
- availableAgents: discovery.availableAgents
13397
- }
13417
+ agentInfo: { name: AGENT_INFO.name, version: AGENT_INFO.version },
13418
+ agentCapabilities: {
13419
+ loadSession: true,
13420
+ sessionCapabilities: { close: {}, list: {}, resume: {} }
13421
+ },
13422
+ authMethods: []
13398
13423
  };
13399
13424
  }
13400
13425
  async newSession(params) {
@@ -17752,11 +17777,67 @@ class AgyAcpService {
17752
17777
  }
17753
17778
  }
17754
17779
 
17780
+ // src/lib/debug-log.ts
17781
+ import fs10 from "node:fs";
17782
+ import os5 from "node:os";
17783
+ import path11 from "node:path";
17784
+ function resolveLogPath2() {
17785
+ const override = process.env.AGY_ACP_LOG;
17786
+ if (override && override !== "undefined" && override !== "null")
17787
+ return override;
17788
+ return path11.join(os5.tmpdir(), "agy-acp.log");
17789
+ }
17790
+ var logPath2 = null;
17791
+ try {
17792
+ logPath2 = resolveLogPath2();
17793
+ } catch {
17794
+ logPath2 = null;
17795
+ }
17796
+ function writeLine2(line) {
17797
+ if (!logPath2)
17798
+ return;
17799
+ try {
17800
+ let truncate = false;
17801
+ try {
17802
+ const st = fs10.statSync(logPath2);
17803
+ if (st.size > 1024 * 1024)
17804
+ truncate = true;
17805
+ } catch {}
17806
+ fs10.appendFileSync(logPath2, line + `
17807
+ `, "utf8");
17808
+ if (truncate) {
17809
+ try {
17810
+ const text = fs10.readFileSync(logPath2, "utf8");
17811
+ fs10.writeFileSync(logPath2, text.slice(-512 * 1024), "utf8");
17812
+ } catch {}
17813
+ }
17814
+ } catch {}
17815
+ }
17816
+ function debugLog2(msg) {
17817
+ writeLine2(`${new Date().toISOString()} pid=${process.pid} ${msg}`);
17818
+ }
17819
+ function installFileLogging() {
17820
+ try {
17821
+ process.on("uncaughtException", (err) => {
17822
+ debugLog2(`FATAL uncaughtException: ${err?.stack || err}`);
17823
+ });
17824
+ process.on("unhandledRejection", (reason) => {
17825
+ debugLog2(`FATAL unhandledRejection: ${reason instanceof Error ? reason.stack : reason}`);
17826
+ });
17827
+ process.stdin.on("end", () => debugLog2("stdin END (parent closed pipe)"));
17828
+ process.stdin.on("close", () => debugLog2("stdin CLOSE"));
17829
+ } catch {}
17830
+ return logPath2;
17831
+ }
17832
+
17755
17833
  // src/sdk-server.ts
17756
17834
  hideConsoleWindow();
17835
+ var logPath3 = installFileLogging();
17836
+ debugLog2(`START argv=${JSON.stringify(process.argv.slice(1))} cwd=${process.cwd()} bun=${process.versions?.bun || "no"} node=${process.version} log=${logPath3}`);
17757
17837
  var service = new AgyAcpService;
17758
17838
  var app = createDualAcpApp(service);
17759
17839
  var stream = ndJsonStream2(Writable.toWeb(process.stdout), Readable.toWeb(process.stdin));
17760
17840
  process.stderr.write(`[agy-acp-sdk] Starting official @agentclientprotocol/sdk stdio server...
17761
17841
  `);
17762
17842
  await app.connect(stream);
17843
+ debugLog2("CONNECT-SETUP-DONE (stream established; exit 0 only happens after stdin END/CLOSE)");
package/dist/index.d.ts CHANGED
@@ -17,3 +17,4 @@ export * from './lib/agy-discovery.ts';
17
17
  export * from './lib/session-store.ts';
18
18
  export * from './lib/session-history.ts';
19
19
  export * from './lib/win32-console.ts';
20
+ export * from './lib/debug-log.ts';
package/dist/index.js CHANGED
@@ -17,8 +17,8 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
17
17
 
18
18
  // src/core/session-core.ts
19
19
  import { randomUUID as randomUUID3 } from "node:crypto";
20
- import * as fs8 from "node:fs";
21
- import path9 from "node:path";
20
+ import * as fs9 from "node:fs";
21
+ import path10 from "node:path";
22
22
 
23
23
  // node_modules/@agentclientprotocol/sdk/dist/schema/index.js
24
24
  var AGENT_METHODS = {
@@ -11457,8 +11457,10 @@ function isAgyExecutable(bin) {
11457
11457
  }
11458
11458
  function findHeadlessLauncher() {
11459
11459
  const moduleDir = import.meta.dir ?? path5.dirname(process.argv[1] ?? "");
11460
+ const execDir = path5.dirname(process.execPath ?? "");
11460
11461
  const candidates = [
11461
11462
  process.env.AGY_HEADLESS_LAUNCHER,
11463
+ execDir ? path5.join(execDir, "agy-headless.exe") : undefined,
11462
11464
  path5.resolve(moduleDir, "..", "..", "dist", "agy-headless.exe"),
11463
11465
  path5.resolve(moduleDir, "agy-headless.exe"),
11464
11466
  path5.resolve(process.cwd(), "dist", "agy-headless.exe")
@@ -12273,7 +12275,7 @@ class SessionHistoryStore {
12273
12275
  var AGENT_INFO = {
12274
12276
  name: "agy-acp",
12275
12277
  title: "agy ACP (stream-json)",
12276
- version: "0.1.4"
12278
+ version: "0.1.6"
12277
12279
  };
12278
12280
  var BRIDGE_CAPABILITIES = {
12279
12281
  prompt: true,
@@ -12339,6 +12341,59 @@ class AsyncSerialQueue {
12339
12341
  }
12340
12342
  }
12341
12343
 
12344
+ // src/lib/debug-log.ts
12345
+ import fs8 from "node:fs";
12346
+ import os4 from "node:os";
12347
+ import path9 from "node:path";
12348
+ function resolveLogPath() {
12349
+ const override = process.env.AGY_ACP_LOG;
12350
+ if (override && override !== "undefined" && override !== "null")
12351
+ return override;
12352
+ return path9.join(os4.tmpdir(), "agy-acp.log");
12353
+ }
12354
+ var logPath = null;
12355
+ try {
12356
+ logPath = resolveLogPath();
12357
+ } catch {
12358
+ logPath = null;
12359
+ }
12360
+ function writeLine(line) {
12361
+ if (!logPath)
12362
+ return;
12363
+ try {
12364
+ let truncate = false;
12365
+ try {
12366
+ const st = fs8.statSync(logPath);
12367
+ if (st.size > 1024 * 1024)
12368
+ truncate = true;
12369
+ } catch {}
12370
+ fs8.appendFileSync(logPath, line + `
12371
+ `, "utf8");
12372
+ if (truncate) {
12373
+ try {
12374
+ const text = fs8.readFileSync(logPath, "utf8");
12375
+ fs8.writeFileSync(logPath, text.slice(-512 * 1024), "utf8");
12376
+ } catch {}
12377
+ }
12378
+ } catch {}
12379
+ }
12380
+ function debugLog(msg) {
12381
+ writeLine(`${new Date().toISOString()} pid=${process.pid} ${msg}`);
12382
+ }
12383
+ function installFileLogging() {
12384
+ try {
12385
+ process.on("uncaughtException", (err) => {
12386
+ debugLog(`FATAL uncaughtException: ${err?.stack || err}`);
12387
+ });
12388
+ process.on("unhandledRejection", (reason) => {
12389
+ debugLog(`FATAL unhandledRejection: ${reason instanceof Error ? reason.stack : reason}`);
12390
+ });
12391
+ process.stdin.on("end", () => debugLog("stdin END (parent closed pipe)"));
12392
+ process.stdin.on("close", () => debugLog("stdin CLOSE"));
12393
+ } catch {}
12394
+ return logPath;
12395
+ }
12396
+
12342
12397
  // src/core/session-core.ts
12343
12398
  class AgySessionCore {
12344
12399
  sessions = new Map;
@@ -12397,8 +12452,8 @@ class AgySessionCore {
12397
12452
  const rawBin = process.env.AGY_BIN;
12398
12453
  let bin = rawBin && rawBin !== "undefined" && rawBin !== "null" ? rawBin : "agy";
12399
12454
  if (bin === "agy" || bin === "agy.exe") {
12400
- const geminiBin = path9.join(process.env.USERPROFILE || process.env.HOME || "", ".gemini", "bin", process.platform === "win32" ? "agy.exe" : "agy");
12401
- if (fs8.existsSync(geminiBin)) {
12455
+ const geminiBin = path10.join(process.env.USERPROFILE || process.env.HOME || "", ".gemini", "bin", process.platform === "win32" ? "agy.exe" : "agy");
12456
+ if (fs9.existsSync(geminiBin)) {
12402
12457
  bin = geminiBin;
12403
12458
  }
12404
12459
  }
@@ -12533,10 +12588,11 @@ class AgySessionCore {
12533
12588
  }
12534
12589
  async createSession(params, protocolVersion = 1) {
12535
12590
  const cwd = params?.cwd;
12536
- if (!cwd || typeof cwd !== "string" || !path9.isAbsolute(cwd)) {
12591
+ debugLog(`createSession v${protocolVersion} cwd=${cwd}`);
12592
+ if (!cwd || typeof cwd !== "string" || !path10.isAbsolute(cwd)) {
12537
12593
  throw new RequestError(-32602, "cwd must be an absolute path");
12538
12594
  }
12539
- if (!fs8.existsSync(cwd) || !fs8.statSync(cwd).isDirectory()) {
12595
+ if (!fs9.existsSync(cwd) || !fs9.statSync(cwd).isDirectory()) {
12540
12596
  throw new RequestError(-32602, `cwd does not exist or is not a directory: ${cwd}`);
12541
12597
  }
12542
12598
  if (params?.additionalDirectories !== undefined) {
@@ -12544,7 +12600,7 @@ class AgySessionCore {
12544
12600
  throw new RequestError(-32602, "additionalDirectories must be an array");
12545
12601
  }
12546
12602
  for (const d of params.additionalDirectories) {
12547
- if (typeof d !== "string" || !path9.isAbsolute(d)) {
12603
+ if (typeof d !== "string" || !path10.isAbsolute(d)) {
12548
12604
  throw new RequestError(-32602, `additionalDirectory must be an absolute path: ${d}`);
12549
12605
  }
12550
12606
  }
@@ -12611,10 +12667,10 @@ class AgySessionCore {
12611
12667
  if (!cwd || typeof cwd !== "string") {
12612
12668
  throw new RequestError(-32602, "cwd is required for session/resume");
12613
12669
  }
12614
- if (!path9.isAbsolute(cwd)) {
12670
+ if (!path10.isAbsolute(cwd)) {
12615
12671
  throw new RequestError(-32602, "cwd must be an absolute path");
12616
12672
  }
12617
- if (!fs8.existsSync(cwd) || !fs8.statSync(cwd).isDirectory()) {
12673
+ if (!fs9.existsSync(cwd) || !fs9.statSync(cwd).isDirectory()) {
12618
12674
  throw new RequestError(-32602, `cwd does not exist or is not a directory: ${cwd}`);
12619
12675
  }
12620
12676
  if (params?.replayFrom !== undefined && params?.replayFrom !== null) {
@@ -12636,7 +12692,7 @@ class AgySessionCore {
12636
12692
  throw new RequestError(-32602, "additionalDirectories must be an array");
12637
12693
  }
12638
12694
  for (const d of params.additionalDirectories) {
12639
- if (typeof d !== "string" || !path9.isAbsolute(d)) {
12695
+ if (typeof d !== "string" || !path10.isAbsolute(d)) {
12640
12696
  throw new RequestError(-32602, `additionalDirectory must be an absolute path: ${d}`);
12641
12697
  }
12642
12698
  }
@@ -12652,7 +12708,7 @@ class AgySessionCore {
12652
12708
  if (recordedVersion !== protocolVersion) {
12653
12709
  throw new RequestError(-32602, `Session ${sessionId} was created with ACP v${recordedVersion} and cannot be resumed with v${protocolVersion}`);
12654
12710
  }
12655
- if (record.cwd && path9.resolve(record.cwd) !== path9.resolve(cwd)) {
12711
+ if (record.cwd && path10.resolve(record.cwd) !== path10.resolve(cwd)) {
12656
12712
  throw new RequestError(-32602, `cwd does not match session cwd: expected ${record.cwd}, got ${cwd}`);
12657
12713
  }
12658
12714
  const richRoots = richRootsFromSession({
@@ -12696,7 +12752,7 @@ class AgySessionCore {
12696
12752
  if (session.protocolVersion !== protocolVersion) {
12697
12753
  throw new RequestError(-32602, `Session ${sessionId} was created with ACP v${session.protocolVersion} and cannot be resumed with v${protocolVersion}`);
12698
12754
  }
12699
- if (path9.resolve(session.cwd) !== path9.resolve(cwd)) {
12755
+ if (path10.resolve(session.cwd) !== path10.resolve(cwd)) {
12700
12756
  throw new RequestError(-32602, `cwd does not match session cwd: expected ${session.cwd}, got ${cwd}`);
12701
12757
  }
12702
12758
  session.additionalDirectories = additionalDirectories;
@@ -12764,7 +12820,7 @@ class AgySessionCore {
12764
12820
  async listSessions(params) {
12765
12821
  const filterCwd = params?.cwd;
12766
12822
  if (filterCwd !== undefined && filterCwd !== null) {
12767
- if (typeof filterCwd !== "string" || !path9.isAbsolute(filterCwd)) {
12823
+ if (typeof filterCwd !== "string" || !path10.isAbsolute(filterCwd)) {
12768
12824
  throw new RequestError(-32602, "cwd must be an absolute path");
12769
12825
  }
12770
12826
  }
@@ -12991,8 +13047,8 @@ class AgySessionCore {
12991
13047
  if (process.env.AGY_ACP_KEEP_STAGING !== "1" && session.stagedFiles.length) {
12992
13048
  for (const f of session.stagedFiles) {
12993
13049
  try {
12994
- if (fs8.existsSync(f))
12995
- fs8.unlinkSync(f);
13050
+ if (fs9.existsSync(f))
13051
+ fs9.unlinkSync(f);
12996
13052
  } catch {}
12997
13053
  }
12998
13054
  session.stagedFiles = [];
@@ -13117,18 +13173,6 @@ class AgySessionCore {
13117
13173
  }
13118
13174
  }
13119
13175
 
13120
- // src/v1/types.ts
13121
- var V1_AGENT_CAPABILITIES = {
13122
- loadSession: true,
13123
- sessionCapabilities: {
13124
- list: {},
13125
- resume: {},
13126
- close: {},
13127
- delete: {},
13128
- additionalDirectories: {}
13129
- }
13130
- };
13131
-
13132
13176
  // src/v1/config.ts
13133
13177
  function buildV1ConfigOptions(discovery, session) {
13134
13178
  const models = catalogChoices(discovery.availableModels, session?.model);
@@ -13166,22 +13210,16 @@ class AgyAcpV1Service {
13166
13210
  this.core = core;
13167
13211
  }
13168
13212
  async initialize() {
13169
- const discovery = await this.core.getDiscovery();
13170
- const configOptions = buildV1ConfigOptions(discovery);
13213
+ debugLog("V1 initialize called");
13214
+ debugLog("V1 initialize called (minimal response)");
13171
13215
  return {
13172
13216
  protocolVersion: 1,
13173
- agentInfo: AGENT_INFO,
13174
- agentCapabilities: V1_AGENT_CAPABILITIES,
13175
- _meta: {
13176
- bridgeCapabilities: {
13177
- ...BRIDGE_CAPABILITIES,
13178
- availableModels: discovery.availableModels,
13179
- availableAgents: discovery.availableAgents,
13180
- configOptions
13181
- },
13182
- availableModels: discovery.availableModels,
13183
- availableAgents: discovery.availableAgents
13184
- }
13217
+ agentInfo: { name: AGENT_INFO.name, version: AGENT_INFO.version },
13218
+ agentCapabilities: {
13219
+ loadSession: true,
13220
+ sessionCapabilities: { close: {}, list: {}, resume: {} }
13221
+ },
13222
+ authMethods: []
13185
13223
  };
13186
13224
  }
13187
13225
  async newSession(params) {
@@ -17555,6 +17593,18 @@ __export(exports_v1, {
17555
17593
  buildV1ConfigOptions: () => buildV1ConfigOptions,
17556
17594
  createAcpV1App: () => createAcpV1App
17557
17595
  });
17596
+
17597
+ // src/v1/types.ts
17598
+ var V1_AGENT_CAPABILITIES = {
17599
+ loadSession: true,
17600
+ sessionCapabilities: {
17601
+ list: {},
17602
+ resume: {},
17603
+ close: {},
17604
+ delete: {},
17605
+ additionalDirectories: {}
17606
+ }
17607
+ };
17558
17608
  // src/v2/index.ts
17559
17609
  var exports_v2 = {};
17560
17610
  __export(exports_v2, {
@@ -17620,6 +17670,7 @@ export {
17620
17670
  createAcpV2App,
17621
17671
  createDualAcpApp,
17622
17672
  createMapperState,
17673
+ debugLog,
17623
17674
  decodeFsPath,
17624
17675
  deleteOnCloseEnabled,
17625
17676
  discoverAgyCatalog,
@@ -17633,6 +17684,7 @@ export {
17633
17684
  getCachedDiscovery,
17634
17685
  guessToolKind,
17635
17686
  hideConsoleWindow,
17687
+ installFileLogging,
17636
17688
  isPathAllowed,
17637
17689
  killAgyChild,
17638
17690
  mapAgyEvent,
@@ -0,0 +1,2 @@
1
+ export declare function debugLog(msg: string): void;
2
+ export declare function installFileLogging(): string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yitom/agy-acp-map",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -28,6 +28,7 @@
28
28
  "build": "bun run build:js && bun run build:types && bun run build:headless",
29
29
  "build:headless": "bun scripts/build-headless.ts",
30
30
  "build:js": "bun build src/sdk-server.ts --target node --outfile dist/bin.js && bun build src/index.ts --target node --outfile dist/index.js",
31
+ "build:exe": "bun build src/sdk-server.ts --compile --target=bun-windows-x64 --outfile dist/agy-acp-win-x64.exe",
31
32
  "build:types": "bunx tsc -p tsconfig.build.json",
32
33
  "release:patch": "bun scripts/release.ts",
33
34
  "release:publish": "bun scripts/release.ts --publish",