@runuai/host 0.8.19 → 0.8.21
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/lib/agent.ts +2 -0
- package/package.json +1 -1
- package/scripts/agent/task-down.sh +16 -10
- package/scripts/agent/task-up.sh +26 -2
- package/src/index.ts +8 -0
- package/src/protocol.ts +2 -0
package/lib/agent.ts
CHANGED
|
@@ -75,6 +75,8 @@ const TaskUpData = z.object({
|
|
|
75
75
|
worktreePath: z.string(),
|
|
76
76
|
codeServerPort: z.number().int().positive().optional(),
|
|
77
77
|
previewPorts: PreviewPortRuntimesSchema.optional(),
|
|
78
|
+
/** Degraded start: uai-init failed twice; surfaced as a feed system note. */
|
|
79
|
+
initWarning: z.string().optional(),
|
|
78
80
|
});
|
|
79
81
|
export type TaskUpResult = z.infer<typeof TaskUpData>;
|
|
80
82
|
|
package/package.json
CHANGED
|
@@ -20,17 +20,23 @@ UAI_TASK_ID="$task_id"
|
|
|
20
20
|
setup_err_trap
|
|
21
21
|
|
|
22
22
|
step "TASK_NOT_FOUND" "read task row"
|
|
23
|
-
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
# Teardown must never depend on bookkeeping: a broken/missing command
|
|
24
|
+
# snapshot (seen live 2026-07-21 cleaning up after a failed task-up —
|
|
25
|
+
# db_get_task errored, the trap reported TASK_NOT_FOUND, and the container
|
|
26
|
+
# survived) still tears the stack down by convention-derived names.
|
|
27
|
+
task_json=$(db_get_task "$task_id" 2>/dev/null) || task_json="[]"
|
|
28
|
+
row_count=$(jq 'length' <<<"$task_json" 2>/dev/null) || row_count=0
|
|
29
|
+
if [ "$row_count" -lt 1 ]; then
|
|
30
|
+
log "task row unavailable — tearing down by derived names"
|
|
31
|
+
worktree_path=""
|
|
32
|
+
compose_project="$(compose_project_for_task "$task_id")"
|
|
33
|
+
projects_json="[]"
|
|
34
|
+
else
|
|
35
|
+
worktree_path=$(jq -r '.[0].worktree_path // ""' <<<"$task_json")
|
|
36
|
+
compose_project=$(jq -r '.[0].compose_project // ""' <<<"$task_json")
|
|
37
|
+
projects_json=$(db_get_projects_for_task "$task_id" 2>/dev/null) \
|
|
38
|
+
|| projects_json="[]"
|
|
28
39
|
fi
|
|
29
|
-
|
|
30
|
-
worktree_path=$(jq -r '.[0].worktree_path // ""' <<<"$task_json")
|
|
31
|
-
compose_project=$(jq -r '.[0].compose_project // ""' <<<"$task_json")
|
|
32
|
-
|
|
33
|
-
projects_json=$(db_get_projects_for_task "$task_id")
|
|
34
40
|
projects_root="$UAI_WORKSPACE_ROOT/projects"
|
|
35
41
|
|
|
36
42
|
# task_dir falls back to the derived path when the row's worktree_path is
|
package/scripts/agent/task-up.sh
CHANGED
|
@@ -198,7 +198,15 @@ while IFS= read -r project_obj; do
|
|
|
198
198
|
[ -n "$project_default" ] || project_default="main"
|
|
199
199
|
|
|
200
200
|
mkdir -p "$(dirname "$worktree_target")"
|
|
201
|
-
if
|
|
201
|
+
if [ -e "$worktree_target/.git" ]; then
|
|
202
|
+
# Resume (ADR-028): the task worktree survived the stop — reuse it as-is
|
|
203
|
+
# (a linked worktree's .git is a FILE, hence -e). Re-running `git
|
|
204
|
+
# worktree add` would refuse ("already exists" / branch exists) and
|
|
205
|
+
# errored EVERY resume of a worktree-preserving stop within seconds
|
|
206
|
+
# (found live 2026-07-21). The task branch and any uncommitted work are
|
|
207
|
+
# exactly what the user expects back.
|
|
208
|
+
log "worktree for $project_slug already present — resuming with it"
|
|
209
|
+
elif git -C "$mirror_dir" rev-parse --verify --quiet \
|
|
202
210
|
"refs/remotes/origin/$project_default" >/dev/null 2>&1; then
|
|
203
211
|
# Normal case: branch the task worktree off origin/<defaultBranch>.
|
|
204
212
|
step "WORKTREE_FAILED" "git worktree add ($project_id)"
|
|
@@ -537,7 +545,21 @@ if [ -f "$uai_identity_key" ]; then
|
|
|
537
545
|
>/dev/null 2>&1 || true
|
|
538
546
|
fi
|
|
539
547
|
|
|
540
|
-
|
|
548
|
+
# uai-init (workspace deps + code-server) is re-runnable, and its death must
|
|
549
|
+
# not error a task whose container is already up (graceful degradation): a
|
|
550
|
+
# SIGKILLed exec session (observed live 2026-07-21, exit 137 with no timeout
|
|
551
|
+
# anywhere on this path) used to fail the whole task over a step anyone can
|
|
552
|
+
# re-run. Retry once, then come up DEGRADED with a warning the host surfaces
|
|
553
|
+
# as a system note in the task feed.
|
|
554
|
+
init_warning=""
|
|
555
|
+
if ! docker exec "$app_container" /usr/local/bin/uai-init >/dev/null; then
|
|
556
|
+
log "warning: uai-init failed — retrying once"
|
|
557
|
+
sleep 2
|
|
558
|
+
if ! docker exec "$app_container" /usr/local/bin/uai-init >/dev/null; then
|
|
559
|
+
init_warning="Workspace init (deps + editor) failed twice — the task is up, but the editor and installed dependencies may be missing. Retry from a task terminal with: /usr/local/bin/uai-init"
|
|
560
|
+
log "warning: $init_warning"
|
|
561
|
+
fi
|
|
562
|
+
fi
|
|
541
563
|
|
|
542
564
|
# -----------------------------------------------------------------------------
|
|
543
565
|
# 7. Discover code-server + preview ports, mark running, unlock.
|
|
@@ -580,7 +602,9 @@ emit_ok "$(jq -nc \
|
|
|
580
602
|
--arg cp "$compose_project" \
|
|
581
603
|
--arg wp "$task_dir" \
|
|
582
604
|
--arg csport "${code_server_port:-}" \
|
|
605
|
+
--arg iw "${init_warning}" \
|
|
583
606
|
--argjson previewPorts "$preview_ports_runtime_json" \
|
|
584
607
|
'{composeProject:$cp,worktreePath:$wp}
|
|
585
608
|
+ (if $csport == "" then {} else {codeServerPort:($csport|tonumber)} end)
|
|
609
|
+
+ (if $iw == "" then {} else {initWarning:$iw} end)
|
|
586
610
|
+ {previewPorts:$previewPorts}')"
|
package/src/index.ts
CHANGED
|
@@ -123,6 +123,14 @@ export const hostCommands: HostCommands = {
|
|
|
123
123
|
if (result.ok) {
|
|
124
124
|
recordTaskUpResult(input.task.id, result.value);
|
|
125
125
|
recordHostEvent(input.task.id, "task.started");
|
|
126
|
+
// Degraded start (uai-init failed twice): the task is up, but say so
|
|
127
|
+
// in the feed — a silent half-start reads as a broken product.
|
|
128
|
+
if (result.value.initWarning) {
|
|
129
|
+
getOrchestrator().emitSystemNote(
|
|
130
|
+
input.task.id,
|
|
131
|
+
result.value.initWarning,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
126
134
|
// GitHub auth for the container is best-effort (ADR-027) and runs in the
|
|
127
135
|
// background — it must never block or fail task-up. Awaiting it here would
|
|
128
136
|
// couple the command result to a network token-exchange: a slow/hung
|
package/src/protocol.ts
CHANGED
|
@@ -93,6 +93,8 @@ export interface TaskUpResult {
|
|
|
93
93
|
worktreePath: string;
|
|
94
94
|
codeServerPort?: number;
|
|
95
95
|
previewPorts?: Array<{ name: string; hostPort: number }>;
|
|
96
|
+
/** Degraded start: uai-init failed twice; the task is up without deps/editor. */
|
|
97
|
+
initWarning?: string;
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
export interface TaskDownResult {
|