Skip to content

Commit bec8016

Browse files
committed
feat: Add support for custom entrypoints in sandbox configs
1 parent 9f1a0c4 commit bec8016

File tree

14 files changed

+330
-74
lines changed

14 files changed

+330
-74
lines changed

packages/service/core/agentSkills/sandboxConfig.ts

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ export type SandboxDefaults = {
2424
cleanupInterval: number; // in milliseconds
2525
inactiveThreshold: number; // in seconds
2626
defaultImage: SandboxImageConfigType;
27-
homeDirectory: string;
2827
workDirectory: string;
2928
targetPort: number;
29+
entrypoint: {
30+
editDebugKubernetes: string; // SANDBOX_K8S_ENTRYPOINT
31+
sessionKubernetes: string; // SANDBOX_SESSION_K8S_ENTRYPOINT
32+
docker: string; // SANDBOX_DOCKER_ENTRYPOINT
33+
};
3034
};
3135

3236
/**
@@ -55,12 +59,17 @@ export function getSandboxDefaults(): SandboxDefaults {
5559
cleanupInterval: safeParseInt(process.env.SANDBOX_CLEANUP_INTERVAL, 3600000),
5660
inactiveThreshold: safeParseInt(process.env.SANDBOX_INACTIVE_THRESHOLD, 7200),
5761
defaultImage: {
58-
repository: process.env.SANDBOX_DEFAULT_IMAGE || 'node',
59-
tag: process.env.SANDBOX_DEFAULT_IMAGE_TAG || '18-alpine'
62+
repository: process.env.SANDBOX_DEFAULT_IMAGE || 'fastgpt-agent-sandbox',
63+
tag: process.env.SANDBOX_DEFAULT_IMAGE_TAG || 'docker'
6064
},
61-
homeDirectory: '/home/coder',
62-
workDirectory: '/workspace/projects',
63-
targetPort: 8080
65+
workDirectory: process.env.SANDBOX_WORK_DIRECTORY || '/home/sandbox/workspace',
66+
targetPort: 8080,
67+
entrypoint: {
68+
editDebugKubernetes: process.env.SANDBOX_K8S_ENTRYPOINT || '/home/sandbox/entrypoint.sh',
69+
sessionKubernetes:
70+
process.env.SANDBOX_SESSION_K8S_ENTRYPOINT || '/opt/sync-agent/docker-entrypoint.sh',
71+
docker: process.env.SANDBOX_DOCKER_ENTRYPOINT || '/opt/sync-agent/docker-entrypoint.sh'
72+
}
6473
};
6574
}
6675

@@ -129,12 +138,13 @@ export function buildDockerSyncEnv(
129138
}
130139

131140
return {
132-
SESSION_ID: sessionId,
133-
MINIO_ENDPOINT: endpoint,
134-
MINIO_ACCESS_KEY: accessKey,
135-
MINIO_SECRET_KEY: secretKey,
136-
MINIO_BUCKET: bucket,
137-
SYNC_PATH: syncPath,
138-
ENABLE_CODE_SERVER: enableCodeServer ? 'true' : 'false'
141+
FASTGPT_SESSION_ID: sessionId,
142+
FASTGPT_MINIO_ENDPOINT: endpoint,
143+
FASTGPT_MINIO_ACCESS_KEY: accessKey,
144+
FASTGPT_MINIO_SECRET_KEY: secretKey,
145+
FASTGPT_MINIO_BUCKET: bucket,
146+
FASTGPT_WORKDIR: syncPath,
147+
FASTGPT_SYNC_PATH: syncPath,
148+
FASTGPT_ENABLE_CODE_SERVER: enableCodeServer ? 'true' : 'false'
139149
};
140150
}

packages/service/core/agentSkills/sandboxController.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export type CreateEditDebugSandboxParams = {
3737
tmbId: string;
3838
image?: SandboxImageConfigType;
3939
timeout?: number;
40+
entrypoint?: string; // override default entrypoint for this request
4041
onProgress?: (status: SandboxStatusItemType) => void; // lifecycle progress callback
4142
};
4243

@@ -78,7 +79,7 @@ export type RenewSandboxParams = {
7879
export async function createEditDebugSandbox(
7980
params: CreateEditDebugSandboxParams
8081
): Promise<CreateEditDebugSandboxResult> {
81-
const { skillId, teamId, tmbId, image, timeout, onProgress } = params;
82+
const { skillId, teamId, tmbId, image, timeout, entrypoint, onProgress } = params;
8283

8384
// === Phase 1: Resolve and validate configuration ===
8485
const providerConfig = getSandboxProviderConfig();
@@ -186,7 +187,8 @@ export async function createEditDebugSandbox(
186187
await sandbox.create({
187188
image: sandboxImage,
188189
timeout: sandboxTimeout,
189-
entrypoint: ['/home/coder/entrypoint.sh'],
190+
entrypoint: [entrypoint ?? defaults.entrypoint.editDebugKubernetes],
191+
env: buildDockerSyncEnv(sessionId, defaults.workDirectory, true),
190192
metadata: {
191193
skillId,
192194
teamId,
@@ -196,9 +198,9 @@ export async function createEditDebugSandbox(
196198
});
197199
} else {
198200
await sandbox.create({
199-
image: { repository: 'fastgpt-agent-sandbox', tag: 'docker' },
201+
image: sandboxImage,
200202
timeout: sandboxTimeout,
201-
entrypoint: ['/opt/sync-agent/docker-entrypoint.sh'],
203+
entrypoint: [entrypoint ?? defaults.entrypoint.docker],
202204
env: buildDockerSyncEnv(sessionId, defaults.workDirectory, true),
203205
metadata: {
204206
skillId,
@@ -468,7 +470,7 @@ export async function renewSandboxExpiration(
468470
*
469471
* @param params - Parameters for packaging
470472
* @param params.providerSandboxId - Provider sandbox ID
471-
* @param params.workDirectory - Working directory (defaults to homeDirectory)
473+
* @param params.workDirectory - Working directory
472474
* @returns Buffer containing the package.zip file
473475
*
474476
* @throws Error if packaging fails, file cannot be read, or directory exceeds size limit

packages/service/core/workflow/dispatch/ai/agent/sub/sandbox/lifecycle.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type CreateAgentSandboxParams = {
4343
teamId: string;
4444
tmbId: string;
4545
sessionId: string; // chat 模式 = chatId,debug 模式 = 构造的 key,决定 MinIO 数据路径
46+
entrypoint?: string; // override default entrypoint for this request
4647
onProgress?: (status: SandboxStatusItemType) => void; // lifecycle progress callback
4748
};
4849

@@ -96,10 +97,10 @@ function mergeSkillWithVersion(
9697

9798
/** Dynamically discover all deployed skill directories in the sandbox by locating SKILL.md files.
9899
* Example:
99-
* $ find /workspace/projects -name "SKILL.md" -maxdepth 5 2>/dev/null
100-
* /workspace/projects/skill-creator/SKILL.md
101-
* /workspace/projects/deep-research/SKILL.md
102-
* /workspace/projects/science/SKILL.md
100+
* $ find ${FASTGPT_WORKDIR} -name "SKILL.md" -maxdepth 5 2>/dev/null
101+
* /home/sandbox/workspace/projects/skill-creator/SKILL.md
102+
* /home/sandbox/workspace/projects/deep-research/SKILL.md
103+
* /home/sandbox/workspace/projects/science/SKILL.md
103104
*
104105
* Runs `find` inside the sandbox to locate SKILL.md files up to maxdepth 2,
105106
* then reads each file and parses the frontmatter for name/description.
@@ -186,7 +187,7 @@ async function deploySkillsToSandbox(
186187
export async function createAgentSandbox(
187188
params: CreateAgentSandboxParams
188189
): Promise<AgentSandboxContext> {
189-
const { skillIds, teamId, tmbId, sessionId, onProgress } = params;
190+
const { skillIds, teamId, tmbId, sessionId, entrypoint, onProgress } = params;
190191

191192
const providerConfig = getSandboxProviderConfig();
192193
const defaults = getSandboxDefaults();
@@ -275,7 +276,7 @@ export async function createAgentSandbox(
275276
await sandbox.create({
276277
image: defaults.defaultImage,
277278
timeout: defaults.timeout,
278-
entrypoint: ['/opt/sync-agent/docker-entrypoint.sh'],
279+
entrypoint: [entrypoint ?? defaults.entrypoint.sessionKubernetes],
279280
env: buildDockerSyncEnv(sessionId, defaults.workDirectory, false),
280281
metadata: {
281282
teamId,
@@ -290,7 +291,7 @@ export async function createAgentSandbox(
290291
await sandbox.create({
291292
image: { repository: 'fastgpt-agent-sandbox', tag: 'docker' },
292293
timeout: defaults.timeout,
293-
entrypoint: ['/opt/sync-agent/docker-entrypoint.sh'],
294+
entrypoint: [entrypoint ?? defaults.entrypoint.docker],
294295
env: buildDockerSyncEnv(sessionId, defaults.workDirectory, false),
295296
metadata: {
296297
teamId,

packages/service/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
"version": "1.0.0",
44
"type": "module",
55
"dependencies": {
6+
"@anyany/sandbox_provider": "^0.1.1",
7+
"@apidevtools/json-schema-ref-parser": "^11.7.2",
68
"@fastgpt-sdk/storage": "^0.6.15",
79
"@fastgpt/global": "workspace:*",
810
"@logtape/logtape": "^2",
@@ -39,7 +41,6 @@
3941
"iconv-lite": "^0.6.3",
4042
"ioredis": "^5.6.0",
4143
"joplin-turndown-plugin-gfm": "^1.0.12",
42-
"@apidevtools/json-schema-ref-parser": "^11.7.2",
4344
"json5": "^2.2.3",
4445
"jsonpath-plus": "^10.3.0",
4546
"jsonwebtoken": "^9.0.2",

projects/sandbox-sync-agent/Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ USER root
1111
# 安装 Sync Agent 依赖
1212
RUN apt-get update && apt-get install -y \
1313
inotify-tools \
14-
curl \
1514
&& rm -rf /var/lib/apt/lists/*
1615

1716
# 安装 MinIO Client (mc)
@@ -28,6 +27,6 @@ RUN chmod +x /sync.sh /entrypoint.sh
2827
# 8081: Sync Agent HTTP API(健康检查 / 手动触发同步)
2928
EXPOSE 8081
3029

31-
USER coder
30+
USER sandbox
3231

3332
ENTRYPOINT ["/entrypoint.sh"]

projects/sandbox-sync-agent/Dockerfile.docker-runtime

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ USER root
1111
# 安装 Sync Agent 依赖
1212
RUN apt-get update && apt-get install -y \
1313
inotify-tools \
14-
curl \
1514
supervisor \
1615
&& rm -rf /var/lib/apt/lists/*
1716

@@ -29,8 +28,8 @@ COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
2928
RUN chmod +x /opt/sync-agent/sync.sh \
3029
/opt/sync-agent/docker-entrypoint.sh && \
3130
mkdir -p /var/log/supervisor && \
32-
chown -R coder:coder /var/log/supervisor
31+
chown -R sandbox:sandbox /var/log/supervisor
3332

34-
USER coder
33+
USER sandbox
3534

3635
ENTRYPOINT ["/opt/sync-agent/docker-entrypoint.sh"]

projects/sandbox-sync-agent/base/Dockerfile

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ ENV DEBIAN_FRONTEND=noninteractive
1010

1111
# Install dependencies
1212
RUN apt-get update && apt-get install -y \
13+
git \
14+
jq \
15+
ripgrep \
1316
vim-tiny \
1417
tree \
1518
unzip \
1619
curl \
17-
ca-certificates \
18-
sudo
20+
ca-certificates
1921
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
2022
RUN apt install -y python3 nodejs
2123
RUN rm -rf /var/lib/apt/lists/*
@@ -24,24 +26,20 @@ RUN rm -rf /var/lib/apt/lists/*
2426
RUN curl -fsSL https://code-server.dev/install.sh | sh
2527

2628
# Create a non-root user for security
27-
RUN useradd -m -s /bin/bash coder
29+
RUN useradd --create-home --shell /bin/bash sandbox
2830

29-
# Create the workspace directory and set permissions
30-
RUN mkdir -p /workspace/projects && \
31-
chown -R coder:coder /workspace/projects
32-
33-
USER coder
34-
WORKDIR /workspace/projects
31+
USER sandbox
32+
WORKDIR /home/sandbox
3533

3634
# Copy VS Code settings
37-
RUN mkdir -p /home/coder/.local/share/code-server/User
38-
COPY --chown=coder:coder settings.json /home/coder/.local/share/code-server/User/settings.json
35+
RUN mkdir -p /home/sandbox/.local/share/code-server/User
36+
COPY --chown=sandbox:sandbox settings.json /home/sandbox/.local/share/code-server/User/settings.json
3937

4038
# Copy and configure entrypoint
41-
COPY --chown=coder:coder entrypoint.sh /home/coder/entrypoint.sh
42-
RUN chmod +x /home/coder/entrypoint.sh
39+
COPY --chown=sandbox:sandbox entrypoint.sh /home/sandbox/entrypoint.sh
40+
RUN chmod +x /home/sandbox/entrypoint.sh
4341

4442
# Expose code-server port
4543
EXPOSE 8080
4644

47-
ENTRYPOINT ["/home/coder/entrypoint.sh"]
45+
ENTRYPOINT ["/home/sandbox/entrypoint.sh"]

projects/sandbox-sync-agent/base/entrypoint.sh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#!/bin/bash
22

3+
# Set work directory from environment variable, default to /home/sandbox
4+
WORKDIR="${FASTGPT_WORKDIR:-/home/sandbox}"
5+
mkdir -p "${WORKDIR}"
6+
37
# Start code-server
48
# --bind-addr 0.0.0.0:8080 allows access from outside the container
59
# --auth none removes password protection
@@ -11,5 +15,5 @@ exec code-server \
1115
--disable-workspace-trust \
1216
--disable-getting-started-override \
1317
--app-name "Skills" \
14-
--user-data-dir /home/coder/.local/share/code-server \
15-
/workspace/projects
18+
--user-data-dir /home/sandbox/.local/share/code-server \
19+
"${WORKDIR}"

0 commit comments

Comments
 (0)