@snack-kit/porygon 0.2.0 → 0.4.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 +17 -0
- package/dist/index.cjs +89 -8
- 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 +88 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -551,6 +551,23 @@ npm run playground # 启动 Playground
|
|
|
551
551
|
|
|
552
552
|
## Changelog
|
|
553
553
|
|
|
554
|
+
### v0.4.0
|
|
555
|
+
|
|
556
|
+
#### Bug Fixes
|
|
557
|
+
|
|
558
|
+
- **Claude adapter**: 修复 `result` 事件中 `inputTokens` 和 `outputTokens` 始终为 0 的问题。Claude CLI 的 token 统计位于 `event.usage.input_tokens` / `event.usage.output_tokens`,而非顶层的 `event.input_tokens` / `event.output_tokens`
|
|
559
|
+
- **Claude adapter**: 修复 `costUsd` 始终为 `undefined` 的问题。Claude CLI 使用 `total_cost_usd` 字段名,而非 `cost_usd`
|
|
560
|
+
|
|
561
|
+
### v0.3.0
|
|
562
|
+
|
|
563
|
+
#### Bug Fixes
|
|
564
|
+
|
|
565
|
+
- **Claude adapter**: 将 prompt 从 CLI 参数 (`-p <prompt>`) 改为通过 stdin 传递 (`--print` + stdin pipe),修复超长 prompt 导致的偶发 403 "Request not allowed" 错误
|
|
566
|
+
|
|
567
|
+
#### 改进
|
|
568
|
+
|
|
569
|
+
- `SpawnOptions` 新增 `stdinData` 字段,`EphemeralProcess.executeStreaming` 支持向子进程 stdin 写入数据
|
|
570
|
+
|
|
554
571
|
### v0.2.0
|
|
555
572
|
|
|
556
573
|
#### 新特性
|
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(() => {
|
|
@@ -852,14 +859,15 @@ function mapClaudeEvent(event, sessionId) {
|
|
|
852
859
|
return [];
|
|
853
860
|
}
|
|
854
861
|
if (isResultEvent(event)) {
|
|
862
|
+
const usage = event.usage;
|
|
855
863
|
return [{
|
|
856
864
|
...baseFields,
|
|
857
865
|
type: "result",
|
|
858
866
|
text: event.result,
|
|
859
|
-
costUsd: event.cost_usd,
|
|
867
|
+
costUsd: event.total_cost_usd ?? event.cost_usd,
|
|
860
868
|
durationMs: event.duration_ms,
|
|
861
|
-
inputTokens: event.input_tokens,
|
|
862
|
-
outputTokens: event.output_tokens
|
|
869
|
+
inputTokens: usage?.input_tokens ?? event.input_tokens,
|
|
870
|
+
outputTokens: usage?.output_tokens ?? event.output_tokens
|
|
863
871
|
}];
|
|
864
872
|
}
|
|
865
873
|
return [];
|
|
@@ -967,7 +975,8 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
967
975
|
"tool-restriction",
|
|
968
976
|
"mcp",
|
|
969
977
|
"subagents",
|
|
970
|
-
"worktree"
|
|
978
|
+
"worktree",
|
|
979
|
+
"interactive-session"
|
|
971
980
|
]),
|
|
972
981
|
streamingMode: "chunked",
|
|
973
982
|
outputFormats: ["text", "json", "stream-json"],
|
|
@@ -1000,12 +1009,14 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
1000
1009
|
if (v) cleanEnv[k] = v;
|
|
1001
1010
|
}
|
|
1002
1011
|
}
|
|
1012
|
+
const stdinData = this.buildStdinData(request);
|
|
1003
1013
|
const streamOptions = {
|
|
1004
1014
|
command: this.cliCommand,
|
|
1005
1015
|
args,
|
|
1006
1016
|
...cwd ? { cwd } : {},
|
|
1007
1017
|
env: cleanEnv,
|
|
1008
|
-
timeoutMs: request.timeoutMs
|
|
1018
|
+
timeoutMs: request.timeoutMs,
|
|
1019
|
+
stdinData
|
|
1009
1020
|
};
|
|
1010
1021
|
const cmdStr = [this.cliCommand, ...args.map((a) => /[\s"']/.test(a) ? JSON.stringify(a) : a)].join(" ");
|
|
1011
1022
|
const debugCmd = cwd ? `cd ${JSON.stringify(cwd)} && ${cmdStr}` : cmdStr;
|
|
@@ -1138,10 +1149,16 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
1138
1149
|
env["NO_PROXY"] = noProxy;
|
|
1139
1150
|
}
|
|
1140
1151
|
}
|
|
1152
|
+
/**
|
|
1153
|
+
* 构建通过 stdin 传递给 Claude CLI 的数据。
|
|
1154
|
+
* 使用 stdin 而非 CLI 参数传递 prompt,避免超长参数导致的 403 错误。
|
|
1155
|
+
*/
|
|
1156
|
+
buildStdinData(request) {
|
|
1157
|
+
return request.prompt;
|
|
1158
|
+
}
|
|
1141
1159
|
buildArgs(request) {
|
|
1142
1160
|
const args = [
|
|
1143
|
-
"
|
|
1144
|
-
request.prompt,
|
|
1161
|
+
"--print",
|
|
1145
1162
|
"--output-format",
|
|
1146
1163
|
"stream-json",
|
|
1147
1164
|
"--verbose"
|
|
@@ -1753,6 +1770,54 @@ var OpenCodeAdapter = class extends AbstractAgentAdapter {
|
|
|
1753
1770
|
}
|
|
1754
1771
|
};
|
|
1755
1772
|
|
|
1773
|
+
// src/session/interactive-session.ts
|
|
1774
|
+
var InteractiveSession = class {
|
|
1775
|
+
initialSessionId;
|
|
1776
|
+
resolvedSessionId;
|
|
1777
|
+
adapter;
|
|
1778
|
+
baseRequest;
|
|
1779
|
+
firstSent = false;
|
|
1780
|
+
closed = false;
|
|
1781
|
+
constructor(initialSessionId, adapter, baseRequest) {
|
|
1782
|
+
this.initialSessionId = initialSessionId;
|
|
1783
|
+
this.adapter = adapter;
|
|
1784
|
+
this.baseRequest = baseRequest;
|
|
1785
|
+
}
|
|
1786
|
+
/** 当前生效的 sessionId(首次 send 后反映 CLI 返回的真实 ID) */
|
|
1787
|
+
get sessionId() {
|
|
1788
|
+
return this.resolvedSessionId ?? this.initialSessionId;
|
|
1789
|
+
}
|
|
1790
|
+
/** 会话是否仍然活跃 */
|
|
1791
|
+
get isActive() {
|
|
1792
|
+
return !this.closed;
|
|
1793
|
+
}
|
|
1794
|
+
/**
|
|
1795
|
+
* 发送一条消息,返回流式响应。
|
|
1796
|
+
* 首次调用使用 initialSessionId,后续自动附加 resume。
|
|
1797
|
+
*/
|
|
1798
|
+
async *send(prompt) {
|
|
1799
|
+
if (this.closed) {
|
|
1800
|
+
throw new SessionNotFoundError(this.sessionId);
|
|
1801
|
+
}
|
|
1802
|
+
const request = {
|
|
1803
|
+
...this.baseRequest,
|
|
1804
|
+
prompt,
|
|
1805
|
+
...this.firstSent ? { resume: this.sessionId } : {}
|
|
1806
|
+
};
|
|
1807
|
+
for await (const msg of this.adapter.query(request)) {
|
|
1808
|
+
if (!this.firstSent && msg.sessionId) {
|
|
1809
|
+
this.resolvedSessionId = msg.sessionId;
|
|
1810
|
+
}
|
|
1811
|
+
yield msg;
|
|
1812
|
+
}
|
|
1813
|
+
this.firstSent = true;
|
|
1814
|
+
}
|
|
1815
|
+
/** 关闭会话(仅清理内部状态,无进程需要释放) */
|
|
1816
|
+
close() {
|
|
1817
|
+
this.closed = true;
|
|
1818
|
+
}
|
|
1819
|
+
};
|
|
1820
|
+
|
|
1756
1821
|
// src/porygon.ts
|
|
1757
1822
|
var Porygon = class extends import_node_events2.EventEmitter {
|
|
1758
1823
|
config;
|
|
@@ -1852,6 +1917,21 @@ var Porygon = class extends import_node_events2.EventEmitter {
|
|
|
1852
1917
|
}
|
|
1853
1918
|
return resultText;
|
|
1854
1919
|
}
|
|
1920
|
+
/**
|
|
1921
|
+
* 创建交互式多轮对话会话。
|
|
1922
|
+
* 自动管理 sessionId 和 resume,对调用方透明。
|
|
1923
|
+
*/
|
|
1924
|
+
session(options) {
|
|
1925
|
+
const backend = options?.backend ?? this.config.defaultBackend ?? "claude";
|
|
1926
|
+
const adapter = this.getAdapter(backend);
|
|
1927
|
+
const merged = this.mergeRequest({ ...options, prompt: "" }, backend);
|
|
1928
|
+
const { prompt: _, ...baseRequest } = merged;
|
|
1929
|
+
return new InteractiveSession(
|
|
1930
|
+
crypto.randomUUID(),
|
|
1931
|
+
adapter,
|
|
1932
|
+
baseRequest
|
|
1933
|
+
);
|
|
1934
|
+
}
|
|
1855
1935
|
/**
|
|
1856
1936
|
* 注册拦截器
|
|
1857
1937
|
* @param direction 拦截方向
|
|
@@ -2100,6 +2180,7 @@ function createOutputGuard(options) {
|
|
|
2100
2180
|
AgentTimeoutError,
|
|
2101
2181
|
ClaudeAdapter,
|
|
2102
2182
|
ConfigValidationError,
|
|
2183
|
+
InteractiveSession,
|
|
2103
2184
|
InterceptorRejectedError,
|
|
2104
2185
|
OpenCodeAdapter,
|
|
2105
2186
|
Porygon,
|