@downcity/agent 1.1.108 → 1.1.113
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/bin/agent/remote/RemoteAgent.d.ts +9 -1
- package/bin/agent/remote/RemoteAgent.d.ts.map +1 -1
- package/bin/agent/remote/RemoteAgent.js +22 -0
- package/bin/agent/remote/RemoteAgent.js.map +1 -1
- package/bin/agent/remote/RemoteTransport.d.ts +3 -1
- package/bin/agent/remote/RemoteTransport.d.ts.map +1 -1
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts +2 -1
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts.map +1 -1
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.js +26 -0
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.js.map +1 -1
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts +2 -1
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts.map +1 -1
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.js +7 -0
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.js.map +1 -1
- package/bin/executor/composer/system/default/assets/core.prompt.d.ts +1 -1
- package/bin/executor/composer/system/default/assets/core.prompt.d.ts.map +1 -1
- package/bin/executor/composer/system/default/assets/core.prompt.js +1 -1
- package/bin/executor/composer/system/default/assets/core.prompt.js.map +1 -1
- package/bin/executor/tools/shell/ShellToolBridge.d.ts.map +1 -1
- package/bin/executor/tools/shell/ShellToolBridge.js +22 -4
- package/bin/executor/tools/shell/ShellToolBridge.js.map +1 -1
- package/bin/executor/tools/shell/ShellToolDefinition.d.ts +2 -0
- package/bin/executor/tools/shell/ShellToolDefinition.d.ts.map +1 -1
- package/bin/executor/tools/shell/ShellToolDefinition.js +14 -4
- package/bin/executor/tools/shell/ShellToolDefinition.js.map +1 -1
- package/bin/executor/tools/shell/ShellToolSchemas.d.ts +11 -0
- package/bin/executor/tools/shell/ShellToolSchemas.d.ts.map +1 -1
- package/bin/executor/tools/shell/ShellToolSchemas.js +17 -0
- package/bin/executor/tools/shell/ShellToolSchemas.js.map +1 -1
- package/bin/executor/tools/shell/types/Shell.d.ts +18 -0
- package/bin/executor/tools/shell/types/Shell.d.ts.map +1 -1
- package/bin/executor/tools/shell/types/ShellPlugin.d.ts +34 -0
- package/bin/executor/tools/shell/types/ShellPlugin.d.ts.map +1 -1
- package/bin/index.d.ts +1 -1
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js.map +1 -1
- package/bin/sandbox/LinuxBubblewrapSandbox.d.ts.map +1 -1
- package/bin/sandbox/LinuxBubblewrapSandbox.js +1 -0
- package/bin/sandbox/LinuxBubblewrapSandbox.js.map +1 -1
- package/bin/sandbox/MacOsSeatbeltSandbox.d.ts.map +1 -1
- package/bin/sandbox/MacOsSeatbeltSandbox.js +1 -0
- package/bin/sandbox/MacOsSeatbeltSandbox.js.map +1 -1
- package/bin/sandbox/SandboxRunner.d.ts +2 -0
- package/bin/sandbox/SandboxRunner.d.ts.map +1 -1
- package/bin/sandbox/SandboxRunner.js +14 -0
- package/bin/sandbox/SandboxRunner.js.map +1 -1
- package/bin/sandbox/UnrestrictedSandbox.d.ts +16 -0
- package/bin/sandbox/UnrestrictedSandbox.d.ts.map +1 -0
- package/bin/sandbox/UnrestrictedSandbox.js +39 -0
- package/bin/sandbox/UnrestrictedSandbox.js.map +1 -0
- package/bin/sandbox/types/SandboxRuntime.d.ts +9 -1
- package/bin/sandbox/types/SandboxRuntime.d.ts.map +1 -1
- package/bin/session/Session.d.ts.map +1 -1
- package/bin/session/Session.js +3 -0
- package/bin/session/Session.js.map +1 -1
- package/bin/session/services/SessionTurnService.d.ts.map +1 -1
- package/bin/session/services/SessionTurnService.js +1 -0
- package/bin/session/services/SessionTurnService.js.map +1 -1
- package/bin/session/storage/RuntimeSessionPort.d.ts +5 -1
- package/bin/session/storage/RuntimeSessionPort.d.ts.map +1 -1
- package/bin/session/storage/RuntimeSessionPort.js +3 -0
- package/bin/session/storage/RuntimeSessionPort.js.map +1 -1
- package/bin/types/agent/AgentTypes.d.ts +1 -0
- package/bin/types/agent/AgentTypes.d.ts.map +1 -1
- package/bin/types/agent/RemoteAgentPluginAction.d.ts +46 -0
- package/bin/types/agent/RemoteAgentPluginAction.d.ts.map +1 -0
- package/bin/types/agent/RemoteAgentPluginAction.js +9 -0
- package/bin/types/agent/RemoteAgentPluginAction.js.map +1 -0
- package/bin/types/executor/SessionRunContext.d.ts +8 -0
- package/bin/types/executor/SessionRunContext.d.ts.map +1 -1
- package/bin/types/runtime/agent/AgentContext.d.ts +9 -1
- package/bin/types/runtime/agent/AgentContext.d.ts.map +1 -1
- package/bin/types/sdk/AgentSessionEvent.d.ts +97 -3
- package/bin/types/sdk/AgentSessionEvent.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/agent/remote/RemoteAgent.ts +27 -0
- package/src/agent/remote/RemoteTransport.ts +6 -0
- package/src/agent/remote/transports/HttpRemoteAgentTransport.ts +38 -0
- package/src/agent/remote/transports/RpcRemoteAgentTransport.ts +12 -0
- package/src/executor/composer/system/default/assets/core.prompt.ts +1 -1
- package/src/executor/composer/system/default/assets/core.prompt.ts.txt +5 -2
- package/src/executor/tools/shell/ShellToolBridge.ts +24 -4
- package/src/executor/tools/shell/ShellToolDefinition.ts +17 -2
- package/src/executor/tools/shell/ShellToolSchemas.ts +19 -0
- package/src/executor/tools/shell/types/Shell.ts +20 -0
- package/src/executor/tools/shell/types/ShellPlugin.ts +37 -0
- package/src/index.ts +2 -0
- package/src/sandbox/LinuxBubblewrapSandbox.ts +1 -0
- package/src/sandbox/MacOsSeatbeltSandbox.ts +1 -0
- package/src/sandbox/SandboxRunner.ts +17 -0
- package/src/sandbox/UnrestrictedSandbox.ts +53 -0
- package/src/sandbox/types/SandboxRuntime.ts +11 -1
- package/src/session/Session.ts +3 -0
- package/src/session/services/SessionTurnService.ts +1 -0
- package/src/session/storage/RuntimeSessionPort.ts +8 -0
- package/src/types/agent/AgentTypes.ts +4 -0
- package/src/types/agent/RemoteAgentPluginAction.ts +52 -0
- package/src/types/executor/SessionRunContext.ts +9 -0
- package/src/types/runtime/agent/AgentContext.ts +9 -0
- package/src/types/sdk/AgentSessionEvent.ts +118 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -15,6 +15,8 @@ import type {
|
|
|
15
15
|
AgentSessionInfo,
|
|
16
16
|
AgentSessionSummaryPage,
|
|
17
17
|
AgentSessionSystemSnapshot,
|
|
18
|
+
RemoteAgentPluginActionInput,
|
|
19
|
+
RemoteAgentPluginActionResult,
|
|
18
20
|
} from "@/types/agent/AgentTypes.js";
|
|
19
21
|
import type { AgentSessionEvent } from "@/types/sdk/AgentSessionEvent.js";
|
|
20
22
|
import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
|
|
@@ -239,6 +241,29 @@ export class HttpRemoteAgentTransport implements RemoteAgentTransport {
|
|
|
239
241
|
}
|
|
240
242
|
return payload.page;
|
|
241
243
|
}
|
|
244
|
+
|
|
245
|
+
async run_plugin_action(
|
|
246
|
+
input: RemoteAgentPluginActionInput,
|
|
247
|
+
): Promise<RemoteAgentPluginActionResult> {
|
|
248
|
+
const payload = await read_http_action_json<RemoteAgentPluginActionResult>(
|
|
249
|
+
`${this.base_url}/api/plugins/action`,
|
|
250
|
+
{
|
|
251
|
+
method: "POST",
|
|
252
|
+
headers: this.headers({
|
|
253
|
+
"Content-Type": "application/json",
|
|
254
|
+
}),
|
|
255
|
+
body: JSON.stringify({
|
|
256
|
+
pluginName: input.plugin,
|
|
257
|
+
actionName: input.action,
|
|
258
|
+
...(input.payload !== undefined ? { payload: input.payload } : {}),
|
|
259
|
+
}),
|
|
260
|
+
},
|
|
261
|
+
);
|
|
262
|
+
if (typeof payload.success !== "boolean") {
|
|
263
|
+
throw new Error("Remote plugin action returned an invalid response");
|
|
264
|
+
}
|
|
265
|
+
return payload;
|
|
266
|
+
}
|
|
242
267
|
}
|
|
243
268
|
|
|
244
269
|
async function read_http_json<T>(input: string, init?: RequestInit): Promise<T> {
|
|
@@ -251,6 +276,19 @@ async function read_http_json<T>(input: string, init?: RequestInit): Promise<T>
|
|
|
251
276
|
return payload;
|
|
252
277
|
}
|
|
253
278
|
|
|
279
|
+
async function read_http_action_json<T extends { success?: boolean }>(
|
|
280
|
+
input: string,
|
|
281
|
+
init?: RequestInit,
|
|
282
|
+
): Promise<T> {
|
|
283
|
+
const response = await fetch(input, init);
|
|
284
|
+
const payload = (await response.json().catch(() => ({}))) as T;
|
|
285
|
+
if (!response.ok && typeof payload.success !== "boolean") {
|
|
286
|
+
const message = extract_error_message(payload);
|
|
287
|
+
throw new Error(message || `HTTP ${response.status}`);
|
|
288
|
+
}
|
|
289
|
+
return payload;
|
|
290
|
+
}
|
|
291
|
+
|
|
254
292
|
async function consume_http_event_stream(params: {
|
|
255
293
|
body: ReadableStream<Uint8Array>;
|
|
256
294
|
abort_controller: AbortController;
|
|
@@ -15,6 +15,8 @@ import type {
|
|
|
15
15
|
AgentSessionInfo,
|
|
16
16
|
AgentSessionSummaryPage,
|
|
17
17
|
AgentSessionSystemSnapshot,
|
|
18
|
+
RemoteAgentPluginActionInput,
|
|
19
|
+
RemoteAgentPluginActionResult,
|
|
18
20
|
} from "@/types/agent/AgentTypes.js";
|
|
19
21
|
import type { AgentSessionEvent } from "@/types/sdk/AgentSessionEvent.js";
|
|
20
22
|
import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
|
|
@@ -101,6 +103,16 @@ export class RpcRemoteAgentTransport implements RemoteAgentTransport {
|
|
|
101
103
|
return await this.client.list_sessions(input);
|
|
102
104
|
}
|
|
103
105
|
|
|
106
|
+
async run_plugin_action(
|
|
107
|
+
input: RemoteAgentPluginActionInput,
|
|
108
|
+
): Promise<RemoteAgentPluginActionResult> {
|
|
109
|
+
return await this.client.run_internal_plugin_action({
|
|
110
|
+
plugin_name: input.plugin,
|
|
111
|
+
action_name: input.action,
|
|
112
|
+
...(input.payload !== undefined ? { payload: input.payload } : {}),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
104
116
|
async close(): Promise<void> {
|
|
105
117
|
await this.client.close();
|
|
106
118
|
}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// Source: src/executor/composer/system/default/assets/core.prompt.ts.txt
|
|
7
|
-
const TEXT_MODULE_CONTENT = "你拥有且仅拥有当前项目 {{project_path}} 的使用权和修改权。当前年份是 {{current_year}} 年。\n1. `.downcity/` 是 Downcity 的运行时数据目录(通常不需要你手动读取/修改;系统会自动写入与注入)。结构与逻辑如下:\n - `.downcity/agents/<agentId>/sessions/` 是会话消息。\n - `.downcity/memory/` 是中长期记忆。\n - `.downcity/profile/Primary.md`、`.downcity/profile/other.md`:全局 profile 记忆;存在时会自动作为 system prompt 注入。\n - `.downcity/public/`:对外静态资源目录,通过 `GET /downcity/public/<path>` 访问;用于给外部访问的路径。不要存放敏感信息,Agent HTTP gateway 会把 `.downcity/public/` 暴露为 HTTP 静态资源:`GET /downcity/public/<path>`,你可以把该 URL 发给用户用于下载/查看生成的文件(注意不要暴露敏感信息)。\n - `.downcity/logs/<YYYY-MM-DD>.jsonl`:运行日志(JSONL);用于排查问题,避免把原始日志整段贴给用户。\n - `.downcity/.cache/`:幂等/去重缓存(ingress/egress);不要手动改。\n - `.downcity/.debug/`:调试产物(托管进程 pid/log/meta、适配器事件抓取等);仅在排查问题时查看。\n - `.downcity/data/`:小型持久化数据(预留)。\n - `.downcity/task/`:Task 目录。\n - `.downcity/sandbox/`:当前 agent 的本地命令执行 sandbox HOME/cache/tmp;shell 与 script 命令会共享它。\n2. PROFILE.md + SOUL.md + downcity.json 是你的一些配置文件,你不需要读取。\n\n# 最重要\n【关于命令执行工具】(重要)\n- 短命令、一次性命令优先使用 `shell_exec`。\n- 长任务、需要中途查状态、需要 stdin 交互时,使用 `shell_start` / `shell_status` / `shell_read` / `shell_write` / `shell_wait` / `shell_close`。\n- 先用 `shell_start` 启动命令并拿到 `shell_id`。\n- `shell_id` 是 shell 会话标识;它不是 chat `session_id`。\n- 长任务期间,优先使用 `shell_status` 查询进度,或使用 `shell_wait` 等待状态变化;不要自己写高频空轮询循环。\n- 只有在确实需要原始增量输出时,才使用 `shell_read` 按 `from_cursor` 继续读取。\n- 需要向进程 stdin 输入内容时,使用 `shell_write`。\n- 命令会话完成后若不再需要,使用 `shell_close` 主动释放资源。\n- 不要把原始超长 shell 输出直接转发给用户,应先总结。\n- shell
|
|
7
|
+
const TEXT_MODULE_CONTENT = "你拥有且仅拥有当前项目 {{project_path}} 的使用权和修改权。当前年份是 {{current_year}} 年。\n1. `.downcity/` 是 Downcity 的运行时数据目录(通常不需要你手动读取/修改;系统会自动写入与注入)。结构与逻辑如下:\n - `.downcity/agents/<agentId>/sessions/` 是会话消息。\n - `.downcity/memory/` 是中长期记忆。\n - `.downcity/profile/Primary.md`、`.downcity/profile/other.md`:全局 profile 记忆;存在时会自动作为 system prompt 注入。\n - `.downcity/public/`:对外静态资源目录,通过 `GET /downcity/public/<path>` 访问;用于给外部访问的路径。不要存放敏感信息,Agent HTTP gateway 会把 `.downcity/public/` 暴露为 HTTP 静态资源:`GET /downcity/public/<path>`,你可以把该 URL 发给用户用于下载/查看生成的文件(注意不要暴露敏感信息)。\n - `.downcity/logs/<YYYY-MM-DD>.jsonl`:运行日志(JSONL);用于排查问题,避免把原始日志整段贴给用户。\n - `.downcity/.cache/`:幂等/去重缓存(ingress/egress);不要手动改。\n - `.downcity/.debug/`:调试产物(托管进程 pid/log/meta、适配器事件抓取等);仅在排查问题时查看。\n - `.downcity/data/`:小型持久化数据(预留)。\n - `.downcity/task/`:Task 目录。\n - `.downcity/sandbox/`:当前 agent 的本地命令执行 sandbox HOME/cache/tmp;shell 与 script 命令会共享它。\n2. PROFILE.md + SOUL.md + downcity.json 是你的一些配置文件,你不需要读取。\n\n# 最重要\n【关于命令执行工具】(重要)\n- 短命令、一次性命令优先使用 `shell_exec`。\n- 长任务、需要中途查状态、需要 stdin 交互时,使用 `shell_start` / `shell_status` / `shell_read` / `shell_write` / `shell_wait` / `shell_close`。\n- 先用 `shell_start` 启动命令并拿到 `shell_id`。\n- `shell_id` 是 shell 会话标识;它不是 chat `session_id`。\n- 长任务期间,优先使用 `shell_status` 查询进度,或使用 `shell_wait` 等待状态变化;不要自己写高频空轮询循环。\n- 只有在确实需要原始增量输出时,才使用 `shell_read` 按 `from_cursor` 继续读取。\n- 需要向进程 stdin 输入内容时,使用 `shell_write`。\n- 向 unrestricted shell session 使用 `shell_write` 时,每一次写入都必须提供清楚的 `reason`,并等待用户确认;`shell_start` 的审批只授权启动进程,不授权后续 stdin 写入。\n- 命令会话完成后若不再需要,使用 `shell_close` 主动释放资源。\n- 不要把原始超长 shell 输出直接转发给用户,应先总结。\n- shell 命令默认在 Safe Sandbox 中执行:项目目录可读写,网络可用,HOME 指向 `.downcity/sandbox/`,真实用户 HOME 与系统目录不可写。\n- 安装 Python 依赖时优先使用项目内 `.venv`,不要使用 `pip install --user`。\n- 需要全局安装、写宿主目录、访问宿主级能力时,可以请求 `sandbox: \"unrestricted\"`;必须提供清楚的 `reason`,等待用户确认后才能执行。\n- 不要尝试 `sudo`、Xcode Command Line Tools 安装、修改 SSH/keychain/shell profile,或执行明显破坏性命令;这些请求即使使用 unrestricted sandbox 也会被拒绝。\n- 用户拒绝 unrestricted sandbox 请求后,不要反复请求同一命令,应解释影响并给出项目内替代方案。\n- 下载模型、工具缓存、临时状态应自然落在 `.downcity/sandbox/` 或项目目录中,不要假设可复用真实用户缓存。\n\n# 默认决策与澄清\n- 默认先执行,再沟通:对低风险、可回滚、用户意图已经足够明显的请求,优先基于当前日期、时区、聊天上下文与常见默认值直接执行,不要在事件标题、默认平台、显然的时间表达上反复追问。\n- 只有当“缺失信息会实质改变结果”时才追问;例如:会影响日期/对象/金额/账户/发送目标,或会触发不可逆、高风险、涉隐私操作。\n- 处理时间表达时,优先使用当前环境提供的 `current_date`、`current_time` 与 `timezone`;如果入站 `<info>` 明确提供了 `user_timezone`,则优先按 `user_timezone` 解析,否则按 runtime clock 的 `timezone` 解析。像“今天/明天/下午两点/提前两小时”这类表达,应先解析为绝对时间,再执行,并在回复里明确写出绝对日期时间。\n- 当任务依赖外部权限、系统能力或第三方连接(如日历、提醒事项、聊天渠道、系统授权)时,先探测可用性,再决定是否承诺“我来创建/发送/写入”。\n- 如果探测结果显示被系统权限、宿主环境或连接状态阻塞,要直接说明真实阻塞点和下一步,而不是先给出“可以,我来做”的承诺后再多轮追问。\n- 若已经有足够信息可以一次完成多个低风险默认动作,应直接完成,并在结果里简短说明采用了哪些默认假设。\n\n# 很重要\n\n安全与边界\n- 不要执行破坏性命令(如 `rm -rf`、`git reset --hard`)除非用户明确要求。\n- 遇到 API Key、Token、Secret、环境变量、bot 凭据等密钥管理问题时,优先指导用户使用 Console(如 `Global / Env`、`Global / Channel Accounts`)维护,不要要求用户把密钥明文直接发送到当前聊天里。\n- 密钥列表能力只能返回已配置的 key 名与描述,不会返回密钥值。不要让用户把密钥“发给你自己”或继续尝试获取明文。\n";
|
|
8
8
|
|
|
9
9
|
export default TEXT_MODULE_CONTENT;
|
|
@@ -21,11 +21,14 @@
|
|
|
21
21
|
- 长任务期间,优先使用 `shell_status` 查询进度,或使用 `shell_wait` 等待状态变化;不要自己写高频空轮询循环。
|
|
22
22
|
- 只有在确实需要原始增量输出时,才使用 `shell_read` 按 `from_cursor` 继续读取。
|
|
23
23
|
- 需要向进程 stdin 输入内容时,使用 `shell_write`。
|
|
24
|
+
- 向 unrestricted shell session 使用 `shell_write` 时,每一次写入都必须提供清楚的 `reason`,并等待用户确认;`shell_start` 的审批只授权启动进程,不授权后续 stdin 写入。
|
|
24
25
|
- 命令会话完成后若不再需要,使用 `shell_close` 主动释放资源。
|
|
25
26
|
- 不要把原始超长 shell 输出直接转发给用户,应先总结。
|
|
26
|
-
- shell
|
|
27
|
+
- shell 命令默认在 Safe Sandbox 中执行:项目目录可读写,网络可用,HOME 指向 `.downcity/sandbox/`,真实用户 HOME 与系统目录不可写。
|
|
27
28
|
- 安装 Python 依赖时优先使用项目内 `.venv`,不要使用 `pip install --user`。
|
|
28
|
-
-
|
|
29
|
+
- 需要全局安装、写宿主目录、访问宿主级能力时,可以请求 `sandbox: "unrestricted"`;必须提供清楚的 `reason`,等待用户确认后才能执行。
|
|
30
|
+
- 不要尝试 `sudo`、Xcode Command Line Tools 安装、修改 SSH/keychain/shell profile,或执行明显破坏性命令;这些请求即使使用 unrestricted sandbox 也会被拒绝。
|
|
31
|
+
- 用户拒绝 unrestricted sandbox 请求后,不要反复请求同一命令,应解释影响并给出项目内替代方案。
|
|
29
32
|
- 下载模型、工具缓存、临时状态应自然落在 `.downcity/sandbox/` 或项目目录中,不要假设可复用真实用户缓存。
|
|
30
33
|
|
|
31
34
|
# 默认决策与澄清
|
|
@@ -205,13 +205,23 @@ export function flattenShellActionResponse(params: {
|
|
|
205
205
|
}): JsonObject {
|
|
206
206
|
const shell = params.response.shell;
|
|
207
207
|
const chunk = params.response.chunk;
|
|
208
|
+
const exitCode = typeof shell.exitCode === "number" ? shell.exitCode : null;
|
|
209
|
+
const success =
|
|
210
|
+
shell.approvalStatus !== "denied" &&
|
|
211
|
+
shell.approvalStatus !== "expired" &&
|
|
212
|
+
(exitCode === null || exitCode === 0);
|
|
208
213
|
return {
|
|
209
|
-
success
|
|
214
|
+
success,
|
|
210
215
|
shell_id: shell.shellId,
|
|
211
216
|
status: shell.status,
|
|
212
217
|
cmd: shell.cmd,
|
|
213
218
|
cwd: shell.cwd,
|
|
214
219
|
sandboxed: shell.sandboxed === true,
|
|
220
|
+
sandbox: shell.sandboxMode || (shell.sandboxed === false ? "unrestricted" : "safe"),
|
|
221
|
+
approval_status: shell.approvalStatus || null,
|
|
222
|
+
approval_id: shell.approvalId || null,
|
|
223
|
+
approval_reason: shell.approvalReason || null,
|
|
224
|
+
stdin_writable: shell.stdinWritable !== false,
|
|
215
225
|
sandbox_backend: shell.sandboxBackend || null,
|
|
216
226
|
sandbox_network_mode: shell.sandboxNetworkMode || null,
|
|
217
227
|
sandbox_dir: shell.sandboxDir || null,
|
|
@@ -223,7 +233,7 @@ export function flattenShellActionResponse(params: {
|
|
|
223
233
|
started_at: shell.startedAt,
|
|
224
234
|
updated_at: shell.updatedAt,
|
|
225
235
|
ended_at: typeof shell.endedAt === "number" ? shell.endedAt : null,
|
|
226
|
-
exit_code:
|
|
236
|
+
exit_code: exitCode,
|
|
227
237
|
output: chunk?.output || "",
|
|
228
238
|
start_cursor: typeof chunk?.startCursor === "number" ? chunk.startCursor : null,
|
|
229
239
|
end_cursor: typeof chunk?.endCursor === "number" ? chunk.endCursor : null,
|
|
@@ -257,19 +267,29 @@ export function flattenShellExecResponse(params: {
|
|
|
257
267
|
}): JsonObject {
|
|
258
268
|
const shell = params.response.shell;
|
|
259
269
|
const chunk = params.response.chunk;
|
|
270
|
+
const exitCode = typeof shell.exitCode === "number" ? shell.exitCode : null;
|
|
271
|
+
const success =
|
|
272
|
+
shell.approvalStatus !== "denied" &&
|
|
273
|
+
shell.approvalStatus !== "expired" &&
|
|
274
|
+
(exitCode === null || exitCode === 0);
|
|
260
275
|
return {
|
|
261
|
-
success
|
|
276
|
+
success,
|
|
262
277
|
status: shell.status,
|
|
263
278
|
cmd: shell.cmd,
|
|
264
279
|
cwd: shell.cwd,
|
|
265
280
|
sandboxed: shell.sandboxed === true,
|
|
281
|
+
sandbox: shell.sandboxMode || (shell.sandboxed === false ? "unrestricted" : "safe"),
|
|
282
|
+
approval_status: shell.approvalStatus || null,
|
|
283
|
+
approval_id: shell.approvalId || null,
|
|
284
|
+
approval_reason: shell.approvalReason || null,
|
|
285
|
+
stdin_writable: shell.stdinWritable !== false,
|
|
266
286
|
sandbox_backend: shell.sandboxBackend || null,
|
|
267
287
|
sandbox_network_mode: shell.sandboxNetworkMode || null,
|
|
268
288
|
sandbox_dir: shell.sandboxDir || null,
|
|
269
289
|
sandbox_home_dir: shell.sandboxHomeDir || null,
|
|
270
290
|
sandbox_tmp_dir: shell.sandboxTmpDir || null,
|
|
271
291
|
sandbox_cache_dir: shell.sandboxCacheDir || null,
|
|
272
|
-
exit_code:
|
|
292
|
+
exit_code: exitCode,
|
|
273
293
|
output: chunk?.output || "",
|
|
274
294
|
original_chars: chunk?.originalChars ?? 0,
|
|
275
295
|
original_lines: chunk?.originalLines ?? 0,
|
|
@@ -85,6 +85,8 @@ export const shell_start = tool({
|
|
|
85
85
|
inline_wait_ms = 1200,
|
|
86
86
|
max_output_tokens,
|
|
87
87
|
auto_notify_on_exit,
|
|
88
|
+
sandbox = "safe",
|
|
89
|
+
reason,
|
|
88
90
|
}: ShellStartInput) => {
|
|
89
91
|
const startedAt = Date.now();
|
|
90
92
|
|
|
@@ -99,6 +101,8 @@ export const shell_start = tool({
|
|
|
99
101
|
inline_wait_ms,
|
|
100
102
|
max_output_tokens: max_output_tokens ?? null,
|
|
101
103
|
auto_notify_on_exit: auto_notify_on_exit ?? null,
|
|
104
|
+
sandbox,
|
|
105
|
+
reason: reason || "",
|
|
102
106
|
}),
|
|
103
107
|
);
|
|
104
108
|
|
|
@@ -128,6 +132,8 @@ export const shell_start = tool({
|
|
|
128
132
|
...(typeof auto_notify_on_exit === "boolean"
|
|
129
133
|
? { autoNotifyOnExit: auto_notify_on_exit }
|
|
130
134
|
: {}),
|
|
135
|
+
sandbox,
|
|
136
|
+
...(reason ? { reason } : {}),
|
|
131
137
|
},
|
|
132
138
|
});
|
|
133
139
|
|
|
@@ -173,6 +179,8 @@ export const shell_exec = tool({
|
|
|
173
179
|
login = true,
|
|
174
180
|
timeout_ms = 60000,
|
|
175
181
|
max_output_tokens,
|
|
182
|
+
sandbox = "safe",
|
|
183
|
+
reason,
|
|
176
184
|
}: ShellExecInput) => {
|
|
177
185
|
const startedAt = Date.now();
|
|
178
186
|
|
|
@@ -186,6 +194,8 @@ export const shell_exec = tool({
|
|
|
186
194
|
login,
|
|
187
195
|
timeout_ms,
|
|
188
196
|
max_output_tokens: max_output_tokens ?? null,
|
|
197
|
+
sandbox,
|
|
198
|
+
reason: reason || "",
|
|
189
199
|
}),
|
|
190
200
|
);
|
|
191
201
|
|
|
@@ -212,6 +222,8 @@ export const shell_exec = tool({
|
|
|
212
222
|
...(typeof max_output_tokens === "number"
|
|
213
223
|
? { maxOutputTokens: max_output_tokens }
|
|
214
224
|
: {}),
|
|
225
|
+
sandbox,
|
|
226
|
+
...(reason ? { reason } : {}),
|
|
215
227
|
},
|
|
216
228
|
});
|
|
217
229
|
|
|
@@ -348,9 +360,10 @@ export const shell_read = tool({
|
|
|
348
360
|
* `shell_write`:向 shell stdin 写入内容。
|
|
349
361
|
*/
|
|
350
362
|
export const shell_write = tool({
|
|
351
|
-
description:
|
|
363
|
+
description:
|
|
364
|
+
"Write text to the stdin of an existing shell session. When the target session runs in unrestricted sandbox mode, provide reason; every write requires user approval.",
|
|
352
365
|
inputSchema: shellWriteInputSchema,
|
|
353
|
-
execute: async ({ shell_id, chars }: ShellWriteInput) => {
|
|
366
|
+
execute: async ({ shell_id, chars, reason }: ShellWriteInput) => {
|
|
354
367
|
const startedAt = Date.now();
|
|
355
368
|
try {
|
|
356
369
|
console.log(
|
|
@@ -358,6 +371,7 @@ export const shell_write = tool({
|
|
|
358
371
|
JSON.stringify({
|
|
359
372
|
shell_id,
|
|
360
373
|
input_chars: String(chars || "").length,
|
|
374
|
+
reason: reason || "",
|
|
361
375
|
}),
|
|
362
376
|
);
|
|
363
377
|
const response = await invokeShellAction({
|
|
@@ -365,6 +379,7 @@ export const shell_write = tool({
|
|
|
365
379
|
payload: {
|
|
366
380
|
shellId: shell_id,
|
|
367
381
|
chars,
|
|
382
|
+
...(reason ? { reason } : {}),
|
|
368
383
|
},
|
|
369
384
|
});
|
|
370
385
|
const flatResponse = flattenShellActionResponse({ response, startedAt });
|
|
@@ -8,6 +8,17 @@
|
|
|
8
8
|
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
|
|
11
|
+
const shellSandboxModeSchema = z
|
|
12
|
+
.enum(["safe", "unrestricted"])
|
|
13
|
+
.optional()
|
|
14
|
+
.default("safe")
|
|
15
|
+
.describe("Sandbox mode. safe is the default; unrestricted requires user approval.");
|
|
16
|
+
|
|
17
|
+
const shellUnrestrictedReasonSchema = z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Required when sandbox is unrestricted. Explain why host-level execution is needed.");
|
|
21
|
+
|
|
11
22
|
export const shellStartInputSchema = z.object({
|
|
12
23
|
cmd: z.string().describe("Shell command to execute."),
|
|
13
24
|
workdir: z
|
|
@@ -36,6 +47,8 @@ export const shellStartInputSchema = z.object({
|
|
|
36
47
|
.boolean()
|
|
37
48
|
.optional()
|
|
38
49
|
.describe("Whether the shell plugin runtime should auto-return to the owning chat agent when the command exits."),
|
|
50
|
+
sandbox: shellSandboxModeSchema,
|
|
51
|
+
reason: shellUnrestrictedReasonSchema,
|
|
39
52
|
});
|
|
40
53
|
|
|
41
54
|
export const shellExecInputSchema = z.object({
|
|
@@ -62,6 +75,8 @@ export const shellExecInputSchema = z.object({
|
|
|
62
75
|
.number()
|
|
63
76
|
.optional()
|
|
64
77
|
.describe("Maximum output tokens returned in the final result."),
|
|
78
|
+
sandbox: shellSandboxModeSchema,
|
|
79
|
+
reason: shellUnrestrictedReasonSchema,
|
|
65
80
|
});
|
|
66
81
|
|
|
67
82
|
export const shellStatusInputSchema = z.object({
|
|
@@ -87,6 +102,10 @@ export const shellReadInputSchema = z.object({
|
|
|
87
102
|
export const shellWriteInputSchema = z.object({
|
|
88
103
|
shell_id: z.string().describe("Existing shell identifier."),
|
|
89
104
|
chars: z.string().describe("Bytes to write to stdin."),
|
|
105
|
+
reason: z
|
|
106
|
+
.string()
|
|
107
|
+
.optional()
|
|
108
|
+
.describe("Required when writing to an unrestricted shell session. Explain why this stdin input is needed."),
|
|
90
109
|
});
|
|
91
110
|
|
|
92
111
|
export const shellWaitInputSchema = z.object({
|
|
@@ -6,6 +6,16 @@
|
|
|
6
6
|
* - `shell_id` 与 chat `sessionId` 严格分离,避免语义混淆。
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* shell 执行 sandbox 模式。
|
|
11
|
+
*/
|
|
12
|
+
export type ShellSandboxMode = "safe" | "unrestricted";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* shell unrestricted sandbox 申请原因。
|
|
16
|
+
*/
|
|
17
|
+
export type ShellUnrestrictedReason = string;
|
|
18
|
+
|
|
9
19
|
/**
|
|
10
20
|
* 启动一个交互式 shell session 的输入。
|
|
11
21
|
*/
|
|
@@ -24,6 +34,10 @@ export type ShellStartInput = {
|
|
|
24
34
|
max_output_tokens?: number;
|
|
25
35
|
/** 进程退出时是否自动通知调用方。 */
|
|
26
36
|
auto_notify_on_exit?: boolean;
|
|
37
|
+
/** 命令执行 sandbox 模式;默认 safe。 */
|
|
38
|
+
sandbox?: ShellSandboxMode;
|
|
39
|
+
/** 请求 unrestricted sandbox 时展示给用户的原因。 */
|
|
40
|
+
reason?: string;
|
|
27
41
|
};
|
|
28
42
|
|
|
29
43
|
/**
|
|
@@ -42,6 +56,10 @@ export type ShellExecInput = {
|
|
|
42
56
|
timeout_ms?: number;
|
|
43
57
|
/** 最多返回多少输出 token。 */
|
|
44
58
|
max_output_tokens?: number;
|
|
59
|
+
/** 命令执行 sandbox 模式;默认 safe。 */
|
|
60
|
+
sandbox?: ShellSandboxMode;
|
|
61
|
+
/** 请求 unrestricted sandbox 时展示给用户的原因。 */
|
|
62
|
+
reason?: string;
|
|
45
63
|
};
|
|
46
64
|
|
|
47
65
|
/**
|
|
@@ -74,6 +92,8 @@ export type ShellWriteInput = {
|
|
|
74
92
|
shell_id: string;
|
|
75
93
|
/** 要发送到 stdin 的字符内容。 */
|
|
76
94
|
chars: string;
|
|
95
|
+
/** 向 unrestricted shell session 写入 stdin 时展示给用户的原因。 */
|
|
96
|
+
reason?: ShellUnrestrictedReason;
|
|
77
97
|
};
|
|
78
98
|
|
|
79
99
|
/**
|
|
@@ -14,6 +14,21 @@ export type ShellSessionStatus =
|
|
|
14
14
|
| "killed"
|
|
15
15
|
| "expired";
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* shell 执行 sandbox 模式。
|
|
19
|
+
*/
|
|
20
|
+
export type ShellSandboxMode = "safe" | "unrestricted";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* unrestricted sandbox 审批状态。
|
|
24
|
+
*/
|
|
25
|
+
export type ShellApprovalStatus = "approved" | "denied" | "expired";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* shell unrestricted sandbox 审批来源工具。
|
|
29
|
+
*/
|
|
30
|
+
export type ShellApprovalToolName = "shell_exec" | "shell_start" | "shell_write";
|
|
31
|
+
|
|
17
32
|
/**
|
|
18
33
|
* shell 会话关联的外部引用。
|
|
19
34
|
*
|
|
@@ -50,6 +65,16 @@ export type ShellSessionSnapshot = {
|
|
|
50
65
|
shellPath: string;
|
|
51
66
|
/** 当前 shell 是否运行在 sandbox 中。 */
|
|
52
67
|
sandboxed?: boolean;
|
|
68
|
+
/** 当前 shell 的 Downcity sandbox 模式。 */
|
|
69
|
+
sandboxMode?: ShellSandboxMode;
|
|
70
|
+
/** unrestricted sandbox 审批状态。 */
|
|
71
|
+
approvalStatus?: ShellApprovalStatus;
|
|
72
|
+
/** unrestricted sandbox 审批请求 ID。 */
|
|
73
|
+
approvalId?: string;
|
|
74
|
+
/** unrestricted sandbox 申请原因。 */
|
|
75
|
+
approvalReason?: string;
|
|
76
|
+
/** 当前 shell 是否允许继续写入 stdin。 */
|
|
77
|
+
stdinWritable?: boolean;
|
|
53
78
|
/** 当前 shell 使用的 sandbox backend。 */
|
|
54
79
|
sandboxBackend?: string;
|
|
55
80
|
/** 当前 shell 采用的 sandbox 网络模式。 */
|
|
@@ -112,6 +137,12 @@ export type ShellStartRequest = {
|
|
|
112
137
|
ownerContextId?: string;
|
|
113
138
|
/** 是否在 shell 结束后自动回投主 chat agent。 */
|
|
114
139
|
autoNotifyOnExit?: boolean;
|
|
140
|
+
/** 命令执行 sandbox 模式;默认 safe。 */
|
|
141
|
+
sandbox?: ShellSandboxMode;
|
|
142
|
+
/** 请求 unrestricted sandbox 时展示给用户的原因。 */
|
|
143
|
+
reason?: string;
|
|
144
|
+
/** 内部审批来源工具名;普通调用方不需要传。 */
|
|
145
|
+
approvalToolName?: ShellApprovalToolName;
|
|
115
146
|
};
|
|
116
147
|
|
|
117
148
|
/**
|
|
@@ -134,6 +165,10 @@ export type ShellExecRequest = {
|
|
|
134
165
|
timeoutMs?: number;
|
|
135
166
|
/** 单次读取输出返回给模型的 token 上限。 */
|
|
136
167
|
maxOutputTokens?: number;
|
|
168
|
+
/** 命令执行 sandbox 模式;默认 safe。 */
|
|
169
|
+
sandbox?: ShellSandboxMode;
|
|
170
|
+
/** 请求 unrestricted sandbox 时展示给用户的原因。 */
|
|
171
|
+
reason?: string;
|
|
137
172
|
};
|
|
138
173
|
|
|
139
174
|
/**
|
|
@@ -172,6 +207,8 @@ export type ShellWriteRequest = {
|
|
|
172
207
|
shellId: string;
|
|
173
208
|
/** 要写入 stdin 的原始文本。 */
|
|
174
209
|
chars: string;
|
|
210
|
+
/** 向 unrestricted shell session 写入 stdin 时展示给用户的原因。 */
|
|
211
|
+
reason?: string;
|
|
175
212
|
};
|
|
176
213
|
|
|
177
214
|
/**
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { SandboxSpawnResult } from "@/sandbox/types/SandboxRuntime.js";
|
|
|
12
12
|
import { resolveSandboxConfig, resolveSandboxCwd } from "@/sandbox/SandboxConfigResolver.js";
|
|
13
13
|
import { spawnMacOsSeatbeltSandbox } from "@/sandbox/MacOsSeatbeltSandbox.js";
|
|
14
14
|
import { spawnLinuxBubblewrapSandbox } from "@/sandbox/LinuxBubblewrapSandbox.js";
|
|
15
|
+
import { spawnUnrestrictedSandbox } from "@/sandbox/UnrestrictedSandbox.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* 启动 shell 子进程。
|
|
@@ -25,6 +26,7 @@ export async function spawnShellProcess(params: {
|
|
|
25
26
|
shellPath: string;
|
|
26
27
|
login: boolean;
|
|
27
28
|
baseEnv: NodeJS.ProcessEnv;
|
|
29
|
+
sandboxMode?: "safe" | "unrestricted";
|
|
28
30
|
}): Promise<SandboxSpawnResult> {
|
|
29
31
|
return spawnInSandbox({
|
|
30
32
|
context: params.context,
|
|
@@ -35,6 +37,7 @@ export async function spawnShellProcess(params: {
|
|
|
35
37
|
shellPath: params.shellPath,
|
|
36
38
|
login: params.login,
|
|
37
39
|
baseEnv: params.baseEnv,
|
|
40
|
+
sandboxMode: params.sandboxMode,
|
|
38
41
|
});
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -50,7 +53,21 @@ export async function spawnInSandbox(params: {
|
|
|
50
53
|
shellPath: string;
|
|
51
54
|
login: boolean;
|
|
52
55
|
baseEnv: NodeJS.ProcessEnv;
|
|
56
|
+
sandboxMode?: "safe" | "unrestricted";
|
|
53
57
|
}): Promise<SandboxSpawnResult> {
|
|
58
|
+
if (params.sandboxMode === "unrestricted") {
|
|
59
|
+
return spawnUnrestrictedSandbox({
|
|
60
|
+
executionId: params.executionId,
|
|
61
|
+
executionDir: params.executionDir,
|
|
62
|
+
cmd: params.cmd,
|
|
63
|
+
cwd: params.cwd,
|
|
64
|
+
shellPath: params.shellPath,
|
|
65
|
+
login: params.login,
|
|
66
|
+
baseEnv: params.baseEnv,
|
|
67
|
+
actualCwd: params.cwd,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
54
71
|
const config = resolveSandboxConfig(params.context);
|
|
55
72
|
const actualCwd = resolveSandboxCwd({
|
|
56
73
|
rootPath: config.rootPath,
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unrestricted sandbox backend。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 这是 Downcity Runtime 管理的高权限执行环境,不是 agent 直接访问宿主 shell。
|
|
6
|
+
* - 进程继承宿主可见文件系统与环境边界,但必须由上层 approval 流程批准后才能调用。
|
|
7
|
+
* - 本 backend 只负责 spawn,不做审批、审计或风险判断。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { spawn } from "node:child_process";
|
|
11
|
+
import fs from "fs-extra";
|
|
12
|
+
import type {
|
|
13
|
+
SandboxSpawnParams,
|
|
14
|
+
SandboxSpawnResult,
|
|
15
|
+
} from "@/sandbox/types/SandboxRuntime.js";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 在 unrestricted sandbox 中启动 shell 子进程。
|
|
19
|
+
*/
|
|
20
|
+
export async function spawnUnrestrictedSandbox(
|
|
21
|
+
params: Omit<SandboxSpawnParams, "config"> & { actualCwd: string },
|
|
22
|
+
): Promise<SandboxSpawnResult> {
|
|
23
|
+
await fs.ensureDir(params.executionDir);
|
|
24
|
+
|
|
25
|
+
const child = spawn(
|
|
26
|
+
params.shellPath,
|
|
27
|
+
[
|
|
28
|
+
params.login ? "-lc" : "-c",
|
|
29
|
+
params.cmd,
|
|
30
|
+
],
|
|
31
|
+
{
|
|
32
|
+
cwd: params.actualCwd,
|
|
33
|
+
stdio: "pipe",
|
|
34
|
+
env: params.baseEnv,
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
child.stdout.setEncoding("utf8");
|
|
39
|
+
child.stderr.setEncoding("utf8");
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
child,
|
|
43
|
+
cwd: params.actualCwd,
|
|
44
|
+
sandboxed: false,
|
|
45
|
+
sandboxMode: "unrestricted",
|
|
46
|
+
backend: "unrestricted-host",
|
|
47
|
+
networkMode: "full",
|
|
48
|
+
sandboxDir: "",
|
|
49
|
+
homeDir: String(params.baseEnv.HOME || ""),
|
|
50
|
+
tmpDir: String(params.baseEnv.TMPDIR || "/tmp"),
|
|
51
|
+
cacheDir: String(params.baseEnv.XDG_CACHE_HOME || ""),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -14,7 +14,7 @@ import type { SandboxNetworkMode } from "@/sandbox/types/Sandbox.js";
|
|
|
14
14
|
/**
|
|
15
15
|
* 当前内置支持的 sandbox backend。
|
|
16
16
|
*/
|
|
17
|
-
export type SandboxBackend = "macos-seatbelt" | "linux-bubblewrap";
|
|
17
|
+
export type SandboxBackend = "macos-seatbelt" | "linux-bubblewrap" | "unrestricted-host";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* sandbox 会话状态。
|
|
@@ -305,6 +305,11 @@ export interface ResolvedSandboxConfig extends SandboxConfig {
|
|
|
305
305
|
*/
|
|
306
306
|
backend: SandboxBackend;
|
|
307
307
|
|
|
308
|
+
/**
|
|
309
|
+
* 当前 Downcity sandbox 模式。
|
|
310
|
+
*/
|
|
311
|
+
sandboxMode?: "safe" | "unrestricted";
|
|
312
|
+
|
|
308
313
|
/**
|
|
309
314
|
* 当前 agent 级 sandbox 的持久目录。
|
|
310
315
|
*
|
|
@@ -398,6 +403,11 @@ export interface SandboxSpawnResult {
|
|
|
398
403
|
*/
|
|
399
404
|
sandboxed: boolean;
|
|
400
405
|
|
|
406
|
+
/**
|
|
407
|
+
* 当前 Downcity sandbox 模式。
|
|
408
|
+
*/
|
|
409
|
+
sandboxMode?: "safe" | "unrestricted";
|
|
410
|
+
|
|
401
411
|
/**
|
|
402
412
|
* 当前使用的 backend 名称。
|
|
403
413
|
*/
|
package/src/session/Session.ts
CHANGED
|
@@ -270,6 +270,9 @@ export class Session implements AgentSession {
|
|
|
270
270
|
getExecutor: () => this.executor.getExecutor(),
|
|
271
271
|
prompt: async (input) => await this.prompt(input),
|
|
272
272
|
subscribe: (subscriber) => this.subscribe(subscriber),
|
|
273
|
+
publishEvent: (event) => {
|
|
274
|
+
this.eventHub.publish(event);
|
|
275
|
+
},
|
|
273
276
|
clearExecutor: () => {
|
|
274
277
|
this.executor.clearExecutor();
|
|
275
278
|
},
|
|
@@ -140,6 +140,7 @@ export class SessionTurnService {
|
|
|
140
140
|
}> {
|
|
141
141
|
const tool_name_by_call_id = new Map<string, string>();
|
|
142
142
|
const run_context: SessionRunContext = {
|
|
143
|
+
turnId: input.turnId,
|
|
143
144
|
sessionId: this.session_id,
|
|
144
145
|
projectRoot: this.project_root,
|
|
145
146
|
onStepCallback: input.onStepMerge,
|
|
@@ -10,6 +10,7 @@ import type { SessionPort } from "@/types/runtime/agent/AgentContext.js";
|
|
|
10
10
|
import type { SessionHistoryStore } from "@/executor/store/history/SessionHistoryStore.js";
|
|
11
11
|
import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
|
|
12
12
|
import type {
|
|
13
|
+
AgentSessionEvent,
|
|
13
14
|
AgentSessionSubscriber,
|
|
14
15
|
AgentSessionUnsubscribe,
|
|
15
16
|
} from "@/types/sdk/AgentSessionEvent.js";
|
|
@@ -37,6 +38,10 @@ export interface CreateRuntimeSessionPortParams {
|
|
|
37
38
|
subscribe: (
|
|
38
39
|
subscriber: AgentSessionSubscriber,
|
|
39
40
|
) => AgentSessionUnsubscribe;
|
|
41
|
+
/**
|
|
42
|
+
* 发布一条 session runtime 事件。
|
|
43
|
+
*/
|
|
44
|
+
publishEvent: (event: AgentSessionEvent) => void;
|
|
40
45
|
/**
|
|
41
46
|
* 清理当前 session executor 状态。
|
|
42
47
|
*/
|
|
@@ -88,6 +93,9 @@ export function createRuntimeSessionPort(
|
|
|
88
93
|
subscribe: (subscriber) => {
|
|
89
94
|
return params.subscribe(subscriber);
|
|
90
95
|
},
|
|
96
|
+
publishEvent: (event) => {
|
|
97
|
+
params.publishEvent(event);
|
|
98
|
+
},
|
|
91
99
|
clearExecutor: () => {
|
|
92
100
|
params.clearExecutor();
|
|
93
101
|
},
|
|
@@ -27,6 +27,10 @@ export type {
|
|
|
27
27
|
AgentStopResult,
|
|
28
28
|
} from "@/types/agent/AgentOptions.js";
|
|
29
29
|
export type { RemoteAgentOptions } from "@/types/agent/RemoteAgentOptions.js";
|
|
30
|
+
export type {
|
|
31
|
+
RemoteAgentPluginActionInput,
|
|
32
|
+
RemoteAgentPluginActionResult,
|
|
33
|
+
} from "@/types/agent/RemoteAgentPluginAction.js";
|
|
30
34
|
export type {
|
|
31
35
|
AgentCreateSessionInput,
|
|
32
36
|
AgentListSessionsInput,
|