@downcity/agent 1.1.97 → 1.1.100
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/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 +14 -0
- package/bin/executor/tools/shell/ShellToolBridge.js.map +1 -1
- package/bin/executor/tools/shell/types/ShellPlugin.d.ts +8 -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/plugin/core/ImagePlugin.d.ts +2 -5
- package/bin/plugin/core/ImagePlugin.d.ts.map +1 -1
- package/bin/plugin/core/ImagePlugin.js +6 -49
- package/bin/plugin/core/ImagePlugin.js.map +1 -1
- package/bin/sandbox/LinuxBubblewrapSandbox.d.ts +1 -3
- package/bin/sandbox/LinuxBubblewrapSandbox.d.ts.map +1 -1
- package/bin/sandbox/LinuxBubblewrapSandbox.js +31 -30
- package/bin/sandbox/LinuxBubblewrapSandbox.js.map +1 -1
- package/bin/sandbox/MacOsSeatbeltSandbox.d.ts +1 -1
- package/bin/sandbox/MacOsSeatbeltSandbox.d.ts.map +1 -1
- package/bin/sandbox/MacOsSeatbeltSandbox.js +30 -29
- package/bin/sandbox/MacOsSeatbeltSandbox.js.map +1 -1
- package/bin/sandbox/SandboxConfigResolver.d.ts +1 -0
- package/bin/sandbox/SandboxConfigResolver.d.ts.map +1 -1
- package/bin/sandbox/SandboxConfigResolver.js +13 -3
- package/bin/sandbox/SandboxConfigResolver.js.map +1 -1
- package/bin/sandbox/SandboxRunner.d.ts +17 -4
- package/bin/sandbox/SandboxRunner.d.ts.map +1 -1
- package/bin/sandbox/SandboxRunner.js +20 -5
- package/bin/sandbox/SandboxRunner.js.map +1 -1
- package/bin/sandbox/types/SandboxRuntime.d.ts +46 -6
- package/bin/sandbox/types/SandboxRuntime.d.ts.map +1 -1
- package/bin/sandbox/types/SandboxRuntime.js +2 -2
- package/bin/types/plugin/ImagePlugin.d.ts +3 -55
- package/bin/types/plugin/ImagePlugin.d.ts.map +1 -1
- package/package.json +2 -2
- package/scripts/image-plugin-job.test.mjs +10 -43
- package/scripts/linux-bubblewrap-sandbox.test.mjs +23 -14
- package/src/executor/composer/system/default/assets/core.prompt.ts +1 -1
- package/src/executor/composer/system/default/assets/core.prompt.ts.txt +5 -0
- package/src/executor/tools/shell/ShellToolBridge.ts +14 -0
- package/src/executor/tools/shell/types/ShellPlugin.ts +8 -0
- package/src/index.ts +0 -3
- package/src/plugin/core/ImagePlugin.ts +6 -52
- package/src/sandbox/LinuxBubblewrapSandbox.ts +35 -43
- package/src/sandbox/MacOsSeatbeltSandbox.ts +35 -41
- package/src/sandbox/SandboxConfigResolver.ts +15 -3
- package/src/sandbox/SandboxRunner.ts +32 -7
- package/src/sandbox/types/SandboxRuntime.ts +54 -6
- package/src/types/plugin/ImagePlugin.ts +3 -56
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
5
|
* - 这里负责把 `downcity.json` 中面向用户的最小配置,收敛成运行时可直接执行的绝对路径配置。
|
|
6
|
+
* - sandbox 是 agent 项目级能力,持久目录固定为 `<project>/.downcity/sandbox`。
|
|
6
7
|
* - 当前版本只服务 shell / CLI 这条命令执行链,不引入审批、profile 绑定或用户权限系统。
|
|
7
8
|
* - 解析结果只回答一个问题:这次命令执行的 sandbox 边界是什么。
|
|
8
9
|
*/
|
|
@@ -24,6 +25,8 @@ const DEFAULT_ENV_ALLOWLIST = [
|
|
|
24
25
|
"LOGNAME",
|
|
25
26
|
];
|
|
26
27
|
|
|
28
|
+
const SANDBOX_RELATIVE_DIR = path.join(".downcity", "sandbox");
|
|
29
|
+
|
|
27
30
|
function normalizeEnvAllowlist(values?: string[]): string[] {
|
|
28
31
|
const seen = new Set<string>();
|
|
29
32
|
const result: string[] = [];
|
|
@@ -49,14 +52,15 @@ export function isPathInsideRoot(rootPath: string, targetPath: string): boolean
|
|
|
49
52
|
|
|
50
53
|
function normalizeWritablePaths(params: {
|
|
51
54
|
rootPath: string;
|
|
55
|
+
sandboxDir: string;
|
|
52
56
|
writablePaths?: string[];
|
|
53
57
|
context: AgentContext;
|
|
54
58
|
}): string[] {
|
|
55
|
-
const { rootPath, writablePaths, context } = params;
|
|
59
|
+
const { rootPath, sandboxDir, writablePaths, context } = params;
|
|
56
60
|
const rawValues =
|
|
57
61
|
Array.isArray(writablePaths) && writablePaths.length > 0
|
|
58
|
-
? writablePaths
|
|
59
|
-
: [rootPath];
|
|
62
|
+
? [rootPath, sandboxDir, ...writablePaths]
|
|
63
|
+
: [rootPath, sandboxDir];
|
|
60
64
|
const seen = new Set<string>();
|
|
61
65
|
const result: string[] = [];
|
|
62
66
|
|
|
@@ -102,13 +106,21 @@ export function resolveSandboxBackend(): SandboxBackend {
|
|
|
102
106
|
export function resolveSandboxConfig(context: AgentContext): ResolvedSandboxConfig {
|
|
103
107
|
const rootPath = path.resolve(context.rootPath);
|
|
104
108
|
const projectConfig = context.config?.sandbox;
|
|
109
|
+
const sandboxDir = path.join(rootPath, SANDBOX_RELATIVE_DIR);
|
|
110
|
+
const tmpDir = path.join(sandboxDir, "tmp");
|
|
111
|
+
const cacheDir = path.join(sandboxDir, ".cache");
|
|
105
112
|
|
|
106
113
|
return {
|
|
107
114
|
backend: resolveSandboxBackend(),
|
|
108
115
|
rootPath,
|
|
116
|
+
sandboxDir,
|
|
117
|
+
homeDir: sandboxDir,
|
|
118
|
+
tmpDir,
|
|
119
|
+
cacheDir,
|
|
109
120
|
envAllowlist: normalizeEnvAllowlist(projectConfig?.envAllowlist),
|
|
110
121
|
writablePaths: normalizeWritablePaths({
|
|
111
122
|
rootPath,
|
|
123
|
+
sandboxDir,
|
|
112
124
|
writablePaths: projectConfig?.writablePaths,
|
|
113
125
|
context,
|
|
114
126
|
}),
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* SandboxRunner 入口。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - 这里不实现完整的 session/read/write
|
|
5
|
+
* - 这里不实现完整的 session/read/write 协议,只负责本地子进程创建时统一进入 agent sandbox backend。
|
|
6
6
|
* - 当前版本接入 macOS seatbelt 与 Linux bubblewrap backend。
|
|
7
|
-
* -
|
|
7
|
+
* - 本地命令不再允许回退到宿主机普通子进程执行。
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { AgentContext } from "@/types/runtime/agent/AgentContext.js";
|
|
@@ -25,6 +25,31 @@ export async function spawnShellProcess(params: {
|
|
|
25
25
|
shellPath: string;
|
|
26
26
|
login: boolean;
|
|
27
27
|
baseEnv: NodeJS.ProcessEnv;
|
|
28
|
+
}): Promise<SandboxSpawnResult> {
|
|
29
|
+
return spawnInSandbox({
|
|
30
|
+
context: params.context,
|
|
31
|
+
executionId: params.shellId,
|
|
32
|
+
executionDir: params.shellDir,
|
|
33
|
+
cmd: params.cmd,
|
|
34
|
+
cwd: params.cwd,
|
|
35
|
+
shellPath: params.shellPath,
|
|
36
|
+
login: params.login,
|
|
37
|
+
baseEnv: params.baseEnv,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 在当前 agent sandbox 中启动本地子进程。
|
|
43
|
+
*/
|
|
44
|
+
export async function spawnInSandbox(params: {
|
|
45
|
+
context: AgentContext;
|
|
46
|
+
executionId: string;
|
|
47
|
+
executionDir: string;
|
|
48
|
+
cmd: string;
|
|
49
|
+
cwd: string;
|
|
50
|
+
shellPath: string;
|
|
51
|
+
login: boolean;
|
|
52
|
+
baseEnv: NodeJS.ProcessEnv;
|
|
28
53
|
}): Promise<SandboxSpawnResult> {
|
|
29
54
|
const config = resolveSandboxConfig(params.context);
|
|
30
55
|
const actualCwd = resolveSandboxCwd({
|
|
@@ -33,8 +58,8 @@ export async function spawnShellProcess(params: {
|
|
|
33
58
|
context: params.context,
|
|
34
59
|
});
|
|
35
60
|
const spawnParams = {
|
|
36
|
-
|
|
37
|
-
|
|
61
|
+
executionId: params.executionId,
|
|
62
|
+
executionDir: params.executionDir,
|
|
38
63
|
cmd: params.cmd,
|
|
39
64
|
cwd: params.cwd,
|
|
40
65
|
shellPath: params.shellPath,
|
|
@@ -61,8 +86,8 @@ export async function spawnShellProcess(params: {
|
|
|
61
86
|
*/
|
|
62
87
|
export async function runSandboxCommand(params: {
|
|
63
88
|
context: AgentContext;
|
|
64
|
-
|
|
65
|
-
|
|
89
|
+
executionId: string;
|
|
90
|
+
executionDir: string;
|
|
66
91
|
cmd: string;
|
|
67
92
|
cwd: string;
|
|
68
93
|
shellPath: string;
|
|
@@ -74,7 +99,7 @@ export async function runSandboxCommand(params: {
|
|
|
74
99
|
exitCode: number;
|
|
75
100
|
spawn: SandboxSpawnResult;
|
|
76
101
|
}> {
|
|
77
|
-
const spawn = await
|
|
102
|
+
const spawn = await spawnInSandbox(params);
|
|
78
103
|
const stdoutChunks: string[] = [];
|
|
79
104
|
const stderrChunks: string[] = [];
|
|
80
105
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
5
|
* - 这里放的是 agent 执行层内部使用的最小 sandbox 运行时类型。
|
|
6
|
-
* - 当前只围绕
|
|
7
|
-
* - 目标是让 shell
|
|
6
|
+
* - 当前只围绕 agent 级 sandbox spawn 设计,不引入复杂 provider / policy / binding 对象。
|
|
7
|
+
* - 目标是让 shell、task script 等本地执行入口都能复用同一个 agent sandbox 边界。
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { ChildProcessWithoutNullStreams } from "node:child_process";
|
|
@@ -304,6 +304,30 @@ export interface ResolvedSandboxConfig extends SandboxConfig {
|
|
|
304
304
|
* 当前运行时选中的 backend。
|
|
305
305
|
*/
|
|
306
306
|
backend: SandboxBackend;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* 当前 agent 级 sandbox 的持久目录。
|
|
310
|
+
*
|
|
311
|
+
* 说明(中文)
|
|
312
|
+
* - 该目录不属于某个 shellId,而属于当前 agent 项目。
|
|
313
|
+
* - shell、task script 等所有 sandbox 子进程共享它作为 HOME/cache 根。
|
|
314
|
+
*/
|
|
315
|
+
sandboxDir: string;
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* sandbox 子进程使用的 HOME。
|
|
319
|
+
*/
|
|
320
|
+
homeDir: string;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* sandbox 子进程使用的临时目录。
|
|
324
|
+
*/
|
|
325
|
+
tmpDir: string;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* sandbox 子进程使用的 XDG cache 目录。
|
|
329
|
+
*/
|
|
330
|
+
cacheDir: string;
|
|
307
331
|
}
|
|
308
332
|
|
|
309
333
|
/**
|
|
@@ -311,14 +335,18 @@ export interface ResolvedSandboxConfig extends SandboxConfig {
|
|
|
311
335
|
*/
|
|
312
336
|
export interface SandboxSpawnParams {
|
|
313
337
|
/**
|
|
314
|
-
*
|
|
338
|
+
* 当前执行记录标识。
|
|
339
|
+
*
|
|
340
|
+
* 说明(中文)
|
|
341
|
+
* - shell plugin 传入 shellId,task script 可以传入自己的 executionId。
|
|
342
|
+
* - 它只用于日志与诊断,不参与 sandbox HOME/cache/权限边界的计算。
|
|
315
343
|
*/
|
|
316
|
-
|
|
344
|
+
executionId: string;
|
|
317
345
|
|
|
318
346
|
/**
|
|
319
|
-
*
|
|
347
|
+
* 当前执行记录目录。
|
|
320
348
|
*/
|
|
321
|
-
|
|
349
|
+
executionDir: string;
|
|
322
350
|
|
|
323
351
|
/**
|
|
324
352
|
* 要执行的原始命令文本。
|
|
@@ -379,4 +407,24 @@ export interface SandboxSpawnResult {
|
|
|
379
407
|
* 当前实际采用的网络模式。
|
|
380
408
|
*/
|
|
381
409
|
networkMode: SandboxNetworkMode;
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* 当前 agent 级 sandbox 的持久目录。
|
|
413
|
+
*/
|
|
414
|
+
sandboxDir: string;
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* 当前子进程使用的 HOME。
|
|
418
|
+
*/
|
|
419
|
+
homeDir: string;
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* 当前子进程使用的临时目录。
|
|
423
|
+
*/
|
|
424
|
+
tmpDir: string;
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* 当前子进程使用的 XDG cache 目录。
|
|
428
|
+
*/
|
|
429
|
+
cacheDir: string;
|
|
382
430
|
}
|
|
@@ -75,7 +75,7 @@ export interface ImagePluginInput {
|
|
|
75
75
|
quality?: string;
|
|
76
76
|
/** 随机种子。 */
|
|
77
77
|
seed?: number;
|
|
78
|
-
/** 业务侧任务 ID
|
|
78
|
+
/** 业务侧任务 ID,用于 provider 侧幂等、追踪和恢复。 */
|
|
79
79
|
client_job_id?: string;
|
|
80
80
|
/** Provider 私有参数,例如 `{ openai: {...}, gemini: {...}, luchi: {...} }`。 */
|
|
81
81
|
provider_options?: JsonObject;
|
|
@@ -83,58 +83,11 @@ export interface ImagePluginInput {
|
|
|
83
83
|
[key: string]: JsonValue | ImagePluginMessage[] | undefined;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
/**
|
|
87
|
-
* ImagePlugin 图片任务状态。
|
|
88
|
-
*/
|
|
89
|
-
export type ImagePluginJobStatus = "queued" | "running" | "succeeded" | "failed";
|
|
90
|
-
|
|
91
86
|
/**
|
|
92
87
|
* ImagePlugin 生成结果。
|
|
93
88
|
*/
|
|
94
89
|
export type ImagePluginResult = UIMessage;
|
|
95
90
|
|
|
96
|
-
/**
|
|
97
|
-
* ImagePlugin 图片任务创建结果。
|
|
98
|
-
*/
|
|
99
|
-
export interface ImagePluginJobCreateResult {
|
|
100
|
-
/** 图片任务唯一 ID。 */
|
|
101
|
-
job_id: string;
|
|
102
|
-
/** 当前任务状态。 */
|
|
103
|
-
status: ImagePluginJobStatus;
|
|
104
|
-
/** 读取任务结果的路径或 URL。 */
|
|
105
|
-
result_path?: string;
|
|
106
|
-
/** 人类可读状态说明。 */
|
|
107
|
-
message?: string;
|
|
108
|
-
/** 建议下次轮询前等待的毫秒数。 */
|
|
109
|
-
poll_after_ms?: number;
|
|
110
|
-
/** 任务创建时间。 */
|
|
111
|
-
created_at?: string;
|
|
112
|
-
/** 任务更新时间。 */
|
|
113
|
-
updated_at?: string;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* ImagePlugin 图片任务结果查询结果。
|
|
118
|
-
*/
|
|
119
|
-
export interface ImagePluginJobResult {
|
|
120
|
-
/** 图片任务唯一 ID。 */
|
|
121
|
-
job_id: string;
|
|
122
|
-
/** 当前任务状态。 */
|
|
123
|
-
status: ImagePluginJobStatus;
|
|
124
|
-
/** 成功时的图片结果。 */
|
|
125
|
-
result?: ImagePluginResult;
|
|
126
|
-
/** 失败时的错误信息。 */
|
|
127
|
-
error?: string;
|
|
128
|
-
/** 人类可读状态说明。 */
|
|
129
|
-
message?: string;
|
|
130
|
-
/** 任务未完成时建议下次轮询前等待的毫秒数。 */
|
|
131
|
-
poll_after_ms?: number;
|
|
132
|
-
/** 任务创建时间。 */
|
|
133
|
-
created_at?: string;
|
|
134
|
-
/** 任务更新时间。 */
|
|
135
|
-
updated_at?: string;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
91
|
/**
|
|
139
92
|
* ImagePlugin 构造参数。
|
|
140
93
|
*/
|
|
@@ -145,12 +98,6 @@ export interface ImagePluginOptions {
|
|
|
145
98
|
title?: string;
|
|
146
99
|
/** Plugin 用途说明。 */
|
|
147
100
|
description?: string;
|
|
148
|
-
/**
|
|
149
|
-
|
|
150
|
-
/** 可选:读取图片生成任务结果,通常传入 `(input) => city.ai.image_result(input)`。 */
|
|
151
|
-
result?: (input: { job_id: string }) => Promise<ImagePluginJobResult> | ImagePluginJobResult;
|
|
152
|
-
/** 兼容 `generate` 动作等待任务完成的最长毫秒数。 */
|
|
153
|
-
wait_timeout_ms?: number;
|
|
154
|
-
/** 兼容 `generate` 动作每次轮询间隔毫秒数。 */
|
|
155
|
-
poll_interval_ms?: number;
|
|
101
|
+
/** 图片生成函数,通常传入 `(input) => city.ai.image(input)`。 */
|
|
102
|
+
image?: (input: ImagePluginInput) => Promise<ImagePluginResult> | ImagePluginResult;
|
|
156
103
|
}
|