param( [Parameter(Mandatory = $true)] [string]$TaskFile, [Parameter(Mandatory = $true)] [string]$ReportFile, [string]$ProjectRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path, [string]$Model = "glm-5", [string]$BaseUrl = $(if ($env:ANTHROPIC_BASE_URL) { $env:ANTHROPIC_BASE_URL } else { "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic" }), [string]$AuthToken = $env:ANTHROPIC_AUTH_TOKEN, [string]$AgentsFile = (Join-Path $PSScriptRoot "glm_agents.team.json"), [string]$TelegramBotToken = $env:TELEGRAM_BOT_TOKEN, [string]$TelegramChatId = $env:TELEGRAM_CHAT_ID, [string]$TelegramConfigPath = (Join-Path $PSScriptRoot "telegram.local.json"), [switch]$VerboseLogs ) $ErrorActionPreference = "Stop" function Require-Command([string]$Name) { if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) { throw "Command not found: $Name" } } function Require-File([string]$PathValue, [string]$Label) { if (-not (Test-Path -LiteralPath $PathValue)) { throw "$Label not found: $PathValue" } } function Resolve-RepoPath([string]$BasePath, [string]$TargetPath) { if ([System.IO.Path]::IsPathRooted($TargetPath)) { return [System.IO.Path]::GetFullPath($TargetPath) } return [System.IO.Path]::GetFullPath((Join-Path $BasePath $TargetPath)) } function Resolve-TelegramSettings() { if (([string]::IsNullOrWhiteSpace($TelegramBotToken) -or [string]::IsNullOrWhiteSpace($TelegramChatId)) -and (Test-Path -LiteralPath $TelegramConfigPath)) { $config = Get-Content -LiteralPath $TelegramConfigPath -Raw | ConvertFrom-Json if ([string]::IsNullOrWhiteSpace($TelegramBotToken)) { $script:TelegramBotToken = $config.bot_token } if ([string]::IsNullOrWhiteSpace($TelegramChatId)) { $script:TelegramChatId = $config.chat_id } } } function Send-RunNotification([string]$Message) { Resolve-TelegramSettings if ([string]::IsNullOrWhiteSpace($TelegramBotToken) -or [string]::IsNullOrWhiteSpace($TelegramChatId)) { return } $notifier = Join-Path $PSScriptRoot "send_telegram_notification.ps1" try { & $notifier -Message $Message -BotToken $TelegramBotToken -ChatId $TelegramChatId -ConfigPath $TelegramConfigPath } catch { Write-Warning ("Telegram notification failed: " + $_.Exception.Message) } } Require-Command "claude" Require-File $TaskFile "Task file" if ([string]::IsNullOrWhiteSpace($BaseUrl)) { throw "ANTHROPIC_BASE_URL is not set. Pass -BaseUrl or export the env var first." } if ([string]::IsNullOrWhiteSpace($AuthToken)) { throw "ANTHROPIC_AUTH_TOKEN is not set. Pass -AuthToken or export the env var first." } $env:ANTHROPIC_BASE_URL = $BaseUrl $env:ANTHROPIC_AUTH_TOKEN = $AuthToken $env:CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1" $env:ANTHROPIC_MODEL = $Model $env:ANTHROPIC_SMALL_FAST_MODEL = $Model $env:ANTHROPIC_DEFAULT_HAIKU_MODEL = $Model $env:ANTHROPIC_DEFAULT_SONNET_MODEL = $Model $env:ANTHROPIC_DEFAULT_OPUS_MODEL = $Model $taskPath = (Resolve-Path -LiteralPath $TaskFile).Path $projectPath = (Resolve-Path -LiteralPath $ProjectRoot).Path $reportPath = Resolve-RepoPath $projectPath $ReportFile $reportDir = Split-Path -Parent $reportPath New-Item -ItemType Directory -Force -Path $reportDir | Out-Null $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" $runDir = Join-Path $projectPath ("automation\\runs\\glm_" + $timestamp) New-Item -ItemType Directory -Force -Path $runDir | Out-Null $stdoutPath = Join-Path $runDir "glm_stdout.txt" $prompt = @" You are running as the GLM worker on this Windows repository. Repository root: $projectPath Task file to follow exactly: $taskPath You must: 1. Read the task markdown and implement the requested changes in the repository. 2. Run the validations requested by the task. 3. Create or overwrite this report file with a truthful report: $reportPath 4. Do not overclaim. If something is incomplete, say so explicitly in the report. 5. Keep the diff focused. 6. If custom agents are available, use them aggressively and in parallel where safe: - planner first - implementer_core and implementer_aux for disjoint work - validator before finishing - retrieval_reviewer or runtime_guard when relevant - reporter last Open and follow the task markdown from disk instead of asking for the task again. "@ $claudeArgs = @( "-p", "--dangerously-skip-permissions", "--effort", "max", "--model", $Model, "--add-dir", $projectPath ) if (-not [string]::IsNullOrWhiteSpace($AgentsFile)) { $agentsPath = (Resolve-Path -LiteralPath $AgentsFile).Path $claudeArgs += @("--agents", (Get-Content -LiteralPath $agentsPath -Raw)) } if ($VerboseLogs) { $claudeArgs += "--verbose" } Write-Host "Running GLM worker with model $Model..." Send-RunNotification("GLM worker started: $(Split-Path -Leaf $taskPath)") try { $prompt | & claude @claudeArgs 2>&1 | Tee-Object -FilePath $stdoutPath } catch { Send-RunNotification("GLM worker failed: $(Split-Path -Leaf $taskPath)`n$($_.Exception.Message)") throw } if (-not (Test-Path -LiteralPath $reportPath)) { Send-RunNotification("GLM worker failed: missing report for $(Split-Path -Leaf $taskPath)") throw "GLM finished but did not create the expected report file: $reportPath" } Send-RunNotification("GLM worker finished: $(Split-Path -Leaf $taskPath)`nReport: $(Split-Path -Leaf $reportPath)") Write-Host "" Write-Host "GLM cycle finished." Write-Host "Task: $taskPath" Write-Host "Report: $reportPath" Write-Host "Stdout: $stdoutPath"