@snack-kit/porygon 0.2.0 → 0.3.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 +10 -0
- package/dist/index.cjs +85 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -2
- package/dist/index.d.ts +46 -2
- package/dist/index.js +84 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -551,6 +551,16 @@ npm run playground # 启动 Playground
|
|
|
551
551
|
|
|
552
552
|
## Changelog
|
|
553
553
|
|
|
554
|
+
### v0.3.0
|
|
555
|
+
|
|
556
|
+
#### Bug Fixes
|
|
557
|
+
|
|
558
|
+
- **Claude adapter**: 将 prompt 从 CLI 参数 (`-p <prompt>`) 改为通过 stdin 传递 (`--print` + stdin pipe),修复超长 prompt 导致的偶发 403 "Request not allowed" 错误
|
|
559
|
+
|
|
560
|
+
#### 改进
|
|
561
|
+
|
|
562
|
+
- `SpawnOptions` 新增 `stdinData` 字段,`EphemeralProcess.executeStreaming` 支持向子进程 stdin 写入数据
|
|
563
|
+
|
|
554
564
|
### v0.2.0
|
|
555
565
|
|
|
556
566
|
#### 新特性
|
package/dist/index.cjs
CHANGED
|
@@ -28,6 +28,7 @@ __export(index_exports, {
|
|
|
28
28
|
AgentTimeoutError: () => AgentTimeoutError,
|
|
29
29
|
ClaudeAdapter: () => ClaudeAdapter,
|
|
30
30
|
ConfigValidationError: () => ConfigValidationError,
|
|
31
|
+
InteractiveSession: () => InteractiveSession,
|
|
31
32
|
InterceptorRejectedError: () => InterceptorRejectedError,
|
|
32
33
|
OpenCodeAdapter: () => OpenCodeAdapter,
|
|
33
34
|
Porygon: () => Porygon,
|
|
@@ -350,12 +351,18 @@ var EphemeralProcess = class {
|
|
|
350
351
|
throw new Error("Process aborted before start");
|
|
351
352
|
}
|
|
352
353
|
this.aborted = false;
|
|
354
|
+
const useStdin = options.stdinData !== void 0;
|
|
353
355
|
const child = (0, import_node_child_process.spawn)(options.command, options.args, {
|
|
354
356
|
cwd: options.cwd,
|
|
355
357
|
env: options.env ?? void 0,
|
|
356
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
358
|
+
stdio: [useStdin ? "pipe" : "ignore", "pipe", "pipe"]
|
|
357
359
|
});
|
|
358
360
|
this.childProcess = child;
|
|
361
|
+
if (useStdin && child.stdin) {
|
|
362
|
+
child.stdin.write(options.stdinData, () => {
|
|
363
|
+
child.stdin.end();
|
|
364
|
+
});
|
|
365
|
+
}
|
|
359
366
|
let timeoutTimer;
|
|
360
367
|
if (options.timeoutMs !== void 0 && options.timeoutMs > 0) {
|
|
361
368
|
timeoutTimer = setTimeout(() => {
|
|
@@ -967,7 +974,8 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
967
974
|
"tool-restriction",
|
|
968
975
|
"mcp",
|
|
969
976
|
"subagents",
|
|
970
|
-
"worktree"
|
|
977
|
+
"worktree",
|
|
978
|
+
"interactive-session"
|
|
971
979
|
]),
|
|
972
980
|
streamingMode: "chunked",
|
|
973
981
|
outputFormats: ["text", "json", "stream-json"],
|
|
@@ -1000,12 +1008,14 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
1000
1008
|
if (v) cleanEnv[k] = v;
|
|
1001
1009
|
}
|
|
1002
1010
|
}
|
|
1011
|
+
const stdinData = this.buildStdinData(request);
|
|
1003
1012
|
const streamOptions = {
|
|
1004
1013
|
command: this.cliCommand,
|
|
1005
1014
|
args,
|
|
1006
1015
|
...cwd ? { cwd } : {},
|
|
1007
1016
|
env: cleanEnv,
|
|
1008
|
-
timeoutMs: request.timeoutMs
|
|
1017
|
+
timeoutMs: request.timeoutMs,
|
|
1018
|
+
stdinData
|
|
1009
1019
|
};
|
|
1010
1020
|
const cmdStr = [this.cliCommand, ...args.map((a) => /[\s"']/.test(a) ? JSON.stringify(a) : a)].join(" ");
|
|
1011
1021
|
const debugCmd = cwd ? `cd ${JSON.stringify(cwd)} && ${cmdStr}` : cmdStr;
|
|
@@ -1138,10 +1148,16 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
1138
1148
|
env["NO_PROXY"] = noProxy;
|
|
1139
1149
|
}
|
|
1140
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* 构建通过 stdin 传递给 Claude CLI 的数据。
|
|
1153
|
+
* 使用 stdin 而非 CLI 参数传递 prompt,避免超长参数导致的 403 错误。
|
|
1154
|
+
*/
|
|
1155
|
+
buildStdinData(request) {
|
|
1156
|
+
return request.prompt;
|
|
1157
|
+
}
|
|
1141
1158
|
buildArgs(request) {
|
|
1142
1159
|
const args = [
|
|
1143
|
-
"
|
|
1144
|
-
request.prompt,
|
|
1160
|
+
"--print",
|
|
1145
1161
|
"--output-format",
|
|
1146
1162
|
"stream-json",
|
|
1147
1163
|
"--verbose"
|
|
@@ -1753,6 +1769,54 @@ var OpenCodeAdapter = class extends AbstractAgentAdapter {
|
|
|
1753
1769
|
}
|
|
1754
1770
|
};
|
|
1755
1771
|
|
|
1772
|
+
// src/session/interactive-session.ts
|
|
1773
|
+
var InteractiveSession = class {
|
|
1774
|
+
initialSessionId;
|
|
1775
|
+
resolvedSessionId;
|
|
1776
|
+
adapter;
|
|
1777
|
+
baseRequest;
|
|
1778
|
+
firstSent = false;
|
|
1779
|
+
closed = false;
|
|
1780
|
+
constructor(initialSessionId, adapter, baseRequest) {
|
|
1781
|
+
this.initialSessionId = initialSessionId;
|
|
1782
|
+
this.adapter = adapter;
|
|
1783
|
+
this.baseRequest = baseRequest;
|
|
1784
|
+
}
|
|
1785
|
+
/** 当前生效的 sessionId(首次 send 后反映 CLI 返回的真实 ID) */
|
|
1786
|
+
get sessionId() {
|
|
1787
|
+
return this.resolvedSessionId ?? this.initialSessionId;
|
|
1788
|
+
}
|
|
1789
|
+
/** 会话是否仍然活跃 */
|
|
1790
|
+
get isActive() {
|
|
1791
|
+
return !this.closed;
|
|
1792
|
+
}
|
|
1793
|
+
/**
|
|
1794
|
+
* 发送一条消息,返回流式响应。
|
|
1795
|
+
* 首次调用使用 initialSessionId,后续自动附加 resume。
|
|
1796
|
+
*/
|
|
1797
|
+
async *send(prompt) {
|
|
1798
|
+
if (this.closed) {
|
|
1799
|
+
throw new SessionNotFoundError(this.sessionId);
|
|
1800
|
+
}
|
|
1801
|
+
const request = {
|
|
1802
|
+
...this.baseRequest,
|
|
1803
|
+
prompt,
|
|
1804
|
+
...this.firstSent ? { resume: this.sessionId } : {}
|
|
1805
|
+
};
|
|
1806
|
+
for await (const msg of this.adapter.query(request)) {
|
|
1807
|
+
if (!this.firstSent && msg.sessionId) {
|
|
1808
|
+
this.resolvedSessionId = msg.sessionId;
|
|
1809
|
+
}
|
|
1810
|
+
yield msg;
|
|
1811
|
+
}
|
|
1812
|
+
this.firstSent = true;
|
|
1813
|
+
}
|
|
1814
|
+
/** 关闭会话(仅清理内部状态,无进程需要释放) */
|
|
1815
|
+
close() {
|
|
1816
|
+
this.closed = true;
|
|
1817
|
+
}
|
|
1818
|
+
};
|
|
1819
|
+
|
|
1756
1820
|
// src/porygon.ts
|
|
1757
1821
|
var Porygon = class extends import_node_events2.EventEmitter {
|
|
1758
1822
|
config;
|
|
@@ -1852,6 +1916,21 @@ var Porygon = class extends import_node_events2.EventEmitter {
|
|
|
1852
1916
|
}
|
|
1853
1917
|
return resultText;
|
|
1854
1918
|
}
|
|
1919
|
+
/**
|
|
1920
|
+
* 创建交互式多轮对话会话。
|
|
1921
|
+
* 自动管理 sessionId 和 resume,对调用方透明。
|
|
1922
|
+
*/
|
|
1923
|
+
session(options) {
|
|
1924
|
+
const backend = options?.backend ?? this.config.defaultBackend ?? "claude";
|
|
1925
|
+
const adapter = this.getAdapter(backend);
|
|
1926
|
+
const merged = this.mergeRequest({ ...options, prompt: "" }, backend);
|
|
1927
|
+
const { prompt: _, ...baseRequest } = merged;
|
|
1928
|
+
return new InteractiveSession(
|
|
1929
|
+
crypto.randomUUID(),
|
|
1930
|
+
adapter,
|
|
1931
|
+
baseRequest
|
|
1932
|
+
);
|
|
1933
|
+
}
|
|
1855
1934
|
/**
|
|
1856
1935
|
* 注册拦截器
|
|
1857
1936
|
* @param direction 拦截方向
|
|
@@ -2100,6 +2179,7 @@ function createOutputGuard(options) {
|
|
|
2100
2179
|
AgentTimeoutError,
|
|
2101
2180
|
ClaudeAdapter,
|
|
2102
2181
|
ConfigValidationError,
|
|
2182
|
+
InteractiveSession,
|
|
2103
2183
|
InterceptorRejectedError,
|
|
2104
2184
|
OpenCodeAdapter,
|
|
2105
2185
|
Porygon,
|