@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/dist/index.d.cts
CHANGED
|
@@ -128,7 +128,7 @@ interface AgentErrorMessage extends BaseAgentMessage {
|
|
|
128
128
|
* 适配器能力声明
|
|
129
129
|
*/
|
|
130
130
|
interface AdapterCapabilities {
|
|
131
|
-
features: Set<"streaming" | "session-resume" | "system-prompt" | "tool-restriction" | "mcp" | "subagents" | "worktree" | "budget-limit" | "serve-mode">;
|
|
131
|
+
features: Set<"streaming" | "session-resume" | "system-prompt" | "tool-restriction" | "mcp" | "subagents" | "worktree" | "budget-limit" | "serve-mode" | "interactive-session">;
|
|
132
132
|
/**
|
|
133
133
|
* 流式输出模式:
|
|
134
134
|
* - 'delta': 后端原生产生增量 stream_chunk 事件(如 OpenCode)
|
|
@@ -209,6 +209,38 @@ interface InterceptorContext {
|
|
|
209
209
|
*/
|
|
210
210
|
type InterceptorFn = (text: string, context: InterceptorContext) => string | boolean | undefined | Promise<string | boolean | undefined>;
|
|
211
211
|
|
|
212
|
+
/**
|
|
213
|
+
* 便捷的多轮对话封装。
|
|
214
|
+
*
|
|
215
|
+
* 底层仍是 per-turn spawn + --resume,但对调用方透明:
|
|
216
|
+
* ```ts
|
|
217
|
+
* const session = porygon.session({ systemPrompt: '...' });
|
|
218
|
+
* for await (const msg of session.send('Hello')) { ... }
|
|
219
|
+
* for await (const msg of session.send('继续')) { ... } // 自动 resume
|
|
220
|
+
* session.close();
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
declare class InteractiveSession {
|
|
224
|
+
readonly initialSessionId: string;
|
|
225
|
+
private resolvedSessionId?;
|
|
226
|
+
private adapter;
|
|
227
|
+
private baseRequest;
|
|
228
|
+
private firstSent;
|
|
229
|
+
private closed;
|
|
230
|
+
constructor(initialSessionId: string, adapter: IAgentAdapter, baseRequest: Omit<PromptRequest, "prompt">);
|
|
231
|
+
/** 当前生效的 sessionId(首次 send 后反映 CLI 返回的真实 ID) */
|
|
232
|
+
get sessionId(): string;
|
|
233
|
+
/** 会话是否仍然活跃 */
|
|
234
|
+
get isActive(): boolean;
|
|
235
|
+
/**
|
|
236
|
+
* 发送一条消息,返回流式响应。
|
|
237
|
+
* 首次调用使用 initialSessionId,后续自动附加 resume。
|
|
238
|
+
*/
|
|
239
|
+
send(prompt: string): AsyncGenerator<AgentMessage>;
|
|
240
|
+
/** 关闭会话(仅清理内部状态,无进程需要释放) */
|
|
241
|
+
close(): void;
|
|
242
|
+
}
|
|
243
|
+
|
|
212
244
|
/**
|
|
213
245
|
* 健康检查结果(扁平化结构)
|
|
214
246
|
*/
|
|
@@ -270,6 +302,11 @@ declare class Porygon extends EventEmitter {
|
|
|
270
302
|
* @returns 最终结果文本
|
|
271
303
|
*/
|
|
272
304
|
run(request: PromptRequest): Promise<string>;
|
|
305
|
+
/**
|
|
306
|
+
* 创建交互式多轮对话会话。
|
|
307
|
+
* 自动管理 sessionId 和 resume,对调用方透明。
|
|
308
|
+
*/
|
|
309
|
+
session(options?: Omit<PromptRequest, "prompt">): InteractiveSession;
|
|
273
310
|
/**
|
|
274
311
|
* 注册拦截器
|
|
275
312
|
* @param direction 拦截方向
|
|
@@ -458,6 +495,8 @@ interface SpawnOptions {
|
|
|
458
495
|
cwd?: string;
|
|
459
496
|
env?: Record<string, string>;
|
|
460
497
|
timeoutMs?: number;
|
|
498
|
+
/** 写入 stdin 后自动关闭的数据 */
|
|
499
|
+
stdinData?: string;
|
|
461
500
|
}
|
|
462
501
|
/**
|
|
463
502
|
* 进程执行结果
|
|
@@ -681,6 +720,11 @@ declare class ClaudeAdapter extends AbstractAgentAdapter {
|
|
|
681
720
|
* @param noProxy 不走代理的地址列表
|
|
682
721
|
*/
|
|
683
722
|
private applyProxyEnv;
|
|
723
|
+
/**
|
|
724
|
+
* 构建通过 stdin 传递给 Claude CLI 的数据。
|
|
725
|
+
* 使用 stdin 而非 CLI 参数传递 prompt,避免超长参数导致的 403 错误。
|
|
726
|
+
*/
|
|
727
|
+
private buildStdinData;
|
|
684
728
|
private buildArgs;
|
|
685
729
|
}
|
|
686
730
|
|
|
@@ -765,4 +809,4 @@ declare class OpenCodeAdapter extends AbstractAgentAdapter {
|
|
|
765
809
|
private getConfigPath;
|
|
766
810
|
}
|
|
767
811
|
|
|
768
|
-
export { AbstractAgentAdapter, type AdapterCapabilities, AdapterIncompatibleError, AdapterNotAvailableError, AdapterNotFoundError, type AgentAssistantMessage, type AgentErrorMessage, AgentExecutionError, type AgentMessage, type AgentResultMessage, type AgentStreamChunkMessage, type AgentSystemMessage, AgentTimeoutError, type AgentToolUseMessage, type BackendConfig, ClaudeAdapter, type CompatibilityResult, ConfigValidationError, type GuardAction, type GuardOptions, type HealthCheckResult, type IAgentAdapter, type InterceptorContext, type InterceptorDirection, type InterceptorFn, InterceptorRejectedError, type McpServerConfig, type ModelInfo, OpenCodeAdapter, Porygon, type PorygonConfig, PorygonError, type PorygonEvents, type PromptRequest, type ProxyConfig, type SessionInfo, type SessionListOptions, SessionNotFoundError, createInputGuard, createOutputGuard, createPorygon };
|
|
812
|
+
export { AbstractAgentAdapter, type AdapterCapabilities, AdapterIncompatibleError, AdapterNotAvailableError, AdapterNotFoundError, type AgentAssistantMessage, type AgentErrorMessage, AgentExecutionError, type AgentMessage, type AgentResultMessage, type AgentStreamChunkMessage, type AgentSystemMessage, AgentTimeoutError, type AgentToolUseMessage, type BackendConfig, ClaudeAdapter, type CompatibilityResult, ConfigValidationError, type GuardAction, type GuardOptions, type HealthCheckResult, type IAgentAdapter, InteractiveSession, type InterceptorContext, type InterceptorDirection, type InterceptorFn, InterceptorRejectedError, type McpServerConfig, type ModelInfo, OpenCodeAdapter, Porygon, type PorygonConfig, PorygonError, type PorygonEvents, type PromptRequest, type ProxyConfig, type SessionInfo, type SessionListOptions, SessionNotFoundError, createInputGuard, createOutputGuard, createPorygon };
|
package/dist/index.d.ts
CHANGED
|
@@ -128,7 +128,7 @@ interface AgentErrorMessage extends BaseAgentMessage {
|
|
|
128
128
|
* 适配器能力声明
|
|
129
129
|
*/
|
|
130
130
|
interface AdapterCapabilities {
|
|
131
|
-
features: Set<"streaming" | "session-resume" | "system-prompt" | "tool-restriction" | "mcp" | "subagents" | "worktree" | "budget-limit" | "serve-mode">;
|
|
131
|
+
features: Set<"streaming" | "session-resume" | "system-prompt" | "tool-restriction" | "mcp" | "subagents" | "worktree" | "budget-limit" | "serve-mode" | "interactive-session">;
|
|
132
132
|
/**
|
|
133
133
|
* 流式输出模式:
|
|
134
134
|
* - 'delta': 后端原生产生增量 stream_chunk 事件(如 OpenCode)
|
|
@@ -209,6 +209,38 @@ interface InterceptorContext {
|
|
|
209
209
|
*/
|
|
210
210
|
type InterceptorFn = (text: string, context: InterceptorContext) => string | boolean | undefined | Promise<string | boolean | undefined>;
|
|
211
211
|
|
|
212
|
+
/**
|
|
213
|
+
* 便捷的多轮对话封装。
|
|
214
|
+
*
|
|
215
|
+
* 底层仍是 per-turn spawn + --resume,但对调用方透明:
|
|
216
|
+
* ```ts
|
|
217
|
+
* const session = porygon.session({ systemPrompt: '...' });
|
|
218
|
+
* for await (const msg of session.send('Hello')) { ... }
|
|
219
|
+
* for await (const msg of session.send('继续')) { ... } // 自动 resume
|
|
220
|
+
* session.close();
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
declare class InteractiveSession {
|
|
224
|
+
readonly initialSessionId: string;
|
|
225
|
+
private resolvedSessionId?;
|
|
226
|
+
private adapter;
|
|
227
|
+
private baseRequest;
|
|
228
|
+
private firstSent;
|
|
229
|
+
private closed;
|
|
230
|
+
constructor(initialSessionId: string, adapter: IAgentAdapter, baseRequest: Omit<PromptRequest, "prompt">);
|
|
231
|
+
/** 当前生效的 sessionId(首次 send 后反映 CLI 返回的真实 ID) */
|
|
232
|
+
get sessionId(): string;
|
|
233
|
+
/** 会话是否仍然活跃 */
|
|
234
|
+
get isActive(): boolean;
|
|
235
|
+
/**
|
|
236
|
+
* 发送一条消息,返回流式响应。
|
|
237
|
+
* 首次调用使用 initialSessionId,后续自动附加 resume。
|
|
238
|
+
*/
|
|
239
|
+
send(prompt: string): AsyncGenerator<AgentMessage>;
|
|
240
|
+
/** 关闭会话(仅清理内部状态,无进程需要释放) */
|
|
241
|
+
close(): void;
|
|
242
|
+
}
|
|
243
|
+
|
|
212
244
|
/**
|
|
213
245
|
* 健康检查结果(扁平化结构)
|
|
214
246
|
*/
|
|
@@ -270,6 +302,11 @@ declare class Porygon extends EventEmitter {
|
|
|
270
302
|
* @returns 最终结果文本
|
|
271
303
|
*/
|
|
272
304
|
run(request: PromptRequest): Promise<string>;
|
|
305
|
+
/**
|
|
306
|
+
* 创建交互式多轮对话会话。
|
|
307
|
+
* 自动管理 sessionId 和 resume,对调用方透明。
|
|
308
|
+
*/
|
|
309
|
+
session(options?: Omit<PromptRequest, "prompt">): InteractiveSession;
|
|
273
310
|
/**
|
|
274
311
|
* 注册拦截器
|
|
275
312
|
* @param direction 拦截方向
|
|
@@ -458,6 +495,8 @@ interface SpawnOptions {
|
|
|
458
495
|
cwd?: string;
|
|
459
496
|
env?: Record<string, string>;
|
|
460
497
|
timeoutMs?: number;
|
|
498
|
+
/** 写入 stdin 后自动关闭的数据 */
|
|
499
|
+
stdinData?: string;
|
|
461
500
|
}
|
|
462
501
|
/**
|
|
463
502
|
* 进程执行结果
|
|
@@ -681,6 +720,11 @@ declare class ClaudeAdapter extends AbstractAgentAdapter {
|
|
|
681
720
|
* @param noProxy 不走代理的地址列表
|
|
682
721
|
*/
|
|
683
722
|
private applyProxyEnv;
|
|
723
|
+
/**
|
|
724
|
+
* 构建通过 stdin 传递给 Claude CLI 的数据。
|
|
725
|
+
* 使用 stdin 而非 CLI 参数传递 prompt,避免超长参数导致的 403 错误。
|
|
726
|
+
*/
|
|
727
|
+
private buildStdinData;
|
|
684
728
|
private buildArgs;
|
|
685
729
|
}
|
|
686
730
|
|
|
@@ -765,4 +809,4 @@ declare class OpenCodeAdapter extends AbstractAgentAdapter {
|
|
|
765
809
|
private getConfigPath;
|
|
766
810
|
}
|
|
767
811
|
|
|
768
|
-
export { AbstractAgentAdapter, type AdapterCapabilities, AdapterIncompatibleError, AdapterNotAvailableError, AdapterNotFoundError, type AgentAssistantMessage, type AgentErrorMessage, AgentExecutionError, type AgentMessage, type AgentResultMessage, type AgentStreamChunkMessage, type AgentSystemMessage, AgentTimeoutError, type AgentToolUseMessage, type BackendConfig, ClaudeAdapter, type CompatibilityResult, ConfigValidationError, type GuardAction, type GuardOptions, type HealthCheckResult, type IAgentAdapter, type InterceptorContext, type InterceptorDirection, type InterceptorFn, InterceptorRejectedError, type McpServerConfig, type ModelInfo, OpenCodeAdapter, Porygon, type PorygonConfig, PorygonError, type PorygonEvents, type PromptRequest, type ProxyConfig, type SessionInfo, type SessionListOptions, SessionNotFoundError, createInputGuard, createOutputGuard, createPorygon };
|
|
812
|
+
export { AbstractAgentAdapter, type AdapterCapabilities, AdapterIncompatibleError, AdapterNotAvailableError, AdapterNotFoundError, type AgentAssistantMessage, type AgentErrorMessage, AgentExecutionError, type AgentMessage, type AgentResultMessage, type AgentStreamChunkMessage, type AgentSystemMessage, AgentTimeoutError, type AgentToolUseMessage, type BackendConfig, ClaudeAdapter, type CompatibilityResult, ConfigValidationError, type GuardAction, type GuardOptions, type HealthCheckResult, type IAgentAdapter, InteractiveSession, type InterceptorContext, type InterceptorDirection, type InterceptorFn, InterceptorRejectedError, type McpServerConfig, type ModelInfo, OpenCodeAdapter, Porygon, type PorygonConfig, PorygonError, type PorygonEvents, type PromptRequest, type ProxyConfig, type SessionInfo, type SessionListOptions, SessionNotFoundError, createInputGuard, createOutputGuard, createPorygon };
|
package/dist/index.js
CHANGED
|
@@ -309,12 +309,18 @@ var EphemeralProcess = class {
|
|
|
309
309
|
throw new Error("Process aborted before start");
|
|
310
310
|
}
|
|
311
311
|
this.aborted = false;
|
|
312
|
+
const useStdin = options.stdinData !== void 0;
|
|
312
313
|
const child = spawn(options.command, options.args, {
|
|
313
314
|
cwd: options.cwd,
|
|
314
315
|
env: options.env ?? void 0,
|
|
315
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
316
|
+
stdio: [useStdin ? "pipe" : "ignore", "pipe", "pipe"]
|
|
316
317
|
});
|
|
317
318
|
this.childProcess = child;
|
|
319
|
+
if (useStdin && child.stdin) {
|
|
320
|
+
child.stdin.write(options.stdinData, () => {
|
|
321
|
+
child.stdin.end();
|
|
322
|
+
});
|
|
323
|
+
}
|
|
318
324
|
let timeoutTimer;
|
|
319
325
|
if (options.timeoutMs !== void 0 && options.timeoutMs > 0) {
|
|
320
326
|
timeoutTimer = setTimeout(() => {
|
|
@@ -926,7 +932,8 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
926
932
|
"tool-restriction",
|
|
927
933
|
"mcp",
|
|
928
934
|
"subagents",
|
|
929
|
-
"worktree"
|
|
935
|
+
"worktree",
|
|
936
|
+
"interactive-session"
|
|
930
937
|
]),
|
|
931
938
|
streamingMode: "chunked",
|
|
932
939
|
outputFormats: ["text", "json", "stream-json"],
|
|
@@ -959,12 +966,14 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
959
966
|
if (v) cleanEnv[k] = v;
|
|
960
967
|
}
|
|
961
968
|
}
|
|
969
|
+
const stdinData = this.buildStdinData(request);
|
|
962
970
|
const streamOptions = {
|
|
963
971
|
command: this.cliCommand,
|
|
964
972
|
args,
|
|
965
973
|
...cwd ? { cwd } : {},
|
|
966
974
|
env: cleanEnv,
|
|
967
|
-
timeoutMs: request.timeoutMs
|
|
975
|
+
timeoutMs: request.timeoutMs,
|
|
976
|
+
stdinData
|
|
968
977
|
};
|
|
969
978
|
const cmdStr = [this.cliCommand, ...args.map((a) => /[\s"']/.test(a) ? JSON.stringify(a) : a)].join(" ");
|
|
970
979
|
const debugCmd = cwd ? `cd ${JSON.stringify(cwd)} && ${cmdStr}` : cmdStr;
|
|
@@ -1097,10 +1106,16 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
1097
1106
|
env["NO_PROXY"] = noProxy;
|
|
1098
1107
|
}
|
|
1099
1108
|
}
|
|
1109
|
+
/**
|
|
1110
|
+
* 构建通过 stdin 传递给 Claude CLI 的数据。
|
|
1111
|
+
* 使用 stdin 而非 CLI 参数传递 prompt,避免超长参数导致的 403 错误。
|
|
1112
|
+
*/
|
|
1113
|
+
buildStdinData(request) {
|
|
1114
|
+
return request.prompt;
|
|
1115
|
+
}
|
|
1100
1116
|
buildArgs(request) {
|
|
1101
1117
|
const args = [
|
|
1102
|
-
"
|
|
1103
|
-
request.prompt,
|
|
1118
|
+
"--print",
|
|
1104
1119
|
"--output-format",
|
|
1105
1120
|
"stream-json",
|
|
1106
1121
|
"--verbose"
|
|
@@ -1712,6 +1727,54 @@ var OpenCodeAdapter = class extends AbstractAgentAdapter {
|
|
|
1712
1727
|
}
|
|
1713
1728
|
};
|
|
1714
1729
|
|
|
1730
|
+
// src/session/interactive-session.ts
|
|
1731
|
+
var InteractiveSession = class {
|
|
1732
|
+
initialSessionId;
|
|
1733
|
+
resolvedSessionId;
|
|
1734
|
+
adapter;
|
|
1735
|
+
baseRequest;
|
|
1736
|
+
firstSent = false;
|
|
1737
|
+
closed = false;
|
|
1738
|
+
constructor(initialSessionId, adapter, baseRequest) {
|
|
1739
|
+
this.initialSessionId = initialSessionId;
|
|
1740
|
+
this.adapter = adapter;
|
|
1741
|
+
this.baseRequest = baseRequest;
|
|
1742
|
+
}
|
|
1743
|
+
/** 当前生效的 sessionId(首次 send 后反映 CLI 返回的真实 ID) */
|
|
1744
|
+
get sessionId() {
|
|
1745
|
+
return this.resolvedSessionId ?? this.initialSessionId;
|
|
1746
|
+
}
|
|
1747
|
+
/** 会话是否仍然活跃 */
|
|
1748
|
+
get isActive() {
|
|
1749
|
+
return !this.closed;
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* 发送一条消息,返回流式响应。
|
|
1753
|
+
* 首次调用使用 initialSessionId,后续自动附加 resume。
|
|
1754
|
+
*/
|
|
1755
|
+
async *send(prompt) {
|
|
1756
|
+
if (this.closed) {
|
|
1757
|
+
throw new SessionNotFoundError(this.sessionId);
|
|
1758
|
+
}
|
|
1759
|
+
const request = {
|
|
1760
|
+
...this.baseRequest,
|
|
1761
|
+
prompt,
|
|
1762
|
+
...this.firstSent ? { resume: this.sessionId } : {}
|
|
1763
|
+
};
|
|
1764
|
+
for await (const msg of this.adapter.query(request)) {
|
|
1765
|
+
if (!this.firstSent && msg.sessionId) {
|
|
1766
|
+
this.resolvedSessionId = msg.sessionId;
|
|
1767
|
+
}
|
|
1768
|
+
yield msg;
|
|
1769
|
+
}
|
|
1770
|
+
this.firstSent = true;
|
|
1771
|
+
}
|
|
1772
|
+
/** 关闭会话(仅清理内部状态,无进程需要释放) */
|
|
1773
|
+
close() {
|
|
1774
|
+
this.closed = true;
|
|
1775
|
+
}
|
|
1776
|
+
};
|
|
1777
|
+
|
|
1715
1778
|
// src/porygon.ts
|
|
1716
1779
|
var Porygon = class extends EventEmitter2 {
|
|
1717
1780
|
config;
|
|
@@ -1811,6 +1874,21 @@ var Porygon = class extends EventEmitter2 {
|
|
|
1811
1874
|
}
|
|
1812
1875
|
return resultText;
|
|
1813
1876
|
}
|
|
1877
|
+
/**
|
|
1878
|
+
* 创建交互式多轮对话会话。
|
|
1879
|
+
* 自动管理 sessionId 和 resume,对调用方透明。
|
|
1880
|
+
*/
|
|
1881
|
+
session(options) {
|
|
1882
|
+
const backend = options?.backend ?? this.config.defaultBackend ?? "claude";
|
|
1883
|
+
const adapter = this.getAdapter(backend);
|
|
1884
|
+
const merged = this.mergeRequest({ ...options, prompt: "" }, backend);
|
|
1885
|
+
const { prompt: _, ...baseRequest } = merged;
|
|
1886
|
+
return new InteractiveSession(
|
|
1887
|
+
crypto.randomUUID(),
|
|
1888
|
+
adapter,
|
|
1889
|
+
baseRequest
|
|
1890
|
+
);
|
|
1891
|
+
}
|
|
1814
1892
|
/**
|
|
1815
1893
|
* 注册拦截器
|
|
1816
1894
|
* @param direction 拦截方向
|
|
@@ -2058,6 +2136,7 @@ export {
|
|
|
2058
2136
|
AgentTimeoutError,
|
|
2059
2137
|
ClaudeAdapter,
|
|
2060
2138
|
ConfigValidationError,
|
|
2139
|
+
InteractiveSession,
|
|
2061
2140
|
InterceptorRejectedError,
|
|
2062
2141
|
OpenCodeAdapter,
|
|
2063
2142
|
Porygon,
|