From 733615d889d4fe33d557cc6340c8ddfa364123ef Mon Sep 17 00:00:00 2001 From: Liang Jiaqing Date: Wed, 22 Jul 2026 23:38:10 +0800 Subject: [PATCH] fix: sticky llm_no on reload, portal UX, mainland install without Git - agentmain: keep current LLM across mykey hot-reload by backend.name - stapp: fix DeltaGenerator leak from ternary, update reopen_page wording - ga_install: mainland mode skips PortableGit, use NJU python mirror + --no-bin - ga: block start_long_term_update before turn 10 --- agentmain.py | 6 ++-- assets/ga_install.ps1 | 78 +++++++++++++++++++++++++------------------ frontends/stapp.py | 7 ++-- ga.py | 1 + 4 files changed, 54 insertions(+), 38 deletions(-) diff --git a/agentmain.py b/agentmain.py index da7b37c9..7d73cb7f 100644 --- a/agentmain.py +++ b/agentmain.py @@ -63,8 +63,8 @@ class GenericAgent: def load_llm_sessions(self): mykeys, changed = reload_mykeys() if not changed and hasattr(self, 'llmclients'): return - try: oldhistory = self.llmclient.backend.history - except: oldhistory = None + try: oldhistory, oldname = self.llmclient.backend.history, self.llmclient.backend.name + except: oldhistory = oldname = None llm_sessions = [] for k, cfg in mykeys.items(): if not any(x in k for x in ['api', 'config', 'cookie']): continue @@ -81,6 +81,8 @@ class GenericAgent: except Exception as e: print(f'\n\n\n[ERROR] Failed to init MixinSession with cfg {s["mixin_cfg"]}: {e}!!!\n\n') self.llmclients = llm_sessions if not self.llmclients: return + names = [c.backend.name for c in self.llmclients] + if oldname in names: self.llm_no = names.index(oldname) self.llmclient = self.llmclients[self.llm_no%len(self.llmclients)] if oldhistory: self.llmclient.backend.history = oldhistory diff --git a/assets/ga_install.ps1 b/assets/ga_install.ps1 index 5d5e1950..1f7b13d1 100644 --- a/assets/ga_install.ps1 +++ b/assets/ga_install.ps1 @@ -8,7 +8,7 @@ GenericAgent one-click portable deployer for Windows. Modes: - Default/Mainland: download GenericAgent.zip + uv + PortableGit from user's VPS, set China PyPI mirror. + Default/Mainland: download GenericAgent.zip + uv from user's VPS, set China PyPI mirror; no Git download. GLOBAL=1: clone GenericAgent from GitHub; uv and PortableGit also come from GitHub releases; no PyPI mirror. @@ -16,7 +16,7 @@ Modes: Portable components are installed under \.portable: - uv, Python installed by uv, PortableGit. + uv and Python installed by uv; GLOBAL=1 also installs PortableGit. #> @@ -64,6 +64,8 @@ $Deps = @("requests>=2.28", "beautifulsoup4>=4.12", "bottle>=0.12", "simple-webs $MainlandIndex = "https://pypi.tuna.tsinghua.edu.cn/simple" +$MainlandPythonMirror = "https://mirror.nju.edu.cn/github-release/astral-sh/python-build-standalone" + $GlobalMode = ($env:GLOBAL -eq "1") if ($GlobalMode) { @@ -243,7 +245,11 @@ if (Test-Path $uvPyDir) { Say "Installing Python $PythonVersion via uv" -$ec = Invoke-Native { & $UvExe python install $PythonVersion } +$pythonInstallArgs = @("python", "install", $PythonVersion, "--no-bin") + +if (!$GlobalMode) { $pythonInstallArgs += @("--mirror", $MainlandPythonMirror) } + +$ec = Invoke-Native { & $UvExe @pythonInstallArgs } if ($ec -ne 0) { Die "uv python install failed" } @@ -255,37 +261,43 @@ Ok "Python: $(& $PythonExe --version)" -# PortableGit (GitHub release in GLOBAL mode, user's VPS otherwise). Needed for GLOBAL=1 and useful for user shell. - -if (!(Test-Path $GitExe) -or $Force) { - - Download-File $GitUrl $GitExeArchive - - if (Test-Path $GitDir) { Remove-Item -Recurse -Force $GitDir } - - New-Item -ItemType Directory -Force -Path $GitDir | Out-Null - - Say "Extracting PortableGit" - - $ec = Invoke-Native { & $GitExeArchive -y -o"$GitDir" | Out-Null } - - if ($ec -ne 0) { Die "PortableGit extraction failed" } - -} - -if (!(Test-Path $GitExe)) { Die "git.exe missing: $GitExe" } - -Ok "Git: $(& $GitExe --version)" - - - $PythonDir = Split-Path $PythonExe -Parent -$GitBin = Split-Path $GitExe -Parent +if ($GlobalMode) { -$GitUsrBin = Join-Path $GitDir "usr\bin" + # GLOBAL=1 needs PortableGit to clone GenericAgent from GitHub. -$env:PATH = "$Bin;$PythonDir;$PythonDir\Scripts;$GitBin;$GitUsrBin;$env:PATH" + if (!(Test-Path $GitExe) -or $Force) { + + Download-File $GitUrl $GitExeArchive + + if (Test-Path $GitDir) { Remove-Item -Recurse -Force $GitDir } + + New-Item -ItemType Directory -Force -Path $GitDir | Out-Null + + Say "Extracting PortableGit" + + $ec = Invoke-Native { & $GitExeArchive -y -o"$GitDir" | Out-Null } + + if ($ec -ne 0) { Die "PortableGit extraction failed" } + + } + + if (!(Test-Path $GitExe)) { Die "git.exe missing: $GitExe" } + + Ok "Git: $(& $GitExe --version)" + + $GitBin = Split-Path $GitExe -Parent + + $GitUsrBin = Join-Path $GitDir "usr\bin" + + $env:PATH = "$Bin;$PythonDir;$PythonDir\Scripts;$GitBin;$GitUsrBin;$env:PATH" + +} else { + + $env:PATH = "$Bin;$PythonDir;$PythonDir\Scripts;$env:PATH" + +} @@ -459,7 +471,7 @@ set "UV_DEFAULT_INDEX=$MainlandIndex" set "PIP_INDEX_URL=$MainlandIndex" -set "PATH=$Bin;$PythonDir;$PythonDir\Scripts;$GitBin;$GitUsrBin;%PATH%" +set "PATH=$Bin;$PythonDir;$PythonDir\Scripts;%PATH%" echo Activated GenericAgent portable env: %GENERICAGENT_HOME% @@ -481,7 +493,7 @@ echo Activated GenericAgent portable env: %GENERICAGENT_HOME% `$env:PIP_INDEX_URL = "$MainlandIndex" -`$env:PATH = "$Bin;$PythonDir;$PythonDir\Scripts;$GitBin;$GitUsrBin;`$env:PATH" +`$env:PATH = "$Bin;$PythonDir;$PythonDir\Scripts;`$env:PATH" Write-Host "Activated GenericAgent portable env: `$env:GENERICAGENT_HOME" -ForegroundColor Green @@ -497,7 +509,7 @@ Ok "Verification:" & $PythonExe --version -& $GitExe --version +if ($GlobalMode) { & $GitExe --version } & $PythonExe -c "import requests, bs4, bottle; print('deps ok')" diff --git a/frontends/stapp.py b/frontends/stapp.py index b0f3ab3d..a59fb80e 100644 --- a/frontends/stapp.py +++ b/frontends/stapp.py @@ -51,7 +51,7 @@ I18N = { 'get_token': '🔑 获取 Token', 'get_token_toast': '已打开浏览器', 'need_mykey': '⚠️ 请配置 mykey.py', - 'reopen_page': '请重新打开程序', + 'reopen_page': '等待配置写入,完成后将自动进入…', }, 'en': { 'force_stop': 'Force Stop', @@ -66,7 +66,7 @@ I18N = { 'get_token': '🔑 Get Token', 'get_token_toast': 'Opened in browser', 'need_mykey': '⚠️ Please set mykey.py', - 'reopen_page': 'Please restart the app', + 'reopen_page': 'Waiting for config… will enter automatically', }, } def T(key): return I18N.get(LANG, I18N['zh']).get(key, key) @@ -94,7 +94,8 @@ if not agent.llmclients and _sp: if "portal_wait" in st.session_state: _watch_portal() if not agent.llmclients: - st.warning(T("reopen_page")) if _sp else st.error(T("need_mykey")) + if _sp: st.warning(T("reopen_page")) + else: st.error(T("need_mykey")) st.stop() def build_prompt(objective): diff --git a/ga.py b/ga.py index 589e22fe..3662cfb2 100644 --- a/ga.py +++ b/ga.py @@ -539,6 +539,7 @@ class GenericAgentHandler(BaseHandler): path = './memory/memory_management_sop.md' if os.path.exists(path): result = 'This is L0:\n' + file_read(path, show_linenos=False) else: result = "Memory Management SOP not found. Do not update memory." + if self.current_turn < 10: result, prompt = 'start_long_term_update is only used after completing a long turn task!', '.\n' return StepOutcome(result, next_prompt=prompt) def _fold_earlier(self, lines):