@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.
Files changed (53) hide show
  1. package/bin/executor/composer/system/default/assets/core.prompt.d.ts +1 -1
  2. package/bin/executor/composer/system/default/assets/core.prompt.d.ts.map +1 -1
  3. package/bin/executor/composer/system/default/assets/core.prompt.js +1 -1
  4. package/bin/executor/composer/system/default/assets/core.prompt.js.map +1 -1
  5. package/bin/executor/tools/shell/ShellToolBridge.d.ts.map +1 -1
  6. package/bin/executor/tools/shell/ShellToolBridge.js +14 -0
  7. package/bin/executor/tools/shell/ShellToolBridge.js.map +1 -1
  8. package/bin/executor/tools/shell/types/ShellPlugin.d.ts +8 -0
  9. package/bin/executor/tools/shell/types/ShellPlugin.d.ts.map +1 -1
  10. package/bin/index.d.ts +1 -1
  11. package/bin/index.d.ts.map +1 -1
  12. package/bin/index.js.map +1 -1
  13. package/bin/plugin/core/ImagePlugin.d.ts +2 -5
  14. package/bin/plugin/core/ImagePlugin.d.ts.map +1 -1
  15. package/bin/plugin/core/ImagePlugin.js +6 -49
  16. package/bin/plugin/core/ImagePlugin.js.map +1 -1
  17. package/bin/sandbox/LinuxBubblewrapSandbox.d.ts +1 -3
  18. package/bin/sandbox/LinuxBubblewrapSandbox.d.ts.map +1 -1
  19. package/bin/sandbox/LinuxBubblewrapSandbox.js +31 -30
  20. package/bin/sandbox/LinuxBubblewrapSandbox.js.map +1 -1
  21. package/bin/sandbox/MacOsSeatbeltSandbox.d.ts +1 -1
  22. package/bin/sandbox/MacOsSeatbeltSandbox.d.ts.map +1 -1
  23. package/bin/sandbox/MacOsSeatbeltSandbox.js +30 -29
  24. package/bin/sandbox/MacOsSeatbeltSandbox.js.map +1 -1
  25. package/bin/sandbox/SandboxConfigResolver.d.ts +1 -0
  26. package/bin/sandbox/SandboxConfigResolver.d.ts.map +1 -1
  27. package/bin/sandbox/SandboxConfigResolver.js +13 -3
  28. package/bin/sandbox/SandboxConfigResolver.js.map +1 -1
  29. package/bin/sandbox/SandboxRunner.d.ts +17 -4
  30. package/bin/sandbox/SandboxRunner.d.ts.map +1 -1
  31. package/bin/sandbox/SandboxRunner.js +20 -5
  32. package/bin/sandbox/SandboxRunner.js.map +1 -1
  33. package/bin/sandbox/types/SandboxRuntime.d.ts +46 -6
  34. package/bin/sandbox/types/SandboxRuntime.d.ts.map +1 -1
  35. package/bin/sandbox/types/SandboxRuntime.js +2 -2
  36. package/bin/types/plugin/ImagePlugin.d.ts +3 -55
  37. package/bin/types/plugin/ImagePlugin.d.ts.map +1 -1
  38. package/package.json +2 -2
  39. package/scripts/image-plugin-job.test.mjs +10 -43
  40. package/scripts/linux-bubblewrap-sandbox.test.mjs +23 -14
  41. package/src/executor/composer/system/default/assets/core.prompt.ts +1 -1
  42. package/src/executor/composer/system/default/assets/core.prompt.ts.txt +5 -0
  43. package/src/executor/tools/shell/ShellToolBridge.ts +14 -0
  44. package/src/executor/tools/shell/types/ShellPlugin.ts +8 -0
  45. package/src/index.ts +0 -3
  46. package/src/plugin/core/ImagePlugin.ts +6 -52
  47. package/src/sandbox/LinuxBubblewrapSandbox.ts +35 -43
  48. package/src/sandbox/MacOsSeatbeltSandbox.ts +35 -41
  49. package/src/sandbox/SandboxConfigResolver.ts +15 -3
  50. package/src/sandbox/SandboxRunner.ts +32 -7
  51. package/src/sandbox/types/SandboxRuntime.ts +54 -6
  52. package/src/types/plugin/ImagePlugin.ts +3 -56
  53. 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 协议,只负责 shell 子进程创建时统一进入 sandbox backend。
5
+ * - 这里不实现完整的 session/read/write 协议,只负责本地子进程创建时统一进入 agent sandbox backend。
6
6
  * - 当前版本接入 macOS seatbelt 与 Linux bubblewrap backend。
7
- * - shell 命令不再允许回退到宿主机普通子进程执行。
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
- shellId: params.shellId,
37
- shellDir: params.shellDir,
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
- shellId: string;
65
- shellDir: string;
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 spawnShellProcess(params);
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
- * - 当前只围绕 `SandboxRunner` 设计,不引入复杂 provider / policy / binding 对象。
7
- * - 目标是让 shell plugin runtime 可以直接把命令交给 `SandboxRunner` 执行。
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
- * 当前 shell 会话标识。
338
+ * 当前执行记录标识。
339
+ *
340
+ * 说明(中文)
341
+ * - shell plugin 传入 shellId,task script 可以传入自己的 executionId。
342
+ * - 它只用于日志与诊断,不参与 sandbox HOME/cache/权限边界的计算。
315
343
  */
316
- shellId: string;
344
+ executionId: string;
317
345
 
318
346
  /**
319
- * shell 会话目录。
347
+ * 当前执行记录目录。
320
348
  */
321
- shellDir: string;
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
- /** 可选:创建图片生成任务,通常传入 `(input) => city.ai.image_create(input)`。 */
149
- create?: (input: ImagePluginInput) => Promise<ImagePluginJobCreateResult> | ImagePluginJobCreateResult;
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
  }