agent-control-plane 0.1.14 → 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 +323 -349
- package/bin/pr-risk.sh +28 -6
- package/hooks/heartbeat-hooks.sh +62 -22
- package/npm/bin/agent-control-plane.js +434 -12
- 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 +45 -12
- package/tools/bin/agent-project-reconcile-pr-session +25 -0
- package/tools/bin/agent-project-run-claude-session +2 -2
- package/tools/bin/agent-project-run-codex-resilient +57 -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 +73 -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 +38 -1
- package/tools/bin/flow-config-lib.sh +123 -3
- package/tools/bin/flow-resident-worker-lib.sh +1 -1
- package/tools/bin/flow-shell-lib.sh +7 -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 +4 -1
- package/tools/bin/start-pr-fix-worker.sh +33 -0
- package/tools/bin/start-pr-review-worker.sh +34 -0
- package/tools/bin/start-resident-issue-loop.sh +5 -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/dashboard/app.js +62 -0
- package/tools/dashboard/dashboard_snapshot.py +53 -4
- package/tools/dashboard/index.html +5 -1
- package/tools/dashboard/styles.css +97 -20
- package/tools/templates/pr-fix-template.md +4 -8
- package/tools/templates/pr-merge-repair-template.md +4 -8
- package/tools/templates/pr-review-template.md +2 -1
|
@@ -168,13 +168,15 @@ join_by_comma() {
|
|
|
168
168
|
runtime_started() {
|
|
169
169
|
local heartbeat=""
|
|
170
170
|
local shared_loop=""
|
|
171
|
-
local
|
|
171
|
+
local active_sessions=""
|
|
172
|
+
local pending_pids=""
|
|
172
173
|
|
|
173
174
|
heartbeat="$(heartbeat_pid)"
|
|
174
175
|
shared_loop="$(shared_loop_pid)"
|
|
175
|
-
|
|
176
|
+
active_sessions="$(collect_active_tmux_sessions | sort -u)"
|
|
177
|
+
pending_pids="$(collect_pending_launch_pids | sort -u)"
|
|
176
178
|
|
|
177
|
-
[[ -n "${heartbeat}" || -n "${shared_loop}" || -n "${
|
|
179
|
+
[[ -n "${heartbeat}" || -n "${shared_loop}" || -n "${active_sessions}" || -n "${pending_pids}" ]]
|
|
178
180
|
}
|
|
179
181
|
|
|
180
182
|
wait_for_runtime_start() {
|
|
@@ -197,6 +199,13 @@ sync_stamp_value() {
|
|
|
197
199
|
| sed -e "s/^'//" -e "s/'$//"
|
|
198
200
|
}
|
|
199
201
|
|
|
202
|
+
shared_loop_status_value() {
|
|
203
|
+
local key="${1:?key required}"
|
|
204
|
+
local file="${STATE_ROOT}/shared-heartbeat-loop.env"
|
|
205
|
+
[[ -f "${file}" ]] || return 1
|
|
206
|
+
awk -F= -v target="${key}" '$1 == target {print $2; exit}' "${file}" 2>/dev/null
|
|
207
|
+
}
|
|
208
|
+
|
|
200
209
|
tmux_session_exists() {
|
|
201
210
|
local session="${1:-}"
|
|
202
211
|
[[ -n "${TMUX_BIN}" && -n "${session}" ]] || return 1
|
|
@@ -218,14 +227,53 @@ collect_run_sessions() {
|
|
|
218
227
|
done < <(find "${RUNS_ROOT}" -mindepth 2 -maxdepth 2 -type f -name run.env 2>/dev/null | sort -u)
|
|
219
228
|
}
|
|
220
229
|
|
|
230
|
+
list_tmux_sessions() {
|
|
231
|
+
[[ -n "${TMUX_BIN}" ]] || return 0
|
|
232
|
+
"${TMUX_BIN}" list-sessions -F '#S' 2>/dev/null || true
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
collect_profile_tmux_sessions() {
|
|
236
|
+
local issue_prefix=""
|
|
237
|
+
local pr_prefix=""
|
|
238
|
+
local session=""
|
|
239
|
+
|
|
240
|
+
issue_prefix="$(flow_resolve_issue_session_prefix "${CONFIG_YAML}")"
|
|
241
|
+
pr_prefix="$(flow_resolve_pr_session_prefix "${CONFIG_YAML}")"
|
|
242
|
+
|
|
243
|
+
while IFS= read -r session; do
|
|
244
|
+
[[ -n "${session}" ]] || continue
|
|
245
|
+
case "${session}" in
|
|
246
|
+
"${issue_prefix}"*|"${pr_prefix}"*)
|
|
247
|
+
printf '%s\n' "${session}"
|
|
248
|
+
;;
|
|
249
|
+
esac
|
|
250
|
+
done < <(list_tmux_sessions)
|
|
251
|
+
}
|
|
252
|
+
|
|
221
253
|
collect_active_tmux_sessions() {
|
|
254
|
+
local known_sessions=""
|
|
222
255
|
local session=""
|
|
256
|
+
known_sessions="$(collect_run_sessions | sort -u)"
|
|
257
|
+
|
|
223
258
|
while IFS= read -r session; do
|
|
224
259
|
[[ -n "${session}" ]] || continue
|
|
225
|
-
if tmux_session_exists "${session}"; then
|
|
260
|
+
if tmux_session_exists "${session}" && grep -Fxq "${session}" <<<"${known_sessions}"; then
|
|
226
261
|
printf '%s\n' "${session}"
|
|
227
262
|
fi
|
|
228
|
-
done < <(
|
|
263
|
+
done < <(collect_profile_tmux_sessions)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
collect_stale_tmux_sessions() {
|
|
267
|
+
local known_sessions=""
|
|
268
|
+
local session=""
|
|
269
|
+
known_sessions="$(collect_run_sessions | sort -u)"
|
|
270
|
+
|
|
271
|
+
while IFS= read -r session; do
|
|
272
|
+
[[ -n "${session}" ]] || continue
|
|
273
|
+
if tmux_session_exists "${session}" && ! grep -Fxq "${session}" <<<"${known_sessions}"; then
|
|
274
|
+
printf '%s\n' "${session}"
|
|
275
|
+
fi
|
|
276
|
+
done < <(collect_profile_tmux_sessions)
|
|
229
277
|
}
|
|
230
278
|
|
|
231
279
|
collect_repo_shared_loop_pids() {
|
|
@@ -336,15 +384,21 @@ print_status() {
|
|
|
336
384
|
local supervisor=""
|
|
337
385
|
local controller_pids=""
|
|
338
386
|
local active_sessions=""
|
|
387
|
+
local stale_sessions=""
|
|
339
388
|
local pending_pids=""
|
|
340
389
|
local runtime_status="stopped"
|
|
341
390
|
local controller_count="0"
|
|
342
391
|
local active_session_count="0"
|
|
392
|
+
local stale_session_count="0"
|
|
343
393
|
local pending_count="0"
|
|
344
394
|
local launchd_state=""
|
|
345
395
|
local runtime_sync_status=""
|
|
346
396
|
local runtime_sync_updated_at=""
|
|
347
397
|
local runtime_sync_fingerprint=""
|
|
398
|
+
local shared_loop_state=""
|
|
399
|
+
local shared_loop_last_status=""
|
|
400
|
+
local shared_loop_started_at=""
|
|
401
|
+
local shared_loop_updated_at=""
|
|
348
402
|
|
|
349
403
|
heartbeat="$(heartbeat_pid)"
|
|
350
404
|
shared_loop="$(shared_loop_pid)"
|
|
@@ -352,16 +406,18 @@ print_status() {
|
|
|
352
406
|
heartbeat_parent="$(heartbeat_parent_pid)"
|
|
353
407
|
controller_pids="$(collect_controller_pids | sort -u)"
|
|
354
408
|
active_sessions="$(collect_active_tmux_sessions | sort -u)"
|
|
409
|
+
stale_sessions="$(collect_stale_tmux_sessions | sort -u)"
|
|
355
410
|
pending_pids="$(collect_pending_launch_pids | sort -u)"
|
|
356
411
|
|
|
357
412
|
[[ -n "${controller_pids}" ]] && controller_count="$(printf '%s\n' "${controller_pids}" | awk 'NF {c+=1} END {print c+0}')"
|
|
358
413
|
[[ -n "${active_sessions}" ]] && active_session_count="$(printf '%s\n' "${active_sessions}" | awk 'NF {c+=1} END {print c+0}')"
|
|
414
|
+
[[ -n "${stale_sessions}" ]] && stale_session_count="$(printf '%s\n' "${stale_sessions}" | awk 'NF {c+=1} END {print c+0}')"
|
|
359
415
|
[[ -n "${pending_pids}" ]] && pending_count="$(printf '%s\n' "${pending_pids}" | awk 'NF {c+=1} END {print c+0}')"
|
|
360
416
|
|
|
361
|
-
if [[ -n "${heartbeat}" || -n "${shared_loop}" ||
|
|
417
|
+
if [[ -n "${heartbeat}" || -n "${shared_loop}" || "${active_session_count}" != "0" ]]; then
|
|
362
418
|
runtime_status="running"
|
|
363
419
|
fi
|
|
364
|
-
if [[
|
|
420
|
+
if [[ "${runtime_status}" != "running" && ( -n "${supervisor}" || "${controller_count}" != "0" || "${pending_count}" != "0" || "${stale_session_count}" != "0" ) ]]; then
|
|
365
421
|
runtime_status="partial"
|
|
366
422
|
fi
|
|
367
423
|
|
|
@@ -369,6 +425,10 @@ print_status() {
|
|
|
369
425
|
runtime_sync_status="$(sync_stamp_value "SYNC_STATUS" || true)"
|
|
370
426
|
runtime_sync_updated_at="$(sync_stamp_value "UPDATED_AT" || true)"
|
|
371
427
|
runtime_sync_fingerprint="$(sync_stamp_value "SOURCE_FINGERPRINT" || true)"
|
|
428
|
+
shared_loop_state="$(shared_loop_status_value "STATE" || true)"
|
|
429
|
+
shared_loop_last_status="$(shared_loop_status_value "STATUS" || true)"
|
|
430
|
+
shared_loop_started_at="$(shared_loop_status_value "STARTED_AT" || true)"
|
|
431
|
+
shared_loop_updated_at="$(shared_loop_status_value "UPDATED_AT" || true)"
|
|
372
432
|
|
|
373
433
|
printf 'PROFILE_ID=%s\n' "${PROFILE_ID}"
|
|
374
434
|
printf 'CONFIG_YAML=%s\n' "${CONFIG_YAML}"
|
|
@@ -382,12 +442,18 @@ print_status() {
|
|
|
382
442
|
printf 'HEARTBEAT_PID=%s\n' "${heartbeat}"
|
|
383
443
|
printf 'HEARTBEAT_PARENT_PID=%s\n' "${heartbeat_parent}"
|
|
384
444
|
printf 'SHARED_LOOP_PID=%s\n' "${shared_loop}"
|
|
445
|
+
printf 'SHARED_LOOP_STATE=%s\n' "${shared_loop_state}"
|
|
446
|
+
printf 'SHARED_LOOP_LAST_STATUS=%s\n' "${shared_loop_last_status}"
|
|
447
|
+
printf 'SHARED_LOOP_STARTED_AT=%s\n' "${shared_loop_started_at}"
|
|
448
|
+
printf 'SHARED_LOOP_UPDATED_AT=%s\n' "${shared_loop_updated_at}"
|
|
385
449
|
printf 'SUPERVISOR_PID=%s\n' "${supervisor}"
|
|
386
450
|
printf 'CONTROLLER_COUNT=%s\n' "${controller_count}"
|
|
387
451
|
printf 'ACTIVE_TMUX_SESSION_COUNT=%s\n' "${active_session_count}"
|
|
452
|
+
printf 'STALE_TMUX_SESSION_COUNT=%s\n' "${stale_session_count}"
|
|
388
453
|
printf 'PENDING_LAUNCH_COUNT=%s\n' "${pending_count}"
|
|
389
454
|
printf 'CONTROLLER_PIDS=%s\n' "$(printf '%s\n' "${controller_pids}" | join_by_comma)"
|
|
390
455
|
printf 'ACTIVE_TMUX_SESSIONS=%s\n' "$(printf '%s\n' "${active_sessions}" | join_by_comma)"
|
|
456
|
+
printf 'STALE_TMUX_SESSIONS=%s\n' "$(printf '%s\n' "${stale_sessions}" | join_by_comma)"
|
|
391
457
|
printf 'PENDING_LAUNCH_PIDS=%s\n' "$(printf '%s\n' "${pending_pids}" | join_by_comma)"
|
|
392
458
|
printf 'SYNC_STAMP_FILE=%s\n' "${SYNC_STAMP_FILE}"
|
|
393
459
|
printf 'RUNTIME_SYNC_STATUS=%s\n' "${runtime_sync_status}"
|
|
@@ -452,12 +518,18 @@ clear_running_labels_after_stop() {
|
|
|
452
518
|
fi
|
|
453
519
|
|
|
454
520
|
issue_json="$(flow_github_issue_list_json "${REPO_SLUG}" open 100 2>/dev/null || printf '[]\n')"
|
|
521
|
+
if [[ "${issue_json}" == "[]" ]]; then
|
|
522
|
+
issue_json="$(gh issue list -R "${REPO_SLUG}" --state open --limit 100 --json number,labels 2>/dev/null || printf '[]\n')"
|
|
523
|
+
fi
|
|
455
524
|
while IFS= read -r number; do
|
|
456
525
|
[[ -n "${number}" ]] || continue
|
|
457
526
|
bash "${UPDATE_LABELS_SCRIPT}" --repo-slug "${REPO_SLUG}" --number "${number}" --remove agent-running >/dev/null 2>&1 || true
|
|
458
527
|
done < <(jq -r '.[] | select(any(.labels[]?; .name == "agent-running")) | .number' <<<"${issue_json}" 2>/dev/null || true)
|
|
459
528
|
|
|
460
529
|
pr_json="$(flow_github_pr_list_json "${REPO_SLUG}" open 100 2>/dev/null || printf '[]\n')"
|
|
530
|
+
if [[ "${pr_json}" == "[]" ]]; then
|
|
531
|
+
pr_json="$(gh pr list -R "${REPO_SLUG}" --state open --limit 100 --json number,labels 2>/dev/null || printf '[]\n')"
|
|
532
|
+
fi
|
|
461
533
|
while IFS= read -r number; do
|
|
462
534
|
[[ -n "${number}" ]] || continue
|
|
463
535
|
bash "${UPDATE_LABELS_SCRIPT}" --repo-slug "${REPO_SLUG}" --number "${number}" --remove agent-running >/dev/null 2>&1 || true
|
|
@@ -466,6 +538,7 @@ clear_running_labels_after_stop() {
|
|
|
466
538
|
|
|
467
539
|
stop_runtime() {
|
|
468
540
|
local -a tmux_sessions=()
|
|
541
|
+
local -a stale_tmux_sessions=()
|
|
469
542
|
local -a pid_targets=()
|
|
470
543
|
local session=""
|
|
471
544
|
local pid=""
|
|
@@ -476,6 +549,11 @@ stop_runtime() {
|
|
|
476
549
|
tmux_sessions+=("${session}")
|
|
477
550
|
done < <(collect_active_tmux_sessions | sort -u)
|
|
478
551
|
|
|
552
|
+
while IFS= read -r session; do
|
|
553
|
+
[[ -n "${session}" ]] || continue
|
|
554
|
+
stale_tmux_sessions+=("${session}")
|
|
555
|
+
done < <(collect_stale_tmux_sessions | sort -u)
|
|
556
|
+
|
|
479
557
|
while IFS= read -r pid; do
|
|
480
558
|
[[ -n "${pid}" ]] || continue
|
|
481
559
|
pid_targets+=("${pid}")
|
|
@@ -501,6 +579,9 @@ stop_runtime() {
|
|
|
501
579
|
for session in "${tmux_sessions[@]+"${tmux_sessions[@]}"}"; do
|
|
502
580
|
"${TMUX_BIN}" kill-session -t "${session}" >/dev/null 2>&1 || true
|
|
503
581
|
done
|
|
582
|
+
for session in "${stale_tmux_sessions[@]+"${stale_tmux_sessions[@]}"}"; do
|
|
583
|
+
"${TMUX_BIN}" kill-session -t "${session}" >/dev/null 2>&1 || true
|
|
584
|
+
done
|
|
504
585
|
fi
|
|
505
586
|
|
|
506
587
|
terminate_pid_list TERM "${pid_targets[@]+"${pid_targets[@]}"}"
|
|
@@ -513,8 +594,10 @@ stop_runtime() {
|
|
|
513
594
|
printf 'LAUNCHD_STOPPED=%s\n' "${launchd_stopped}"
|
|
514
595
|
printf 'STOPPED_PID_COUNT=%s\n' "$(printf '%s\n' "${pid_targets[@]+"${pid_targets[@]}"}" | awk 'NF {c+=1} END {print c+0}')"
|
|
515
596
|
printf 'STOPPED_TMUX_SESSION_COUNT=%s\n' "$(printf '%s\n' "${tmux_sessions[@]+"${tmux_sessions[@]}"}" | awk 'NF {c+=1} END {print c+0}')"
|
|
597
|
+
printf 'STOPPED_STALE_TMUX_SESSION_COUNT=%s\n' "$(printf '%s\n' "${stale_tmux_sessions[@]+"${stale_tmux_sessions[@]}"}" | awk 'NF {c+=1} END {print c+0}')"
|
|
516
598
|
printf 'STOPPED_PIDS=%s\n' "$(printf '%s\n' "${pid_targets[@]+"${pid_targets[@]}"}" | join_by_comma)"
|
|
517
599
|
printf 'STOPPED_TMUX_SESSIONS=%s\n' "$(printf '%s\n' "${tmux_sessions[@]+"${tmux_sessions[@]}"}" | join_by_comma)"
|
|
600
|
+
printf 'STOPPED_STALE_TMUX_SESSIONS=%s\n' "$(printf '%s\n' "${stale_tmux_sessions[@]+"${stale_tmux_sessions[@]}"}" | join_by_comma)"
|
|
518
601
|
}
|
|
519
602
|
|
|
520
603
|
start_runtime() {
|
|
@@ -65,13 +65,13 @@ resolve_backend() {
|
|
|
65
65
|
return 0
|
|
66
66
|
fi
|
|
67
67
|
|
|
68
|
-
if [[ -n "${ACP_ACTIVE_PROVIDER_BACKEND
|
|
69
|
-
printf '%s\n' "${ACP_ACTIVE_PROVIDER_BACKEND
|
|
68
|
+
if [[ -n "${ACP_ACTIVE_PROVIDER_BACKEND:-}" ]]; then
|
|
69
|
+
printf '%s\n' "${ACP_ACTIVE_PROVIDER_BACKEND:-}"
|
|
70
70
|
return 0
|
|
71
71
|
fi
|
|
72
72
|
|
|
73
|
-
if [[ -n "${ACP_CODING_WORKER
|
|
74
|
-
printf '%s\n' "${ACP_CODING_WORKER
|
|
73
|
+
if [[ -n "${ACP_CODING_WORKER:-}" ]]; then
|
|
74
|
+
printf '%s\n' "${ACP_CODING_WORKER:-}"
|
|
75
75
|
return 0
|
|
76
76
|
fi
|
|
77
77
|
|
|
@@ -79,7 +79,7 @@ resolve_backend() {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
resolve_codex_label() {
|
|
82
|
-
local configured_label="${ACP_ACTIVE_PROVIDER_LABEL
|
|
82
|
+
local configured_label="${ACP_ACTIVE_PROVIDER_LABEL:-}"
|
|
83
83
|
local codex_quota_bin=""
|
|
84
84
|
local active_label=""
|
|
85
85
|
|
|
@@ -88,8 +88,8 @@ resolve_codex_label() {
|
|
|
88
88
|
return 0
|
|
89
89
|
fi
|
|
90
90
|
|
|
91
|
-
if [[ -n "${ACP_CODEX_QUOTA_LABEL
|
|
92
|
-
printf '%s\n' "${ACP_CODEX_QUOTA_LABEL
|
|
91
|
+
if [[ -n "${ACP_CODEX_QUOTA_LABEL:-}" ]]; then
|
|
92
|
+
printf '%s\n' "${ACP_CODEX_QUOTA_LABEL:-}"
|
|
93
93
|
return 0
|
|
94
94
|
fi
|
|
95
95
|
|
|
@@ -108,7 +108,7 @@ resolve_codex_label() {
|
|
|
108
108
|
resolve_model() {
|
|
109
109
|
local resolved_backend="${1:?backend required}"
|
|
110
110
|
local raw_model="${2:-}"
|
|
111
|
-
local active_provider_model="${ACP_ACTIVE_PROVIDER_MODEL
|
|
111
|
+
local active_provider_model="${ACP_ACTIVE_PROVIDER_MODEL:-}"
|
|
112
112
|
|
|
113
113
|
if [[ -n "${raw_model}" ]]; then
|
|
114
114
|
printf '%s\n' "${raw_model}"
|
|
@@ -121,8 +121,8 @@ resolve_model() {
|
|
|
121
121
|
printf '%s\n' "${OPENCLAW_MODEL}"
|
|
122
122
|
elif [[ -n "${active_provider_model}" ]]; then
|
|
123
123
|
printf '%s\n' "${active_provider_model}"
|
|
124
|
-
elif [[ -n "${ACP_OPENCLAW_MODEL
|
|
125
|
-
printf '%s\n' "${ACP_OPENCLAW_MODEL
|
|
124
|
+
elif [[ -n "${ACP_OPENCLAW_MODEL:-}" ]]; then
|
|
125
|
+
printf '%s\n' "${ACP_OPENCLAW_MODEL:-}"
|
|
126
126
|
else
|
|
127
127
|
flow_config_get "${CONFIG_YAML}" "execution.openclaw.model"
|
|
128
128
|
fi
|
|
@@ -132,8 +132,8 @@ resolve_model() {
|
|
|
132
132
|
printf '%s\n' "${CLAUDE_MODEL}"
|
|
133
133
|
elif [[ -n "${active_provider_model}" ]]; then
|
|
134
134
|
printf '%s\n' "${active_provider_model}"
|
|
135
|
-
elif [[ -n "${ACP_CLAUDE_MODEL
|
|
136
|
-
printf '%s\n' "${ACP_CLAUDE_MODEL
|
|
135
|
+
elif [[ -n "${ACP_CLAUDE_MODEL:-}" ]]; then
|
|
136
|
+
printf '%s\n' "${ACP_CLAUDE_MODEL:-}"
|
|
137
137
|
else
|
|
138
138
|
flow_config_get "${CONFIG_YAML}" "execution.claude.model"
|
|
139
139
|
fi
|
|
@@ -143,8 +143,8 @@ resolve_model() {
|
|
|
143
143
|
printf '%s\n' "${CODEX_PROFILE_SAFE}"
|
|
144
144
|
elif [[ -n "${active_provider_model}" ]]; then
|
|
145
145
|
printf '%s\n' "${active_provider_model}"
|
|
146
|
-
elif [[ -n "${ACP_CODEX_PROFILE_SAFE
|
|
147
|
-
printf '%s\n' "${ACP_CODEX_PROFILE_SAFE
|
|
146
|
+
elif [[ -n "${ACP_CODEX_PROFILE_SAFE:-}" ]]; then
|
|
147
|
+
printf '%s\n' "${ACP_CODEX_PROFILE_SAFE:-}"
|
|
148
148
|
else
|
|
149
149
|
flow_config_get "${CONFIG_YAML}" "execution.safe_profile"
|
|
150
150
|
fi
|
|
@@ -17,9 +17,6 @@ CONFIG_YAML="$(resolve_flow_config_yaml "${BASH_SOURCE[0]}")"
|
|
|
17
17
|
for _clean in ACP_CODING_WORKER ACP_OPENCLAW_MODEL ACP_CLAUDE_MODEL \
|
|
18
18
|
ACP_CLAUDE_TIMEOUT_SECONDS ACP_CLAUDE_MAX_ATTEMPTS ACP_CLAUDE_RETRY_BACKOFF_SECONDS \
|
|
19
19
|
ACP_OPENCLAW_THINKING ACP_OPENCLAW_TIMEOUT_SECONDS \
|
|
20
|
-
F_LOSNING_CODING_WORKER F_LOSNING_OPENCLAW_MODEL F_LOSNING_CLAUDE_MODEL \
|
|
21
|
-
F_LOSNING_CLAUDE_TIMEOUT_SECONDS F_LOSNING_CLAUDE_MAX_ATTEMPTS F_LOSNING_CLAUDE_RETRY_BACKOFF_SECONDS \
|
|
22
|
-
F_LOSNING_OPENCLAW_THINKING F_LOSNING_OPENCLAW_TIMEOUT_SECONDS \
|
|
23
20
|
CODING_WORKER; do
|
|
24
21
|
unset "${_clean}" 2>/dev/null || true
|
|
25
22
|
done
|
|
@@ -69,33 +66,33 @@ if [[ -f "${PROFILE_NOTES}" ]]; then
|
|
|
69
66
|
else
|
|
70
67
|
printf 'PROFILE_NOTES_EXISTS=no\n'
|
|
71
68
|
fi
|
|
72
|
-
printf 'EFFECTIVE_REPO_ROOT=%s\n' "$(config_or_env 'ACP_REPO_ROOT
|
|
73
|
-
printf 'EFFECTIVE_AGENT_REPO_ROOT=%s\n' "$(config_or_env 'ACP_AGENT_REPO_ROOT
|
|
74
|
-
printf 'EFFECTIVE_WORKTREE_ROOT=%s\n' "$(config_or_env 'ACP_WORKTREE_ROOT
|
|
75
|
-
printf 'EFFECTIVE_RUNS_ROOT=%s\n' "$(config_or_env 'ACP_RUNS_ROOT
|
|
76
|
-
printf 'EFFECTIVE_STATE_ROOT=%s\n' "$(config_or_env 'ACP_STATE_ROOT
|
|
77
|
-
printf 'EFFECTIVE_RETAINED_REPO_ROOT=%s\n' "$(config_or_env 'ACP_RETAINED_REPO_ROOT
|
|
78
|
-
printf 'EFFECTIVE_VSCODE_WORKSPACE_FILE=%s\n' "$(config_or_env 'ACP_VSCODE_WORKSPACE_FILE
|
|
79
|
-
printf 'EFFECTIVE_CODING_WORKER=%s\n' "$(config_or_env 'ACP_CODING_WORKER
|
|
80
|
-
printf 'EFFECTIVE_PROVIDER_QUOTA_COOLDOWNS=%s\n' "$(config_or_env 'ACP_PROVIDER_QUOTA_COOLDOWNS
|
|
81
|
-
printf 'EFFECTIVE_PROVIDER_POOL_ORDER=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_ORDER
|
|
82
|
-
printf 'EFFECTIVE_PROVIDER_POOL_NAME=%s\n' "$(config_or_env 'ACP_ACTIVE_PROVIDER_POOL_NAME
|
|
83
|
-
printf 'EFFECTIVE_PROVIDER_POOL_BACKEND=%s\n' "$(config_or_env 'ACP_ACTIVE_PROVIDER_BACKEND
|
|
84
|
-
printf 'EFFECTIVE_PROVIDER_POOL_MODEL=%s\n' "$(config_or_env 'ACP_ACTIVE_PROVIDER_MODEL
|
|
85
|
-
printf 'EFFECTIVE_PROVIDER_POOL_KEY=%s\n' "$(config_or_env 'ACP_ACTIVE_PROVIDER_KEY
|
|
86
|
-
printf 'EFFECTIVE_PROVIDER_POOLS_EXHAUSTED=%s\n' "$(config_or_env 'ACP_PROVIDER_POOLS_EXHAUSTED
|
|
87
|
-
printf 'EFFECTIVE_PROVIDER_POOL_SELECTION_REASON=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_SELECTION_REASON
|
|
88
|
-
printf 'EFFECTIVE_PROVIDER_POOL_NEXT_ATTEMPT_EPOCH=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_NEXT_ATTEMPT_EPOCH
|
|
89
|
-
printf 'EFFECTIVE_PROVIDER_POOL_NEXT_ATTEMPT_AT=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_NEXT_ATTEMPT_AT
|
|
90
|
-
printf 'EFFECTIVE_PROVIDER_POOL_LAST_REASON=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_LAST_REASON
|
|
91
|
-
printf 'EFFECTIVE_CODEX_PROFILE_SAFE=%s\n' "$(config_or_env 'ACP_CODEX_PROFILE_SAFE
|
|
92
|
-
printf 'EFFECTIVE_CODEX_PROFILE_BYPASS=%s\n' "$(config_or_env 'ACP_CODEX_PROFILE_BYPASS
|
|
93
|
-
printf 'EFFECTIVE_CLAUDE_MODEL=%s\n' "$(config_or_env 'ACP_CLAUDE_MODEL
|
|
94
|
-
printf 'EFFECTIVE_CLAUDE_PERMISSION_MODE=%s\n' "$(config_or_env 'ACP_CLAUDE_PERMISSION_MODE
|
|
95
|
-
printf 'EFFECTIVE_CLAUDE_EFFORT=%s\n' "$(config_or_env 'ACP_CLAUDE_EFFORT
|
|
96
|
-
printf 'EFFECTIVE_CLAUDE_TIMEOUT_SECONDS=%s\n' "$(config_or_env 'ACP_CLAUDE_TIMEOUT_SECONDS
|
|
97
|
-
printf 'EFFECTIVE_CLAUDE_MAX_ATTEMPTS=%s\n' "$(config_or_env 'ACP_CLAUDE_MAX_ATTEMPTS
|
|
98
|
-
printf 'EFFECTIVE_CLAUDE_RETRY_BACKOFF_SECONDS=%s\n' "$(config_or_env 'ACP_CLAUDE_RETRY_BACKOFF_SECONDS
|
|
99
|
-
printf 'EFFECTIVE_OPENCLAW_MODEL=%s\n' "$(config_or_env 'ACP_OPENCLAW_MODEL
|
|
100
|
-
printf 'EFFECTIVE_OPENCLAW_THINKING=%s\n' "$(config_or_env 'ACP_OPENCLAW_THINKING
|
|
101
|
-
printf 'EFFECTIVE_OPENCLAW_TIMEOUT_SECONDS=%s\n' "$(config_or_env 'ACP_OPENCLAW_TIMEOUT_SECONDS
|
|
69
|
+
printf 'EFFECTIVE_REPO_ROOT=%s\n' "$(config_or_env 'ACP_REPO_ROOT' repo.root)"
|
|
70
|
+
printf 'EFFECTIVE_AGENT_REPO_ROOT=%s\n' "$(config_or_env 'ACP_AGENT_REPO_ROOT' runtime.agent_repo_root)"
|
|
71
|
+
printf 'EFFECTIVE_WORKTREE_ROOT=%s\n' "$(config_or_env 'ACP_WORKTREE_ROOT' runtime.worktree_root)"
|
|
72
|
+
printf 'EFFECTIVE_RUNS_ROOT=%s\n' "$(config_or_env 'ACP_RUNS_ROOT' runtime.runs_root)"
|
|
73
|
+
printf 'EFFECTIVE_STATE_ROOT=%s\n' "$(config_or_env 'ACP_STATE_ROOT' runtime.state_root)"
|
|
74
|
+
printf 'EFFECTIVE_RETAINED_REPO_ROOT=%s\n' "$(config_or_env 'ACP_RETAINED_REPO_ROOT' runtime.retained_repo_root)"
|
|
75
|
+
printf 'EFFECTIVE_VSCODE_WORKSPACE_FILE=%s\n' "$(config_or_env 'ACP_VSCODE_WORKSPACE_FILE' runtime.vscode_workspace_file)"
|
|
76
|
+
printf 'EFFECTIVE_CODING_WORKER=%s\n' "$(config_or_env 'ACP_CODING_WORKER' execution.coding_worker)"
|
|
77
|
+
printf 'EFFECTIVE_PROVIDER_QUOTA_COOLDOWNS=%s\n' "$(config_or_env 'ACP_PROVIDER_QUOTA_COOLDOWNS' execution.provider_quota.cooldowns)"
|
|
78
|
+
printf 'EFFECTIVE_PROVIDER_POOL_ORDER=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_ORDER' execution.provider_pool_order)"
|
|
79
|
+
printf 'EFFECTIVE_PROVIDER_POOL_NAME=%s\n' "$(config_or_env 'ACP_ACTIVE_PROVIDER_POOL_NAME')"
|
|
80
|
+
printf 'EFFECTIVE_PROVIDER_POOL_BACKEND=%s\n' "$(config_or_env 'ACP_ACTIVE_PROVIDER_BACKEND')"
|
|
81
|
+
printf 'EFFECTIVE_PROVIDER_POOL_MODEL=%s\n' "$(config_or_env 'ACP_ACTIVE_PROVIDER_MODEL')"
|
|
82
|
+
printf 'EFFECTIVE_PROVIDER_POOL_KEY=%s\n' "$(config_or_env 'ACP_ACTIVE_PROVIDER_KEY')"
|
|
83
|
+
printf 'EFFECTIVE_PROVIDER_POOLS_EXHAUSTED=%s\n' "$(config_or_env 'ACP_PROVIDER_POOLS_EXHAUSTED')"
|
|
84
|
+
printf 'EFFECTIVE_PROVIDER_POOL_SELECTION_REASON=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_SELECTION_REASON')"
|
|
85
|
+
printf 'EFFECTIVE_PROVIDER_POOL_NEXT_ATTEMPT_EPOCH=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_NEXT_ATTEMPT_EPOCH')"
|
|
86
|
+
printf 'EFFECTIVE_PROVIDER_POOL_NEXT_ATTEMPT_AT=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_NEXT_ATTEMPT_AT')"
|
|
87
|
+
printf 'EFFECTIVE_PROVIDER_POOL_LAST_REASON=%s\n' "$(config_or_env 'ACP_PROVIDER_POOL_LAST_REASON')"
|
|
88
|
+
printf 'EFFECTIVE_CODEX_PROFILE_SAFE=%s\n' "$(config_or_env 'ACP_CODEX_PROFILE_SAFE' execution.safe_profile)"
|
|
89
|
+
printf 'EFFECTIVE_CODEX_PROFILE_BYPASS=%s\n' "$(config_or_env 'ACP_CODEX_PROFILE_BYPASS' execution.bypass_profile)"
|
|
90
|
+
printf 'EFFECTIVE_CLAUDE_MODEL=%s\n' "$(config_or_env 'ACP_CLAUDE_MODEL' execution.claude.model)"
|
|
91
|
+
printf 'EFFECTIVE_CLAUDE_PERMISSION_MODE=%s\n' "$(config_or_env 'ACP_CLAUDE_PERMISSION_MODE' execution.claude.permission_mode)"
|
|
92
|
+
printf 'EFFECTIVE_CLAUDE_EFFORT=%s\n' "$(config_or_env 'ACP_CLAUDE_EFFORT' execution.claude.effort)"
|
|
93
|
+
printf 'EFFECTIVE_CLAUDE_TIMEOUT_SECONDS=%s\n' "$(config_or_env 'ACP_CLAUDE_TIMEOUT_SECONDS' execution.claude.timeout_seconds)"
|
|
94
|
+
printf 'EFFECTIVE_CLAUDE_MAX_ATTEMPTS=%s\n' "$(config_or_env 'ACP_CLAUDE_MAX_ATTEMPTS' execution.claude.max_attempts)"
|
|
95
|
+
printf 'EFFECTIVE_CLAUDE_RETRY_BACKOFF_SECONDS=%s\n' "$(config_or_env 'ACP_CLAUDE_RETRY_BACKOFF_SECONDS' execution.claude.retry_backoff_seconds)"
|
|
96
|
+
printf 'EFFECTIVE_OPENCLAW_MODEL=%s\n' "$(config_or_env 'ACP_OPENCLAW_MODEL' execution.openclaw.model)"
|
|
97
|
+
printf 'EFFECTIVE_OPENCLAW_THINKING=%s\n' "$(config_or_env 'ACP_OPENCLAW_THINKING' execution.openclaw.thinking)"
|
|
98
|
+
printf 'EFFECTIVE_OPENCLAW_TIMEOUT_SECONDS=%s\n' "$(config_or_env 'ACP_OPENCLAW_TIMEOUT_SECONDS' execution.openclaw.timeout_seconds)"
|
|
@@ -35,7 +35,7 @@ RECONCILE_COMMAND=""
|
|
|
35
35
|
ADAPTER_ID="$(flow_resolve_adapter_id "${CONFIG_YAML}")"
|
|
36
36
|
ISSUE_SESSION_PREFIX="$(flow_resolve_issue_session_prefix "${CONFIG_YAML}")"
|
|
37
37
|
PR_SESSION_PREFIX="$(flow_resolve_pr_session_prefix "${CONFIG_YAML}")"
|
|
38
|
-
CODING_WORKER="${ACP_CODING_WORKER
|
|
38
|
+
CODING_WORKER="${ACP_CODING_WORKER:-codex}"
|
|
39
39
|
CODEX_PROFILE_SAFE="${ACP_CODEX_PROFILE_SAFE:-${F_LOSNING_CODEX_PROFILE_SAFE:-${CODEX_PROFILE_SAFE:-f_losning_safe_auto}}}"
|
|
40
40
|
CODEX_PROFILE_BYPASS="${ACP_CODEX_PROFILE_BYPASS:-${F_LOSNING_CODEX_PROFILE_BYPASS:-${CODEX_PROFILE_BYPASS:-f_losning_yolo}}}"
|
|
41
41
|
if [[ "$MODE" == "bypass" ]]; then
|
|
@@ -64,23 +64,47 @@ RESIDENT_OPENCLAW_CONFIG_PATH="${ACP_RESIDENT_OPENCLAW_CONFIG_PATH:-${F_LOSNING_
|
|
|
64
64
|
OPENCLAW_MODEL="${OPENCLAW_MODEL:-${ACP_OPENCLAW_MODEL:-${F_LOSNING_OPENCLAW_MODEL:-openrouter/qwen/qwen3.6-plus-preview:free}}}"
|
|
65
65
|
OPENCLAW_THINKING="${OPENCLAW_THINKING:-${ACP_OPENCLAW_THINKING:-${F_LOSNING_OPENCLAW_THINKING:-low}}}"
|
|
66
66
|
OPENCLAW_TIMEOUT_SECONDS="${OPENCLAW_TIMEOUT_SECONDS:-${ACP_OPENCLAW_TIMEOUT_SECONDS:-${F_LOSNING_OPENCLAW_TIMEOUT_SECONDS:-900}}}"
|
|
67
|
+
OLLAMA_MODEL="${ACP_OLLAMA_MODEL:-${F_LOSNING_OLLAMA_MODEL:-qwen2.5-coder:7b}}"
|
|
68
|
+
OLLAMA_BASE_URL="${ACP_OLLAMA_BASE_URL:-${F_LOSNING_OLLAMA_BASE_URL:-http://localhost:11434}}"
|
|
69
|
+
OLLAMA_TIMEOUT_SECONDS="${ACP_OLLAMA_TIMEOUT_SECONDS:-${F_LOSNING_OLLAMA_TIMEOUT_SECONDS:-900}}"
|
|
70
|
+
PI_MODEL="${ACP_PI_MODEL:-${F_LOSNING_PI_MODEL:-openrouter/qwen/qwen3.6-plus:free}}"
|
|
71
|
+
PI_THINKING="${ACP_PI_THINKING:-${F_LOSNING_PI_THINKING:-low}}"
|
|
72
|
+
PI_TIMEOUT_SECONDS="${ACP_PI_TIMEOUT_SECONDS:-${F_LOSNING_PI_TIMEOUT_SECONDS:-900}}"
|
|
73
|
+
PI_STALL_SECONDS="${ACP_PI_STALL_SECONDS:-${F_LOSNING_PI_STALL_SECONDS:-300}}"
|
|
74
|
+
OPENCODE_MODEL="${ACP_OPENCODE_MODEL:-${F_LOSNING_OPENCODE_MODEL:-anthropic/claude-sonnet-4-20250514}}"
|
|
75
|
+
OPENCODE_TIMEOUT_SECONDS="${ACP_OPENCODE_TIMEOUT_SECONDS:-${F_LOSNING_OPENCODE_TIMEOUT_SECONDS:-900}}"
|
|
76
|
+
KILO_MODEL="${ACP_KILO_MODEL:-${F_LOSNING_KILO_MODEL:-anthropic/claude-sonnet-4-20250514}}"
|
|
77
|
+
KILO_TIMEOUT_SECONDS="${ACP_KILO_TIMEOUT_SECONDS:-${F_LOSNING_KILO_TIMEOUT_SECONDS:-900}}"
|
|
67
78
|
printf -v SESSION_Q '%q' "$SESSION"
|
|
68
79
|
printf -v CONFIG_YAML_Q '%q' "$CONFIG_YAML"
|
|
69
80
|
printf -v ADAPTER_ID_Q '%q' "$ADAPTER_ID"
|
|
70
|
-
|
|
81
|
+
printf -v CANONICAL_REPO_ROOT_Q '%q' "$CANONICAL_REPO_ROOT"
|
|
82
|
+
RECONCILE_ENV_PREFIX="ACP_PROJECT_ID=${ADAPTER_ID_Q} AGENT_PROJECT_ID=${ADAPTER_ID_Q} AGENT_CONTROL_PLANE_CONFIG=${CONFIG_YAML_Q} ACP_CONFIG=${CONFIG_YAML_Q} ACP_ROOT=${CANONICAL_REPO_ROOT_Q} AGENT_CONTROL_PLANE_ROOT=${CANONICAL_REPO_ROOT_Q}"
|
|
83
|
+
|
|
84
|
+
# The materialized skills surface is cleaned up after each heartbeat cycle.
|
|
85
|
+
# Reconcile runs post-tmux via nohup, after the skills dir is gone.
|
|
86
|
+
# Use the permanent runtime-home/tools/bin path derived from AGENT_PLATFORM_HOME.
|
|
87
|
+
_runtime_tools_bin="${AGENT_PLATFORM_HOME:-${HOME}/.agent-runtime}/runtime-home/tools/bin"
|
|
88
|
+
if [[ -f "${_runtime_tools_bin}/reconcile-pr-worker.sh" ]]; then
|
|
89
|
+
RECONCILE_ISSUE_BIN="${_runtime_tools_bin}/reconcile-issue-worker.sh"
|
|
90
|
+
RECONCILE_PR_BIN="${_runtime_tools_bin}/reconcile-pr-worker.sh"
|
|
91
|
+
else
|
|
92
|
+
RECONCILE_ISSUE_BIN="${WORKSPACE_DIR}/bin/reconcile-issue-worker.sh"
|
|
93
|
+
RECONCILE_PR_BIN="${WORKSPACE_DIR}/bin/reconcile-pr-worker.sh"
|
|
94
|
+
fi
|
|
71
95
|
|
|
72
96
|
case "$SESSION" in
|
|
73
97
|
"${ISSUE_SESSION_PREFIX}"*)
|
|
74
98
|
TASK_KIND="issue"
|
|
75
99
|
TASK_ID="${ISSUE_ID:-${SESSION#${ISSUE_SESSION_PREFIX}}}"
|
|
76
100
|
if [[ "${RESIDENT_WORKER_ENABLED}" != "yes" ]]; then
|
|
77
|
-
RECONCILE_COMMAND="${RECONCILE_ENV_PREFIX} ${
|
|
101
|
+
RECONCILE_COMMAND="${RECONCILE_ENV_PREFIX} ${RECONCILE_ISSUE_BIN} ${SESSION_Q}"
|
|
78
102
|
fi
|
|
79
103
|
;;
|
|
80
104
|
"${PR_SESSION_PREFIX}"*)
|
|
81
105
|
TASK_KIND="pr"
|
|
82
106
|
TASK_ID="${PR_NUMBER:-${SESSION#${PR_SESSION_PREFIX}}}"
|
|
83
|
-
RECONCILE_COMMAND="${RECONCILE_ENV_PREFIX} ${
|
|
107
|
+
RECONCILE_COMMAND="${RECONCILE_ENV_PREFIX} ${RECONCILE_PR_BIN} ${SESSION_Q}"
|
|
84
108
|
;;
|
|
85
109
|
esac
|
|
86
110
|
|
|
@@ -219,11 +243,36 @@ case "$CODING_WORKER" in
|
|
|
219
243
|
bash "${FLOW_TOOLS_DIR}/agent-project-run-openclaw-session" "${ARGS[@]}"
|
|
220
244
|
;;
|
|
221
245
|
opencode)
|
|
246
|
+
ARGS+=(
|
|
247
|
+
--opencode-model "${OPENCODE_MODEL}"
|
|
248
|
+
--opencode-timeout-seconds "${OPENCODE_TIMEOUT_SECONDS}"
|
|
249
|
+
)
|
|
222
250
|
bash "${FLOW_TOOLS_DIR}/agent-project-run-opencode-session" "${ARGS[@]}"
|
|
223
251
|
;;
|
|
224
252
|
kilo)
|
|
253
|
+
ARGS+=(
|
|
254
|
+
--kilo-model "${KILO_MODEL}"
|
|
255
|
+
--kilo-timeout-seconds "${KILO_TIMEOUT_SECONDS}"
|
|
256
|
+
)
|
|
225
257
|
bash "${FLOW_TOOLS_DIR}/agent-project-run-kilo-session" "${ARGS[@]}"
|
|
226
258
|
;;
|
|
259
|
+
ollama)
|
|
260
|
+
ARGS+=(
|
|
261
|
+
--ollama-model "${OLLAMA_MODEL}"
|
|
262
|
+
--ollama-base-url "${OLLAMA_BASE_URL}"
|
|
263
|
+
--ollama-timeout-seconds "${OLLAMA_TIMEOUT_SECONDS}"
|
|
264
|
+
)
|
|
265
|
+
bash "${FLOW_TOOLS_DIR}/agent-project-run-ollama-session" "${ARGS[@]}"
|
|
266
|
+
;;
|
|
267
|
+
pi)
|
|
268
|
+
ARGS+=(
|
|
269
|
+
--pi-model "${PI_MODEL}"
|
|
270
|
+
--pi-thinking "${PI_THINKING}"
|
|
271
|
+
--pi-timeout-seconds "${PI_TIMEOUT_SECONDS}"
|
|
272
|
+
--pi-stall-seconds "${PI_STALL_SECONDS}"
|
|
273
|
+
)
|
|
274
|
+
bash "${FLOW_TOOLS_DIR}/agent-project-run-pi-session" "${ARGS[@]}"
|
|
275
|
+
;;
|
|
227
276
|
*)
|
|
228
277
|
echo "unsupported coding worker: ${CODING_WORKER}" >&2
|
|
229
278
|
exit 1
|
|
@@ -22,7 +22,7 @@ Options:
|
|
|
22
22
|
--worktree-root <path> Worktree parent root
|
|
23
23
|
--retained-repo-root <path> Optional retained/manual checkout root
|
|
24
24
|
--vscode-workspace-file <path> Optional VS Code workspace file
|
|
25
|
-
--coding-worker <codex|openclaw|claude>
|
|
25
|
+
--coding-worker <codex|openclaw|claude|ollama|pi|opencode|kilo>
|
|
26
26
|
Default coding backend (default: openclaw)
|
|
27
27
|
--claude-model <model> Claude model alias or full name
|
|
28
28
|
--claude-permission-mode <mode> Claude permission mode (default: acceptEdits)
|
|
@@ -97,9 +97,9 @@ if [[ ! "$profile_id" =~ ^[a-z0-9][a-z0-9-]*$ ]]; then
|
|
|
97
97
|
fi
|
|
98
98
|
|
|
99
99
|
case "$coding_worker" in
|
|
100
|
-
codex|openclaw|claude) ;;
|
|
100
|
+
codex|openclaw|claude|ollama|pi|opencode|kilo) ;;
|
|
101
101
|
*)
|
|
102
|
-
echo "--coding-worker must be codex, openclaw, or
|
|
102
|
+
echo "--coding-worker must be codex, openclaw, claude, ollama, pi, opencode, or kilo" >&2
|
|
103
103
|
exit 1
|
|
104
104
|
;;
|
|
105
105
|
esac
|
|
@@ -271,6 +271,21 @@ execution:
|
|
|
271
271
|
model: "${openclaw_model}"
|
|
272
272
|
thinking: "${openclaw_thinking}"
|
|
273
273
|
timeout_seconds: ${openclaw_timeout_seconds}
|
|
274
|
+
ollama:
|
|
275
|
+
model: "qwen2.5-coder:7b"
|
|
276
|
+
base_url: "http://localhost:11434"
|
|
277
|
+
timeout_seconds: 900
|
|
278
|
+
pi:
|
|
279
|
+
model: "openrouter/qwen/qwen3.6-plus:free"
|
|
280
|
+
thinking: "low"
|
|
281
|
+
timeout_seconds: 900
|
|
282
|
+
stall_seconds: 300
|
|
283
|
+
opencode:
|
|
284
|
+
model: "anthropic/claude-sonnet-4-20250514"
|
|
285
|
+
timeout_seconds: 900
|
|
286
|
+
kilo:
|
|
287
|
+
model: "anthropic/claude-sonnet-4-20250514"
|
|
288
|
+
timeout_seconds: 900
|
|
274
289
|
review_requires_independent_final_review: true
|
|
275
290
|
verification:
|
|
276
291
|
web_playwright_command: "pnpm exec playwright test"
|
|
@@ -30,7 +30,7 @@ LOCAL_INSTALL_POLICY_BIN="${WORKSPACE_DIR}/bin/issue-requires-local-workspace-in
|
|
|
30
30
|
SESSION="${ISSUE_SESSION_PREFIX}${ISSUE_ID}"
|
|
31
31
|
RUN_DIR="${RUNS_ROOT}/${SESSION}"
|
|
32
32
|
UPDATE_LABELS_BIN="${WORKSPACE_DIR}/bin/agent-github-update-labels"
|
|
33
|
-
CODING_WORKER="${ACP_CODING_WORKER
|
|
33
|
+
CODING_WORKER="${ACP_CODING_WORKER:-codex}"
|
|
34
34
|
launch_success="no"
|
|
35
35
|
label_rollback_armed="no"
|
|
36
36
|
RECURRING_CHECKLIST_SYNC_BIN="${FLOW_TOOLS_DIR}/sync-recurring-issue-checklist.sh"
|
|
@@ -54,6 +54,9 @@ rollback_labels_on_failure() {
|
|
|
54
54
|
if [[ "${label_rollback_armed}" != "yes" || "${launch_success}" == "yes" ]]; then
|
|
55
55
|
return 0
|
|
56
56
|
fi
|
|
57
|
+
if [[ -d "${RUN_DIR}" && ! -f "${RUN_DIR}/run.env" && ! -f "${RUN_DIR}/runner.env" && ! -f "${RUN_DIR}/result.env" ]]; then
|
|
58
|
+
rm -rf "${RUN_DIR}" >/dev/null 2>&1 || true
|
|
59
|
+
fi
|
|
57
60
|
if [[ -x "${UPDATE_LABELS_BIN}" ]]; then
|
|
58
61
|
bash "${UPDATE_LABELS_BIN}" --repo-slug "${REPO_SLUG}" --number "${ISSUE_ID}" --remove agent-running >/dev/null 2>&1 || true
|
|
59
62
|
fi
|
|
@@ -33,6 +33,9 @@ rollback_labels_on_failure() {
|
|
|
33
33
|
if [[ "${label_rollback_armed}" != "yes" || "${launch_success}" == "yes" ]]; then
|
|
34
34
|
return 0
|
|
35
35
|
fi
|
|
36
|
+
if [[ -d "${RUN_DIR}" && ! -f "${RUN_DIR}/run.env" && ! -f "${RUN_DIR}/runner.env" && ! -f "${RUN_DIR}/result.env" ]]; then
|
|
37
|
+
rm -rf "${RUN_DIR}" >/dev/null 2>&1 || true
|
|
38
|
+
fi
|
|
36
39
|
if [[ -x "${UPDATE_LABELS_BIN}" ]]; then
|
|
37
40
|
bash "${UPDATE_LABELS_BIN}" --repo-slug "${REPO_SLUG}" --number "${PR_NUMBER}" --remove agent-running >/dev/null 2>&1 || true
|
|
38
41
|
fi
|
|
@@ -130,6 +133,34 @@ PR_LINKED_ISSUE_ID="$(jq -r '.linkedIssueId // ""' <<<"$RISK_JSON")"
|
|
|
130
133
|
PR_FILES_TEXT="$(jq -r '.files[] | "- " + .' <<<"$RISK_JSON")"
|
|
131
134
|
PR_REPO_ROOT="$(flow_resolve_repo_root "${CONFIG_YAML}")"
|
|
132
135
|
PR_DEPENDENCY_SOURCE_ROOT="${ACP_DEPENDENCY_SOURCE_ROOT:-${F_LOSNING_DEPENDENCY_SOURCE_ROOT:-$PR_REPO_ROOT}}"
|
|
136
|
+
render_pr_context_reads_text() {
|
|
137
|
+
local repo_root="${1:?repo root required}"
|
|
138
|
+
local -a candidate_paths=(
|
|
139
|
+
"${repo_root}/AGENTS.md"
|
|
140
|
+
"${repo_root}/openspec/AGENT_RULES.md"
|
|
141
|
+
"${repo_root}/openspec/AGENTS.md"
|
|
142
|
+
"${repo_root}/openspec/project.md"
|
|
143
|
+
"${repo_root}/openspec/CONVENTIONS.md"
|
|
144
|
+
"${repo_root}/docs/TESTING_AND_SEED_POLICY.md"
|
|
145
|
+
)
|
|
146
|
+
local -a existing_paths=()
|
|
147
|
+
local candidate_path=""
|
|
148
|
+
|
|
149
|
+
for candidate_path in "${candidate_paths[@]}"; do
|
|
150
|
+
if [[ -f "${candidate_path}" ]]; then
|
|
151
|
+
existing_paths+=("${candidate_path}")
|
|
152
|
+
fi
|
|
153
|
+
done
|
|
154
|
+
|
|
155
|
+
if [[ "${#existing_paths[@]}" -eq 0 ]]; then
|
|
156
|
+
printf '%s\n' '- No repo-specific context files were found under the expected AGENTS/OpenSpec/testing-doc locations; rely on the current diff and nearby source.'
|
|
157
|
+
return 0
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
printf '%s\n' "${existing_paths[@]}" | sed 's/^/- `/' | sed 's/$/`/'
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
PR_CONTEXT_READS_TEXT="$(render_pr_context_reads_text "${PR_REPO_ROOT}")"
|
|
133
164
|
PR_CHECK_FAILURES_TEXT="$(jq -r '(.checkFailures + .pendingChecks)[]? | "- " + .' <<<"$RISK_JSON")"
|
|
134
165
|
if [[ -z "$PR_CHECK_FAILURES_TEXT" ]]; then
|
|
135
166
|
PR_CHECK_FAILURES_TEXT="- none reported"
|
|
@@ -290,6 +321,7 @@ PR_MERGE_STATE_STATUS="$PR_MERGE_STATE_STATUS" \
|
|
|
290
321
|
PR_MERGEABLE_STATUS="$PR_MERGEABLE_STATUS" \
|
|
291
322
|
PR_CHECKS_TEXT="$PR_CHECKS_TEXT" \
|
|
292
323
|
PR_FILES_TEXT="$PR_FILES_TEXT" \
|
|
324
|
+
PR_CONTEXT_READS_TEXT="$PR_CONTEXT_READS_TEXT" \
|
|
293
325
|
PR_CHECK_FAILURES_TEXT="$PR_CHECK_FAILURES_TEXT" \
|
|
294
326
|
PR_MISSING_REASONS_TEXT="$PR_MISSING_REASONS_TEXT" \
|
|
295
327
|
PR_REVIEW_FINDINGS_TEXT="$PR_REVIEW_FINDINGS_TEXT" \
|
|
@@ -400,6 +432,7 @@ const replacements = {
|
|
|
400
432
|
'{PR_MERGEABLE_STATUS}': process.env.PR_MERGEABLE_STATUS || '',
|
|
401
433
|
'{PR_CHECKS_TEXT}': process.env.PR_CHECKS_TEXT || '',
|
|
402
434
|
'{PR_FILES_TEXT}': process.env.PR_FILES_TEXT || '',
|
|
435
|
+
'{PR_CONTEXT_READS_TEXT}': process.env.PR_CONTEXT_READS_TEXT || '',
|
|
403
436
|
'{PR_CHECK_FAILURES_TEXT}': process.env.PR_CHECK_FAILURES_TEXT || '',
|
|
404
437
|
'{PR_MISSING_REASONS_TEXT}': process.env.PR_MISSING_REASONS_TEXT || '',
|
|
405
438
|
'{PR_REVIEW_FINDINGS_TEXT}': process.env.PR_REVIEW_FINDINGS_TEXT || '',
|