Skip to content

Commit 5294195

Browse files
committed
Use public container IP in agent prompts
1 parent 5182ee0 commit 5294195

6 files changed

Lines changed: 79 additions & 0 deletions

File tree

packages/app/tests/docker-git/entrypoint-auth.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,22 @@ describe("renderEntrypoint auth bridge", () => {
7979
expect(entrypoint).toContain("CLAUDE_GLOBAL_PROMPT_FILE=\"/home/dev/.claude/CLAUDE.md\"")
8080
expect(entrypoint).toContain("CLAUDE_AUTO_SYSTEM_PROMPT=\"${CLAUDE_AUTO_SYSTEM_PROMPT:-1}\"")
8181
expect(entrypoint).toContain("docker-git-managed:claude-md")
82+
expect(entrypoint).toContain("DOCKER_GIT_PUBLIC_IP=\"${DOCKER_GIT_PUBLIC_IP:-}\"")
83+
expect(entrypoint).toContain("docker_git_detect_public_ip()")
84+
expect(entrypoint).toContain("PUBLIC_IP_PROFILE=\"/etc/profile.d/docker-git-public-ip.sh\"")
85+
expect(entrypoint).toContain("docker_git_upsert_ssh_env \"DOCKER_GIT_PUBLIC_IP\" \"$DOCKER_GIT_PUBLIC_IP\"")
86+
expect(entrypoint).toContain("Публичный IP контейнера: $DOCKER_GIT_PUBLIC_IP")
87+
expect(entrypoint).toContain(
88+
"Если даёшь пользователю URL для HTTP API, dev-сервера, UI или другого сервиса из контейнера, используй этот IP вместо localhost и 127.0.0.1."
89+
)
90+
expect(entrypoint).toContain("Формат внешнего адреса: http://$DOCKER_GIT_PUBLIC_IP:<port>")
8291
expect(entrypoint).toContain(
8392
"SUBAGENTS_LINE=\"Для решения задач обязательно используй subagents. Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю.\""
8493
)
8594
expect(entrypoint.split("Для решения задач обязательно используй subagents.").length - 1).toBeGreaterThanOrEqual(
8695
2
8796
)
97+
expect(entrypoint.split("Публичный IP контейнера: $DOCKER_GIT_PUBLIC_IP").length - 1).toBeGreaterThanOrEqual(3)
8898
expect(entrypoint).toContain("token=\"${GITHUB_TOKEN:-}\"")
8999
expect(entrypoint).toContain("token=\"${GH_TOKEN:-}\"")
90100
expect(entrypoint).toContain(String.raw`printf "%s\n" "password=$token"`)

packages/lib/src/core/templates-entrypoint.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
renderEntrypointHeader,
88
renderEntrypointInputRc,
99
renderEntrypointPackageCache,
10+
renderEntrypointPublicIp,
1011
renderEntrypointSshd,
1112
renderEntrypointZshShell,
1213
renderEntrypointZshUserRc
@@ -37,6 +38,7 @@ export const renderEntrypoint = (config: TemplateConfig): string =>
3738
renderEntrypointHeader(config),
3839
renderEntrypointDnsRepair(),
3940
renderEntrypointPackageCache(config),
41+
renderEntrypointPublicIp(),
4042
renderEntrypointAuthorizedKeys(config),
4143
renderEntrypointCodexHome(config),
4244
renderEntrypointCodexSharedAuth(config),

packages/lib/src/core/templates-entrypoint/base.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,40 @@ docker_git_upsert_ssh_env "NPM_CONFIG_CACHE" "$PACKAGE_NPM_CACHE"
7676
docker_git_upsert_ssh_env "npm_config_cache" "$PACKAGE_NPM_CACHE"
7777
docker_git_upsert_ssh_env "YARN_CACHE_FOLDER" "$PACKAGE_YARN_CACHE"`
7878

79+
export const renderEntrypointPublicIp = (): string =>
80+
`# Detect a non-local container IP and expose it for user-facing service URLs
81+
DOCKER_GIT_PUBLIC_IP="\${DOCKER_GIT_PUBLIC_IP:-}"
82+
83+
docker_git_detect_public_ip() {
84+
local candidate=""
85+
if [[ -n "$DOCKER_GIT_PUBLIC_IP" ]]; then
86+
printf "%s" "$DOCKER_GIT_PUBLIC_IP"
87+
return 0
88+
fi
89+
90+
if command -v ip >/dev/null 2>&1; then
91+
candidate="$(ip -o -4 addr show scope global 2>/dev/null \
92+
| awk '{split($4, parts, "/"); if (parts[1] != "127.0.0.1") { print parts[1]; exit }}')"
93+
fi
94+
95+
if [[ -z "$candidate" ]] && command -v hostname >/dev/null 2>&1; then
96+
candidate="$(hostname -I 2>/dev/null | awk '{for (i = 1; i <= NF; i += 1) if ($i != "127.0.0.1") { print $i; exit }}')"
97+
fi
98+
99+
printf "%s" "$candidate"
100+
}
101+
102+
DOCKER_GIT_PUBLIC_IP="$(docker_git_detect_public_ip)"
103+
export DOCKER_GIT_PUBLIC_IP
104+
105+
PUBLIC_IP_PROFILE="/etc/profile.d/docker-git-public-ip.sh"
106+
cat <<EOF > "$PUBLIC_IP_PROFILE"
107+
export DOCKER_GIT_PUBLIC_IP="$DOCKER_GIT_PUBLIC_IP"
108+
EOF
109+
chmod 0644 "$PUBLIC_IP_PROFILE" || true
110+
111+
docker_git_upsert_ssh_env "DOCKER_GIT_PUBLIC_IP" "$DOCKER_GIT_PUBLIC_IP"`
112+
79113
export const renderEntrypointAuthorizedKeys = (config: TemplateConfig): string =>
80114
`# 1) Authorized keys are mounted from host at /authorized_keys
81115
mkdir -p /home/${config.sshUser}/.ssh

packages/lib/src/core/templates-entrypoint/claude-extra-config.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const entrypointClaudeGlobalPromptTemplate = String
55
CLAUDE_GLOBAL_PROMPT_FILE="/home/__SSH_USER__/.claude/CLAUDE.md"
66
CLAUDE_AUTO_SYSTEM_PROMPT="${"$"}{CLAUDE_AUTO_SYSTEM_PROMPT:-1}"
77
CLAUDE_WORKSPACE_CONTEXT="Контекст workspace: repository"
8+
CLAUDE_PUBLIC_ACCESS_BLOCK=""
89
REPO_REF_VALUE="${"$"}{REPO_REF:-__REPO_REF_DEFAULT__}"
910
REPO_URL_VALUE="${"$"}{REPO_URL:-__REPO_URL_DEFAULT__}"
1011
@@ -40,6 +41,15 @@ elif [[ "$REPO_REF_VALUE" == refs/pull/*/head ]]; then
4041
fi
4142
fi
4243
44+
if [[ -n "$DOCKER_GIT_PUBLIC_IP" ]]; then
45+
CLAUDE_PUBLIC_ACCESS_BLOCK="$(cat <<EOF
46+
Публичный IP контейнера: $DOCKER_GIT_PUBLIC_IP
47+
Если даёшь пользователю URL для HTTP API, dev-сервера, UI или другого сервиса из контейнера, используй этот IP вместо localhost и 127.0.0.1.
48+
Формат внешнего адреса: http://$DOCKER_GIT_PUBLIC_IP:<port>
49+
EOF
50+
)"
51+
fi
52+
4353
if [[ "$CLAUDE_AUTO_SYSTEM_PROMPT" == "1" ]]; then
4454
mkdir -p "$(dirname "$CLAUDE_GLOBAL_PROMPT_FILE")"
4555
chown 1000:1000 "$(dirname "$CLAUDE_GLOBAL_PROMPT_FILE")" 2>/dev/null || true
@@ -52,6 +62,7 @@ if [[ "$CLAUDE_AUTO_SYSTEM_PROMPT" == "1" ]]; then
5262
$CLAUDE_WORKSPACE_CONTEXT
5363
Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__
5464
Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе.
65+
$CLAUDE_PUBLIC_ACCESS_BLOCK
5566
Для решения задач обязательно используй subagents. Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю.
5667
Если ты видишь файлы AGENTS.md или CLAUDE.md внутри проекта, ты обязан их читать и соблюдать инструкции.
5768
<!-- /docker-git-managed:claude-md -->

packages/lib/src/core/templates-entrypoint/codex.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ WORKSPACES_LINE="Доступные workspace пути: __TARGET_DIR__"
129129
WORKSPACE_INFO_LINE="Контекст workspace: repository"
130130
FOCUS_LINE="Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__"
131131
INTERNET_LINE="Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе."
132+
PUBLIC_ACCESS_BLOCK=""
133+
if [[ -n "$DOCKER_GIT_PUBLIC_IP" ]]; then
134+
PUBLIC_ACCESS_BLOCK="$(cat <<EOF
135+
Публичный IP контейнера: $DOCKER_GIT_PUBLIC_IP
136+
Если даёшь пользователю URL для HTTP API, dev-сервера, UI или другого сервиса из контейнера, используй этот IP вместо localhost и 127.0.0.1.
137+
Формат внешнего адреса: http://$DOCKER_GIT_PUBLIC_IP:<port>
138+
EOF
139+
)"
140+
fi
132141
SUBAGENTS_LINE="Для решения задач обязательно используй subagents. Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю."
133142
if [[ "$REPO_REF" == issue-* ]]; then
134143
ISSUE_ID="$(printf "%s" "$REPO_REF" | sed -E 's#^issue-##')"
@@ -171,6 +180,7 @@ $WORKSPACES_LINE
171180
$WORKSPACE_INFO_LINE
172181
$FOCUS_LINE
173182
$INTERNET_LINE
183+
$PUBLIC_ACCESS_BLOCK
174184
$SUBAGENTS_LINE
175185
$MANAGED_END
176186
EOF
@@ -190,6 +200,7 @@ $WORKSPACES_LINE
190200
$WORKSPACE_INFO_LINE
191201
$FOCUS_LINE
192202
$INTERNET_LINE
203+
$PUBLIC_ACCESS_BLOCK
193204
$SUBAGENTS_LINE
194205
$MANAGED_END
195206
EOF

packages/lib/src/core/templates-entrypoint/gemini.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ docker_git_upsert_ssh_env "GEMINI_CLI_APPROVAL_MODE" "yolo"`
232232
const entrypointGeminiNoticeTemplate = String.raw`# Ensure global GEMINI.md exists for container context
233233
GEMINI_MD_PATH="__GEMINI_HOME__/GEMINI.md"
234234
GEMINI_WORKSPACE_CONTEXT="Контекст workspace: repository"
235+
GEMINI_PUBLIC_ACCESS_BLOCK=""
235236
if [[ "$REPO_REF" == issue-* ]]; then
236237
ISSUE_ID="$(printf "%s" "$REPO_REF" | sed -E 's#^issue-##')"
237238
ISSUE_URL=""
@@ -264,6 +265,15 @@ elif [[ "$REPO_REF" == refs/pull/*/head ]]; then
264265
fi
265266
fi
266267
268+
if [[ -n "$DOCKER_GIT_PUBLIC_IP" ]]; then
269+
GEMINI_PUBLIC_ACCESS_BLOCK="$(cat <<EOF
270+
Публичный IP контейнера: $DOCKER_GIT_PUBLIC_IP
271+
Если даёшь пользователю URL для HTTP API, dev-сервера, UI или другого сервиса из контейнера, используй этот IP вместо localhost и 127.0.0.1.
272+
Формат внешнего адреса: http://$DOCKER_GIT_PUBLIC_IP:<port>
273+
EOF
274+
)"
275+
fi
276+
267277
cat <<EOF > "$GEMINI_MD_PATH"
268278
<!-- docker-git-managed:gemini-md -->
269279
Ты автономный агент, который имеет полностью все права управления контейнером. У тебя есть доступ к командам sudo, gh, codex, gemini, claude, opencode, oh-my-opencode, sshpass, git, node, pnpm и всем остальным другим. Проекты с которыми идёт работа лежат по пути ~
@@ -272,6 +282,7 @@ cat <<EOF > "$GEMINI_MD_PATH"
272282
$GEMINI_WORKSPACE_CONTEXT
273283
Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__
274284
Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе.
285+
$GEMINI_PUBLIC_ACCESS_BLOCK
275286
Для решения задач обязательно используй subagents. Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю.
276287
Если ты видишь файлы AGENTS.md, GEMINI.md или CLAUDE.md внутри проекта, ты обязан их читать и соблюдать инструкции.
277288
<!-- /docker-git-managed:gemini-md -->

0 commit comments

Comments
 (0)