Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions packages/lib/src/core/templates-entrypoint/codex-resume-hint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import type { TemplateConfig } from "../domain.js"

const escapeForDoubleQuotes = (value: string): string => {
const backslash = String.fromCodePoint(92)
return value
.replaceAll(backslash, `${backslash}${backslash}`)
.replaceAll(String.fromCodePoint(34), `${backslash}${String.fromCodePoint(34)}`)
}

const entrypointCodexResumeHintTemplate = `# Ensure codex resume hint is shown for interactive shells
CODEX_HINT_PATH="/etc/profile.d/zz-codex-resume.sh"
if [[ ! -s "$CODEX_HINT_PATH" ]]; then
cat <<'EOF' > "$CODEX_HINT_PATH"
docker_git_workspace_context_line() {
REPO_REF_VALUE="\${REPO_REF:-__REPO_REF_DEFAULT__}"
REPO_URL_VALUE="\${REPO_URL:-__REPO_URL_DEFAULT__}"

if [[ "$REPO_REF_VALUE" == issue-* ]]; then
ISSUE_ID_VALUE="$(printf "%s" "$REPO_REF_VALUE" | sed -E 's#^issue-##')"
ISSUE_URL_VALUE=""
if [[ "$REPO_URL_VALUE" == https://github.com/* ]]; then
ISSUE_REPO_VALUE="$(printf "%s" "$REPO_URL_VALUE" | sed -E 's#^https://github.com/##; s#[.]git$##; s#/*$##')"
if [[ -n "$ISSUE_REPO_VALUE" ]]; then
ISSUE_URL_VALUE="https://github.com/$ISSUE_REPO_VALUE/issues/$ISSUE_ID_VALUE"
fi
fi
if [[ -n "$ISSUE_URL_VALUE" ]]; then
printf "%s\n" "Контекст workspace: issue #$ISSUE_ID_VALUE ($ISSUE_URL_VALUE)"
else
printf "%s\n" "Контекст workspace: issue #$ISSUE_ID_VALUE"
fi
return
fi

if [[ "$REPO_REF_VALUE" == refs/pull/*/head ]]; then
PR_ID_VALUE="$(printf "%s" "$REPO_REF_VALUE" | sed -nE 's#^refs/pull/([0-9]+)/head$#\\1#p')"
PR_URL_VALUE=""
if [[ "$REPO_URL_VALUE" == https://github.com/* && -n "$PR_ID_VALUE" ]]; then
PR_REPO_VALUE="$(printf "%s" "$REPO_URL_VALUE" | sed -E 's#^https://github.com/##; s#[.]git$##; s#/*$##')"
if [[ -n "$PR_REPO_VALUE" ]]; then
PR_URL_VALUE="https://github.com/$PR_REPO_VALUE/pull/$PR_ID_VALUE"
fi
fi
if [[ -n "$PR_ID_VALUE" && -n "$PR_URL_VALUE" ]]; then
printf "%s\n" "Контекст workspace: PR #$PR_ID_VALUE ($PR_URL_VALUE)"
elif [[ -n "$PR_ID_VALUE" ]]; then
printf "%s\n" "Контекст workspace: PR #$PR_ID_VALUE"
elif [[ -n "$REPO_REF_VALUE" ]]; then
printf "%s\n" "Контекст workspace: pull request ($REPO_REF_VALUE)"
fi
return
fi

if [[ -n "$REPO_URL_VALUE" ]]; then
printf "%s\n" "Контекст workspace: $REPO_URL_VALUE"
fi
}

docker_git_print_codex_resume_hint() {
if [ -z "\${CODEX_RESUME_HINT_SHOWN-}" ]; then
DOCKER_GIT_CONTEXT_LINE="$(docker_git_workspace_context_line)"
if [[ -n "$DOCKER_GIT_CONTEXT_LINE" ]]; then
echo "$DOCKER_GIT_CONTEXT_LINE"
fi
echo "Старые сессии можно запустить с помощью codex resume или codex resume <id>, если знаешь айди."
export CODEX_RESUME_HINT_SHOWN=1
fi
}

if [ -n "$BASH_VERSION" ]; then
case "$-" in
*i*)
docker_git_print_codex_resume_hint
;;
esac
fi
if [ -n "$ZSH_VERSION" ]; then
if [[ "$-" == *i* ]]; then
docker_git_print_codex_resume_hint
fi
fi
EOF
chmod 0644 "$CODEX_HINT_PATH"
fi
if ! grep -q "zz-codex-resume.sh" /etc/bash.bashrc 2>/dev/null; then
printf "%s\\n" "if [ -f /etc/profile.d/zz-codex-resume.sh ]; then . /etc/profile.d/zz-codex-resume.sh; fi" >> /etc/bash.bashrc
fi
if [[ -s /etc/zsh/zshrc ]] && ! grep -q "zz-codex-resume.sh" /etc/zsh/zshrc 2>/dev/null; then
printf "%s\\n" "if [ -f /etc/profile.d/zz-codex-resume.sh ]; then source /etc/profile.d/zz-codex-resume.sh; fi" >> /etc/zsh/zshrc
fi`

