agent-control-plane 0.1.16 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -14
- package/bin/pr-risk.sh +28 -6
- package/hooks/heartbeat-hooks.sh +62 -22
- package/npm/bin/agent-control-plane.js +322 -9
- package/package.json +1 -1
- package/references/architecture.md +8 -0
- package/references/control-plane-map.md +6 -2
- package/references/release-checklist.md +0 -2
- package/tools/bin/agent-github-update-labels +6 -1
- package/tools/bin/agent-project-catch-up-issue-pr-links +118 -0
- package/tools/bin/agent-project-catch-up-merged-prs +77 -21
- package/tools/bin/agent-project-catch-up-scheduled-issue-retries +123 -0
- package/tools/bin/agent-project-cleanup-session +84 -0
- package/tools/bin/agent-project-heartbeat-loop +10 -3
- package/tools/bin/agent-project-reconcile-issue-session +24 -12
- package/tools/bin/agent-project-run-claude-session +2 -2
- package/tools/bin/agent-project-run-kilo-session +346 -14
- package/tools/bin/agent-project-run-ollama-session +658 -0
- package/tools/bin/agent-project-run-openclaw-session +27 -25
- package/tools/bin/agent-project-run-opencode-session +354 -14
- package/tools/bin/agent-project-run-pi-session +479 -0
- package/tools/bin/agent-project-worker-status +1 -1
- package/tools/bin/flow-config-lib.sh +116 -3
- package/tools/bin/flow-resident-worker-lib.sh +1 -1
- package/tools/bin/flow-shell-lib.sh +5 -2
- package/tools/bin/heartbeat-recovery-preflight.sh +1 -0
- package/tools/bin/heartbeat-safe-auto.sh +105 -17
- package/tools/bin/install-project-launchd.sh +19 -2
- package/tools/bin/prepare-worktree.sh +4 -4
- package/tools/bin/profile-activate.sh +2 -2
- package/tools/bin/profile-adopt.sh +2 -2
- package/tools/bin/project-init.sh +1 -1
- package/tools/bin/project-runtimectl.sh +90 -7
- package/tools/bin/provider-cooldown-state.sh +14 -14
- package/tools/bin/render-flow-config.sh +30 -33
- package/tools/bin/run-codex-task.sh +53 -4
- package/tools/bin/scaffold-profile.sh +18 -3
- package/tools/bin/start-issue-worker.sh +1 -1
- package/tools/bin/start-pr-fix-worker.sh +30 -0
- package/tools/bin/start-pr-review-worker.sh +31 -0
- package/tools/bin/start-resident-issue-loop.sh +4 -4
- package/tools/bin/sync-agent-repo.sh +2 -2
- package/tools/bin/sync-dependency-baseline.sh +3 -3
- package/tools/bin/sync-shared-agent-home.sh +4 -1
- package/tools/templates/pr-fix-template.md +3 -7
- package/tools/templates/pr-merge-repair-template.md +3 -7
- package/tools/templates/pr-review-template.md +2 -1
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
usage() {
|
|
5
|
+
cat <<'EOF'
|
|
6
|
+
Usage:
|
|
7
|
+
agent-project-run-pi-session --mode safe|bypass --session <id> --worktree <path> --prompt-file <path> --runs-root <path> --adapter-id <id> --task-kind <kind> --task-id <id> [options]
|
|
8
|
+
|
|
9
|
+
Launch a Pi coding agent worker session inside tmux for a project adapter and
|
|
10
|
+
persist the standard run artifacts.
|
|
11
|
+
|
|
12
|
+
Pi supports any OpenRouter model (or other providers) via --model provider/id.
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--env-prefix <prefix> Export prefixed runtime/context env vars inside the worker
|
|
16
|
+
--context <KEY=VALUE> Extra metadata written to run.env and exported to the worker
|
|
17
|
+
--collect-file <name> Copy sandbox artifact file into the host run dir after execution
|
|
18
|
+
--reconcile-command <cmd> Host-side command queued after the worker exits
|
|
19
|
+
--sandbox-subdir <name> Subdir under the worktree for worker artifacts (default: .pi-artifacts)
|
|
20
|
+
--pi-model <id> Model ID for pi (e.g. openrouter/qwen/qwen3.6-plus:free)
|
|
21
|
+
--pi-thinking <level> Thinking level: off, minimal, low, medium, high, xhigh (default: low)
|
|
22
|
+
--pi-timeout-seconds <secs> Hard timeout in seconds (default: 900)
|
|
23
|
+
--pi-stall-seconds <secs> Abort if no output for this long, 0 disables (default: 300)
|
|
24
|
+
--help Show this help
|
|
25
|
+
EOF
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
mode=""
|
|
29
|
+
session=""
|
|
30
|
+
worktree=""
|
|
31
|
+
prompt_file=""
|
|
32
|
+
runs_root=""
|
|
33
|
+
adapter_id=""
|
|
34
|
+
task_kind=""
|
|
35
|
+
task_id=""
|
|
36
|
+
env_prefix=""
|
|
37
|
+
sandbox_subdir=".pi-artifacts"
|
|
38
|
+
reconcile_command=""
|
|
39
|
+
pi_model="${ACP_PI_MODEL:-${F_LOSNING_PI_MODEL:-openrouter/qwen/qwen3.6-plus:free}}"
|
|
40
|
+
pi_thinking="${ACP_PI_THINKING:-${F_LOSNING_PI_THINKING:-low}}"
|
|
41
|
+
pi_timeout_seconds="${ACP_PI_TIMEOUT_SECONDS:-${F_LOSNING_PI_TIMEOUT_SECONDS:-900}}"
|
|
42
|
+
pi_stall_seconds="${ACP_PI_STALL_SECONDS:-${F_LOSNING_PI_STALL_SECONDS:-300}}"
|
|
43
|
+
declare -a context_items=()
|
|
44
|
+
declare -a collect_files=()
|
|
45
|
+
|
|
46
|
+
while [[ $# -gt 0 ]]; do
|
|
47
|
+
case "$1" in
|
|
48
|
+
--mode) mode="${2:-}"; shift 2 ;;
|
|
49
|
+
--session) session="${2:-}"; shift 2 ;;
|
|
50
|
+
--worktree) worktree="${2:-}"; shift 2 ;;
|
|
51
|
+
--prompt-file) prompt_file="${2:-}"; shift 2 ;;
|
|
52
|
+
--runs-root) runs_root="${2:-}"; shift 2 ;;
|
|
53
|
+
--adapter-id) adapter_id="${2:-}"; shift 2 ;;
|
|
54
|
+
--task-kind) task_kind="${2:-}"; shift 2 ;;
|
|
55
|
+
--task-id) task_id="${2:-}"; shift 2 ;;
|
|
56
|
+
--env-prefix) env_prefix="${2:-}"; shift 2 ;;
|
|
57
|
+
--context) context_items+=("${2:-}"); shift 2 ;;
|
|
58
|
+
--collect-file) collect_files+=("${2:-}"); shift 2 ;;
|
|
59
|
+
--reconcile-command) reconcile_command="${2:-}"; shift 2 ;;
|
|
60
|
+
--sandbox-subdir) sandbox_subdir="${2:-}"; shift 2 ;;
|
|
61
|
+
--pi-model) pi_model="${2:-}"; shift 2 ;;
|
|
62
|
+
--pi-thinking) pi_thinking="${2:-}"; shift 2 ;;
|
|
63
|
+
--pi-timeout-seconds) pi_timeout_seconds="${2:-}"; shift 2 ;;
|
|
64
|
+
--pi-stall-seconds) pi_stall_seconds="${2:-}"; shift 2 ;;
|
|
65
|
+
--help|-h) usage; exit 0 ;;
|
|
66
|
+
*) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;;
|
|
67
|
+
esac
|
|
68
|
+
done
|
|
69
|
+
|
|
70
|
+
if [[ -z "$mode" || -z "$session" || -z "$worktree" || -z "$prompt_file" || -z "$runs_root" || -z "$adapter_id" || -z "$task_kind" || -z "$task_id" ]]; then
|
|
71
|
+
usage >&2
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
case "$mode" in
|
|
76
|
+
safe|bypass) ;;
|
|
77
|
+
*) echo "--mode must be safe or bypass" >&2; exit 1 ;;
|
|
78
|
+
esac
|
|
79
|
+
|
|
80
|
+
case "$pi_thinking" in
|
|
81
|
+
off|minimal|low|medium|high|xhigh) ;;
|
|
82
|
+
*) echo "--pi-thinking must be one of: off, minimal, low, medium, high, xhigh" >&2; exit 1 ;;
|
|
83
|
+
esac
|
|
84
|
+
|
|
85
|
+
case "$pi_timeout_seconds" in
|
|
86
|
+
''|*[!0-9]*|0) echo "--pi-timeout-seconds must be a positive integer" >&2; exit 1 ;;
|
|
87
|
+
esac
|
|
88
|
+
|
|
89
|
+
case "$pi_stall_seconds" in
|
|
90
|
+
''|*[!0-9]*) echo "--pi-stall-seconds must be numeric" >&2; exit 1 ;;
|
|
91
|
+
esac
|
|
92
|
+
|
|
93
|
+
resolve_pi_bin() {
|
|
94
|
+
local configured_bin="${PI_BIN:-${ACP_PI_BIN:-${F_LOSNING_PI_BIN:-}}}"
|
|
95
|
+
if [[ -n "${configured_bin}" && -x "${configured_bin}" ]]; then
|
|
96
|
+
printf '%s\n' "${configured_bin}"
|
|
97
|
+
return 0
|
|
98
|
+
fi
|
|
99
|
+
if command -v pi >/dev/null 2>&1; then
|
|
100
|
+
command -v pi
|
|
101
|
+
return 0
|
|
102
|
+
fi
|
|
103
|
+
local -a fallback_paths=(
|
|
104
|
+
"/opt/homebrew/bin/pi"
|
|
105
|
+
"/usr/local/bin/pi"
|
|
106
|
+
"${HOME}/.local/bin/pi"
|
|
107
|
+
"${HOME}/.nvm/versions/node/$(node --version 2>/dev/null || true)/bin/pi"
|
|
108
|
+
)
|
|
109
|
+
local p
|
|
110
|
+
for p in "${fallback_paths[@]}"; do
|
|
111
|
+
if [[ -x "${p}" ]]; then
|
|
112
|
+
printf '%s\n' "${p}"
|
|
113
|
+
return 0
|
|
114
|
+
fi
|
|
115
|
+
done
|
|
116
|
+
return 1
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
pi_bin="$(resolve_pi_bin || true)"
|
|
120
|
+
if [[ -z "${pi_bin}" || ! -x "${pi_bin}" ]]; then
|
|
121
|
+
echo "unable to resolve a runnable pi binary — install with: npm install -g @mariozechner/pi-coding-agent" >&2
|
|
122
|
+
exit 1
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
artifact_dir="${runs_root}/${session}"
|
|
126
|
+
output_file="${artifact_dir}/${session}.log"
|
|
127
|
+
inner_script="${artifact_dir}/${session}.sh"
|
|
128
|
+
meta_file="${artifact_dir}/run.env"
|
|
129
|
+
result_file="${artifact_dir}/result.env"
|
|
130
|
+
runner_state_file="${artifact_dir}/runner.env"
|
|
131
|
+
sandbox_run_dir="${worktree%/}/${sandbox_subdir}/${session}"
|
|
132
|
+
retained_repo_root="${ACP_RETAINED_REPO_ROOT:-${F_LOSNING_RETAINED_REPO_ROOT:-}}"
|
|
133
|
+
started_at="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
134
|
+
|
|
135
|
+
mkdir -p "$artifact_dir"
|
|
136
|
+
mkdir -p "$sandbox_run_dir"
|
|
137
|
+
|
|
138
|
+
if tmux has-session -t "$session" 2>/dev/null; then
|
|
139
|
+
echo "tmux session already exists: $session" >&2
|
|
140
|
+
exit 1
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
branch_name="$(git -C "$worktree" branch --show-current 2>/dev/null || true)"
|
|
144
|
+
|
|
145
|
+
printf -v session_q '%q' "$session"
|
|
146
|
+
printf -v task_kind_q '%q' "$task_kind"
|
|
147
|
+
printf -v task_id_q '%q' "$task_id"
|
|
148
|
+
printf -v mode_q '%q' "$mode"
|
|
149
|
+
printf -v worktree_q '%q' "$worktree"
|
|
150
|
+
printf -v prompt_q '%q' "$prompt_file"
|
|
151
|
+
printf -v output_q '%q' "$output_file"
|
|
152
|
+
printf -v artifact_dir_q '%q' "$artifact_dir"
|
|
153
|
+
printf -v script_q '%q' "$inner_script"
|
|
154
|
+
printf -v result_q '%q' "$result_file"
|
|
155
|
+
printf -v meta_file_q '%q' "$meta_file"
|
|
156
|
+
printf -v runner_state_q '%q' "$runner_state_file"
|
|
157
|
+
printf -v branch_q '%q' "$branch_name"
|
|
158
|
+
printf -v sandbox_run_dir_q '%q' "$sandbox_run_dir"
|
|
159
|
+
printf -v retained_repo_root_q '%q' "$retained_repo_root"
|
|
160
|
+
printf -v adapter_id_q '%q' "$adapter_id"
|
|
161
|
+
printf -v started_at_q '%q' "$started_at"
|
|
162
|
+
printf -v pi_bin_q '%q' "$pi_bin"
|
|
163
|
+
printf -v pi_model_q '%q' "$pi_model"
|
|
164
|
+
printf -v pi_thinking_q '%q' "$pi_thinking"
|
|
165
|
+
printf -v pi_timeout_q '%q' "$pi_timeout_seconds"
|
|
166
|
+
printf -v pi_stall_q '%q' "$pi_stall_seconds"
|
|
167
|
+
|
|
168
|
+
{
|
|
169
|
+
printf 'TASK_KIND=%s\n' "$task_kind_q"
|
|
170
|
+
printf 'TASK_ID=%s\n' "$task_id_q"
|
|
171
|
+
printf 'SESSION=%s\n' "$session_q"
|
|
172
|
+
printf 'MODE=%s\n' "$mode_q"
|
|
173
|
+
printf 'WORKTREE=%s\n' "$worktree_q"
|
|
174
|
+
printf 'PROMPT_FILE=%s\n' "$prompt_q"
|
|
175
|
+
printf 'OUTPUT_FILE=%s\n' "$output_q"
|
|
176
|
+
printf 'SCRIPT=%s\n' "$script_q"
|
|
177
|
+
printf 'BRANCH=%s\n' "$branch_q"
|
|
178
|
+
printf 'RESULT_FILE=%s\n' "$result_q"
|
|
179
|
+
printf 'RUNNER_STATE_FILE=%s\n' "$runner_state_q"
|
|
180
|
+
printf 'SANDBOX_RUN_DIR=%s\n' "$sandbox_run_dir_q"
|
|
181
|
+
printf 'ADAPTER_ID=%s\n' "$adapter_id_q"
|
|
182
|
+
printf 'STARTED_AT=%s\n' "$started_at_q"
|
|
183
|
+
printf 'PI_BIN=%s\n' "$pi_bin_q"
|
|
184
|
+
printf 'PI_MODEL=%s\n' "$pi_model_q"
|
|
185
|
+
printf 'PI_THINKING=%s\n' "$pi_thinking_q"
|
|
186
|
+
printf 'PI_TIMEOUT_SECONDS=%s\n' "$pi_timeout_q"
|
|
187
|
+
printf 'PI_STALL_SECONDS=%s\n' "$pi_stall_q"
|
|
188
|
+
} >"$meta_file"
|
|
189
|
+
|
|
190
|
+
context_exports=""
|
|
191
|
+
if ((${#context_items[@]} > 0)); then
|
|
192
|
+
for item in "${context_items[@]}"; do
|
|
193
|
+
if [[ "$item" != *=* ]]; then
|
|
194
|
+
echo "--context must use KEY=VALUE syntax: $item" >&2
|
|
195
|
+
exit 1
|
|
196
|
+
fi
|
|
197
|
+
key="${item%%=*}"
|
|
198
|
+
value="${item#*=}"
|
|
199
|
+
if [[ ! "$key" =~ ^[A-Z0-9_]+$ ]]; then
|
|
200
|
+
echo "Invalid context key: $key" >&2
|
|
201
|
+
exit 1
|
|
202
|
+
fi
|
|
203
|
+
printf -v value_q '%q' "$value"
|
|
204
|
+
printf '%s=%s\n' "$key" "$value_q" >>"$meta_file"
|
|
205
|
+
if [[ -n "$env_prefix" ]]; then
|
|
206
|
+
context_exports+="export ${env_prefix}${key}=${value_q}"$'\n'
|
|
207
|
+
fi
|
|
208
|
+
context_exports+="export ACP_${key}=${value_q}"$'\n'
|
|
209
|
+
if [[ "$env_prefix" != "F_LOSNING_" ]]; then
|
|
210
|
+
context_exports+="export F_LOSNING_${key}=${value_q}"$'\n'
|
|
211
|
+
fi
|
|
212
|
+
done
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
runtime_exports=$(
|
|
216
|
+
cat <<EOF
|
|
217
|
+
export AGENT_PROJECT_SESSION=${session_q}
|
|
218
|
+
export AGENT_PROJECT_RUN_DIR=${sandbox_run_dir_q}
|
|
219
|
+
export AGENT_PROJECT_HOST_RUN_DIR=${artifact_dir_q}
|
|
220
|
+
export AGENT_PROJECT_RESULT_FILE=${sandbox_run_dir_q}/result.env
|
|
221
|
+
export AGENT_PROJECT_PI_BIN=${pi_bin_q}
|
|
222
|
+
export AGENT_PROJECT_RETAINED_REPO_ROOT=${retained_repo_root_q}
|
|
223
|
+
export ACP_SESSION=${session_q}
|
|
224
|
+
export ACP_RUN_DIR=${sandbox_run_dir_q}
|
|
225
|
+
export ACP_HOST_RUN_DIR=${artifact_dir_q}
|
|
226
|
+
export ACP_RESULT_FILE=${sandbox_run_dir_q}/result.env
|
|
227
|
+
export ACP_PI_BIN=${pi_bin_q}
|
|
228
|
+
export ACP_PI_MODEL=${pi_model_q}
|
|
229
|
+
export ACP_PI_THINKING=${pi_thinking_q}
|
|
230
|
+
export ACP_PI_TIMEOUT_SECONDS=${pi_timeout_q}
|
|
231
|
+
export ACP_RETAINED_REPO_ROOT=${retained_repo_root_q}
|
|
232
|
+
export F_LOSNING_SESSION=${session_q}
|
|
233
|
+
export F_LOSNING_RUN_DIR=${sandbox_run_dir_q}
|
|
234
|
+
export F_LOSNING_HOST_RUN_DIR=${artifact_dir_q}
|
|
235
|
+
export F_LOSNING_RESULT_FILE=${sandbox_run_dir_q}/result.env
|
|
236
|
+
export F_LOSNING_PI_BIN=${pi_bin_q}
|
|
237
|
+
export F_LOSNING_PI_MODEL=${pi_model_q}
|
|
238
|
+
export F_LOSNING_PI_THINKING=${pi_thinking_q}
|
|
239
|
+
export F_LOSNING_PI_TIMEOUT_SECONDS=${pi_timeout_q}
|
|
240
|
+
export F_LOSNING_RETAINED_REPO_ROOT=${retained_repo_root_q}
|
|
241
|
+
EOF
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
if [[ -n "$env_prefix" ]]; then
|
|
245
|
+
runtime_exports+=$'\n'
|
|
246
|
+
runtime_exports+=$(cat <<EOF
|
|
247
|
+
export ${env_prefix}SESSION=${session_q}
|
|
248
|
+
export ${env_prefix}RUN_DIR=${sandbox_run_dir_q}
|
|
249
|
+
export ${env_prefix}HOST_RUN_DIR=${artifact_dir_q}
|
|
250
|
+
export ${env_prefix}RESULT_FILE=${sandbox_run_dir_q}/result.env
|
|
251
|
+
export ${env_prefix}PI_BIN=${pi_bin_q}
|
|
252
|
+
export ${env_prefix}PI_MODEL=${pi_model_q}
|
|
253
|
+
export ${env_prefix}PI_THINKING=${pi_thinking_q}
|
|
254
|
+
export ${env_prefix}PI_TIMEOUT_SECONDS=${pi_timeout_q}
|
|
255
|
+
EOF
|
|
256
|
+
)
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
collect_copy_snippet=""
|
|
260
|
+
if ((${#collect_files[@]} > 0)); then
|
|
261
|
+
for artifact_name in "${collect_files[@]}"; do
|
|
262
|
+
[[ -z "$artifact_name" ]] && continue
|
|
263
|
+
printf -v artifact_q '%q' "$artifact_name"
|
|
264
|
+
collect_copy_snippet+=$(
|
|
265
|
+
cat <<EOF
|
|
266
|
+
if [[ -f ${sandbox_run_dir_q}/${artifact_q} ]]; then
|
|
267
|
+
cp ${sandbox_run_dir_q}/${artifact_q} ${artifact_dir_q}/${artifact_q}
|
|
268
|
+
fi
|
|
269
|
+
EOF
|
|
270
|
+
)
|
|
271
|
+
collect_copy_snippet+=$'\n'
|
|
272
|
+
done
|
|
273
|
+
fi
|
|
274
|
+
|
|
275
|
+
# Always collect result.env from sandbox to artifact_dir
|
|
276
|
+
collect_copy_snippet+=$(
|
|
277
|
+
cat <<EOF
|
|
278
|
+
if [[ -f ${sandbox_run_dir_q}/result.env ]]; then
|
|
279
|
+
cp ${sandbox_run_dir_q}/result.env ${result_q}
|
|
280
|
+
fi
|
|
281
|
+
EOF
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
reconcile_snippet=""
|
|
285
|
+
if [[ -n "$reconcile_command" ]]; then
|
|
286
|
+
printf -v delayed_reconcile_q '%q' "export ACP_EXPECTED_RUN_STARTED_AT=${started_at_q}; export F_LOSNING_EXPECTED_RUN_STARTED_AT=${started_at_q}; while tmux has-session -t ${session_q} 2>/dev/null; do sleep 1; done; sleep 2; $reconcile_command"
|
|
287
|
+
reconcile_snippet="nohup bash -lc ${delayed_reconcile_q} >> ${output_q} 2>&1 </dev/null &"
|
|
288
|
+
fi
|
|
289
|
+
|
|
290
|
+
cat >"$inner_script" <<EOF
|
|
291
|
+
#!/usr/bin/env bash
|
|
292
|
+
set -euo pipefail
|
|
293
|
+
${runtime_exports}
|
|
294
|
+
${context_exports}cd ${worktree_q}
|
|
295
|
+
|
|
296
|
+
runner_state_file=${runner_state_q}
|
|
297
|
+
output_file=${output_q}
|
|
298
|
+
sandbox_run_dir=${sandbox_run_dir_q}
|
|
299
|
+
artifact_dir=${artifact_dir_q}
|
|
300
|
+
result_file_path=${sandbox_run_dir_q}/result.env
|
|
301
|
+
host_result_file=${result_q}
|
|
302
|
+
pi_bin=${pi_bin_q}
|
|
303
|
+
pi_model=${pi_model_q}
|
|
304
|
+
pi_thinking=${pi_thinking_q}
|
|
305
|
+
pi_timeout_seconds=${pi_timeout_q}
|
|
306
|
+
pi_stall_seconds=${pi_stall_q}
|
|
307
|
+
prompt_file=${prompt_q}
|
|
308
|
+
worktree=${worktree_q}
|
|
309
|
+
|
|
310
|
+
write_state() {
|
|
311
|
+
local runner_state="\${1:?runner state required}"
|
|
312
|
+
local last_exit_code="\${2:-}"
|
|
313
|
+
local failure_reason="\${3:-}"
|
|
314
|
+
local updated_at tmp_file
|
|
315
|
+
|
|
316
|
+
updated_at="\$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
317
|
+
tmp_file="\${runner_state_file}.tmp.\$\$"
|
|
318
|
+
{
|
|
319
|
+
printf 'RUNNER_STATE=%q\n' "\${runner_state}"
|
|
320
|
+
printf 'ATTEMPT=1\n'
|
|
321
|
+
printf 'RESUME_COUNT=0\n'
|
|
322
|
+
printf 'LAST_EXIT_CODE=%q\n' "\${last_exit_code}"
|
|
323
|
+
printf 'LAST_FAILURE_REASON=%q\n' "\${failure_reason}"
|
|
324
|
+
printf 'LAST_TRIGGER_REASON=%q\n' ''
|
|
325
|
+
printf 'AUTH_WAIT_STARTED_AT=%q\n' ''
|
|
326
|
+
printf 'UPDATED_AT=%q\n' "\${updated_at}"
|
|
327
|
+
} >"\${tmp_file}"
|
|
328
|
+
mv "\${tmp_file}" "\${runner_state_file}"
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
write_result_fallback() {
|
|
332
|
+
local detail="\${1:-missing-result-contract}"
|
|
333
|
+
local tmp_file
|
|
334
|
+
tmp_file="\${result_file_path}.tmp.\$\$"
|
|
335
|
+
{
|
|
336
|
+
printf 'OUTCOME=blocked\n'
|
|
337
|
+
printf 'ACTION=host-comment-blocker\n'
|
|
338
|
+
printf 'DETAIL=%s\n' "\${detail}"
|
|
339
|
+
} >"\${tmp_file}"
|
|
340
|
+
mv "\${tmp_file}" "\${result_file_path}"
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
record_final_git_state() {
|
|
344
|
+
local final_head final_branch tmp_file
|
|
345
|
+
final_head="\$(git -C ${worktree_q} rev-parse HEAD 2>/dev/null || true)"
|
|
346
|
+
final_branch="\$(git -C ${worktree_q} branch --show-current 2>/dev/null || true)"
|
|
347
|
+
tmp_file=${meta_file_q}.tmp.final.$$
|
|
348
|
+
grep -vE '^(FINAL_HEAD|FINAL_BRANCH)=' ${meta_file_q} >"\${tmp_file}" 2>/dev/null || true
|
|
349
|
+
{
|
|
350
|
+
printf 'FINAL_HEAD=%q\n' "\${final_head}"
|
|
351
|
+
printf 'FINAL_BRANCH=%q\n' "\${final_branch}"
|
|
352
|
+
} >>"\${tmp_file}"
|
|
353
|
+
mv "\${tmp_file}" ${meta_file_q}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
${reconcile_snippet}
|
|
357
|
+
|
|
358
|
+
write_state running
|
|
359
|
+
|
|
360
|
+
mkdir -p "\${sandbox_run_dir}"
|
|
361
|
+
|
|
362
|
+
# Run pi in print mode (non-interactive, single-shot)
|
|
363
|
+
# --no-session: ephemeral, don't persist session state
|
|
364
|
+
# --thinking: reasoning depth
|
|
365
|
+
# @prompt_file: pass prompt as file reference
|
|
366
|
+
pi_exit_code=0
|
|
367
|
+
# macOS does not ship 'timeout'; prefer it when available, else use background watchdog
|
|
368
|
+
if command -v timeout >/dev/null 2>&1; then
|
|
369
|
+
timeout "\${pi_timeout_seconds}" \\
|
|
370
|
+
"\${pi_bin}" --print --no-session \\
|
|
371
|
+
--model "\${pi_model}" \\
|
|
372
|
+
--thinking "\${pi_thinking}" \\
|
|
373
|
+
"@\${prompt_file}" \\
|
|
374
|
+
2>&1 | tee -a "\${output_file}" || pi_exit_code=\$?
|
|
375
|
+
elif command -v gtimeout >/dev/null 2>&1; then
|
|
376
|
+
gtimeout "\${pi_timeout_seconds}" \\
|
|
377
|
+
"\${pi_bin}" --print --no-session \\
|
|
378
|
+
--model "\${pi_model}" \\
|
|
379
|
+
--thinking "\${pi_thinking}" \\
|
|
380
|
+
"@\${prompt_file}" \\
|
|
381
|
+
2>&1 | tee -a "\${output_file}" || pi_exit_code=\$?
|
|
382
|
+
else
|
|
383
|
+
"\${pi_bin}" --print --no-session \\
|
|
384
|
+
--model "\${pi_model}" \\
|
|
385
|
+
--thinking "\${pi_thinking}" \\
|
|
386
|
+
"@\${prompt_file}" \\
|
|
387
|
+
2>&1 >> "\${output_file}" &
|
|
388
|
+
_pi_bgpid=\$!
|
|
389
|
+
# Hard timeout watchdog
|
|
390
|
+
( sleep "\${pi_timeout_seconds}" && kill "\${_pi_bgpid}" 2>/dev/null \\
|
|
391
|
+
&& printf '[pi] timed out after %s seconds\n' "\${pi_timeout_seconds}" >> "\${output_file}" ) &
|
|
392
|
+
_pi_timeout_wd=\$!
|
|
393
|
+
# Stall watchdog: kill if output file stops growing for pi_stall_seconds
|
|
394
|
+
if [[ "\${pi_stall_seconds}" -gt 0 ]]; then
|
|
395
|
+
(
|
|
396
|
+
_prev_size=-1
|
|
397
|
+
while kill -0 "\${_pi_bgpid}" 2>/dev/null; do
|
|
398
|
+
_cur_size="\$(wc -c < "\${output_file}" 2>/dev/null || echo 0)"
|
|
399
|
+
if [[ "\${_cur_size}" -eq "\${_prev_size}" ]]; then
|
|
400
|
+
if [[ -z "\${_idle_since:-}" ]]; then _idle_since="\$(date +%s)"; fi
|
|
401
|
+
if (( \$(date +%s) - _idle_since >= pi_stall_seconds )); then
|
|
402
|
+
printf '[pi] no output for %s seconds — aborting stalled worker\n' "\${pi_stall_seconds}" >> "\${output_file}"
|
|
403
|
+
kill "\${_pi_bgpid}" 2>/dev/null
|
|
404
|
+
break
|
|
405
|
+
fi
|
|
406
|
+
else
|
|
407
|
+
_idle_since=""
|
|
408
|
+
_prev_size="\${_cur_size}"
|
|
409
|
+
fi
|
|
410
|
+
sleep 5
|
|
411
|
+
done
|
|
412
|
+
) &
|
|
413
|
+
_pi_stall_wd=\$!
|
|
414
|
+
fi
|
|
415
|
+
wait "\${_pi_bgpid}" || pi_exit_code=\$?
|
|
416
|
+
kill "\${_pi_timeout_wd}" 2>/dev/null || true
|
|
417
|
+
wait "\${_pi_timeout_wd}" 2>/dev/null || true
|
|
418
|
+
if [[ -n "\${_pi_stall_wd:-}" ]]; then
|
|
419
|
+
kill "\${_pi_stall_wd}" 2>/dev/null || true
|
|
420
|
+
wait "\${_pi_stall_wd}" 2>/dev/null || true
|
|
421
|
+
fi
|
|
422
|
+
if [[ "\${pi_exit_code}" -eq 143 ]]; then
|
|
423
|
+
pi_exit_code=124
|
|
424
|
+
fi
|
|
425
|
+
fi
|
|
426
|
+
|
|
427
|
+
if [[ "\${pi_exit_code}" -eq 0 ]]; then
|
|
428
|
+
# Pi runs in --print mode and cannot write result.env itself.
|
|
429
|
+
# If the result file is missing, write a blocked fallback so reconcile
|
|
430
|
+
# sees a valid contract instead of an invalid-result-contract failure.
|
|
431
|
+
if [[ ! -f "\${result_file_path}" ]]; then
|
|
432
|
+
write_result_fallback "missing-result-contract"
|
|
433
|
+
fi
|
|
434
|
+
write_state succeeded 0
|
|
435
|
+
else
|
|
436
|
+
failure_reason="pi-exit-\${pi_exit_code}"
|
|
437
|
+
if [[ "\${pi_exit_code}" -eq 124 ]]; then
|
|
438
|
+
failure_reason="timeout"
|
|
439
|
+
fi
|
|
440
|
+
if [[ ! -f "\${result_file_path}" ]]; then
|
|
441
|
+
write_result_fallback "\${failure_reason}"
|
|
442
|
+
fi
|
|
443
|
+
write_state failed "\${pi_exit_code}" "\${failure_reason}"
|
|
444
|
+
fi
|
|
445
|
+
|
|
446
|
+
record_final_git_state
|
|
447
|
+
|
|
448
|
+
${collect_copy_snippet}
|
|
449
|
+
printf '\n__CODEX_EXIT__:%s\n' "\${pi_exit_code}" | tee -a "\${output_file}"
|
|
450
|
+
exit "\${pi_exit_code}"
|
|
451
|
+
EOF
|
|
452
|
+
|
|
453
|
+
chmod +x "$inner_script"
|
|
454
|
+
|
|
455
|
+
# Write initial runner state
|
|
456
|
+
{
|
|
457
|
+
printf 'RUNNER_STATE=%q\n' "running"
|
|
458
|
+
printf 'ATTEMPT=1\n'
|
|
459
|
+
printf 'RESUME_COUNT=0\n'
|
|
460
|
+
printf "LAST_EXIT_CODE=''\n"
|
|
461
|
+
printf "LAST_FAILURE_REASON=''\n"
|
|
462
|
+
printf "LAST_TRIGGER_REASON=''\n"
|
|
463
|
+
printf "AUTH_WAIT_STARTED_AT=''\n"
|
|
464
|
+
printf 'UPDATED_AT=%q\n' "$started_at"
|
|
465
|
+
printf 'RUNNER_STATE_FILE=%q\n' "$runner_state_file"
|
|
466
|
+
} >"$runner_state_file"
|
|
467
|
+
|
|
468
|
+
# Append pi-specific metadata to run.env for dashboard/status visibility
|
|
469
|
+
{
|
|
470
|
+
printf 'PI_MODEL=%s\n' "$pi_model_q"
|
|
471
|
+
printf 'PI_THINKING=%s\n' "$pi_thinking_q"
|
|
472
|
+
printf 'PI_TIMEOUT_SECONDS=%s\n' "$pi_timeout_q"
|
|
473
|
+
printf 'PI_STALL_SECONDS=%s\n' "$pi_stall_q"
|
|
474
|
+
printf 'PI_BIN=%s\n' "$pi_bin_q"
|
|
475
|
+
} >>"$meta_file"
|
|
476
|
+
|
|
477
|
+
tmux new-session -d -s "$session" -x 220 -y 50 \
|
|
478
|
+
"bash -l $script_q >> $output_q 2>&1; tmux wait-for -S $session_q-done" \; \
|
|
479
|
+
wait-for "$session-done" || true
|
|
@@ -1699,6 +1699,48 @@ flow_provider_pool_openclaw_timeout_seconds() {
|
|
|
1699
1699
|
flow_provider_pool_value "${config_file}" "${pool_name}" "openclaw.timeout_seconds"
|
|
1700
1700
|
}
|
|
1701
1701
|
|
|
1702
|
+
flow_provider_pool_ollama_model() {
|
|
1703
|
+
local config_file="${1:?config file required}"
|
|
1704
|
+
local pool_name="${2:?pool name required}"
|
|
1705
|
+
|
|
1706
|
+
flow_provider_pool_value "${config_file}" "${pool_name}" "ollama.model"
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
flow_provider_pool_ollama_base_url() {
|
|
1710
|
+
local config_file="${1:?config file required}"
|
|
1711
|
+
local pool_name="${2:?pool name required}"
|
|
1712
|
+
|
|
1713
|
+
flow_provider_pool_value "${config_file}" "${pool_name}" "ollama.base_url"
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
flow_provider_pool_ollama_timeout_seconds() {
|
|
1717
|
+
local config_file="${1:?config file required}"
|
|
1718
|
+
local pool_name="${2:?pool name required}"
|
|
1719
|
+
|
|
1720
|
+
flow_provider_pool_value "${config_file}" "${pool_name}" "ollama.timeout_seconds"
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
flow_provider_pool_pi_model() {
|
|
1724
|
+
local config_file="${1:?config file required}"
|
|
1725
|
+
local pool_name="${2:?pool name required}"
|
|
1726
|
+
|
|
1727
|
+
flow_provider_pool_value "${config_file}" "${pool_name}" "pi.model"
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
flow_provider_pool_pi_thinking() {
|
|
1731
|
+
local config_file="${1:?config file required}"
|
|
1732
|
+
local pool_name="${2:?pool name required}"
|
|
1733
|
+
|
|
1734
|
+
flow_provider_pool_value "${config_file}" "${pool_name}" "pi.thinking"
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
flow_provider_pool_pi_timeout_seconds() {
|
|
1738
|
+
local config_file="${1:?config file required}"
|
|
1739
|
+
local pool_name="${2:?pool name required}"
|
|
1740
|
+
|
|
1741
|
+
flow_provider_pool_value "${config_file}" "${pool_name}" "pi.timeout_seconds"
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1702
1744
|
flow_sanitize_provider_key() {
|
|
1703
1745
|
local raw_key="${1:?raw key required}"
|
|
1704
1746
|
|
|
@@ -1723,6 +1765,12 @@ flow_provider_pool_model_identity() {
|
|
|
1723
1765
|
openclaw)
|
|
1724
1766
|
flow_provider_pool_openclaw_model "${config_file}" "${pool_name}"
|
|
1725
1767
|
;;
|
|
1768
|
+
ollama)
|
|
1769
|
+
flow_provider_pool_ollama_model "${config_file}" "${pool_name}"
|
|
1770
|
+
;;
|
|
1771
|
+
pi)
|
|
1772
|
+
flow_provider_pool_pi_model "${config_file}" "${pool_name}"
|
|
1773
|
+
;;
|
|
1726
1774
|
*)
|
|
1727
1775
|
printf '\n'
|
|
1728
1776
|
;;
|
|
@@ -1756,6 +1804,12 @@ flow_provider_pool_state_get() {
|
|
|
1756
1804
|
local openclaw_model=""
|
|
1757
1805
|
local openclaw_thinking=""
|
|
1758
1806
|
local openclaw_timeout_seconds=""
|
|
1807
|
+
local ollama_model=""
|
|
1808
|
+
local ollama_base_url=""
|
|
1809
|
+
local ollama_timeout_seconds=""
|
|
1810
|
+
local pi_model=""
|
|
1811
|
+
local pi_thinking=""
|
|
1812
|
+
local pi_timeout_seconds=""
|
|
1759
1813
|
|
|
1760
1814
|
backend="$(flow_provider_pool_backend "${config_file}" "${pool_name}")"
|
|
1761
1815
|
safe_profile="$(flow_provider_pool_safe_profile "${config_file}" "${pool_name}")"
|
|
@@ -1769,6 +1823,12 @@ flow_provider_pool_state_get() {
|
|
|
1769
1823
|
openclaw_model="$(flow_provider_pool_openclaw_model "${config_file}" "${pool_name}")"
|
|
1770
1824
|
openclaw_thinking="$(flow_provider_pool_openclaw_thinking "${config_file}" "${pool_name}")"
|
|
1771
1825
|
openclaw_timeout_seconds="$(flow_provider_pool_openclaw_timeout_seconds "${config_file}" "${pool_name}")"
|
|
1826
|
+
ollama_model="$(flow_provider_pool_ollama_model "${config_file}" "${pool_name}")"
|
|
1827
|
+
ollama_base_url="$(flow_provider_pool_ollama_base_url "${config_file}" "${pool_name}")"
|
|
1828
|
+
ollama_timeout_seconds="$(flow_provider_pool_ollama_timeout_seconds "${config_file}" "${pool_name}")"
|
|
1829
|
+
pi_model="$(flow_provider_pool_pi_model "${config_file}" "${pool_name}")"
|
|
1830
|
+
pi_thinking="$(flow_provider_pool_pi_thinking "${config_file}" "${pool_name}")"
|
|
1831
|
+
pi_timeout_seconds="$(flow_provider_pool_pi_timeout_seconds "${config_file}" "${pool_name}")"
|
|
1772
1832
|
model="$(flow_provider_pool_model_identity "${config_file}" "${pool_name}")"
|
|
1773
1833
|
|
|
1774
1834
|
case "${backend}" in
|
|
@@ -1781,6 +1841,12 @@ flow_provider_pool_state_get() {
|
|
|
1781
1841
|
openclaw)
|
|
1782
1842
|
[[ -n "${openclaw_model}" && -n "${openclaw_thinking}" && -n "${openclaw_timeout_seconds}" ]] || valid="no"
|
|
1783
1843
|
;;
|
|
1844
|
+
ollama)
|
|
1845
|
+
[[ -n "${ollama_model}" ]] || valid="no"
|
|
1846
|
+
;;
|
|
1847
|
+
pi)
|
|
1848
|
+
[[ -n "${pi_model}" ]] || valid="no"
|
|
1849
|
+
;;
|
|
1784
1850
|
*)
|
|
1785
1851
|
valid="no"
|
|
1786
1852
|
;;
|
|
@@ -1833,6 +1899,12 @@ flow_provider_pool_state_get() {
|
|
|
1833
1899
|
printf 'OPENCLAW_MODEL=%s\n' "${openclaw_model}"
|
|
1834
1900
|
printf 'OPENCLAW_THINKING=%s\n' "${openclaw_thinking}"
|
|
1835
1901
|
printf 'OPENCLAW_TIMEOUT_SECONDS=%s\n' "${openclaw_timeout_seconds}"
|
|
1902
|
+
printf 'OLLAMA_MODEL=%s\n' "${ollama_model}"
|
|
1903
|
+
printf 'OLLAMA_BASE_URL=%s\n' "${ollama_base_url}"
|
|
1904
|
+
printf 'OLLAMA_TIMEOUT_SECONDS=%s\n' "${ollama_timeout_seconds}"
|
|
1905
|
+
printf 'PI_MODEL=%s\n' "${pi_model}"
|
|
1906
|
+
printf 'PI_THINKING=%s\n' "${pi_thinking}"
|
|
1907
|
+
printf 'PI_TIMEOUT_SECONDS=%s\n' "${pi_timeout_seconds}"
|
|
1836
1908
|
}
|
|
1837
1909
|
|
|
1838
1910
|
flow_selected_provider_pool_env() {
|
|
@@ -2040,11 +2112,17 @@ flow_export_execution_env() {
|
|
|
2040
2112
|
local openclaw_thinking=""
|
|
2041
2113
|
local openclaw_timeout=""
|
|
2042
2114
|
local openclaw_stall=""
|
|
2115
|
+
local ollama_model=""
|
|
2116
|
+
local ollama_base_url=""
|
|
2117
|
+
local ollama_timeout=""
|
|
2118
|
+
local pi_model=""
|
|
2119
|
+
local pi_thinking=""
|
|
2120
|
+
local pi_timeout=""
|
|
2043
2121
|
|
|
2044
2122
|
repo_id="$(flow_resolve_repo_id "${config_file}")"
|
|
2045
2123
|
provider_quota_cooldowns="$(flow_resolve_provider_quota_cooldowns "${config_file}")"
|
|
2046
2124
|
provider_pool_order="$(flow_resolve_provider_pool_order "${config_file}")"
|
|
2047
|
-
explicit_coding_worker="${ACP_CODING_WORKER
|
|
2125
|
+
explicit_coding_worker="${ACP_CODING_WORKER:-}"
|
|
2048
2126
|
if [[ -z "${explicit_coding_worker}" && -n "${provider_pool_order}" ]]; then
|
|
2049
2127
|
provider_pool_selection="$(flow_selected_provider_pool_env "${config_file}" || true)"
|
|
2050
2128
|
fi
|
|
@@ -2073,11 +2151,17 @@ flow_export_execution_env() {
|
|
|
2073
2151
|
openclaw_thinking="$(flow_kv_get "${provider_pool_selection}" "OPENCLAW_THINKING")"
|
|
2074
2152
|
openclaw_timeout="$(flow_kv_get "${provider_pool_selection}" "OPENCLAW_TIMEOUT_SECONDS")"
|
|
2075
2153
|
openclaw_stall="$(flow_kv_get "${provider_pool_selection}" "OPENCLAW_STALL_SECONDS")"
|
|
2154
|
+
ollama_model="$(flow_kv_get "${provider_pool_selection}" "OLLAMA_MODEL")"
|
|
2155
|
+
ollama_base_url="$(flow_kv_get "${provider_pool_selection}" "OLLAMA_BASE_URL")"
|
|
2156
|
+
ollama_timeout="$(flow_kv_get "${provider_pool_selection}" "OLLAMA_TIMEOUT_SECONDS")"
|
|
2157
|
+
pi_model="$(flow_kv_get "${provider_pool_selection}" "PI_MODEL")"
|
|
2158
|
+
pi_thinking="$(flow_kv_get "${provider_pool_selection}" "PI_THINKING")"
|
|
2159
|
+
pi_timeout="$(flow_kv_get "${provider_pool_selection}" "PI_TIMEOUT_SECONDS")"
|
|
2076
2160
|
else
|
|
2077
2161
|
if [[ -n "${explicit_coding_worker}" ]]; then
|
|
2078
2162
|
active_provider_selection_reason="env-override"
|
|
2079
2163
|
fi
|
|
2080
|
-
coding_worker="$(flow_env_or_config "${config_file}" "ACP_CODING_WORKER
|
|
2164
|
+
coding_worker="$(flow_env_or_config "${config_file}" "ACP_CODING_WORKER" "execution.coding_worker" "")"
|
|
2081
2165
|
safe_profile="$(flow_env_or_config "${config_file}" "ACP_CODEX_PROFILE_SAFE F_LOSNING_CODEX_PROFILE_SAFE" "execution.safe_profile" "")"
|
|
2082
2166
|
bypass_profile="$(flow_env_or_config "${config_file}" "ACP_CODEX_PROFILE_BYPASS F_LOSNING_CODEX_PROFILE_BYPASS" "execution.bypass_profile" "")"
|
|
2083
2167
|
claude_model="$(flow_env_or_config "${config_file}" "ACP_CLAUDE_MODEL F_LOSNING_CLAUDE_MODEL" "execution.claude.model" "")"
|
|
@@ -2090,10 +2174,15 @@ flow_export_execution_env() {
|
|
|
2090
2174
|
openclaw_thinking="$(flow_env_or_config "${config_file}" "ACP_OPENCLAW_THINKING F_LOSNING_OPENCLAW_THINKING" "execution.openclaw.thinking" "")"
|
|
2091
2175
|
openclaw_timeout="$(flow_env_or_config "${config_file}" "ACP_OPENCLAW_TIMEOUT_SECONDS F_LOSNING_OPENCLAW_TIMEOUT_SECONDS" "execution.openclaw.timeout_seconds" "")"
|
|
2092
2176
|
openclaw_stall="$(flow_env_or_config "${config_file}" "ACP_OPENCLAW_STALL_SECONDS F_LOSNING_OPENCLAW_STALL_SECONDS" "execution.openclaw.stall_seconds" "")"
|
|
2177
|
+
ollama_model="$(flow_env_or_config "${config_file}" "ACP_OLLAMA_MODEL F_LOSNING_OLLAMA_MODEL" "execution.ollama.model" "")"
|
|
2178
|
+
ollama_base_url="$(flow_env_or_config "${config_file}" "ACP_OLLAMA_BASE_URL F_LOSNING_OLLAMA_BASE_URL" "execution.ollama.base_url" "")"
|
|
2179
|
+
ollama_timeout="$(flow_env_or_config "${config_file}" "ACP_OLLAMA_TIMEOUT_SECONDS F_LOSNING_OLLAMA_TIMEOUT_SECONDS" "execution.ollama.timeout_seconds" "")"
|
|
2180
|
+
pi_model="$(flow_env_or_config "${config_file}" "ACP_PI_MODEL F_LOSNING_PI_MODEL" "execution.pi.model" "")"
|
|
2181
|
+
pi_thinking="$(flow_env_or_config "${config_file}" "ACP_PI_THINKING F_LOSNING_PI_THINKING" "execution.pi.thinking" "")"
|
|
2182
|
+
pi_timeout="$(flow_env_or_config "${config_file}" "ACP_PI_TIMEOUT_SECONDS F_LOSNING_PI_TIMEOUT_SECONDS" "execution.pi.timeout_seconds" "")"
|
|
2093
2183
|
fi
|
|
2094
2184
|
|
|
2095
2185
|
if [[ -n "${coding_worker}" ]]; then
|
|
2096
|
-
export F_LOSNING_CODING_WORKER="${coding_worker}"
|
|
2097
2186
|
export ACP_CODING_WORKER="${coding_worker}"
|
|
2098
2187
|
fi
|
|
2099
2188
|
if [[ -n "${repo_id}" ]]; then
|
|
@@ -2174,6 +2263,30 @@ flow_export_execution_env() {
|
|
|
2174
2263
|
export F_LOSNING_OPENCLAW_STALL_SECONDS="${openclaw_stall}"
|
|
2175
2264
|
export ACP_OPENCLAW_STALL_SECONDS="${openclaw_stall}"
|
|
2176
2265
|
fi
|
|
2266
|
+
if [[ -n "${ollama_model}" ]]; then
|
|
2267
|
+
export F_LOSNING_OLLAMA_MODEL="${ollama_model}"
|
|
2268
|
+
export ACP_OLLAMA_MODEL="${ollama_model}"
|
|
2269
|
+
fi
|
|
2270
|
+
if [[ -n "${ollama_base_url}" ]]; then
|
|
2271
|
+
export F_LOSNING_OLLAMA_BASE_URL="${ollama_base_url}"
|
|
2272
|
+
export ACP_OLLAMA_BASE_URL="${ollama_base_url}"
|
|
2273
|
+
fi
|
|
2274
|
+
if [[ -n "${ollama_timeout}" ]]; then
|
|
2275
|
+
export F_LOSNING_OLLAMA_TIMEOUT_SECONDS="${ollama_timeout}"
|
|
2276
|
+
export ACP_OLLAMA_TIMEOUT_SECONDS="${ollama_timeout}"
|
|
2277
|
+
fi
|
|
2278
|
+
if [[ -n "${pi_model}" ]]; then
|
|
2279
|
+
export F_LOSNING_PI_MODEL="${pi_model}"
|
|
2280
|
+
export ACP_PI_MODEL="${pi_model}"
|
|
2281
|
+
fi
|
|
2282
|
+
if [[ -n "${pi_thinking}" ]]; then
|
|
2283
|
+
export F_LOSNING_PI_THINKING="${pi_thinking}"
|
|
2284
|
+
export ACP_PI_THINKING="${pi_thinking}"
|
|
2285
|
+
fi
|
|
2286
|
+
if [[ -n "${pi_timeout}" ]]; then
|
|
2287
|
+
export F_LOSNING_PI_TIMEOUT_SECONDS="${pi_timeout}"
|
|
2288
|
+
export ACP_PI_TIMEOUT_SECONDS="${pi_timeout}"
|
|
2289
|
+
fi
|
|
2177
2290
|
|
|
2178
2291
|
flow_export_github_cli_auth_env "$(flow_resolve_repo_slug "${config_file}")"
|
|
2179
2292
|
flow_export_project_env_aliases
|