thinkpool-pair 0.7.101 → 0.7.103
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/bridge.mjs +1 -1
- package/flow-conductor.mjs +2 -0
- package/package.json +1 -1
- package/service.mjs +18 -5
package/bridge.mjs
CHANGED
|
@@ -594,7 +594,7 @@ const announce = () =>
|
|
|
594
594
|
// the chosen label instead of defaulting to Normal / unnamed. `spawned` (set
|
|
595
595
|
// when an agent Dispatched this lane via spawn_terminal) lets the client keep
|
|
596
596
|
// it OUT of the top tab strip and show it only in the Ensemble menu.
|
|
597
|
-
...[...sessions.entries()].map(([id, s]) => ({ id, cmd: s.cmd, kind: 'structured', alive: true, commands: s.commands, mode: s.mode || undefined, name: termNames[id] || undefined, ...(s.archiveOldestSeq != null ? { oldestSeq: s.archiveOldestSeq } : {}), ...(s.spawnedBy ? { spawned: true, spawnedBy: s.spawnedBy } : {}) })),
|
|
597
|
+
...[...sessions.entries()].map(([id, s]) => ({ id, cmd: s.cmd, kind: 'structured', alive: true, commands: s.commands, mode: s.mode || undefined, name: termNames[id] || undefined, ...(s.archiveOldestSeq != null ? { oldestSeq: s.archiveOldestSeq } : {}), ...(s.spawnedBy ? { spawned: true, spawnedBy: s.spawnedBy } : {}), ...(s.flowSessionId ? { flowId: s.flowSessionId, flowRole: s.flowTaskKey ? 'lane' : 'conductor' } : {}) })),
|
|
598
598
|
],
|
|
599
599
|
})
|
|
600
600
|
|
package/flow-conductor.mjs
CHANGED
|
@@ -26,6 +26,8 @@ export { normalizePlanOutput }
|
|
|
26
26
|
export const FLOW_CONDUCTOR_PROMPT = [
|
|
27
27
|
'THINKPOOL FLOW CONDUCTOR — HARD RULES (read first, no exceptions): You are in PLAN MODE. Your ONLY output action is calling the ExitPlanMode tool EXACTLY ONCE with the task-graph JSON. You MUST NOT write or edit files, MUST NOT run bash/git, MUST NOT call AskUserQuestion, and MUST NOT build the project yourself — in plan mode those are blocked and will just stall you on a permission prompt. You do NOT build; you DECOMPOSE so the lanes build. A fully-specified build is STILL decomposed, never built here. If a detail is ambiguous, make a reasonable assumption and note it in the plan summary — do NOT ask. Think, then call ExitPlanMode. That is the whole job.',
|
|
28
28
|
|
|
29
|
+
'DO NOT SPAWN SUBAGENTS. You MUST NOT use the Task/Agent tool or launch Explore / sub-agents — in plan mode every subagent spawn pops a permission card and stalls the whole flow (this is the #1 way the conductor hangs asking for permission). You almost never need to look at code to decompose: decompose from the build request itself. If you genuinely must inspect something first, read it YOURSELF with Read/Grep/Glob (those are allowed in plan mode without a prompt) — never delegate it to a spawned agent. Decompose, then ExitPlanMode.',
|
|
30
|
+
|
|
29
31
|
'THINKPOOL FLOW — you are the CONDUCTOR of an ensemble build. Your job RIGHT NOW (Step 1) is to decompose the user\'s build request into a TASK-GRAPH: a set of RUNNABLE slices with explicit dependencies, then submit that plan for human approval. Do NOT start building and do NOT spawn lanes yet — that happens only after the user approves the plan (Step 2+).',
|
|
30
32
|
|
|
31
33
|
'DECOMPOSE INTO RUNNABLE SLICES. Each slice must be something ONE lane can build, RUN in its own browser-side WebContainer sandbox, observe, and self-correct INDEPENDENTLY. A slice that cannot run on its own is not a slice — split it or merge it until it is. The runtime (a lane running what it built) is the moat; slices that can\'t run break the whole model.',
|
package/package.json
CHANGED
package/service.mjs
CHANGED
|
@@ -115,12 +115,25 @@ export function buildArtifact(platform, { room = null, cmdArgs = [], autoUpdate
|
|
|
115
115
|
// retried on the EIO race → a final `print` so the command's exit code reports the
|
|
116
116
|
// real loaded state (installService warns if it ends not-loaded).
|
|
117
117
|
const lbl = label(room), dom = 'gui/$(id -u)'
|
|
118
|
+
const pr = `launchctl print ${dom}/${lbl} >/dev/null 2>&1`
|
|
118
119
|
const post = [
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
// Evict any existing instance so the REWRITTEN plist (new pinned version) is what
|
|
121
|
+
// loads. bootout is async + occasionally sticky: if the old supervised process
|
|
122
|
+
// won't leave the domain, the follow-up bootstrap throws "Bootstrap failed: 5:
|
|
123
|
+
// Input/output error" and we'd SILENTLY keep running the OLD pinned version while
|
|
124
|
+
// reporting success — the 2026-06-30 "Restart & update" stuck-on-0.7.96 bug. So:
|
|
125
|
+
// bootout, wait for it to actually leave, and if it WON'T, SIGKILL the wedged pid
|
|
126
|
+
// then bootout again (KeepAlive can't relaunch a job that's booting out).
|
|
127
|
+
`launchctl bootout ${dom}/${lbl} 2>/dev/null || true`,
|
|
128
|
+
`for i in $(seq 1 25); do ${pr} || break; sleep 0.2; done`,
|
|
129
|
+
`if ${pr}; then p=$(launchctl print ${dom}/${lbl} 2>/dev/null | sed -n 's/.*[^a-z]pid = \\([0-9][0-9]*\\).*/\\1/p' | head -1); [ -n "$p" ] && kill -9 "$p" 2>/dev/null || true; launchctl bootout ${dom}/${lbl} 2>/dev/null || true; for i in $(seq 1 25); do ${pr} || break; sleep 0.2; done; fi`,
|
|
130
|
+
// Clear a stale `disabled` override (from a prior bootout / account-storm cleanup),
|
|
131
|
+
// then load the rewritten plist from disk, retried on the EIO teardown race.
|
|
132
|
+
`launchctl enable ${dom}/${lbl} 2>/dev/null || true`,
|
|
133
|
+
`ok=0; for i in $(seq 1 25); do launchctl bootstrap ${dom} "${file}" 2>/dev/null && { ok=1; break; }; sleep 0.3; done`,
|
|
134
|
+
// Be HONEST about the outcome: if it never loaded, say so + give the exact manual
|
|
135
|
+
// recovery — never let a failed reload masquerade as a successful update.
|
|
136
|
+
`if [ "$ok" != 1 ] && ! ${pr}; then echo " ⚠ thinkpool-pair: launchd reload FAILED — run by hand: launchctl bootout ${dom}/${lbl} ; launchctl bootstrap ${dom} \\"${file}\\"" >&2; fi`,
|
|
124
137
|
].join('; ')
|
|
125
138
|
return { file, content, logDir, post: [post], note: 'Loaded as a LaunchAgent — starts at login, restarts on crash.' }
|
|
126
139
|
}
|