// PURITY: CORE
// INVARIANT: rendered output contains shell-escaped repo ref and url placeholders
// COMPLEXITY: O(1)
export const renderEntrypointCodexResumeHint = (config: TemplateConfig): string =>
entrypointCodexResumeHintTemplate
.replaceAll("__REPO_REF_DEFAULT__", escapeForDoubleQuotes(config.repoRef))
.replaceAll("__REPO_URL_DEFAULT__", escapeForDoubleQuotes(config.repoUrl))
104 changes: 8 additions & 96 deletions packages/lib/src/core/templates-entrypoint/codex.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { TemplateConfig } from "../domain.js"
export { renderEntrypointCodexResumeHint } from "./codex-resume-hint.js"

export const renderEntrypointCodexHome = (config: TemplateConfig): string =>
`# Ensure Codex home exists if mounted
Expand Down Expand Up @@ -65,8 +66,6 @@ else
cat <<'EOF' > "$CODEX_CONFIG_FILE"
# docker-git codex config
model = "gpt-5.4"
model_context_window = 1050000
model_auto_compact_token_limit = 945000
model_reasoning_effort = "xhigh"
plan_mode_reasoning_effort = "xhigh"
personality = "pragmatic"
Expand All @@ -80,6 +79,13 @@ shell_snapshot = true
multi_agent = true
apps = true
shell_tool = true

[profiles.longcontx]
model = "gpt-5.4"
model_context_window = 1050000
model_auto_compact_token_limit = 945000
model_reasoning_effort = "xhigh"
plan_mode_reasoning_effort = "xhigh"
EOF
chown 1000:1000 "$CODEX_CONFIG_FILE" || true
fi
Expand Down Expand Up @@ -114,100 +120,6 @@ export const renderEntrypointMcpPlaywright = (config: TemplateConfig): string =>
.replaceAll("__CODEX_HOME__", config.codexHome)
.replaceAll("__SERVICE_NAME__", config.serviceName)

const entrypointCodexResumeHintTemplate = `# Ensure codex resume hint is shown for interactive shells
CODEX_HINT_PATH="/etc/profile.d/zz-codex-resume.sh"
if [[ ! -s "$CODEX_HINT_PATH" ]]; then
cat <<'EOF' > "$CODEX_HINT_PATH"
docker_git_workspace_context_line() {
REPO_REF_VALUE="\${REPO_REF:-__REPO_REF_DEFAULT__}"
REPO_URL_VALUE="\${REPO_URL:-__REPO_URL_DEFAULT__}"

if [[ "$REPO_REF_VALUE" == issue-* ]]; then
ISSUE_ID_VALUE="$(printf "%s" "$REPO_REF_VALUE" | sed -E 's#^issue-##')"
ISSUE_URL_VALUE=""
if [[ "$REPO_URL_VALUE" == https://github.com/* ]]; then
ISSUE_REPO_VALUE="$(printf "%s" "$REPO_URL_VALUE" | sed -E 's#^https://github.com/##; s#[.]git$##; s#/*$##')"
if [[ -n "$ISSUE_REPO_VALUE" ]]; then
ISSUE_URL_VALUE="https://github.com/$ISSUE_REPO_VALUE/issues/$ISSUE_ID_VALUE"
fi
fi
if [[ -n "$ISSUE_URL_VALUE" ]]; then
printf "%s\n" "Контекст workspace: issue #$ISSUE_ID_VALUE ($ISSUE_URL_VALUE)"
else
printf "%s\n" "Контекст workspace: issue #$ISSUE_ID_VALUE"
fi
return
fi

if [[ "$REPO_REF_VALUE" == refs/pull/*/head ]]; then
PR_ID_VALUE="$(printf "%s" "$REPO_REF_VALUE" | sed -nE 's#^refs/pull/([0-9]+)/head$#\\1#p')"
PR_URL_VALUE=""
if [[ "$REPO_URL_VALUE" == https://github.com/* && -n "$PR_ID_VALUE" ]]; then
PR_REPO_VALUE="$(printf "%s" "$REPO_URL_VALUE" | sed -E 's#^https://github.com/##; s#[.]git$##; s#/*$##')"
if [[ -n "$PR_REPO_VALUE" ]]; then
PR_URL_VALUE="https://github.com/$PR_REPO_VALUE/pull/$PR_ID_VALUE"
fi
fi
if [[ -n "$PR_ID_VALUE" && -n "$PR_URL_VALUE" ]]; then
printf "%s\n" "Контекст workspace: PR #$PR_ID_VALUE ($PR_URL_VALUE)"
elif [[ -n "$PR_ID_VALUE" ]]; then
printf "%s\n" "Контекст workspace: PR #$PR_ID_VALUE"
elif [[ -n "$REPO_REF_VALUE" ]]; then
printf "%s\n" "Контекст workspace: pull request ($REPO_REF_VALUE)"
fi
return
fi

if [[ -n "$REPO_URL_VALUE" ]]; then
printf "%s\n" "Контекст workspace: $REPO_URL_VALUE"
fi
}

docker_git_print_codex_resume_hint() {
if [ -z "\${CODEX_RESUME_HINT_SHOWN-}" ]; then
DOCKER_GIT_CONTEXT_LINE="$(docker_git_workspace_context_line)"
if [[ -n "$DOCKER_GIT_CONTEXT_LINE" ]]; then
echo "$DOCKER_GIT_CONTEXT_LINE"
fi
echo "Старые сессии можно запустить с помощью codex resume или codex resume <id>, если знаешь айди."
export CODEX_RESUME_HINT_SHOWN=1
fi
}

if [ -n "$BASH_VERSION" ]; then
case "$-" in
*i*)
docker_git_print_codex_resume_hint
;;
esac
fi
if [ -n "$ZSH_VERSION" ]; then
if [[ "$-" == *i* ]]; then
docker_git_print_codex_resume_hint
fi
fi
EOF
chmod 0644 "$CODEX_HINT_PATH"
fi
if ! grep -q "zz-codex-resume.sh" /etc/bash.bashrc 2>/dev/null; then
printf "%s\\n" "if [ -f /etc/profile.d/zz-codex-resume.sh ]; then . /etc/profile.d/zz-codex-resume.sh; fi" >> /etc/bash.bashrc
fi
if [[ -s /etc/zsh/zshrc ]] && ! grep -q "zz-codex-resume.sh" /etc/zsh/zshrc 2>/dev/null; then
printf "%s\\n" "if [ -f /etc/profile.d/zz-codex-resume.sh ]; then source /etc/profile.d/zz-codex-resume.sh; fi" >> /etc/zsh/zshrc
fi`

const escapeForDoubleQuotes = (value: string): string => {
const backslash = String.fromCodePoint(92)
return value
.replaceAll(backslash, `${backslash}${backslash}`)
.replaceAll(String.fromCodePoint(34), `${backslash}${String.fromCodePoint(34)}`)
}

export const renderEntrypointCodexResumeHint = (config: TemplateConfig): string =>
entrypointCodexResumeHintTemplate
.replaceAll("__REPO_REF_DEFAULT__", escapeForDoubleQuotes(config.repoRef))
.replaceAll("__REPO_URL_DEFAULT__", escapeForDoubleQuotes(config.repoUrl))

const entrypointAgentsNoticeTemplate = String.raw`# Ensure global AGENTS.md exists for container context
AGENTS_PATH="__CODEX_HOME__/AGENTS.md"
LEGACY_AGENTS_PATH="/home/__SSH_USER__/AGENTS.md"
Expand Down
23 changes: 14 additions & 9 deletions packages/lib/src/usecases/auth-sync-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,19 @@ const JsonRecordFromStringSchema = Schema.parseJson(JsonRecordSchema)
const defaultEnvContents = "# docker-git env\n# KEY=value\n"
const codexConfigMarker = "# docker-git codex config"

// CHANGE: switch default model to gpt-5.4 and pin xhigh reasoning for default + plan mode
// WHY: keep plan mode aligned with development mode while preserving long-context defaults
// QUOTE(ТЗ): "Сделать plan mode тоже с xhigh режимом как и разработка по дефолту. Так же заменить модель на gpt-5.4"
// REF: github-issue-109
// CHANGE: move model_context_window and model_auto_compact_token_limit to [profiles.longcontx]
// WHY: global context window settings apply to all models; profile-scoped settings allow opt-in
// QUOTE(ТЗ): "добавь longcontx"
// REF: github-issue-183
// SOURCE: n/a
// FORMAT THEOREM: ∀c: config(c) -> model(c)="gpt-5.4" ∧ reasoning(c)=xhigh ∧ plan_reasoning(c)=xhigh
// FORMAT THEOREM: ∀c: config(c) -> model(c)="gpt-5.4" ∧ reasoning(c)=xhigh ∧ longcontx_profile(c)=defined
// PURITY: CORE
// EFFECT: n/a
// INVARIANT: default config stays deterministic
// INVARIANT: default config stays deterministic; longcontx profile always present
// COMPLEXITY: O(1)
export const defaultCodexConfig = [
"# docker-git codex config",
"model = \"gpt-5.4\"",
"model_context_window = 1050000",
"model_auto_compact_token_limit = 945000",
"model_reasoning_effort = \"xhigh\"",
"plan_mode_reasoning_effort = \"xhigh\"",
"personality = \"pragmatic\"",
Expand All @@ -56,7 +54,14 @@ export const defaultCodexConfig = [
"shell_snapshot = true",
"multi_agent = true",
"apps = true",
"shell_tool = true"
"shell_tool = true",
"",
"[profiles.longcontx]",
"model = \"gpt-5.4\"",
"model_context_window = 1050000",
"model_auto_compact_token_limit = 945000",
"model_reasoning_effort = \"xhigh\"",
"plan_mode_reasoning_effort = \"xhigh\""
].join("\n")

export const resolvePathFromBase = (
Expand Down