@snack-kit/porygon 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -630,6 +630,32 @@ npm run playground # 启动 Playground
630
630
 
631
631
  ## Changelog
632
632
 
633
+ ### v0.7.0
634
+
635
+ #### 新特性
636
+
637
+ - **`InteractiveSession` 多轮对话封装** — 新增 `InteractiveSession` 类,封装 per-turn spawn + `--resume` 模式,提供透明的多轮对话体验。通过 `porygon.session()` 创建,调用 `session.send(prompt)` 自动管理 sessionId 续接
638
+ - **`EphemeralProcess` 超时错误明确化** — 进程超时终止后抛出明确的 `Process timed out after ${timeoutMs}ms` 错误,替代之前模糊的退出码错误信息
639
+
640
+ #### 改进
641
+
642
+ - `EphemeralProcess` 内部新增 `timedOut` 状态标记,区分正常退出与超时终止场景
643
+
644
+ ---
645
+
646
+ ### v0.6.0
647
+
648
+ #### 改进
649
+
650
+ - **Windows 跨平台兼容** — 使用 `cross-spawn` 替换原生 `child_process.spawn`,解决 Windows 上因 PATH 解析、PATHEXT 扩展名(`.exe`、`.cmd` 等)导致的 `ENOENT` 错误。所有进程启动(`EphemeralProcess`、`PersistentProcess`)均已适配
651
+ - **`isAvailable()` Windows 适配** — Claude adapter 的 CLI 存在性检测在 Windows 上使用 `where` 命令替代 `which`
652
+
653
+ #### 新增依赖
654
+
655
+ - `cross-spawn` — Node.js 生态标准的跨平台进程启动库,正确处理 Windows 上的命令解析、参数转义和 PATHEXT 查找
656
+
657
+ ---
658
+
633
659
  ### v0.5.0
634
660
 
635
661
  #### 新特性
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -278,13 +288,14 @@ var InterceptorManager = class {
278
288
  };
279
289
 
280
290
  // src/process/process-handle.ts
281
- var import_node_child_process = require("child_process");
291
+ var import_cross_spawn = __toESM(require("cross-spawn"), 1);
282
292
  var import_node_events = require("events");
283
293
  var import_node_readline = require("readline");
284
294
  var GRACE_PERIOD_MS = 5e3;
285
295
  var EphemeralProcess = class {
286
296
  childProcess = null;
287
297
  aborted = false;
298
+ timedOut = false;
288
299
  /**
289
300
  * 执行命令并收集输出。支持 AbortController 进行取消操作。
290
301
  * @param options 进程启动选项
@@ -298,7 +309,7 @@ var EphemeralProcess = class {
298
309
  return;
299
310
  }
300
311
  this.aborted = false;
301
- const child = (0, import_node_child_process.spawn)(options.command, options.args, {
312
+ const child = (0, import_cross_spawn.default)(options.command, options.args, {
302
313
  cwd: options.cwd,
303
314
  env: options.env ? { ...process.env, ...options.env } : void 0,
304
315
  stdio: ["pipe", "pipe", "pipe"]
@@ -353,8 +364,9 @@ var EphemeralProcess = class {
353
364
  throw new Error("Process aborted before start");
354
365
  }
355
366
  this.aborted = false;
367
+ this.timedOut = false;
356
368
  const useStdin = options.stdinData !== void 0;
357
- const child = (0, import_node_child_process.spawn)(options.command, options.args, {
369
+ const child = (0, import_cross_spawn.default)(options.command, options.args, {
358
370
  cwd: options.cwd,
359
371
  env: options.env ?? void 0,
360
372
  stdio: [useStdin ? "pipe" : "ignore", "pipe", "pipe"]
@@ -368,6 +380,7 @@ var EphemeralProcess = class {
368
380
  let timeoutTimer;
369
381
  if (options.timeoutMs !== void 0 && options.timeoutMs > 0) {
370
382
  timeoutTimer = setTimeout(() => {
383
+ this.timedOut = true;
371
384
  this.terminate();
372
385
  }, options.timeoutMs);
373
386
  }
@@ -400,6 +413,9 @@ var EphemeralProcess = class {
400
413
  stderr || `Process exited with code ${exitCode}`
401
414
  );
402
415
  }
416
+ if (this.timedOut) {
417
+ throw new Error(`Process timed out after ${options.timeoutMs}ms`);
418
+ }
403
419
  } finally {
404
420
  if (timeoutTimer) clearTimeout(timeoutTimer);
405
421
  abortSignal?.removeEventListener("abort", onAbort);
@@ -437,7 +453,7 @@ var PersistentProcess = class extends import_node_events.EventEmitter {
437
453
  /** 启动持久进程 */
438
454
  async start() {
439
455
  this.stopped = false;
440
- const child = (0, import_node_child_process.spawn)(this.options.command, this.options.args, {
456
+ const child = (0, import_cross_spawn.default)(this.options.command, this.options.args, {
441
457
  cwd: this.options.cwd,
442
458
  env: this.options.env ? { ...process.env, ...this.options.env } : void 0,
443
459
  stdio: ["pipe", "pipe", "pipe"]
@@ -939,8 +955,9 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
939
955
  async isAvailable() {
940
956
  try {
941
957
  const proc = new EphemeralProcess();
958
+ const findCmd = process.platform === "win32" ? "where" : "which";
942
959
  const result = await proc.execute({
943
- command: "which",
960
+ command: findCmd,
944
961
  args: [this.cliCommand]
945
962
  });
946
963
  return result.exitCode === 0;