@bojackduy/opencode-loopd 1.0.0 → 1.0.1
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 +162 -66
- package/assets/demo.png +0 -0
- package/dist/server.js +15 -15
- package/dist/tui.js +193 -193
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -1,137 +1,233 @@
|
|
|
1
1
|
# opencode-loopd
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Codex-inspired background goal engine for OpenCode — autonomous subagents, engine-driven loop, and modal TUI dashboard. Like Claude Code's loop, for OpenCode.**
|
|
4
|
+
|
|
5
|
+
> Run long-running tasks as **autonomous child sessions** (subagents) while the main chat stays interactive. Create a goal with `/goal`, watch it loop in the background, and monitor everything from a keyboard-driven TUI — without blocking the parent conversation.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@bojackduy/opencode-loopd)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://opencode.ai)
|
|
10
|
+
[](https://github.com/anomalyco/opentui)
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
*Modal dashboard (`/loop` / `Ctrl+L`): zero chat pollution — keys are trapped inside the dialog, NORMAL vs INSERT modes, vivid per-status coloring.*
|
|
15
|
+
|
|
16
|
+
## Why opencode-loopd
|
|
17
|
+
|
|
18
|
+
- **Background agents, not blocked chats** — an OpenCode plugin that spawns a dedicated **worker (child) session** per goal. The parent stays free to keep chatting.
|
|
19
|
+
- **Codex-style engine-driven loop** — idle detection → continuation steering with accumulated context (progress history, transcript tail, inbox). No prompt spam in the parent.
|
|
20
|
+
- **Parent ↔ child visibility** — `list/inspect/read_transcript/send_input` give the parent full observability. Bidirectional inbox lets you steer mid-run.
|
|
21
|
+
- **Safe by default** — per-goal artifact isolation (`.opencode/loopd/goals/<id>/`), `maxTurns`/`maxFailures`/`maxNoProgress`, force-finish → semantic `complete_goal` summary → parent notification via wake-up injection.
|
|
22
|
+
- **Modal TUI dashboard** — `Ctrl+L` or `/loop` opens a focused dialog (no leak to chat prompt). Vim-style navigation, live running indicator, per-status borders.
|
|
23
|
+
|
|
24
|
+
Keywords: `opencode` `opencode-plugin` `background-agent` `autonomous` `subagent` `loop` `goal` `tui` `codex` `claude-code` `worker`
|
|
4
25
|
|
|
5
26
|
## What it is
|
|
6
27
|
|
|
7
|
-
opencode-loopd is an OpenCode plugin that
|
|
28
|
+
opencode-loopd is an **OpenCode plugin** (server + TUI) that adds **background goals** to OpenCode. Each goal owns a **worker (child) subagent** that loops autonomously; the **loop engine** drives continuations; the **dashboard** and **owner tools** keep the parent in control. Think *Codex goals* or *Claude Code loop*, but native to OpenCode's session model.
|
|
8
29
|
|
|
9
30
|
## Install
|
|
10
31
|
|
|
11
|
-
###
|
|
32
|
+
### Plugin — simple (no installer, just the plugin)
|
|
12
33
|
|
|
13
|
-
Add to
|
|
34
|
+
Add the package to **both** configs.
|
|
14
35
|
|
|
15
|
-
|
|
36
|
+
**`~/.config/opencode/opencode.jsonc`** — server engine:
|
|
37
|
+
|
|
38
|
+
```jsonc
|
|
16
39
|
{
|
|
17
|
-
"plugin": [
|
|
18
|
-
"/Users/you/Code/opencode-loopd"
|
|
19
|
-
]
|
|
40
|
+
"plugin": ["@bojackduy/opencode-loopd"]
|
|
20
41
|
}
|
|
21
42
|
```
|
|
22
43
|
|
|
23
|
-
|
|
44
|
+
**`~/.config/opencode/tui.json`** — dashboard (modal TUI):
|
|
45
|
+
|
|
46
|
+
```jsonc
|
|
47
|
+
{
|
|
48
|
+
"plugin": ["@bojackduy/opencode-loopd"]
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Then restart OpenCode. Verify with `/loop` (palette → Loop Dashboard) or `Ctrl+L`.
|
|
53
|
+
|
|
54
|
+
For a local checkout:
|
|
55
|
+
|
|
56
|
+
```jsonc
|
|
57
|
+
// opencode.jsonc
|
|
58
|
+
{ "plugin": ["./path/to/opencode-loopd"] }
|
|
59
|
+
// tui.json
|
|
60
|
+
{ "plugin": ["./path/to/opencode-loopd"] }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Installer — also installs `/goal` + skill
|
|
24
64
|
|
|
25
65
|
```bash
|
|
26
66
|
npx -y @bojackduy/opencode-loopd@latest
|
|
27
67
|
```
|
|
28
68
|
|
|
29
|
-
|
|
69
|
+
Registers the plugin, installs the `/goal` slash command and the `loopd` skill into `~/.config/opencode/`. Run again to update. Then **restart OpenCode**.
|
|
30
70
|
|
|
31
|
-
|
|
71
|
+
Uninstall:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npx -y @bojackduy/opencode-loopd@latest --uninstall
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Or via global npm:
|
|
32
78
|
|
|
33
79
|
```bash
|
|
34
80
|
npm install -g @bojackduy/opencode-loopd@latest
|
|
35
|
-
opencode-loopd
|
|
81
|
+
opencode-loopd # install
|
|
82
|
+
opencode-loopd --uninstall # remove
|
|
36
83
|
```
|
|
37
84
|
|
|
38
85
|
Then restart OpenCode.
|
|
39
86
|
|
|
87
|
+
### Manual (local dev)
|
|
88
|
+
|
|
89
|
+
Add to `~/.config/opencode/opencode.jsonc`:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"plugin": ["@bojackduy/opencode-loopd"]
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Or for local checkout:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"plugin": ["/Users/you/Code/opencode-loopd"]
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`opencode-loopd` exposes:
|
|
106
|
+
- `opencode-loopd/server` → engine plugin
|
|
107
|
+
- `opencode-loopd/tui` → dashboard plugin
|
|
108
|
+
|
|
40
109
|
## Usage
|
|
41
110
|
|
|
42
|
-
### Create a goal
|
|
111
|
+
### 1. Create a goal — `/goal`
|
|
43
112
|
|
|
44
113
|
From any session, tell the agent:
|
|
45
114
|
|
|
46
115
|
```
|
|
47
|
-
|
|
116
|
+
/goal fetch the latest AI news and save 10 items to ai-news.md
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Or be explicit:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Create a background goal to find all .ts files in src/, count lines, and write the summary to line-counts.md — verify with grep -c.
|
|
48
123
|
```
|
|
49
124
|
|
|
50
|
-
The agent will
|
|
125
|
+
The agent will clarify (what/where/how to verify) and then call `loopd_create_goal`. The worker starts immediately in a hidden child session.
|
|
51
126
|
|
|
52
|
-
### Monitor with dashboard
|
|
127
|
+
### 2. Monitor with dashboard — `/loop`
|
|
53
128
|
|
|
54
|
-
Press
|
|
129
|
+
Press **`Ctrl+L`** or open the command palette → **"Loop Dashboard"** (also `/loop`).
|
|
130
|
+
|
|
131
|
+
Dashboard (NORMAL / INSERT `:`):
|
|
55
132
|
|
|
56
|
-
Dashboard shortcuts:
|
|
57
133
|
- `j/k` — move selection
|
|
58
|
-
- `g/G` —
|
|
59
|
-
- `o` — open child session (full transcript)
|
|
134
|
+
- `g/G` — top / bottom
|
|
135
|
+
- `o` — open child session (full transcript, native OpenCode view)
|
|
60
136
|
- `p/r/R/x` — pause / resume / retry / clear selected goal
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
- `Ctrl+N` —
|
|
137
|
+
- `:` — insert mode → `:send <message>` to steer, `:force` / `:block` to finish manually
|
|
138
|
+
- `?` — toggle help — help stays open while you type
|
|
139
|
+
- `Ctrl+N` — back to NORMAL
|
|
64
140
|
- `q` — close
|
|
65
141
|
|
|
66
|
-
|
|
142
|
+
> The dashboard traps all keys — even when open via the palette, the chat input cursor won't blink underneath.
|
|
143
|
+
|
|
144
|
+
### 3. Inspect from the main agent (owner tools)
|
|
67
145
|
|
|
68
|
-
The
|
|
146
|
+
The parent never needs the dashboard — it can ask:
|
|
69
147
|
|
|
70
148
|
```
|
|
71
149
|
list_background_goals() — status snapshot
|
|
72
|
-
inspect_background_goal() — full detail
|
|
73
|
-
read_goal_transcript() —
|
|
74
|
-
send_goal_input(goalID, msg) —
|
|
75
|
-
pause_goal(goalID)
|
|
76
|
-
resume_goal(goalID) — resume
|
|
77
|
-
clear_goal(goalID) — stop and remove
|
|
150
|
+
inspect_background_goal() — full detail: objective, progress, blocker, runtime
|
|
151
|
+
read_goal_transcript() — last N worker messages (what it's doing)
|
|
152
|
+
send_goal_input(goalID, msg) — steer: "skip appendix PDFs"
|
|
153
|
+
pause_goal(goalID) / resume / clear
|
|
78
154
|
```
|
|
79
155
|
|
|
80
|
-
### Worker tools (child session)
|
|
156
|
+
### 4. Worker tools (child session)
|
|
81
157
|
|
|
82
|
-
The child
|
|
158
|
+
The child sees:
|
|
83
159
|
|
|
84
|
-
- `get_goal` — read objective,
|
|
85
|
-
- `report_goal_progress` —
|
|
86
|
-
- `complete_goal` —
|
|
87
|
-
- `block_goal` —
|
|
88
|
-
- `question` (OpenCode builtin) —
|
|
160
|
+
- `get_goal` — read objective, contract, progress, failures
|
|
161
|
+
- `report_goal_progress` — after durable writes
|
|
162
|
+
- `complete_goal` — only when checks pass, with evidence
|
|
163
|
+
- `block_goal` — real blocker needing user
|
|
164
|
+
- `question` (OpenCode builtin) — clarification → TUI blocker tab
|
|
165
|
+
|
|
166
|
+
Completion is semantic: the child writes the summary; the plugin forwards it to the parent via wake-up injection. If limits are hit, the engine first force-asks the child to `complete_goal`; only if ignored does it auto-block with a generic message.
|
|
89
167
|
|
|
90
168
|
## Architecture
|
|
91
169
|
|
|
92
170
|
```
|
|
93
171
|
Main session (parent)
|
|
94
|
-
↕
|
|
95
|
-
Loopd engine
|
|
96
|
-
↕
|
|
97
|
-
|
|
98
|
-
|
|
172
|
+
↕ owner tools: inspect, steer, pause — via inbox
|
|
173
|
+
Loopd engine (plugin server)
|
|
174
|
+
↕ continuation steering + accumulated context
|
|
175
|
+
↕ parent notification on complete/block (wake-up inject)
|
|
176
|
+
Child worker session (subagent)
|
|
177
|
+
↕ goal tools: progress, complete, block, question
|
|
178
|
+
• artifacts isolated: .opencode/loopd/goals/<goal-id>/
|
|
99
179
|
```
|
|
100
180
|
|
|
101
|
-
- **Engine-driven loop
|
|
102
|
-
- **
|
|
103
|
-
- **
|
|
104
|
-
- **Safety defaults**: maxTurns=50, maxFailures=3
|
|
181
|
+
- **Engine-driven loop** (like Codex): `session.idle` → lease + retry + polling → re-prompt child. Not a parent-driven re-prompt machine.
|
|
182
|
+
- **Accumulated context**: each continuation includes progress history, transcript tail, inbox messages, and artifact dir (unless objective names another dir).
|
|
183
|
+
- **Parent wake-up**: when the child calls `complete_goal`/`block_goal`, `tool.execute.after` injects the child's semantic summary into the owner's session — you see "Loop goal … completed: …" without polling.
|
|
105
184
|
|
|
106
|
-
##
|
|
185
|
+
## Artifacts
|
|
107
186
|
|
|
108
|
-
|
|
109
|
-
# Create a goal
|
|
110
|
-
goal: "Find all .ts files in src/, count lines, write summary to line-counts.md"
|
|
187
|
+
Every goal writes under its own directory (`.opencode/loopd/goals/<goal-id>/`); `progressFile` defaults there. The dashboard and transcript never pollute the project root. If your objective says `save to ./reports/`, that wins.
|
|
111
188
|
|
|
112
|
-
|
|
113
|
-
Turn 1: child counts files → reports progress
|
|
114
|
-
Turn 2: child sees "batch 1 done" → continues
|
|
115
|
-
Turn 3: child finishes → calls complete_goal
|
|
189
|
+
## Example — multi-turn with force-finish
|
|
116
190
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
191
|
+
```
|
|
192
|
+
# Parent: /goal
|
|
193
|
+
goal: "Generate 5 files file1..5.md under artifacts/, 2 lines each — verify with glob."
|
|
194
|
+
maxTurns: 1
|
|
195
|
+
|
|
196
|
+
# Turn 1: child writes file1..3, reports progress
|
|
197
|
+
# → engine hits maxTurns, injects FINAL REPORT REQUIRED
|
|
198
|
+
# Turn 2 (forced): child wraps up, calls complete_goal(summary="created 5 files…", evidence="glob confirmed…")
|
|
199
|
+
# → engine forwards to parent: "Loop goal … completed: created 5 files…"
|
|
200
|
+
# → Artifacts: .opencode/loopd/goals/<id>/file*.md
|
|
120
201
|
```
|
|
121
202
|
|
|
203
|
+
See `assets/demo.png` above for the dashboard at rest (0 active, 7 done) with vivid status colors, running spinner, and `INSERT` badge.
|
|
204
|
+
|
|
122
205
|
## Configuration
|
|
123
206
|
|
|
124
|
-
Goals accept
|
|
207
|
+
Goals accept:
|
|
125
208
|
|
|
126
209
|
| Option | Default | Description |
|
|
127
210
|
|---|---|---|
|
|
128
|
-
| `maxTurns` | 50 | Max continuation turns |
|
|
129
|
-
| `maxFailures` | 3 |
|
|
130
|
-
| `maxNoProgress` | 3 | Turns without progress before
|
|
131
|
-
| `timeoutMs` | 300000 | Per-turn
|
|
132
|
-
| `compactEvery` | — | Compact child
|
|
133
|
-
| `checks` | [] | Shell commands that must pass for
|
|
134
|
-
| `progressFile` |
|
|
211
|
+
| `maxTurns` | `50` | Max continuation turns before force-finish |
|
|
212
|
+
| `maxFailures` | `3` | Consecutive failures before block |
|
|
213
|
+
| `maxNoProgress` | `3` | Turns without progress before force-finish |
|
|
214
|
+
| `timeoutMs` | `300000` | Per-turn lease (5 min) |
|
|
215
|
+
| `compactEvery` | — | Compact child every N turns |
|
|
216
|
+
| `checks` | `[]` | Shell commands that must pass for `complete_goal` |
|
|
217
|
+
| `progressFile` | `<artifactDir>/progress.md` | Transaction state file |
|
|
218
|
+
| `artifactDir` | `goals/<id>/` | Auto — override only if objective names another dir |
|
|
219
|
+
|
|
220
|
+
Artifacts, logs, and state live under `.opencode/loopd/` (project-local). Locks live in `/tmp/loopd-locks/<project-hash>/` to avoid snapshot noise.
|
|
221
|
+
|
|
222
|
+
## Dashboard tips
|
|
223
|
+
|
|
224
|
+
- Press `:` then type bare text → sent as `send_goal_input` to the selected goal.
|
|
225
|
+
- Bare `:force my summary --evidence "glob ok"` bypasses verification when the child is stuck.
|
|
226
|
+
- `o` jumps to the native OpenCode child session — full transcript, diffs, tool calls.
|
|
227
|
+
|
|
228
|
+
## Related / SEO
|
|
229
|
+
|
|
230
|
+
OpenCode plugin for **background agents**, **autonomous subagents**, **loop**, **goal**, **TUI dashboard**, **Codex**-style continuation, **Claude Code** loop alternative, **opencode-tui**, **worker sessions**. Pairs well with `opencode-telescope` (search) and `lazyjira`/`lazyconfluence` (ATUI) from the same author.
|
|
135
231
|
|
|
136
232
|
## License
|
|
137
233
|
|
package/assets/demo.png
ADDED
|
Binary file
|
package/dist/server.js
CHANGED
|
@@ -18,22 +18,22 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
18
18
|
// src/infrastructure/state-repository.ts
|
|
19
19
|
var exports_state_repository = {};
|
|
20
20
|
__export(exports_state_repository, {
|
|
21
|
-
|
|
22
|
-
writeControlResponse: () => writeControlResponse,
|
|
23
|
-
writeControlRequest: () => writeControlRequest,
|
|
24
|
-
recoverStaleProcessing: () => recoverStaleProcessing,
|
|
25
|
-
readState: () => readState,
|
|
26
|
-
readEvents: () => readEvents,
|
|
27
|
-
readControlResponse: () => readControlResponse,
|
|
28
|
-
readControlRequest: () => readControlRequest,
|
|
29
|
-
mutateState: () => mutateState,
|
|
30
|
-
listPendingRequests: () => listPendingRequests,
|
|
31
|
-
goalArtifactDir: () => goalArtifactDir,
|
|
32
|
-
ensureGoalArtifactDir: () => ensureGoalArtifactDir,
|
|
33
|
-
drainGoalInbox: () => drainGoalInbox,
|
|
34
|
-
claimControlRequest: () => claimControlRequest,
|
|
21
|
+
appendEvent: () => appendEvent,
|
|
35
22
|
appendGoalInbox: () => appendGoalInbox,
|
|
36
|
-
|
|
23
|
+
claimControlRequest: () => claimControlRequest,
|
|
24
|
+
drainGoalInbox: () => drainGoalInbox,
|
|
25
|
+
ensureGoalArtifactDir: () => ensureGoalArtifactDir,
|
|
26
|
+
goalArtifactDir: () => goalArtifactDir,
|
|
27
|
+
listPendingRequests: () => listPendingRequests,
|
|
28
|
+
mutateState: () => mutateState,
|
|
29
|
+
readControlRequest: () => readControlRequest,
|
|
30
|
+
readControlResponse: () => readControlResponse,
|
|
31
|
+
readEvents: () => readEvents,
|
|
32
|
+
readState: () => readState,
|
|
33
|
+
recoverStaleProcessing: () => recoverStaleProcessing,
|
|
34
|
+
writeControlRequest: () => writeControlRequest,
|
|
35
|
+
writeControlResponse: () => writeControlResponse,
|
|
36
|
+
writeState: () => writeState
|
|
37
37
|
});
|
|
38
38
|
import { promises as fs } from "fs";
|
|
39
39
|
import path from "path";
|
package/dist/tui.js
CHANGED
|
@@ -833,7 +833,7 @@ function LoopDashboard(props) {
|
|
|
833
833
|
fg: "yellow",
|
|
834
834
|
bold: true
|
|
835
835
|
});
|
|
836
|
-
_$insert(_el$
|
|
836
|
+
_$insert(_el$27, _$createComponent(For, {
|
|
837
837
|
get each() {
|
|
838
838
|
return commandHelp().split(`
|
|
839
839
|
`);
|
|
@@ -841,16 +841,16 @@ function LoopDashboard(props) {
|
|
|
841
841
|
children: (line) => {
|
|
842
842
|
const isHeader = line.startsWith("Modes:") || line.startsWith("Nav:") || line.startsWith("Commands");
|
|
843
843
|
const isCmd = line.trim().startsWith(":");
|
|
844
|
-
return
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
_$insert(_el$
|
|
848
|
-
_$effect((_$p) => _$setProp(_el$
|
|
844
|
+
return [`
|
|
845
|
+
`, (() => {
|
|
846
|
+
var _el$41 = _$createElement("span");
|
|
847
|
+
_$insert(_el$41, line);
|
|
848
|
+
_$effect((_$p) => _$setProp(_el$41, "style", {
|
|
849
849
|
fg: isHeader ? theme().primary : isCmd ? theme().warning : theme().text,
|
|
850
850
|
bold: isHeader
|
|
851
851
|
}, _$p));
|
|
852
852
|
return _el$41;
|
|
853
|
-
})();
|
|
853
|
+
})()];
|
|
854
854
|
}
|
|
855
855
|
}), null);
|
|
856
856
|
_$effect((_$p) => _$setProp(_el$26, "backgroundColor", theme().background, _$p));
|
|
@@ -868,31 +868,31 @@ function LoopDashboard(props) {
|
|
|
868
868
|
},
|
|
869
869
|
get fallback() {
|
|
870
870
|
return (() => {
|
|
871
|
-
var _el$
|
|
871
|
+
var _el$42 = _$createElement("box"), _el$43 = _$createElement("text"), _el$44 = _$createElement("span"), _el$46 = _$createElement("span"), _el$48 = _$createElement("span"), _el$50 = _$createElement("text"), _el$51 = _$createElement("span"), _el$53 = _$createElement("span"), _el$55 = _$createElement("span"), _el$57 = _$createElement("span"), _el$59 = _$createElement("span"), _el$61 = _$createElement("span"), _el$63 = _$createElement("span");
|
|
872
|
+
_$insertNode(_el$42, _el$43);
|
|
873
|
+
_$insertNode(_el$42, _el$50);
|
|
874
|
+
_$setProp(_el$42, "flexDirection", "column");
|
|
875
|
+
_$setProp(_el$42, "gap", 1);
|
|
872
876
|
_$insertNode(_el$43, _el$44);
|
|
873
|
-
_$insertNode(_el$43, _el$
|
|
874
|
-
_$
|
|
875
|
-
_$
|
|
876
|
-
_$insertNode(_el$
|
|
877
|
-
_$insertNode(_el$
|
|
878
|
-
_$insertNode(_el$
|
|
879
|
-
_$insertNode(_el$
|
|
880
|
-
_$insertNode(_el$
|
|
881
|
-
_$insertNode(_el$
|
|
882
|
-
_$insertNode(_el$
|
|
883
|
-
_$insertNode(_el$
|
|
884
|
-
_$insertNode(_el$
|
|
885
|
-
_$insertNode(_el$51,
|
|
886
|
-
_$insertNode(_el$
|
|
887
|
-
_$insertNode(_el$
|
|
888
|
-
_$insertNode(_el$
|
|
889
|
-
_$insertNode(_el$
|
|
890
|
-
_$insertNode(_el$
|
|
891
|
-
_$insertNode(_el$
|
|
892
|
-
_$insertNode(_el$58, _$createTextNode(`o`));
|
|
893
|
-
_$insertNode(_el$60, _$createTextNode(` to open child \xB7 `));
|
|
894
|
-
_$insertNode(_el$62, _$createTextNode(`:force`));
|
|
895
|
-
_$insertNode(_el$64, _$createTextNode(` to complete manually.`));
|
|
877
|
+
_$insertNode(_el$43, _el$46);
|
|
878
|
+
_$insertNode(_el$43, _el$48);
|
|
879
|
+
_$insertNode(_el$44, _$createTextNode(`No active goals.`));
|
|
880
|
+
_$insertNode(_el$46, _$createTextNode(` /goal`));
|
|
881
|
+
_$insertNode(_el$48, _$createTextNode(` in parent chat to create one.`));
|
|
882
|
+
_$insertNode(_el$50, _el$51);
|
|
883
|
+
_$insertNode(_el$50, _el$53);
|
|
884
|
+
_$insertNode(_el$50, _el$55);
|
|
885
|
+
_$insertNode(_el$50, _el$57);
|
|
886
|
+
_$insertNode(_el$50, _el$59);
|
|
887
|
+
_$insertNode(_el$50, _el$61);
|
|
888
|
+
_$insertNode(_el$50, _el$63);
|
|
889
|
+
_$insertNode(_el$51, _$createTextNode(`Tip: `));
|
|
890
|
+
_$insertNode(_el$53, _$createTextNode(`:send`));
|
|
891
|
+
_$insertNode(_el$55, _$createTextNode(` to steer the worker \xB7 `));
|
|
892
|
+
_$insertNode(_el$57, _$createTextNode(`o`));
|
|
893
|
+
_$insertNode(_el$59, _$createTextNode(` to open child \xB7 `));
|
|
894
|
+
_$insertNode(_el$61, _$createTextNode(`:force`));
|
|
895
|
+
_$insertNode(_el$63, _$createTextNode(` to complete manually.`));
|
|
896
896
|
_$effect((_p$) => {
|
|
897
897
|
var _v$21 = {
|
|
898
898
|
fg: theme().textMuted
|
|
@@ -915,16 +915,16 @@ function LoopDashboard(props) {
|
|
|
915
915
|
}, _v$30 = {
|
|
916
916
|
fg: theme().textMuted
|
|
917
917
|
};
|
|
918
|
-
_v$21 !== _p$.e && (_p$.e = _$setProp(_el$
|
|
919
|
-
_v$22 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
920
|
-
_v$23 !== _p$.a && (_p$.a = _$setProp(_el$
|
|
921
|
-
_v$24 !== _p$.o && (_p$.o = _$setProp(_el$
|
|
922
|
-
_v$25 !== _p$.i && (_p$.i = _$setProp(_el$
|
|
923
|
-
_v$26 !== _p$.n && (_p$.n = _$setProp(_el$
|
|
924
|
-
_v$27 !== _p$.s && (_p$.s = _$setProp(_el$
|
|
925
|
-
_v$28 !== _p$.h && (_p$.h = _$setProp(_el$
|
|
926
|
-
_v$29 !== _p$.r && (_p$.r = _$setProp(_el$
|
|
927
|
-
_v$30 !== _p$.d && (_p$.d = _$setProp(_el$
|
|
918
|
+
_v$21 !== _p$.e && (_p$.e = _$setProp(_el$44, "style", _v$21, _p$.e));
|
|
919
|
+
_v$22 !== _p$.t && (_p$.t = _$setProp(_el$46, "style", _v$22, _p$.t));
|
|
920
|
+
_v$23 !== _p$.a && (_p$.a = _$setProp(_el$48, "style", _v$23, _p$.a));
|
|
921
|
+
_v$24 !== _p$.o && (_p$.o = _$setProp(_el$51, "style", _v$24, _p$.o));
|
|
922
|
+
_v$25 !== _p$.i && (_p$.i = _$setProp(_el$53, "style", _v$25, _p$.i));
|
|
923
|
+
_v$26 !== _p$.n && (_p$.n = _$setProp(_el$55, "style", _v$26, _p$.n));
|
|
924
|
+
_v$27 !== _p$.s && (_p$.s = _$setProp(_el$57, "style", _v$27, _p$.s));
|
|
925
|
+
_v$28 !== _p$.h && (_p$.h = _$setProp(_el$59, "style", _v$28, _p$.h));
|
|
926
|
+
_v$29 !== _p$.r && (_p$.r = _$setProp(_el$61, "style", _v$29, _p$.r));
|
|
927
|
+
_v$30 !== _p$.d && (_p$.d = _$setProp(_el$63, "style", _v$30, _p$.d));
|
|
928
928
|
return _p$;
|
|
929
929
|
}, {
|
|
930
930
|
e: undefined,
|
|
@@ -938,7 +938,7 @@ function LoopDashboard(props) {
|
|
|
938
938
|
r: undefined,
|
|
939
939
|
d: undefined
|
|
940
940
|
});
|
|
941
|
-
return _el$
|
|
941
|
+
return _el$42;
|
|
942
942
|
})();
|
|
943
943
|
},
|
|
944
944
|
get children() {
|
|
@@ -961,86 +961,86 @@ function LoopDashboard(props) {
|
|
|
961
961
|
return phaseColor(runtime().phase || "idle", theme());
|
|
962
962
|
};
|
|
963
963
|
return (() => {
|
|
964
|
-
var _el$
|
|
964
|
+
var _el$65 = _$createElement("box"), _el$66 = _$createElement("text"), _el$67 = _$createElement("span"), _el$68 = _$createElement("span"), _el$70 = _$createElement("span");
|
|
965
|
+
_$insertNode(_el$65, _el$66);
|
|
966
|
+
_$setProp(_el$65, "flexDirection", "row");
|
|
967
|
+
_$setProp(_el$65, "paddingLeft", 1);
|
|
968
|
+
_$setProp(_el$65, "paddingRight", 1);
|
|
965
969
|
_$insertNode(_el$66, _el$67);
|
|
966
|
-
_$
|
|
967
|
-
_$
|
|
968
|
-
_$
|
|
969
|
-
_$insertNode(_el$67, _el$68);
|
|
970
|
-
_$insertNode(_el$67, _el$69);
|
|
971
|
-
_$insertNode(_el$67, _el$71);
|
|
972
|
-
_$insert(_el$68, (() => {
|
|
970
|
+
_$insertNode(_el$66, _el$68);
|
|
971
|
+
_$insertNode(_el$66, _el$70);
|
|
972
|
+
_$insert(_el$67, (() => {
|
|
973
973
|
var _c$2 = _$memo(() => !!isActive());
|
|
974
974
|
return () => _c$2() ? `\u25B6 ${statusIcon(goal.status)} ${goal.name}` : ` ${statusIcon(goal.status)} ${goal.name}`;
|
|
975
975
|
})());
|
|
976
|
-
_$insertNode(_el$
|
|
977
|
-
_$insert(_el$
|
|
978
|
-
_$insert(_el$
|
|
976
|
+
_$insertNode(_el$68, _$createTextNode(` \u2502 `));
|
|
977
|
+
_$insert(_el$70, () => goal.status.toUpperCase());
|
|
978
|
+
_$insert(_el$66, (() => {
|
|
979
979
|
var _c$3 = _$memo(() => !!runtime());
|
|
980
980
|
return () => _c$3() && [(() => {
|
|
981
|
-
var _el$
|
|
982
|
-
_$insertNode(_el$
|
|
983
|
-
_$effect((_$p) => _$setProp(_el$
|
|
981
|
+
var _el$71 = _$createElement("span");
|
|
982
|
+
_$insertNode(_el$71, _$createTextNode(` \u2502 `));
|
|
983
|
+
_$effect((_$p) => _$setProp(_el$71, "style", {
|
|
984
984
|
fg: theme().textMuted
|
|
985
985
|
}, _$p));
|
|
986
|
-
return _el$
|
|
986
|
+
return _el$71;
|
|
987
987
|
})(), (() => {
|
|
988
|
-
var _el$
|
|
989
|
-
_$insertNode(_el$
|
|
990
|
-
_$insert(_el$
|
|
988
|
+
var _el$73 = _$createElement("span"), _el$74 = _$createTextNode(` `);
|
|
989
|
+
_$insertNode(_el$73, _el$74);
|
|
990
|
+
_$insert(_el$73, (() => {
|
|
991
991
|
var _c$6 = _$memo(() => runtime().phase === "running");
|
|
992
992
|
return () => _c$6() ? runningFrame() : phaseIcon(runtime().phase);
|
|
993
|
-
})(), _el$
|
|
994
|
-
_$insert(_el$
|
|
995
|
-
_$effect((_$p) => _$setProp(_el$
|
|
993
|
+
})(), _el$74);
|
|
994
|
+
_$insert(_el$73, () => runtime().phase.toUpperCase(), null);
|
|
995
|
+
_$effect((_$p) => _$setProp(_el$73, "style", {
|
|
996
996
|
fg: turnColor(),
|
|
997
997
|
bold: runtime().phase === "running"
|
|
998
998
|
}, _$p));
|
|
999
|
-
return _el$
|
|
999
|
+
return _el$73;
|
|
1000
1000
|
})(), (() => {
|
|
1001
|
-
var _el$
|
|
1002
|
-
_$insertNode(_el$
|
|
1003
|
-
_$insert(_el$
|
|
1004
|
-
_$insert(_el$
|
|
1005
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1001
|
+
var _el$75 = _$createElement("span"), _el$76 = _$createTextNode(` `);
|
|
1002
|
+
_$insertNode(_el$75, _el$76);
|
|
1003
|
+
_$insert(_el$75, () => runtime().turnCount, null);
|
|
1004
|
+
_$insert(_el$75, maxTurns ? `/${maxTurns}` : "", null);
|
|
1005
|
+
_$effect((_$p) => _$setProp(_el$75, "style", {
|
|
1006
1006
|
fg: turnColor()
|
|
1007
1007
|
}, _$p));
|
|
1008
|
-
return _el$
|
|
1008
|
+
return _el$75;
|
|
1009
1009
|
})(), (() => {
|
|
1010
|
-
var _el$
|
|
1011
|
-
_$insertNode(_el$
|
|
1012
|
-
_$insert(_el$
|
|
1013
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1010
|
+
var _el$77 = _$createElement("span"), _el$78 = _$createTextNode(` `);
|
|
1011
|
+
_$insertNode(_el$77, _el$78);
|
|
1012
|
+
_$insert(_el$77, () => ageLabel(runtime().lastProgressAt || runtime().lastRunAt, clock()), null);
|
|
1013
|
+
_$effect((_$p) => _$setProp(_el$77, "style", {
|
|
1014
1014
|
fg: theme().textMuted
|
|
1015
1015
|
}, _$p));
|
|
1016
|
-
return _el$
|
|
1016
|
+
return _el$77;
|
|
1017
1017
|
})()];
|
|
1018
1018
|
})(), null);
|
|
1019
|
-
_$insert(_el$
|
|
1019
|
+
_$insert(_el$66, (() => {
|
|
1020
1020
|
var _c$4 = _$memo(() => !!(runtime() && runtime().consecutiveFailures > 0));
|
|
1021
1021
|
return () => _c$4() && (() => {
|
|
1022
|
-
var _el$
|
|
1023
|
-
_$insertNode(_el$
|
|
1024
|
-
_$insertNode(_el$
|
|
1025
|
-
_$insert(_el$
|
|
1026
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1022
|
+
var _el$79 = _$createElement("span"), _el$80 = _$createTextNode(` \u2502 \u26A0 `), _el$81 = _$createTextNode(` fail`);
|
|
1023
|
+
_$insertNode(_el$79, _el$80);
|
|
1024
|
+
_$insertNode(_el$79, _el$81);
|
|
1025
|
+
_$insert(_el$79, () => runtime().consecutiveFailures, _el$81);
|
|
1026
|
+
_$effect((_$p) => _$setProp(_el$79, "style", {
|
|
1027
1027
|
fg: theme().error,
|
|
1028
1028
|
bold: true
|
|
1029
1029
|
}, _$p));
|
|
1030
|
-
return _el$
|
|
1030
|
+
return _el$79;
|
|
1031
1031
|
})();
|
|
1032
1032
|
})(), null);
|
|
1033
|
-
_$insert(_el$
|
|
1033
|
+
_$insert(_el$66, (() => {
|
|
1034
1034
|
var _c$5 = _$memo(() => !!(runtime() && (runtime().noProgressCount || 0) > 0));
|
|
1035
1035
|
return () => _c$5() && (() => {
|
|
1036
|
-
var _el$
|
|
1037
|
-
_$insertNode(_el$
|
|
1038
|
-
_$insertNode(_el$
|
|
1039
|
-
_$insert(_el$
|
|
1040
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1036
|
+
var _el$82 = _$createElement("span"), _el$83 = _$createTextNode(` \u2502 `), _el$84 = _$createTextNode(` no-progress`);
|
|
1037
|
+
_$insertNode(_el$82, _el$83);
|
|
1038
|
+
_$insertNode(_el$82, _el$84);
|
|
1039
|
+
_$insert(_el$82, () => runtime().noProgressCount, _el$84);
|
|
1040
|
+
_$effect((_$p) => _$setProp(_el$82, "style", {
|
|
1041
1041
|
fg: theme().warning
|
|
1042
1042
|
}, _$p));
|
|
1043
|
-
return _el$
|
|
1043
|
+
return _el$82;
|
|
1044
1044
|
})();
|
|
1045
1045
|
})(), null);
|
|
1046
1046
|
_$effect((_p$) => {
|
|
@@ -1053,10 +1053,10 @@ function LoopDashboard(props) {
|
|
|
1053
1053
|
fg: statusColor(goal.status, theme()),
|
|
1054
1054
|
bold: true
|
|
1055
1055
|
};
|
|
1056
|
-
_v$31 !== _p$.e && (_p$.e = _$setProp(_el$
|
|
1057
|
-
_v$32 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
1058
|
-
_v$33 !== _p$.a && (_p$.a = _$setProp(_el$
|
|
1059
|
-
_v$34 !== _p$.o && (_p$.o = _$setProp(_el$
|
|
1056
|
+
_v$31 !== _p$.e && (_p$.e = _$setProp(_el$65, "backgroundColor", _v$31, _p$.e));
|
|
1057
|
+
_v$32 !== _p$.t && (_p$.t = _$setProp(_el$67, "style", _v$32, _p$.t));
|
|
1058
|
+
_v$33 !== _p$.a && (_p$.a = _$setProp(_el$68, "style", _v$33, _p$.a));
|
|
1059
|
+
_v$34 !== _p$.o && (_p$.o = _$setProp(_el$70, "style", _v$34, _p$.o));
|
|
1060
1060
|
return _p$;
|
|
1061
1061
|
}, {
|
|
1062
1062
|
e: undefined,
|
|
@@ -1064,7 +1064,7 @@ function LoopDashboard(props) {
|
|
|
1064
1064
|
a: undefined,
|
|
1065
1065
|
o: undefined
|
|
1066
1066
|
});
|
|
1067
|
-
return _el$
|
|
1067
|
+
return _el$65;
|
|
1068
1068
|
})();
|
|
1069
1069
|
}
|
|
1070
1070
|
});
|
|
@@ -1077,144 +1077,144 @@ function LoopDashboard(props) {
|
|
|
1077
1077
|
children: (goal) => {
|
|
1078
1078
|
const rt = () => state()?.runtimes.find((r) => r.goalID === goal().id);
|
|
1079
1079
|
return (() => {
|
|
1080
|
-
var _el$
|
|
1081
|
-
`), _el$
|
|
1080
|
+
var _el$85 = _$createElement("box"), _el$86 = _$createElement("text"), _el$87 = _$createElement("span"), _el$88 = _$createTextNode(` `), _el$89 = _$createElement("span"), _el$90 = _$createTextNode(` `), _el$91 = _$createTextNode(`
|
|
1081
|
+
`), _el$92 = _$createElement("span");
|
|
1082
|
+
_$insertNode(_el$85, _el$86);
|
|
1083
|
+
_$setProp(_el$85, "flexDirection", "column");
|
|
1084
|
+
_$setProp(_el$85, "border", true);
|
|
1085
|
+
_$setProp(_el$85, "padding", 1);
|
|
1086
|
+
_$setProp(_el$85, "flexShrink", 0);
|
|
1087
|
+
_$setProp(_el$85, "maxHeight", 10);
|
|
1082
1088
|
_$insertNode(_el$86, _el$87);
|
|
1083
|
-
_$
|
|
1084
|
-
_$
|
|
1085
|
-
_$
|
|
1086
|
-
_$setProp(_el$86, "flexShrink", 0);
|
|
1087
|
-
_$setProp(_el$86, "maxHeight", 10);
|
|
1089
|
+
_$insertNode(_el$86, _el$89);
|
|
1090
|
+
_$insertNode(_el$86, _el$91);
|
|
1091
|
+
_$insertNode(_el$86, _el$92);
|
|
1088
1092
|
_$insertNode(_el$87, _el$88);
|
|
1089
|
-
_$
|
|
1090
|
-
_$
|
|
1091
|
-
_$insertNode(_el$
|
|
1092
|
-
_$
|
|
1093
|
-
_$insert(_el$
|
|
1094
|
-
_$insert(_el$88, () => goal().name, null);
|
|
1095
|
-
_$insertNode(_el$90, _el$91);
|
|
1096
|
-
_$insert(_el$90, () => goal().status.toUpperCase(), null);
|
|
1097
|
-
_$insert(_el$87, (() => {
|
|
1093
|
+
_$insert(_el$87, () => statusIcon(goal().status), _el$88);
|
|
1094
|
+
_$insert(_el$87, () => goal().name, null);
|
|
1095
|
+
_$insertNode(_el$89, _el$90);
|
|
1096
|
+
_$insert(_el$89, () => goal().status.toUpperCase(), null);
|
|
1097
|
+
_$insert(_el$86, (() => {
|
|
1098
1098
|
var _c$7 = _$memo(() => !!rt());
|
|
1099
1099
|
return () => _c$7() && [(() => {
|
|
1100
|
-
var _el$
|
|
1101
|
-
_$insertNode(_el$
|
|
1102
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1100
|
+
var _el$93 = _$createElement("span");
|
|
1101
|
+
_$insertNode(_el$93, _$createTextNode(` \u2502 `));
|
|
1102
|
+
_$effect((_$p) => _$setProp(_el$93, "style", {
|
|
1103
1103
|
fg: theme().textMuted
|
|
1104
1104
|
}, _$p));
|
|
1105
|
-
return _el$
|
|
1105
|
+
return _el$93;
|
|
1106
1106
|
})(), (() => {
|
|
1107
|
-
var _el$
|
|
1108
|
-
_$insertNode(_el$
|
|
1109
|
-
_$insert(_el$
|
|
1110
|
-
_$insert(_el$
|
|
1111
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1107
|
+
var _el$95 = _$createElement("span"), _el$96 = _$createTextNode(` `);
|
|
1108
|
+
_$insertNode(_el$95, _el$96);
|
|
1109
|
+
_$insert(_el$95, () => phaseIcon(rt().phase), _el$96);
|
|
1110
|
+
_$insert(_el$95, () => rt().phase, null);
|
|
1111
|
+
_$effect((_$p) => _$setProp(_el$95, "style", {
|
|
1112
1112
|
fg: phaseColor(rt().phase, theme()),
|
|
1113
1113
|
bold: true
|
|
1114
1114
|
}, _$p));
|
|
1115
|
-
return _el$
|
|
1115
|
+
return _el$95;
|
|
1116
1116
|
})(), (() => {
|
|
1117
|
-
var _el$
|
|
1118
|
-
_$insertNode(_el$
|
|
1119
|
-
_$insert(_el$
|
|
1120
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1117
|
+
var _el$97 = _$createElement("span"), _el$98 = _$createTextNode(` turn `);
|
|
1118
|
+
_$insertNode(_el$97, _el$98);
|
|
1119
|
+
_$insert(_el$97, () => rt().turnCount, null);
|
|
1120
|
+
_$effect((_$p) => _$setProp(_el$97, "style", {
|
|
1121
1121
|
fg: theme().textMuted
|
|
1122
1122
|
}, _$p));
|
|
1123
|
-
return _el$
|
|
1123
|
+
return _el$97;
|
|
1124
1124
|
})()];
|
|
1125
|
-
})(), _el$
|
|
1126
|
-
_$insert(_el$
|
|
1127
|
-
_$insert(_el$
|
|
1125
|
+
})(), _el$91);
|
|
1126
|
+
_$insert(_el$92, () => goal().objective.slice(0, 160));
|
|
1127
|
+
_$insert(_el$86, (() => {
|
|
1128
1128
|
var _c$8 = _$memo(() => !!goal().lastProgress);
|
|
1129
1129
|
return () => _c$8() && [(() => {
|
|
1130
|
-
var _el$
|
|
1130
|
+
var _el$99 = _$createElement("span"), _el$100 = _$createTextNode(`
|
|
1131
1131
|
\u2714 `);
|
|
1132
|
-
_$insertNode(_el$
|
|
1133
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1132
|
+
_$insertNode(_el$99, _el$100);
|
|
1133
|
+
_$effect((_$p) => _$setProp(_el$99, "style", {
|
|
1134
1134
|
fg: theme().success
|
|
1135
1135
|
}, _$p));
|
|
1136
|
-
return _el$
|
|
1136
|
+
return _el$99;
|
|
1137
1137
|
})(), (() => {
|
|
1138
|
-
var _el$
|
|
1139
|
-
_$insert(_el$
|
|
1140
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1138
|
+
var _el$102 = _$createElement("span");
|
|
1139
|
+
_$insert(_el$102, () => goal().lastProgress.summary.slice(0, 100));
|
|
1140
|
+
_$effect((_$p) => _$setProp(_el$102, "style", {
|
|
1141
1141
|
fg: theme().text
|
|
1142
1142
|
}, _$p));
|
|
1143
|
-
return _el$
|
|
1143
|
+
return _el$102;
|
|
1144
1144
|
})(), (() => {
|
|
1145
|
-
var _el$
|
|
1146
|
-
_$insertNode(_el$
|
|
1147
|
-
_$insert(_el$
|
|
1148
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1145
|
+
var _el$103 = _$createElement("span"), _el$104 = _$createTextNode(` \u2192 `);
|
|
1146
|
+
_$insertNode(_el$103, _el$104);
|
|
1147
|
+
_$insert(_el$103, () => goal().lastProgress.next?.slice(0, 60) || "", null);
|
|
1148
|
+
_$effect((_$p) => _$setProp(_el$103, "style", {
|
|
1149
1149
|
fg: theme().textMuted
|
|
1150
1150
|
}, _$p));
|
|
1151
|
-
return _el$
|
|
1151
|
+
return _el$103;
|
|
1152
1152
|
})()];
|
|
1153
1153
|
})(), null);
|
|
1154
|
-
_$insert(_el$
|
|
1154
|
+
_$insert(_el$86, (() => {
|
|
1155
1155
|
var _c$9 = _$memo(() => !!goal().blocker);
|
|
1156
1156
|
return () => _c$9() && [(() => {
|
|
1157
|
-
var _el$
|
|
1157
|
+
var _el$105 = _$createElement("span"), _el$106 = _$createTextNode(`
|
|
1158
1158
|
\u2716 blocked: `);
|
|
1159
|
-
_$insertNode(_el$
|
|
1160
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1159
|
+
_$insertNode(_el$105, _el$106);
|
|
1160
|
+
_$effect((_$p) => _$setProp(_el$105, "style", {
|
|
1161
1161
|
fg: theme().error,
|
|
1162
1162
|
bold: true
|
|
1163
1163
|
}, _$p));
|
|
1164
|
-
return _el$
|
|
1164
|
+
return _el$105;
|
|
1165
1165
|
})(), (() => {
|
|
1166
|
-
var _el$
|
|
1167
|
-
_$insert(_el$
|
|
1168
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1166
|
+
var _el$108 = _$createElement("span");
|
|
1167
|
+
_$insert(_el$108, () => goal().blocker.reason.slice(0, 140));
|
|
1168
|
+
_$effect((_$p) => _$setProp(_el$108, "style", {
|
|
1169
1169
|
fg: theme().error
|
|
1170
1170
|
}, _$p));
|
|
1171
|
-
return _el$
|
|
1171
|
+
return _el$108;
|
|
1172
1172
|
})(), (() => {
|
|
1173
|
-
var _el$
|
|
1174
|
-
_$insertNode(_el$
|
|
1175
|
-
_$insert(_el$
|
|
1176
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1173
|
+
var _el$109 = _$createElement("span"), _el$110 = _$createTextNode(` \u2014 `);
|
|
1174
|
+
_$insertNode(_el$109, _el$110);
|
|
1175
|
+
_$insert(_el$109, () => goal().blocker.needed.slice(0, 60), null);
|
|
1176
|
+
_$effect((_$p) => _$setProp(_el$109, "style", {
|
|
1177
1177
|
fg: theme().textMuted
|
|
1178
1178
|
}, _$p));
|
|
1179
|
-
return _el$
|
|
1179
|
+
return _el$109;
|
|
1180
1180
|
})()];
|
|
1181
1181
|
})(), null);
|
|
1182
|
-
_$insert(_el$
|
|
1182
|
+
_$insert(_el$86, (() => {
|
|
1183
1183
|
var _c$0 = _$memo(() => !!goal().config.artifactDir);
|
|
1184
1184
|
return () => _c$0() && [(() => {
|
|
1185
|
-
var _el$
|
|
1185
|
+
var _el$111 = _$createElement("span"), _el$112 = _$createTextNode(`
|
|
1186
1186
|
\uD83D\uDCC1 `);
|
|
1187
|
-
_$insertNode(_el$
|
|
1188
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1187
|
+
_$insertNode(_el$111, _el$112);
|
|
1188
|
+
_$effect((_$p) => _$setProp(_el$111, "style", {
|
|
1189
1189
|
fg: theme().accent
|
|
1190
1190
|
}, _$p));
|
|
1191
|
-
return _el$
|
|
1191
|
+
return _el$111;
|
|
1192
1192
|
})(), (() => {
|
|
1193
|
-
var _el$
|
|
1194
|
-
_$insert(_el$
|
|
1195
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1193
|
+
var _el$114 = _$createElement("span");
|
|
1194
|
+
_$insert(_el$114, () => String(goal().config.artifactDir).replace(String(props.directory), "."));
|
|
1195
|
+
_$effect((_$p) => _$setProp(_el$114, "style", {
|
|
1196
1196
|
fg: theme().textMuted
|
|
1197
1197
|
}, _$p));
|
|
1198
|
-
return _el$
|
|
1198
|
+
return _el$114;
|
|
1199
1199
|
})()];
|
|
1200
1200
|
})(), null);
|
|
1201
|
-
_$insert(_el$
|
|
1201
|
+
_$insert(_el$86, (() => {
|
|
1202
1202
|
var _c$1 = _$memo(() => !!rt()?.lastError);
|
|
1203
1203
|
return () => _c$1() && [(() => {
|
|
1204
|
-
var _el$
|
|
1204
|
+
var _el$115 = _$createElement("span"), _el$116 = _$createTextNode(`
|
|
1205
1205
|
\u26A0 `);
|
|
1206
|
-
_$insertNode(_el$
|
|
1207
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1206
|
+
_$insertNode(_el$115, _el$116);
|
|
1207
|
+
_$effect((_$p) => _$setProp(_el$115, "style", {
|
|
1208
1208
|
fg: theme().error
|
|
1209
1209
|
}, _$p));
|
|
1210
|
-
return _el$
|
|
1210
|
+
return _el$115;
|
|
1211
1211
|
})(), (() => {
|
|
1212
|
-
var _el$
|
|
1213
|
-
_$insert(_el$
|
|
1214
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1212
|
+
var _el$118 = _$createElement("span");
|
|
1213
|
+
_$insert(_el$118, () => rt().lastError.slice(0, 120));
|
|
1214
|
+
_$effect((_$p) => _$setProp(_el$118, "style", {
|
|
1215
1215
|
fg: theme().error
|
|
1216
1216
|
}, _$p));
|
|
1217
|
-
return _el$
|
|
1217
|
+
return _el$118;
|
|
1218
1218
|
})()];
|
|
1219
1219
|
})(), null);
|
|
1220
1220
|
_$effect((_p$) => {
|
|
@@ -1226,10 +1226,10 @@ function LoopDashboard(props) {
|
|
|
1226
1226
|
}, _v$38 = {
|
|
1227
1227
|
fg: theme().text
|
|
1228
1228
|
};
|
|
1229
|
-
_v$35 !== _p$.e && (_p$.e = _$setProp(_el$
|
|
1230
|
-
_v$36 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
1231
|
-
_v$37 !== _p$.a && (_p$.a = _$setProp(_el$
|
|
1232
|
-
_v$38 !== _p$.o && (_p$.o = _$setProp(_el$
|
|
1229
|
+
_v$35 !== _p$.e && (_p$.e = _$setProp(_el$85, "borderColor", _v$35, _p$.e));
|
|
1230
|
+
_v$36 !== _p$.t && (_p$.t = _$setProp(_el$87, "style", _v$36, _p$.t));
|
|
1231
|
+
_v$37 !== _p$.a && (_p$.a = _$setProp(_el$89, "style", _v$37, _p$.a));
|
|
1232
|
+
_v$38 !== _p$.o && (_p$.o = _$setProp(_el$92, "style", _v$38, _p$.o));
|
|
1233
1233
|
return _p$;
|
|
1234
1234
|
}, {
|
|
1235
1235
|
e: undefined,
|
|
@@ -1237,7 +1237,7 @@ function LoopDashboard(props) {
|
|
|
1237
1237
|
a: undefined,
|
|
1238
1238
|
o: undefined
|
|
1239
1239
|
});
|
|
1240
|
-
return _el$
|
|
1240
|
+
return _el$85;
|
|
1241
1241
|
})();
|
|
1242
1242
|
}
|
|
1243
1243
|
}), null);
|
|
@@ -1263,22 +1263,22 @@ function LoopDashboard(props) {
|
|
|
1263
1263
|
return events().slice(-10);
|
|
1264
1264
|
},
|
|
1265
1265
|
children: (ev) => (() => {
|
|
1266
|
-
var _el$
|
|
1267
|
-
_$insertNode(_el$
|
|
1268
|
-
_$insertNode(_el$
|
|
1269
|
-
_$insert(_el$
|
|
1270
|
-
_$insertNode(_el$
|
|
1271
|
-
_$insert(_el$
|
|
1272
|
-
_$insert(_el$
|
|
1266
|
+
var _el$119 = _$createElement("text"), _el$120 = _$createElement("span"), _el$121 = _$createElement("span"), _el$122 = _$createTextNode(` `);
|
|
1267
|
+
_$insertNode(_el$119, _el$120);
|
|
1268
|
+
_$insertNode(_el$119, _el$121);
|
|
1269
|
+
_$insert(_el$120, () => String(ev.type));
|
|
1270
|
+
_$insertNode(_el$121, _el$122);
|
|
1271
|
+
_$insert(_el$121, () => ev.goalID?.slice(0, 8), null);
|
|
1272
|
+
_$insert(_el$119, (() => {
|
|
1273
1273
|
var _c$10 = _$memo(() => !!ev.summary);
|
|
1274
1274
|
return () => _c$10() && (() => {
|
|
1275
|
-
var _el$
|
|
1276
|
-
_$insertNode(_el$
|
|
1277
|
-
_$insert(_el$
|
|
1278
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1275
|
+
var _el$123 = _$createElement("span"), _el$124 = _$createTextNode(` \u2014 `);
|
|
1276
|
+
_$insertNode(_el$123, _el$124);
|
|
1277
|
+
_$insert(_el$123, () => String(ev.summary).slice(0, 60), null);
|
|
1278
|
+
_$effect((_$p) => _$setProp(_el$123, "style", {
|
|
1279
1279
|
fg: theme().text
|
|
1280
1280
|
}, _$p));
|
|
1281
|
-
return _el$
|
|
1281
|
+
return _el$123;
|
|
1282
1282
|
})();
|
|
1283
1283
|
})(), null);
|
|
1284
1284
|
_$effect((_p$) => {
|
|
@@ -1288,14 +1288,14 @@ function LoopDashboard(props) {
|
|
|
1288
1288
|
}, _v$40 = {
|
|
1289
1289
|
fg: theme().textMuted
|
|
1290
1290
|
};
|
|
1291
|
-
_v$39 !== _p$.e && (_p$.e = _$setProp(_el$
|
|
1292
|
-
_v$40 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
1291
|
+
_v$39 !== _p$.e && (_p$.e = _$setProp(_el$120, "style", _v$39, _p$.e));
|
|
1292
|
+
_v$40 !== _p$.t && (_p$.t = _$setProp(_el$121, "style", _v$40, _p$.t));
|
|
1293
1293
|
return _p$;
|
|
1294
1294
|
}, {
|
|
1295
1295
|
e: undefined,
|
|
1296
1296
|
t: undefined
|
|
1297
1297
|
});
|
|
1298
|
-
return _el$
|
|
1298
|
+
return _el$119;
|
|
1299
1299
|
})()
|
|
1300
1300
|
}), null);
|
|
1301
1301
|
_$effect((_p$) => {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@bojackduy/opencode-loopd",
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
"description": "Codex-inspired background goal engine for OpenCode — autonomous
|
|
4
|
+
"version": "1.0.1",
|
|
5
|
+
"description": "Codex-inspired background goal engine for OpenCode — autonomous subagents, engine-driven loop, child worker sessions and modal TUI dashboard. Like Claude Code loop for OpenCode.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "AGPL-3.0-only",
|
|
8
8
|
"private": false,
|
|
@@ -21,9 +21,13 @@
|
|
|
21
21
|
"loop",
|
|
22
22
|
"goal",
|
|
23
23
|
"background",
|
|
24
|
+
"background-agent",
|
|
24
25
|
"automation",
|
|
25
|
-
"
|
|
26
|
+
"autonomous",
|
|
27
|
+
"agent",
|
|
26
28
|
"subagent",
|
|
29
|
+
"codex",
|
|
30
|
+
"claude-code",
|
|
27
31
|
"opencode-loopd"
|
|
28
32
|
],
|
|
29
33
|
"bin": {
|
|
@@ -34,6 +38,7 @@
|
|
|
34
38
|
"scripts",
|
|
35
39
|
"skills",
|
|
36
40
|
"commands",
|
|
41
|
+
"assets",
|
|
37
42
|
"README.md",
|
|
38
43
|
"LICENSE",
|
|
39
44
|
"CHANGELOG.md"
|
|
@@ -45,6 +50,9 @@
|
|
|
45
50
|
"bun": ">=1.1.0"
|
|
46
51
|
},
|
|
47
52
|
"exports": {
|
|
53
|
+
".": {
|
|
54
|
+
"import": "./dist/server.js"
|
|
55
|
+
},
|
|
48
56
|
"./server": {
|
|
49
57
|
"import": "./dist/server.js"
|
|
50
58
|
},
|