From 83b23f389eb93f75e7591e354d27e2430a741b0c Mon Sep 17 00:00:00 2001 From: skulidropek <66840575+skulidropek@users.noreply.github.com> Date: Tue, 24 Mar 2026 13:33:04 +0000 Subject: [PATCH 1/3] feat(lib): extract Claude system prompt into dedicated file Move the agent system prompt from the embedded heredoc in claude-extra-config.ts into a standalone module (claude-system-prompt.ts) so the prompt can be edited in one place without touching the entrypoint generation logic. Co-Authored-By: Claude Sonnet 4.6 --- .../templates-entrypoint/claude-extra-config.ts | 10 ++-------- .../claude-system-prompt.ts | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts diff --git a/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts b/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts index e376aa66..51c93b63 100644 --- a/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts +++ b/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts @@ -1,4 +1,5 @@ import type { TemplateConfig } from "../domain.js" +import { claudeSystemPromptContent } from "./claude-system-prompt.js" const entrypointClaudeGlobalPromptTemplate = String .raw`# Claude Code: managed global memory (CLAUDE.md is auto-loaded by Claude Code) @@ -46,14 +47,7 @@ if [[ "$CLAUDE_AUTO_SYSTEM_PROMPT" == "1" ]]; then if [[ ! -f "$CLAUDE_GLOBAL_PROMPT_FILE" ]] || grep -q "^$" "$CLAUDE_GLOBAL_PROMPT_FILE"; then cat < "$CLAUDE_GLOBAL_PROMPT_FILE" -Ты автономный агент, который имеет полностью все права управления контейнером. У тебя есть доступ к командам sudo, gh, codex, opencode, oh-my-opencode, sshpass, claude, git, node, pnpm и всем остальным другим. Проекты с которыми идёт работа лежат по пути ~ -Рабочая папка проекта (git clone): __TARGET_DIR__ -Доступные workspace пути: __TARGET_DIR__ -$CLAUDE_WORKSPACE_CONTEXT -Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__ -Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе. -Для решения задач обязательно используй subagents. Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю. -Если ты видишь файлы AGENTS.md или CLAUDE.md внутри проекта, ты обязан их читать и соблюдать инструкции. +${claudeSystemPromptContent} EOF chmod 0644 "$CLAUDE_GLOBAL_PROMPT_FILE" || true diff --git a/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts b/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts new file mode 100644 index 00000000..3eaf3993 --- /dev/null +++ b/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts @@ -0,0 +1,17 @@ +/** + * System prompt injected into ~/.claude/CLAUDE.md inside every container. + * + * Edit this file to change the global Claude agent behaviour. + * Supported placeholders (replaced at template-render time): + * __TARGET_DIR__ – absolute path to the cloned repo inside the container + * $CLAUDE_WORKSPACE_CONTEXT – bash variable resolved at container start-up + * (set to "repository", "issue #N", or "PR #N") + */ +export const claudeSystemPromptContent = `Ты автономный агент, который имеет полностью все права управления контейнером. У тебя есть доступ к командам sudo, gh, codex, opencode, oh-my-opencode, sshpass, claude, git, node, pnpm и всем остальным другим. Проекты с которыми идёт работа лежат по пути ~ +Рабочая папка проекта (git clone): __TARGET_DIR__ +Доступные workspace пути: __TARGET_DIR__ +$CLAUDE_WORKSPACE_CONTEXT +Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__ +Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе. +Для решения задач обязательно используй subagents. Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю. +Если ты видишь файлы AGENTS.md или CLAUDE.md внутри проекта, ты обязан их читать и соблюдать инструкции.` From 581825081f627aa64482f95bdf8a3d5fc0218303 Mon Sep 17 00:00:00 2001 From: skulidropek <66840575+skulidropek@users.noreply.github.com> Date: Tue, 24 Mar 2026 13:49:11 +0000 Subject: [PATCH 2/3] feat(lib): unify system prompt across Claude, Gemini and Codex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace per-agent hardcoded prompts with imports from claude-system-prompt.ts (single source of truth): - PROMPT_INTRO / PROMPT_INTERNET / PROMPT_SUBAGENTS / PROMPT_FILES – shared string constants used by Codex's variable-based injection - renderSharedPrompt(workspaceContextBashVar) – builds the full prompt for Claude/Gemini heredoc injection, accepting the per-agent bash variable that resolves the workspace context at container start-up Co-Authored-By: Claude Sonnet 4.6 --- .../claude-extra-config.ts | 4 +- .../claude-system-prompt.ts | 59 ++++++++++++++----- .../src/core/templates-entrypoint/codex.ts | 9 +-- .../src/core/templates-entrypoint/gemini.ts | 10 +--- 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts b/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts index 51c93b63..f44503a0 100644 --- a/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts +++ b/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts @@ -1,5 +1,5 @@ import type { TemplateConfig } from "../domain.js" -import { claudeSystemPromptContent } from "./claude-system-prompt.js" +import { renderSharedPrompt } from "./claude-system-prompt.js" const entrypointClaudeGlobalPromptTemplate = String .raw`# Claude Code: managed global memory (CLAUDE.md is auto-loaded by Claude Code) @@ -47,7 +47,7 @@ if [[ "$CLAUDE_AUTO_SYSTEM_PROMPT" == "1" ]]; then if [[ ! -f "$CLAUDE_GLOBAL_PROMPT_FILE" ]] || grep -q "^$" "$CLAUDE_GLOBAL_PROMPT_FILE"; then cat < "$CLAUDE_GLOBAL_PROMPT_FILE" -${claudeSystemPromptContent} +${renderSharedPrompt("$CLAUDE_WORKSPACE_CONTEXT")} EOF chmod 0644 "$CLAUDE_GLOBAL_PROMPT_FILE" || true diff --git a/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts b/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts index 3eaf3993..be508b0e 100644 --- a/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts +++ b/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts @@ -1,17 +1,48 @@ /** - * System prompt injected into ~/.claude/CLAUDE.md inside every container. + * Shared system prompt injected into every agent (Claude, Gemini, Codex). * - * Edit this file to change the global Claude agent behaviour. - * Supported placeholders (replaced at template-render time): - * __TARGET_DIR__ – absolute path to the cloned repo inside the container - * $CLAUDE_WORKSPACE_CONTEXT – bash variable resolved at container start-up - * (set to "repository", "issue #N", or "PR #N") + * Edit this file to change the global agent behaviour across all providers. + * + * Placeholders resolved at TypeScript render time: + * __TARGET_DIR__ – absolute path to the cloned repo inside the container + * + * Placeholders resolved at container start-up (bash): + * workspaceContextBashVar – per-agent bash variable reference passed to + * renderSharedPrompt(), e.g. "$CLAUDE_WORKSPACE_CONTEXT" + */ + +export const PROMPT_INTRO = + `Ты автономный агент, который имеет полностью все права управления контейнером. ` + + `У тебя есть доступ к командам sudo, gh, codex, opencode, oh-my-opencode, sshpass, ` + + `claude, gemini, git, node, pnpm и всем остальным другим. ` + + `Проекты с которыми идёт работа лежат по пути ~` + +export const PROMPT_INTERNET = + `Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе.` + +export const PROMPT_SUBAGENTS = + `Для решения задач обязательно используй subagents. ` + + `Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю.` + +export const PROMPT_FILES = + `Если ты видишь файлы AGENTS.md, GEMINI.md или CLAUDE.md внутри проекта, ты обязан их читать и соблюдать инструкции.` + +/** + * Builds the full prompt string for heredoc injection (Claude, Gemini). + * + * @param workspaceContextBashVar – bash variable reference that will be + * interpolated at container start-up, e.g. "$CLAUDE_WORKSPACE_CONTEXT" + * + * __TARGET_DIR__ is left as-is and replaced by each agent's render function. */ -export const claudeSystemPromptContent = `Ты автономный агент, который имеет полностью все права управления контейнером. У тебя есть доступ к командам sudo, gh, codex, opencode, oh-my-opencode, sshpass, claude, git, node, pnpm и всем остальным другим. Проекты с которыми идёт работа лежат по пути ~ -Рабочая папка проекта (git clone): __TARGET_DIR__ -Доступные workspace пути: __TARGET_DIR__ -$CLAUDE_WORKSPACE_CONTEXT -Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__ -Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе. -Для решения задач обязательно используй subagents. Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю. -Если ты видишь файлы AGENTS.md или CLAUDE.md внутри проекта, ты обязан их читать и соблюдать инструкции.` +export const renderSharedPrompt = (workspaceContextBashVar: string): string => + [ + PROMPT_INTRO, + `Рабочая папка проекта (git clone): __TARGET_DIR__`, + `Доступные workspace пути: __TARGET_DIR__`, + workspaceContextBashVar, + `Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__`, + PROMPT_INTERNET, + PROMPT_SUBAGENTS, + PROMPT_FILES, + ].join("\n") diff --git a/packages/lib/src/core/templates-entrypoint/codex.ts b/packages/lib/src/core/templates-entrypoint/codex.ts index a2b3b932..eac0e8bf 100644 --- a/packages/lib/src/core/templates-entrypoint/codex.ts +++ b/packages/lib/src/core/templates-entrypoint/codex.ts @@ -1,4 +1,5 @@ import type { TemplateConfig } from "../domain.js" +import { PROMPT_FILES, PROMPT_INTERNET, PROMPT_INTRO, PROMPT_SUBAGENTS } from "./claude-system-prompt.js" export { renderEntrypointCodexResumeHint } from "./codex-resume-hint.js" @@ -128,8 +129,8 @@ PROJECT_LINE="Рабочая папка проекта (git clone): __TARGET_DIR WORKSPACES_LINE="Доступные workspace пути: __TARGET_DIR__" WORKSPACE_INFO_LINE="Контекст workspace: repository" FOCUS_LINE="Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__" -INTERNET_LINE="Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе." -SUBAGENTS_LINE="Для решения задач обязательно используй subagents. Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю." +INTERNET_LINE="${PROMPT_INTERNET}" +SUBAGENTS_LINE="${PROMPT_SUBAGENTS}" if [[ "$REPO_REF" == issue-* ]]; then ISSUE_ID="$(printf "%s" "$REPO_REF" | sed -E 's#^issue-##')" ISSUE_URL="" @@ -176,9 +177,9 @@ $MANAGED_END EOF )" cat < "$AGENTS_PATH" -Ты автономный агент, который имеет полностью все права управления контейнером. У тебя есть доступ к командам sudo, gh, codex, opencode, oh-my-opencode, sshpass, git, node, pnpm и всем остальным другим. Проекты с которыми идёт работа лежат по пути ~ +${PROMPT_INTRO} $MANAGED_BLOCK -Если ты видишь файлы AGENTS.md внутри проекта, ты обязан их читать и соблюдать инструкции. +${PROMPT_FILES} EOF chown 1000:1000 "$AGENTS_PATH" || true fi diff --git a/packages/lib/src/core/templates-entrypoint/gemini.ts b/packages/lib/src/core/templates-entrypoint/gemini.ts index b7a6f8a0..f1bca144 100644 --- a/packages/lib/src/core/templates-entrypoint/gemini.ts +++ b/packages/lib/src/core/templates-entrypoint/gemini.ts @@ -1,4 +1,5 @@ import type { TemplateConfig } from "../domain.js" +import { renderSharedPrompt } from "./claude-system-prompt.js" // CHANGE: add Gemini CLI entrypoint configuration // WHY: enable Gemini CLI in Docker with automated auth, trust settings and MCP @@ -266,14 +267,7 @@ fi cat < "$GEMINI_MD_PATH" -Ты автономный агент, который имеет полностью все права управления контейнером. У тебя есть доступ к командам sudo, gh, codex, gemini, claude, opencode, oh-my-opencode, sshpass, git, node, pnpm и всем остальным другим. Проекты с которыми идёт работа лежат по пути ~ -Рабочая папка проекта (git clone): __TARGET_DIR__ -Доступные workspace пути: __TARGET_DIR__ -$GEMINI_WORKSPACE_CONTEXT -Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__ -Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе. -Для решения задач обязательно используй subagents. Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю. -Если ты видишь файлы AGENTS.md, GEMINI.md или CLAUDE.md внутри проекта, ты обязан их читать и соблюдать инструкции. +${renderSharedPrompt("$GEMINI_WORKSPACE_CONTEXT")} EOF chown 1000:1000 "$GEMINI_MD_PATH" || true` From 56240566a192e4858ac40cdf9b0f5c7e8fec52ab Mon Sep 17 00:00:00 2001 From: skulidropek <66840575+skulidropek@users.noreply.github.com> Date: Tue, 24 Mar 2026 15:09:22 +0000 Subject: [PATCH 3/3] refactor(lib): replace __PLACEHOLDER__ with direct ${} interpolation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - claude-system-prompt.ts: single clean template string via renderSharedPrompt(targetDir, workspaceContext) with ${} params; export PROMPT_* constants + renderFocusLine() for Codex - claude-extra-config.ts: renderClaudeGlobalPromptSetup() builds bash script inline — no module-level template, no .replaceAll() chains - gemini.ts: renderEntrypointGeminiNotice() same approach - codex.ts: FOCUS_LINE uses renderFocusLine() via __FOCUS_LINE__ stub (kept because the 100-line managed-block template stays module-level) Co-Authored-By: Claude Sonnet 4.6 --- .../claude-extra-config.ts | 42 +++++++------- .../claude-system-prompt.ts | 58 +++++++++---------- .../src/core/templates-entrypoint/codex.ts | 13 +++-- .../src/core/templates-entrypoint/gemini.ts | 15 +++-- 4 files changed, 60 insertions(+), 68 deletions(-) diff --git a/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts b/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts index f44503a0..ad28223c 100644 --- a/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts +++ b/packages/lib/src/core/templates-entrypoint/claude-extra-config.ts @@ -1,13 +1,27 @@ import type { TemplateConfig } from "../domain.js" import { renderSharedPrompt } from "./claude-system-prompt.js" -const entrypointClaudeGlobalPromptTemplate = String - .raw`# Claude Code: managed global memory (CLAUDE.md is auto-loaded by Claude Code) -CLAUDE_GLOBAL_PROMPT_FILE="/home/__SSH_USER__/.claude/CLAUDE.md" +const escapeForDoubleQuotes = (value: string): string => { + const backslash = String.fromCodePoint(92) + const quote = String.fromCodePoint(34) + const escapedBackslash = `${backslash}${backslash}` + const escapedQuote = `${backslash}${quote}` + return value + .replaceAll(backslash, escapedBackslash) + .replaceAll(quote, escapedQuote) +} + +export const renderClaudeGlobalPromptSetup = (config: TemplateConfig): string => { + const promptContent = renderSharedPrompt(config.targetDir, "$CLAUDE_WORKSPACE_CONTEXT") + const repoRefDefault = escapeForDoubleQuotes(config.repoRef) + const repoUrlDefault = escapeForDoubleQuotes(config.repoUrl) + + return String.raw`# Claude Code: managed global memory (CLAUDE.md is auto-loaded by Claude Code) +CLAUDE_GLOBAL_PROMPT_FILE="/home/${config.sshUser}/.claude/CLAUDE.md" CLAUDE_AUTO_SYSTEM_PROMPT="${"$"}{CLAUDE_AUTO_SYSTEM_PROMPT:-1}" CLAUDE_WORKSPACE_CONTEXT="Контекст workspace: repository" -REPO_REF_VALUE="${"$"}{REPO_REF:-__REPO_REF_DEFAULT__}" -REPO_URL_VALUE="${"$"}{REPO_URL:-__REPO_URL_DEFAULT__}" +REPO_REF_VALUE="${"$"}{REPO_REF:-${repoRefDefault}}" +REPO_URL_VALUE="${"$"}{REPO_URL:-${repoUrlDefault}}" if [[ "$REPO_REF_VALUE" == issue-* ]]; then ISSUE_ID_VALUE="$(printf "%s" "$REPO_REF_VALUE" | sed -E 's#^issue-##')" @@ -47,7 +61,7 @@ if [[ "$CLAUDE_AUTO_SYSTEM_PROMPT" == "1" ]]; then if [[ ! -f "$CLAUDE_GLOBAL_PROMPT_FILE" ]] || grep -q "^$" "$CLAUDE_GLOBAL_PROMPT_FILE"; then cat < "$CLAUDE_GLOBAL_PROMPT_FILE" -${renderSharedPrompt("$CLAUDE_WORKSPACE_CONTEXT")} +${promptContent} EOF chmod 0644 "$CLAUDE_GLOBAL_PROMPT_FILE" || true @@ -56,24 +70,8 @@ EOF fi export CLAUDE_AUTO_SYSTEM_PROMPT` - -const escapeForDoubleQuotes = (value: string): string => { - const backslash = String.fromCodePoint(92) - const quote = String.fromCodePoint(34) - const escapedBackslash = `${backslash}${backslash}` - const escapedQuote = `${backslash}${quote}` - return value - .replaceAll(backslash, escapedBackslash) - .replaceAll(quote, escapedQuote) } -export const renderClaudeGlobalPromptSetup = (config: TemplateConfig): string => - entrypointClaudeGlobalPromptTemplate - .replaceAll("__TARGET_DIR__", config.targetDir) - .replaceAll("__SSH_USER__", config.sshUser) - .replaceAll("__REPO_REF_DEFAULT__", escapeForDoubleQuotes(config.repoRef)) - .replaceAll("__REPO_URL_DEFAULT__", escapeForDoubleQuotes(config.repoUrl)) - export const renderClaudeWrapperSetup = (): string => String.raw`CLAUDE_WRAPPER_BIN="/usr/local/bin/claude" if command -v claude >/dev/null 2>&1; then diff --git a/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts b/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts index be508b0e..2ed18dd2 100644 --- a/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts +++ b/packages/lib/src/core/templates-entrypoint/claude-system-prompt.ts @@ -1,48 +1,42 @@ /** - * Shared system prompt injected into every agent (Claude, Gemini, Codex). + * Single source of truth for the agent system prompt. + * Edit this file to change behaviour across all providers (Claude, Gemini, Codex). * - * Edit this file to change the global agent behaviour across all providers. - * - * Placeholders resolved at TypeScript render time: - * __TARGET_DIR__ – absolute path to the cloned repo inside the container - * - * Placeholders resolved at container start-up (bash): - * workspaceContextBashVar – per-agent bash variable reference passed to - * renderSharedPrompt(), e.g. "$CLAUDE_WORKSPACE_CONTEXT" + * @param targetDir – absolute path to the repo inside the container + * @param workspaceContext – bash variable reference resolved at container start-up, + * e.g. "$CLAUDE_WORKSPACE_CONTEXT" */ -export const PROMPT_INTRO = +const INTRO = `Ты автономный агент, который имеет полностью все права управления контейнером. ` + `У тебя есть доступ к командам sudo, gh, codex, opencode, oh-my-opencode, sshpass, ` + `claude, gemini, git, node, pnpm и всем остальным другим. ` + `Проекты с которыми идёт работа лежат по пути ~` -export const PROMPT_INTERNET = +const INTERNET = `Доступ к интернету: есть. Если чего-то не знаешь — ищи в интернете или по кодовой базе.` -export const PROMPT_SUBAGENTS = +const SUBAGENTS = `Для решения задач обязательно используй subagents. ` + `Сам агент обязан выполнять финальную проверку, интеграцию и валидацию результата перед ответом пользователю.` -export const PROMPT_FILES = +const FILES = `Если ты видишь файлы AGENTS.md, GEMINI.md или CLAUDE.md внутри проекта, ты обязан их читать и соблюдать инструкции.` -/** - * Builds the full prompt string for heredoc injection (Claude, Gemini). - * - * @param workspaceContextBashVar – bash variable reference that will be - * interpolated at container start-up, e.g. "$CLAUDE_WORKSPACE_CONTEXT" - * - * __TARGET_DIR__ is left as-is and replaced by each agent's render function. - */ -export const renderSharedPrompt = (workspaceContextBashVar: string): string => - [ - PROMPT_INTRO, - `Рабочая папка проекта (git clone): __TARGET_DIR__`, - `Доступные workspace пути: __TARGET_DIR__`, - workspaceContextBashVar, - `Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__`, - PROMPT_INTERNET, - PROMPT_SUBAGENTS, - PROMPT_FILES, - ].join("\n") +// Used by Codex's bash-variable injection pattern +export const PROMPT_INTRO = INTRO +export const PROMPT_INTERNET = INTERNET +export const PROMPT_SUBAGENTS = SUBAGENTS +export const PROMPT_FILES = FILES +export const renderFocusLine = (targetDir: string): string => + `Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: ${targetDir}` + +export const renderSharedPrompt = (targetDir: string, workspaceContext: string): string => + `${INTRO} +Рабочая папка проекта (git clone): ${targetDir} +Доступные workspace пути: ${targetDir} +${workspaceContext} +${renderFocusLine(targetDir)} +${INTERNET} +${SUBAGENTS} +${FILES}` diff --git a/packages/lib/src/core/templates-entrypoint/codex.ts b/packages/lib/src/core/templates-entrypoint/codex.ts index eac0e8bf..e4cab144 100644 --- a/packages/lib/src/core/templates-entrypoint/codex.ts +++ b/packages/lib/src/core/templates-entrypoint/codex.ts @@ -1,5 +1,5 @@ import type { TemplateConfig } from "../domain.js" -import { PROMPT_FILES, PROMPT_INTERNET, PROMPT_INTRO, PROMPT_SUBAGENTS } from "./claude-system-prompt.js" +import { PROMPT_FILES, PROMPT_INTERNET, PROMPT_INTRO, PROMPT_SUBAGENTS, renderFocusLine } from "./claude-system-prompt.js" export { renderEntrypointCodexResumeHint } from "./codex-resume-hint.js" @@ -128,7 +128,7 @@ LEGACY_AGENTS_PATH="/home/__SSH_USER__/AGENTS.md" PROJECT_LINE="Рабочая папка проекта (git clone): __TARGET_DIR__" WORKSPACES_LINE="Доступные workspace пути: __TARGET_DIR__" WORKSPACE_INFO_LINE="Контекст workspace: repository" -FOCUS_LINE="Фокус задачи: работай только в workspace, который запрашивает пользователь. Текущий workspace: __TARGET_DIR__" +FOCUS_LINE="__FOCUS_LINE__" INTERNET_LINE="${PROMPT_INTERNET}" SUBAGENTS_LINE="${PROMPT_SUBAGENTS}" if [[ "$REPO_REF" == issue-* ]]; then @@ -230,7 +230,8 @@ if [[ -f "$LEGACY_AGENTS_PATH" && -f "$AGENTS_PATH" ]]; then fi` export const renderEntrypointAgentsNotice = (config: TemplateConfig): string => - entrypointAgentsNoticeTemplate.replaceAll("__CODEX_HOME__", config.codexHome).replaceAll( - "__SSH_USER__", - config.sshUser - ).replaceAll("__TARGET_DIR__", config.targetDir) + entrypointAgentsNoticeTemplate + .replaceAll("__CODEX_HOME__", config.codexHome) + .replaceAll("__SSH_USER__", config.sshUser) + .replaceAll("__TARGET_DIR__", config.targetDir) + .replaceAll("__FOCUS_LINE__", renderFocusLine(config.targetDir)) diff --git a/packages/lib/src/core/templates-entrypoint/gemini.ts b/packages/lib/src/core/templates-entrypoint/gemini.ts index f1bca144..9b10fdf3 100644 --- a/packages/lib/src/core/templates-entrypoint/gemini.ts +++ b/packages/lib/src/core/templates-entrypoint/gemini.ts @@ -230,8 +230,11 @@ docker_git_upsert_ssh_env "GEMINI_CLI_DISABLE_UPDATE_CHECK" "true" docker_git_upsert_ssh_env "GEMINI_CLI_NONINTERACTIVE" "true" docker_git_upsert_ssh_env "GEMINI_CLI_APPROVAL_MODE" "yolo"` -const entrypointGeminiNoticeTemplate = String.raw`# Ensure global GEMINI.md exists for container context -GEMINI_MD_PATH="__GEMINI_HOME__/GEMINI.md" +const renderEntrypointGeminiNotice = (config: TemplateConfig): string => { + const promptContent = renderSharedPrompt(config.targetDir, "$GEMINI_WORKSPACE_CONTEXT") + + return String.raw`# Ensure global GEMINI.md exists for container context +GEMINI_MD_PATH="${config.geminiHome}/GEMINI.md" GEMINI_WORKSPACE_CONTEXT="Контекст workspace: repository" if [[ "$REPO_REF" == issue-* ]]; then ISSUE_ID="$(printf "%s" "$REPO_REF" | sed -E 's#^issue-##')" @@ -267,15 +270,11 @@ fi cat < "$GEMINI_MD_PATH" -${renderSharedPrompt("$GEMINI_WORKSPACE_CONTEXT")} +${promptContent} EOF chown 1000:1000 "$GEMINI_MD_PATH" || true` - -const renderEntrypointGeminiNotice = (config: TemplateConfig): string => - entrypointGeminiNoticeTemplate - .replaceAll("__GEMINI_HOME__", config.geminiHome) - .replaceAll("__TARGET_DIR__", config.targetDir) +} export const renderEntrypointGeminiConfig = (config: TemplateConfig): string => [