@snack-kit/porygon 0.3.0 → 0.5.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 +115 -8
- package/dist/index.cjs +100 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -4
- package/dist/index.d.ts +50 -4
- package/dist/index.js +100 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -23,6 +23,8 @@ interface BackendConfig {
|
|
|
23
23
|
interactive?: boolean;
|
|
24
24
|
/** CLI 可执行文件路径(如 Claude CLI 的自定义安装路径) */
|
|
25
25
|
cliPath?: string;
|
|
26
|
+
/** 禁止使用的工具黑名单(后端级) */
|
|
27
|
+
disallowedTools?: string[];
|
|
26
28
|
/** 透传给 CLI 的后端特定选项(向后兼容,推荐使用上方的显式字段) */
|
|
27
29
|
options?: Record<string, unknown>;
|
|
28
30
|
}
|
|
@@ -36,6 +38,8 @@ interface PorygonConfig {
|
|
|
36
38
|
appendSystemPrompt?: string;
|
|
37
39
|
timeoutMs?: number;
|
|
38
40
|
maxTurns?: number;
|
|
41
|
+
/** 禁止使用的工具黑名单(全局默认) */
|
|
42
|
+
disallowedTools?: string[];
|
|
39
43
|
};
|
|
40
44
|
proxy?: ProxyConfig;
|
|
41
45
|
}
|
|
@@ -63,7 +67,13 @@ interface PromptRequest {
|
|
|
63
67
|
appendSystemPrompt?: string;
|
|
64
68
|
model?: string;
|
|
65
69
|
timeoutMs?: number;
|
|
66
|
-
|
|
70
|
+
/**
|
|
71
|
+
* 仅允许使用的工具白名单。
|
|
72
|
+
* 运行时通过 getTools() 获取全量工具列表,差集计算后转为 disallowedTools 传递给 CLI。
|
|
73
|
+
* 与 disallowedTools 互斥,同时设置时 onlyTools 优先。
|
|
74
|
+
*/
|
|
75
|
+
onlyTools?: string[];
|
|
76
|
+
/** 禁止使用的工具黑名单 */
|
|
67
77
|
disallowedTools?: string[];
|
|
68
78
|
mcpServers?: Record<string, McpServerConfig>;
|
|
69
79
|
maxTurns?: number;
|
|
@@ -180,6 +190,8 @@ interface IAgentAdapter {
|
|
|
180
190
|
/** 获取可用模型列表 */
|
|
181
191
|
listModels(): Promise<ModelInfo[]>;
|
|
182
192
|
abort(sessionId: string): void;
|
|
193
|
+
/** 获取当前可用的工具列表(可选实现,支持缓存) */
|
|
194
|
+
getTools?(force?: boolean): Promise<string[]>;
|
|
183
195
|
/** 删除会话及其资源(可选实现) */
|
|
184
196
|
deleteSession?(sessionId: string): Promise<void>;
|
|
185
197
|
dispose(): Promise<void>;
|
|
@@ -250,6 +262,23 @@ interface HealthCheckResult {
|
|
|
250
262
|
supported?: boolean;
|
|
251
263
|
warnings?: string[];
|
|
252
264
|
error?: string;
|
|
265
|
+
/** deep 模式下,模型是否真正响应 */
|
|
266
|
+
modelVerified?: boolean;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* checkBackend 的选项
|
|
270
|
+
*/
|
|
271
|
+
interface CheckBackendOptions {
|
|
272
|
+
/**
|
|
273
|
+
* 启用深度检测:在基础 CLI/版本检查通过后,向模型发送一条极短测试消息,
|
|
274
|
+
* 验证 Token/模型/配额是否真正可用。
|
|
275
|
+
* 默认 false(仅做 CLI 存在性 + 版本检查)。
|
|
276
|
+
*/
|
|
277
|
+
deep?: boolean;
|
|
278
|
+
/** deep 模式下使用的模型(可选,不传则用后端默认模型) */
|
|
279
|
+
model?: string;
|
|
280
|
+
/** deep 模式超时(毫秒),默认 15000 */
|
|
281
|
+
timeoutMs?: number;
|
|
253
282
|
}
|
|
254
283
|
/**
|
|
255
284
|
* Porygon 事件类型定义
|
|
@@ -306,7 +335,13 @@ declare class Porygon extends EventEmitter {
|
|
|
306
335
|
* 创建交互式多轮对话会话。
|
|
307
336
|
* 自动管理 sessionId 和 resume,对调用方透明。
|
|
308
337
|
*/
|
|
309
|
-
session(options?: Omit<PromptRequest, "prompt">): InteractiveSession
|
|
338
|
+
session(options?: Omit<PromptRequest, "prompt">): Promise<InteractiveSession>;
|
|
339
|
+
/**
|
|
340
|
+
* 获取当前可用的工具列表。
|
|
341
|
+
* 首次调用通过发起最小化对话从 system 事件中提取工具清单,结果会被缓存。
|
|
342
|
+
* @param force 是否强制刷新缓存
|
|
343
|
+
*/
|
|
344
|
+
getTools(force?: boolean): Promise<string[]>;
|
|
310
345
|
/**
|
|
311
346
|
* 注册拦截器
|
|
312
347
|
* @param direction 拦截方向
|
|
@@ -327,8 +362,9 @@ declare class Porygon extends EventEmitter {
|
|
|
327
362
|
/**
|
|
328
363
|
* 检查单个后端的健康状态
|
|
329
364
|
* @param backend 后端名称
|
|
365
|
+
* @param options 检测选项。传入 `{ deep: true }` 时会向模型发送一条测试消息验证可用性。
|
|
330
366
|
*/
|
|
331
|
-
checkBackend(backend: string): Promise<HealthCheckResult>;
|
|
367
|
+
checkBackend(backend: string, options?: CheckBackendOptions): Promise<HealthCheckResult>;
|
|
332
368
|
/**
|
|
333
369
|
* 对所有已注册后端进行健康检查。
|
|
334
370
|
* 返回扁平化结构,包含 version/supported/warnings 等字段。
|
|
@@ -365,6 +401,8 @@ declare class Porygon extends EventEmitter {
|
|
|
365
401
|
* - timeoutMs: request > defaults
|
|
366
402
|
* - maxTurns: request > defaults
|
|
367
403
|
* - cwd: request > backendConfig
|
|
404
|
+
* - disallowedTools: defaults + backendConfig + request 三层叠加去重
|
|
405
|
+
* - onlyTools: 通过 getTools() 获取全量列表,差集计算转为 disallowedTools(与 disallowedTools 互斥,onlyTools 优先)
|
|
368
406
|
* - appendSystemPrompt: **追加模式** — defaults + backendConfig + request 三层拼接(换行分隔)
|
|
369
407
|
* 但如果 request.systemPrompt 已设置(替换模式),则忽略所有 appendSystemPrompt
|
|
370
408
|
*
|
|
@@ -671,6 +709,8 @@ declare abstract class AbstractAgentAdapter implements IAgentAdapter {
|
|
|
671
709
|
*/
|
|
672
710
|
declare class ClaudeAdapter extends AbstractAgentAdapter {
|
|
673
711
|
readonly backend = "claude";
|
|
712
|
+
/** 工具列表缓存 */
|
|
713
|
+
private cachedTools;
|
|
674
714
|
/** CLI 命令名或路径 */
|
|
675
715
|
private get cliCommand();
|
|
676
716
|
/**
|
|
@@ -690,6 +730,12 @@ declare class ClaudeAdapter extends AbstractAgentAdapter {
|
|
|
690
730
|
* @param request 提示请求参数
|
|
691
731
|
*/
|
|
692
732
|
query(request: PromptRequest): AsyncGenerator<AgentMessage>;
|
|
733
|
+
/**
|
|
734
|
+
* 获取当前可用的工具列表。
|
|
735
|
+
* 首次调用通过发起最小化对话从 system 事件中提取 tools 字段,结果会被缓存。
|
|
736
|
+
* @param force 是否强制刷新缓存
|
|
737
|
+
*/
|
|
738
|
+
getTools(force?: boolean): Promise<string[]>;
|
|
693
739
|
/**
|
|
694
740
|
* 列出 Claude 会话
|
|
695
741
|
* @param options 查询选项
|
|
@@ -809,4 +855,4 @@ declare class OpenCodeAdapter extends AbstractAgentAdapter {
|
|
|
809
855
|
private getConfigPath;
|
|
810
856
|
}
|
|
811
857
|
|
|
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 };
|
|
858
|
+
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, type CheckBackendOptions, 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
|
@@ -23,6 +23,8 @@ interface BackendConfig {
|
|
|
23
23
|
interactive?: boolean;
|
|
24
24
|
/** CLI 可执行文件路径(如 Claude CLI 的自定义安装路径) */
|
|
25
25
|
cliPath?: string;
|
|
26
|
+
/** 禁止使用的工具黑名单(后端级) */
|
|
27
|
+
disallowedTools?: string[];
|
|
26
28
|
/** 透传给 CLI 的后端特定选项(向后兼容,推荐使用上方的显式字段) */
|
|
27
29
|
options?: Record<string, unknown>;
|
|
28
30
|
}
|
|
@@ -36,6 +38,8 @@ interface PorygonConfig {
|
|
|
36
38
|
appendSystemPrompt?: string;
|
|
37
39
|
timeoutMs?: number;
|
|
38
40
|
maxTurns?: number;
|
|
41
|
+
/** 禁止使用的工具黑名单(全局默认) */
|
|
42
|
+
disallowedTools?: string[];
|
|
39
43
|
};
|
|
40
44
|
proxy?: ProxyConfig;
|
|
41
45
|
}
|
|
@@ -63,7 +67,13 @@ interface PromptRequest {
|
|
|
63
67
|
appendSystemPrompt?: string;
|
|
64
68
|
model?: string;
|
|
65
69
|
timeoutMs?: number;
|
|
66
|
-
|
|
70
|
+
/**
|
|
71
|
+
* 仅允许使用的工具白名单。
|
|
72
|
+
* 运行时通过 getTools() 获取全量工具列表,差集计算后转为 disallowedTools 传递给 CLI。
|
|
73
|
+
* 与 disallowedTools 互斥,同时设置时 onlyTools 优先。
|
|
74
|
+
*/
|
|
75
|
+
onlyTools?: string[];
|
|
76
|
+
/** 禁止使用的工具黑名单 */
|
|
67
77
|
disallowedTools?: string[];
|
|
68
78
|
mcpServers?: Record<string, McpServerConfig>;
|
|
69
79
|
maxTurns?: number;
|
|
@@ -180,6 +190,8 @@ interface IAgentAdapter {
|
|
|
180
190
|
/** 获取可用模型列表 */
|
|
181
191
|
listModels(): Promise<ModelInfo[]>;
|
|
182
192
|
abort(sessionId: string): void;
|
|
193
|
+
/** 获取当前可用的工具列表(可选实现,支持缓存) */
|
|
194
|
+
getTools?(force?: boolean): Promise<string[]>;
|
|
183
195
|
/** 删除会话及其资源(可选实现) */
|
|
184
196
|
deleteSession?(sessionId: string): Promise<void>;
|
|
185
197
|
dispose(): Promise<void>;
|
|
@@ -250,6 +262,23 @@ interface HealthCheckResult {
|
|
|
250
262
|
supported?: boolean;
|
|
251
263
|
warnings?: string[];
|
|
252
264
|
error?: string;
|
|
265
|
+
/** deep 模式下,模型是否真正响应 */
|
|
266
|
+
modelVerified?: boolean;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* checkBackend 的选项
|
|
270
|
+
*/
|
|
271
|
+
interface CheckBackendOptions {
|
|
272
|
+
/**
|
|
273
|
+
* 启用深度检测:在基础 CLI/版本检查通过后,向模型发送一条极短测试消息,
|
|
274
|
+
* 验证 Token/模型/配额是否真正可用。
|
|
275
|
+
* 默认 false(仅做 CLI 存在性 + 版本检查)。
|
|
276
|
+
*/
|
|
277
|
+
deep?: boolean;
|
|
278
|
+
/** deep 模式下使用的模型(可选,不传则用后端默认模型) */
|
|
279
|
+
model?: string;
|
|
280
|
+
/** deep 模式超时(毫秒),默认 15000 */
|
|
281
|
+
timeoutMs?: number;
|
|
253
282
|
}
|
|
254
283
|
/**
|
|
255
284
|
* Porygon 事件类型定义
|
|
@@ -306,7 +335,13 @@ declare class Porygon extends EventEmitter {
|
|
|
306
335
|
* 创建交互式多轮对话会话。
|
|
307
336
|
* 自动管理 sessionId 和 resume,对调用方透明。
|
|
308
337
|
*/
|
|
309
|
-
session(options?: Omit<PromptRequest, "prompt">): InteractiveSession
|
|
338
|
+
session(options?: Omit<PromptRequest, "prompt">): Promise<InteractiveSession>;
|
|
339
|
+
/**
|
|
340
|
+
* 获取当前可用的工具列表。
|
|
341
|
+
* 首次调用通过发起最小化对话从 system 事件中提取工具清单,结果会被缓存。
|
|
342
|
+
* @param force 是否强制刷新缓存
|
|
343
|
+
*/
|
|
344
|
+
getTools(force?: boolean): Promise<string[]>;
|
|
310
345
|
/**
|
|
311
346
|
* 注册拦截器
|
|
312
347
|
* @param direction 拦截方向
|
|
@@ -327,8 +362,9 @@ declare class Porygon extends EventEmitter {
|
|
|
327
362
|
/**
|
|
328
363
|
* 检查单个后端的健康状态
|
|
329
364
|
* @param backend 后端名称
|
|
365
|
+
* @param options 检测选项。传入 `{ deep: true }` 时会向模型发送一条测试消息验证可用性。
|
|
330
366
|
*/
|
|
331
|
-
checkBackend(backend: string): Promise<HealthCheckResult>;
|
|
367
|
+
checkBackend(backend: string, options?: CheckBackendOptions): Promise<HealthCheckResult>;
|
|
332
368
|
/**
|
|
333
369
|
* 对所有已注册后端进行健康检查。
|
|
334
370
|
* 返回扁平化结构,包含 version/supported/warnings 等字段。
|
|
@@ -365,6 +401,8 @@ declare class Porygon extends EventEmitter {
|
|
|
365
401
|
* - timeoutMs: request > defaults
|
|
366
402
|
* - maxTurns: request > defaults
|
|
367
403
|
* - cwd: request > backendConfig
|
|
404
|
+
* - disallowedTools: defaults + backendConfig + request 三层叠加去重
|
|
405
|
+
* - onlyTools: 通过 getTools() 获取全量列表,差集计算转为 disallowedTools(与 disallowedTools 互斥,onlyTools 优先)
|
|
368
406
|
* - appendSystemPrompt: **追加模式** — defaults + backendConfig + request 三层拼接(换行分隔)
|
|
369
407
|
* 但如果 request.systemPrompt 已设置(替换模式),则忽略所有 appendSystemPrompt
|
|
370
408
|
*
|
|
@@ -671,6 +709,8 @@ declare abstract class AbstractAgentAdapter implements IAgentAdapter {
|
|
|
671
709
|
*/
|
|
672
710
|
declare class ClaudeAdapter extends AbstractAgentAdapter {
|
|
673
711
|
readonly backend = "claude";
|
|
712
|
+
/** 工具列表缓存 */
|
|
713
|
+
private cachedTools;
|
|
674
714
|
/** CLI 命令名或路径 */
|
|
675
715
|
private get cliCommand();
|
|
676
716
|
/**
|
|
@@ -690,6 +730,12 @@ declare class ClaudeAdapter extends AbstractAgentAdapter {
|
|
|
690
730
|
* @param request 提示请求参数
|
|
691
731
|
*/
|
|
692
732
|
query(request: PromptRequest): AsyncGenerator<AgentMessage>;
|
|
733
|
+
/**
|
|
734
|
+
* 获取当前可用的工具列表。
|
|
735
|
+
* 首次调用通过发起最小化对话从 system 事件中提取 tools 字段,结果会被缓存。
|
|
736
|
+
* @param force 是否强制刷新缓存
|
|
737
|
+
*/
|
|
738
|
+
getTools(force?: boolean): Promise<string[]>;
|
|
693
739
|
/**
|
|
694
740
|
* 列出 Claude 会话
|
|
695
741
|
* @param options 查询选项
|
|
@@ -809,4 +855,4 @@ declare class OpenCodeAdapter extends AbstractAgentAdapter {
|
|
|
809
855
|
private getConfigPath;
|
|
810
856
|
}
|
|
811
857
|
|
|
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 };
|
|
858
|
+
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, type CheckBackendOptions, 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
|
@@ -92,6 +92,7 @@ var BackendConfigSchema = z.object({
|
|
|
92
92
|
apiKey: z.string().optional(),
|
|
93
93
|
interactive: z.boolean().optional(),
|
|
94
94
|
cliPath: z.string().optional(),
|
|
95
|
+
disallowedTools: z.array(z.string()).optional(),
|
|
95
96
|
options: z.record(z.string(), z.unknown()).optional()
|
|
96
97
|
});
|
|
97
98
|
var PorygonConfigSchema = z.object({
|
|
@@ -100,7 +101,8 @@ var PorygonConfigSchema = z.object({
|
|
|
100
101
|
defaults: z.object({
|
|
101
102
|
appendSystemPrompt: z.string().optional(),
|
|
102
103
|
timeoutMs: z.number().positive().optional(),
|
|
103
|
-
maxTurns: z.number().int().positive().optional()
|
|
104
|
+
maxTurns: z.number().int().positive().optional(),
|
|
105
|
+
disallowedTools: z.array(z.string()).optional()
|
|
104
106
|
}).optional(),
|
|
105
107
|
proxy: ProxyConfigSchema.optional()
|
|
106
108
|
});
|
|
@@ -817,14 +819,15 @@ function mapClaudeEvent(event, sessionId) {
|
|
|
817
819
|
return [];
|
|
818
820
|
}
|
|
819
821
|
if (isResultEvent(event)) {
|
|
822
|
+
const usage = event.usage;
|
|
820
823
|
return [{
|
|
821
824
|
...baseFields,
|
|
822
825
|
type: "result",
|
|
823
826
|
text: event.result,
|
|
824
|
-
costUsd: event.cost_usd,
|
|
827
|
+
costUsd: event.total_cost_usd ?? event.cost_usd,
|
|
825
828
|
durationMs: event.duration_ms,
|
|
826
|
-
inputTokens: event.input_tokens,
|
|
827
|
-
outputTokens: event.output_tokens
|
|
829
|
+
inputTokens: usage?.input_tokens ?? event.input_tokens,
|
|
830
|
+
outputTokens: usage?.output_tokens ?? event.output_tokens
|
|
828
831
|
}];
|
|
829
832
|
}
|
|
830
833
|
return [];
|
|
@@ -882,6 +885,8 @@ var CLAUDE_MODELS = [
|
|
|
882
885
|
];
|
|
883
886
|
var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
884
887
|
backend = "claude";
|
|
888
|
+
/** 工具列表缓存 */
|
|
889
|
+
cachedTools = null;
|
|
885
890
|
/** CLI 命令名或路径 */
|
|
886
891
|
get cliCommand() {
|
|
887
892
|
return this.config?.cliPath ?? "claude";
|
|
@@ -1006,6 +1011,40 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
1006
1011
|
this.processManager.removeEphemeral(sessionId);
|
|
1007
1012
|
}
|
|
1008
1013
|
}
|
|
1014
|
+
/**
|
|
1015
|
+
* 获取当前可用的工具列表。
|
|
1016
|
+
* 首次调用通过发起最小化对话从 system 事件中提取 tools 字段,结果会被缓存。
|
|
1017
|
+
* @param force 是否强制刷新缓存
|
|
1018
|
+
*/
|
|
1019
|
+
async getTools(force) {
|
|
1020
|
+
if (!force && this.cachedTools) {
|
|
1021
|
+
return this.cachedTools;
|
|
1022
|
+
}
|
|
1023
|
+
const DEFAULT_TIMEOUT_MS2 = 15e3;
|
|
1024
|
+
let tools = [];
|
|
1025
|
+
for await (const message of this.query({
|
|
1026
|
+
prompt: "hi",
|
|
1027
|
+
maxTurns: 1,
|
|
1028
|
+
timeoutMs: DEFAULT_TIMEOUT_MS2
|
|
1029
|
+
})) {
|
|
1030
|
+
const raw = message.raw;
|
|
1031
|
+
if (message.type === "system" && raw?.tools) {
|
|
1032
|
+
const rawTools = raw.tools;
|
|
1033
|
+
if (Array.isArray(rawTools)) {
|
|
1034
|
+
tools = rawTools.map((t) => {
|
|
1035
|
+
if (typeof t === "string") return t;
|
|
1036
|
+
if (typeof t === "object" && t !== null && "name" in t) {
|
|
1037
|
+
return String(t.name);
|
|
1038
|
+
}
|
|
1039
|
+
return String(t);
|
|
1040
|
+
});
|
|
1041
|
+
break;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
this.cachedTools = tools;
|
|
1046
|
+
return tools;
|
|
1047
|
+
}
|
|
1009
1048
|
/**
|
|
1010
1049
|
* 列出 Claude 会话
|
|
1011
1050
|
* @param options 查询选项
|
|
@@ -1134,11 +1173,6 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
1134
1173
|
if (appendPrompt) {
|
|
1135
1174
|
args.push("--append-system-prompt", appendPrompt);
|
|
1136
1175
|
}
|
|
1137
|
-
if (request.allowedTools && request.allowedTools.length > 0) {
|
|
1138
|
-
for (const tool of request.allowedTools) {
|
|
1139
|
-
args.push("--allowedTools", tool);
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
1176
|
if (request.disallowedTools && request.disallowedTools.length > 0) {
|
|
1143
1177
|
for (const tool of request.disallowedTools) {
|
|
1144
1178
|
args.push("--disallowedTools", tool);
|
|
@@ -1152,16 +1186,17 @@ var ClaudeAdapter = class extends AbstractAgentAdapter {
|
|
|
1152
1186
|
if (skipPerms) {
|
|
1153
1187
|
args.push("--dangerously-skip-permissions");
|
|
1154
1188
|
}
|
|
1155
|
-
if (request.mcpServers) {
|
|
1189
|
+
if (request.mcpServers && Object.keys(request.mcpServers).length > 0) {
|
|
1190
|
+
const mcpConfig = {};
|
|
1156
1191
|
for (const [name, config] of Object.entries(request.mcpServers)) {
|
|
1157
|
-
|
|
1192
|
+
mcpConfig[name] = {
|
|
1158
1193
|
command: config.command,
|
|
1159
1194
|
...config.args ? { args: config.args } : {},
|
|
1160
1195
|
...config.env ? { env: config.env } : {},
|
|
1161
1196
|
...config.url ? { url: config.url } : {}
|
|
1162
1197
|
};
|
|
1163
|
-
args.push("--mcp-server", `${name}=${JSON.stringify(serverSpec)}`);
|
|
1164
1198
|
}
|
|
1199
|
+
args.push("--mcp-config", JSON.stringify({ mcpServers: mcpConfig }));
|
|
1165
1200
|
}
|
|
1166
1201
|
return args;
|
|
1167
1202
|
}
|
|
@@ -1836,7 +1871,7 @@ var Porygon = class extends EventEmitter2 {
|
|
|
1836
1871
|
async *query(request) {
|
|
1837
1872
|
const adapter = this.getAdapter(request.backend);
|
|
1838
1873
|
const backendName = adapter.backend;
|
|
1839
|
-
const mergedRequest = this.mergeRequest(request, backendName);
|
|
1874
|
+
const mergedRequest = await this.mergeRequest(request, backendName);
|
|
1840
1875
|
const processedPrompt = await this.interceptors.processInput(
|
|
1841
1876
|
mergedRequest.prompt,
|
|
1842
1877
|
{ backend: backendName, sessionId: mergedRequest.resume }
|
|
@@ -1878,10 +1913,10 @@ var Porygon = class extends EventEmitter2 {
|
|
|
1878
1913
|
* 创建交互式多轮对话会话。
|
|
1879
1914
|
* 自动管理 sessionId 和 resume,对调用方透明。
|
|
1880
1915
|
*/
|
|
1881
|
-
session(options) {
|
|
1916
|
+
async session(options) {
|
|
1882
1917
|
const backend = options?.backend ?? this.config.defaultBackend ?? "claude";
|
|
1883
1918
|
const adapter = this.getAdapter(backend);
|
|
1884
|
-
const merged = this.mergeRequest({ ...options, prompt: "" }, backend);
|
|
1919
|
+
const merged = await this.mergeRequest({ ...options, prompt: "" }, backend);
|
|
1885
1920
|
const { prompt: _, ...baseRequest } = merged;
|
|
1886
1921
|
return new InteractiveSession(
|
|
1887
1922
|
crypto.randomUUID(),
|
|
@@ -1889,6 +1924,16 @@ var Porygon = class extends EventEmitter2 {
|
|
|
1889
1924
|
baseRequest
|
|
1890
1925
|
);
|
|
1891
1926
|
}
|
|
1927
|
+
/**
|
|
1928
|
+
* 获取当前可用的工具列表。
|
|
1929
|
+
* 首次调用通过发起最小化对话从 system 事件中提取工具清单,结果会被缓存。
|
|
1930
|
+
* @param force 是否强制刷新缓存
|
|
1931
|
+
*/
|
|
1932
|
+
async getTools(force) {
|
|
1933
|
+
const adapter = this.getAdapter();
|
|
1934
|
+
if (!adapter.getTools) return [];
|
|
1935
|
+
return adapter.getTools(force);
|
|
1936
|
+
}
|
|
1892
1937
|
/**
|
|
1893
1938
|
* 注册拦截器
|
|
1894
1939
|
* @param direction 拦截方向
|
|
@@ -1915,8 +1960,9 @@ var Porygon = class extends EventEmitter2 {
|
|
|
1915
1960
|
/**
|
|
1916
1961
|
* 检查单个后端的健康状态
|
|
1917
1962
|
* @param backend 后端名称
|
|
1963
|
+
* @param options 检测选项。传入 `{ deep: true }` 时会向模型发送一条测试消息验证可用性。
|
|
1918
1964
|
*/
|
|
1919
|
-
async checkBackend(backend) {
|
|
1965
|
+
async checkBackend(backend, options) {
|
|
1920
1966
|
const adapter = this.getAdapter(backend);
|
|
1921
1967
|
try {
|
|
1922
1968
|
const available = await adapter.isAvailable();
|
|
@@ -1935,6 +1981,25 @@ var Porygon = class extends EventEmitter2 {
|
|
|
1935
1981
|
if (!compat.supported) {
|
|
1936
1982
|
this.emit("health:degraded", backend, compat.warnings.join("; "));
|
|
1937
1983
|
}
|
|
1984
|
+
if (options?.deep) {
|
|
1985
|
+
try {
|
|
1986
|
+
const response = await this.run({
|
|
1987
|
+
prompt: "Reply with exactly: ok",
|
|
1988
|
+
backend,
|
|
1989
|
+
model: options.model,
|
|
1990
|
+
systemPrompt: "You are a health check probe. Reply with exactly one word: ok",
|
|
1991
|
+
timeoutMs: options.timeoutMs ?? 15e3,
|
|
1992
|
+
maxTurns: 1
|
|
1993
|
+
});
|
|
1994
|
+
result.modelVerified = typeof response === "string" && response.length > 0;
|
|
1995
|
+
} catch (err) {
|
|
1996
|
+
result.modelVerified = false;
|
|
1997
|
+
result.warnings = [
|
|
1998
|
+
...result.warnings || [],
|
|
1999
|
+
`\u6A21\u578B\u9A8C\u8BC1\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`
|
|
2000
|
+
];
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
1938
2003
|
return result;
|
|
1939
2004
|
} catch (err) {
|
|
1940
2005
|
return {
|
|
@@ -2014,6 +2079,8 @@ var Porygon = class extends EventEmitter2 {
|
|
|
2014
2079
|
* - timeoutMs: request > defaults
|
|
2015
2080
|
* - maxTurns: request > defaults
|
|
2016
2081
|
* - cwd: request > backendConfig
|
|
2082
|
+
* - disallowedTools: defaults + backendConfig + request 三层叠加去重
|
|
2083
|
+
* - onlyTools: 通过 getTools() 获取全量列表,差集计算转为 disallowedTools(与 disallowedTools 互斥,onlyTools 优先)
|
|
2017
2084
|
* - appendSystemPrompt: **追加模式** — defaults + backendConfig + request 三层拼接(换行分隔)
|
|
2018
2085
|
* 但如果 request.systemPrompt 已设置(替换模式),则忽略所有 appendSystemPrompt
|
|
2019
2086
|
*
|
|
@@ -2021,7 +2088,7 @@ var Porygon = class extends EventEmitter2 {
|
|
|
2021
2088
|
* @param backend 后端名称
|
|
2022
2089
|
* @returns 合并后的请求
|
|
2023
2090
|
*/
|
|
2024
|
-
mergeRequest(request, backend) {
|
|
2091
|
+
async mergeRequest(request, backend) {
|
|
2025
2092
|
const backendConfig = this.config.backends?.[backend];
|
|
2026
2093
|
const defaults = this.config.defaults;
|
|
2027
2094
|
const appendParts = [];
|
|
@@ -2034,12 +2101,28 @@ var Porygon = class extends EventEmitter2 {
|
|
|
2034
2101
|
if (request.appendSystemPrompt) {
|
|
2035
2102
|
appendParts.push(request.appendSystemPrompt);
|
|
2036
2103
|
}
|
|
2104
|
+
let mergedDisallowedTools;
|
|
2105
|
+
if (request.onlyTools) {
|
|
2106
|
+
const adapter = this.getAdapter(backend);
|
|
2107
|
+
const allTools = adapter.getTools ? await adapter.getTools() : [];
|
|
2108
|
+
const allowSet = new Set(request.onlyTools);
|
|
2109
|
+
const disallowed = allTools.filter((t) => !allowSet.has(t));
|
|
2110
|
+
mergedDisallowedTools = disallowed.length > 0 ? disallowed : void 0;
|
|
2111
|
+
} else {
|
|
2112
|
+
const disallowParts = [
|
|
2113
|
+
...defaults?.disallowedTools ?? [],
|
|
2114
|
+
...backendConfig?.disallowedTools ?? [],
|
|
2115
|
+
...request.disallowedTools ?? []
|
|
2116
|
+
];
|
|
2117
|
+
mergedDisallowedTools = disallowParts.length > 0 ? [...new Set(disallowParts)] : void 0;
|
|
2118
|
+
}
|
|
2037
2119
|
return {
|
|
2038
2120
|
...request,
|
|
2039
2121
|
model: request.model ?? backendConfig?.model,
|
|
2040
2122
|
timeoutMs: request.timeoutMs ?? defaults?.timeoutMs,
|
|
2041
2123
|
maxTurns: request.maxTurns ?? defaults?.maxTurns,
|
|
2042
2124
|
cwd: request.cwd ?? backendConfig?.cwd,
|
|
2125
|
+
disallowedTools: mergedDisallowedTools,
|
|
2043
2126
|
appendSystemPrompt: request.systemPrompt ? void 0 : appendParts.length > 0 ? appendParts.join("\n") : void 0
|
|
2044
2127
|
};
|
|
2045
2128
|
}
|