@sma1lboy/rove 0.8.89
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 +60 -0
- package/dist/cli/index.js +959 -0
- package/dist/cli/kobe.js +959 -0
- package/dist/cli/pty-host-node.mjs +1015 -0
- package/dist/cli/rove.js +959 -0
- package/dist/pulse-n3cq1btw.wav +0 -0
- package/dist/skills/kobe/SKILL.md +317 -0
- package/dist/web-ui/assets/AppShell-BTjvuY-t.js +5 -0
- package/dist/web-ui/assets/AppShell-HiyATJse.css +1 -0
- package/dist/web-ui/assets/Board-DPB4h6mJ.js +1 -0
- package/dist/web-ui/assets/BoardPeek-69VJptGV.js +2 -0
- package/dist/web-ui/assets/ChatTerminal-BrP-ENHg.css +1 -0
- package/dist/web-ui/assets/ChatTerminal-MCI1aBbT.js +144 -0
- package/dist/web-ui/assets/ChatTranscript-DLthbnmB.js +1 -0
- package/dist/web-ui/assets/ConfirmDialog-CDPOtXww.js +1 -0
- package/dist/web-ui/assets/IssueIntakePanel-XYsIcIhp.js +1 -0
- package/dist/web-ui/assets/IssuePeek-CP_rAkqO.js +1 -0
- package/dist/web-ui/assets/IssuesPage-BR5mpuo-.js +1 -0
- package/dist/web-ui/assets/RichEditor-B4sEOPyN.css +1 -0
- package/dist/web-ui/assets/RichEditor-DJFl5TvH.js +173 -0
- package/dist/web-ui/assets/SettingsPage-CLRhr-sg.js +2 -0
- package/dist/web-ui/assets/SlideOver-Dxtk6Gn2.js +1 -0
- package/dist/web-ui/assets/ViewToggle-BdPCMBWa.js +1 -0
- package/dist/web-ui/assets/WorkspaceTabs-CMKlvN_Y.js +3 -0
- package/dist/web-ui/assets/WorkspaceTabs-DLzL-Tad.css +1 -0
- package/dist/web-ui/assets/active-task-GeQZqbJK.js +1 -0
- package/dist/web-ui/assets/activity-BjTd1D8q.js +1 -0
- package/dist/web-ui/assets/arrow-left-DNM2CHhS.js +1 -0
- package/dist/web-ui/assets/board-CGiK0u0M.js +1 -0
- package/dist/web-ui/assets/chips-Da37C4KZ.js +1 -0
- package/dist/web-ui/assets/columns-3-CQGAnX-4.js +1 -0
- package/dist/web-ui/assets/createLucideIcon-CM5xLVj1.js +1 -0
- package/dist/web-ui/assets/desktop-BThq9eSR.js +2 -0
- package/dist/web-ui/assets/engines-Cnxy1hW9.js +1 -0
- package/dist/web-ui/assets/external-link-BwT2u1hD.js +1 -0
- package/dist/web-ui/assets/external-store-DJlWpyYC.js +1 -0
- package/dist/web-ui/assets/harness-q9gT7Jic.js +1 -0
- package/dist/web-ui/assets/index-CgL6oDIY.js +10 -0
- package/dist/web-ui/assets/index-MuA3NLRu.css +1 -0
- package/dist/web-ui/assets/issues-1SCRkcB0.js +4 -0
- package/dist/web-ui/assets/issues-BKkua1D9.js +1 -0
- package/dist/web-ui/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/web-ui/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/web-ui/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/dist/web-ui/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/dist/web-ui/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff +0 -0
- package/dist/web-ui/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
- package/dist/web-ui/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
- package/dist/web-ui/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
- package/dist/web-ui/assets/lazy-issue-panels-0Rhl2uhh.js +6 -0
- package/dist/web-ui/assets/plus-BbX5qXba.js +1 -0
- package/dist/web-ui/assets/react-dom-DCnDkJvp.js +1 -0
- package/dist/web-ui/assets/rotate-cw-D-UUtiD0.js +1 -0
- package/dist/web-ui/assets/routes-SBb-uSy8.js +1 -0
- package/dist/web-ui/assets/search-BxbFZoup.js +1 -0
- package/dist/web-ui/assets/settings-tPcmEHCP.js +1 -0
- package/dist/web-ui/assets/store-uT65Mask.js +2 -0
- package/dist/web-ui/assets/tabs-Dx-TnbvG.js +1 -0
- package/dist/web-ui/assets/task._taskId-BlZ0vG_1.js +2 -0
- package/dist/web-ui/assets/task._taskId-BmObFoVZ.js +1 -0
- package/dist/web-ui/assets/terminal-qBEkzc-m.js +1 -0
- package/dist/web-ui/assets/text-match-DW3sD-Rt.js +1 -0
- package/dist/web-ui/assets/time-kviT26Tm.js +1 -0
- package/dist/web-ui/assets/toast-BXjAT0ix.js +1 -0
- package/dist/web-ui/assets/triage-7QLsCY8d.js +1 -0
- package/dist/web-ui/assets/use-focus-trap-DNMrlNR0.js +1 -0
- package/dist/web-ui/assets/vendor-CdtpTJrf.js +1 -0
- package/dist/web-ui/assets/web-transport-D0bugxxv.js +1 -0
- package/dist/web-ui/assets/with-selector-B5R3h-Ow.js +1 -0
- package/dist/web-ui/assets/worktrees-C_XKA7jM.js +1 -0
- package/dist/web-ui/assets/x-7cB9X7Hi.js +1 -0
- package/dist/web-ui/favicon.ico +0 -0
- package/dist/web-ui/index.html +35 -0
- package/dist/web-ui/logo192.png +0 -0
- package/dist/web-ui/logo512.png +0 -0
- package/dist/web-ui/manifest.json +25 -0
- package/dist/web-ui/origin-policy.mjs +41 -0
- package/dist/web-ui/pty-scrollback.mjs +51 -0
- package/dist/web-ui/pty-server.mjs +212 -0
- package/dist/web-ui/pty-session-lifecycle.mjs +282 -0
- package/dist/web-ui/robots.txt +3 -0
- package/package.json +94 -0
|
Binary file
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kobe
|
|
3
|
+
description: Use when controlling Rove tasks, parallel coding attempts, hosted agent sessions, task lifecycle, or the daemon-owned issue tracker from a shell. Also the ONLY channel for messaging another agent session on this machine — `rove api send`, never a peer/MCP side channel.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- kobe-skill-version: 21 — bump in lockstep with KOBE_SKILL_VERSION (src/lib/skill-install.ts). -->
|
|
7
|
+
|
|
8
|
+
# Rove shell control
|
|
9
|
+
|
|
10
|
+
Use `rove api` to manage local coding tasks. Each Task owns a git Worktree,
|
|
11
|
+
branch, and Hosted PTY engine sessions. API automation works without an open
|
|
12
|
+
TUI; prompted `send`, `add`, and `fan-out` ensure the canonical engine session.
|
|
13
|
+
|
|
14
|
+
## Inside a Rove session, Rove verbs come first
|
|
15
|
+
|
|
16
|
+
Check where you are before choosing how to delegate or parallelize:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
test -n "${KOBE_TASK_ID:-}"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
When that passes, you are an engine session Rove manages — `$KOBE_TASK_ID`
|
|
23
|
+
is your task, `$KOBE_TAB_ID` your tab. Coordination should then go through
|
|
24
|
+
Rove, not around it, because work routed through `rove api` gets what
|
|
25
|
+
ad-hoc subprocesses never do: its own Worktree and branch (no file
|
|
26
|
+
collisions with you), a sidebar row with live state the user can watch,
|
|
27
|
+
lifecycle tracking, and an explicit outcome contract.
|
|
28
|
+
|
|
29
|
+
- Parallel attempts of one prompt → `fan-out`, not N hand-rolled subagents.
|
|
30
|
+
- Delegating a scoped piece of work → `add --prompt`, not a raw `claude -p`
|
|
31
|
+
child the user cannot see or manage.
|
|
32
|
+
- Following up on a task you started → `send`; comparing → `collect`;
|
|
33
|
+
finished your own task and were spawned by another → a bare `send`
|
|
34
|
+
(no `--task-id`) replies to the DISPATCHER — the exact task + tab that
|
|
35
|
+
created you, recorded at creation (`.task.dispatcher` on `get-task`).
|
|
36
|
+
If that tab died it falls back to the dispatcher task's live canonical
|
|
37
|
+
engine tab; nothing alive fails loud (`DISPATCHER_UNREACHABLE`) — it
|
|
38
|
+
never spawns a new engine, so a failed reply is visible, not fake-ok.
|
|
39
|
+
- Messaging another agent session on this machine → `send`, and ONLY `send`
|
|
40
|
+
— never relay through the user, a side file, or a generic peer channel
|
|
41
|
+
(an MCP server offering to message "other instances" is exactly that
|
|
42
|
+
channel: it reaches a process, not a task, so nothing it delivers is
|
|
43
|
+
attributable, watchable, or replyable). Sent from
|
|
44
|
+
inside a Rove task, the prompt arrives prefixed `[KOBE PEER] from
|
|
45
|
+
"<title>" (task <id> — load the Rove agent skill FIRST …)`, so the
|
|
46
|
+
receiver knows who is talking, that this skill is required reading, and
|
|
47
|
+
how to answer — the baked-in reply command is tab-precise
|
|
48
|
+
(`--task-id <sender> --tab <sender's tab>`), so peer conversations need
|
|
49
|
+
no coordinator and no human relay. That prefix is the contract: do not
|
|
50
|
+
strip it with `--plain` for
|
|
51
|
+
coordination messages (`--plain` is only for a verbatim paste the
|
|
52
|
+
receiver should treat as content, not conversation). Received a
|
|
53
|
+
`[KOBE PEER]` message yourself? Load this skill first — required, not
|
|
54
|
+
optional — then reply with the baked-in command, not by asking the user.
|
|
55
|
+
- `dispatch` stays the dispatcher's verb (deliver-only into an
|
|
56
|
+
already-hosted session; never impersonate the user in someone else's
|
|
57
|
+
terminal).
|
|
58
|
+
|
|
59
|
+
Your own engine's in-context subagents remain fine for read-only
|
|
60
|
+
research/exploration inside your task — the boundary is WORK: anything that
|
|
61
|
+
edits files, runs long, or the user should be able to see and steer belongs
|
|
62
|
+
in a Rove task. Do not recursively fan out from a spawned task.
|
|
63
|
+
|
|
64
|
+
When the check fails, none of this applies — use `rove api` only if the
|
|
65
|
+
user asks for Rove by name.
|
|
66
|
+
|
|
67
|
+
## Vocabulary — what the user's words map to
|
|
68
|
+
|
|
69
|
+
| Term | What it is | Isolation it gives | Users also say |
|
|
70
|
+
|---|---|---|---|
|
|
71
|
+
| **Task** | one Worktree + branch + the Terminal Tabs inside it — one sidebar row | its own files AND its own branch | "a task", "a new one", "a separate attempt" |
|
|
72
|
+
| **Worktree** | that task's file tree on disk (`.task.worktreePath`) | — | "workspace", "this checkout", "this branch", "here" |
|
|
73
|
+
| **Terminal Tab** | one engine session inside a task | its own conversation, SAME files | "tab", "chattab", "another chat", "a second agent on this" |
|
|
74
|
+
| **Split** | the tree that divides ONE Terminal Tab into several regions (the `pane-open` verb's unit; a leaf is not called a pane) | none — same session's screen, same files | "split it", "side by side", "put the logs next to it" |
|
|
75
|
+
|
|
76
|
+
Two of those colloquialisms are traps, so read them as INTENT, not as
|
|
77
|
+
product terms: in Rove's own vocabulary **Workspace** is the center Terminal
|
|
78
|
+
Tab region of the UI (CONTEXT.md), not a checkout, and **ChatTab** is
|
|
79
|
+
retired vocabulary for Terminal Tab. A user saying "in this workspace" means
|
|
80
|
+
the worktree they are looking at — answer the intent, keep writing the real
|
|
81
|
+
term.
|
|
82
|
+
|
|
83
|
+
They nest — **Task ⊃ Terminal Tab ⊃ Split** — and isolation drops at every
|
|
84
|
+
level down:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
new Task → own worktree + own branch (parallel work can't collide)
|
|
88
|
+
new Tab → own engine session, SAME files (a helper in the same checkout)
|
|
89
|
+
new Split → same session's screen, one tab divided (a monitor beside the work)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The distinction that decides every routing call: **a new tab shares the
|
|
93
|
+
worktree and branch; only a new task gets its own.** Two tabs in one task
|
|
94
|
+
edit the same files, so they can collide — that is a feature when the user
|
|
95
|
+
wants a helper in the same checkout, and a bug when they wanted parallel
|
|
96
|
+
attempts. A split isolates nothing at all: it is a layout, for watching
|
|
97
|
+
something (logs, `btop`, a test loop) next to the work — never the answer to
|
|
98
|
+
"do this work".
|
|
99
|
+
|
|
100
|
+
### Where does this work land?
|
|
101
|
+
|
|
102
|
+
Inside a Rove session (`$KOBE_TASK_ID` non-empty — check first: it is what
|
|
103
|
+
makes the tab/split rows addressable at all), match top to bottom and take
|
|
104
|
+
the first row that fits:
|
|
105
|
+
|
|
106
|
+
| The user says | Lands in | Command |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| "you do it", "just fix it", "change X to Y" | you, right here | no Rove verb — edit the files yourself |
|
|
109
|
+
| "try it N ways", "compare approaches" | N new tasks | `rove api fan-out --repo "$PWD" --count N --prompt "…"` |
|
|
110
|
+
| "split", "side by side", "keep an eye on X while…" | a new region in the CURRENT tab | `rove api pane-open --command "…"` |
|
|
111
|
+
| names a tab: "tell the agent in tab 3" | that exact tab | `rove api send --task-id <id> --tab tab-3 --prompt "…"` |
|
|
112
|
+
| a LOCATION word: "in this workspace/worktree/checkout", "on this branch", "here", "same task" | THIS task, a NEW Terminal Tab | `rove api send --task-id "$KOBE_TASK_ID" --tab new --prompt "…"` |
|
|
113
|
+
| names an ENGINE for the same files: "let codex take over here", "try this one with claude instead" | THIS task, a new tab pinned to that engine | `rove api send --task-id "$KOBE_TASK_ID" --tab new --vendor codex --prompt "…"` |
|
|
114
|
+
| **anything else — no row above matched** | a NEW task — new worktree + branch | `rove api add --repo "$PWD" --prompt "…"` |
|
|
115
|
+
|
|
116
|
+
Order is the tiebreak: a count ("3 ways in this workspace") beats a location
|
|
117
|
+
word, and delegation language loses to "you do it" — the user asking YOU is
|
|
118
|
+
not asking for a fleet. Two more rules the table can't show:
|
|
119
|
+
|
|
120
|
+
- No location word at all ⇒ new task. It is the only routing whose isolation
|
|
121
|
+
cannot corrupt work-in-progress, so it is the safe default.
|
|
122
|
+
- "this repo" / "this project" are NOT location words — they name the repo,
|
|
123
|
+
not the checkout. Only worktree-scoped words route to a tab.
|
|
124
|
+
|
|
125
|
+
Outside a Rove session none of this applies: there is no "this task" to add
|
|
126
|
+
a tab to, so `add` / `fan-out` are the only routings available.
|
|
127
|
+
|
|
128
|
+
### Know where you are before you route
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
echo "$KOBE_TASK_ID / $KOBE_TAB_ID" # who you are (empty = not a Rove session)
|
|
132
|
+
rove api get-task --task-id "$KOBE_TASK_ID" # .task.worktreePath, .task.branch, .running, .tabs[]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`get-task` is the per-task read that answers "what is my worktree, my
|
|
136
|
+
branch, and which sibling tabs exist" — `.tabs[]` carries each tab's `id`, `kind`,
|
|
137
|
+
`vendor`, `lastTitle` and `alive`, which is exactly the target list for
|
|
138
|
+
`send --tab`. A tab flagged `unregistered: true` is a live session the tab
|
|
139
|
+
snapshot lost; it is addressable like any other.
|
|
140
|
+
|
|
141
|
+
## Discover before calling
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
rove api schema
|
|
145
|
+
rove api schema --verb add
|
|
146
|
+
rove api schema --group create
|
|
147
|
+
rove api <verb> --help
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Do not guess flags. Commands emit one JSON object; errors use
|
|
151
|
+
`{"error":{"message","code",...}}` on stderr. Common rejections also carry
|
|
152
|
+
`hint` (what to do) and `nextCommandArgs` (argv for the same `Rove`
|
|
153
|
+
executable — run `rove <args...>` verbatim to recover, e.g. `["api","list"]`
|
|
154
|
+
after `TASK_NOT_FOUND`). Add `--pretty` for readable output.
|
|
155
|
+
|
|
156
|
+
## Common operations
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# Create one task and start its first engine turn.
|
|
160
|
+
rove api add --repo "$PWD" --title "focused title" --vendor claude \
|
|
161
|
+
--prompt "<complete scoped instruction>"
|
|
162
|
+
|
|
163
|
+
# Parallel attempts of the same prompt (hard cap 10; prefer 3-4).
|
|
164
|
+
rove api fan-out --repo "$PWD" --count 3 --prompt "<prompt>"
|
|
165
|
+
rove api fan-out --repo "$PWD" --agents claude:2,codex:1 --prompt "<prompt>"
|
|
166
|
+
|
|
167
|
+
# Follow up. Use an explicit id for unattended work; the active task can drift.
|
|
168
|
+
# From inside a Rove task this auto-prefixes [KOBE PEER] provenance
|
|
169
|
+
# (sender + reply command); --plain sends verbatim.
|
|
170
|
+
rove api send --task-id <id> --prompt "<complete next turn>"
|
|
171
|
+
|
|
172
|
+
# Reply home: no --task-id inside a dispatched task = the dispatcher's tab.
|
|
173
|
+
rove api send --prompt "succeeded: <one line> (branch <final branch>)"
|
|
174
|
+
|
|
175
|
+
# A task can hold several Terminal Tabs. `get-task` lists ONE task's tabs (the
|
|
176
|
+
# usual read before addressing one); `inspect` is the wider diagnostic — every
|
|
177
|
+
# task's snapshot plus daemon activity and live pty sessions.
|
|
178
|
+
rove api inspect --task-id <id>
|
|
179
|
+
rove api send --task-id <id> --tab tab-3 --prompt "<turn>" # exact alive tab
|
|
180
|
+
rove api send --task-id <id> --tab new --prompt "<turn>" # fresh engine tab
|
|
181
|
+
# Same worktree, DIFFERENT agent — the API twin of the TUI's ctrl+e pick. The
|
|
182
|
+
# engine is pinned to that tab (survives restarts, unaffected by a later
|
|
183
|
+
# set-vendor) and the task's own vendor is left alone. --tab new only.
|
|
184
|
+
rove api send --task-id <id> --tab new --vendor codex --prompt "<turn>"
|
|
185
|
+
|
|
186
|
+
rove api get-task --task-id <id>
|
|
187
|
+
rove api collect --task-ids <id1>,<id2>,<id3> --pretty
|
|
188
|
+
rove api list --pretty
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`.running` means the task's canonical Hosted PTY engine session is alive.
|
|
192
|
+
Omitting BOTH `--task-id` and `--tab` inside a task that has a dispatcher
|
|
193
|
+
targets that dispatcher's tab (see the reply rule above); otherwise the
|
|
194
|
+
target is the active task. Omitting only `--tab` targets a live engine tab
|
|
195
|
+
(`tab-1` first, then any surviving engine tab). Only when the task has NO live session at all does `send`
|
|
196
|
+
auto-start the canonical engine in the task's worktree (`started: true` in
|
|
197
|
+
the result marks that fresh session). If live tabs exist but none resolves
|
|
198
|
+
as an engine, it refuses with `NO_ENGINE_TAB` — address one with `--tab
|
|
199
|
+
tab-N` or spawn one with `--tab new`; it never silently spawns a duplicate
|
|
200
|
+
engine.
|
|
201
|
+
|
|
202
|
+
## Terminal panes
|
|
203
|
+
|
|
204
|
+
Split the workspace terminal the user is watching (tmux-style) or open a
|
|
205
|
+
separate command tab — the attached TUI performs it, so this is a no-op
|
|
206
|
+
headless:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Split the focused tab; the pane runs the command via `sh -lc` and
|
|
210
|
+
# closes when it exits. Omit --command for an interactive shell.
|
|
211
|
+
rove api pane-open --command "btop"
|
|
212
|
+
rove api pane-open --direction down --command "watch -n1 git status -sb"
|
|
213
|
+
rove api pane-open --placement tab --title logs --command "tail -f app.log"
|
|
214
|
+
|
|
215
|
+
# Close panes you opened, by their --title (engine panes are never closed).
|
|
216
|
+
rove api pane-close --title logs
|
|
217
|
+
|
|
218
|
+
# Toast a one-liner in every attached Rove UI — surface "done / needs input /
|
|
219
|
+
# error" moments without touching any session (kinds get severity styling).
|
|
220
|
+
rove api notify --title "build green, artifacts in dist/" --kind done
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Defaults: the caller's own task (`$KOBE_TASK_ID`, then the active task),
|
|
224
|
+
`--placement split`, `--direction right`. Alternate right/down to build a
|
|
225
|
+
grid; screen size bounds splitting — a split that would shrink any pane
|
|
226
|
+
below the minimum usable size (20×6 cells) falls back to a tab.
|
|
227
|
+
Panes land in the USER'S live workspace — open them when asked (monitors,
|
|
228
|
+
logs, dashboards), don't scatter panes for work `add`/`fan-out` should own.
|
|
229
|
+
|
|
230
|
+
## Lifecycle
|
|
231
|
+
|
|
232
|
+
| Verb | Purpose |
|
|
233
|
+
|---|---|
|
|
234
|
+
| `rename --task-id ID --title T` | Rename a task |
|
|
235
|
+
| `set-branch --task-id ID --branch B` | Rename its branch |
|
|
236
|
+
| `set-vendor --task-id ID --vendor V` | Change engine for the next launch |
|
|
237
|
+
| `set-status --task-id ID --status S` | Set lifecycle status |
|
|
238
|
+
| `archive --task-id ID [--archived=false]` | Archive/unarchive; stops live sessions |
|
|
239
|
+
| `pin --task-id ID [--pinned=false]` | Pin/unpin |
|
|
240
|
+
| `set-active --task-id ID` / `--none` | Change shared active task |
|
|
241
|
+
| `ensure-worktree --task-id ID` | Materialize without starting an engine |
|
|
242
|
+
| `land --task-id ID [--strategy merge\|squash] [--delete-branch] [--then-archive] [--remove-worktree]` | Merge the task's branch into the base repo's current branch; `--remove-worktree` cleans up the Worktree after (branch stays; dirty/self/base refused, outcome in the result's `worktree` field) |
|
|
243
|
+
| `delete --task-id ID [--force]` | Destructive task + Worktree removal |
|
|
244
|
+
| `discover-adoptable --repo PATH` | Find untracked Worktrees |
|
|
245
|
+
| `adopt --repo PATH --worktree PATH` | Import a Worktree |
|
|
246
|
+
|
|
247
|
+
Prefer `archive` unless the user explicitly authorizes deletion.
|
|
248
|
+
|
|
249
|
+
## Issue tracker
|
|
250
|
+
|
|
251
|
+
Issues are daemon-owned, not repo files:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
rove api issue-list --repo "$PWD" --pretty
|
|
255
|
+
rove api issue-create --repo "$PWD" --title "title" --body "context"
|
|
256
|
+
rove api issue-set-status --repo "$PWD" --id <n> --status done
|
|
257
|
+
rove api issue-update --repo "$PWD" --id <n> --title "new" --body "body"
|
|
258
|
+
rove api issue-update --repo "$PWD" --id <n> --task <taskId> # link; `--task none` unlinks
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Kanban semantics
|
|
262
|
+
|
|
263
|
+
The TUI and web render issues as a Backlog / In progress / Done board whose
|
|
264
|
+
columns derive from the issue's own lifecycle — do NOT move cards with
|
|
265
|
+
`issue-set-status doing`:
|
|
266
|
+
|
|
267
|
+
- **In progress** = the issue has a linked task; `issue-update --task <taskId>`
|
|
268
|
+
IS the move (typical flow: `issue-create` → `add` a task → link them).
|
|
269
|
+
- **Done** = `status done`; the daemon mirrors it automatically when the
|
|
270
|
+
linked task finishes.
|
|
271
|
+
- **Backlog** = everything else (`open`/`doing`/`hold`, unlinked).
|
|
272
|
+
|
|
273
|
+
## Fan-out rules
|
|
274
|
+
|
|
275
|
+
Fan out only when the user requests parallel approaches, comparison, or an
|
|
276
|
+
explicit count. Give each task a scoped prompt, report returned IDs, then use
|
|
277
|
+
`collect` to compare. Do not recursively fan out from spawned tasks. Do not
|
|
278
|
+
poll `send` in a tight loop or use it as casual chat; every call is a full
|
|
279
|
+
engine turn.
|
|
280
|
+
|
|
281
|
+
### Completion flows back through chat (`send`)
|
|
282
|
+
|
|
283
|
+
Outcomes are explicit, never inferred — and they travel as a MESSAGE to the
|
|
284
|
+
spawning agent's chat tab, not as stored state nobody reads.
|
|
285
|
+
|
|
286
|
+
**Worker side** — a task created from inside another Rove task records its
|
|
287
|
+
dispatcher (the creating task + tab); when the work is finished, a bare
|
|
288
|
+
`rove api send --prompt "<succeeded|failed>: <one line> (branch <final
|
|
289
|
+
branch>)"` routes the outcome back to that exact tab. Include the final
|
|
290
|
+
branch name — the spawner needs it to `land`. The first-prompt coda still
|
|
291
|
+
names the spawner for an explicit `--task-id` send.
|
|
292
|
+
|
|
293
|
+
**Coordinator side** — do NOT block or poll. Keep working (or end your
|
|
294
|
+
turn); each worker's outcome arrives in your chat as a `[KOBE PEER]` message
|
|
295
|
+
with its task id. What arrives is the worker's claim, not Rove-verified —
|
|
296
|
+
verify the winner's actual diff before landing. Silence never proves a
|
|
297
|
+
worker died (it may be mid-turn or stuck on a permission prompt): peek with
|
|
298
|
+
`collect`/`get-task`, nudge with `send`, and never mark a silent task failed
|
|
299
|
+
or auto-retry it.
|
|
300
|
+
|
|
301
|
+
### Closing a round
|
|
302
|
+
|
|
303
|
+
After comparing attempts, finish the round instead of leaving tasks behind:
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
# Land the winner: merge its branch into the base repo's CURRENT branch.
|
|
307
|
+
# Verify the base checkout is on the intended branch first.
|
|
308
|
+
rove api land --task-id <winner> --then-archive
|
|
309
|
+
|
|
310
|
+
# Archive the losers (non-destructive; branches survive).
|
|
311
|
+
rove api archive --task-id <loser1>
|
|
312
|
+
rove api archive --task-id <loser2>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
`land` refuses a dirty base checkout; on merge conflict it aborts cleanly and
|
|
316
|
+
returns the conflicted files for manual resolution. Only `delete` destroys a
|
|
317
|
+
Worktree — never use it on a loser without explicit user authorization.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{l as e,o as t}from"./terminal-qBEkzc-m.js";import{_ as n,f as r,l as i,r as a,y as o}from"./tabs-Dx-TnbvG.js";import{d as s,t as c}from"./createLucideIcon-CM5xLVj1.js";import{a as l,n as u,r as d}from"./toast-BXjAT0ix.js";import{n as f,t as p}from"./ViewToggle-BdPCMBWa.js";import{n as m,t as h}from"./store-uT65Mask.js";import{n as g,t as _}from"./active-task-GeQZqbJK.js";import{t as v}from"./external-store-DJlWpyYC.js";import{c as y,d as b,i as x,l as S,p as C,r as w,t as T,u as E}from"./triage-7QLsCY8d.js";import{i as D,r as O,t as k}from"./WorkspaceTabs-CMKlvN_Y.js";import{t as A}from"./SettingsPage-CLRhr-sg.js";import{t as j}from"./ChatTranscript-DLthbnmB.js";import{t as ee}from"./plus-BbX5qXba.js";import{t as te}from"./search-BxbFZoup.js";import{t as ne}from"./x-7cB9X7Hi.js";import{n as M,t as N}from"./activity-BjTd1D8q.js";import{t as P}from"./use-focus-trap-DNMrlNR0.js";import{t as re}from"./engines-Cnxy1hW9.js";import{n as ie}from"./settings-tPcmEHCP.js";import{i as ae,r as oe}from"./vendor-CdtpTJrf.js";import{r as F}from"./web-transport-D0bugxxv.js";import{n as se,t as I}from"./time-kviT26Tm.js";import{n as L,t as R}from"./ConfirmDialog-CDPOtXww.js";import{t as z}from"./text-match-DW3sD-Rt.js";import{t as B}from"./SlideOver-Dxtk6Gn2.js";import{n as V,r as ce,t as le}from"./chips-Da37C4KZ.js";var ue=c(`circle-question-mark`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`,key:`1u773s`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),de=c(`folder-input`,[[`path`,{d:`M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1`,key:`fm4g5t`}],[`path`,{d:`M2 13h10`,key:`pgb2dq`}],[`path`,{d:`m9 16 3-3-3-3`,key:`6m91ic`}]]),H=c(`loader-circle`,[[`path`,{d:`M21 12a9 9 0 1 1-6.219-8.56`,key:`13zald`}]]),fe=c(`panel-right`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M15 3v18`,key:`14nvp0`}]]),U=e(o(),1),W=s();function pe({onClose:e}){let{tasks:t}=m(),n=l(),i=(0,U.useRef)(null);P(i);let a=(0,U.useMemo)(()=>{let e=new Set,n=[];for(let r of t)r.repo&&!e.has(r.repo)&&(e.add(r.repo),n.push(r.repo));return n.sort()},[t]),o=(0,U.useMemo)(()=>new Set(t.map(e=>e.worktreePath).filter(Boolean)),[t]),[s,c]=(0,U.useState)(a[0]??``),[f,p]=(0,U.useState)(null),[_,v]=(0,U.useState)(!1),[y,b]=(0,U.useState)(null),[x,S]=(0,U.useState)(!1),C=async e=>{if(e){v(!0),p(null);try{let{worktrees:t}=await h(`worktree.discoverAdoptable`,{repo:e});p(t)}catch(e){d(`scan worktrees`,e),p([])}finally{v(!1)}}},T=async t=>{b(t.path);try{let{task:i}=await h(`worktree.adopt`,{repo:s,worktreePath:t.path,branch:t.branch,ifExists:`return`});r(i.id),g(i.id),n({to:`/task/$taskId`,params:{taskId:i.id}}),u(`success`,`Adopted ${t.branch||t.path}`),e()}catch(e){d(`adopt worktree`,e)}finally{b(null)}};return x?(0,W.jsx)(w,{onClose:e}):a.length===0?(0,W.jsx)(`div`,{className:`fixed inset-0 z-40 flex items-center justify-center bg-black/60`,onClick:e,onKeyDown:t=>{t.key===`Escape`&&e()},role:`presentation`,children:(0,W.jsxs)(`div`,{ref:i,role:`dialog`,"aria-modal":`true`,"aria-label":`Adopt worktree`,className:`flex w-[32rem] max-w-[calc(100vw-2rem)] flex-col border border-line bg-surface shadow-xl`,onClick:e=>e.stopPropagation(),onKeyDown:()=>{},children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between border-b border-line px-3 py-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-fg`,children:`Adopt worktree`}),(0,W.jsx)(`span`,{className:`font-mono text-[10px] text-subtle`,children:`pull an existing worktree into Rove`})]}),(0,W.jsxs)(`div`,{className:`px-3 py-6 text-center`,children:[(0,W.jsx)(`p`,{className:`text-[12px] leading-relaxed text-subtle`,children:`No repos known to Rove yet. Create a task in a repo first, then come back to adopt its worktrees.`}),(0,W.jsx)(`button`,{type:`button`,onClick:()=>S(!0),className:`mt-4 border border-primary bg-inset px-3 py-1.5 text-[11px] text-fg transition-colors hover:bg-primary/10`,children:`Create a task`})]}),(0,W.jsx)(`div`,{className:`flex justify-end border-t border-line px-3 py-2`,children:(0,W.jsx)(`button`,{type:`button`,onClick:e,className:`border border-line bg-bg px-3 py-1.5 text-[11px] text-muted transition-colors hover:border-primary hover:text-fg`,children:`Close`})})]})}):(0,W.jsx)(`div`,{className:`fixed inset-0 z-40 flex items-center justify-center bg-black/60`,onClick:e,onKeyDown:t=>{t.key===`Escape`&&e()},role:`presentation`,children:(0,W.jsxs)(`div`,{ref:i,role:`dialog`,"aria-modal":`true`,"aria-label":`Adopt worktree`,className:`flex max-h-[80vh] w-[32rem] max-w-[calc(100vw-2rem)] flex-col border border-line bg-surface shadow-xl`,onClick:e=>e.stopPropagation(),onKeyDown:()=>{},children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between border-b border-line px-3 py-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-fg`,children:`Adopt worktree`}),(0,W.jsx)(`span`,{className:`font-mono text-[10px] text-subtle`,children:`pull an existing worktree into Rove`})]}),(0,W.jsxs)(`div`,{className:`space-y-2 px-3 py-3`,children:[(0,W.jsx)(`div`,{className:`mb-1 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Repo`}),(0,W.jsxs)(`div`,{className:`flex gap-2`,children:[(0,W.jsx)(`select`,{value:s,onChange:e=>c(e.target.value),className:`min-w-0 flex-1 border border-line bg-bg px-2 py-1.5 text-[12px] text-fg focus:border-line-active focus:outline-none`,children:a.map(e=>(0,W.jsx)(`option`,{value:e,children:e},e))}),(0,W.jsx)(`button`,{type:`button`,onClick:()=>void C(s),disabled:!s||_,className:`shrink-0 border border-primary bg-inset px-3 py-1.5 text-[11px] text-fg transition-colors hover:bg-primary/10 disabled:opacity-40`,children:_?`Scanning…`:`Scan`})]})]}),(0,W.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto border-t border-line`,children:f===null?(0,W.jsx)(`p`,{className:`px-3 py-6 text-center text-[12px] text-subtle`,children:`Pick a repo and Scan to find adoptable worktrees.`}):f.length===0?(0,W.jsx)(`p`,{className:`px-3 py-6 text-center text-[12px] text-subtle`,children:`No adoptable worktrees found for this repo.`}):f.map(e=>{let t=o.has(e.path);return(0,W.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-line-subtle px-3 py-2 last:border-b-0`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`truncate font-mono text-[12px] text-fg`,children:e.branch||`(detached)`}),e.dirty&&(0,W.jsx)(`span`,{className:`shrink-0 text-[10px] text-kobe-yellow`,children:`dirty`}),e.kobeManaged&&(0,W.jsx)(`span`,{className:`shrink-0 text-[10px] text-subtle`,children:`rove`})]}),(0,W.jsxs)(`div`,{className:`mt-0.5 flex items-center gap-2 text-[10px] text-subtle`,children:[(0,W.jsx)(`span`,{className:`truncate font-mono`,children:e.path}),e.lastActivityMs>0&&(0,W.jsx)(`span`,{className:`ml-auto shrink-0`,children:se(e.lastActivityMs)})]})]}),t?(0,W.jsx)(`span`,{className:`shrink-0 text-[10px] text-subtle`,children:`tracked`}):(0,W.jsx)(`button`,{type:`button`,onClick:()=>void T(e),disabled:y!==null,className:`shrink-0 border border-line bg-bg px-2 py-1 text-[11px] text-muted transition-colors hover:border-primary hover:text-fg disabled:opacity-40`,children:y===e.path?`Adopting…`:`Adopt`})]},e.path)})}),(0,W.jsx)(`div`,{className:`flex justify-end border-t border-line px-3 py-2`,children:(0,W.jsx)(`button`,{type:`button`,onClick:e,className:`border border-line bg-bg px-3 py-1.5 text-[11px] text-muted transition-colors hover:border-primary hover:text-fg`,children:`Close`})})]})})}var G=v({query:``,statusFilter:`all`,sortMode:`default`,showArchived:!1}),K=null;function q(e){G.update(t=>({...t,...e}))}function J(e){q({query:e})}function Y(e){q({statusFilter:e})}function me(e){q({sortMode:e})}function he(e){q({showArchived:e})}function ge(e){!e||e===K||(K=e,q({sortMode:e}))}function _e(){return G.useSnapshot()}function ve(e){let t=Date.parse(e.updatedAt||e.createdAt);return Number.isFinite(t)?t:0}function ye(e,t){let n=ve(t)-ve(e);return n===0?t.id.localeCompare(e.id):n}function be(e,t){let n=e.filter(e=>e.kind===`main`),r=e.filter(e=>e.kind!==`main`&&e.pinned),i=e.filter(e=>e.kind!==`main`&&!e.pinned);return t===`recent`&&(r.sort(ye),i.sort(ye)),[...n,...r,...i]}function xe(e,t){return z([e.title,e.branch,e.repo,e.worktreePath,e.vendor,e.status].filter(Boolean).join(` `),t)}function Se({task:e,onClose:t}){return(0,W.jsx)(B,{open:e!==null,onClose:t,title:e?(0,W.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`shrink-0 border border-line px-1 py-0.5 font-mono text-[9px] uppercase tracking-wide text-subtle`,children:`Archived`}),(0,W.jsx)(`span`,{className:`min-w-0 truncate`,children:e.title||e.branch})]}):void 0,children:e&&(0,W.jsx)(j,{worktreePath:e.worktreePath??null,vendor:e.vendor??`claude`,title:e.title||e.branch})})}function Ce({children:e,suffix:t}){return(0,W.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:e}),t?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(`span`,{className:`h-px flex-1 bg-line`}),(0,W.jsx)(`span`,{className:`font-mono text-[10px] font-bold uppercase text-primary`,children:t})]}):null]})}function we({task:e,engine:t,job:n,changes:r,engineName:i,active:a,onClick:o}){let s=n?.phase===`running`,c=s?`materializing…`:M(t?.state),l=I(e.updatedAt||e.createdAt);return(0,W.jsxs)(`button`,{type:`button`,"data-task-id":e.id,onClick:o,className:`group w-full border-l-2 px-3 py-2 text-left transition-colors ${a?`border-primary bg-inset`:`border-transparent hover:bg-surface`}`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[s?(0,W.jsx)(H,{size:10,strokeWidth:2.5,className:`shrink-0 animate-spin text-primary`}):(0,W.jsx)(`span`,{className:`h-1.5 w-1.5 shrink-0 rounded-full ${N(t?.state)}`}),(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[13px] ${a?`text-fg`:`text-fg/90`}`,children:e.title||e.branch}),(0,W.jsx)(ce,{pr:e.prStatus}),e.pinned&&(0,W.jsx)(`span`,{className:`shrink-0 text-[10px] text-subtle`,children:`PIN`}),(0,W.jsx)(le,{counts:r})]}),(0,W.jsxs)(`div`,{className:`mt-0.5 flex items-center gap-2 pl-3.5 text-[11px] text-subtle`,children:[(0,W.jsx)(`span`,{className:`min-w-0 truncate`,children:e.branch||`—`}),(0,W.jsxs)(`span`,{className:`ml-auto flex shrink-0 items-center gap-2`,children:[(0,W.jsx)(V,{label:i}),c&&(0,W.jsx)(`span`,{className:`text-muted`,children:c}),l&&(0,W.jsx)(`span`,{className:`text-subtle`,children:l})]})]})]})}function Te({task:e,onRestore:t,onPreview:n}){let r=e.title||e.branch;return(0,W.jsxs)(`div`,{className:`group flex items-center gap-2 border-l-2 border-transparent px-3 py-1.5`,children:[n?(0,W.jsx)(`button`,{type:`button`,onClick:n,title:`Preview history`,className:`min-w-0 flex-1 truncate text-left text-[12px] text-subtle transition-colors hover:text-fg`,children:r}):(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[12px] text-subtle`,children:r}),(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`shrink-0 border border-line bg-surface px-1.5 py-0.5 text-[10px] text-muted opacity-0 transition-opacity hover:border-primary hover:text-fg group-hover:opacity-100`,children:`Restore`})]})}function Ee({onOpenSettings:e,onNewTask:t,onAdopt:i}){let{tasks:a,engineStates:o,jobs:s,worktreeChanges:c,uiPrefs:u,hydrated:f,streamConnected:p}=m(),{selectedTaskId:_}=n(),v=re(),y=(0,U.useMemo)(()=>oe(a),[a]),b=e=>ae(v,e,y),{query:S,statusFilter:C,sortMode:w,showArchived:E}=_e(),D=(0,U.useRef)(null),O=(0,U.useRef)(null);(0,U.useEffect)(()=>{_&&D.current?.querySelector(`[data-task-id="${CSS.escape(_)}"]`)?.scrollIntoView({block:`nearest`})},[_]);let k=u?.sortMode;(0,U.useEffect)(()=>{ge(k)},[k]);let A=(0,U.useMemo)(()=>a.filter(e=>!e.archived),[a]),j=(0,U.useMemo)(()=>a.filter(e=>e.archived&&e.kind!==`main`),[a]),M=(0,U.useMemo)(()=>be(A.filter(e=>xe(e,S)&&T(o[e.id],c[e.worktreePath],C)),w),[A,S,C,w,o,c]),N=M.filter(e=>e.kind===`main`),P=M.filter(e=>e.kind!==`main`),F=!f||!p&&a.length===0,se=l(),I=e=>{r(e),g(e),se({to:`/task/$taskId`,params:{taskId:e}})};(0,U.useEffect)(()=>{let e=e=>{if(e.metaKey||e.ctrlKey||e.altKey)return;let t=e.key,n=t===`ArrowDown`||t===`ArrowUp`,r=t===`j`||t===`ArrowDown`,i=t===`k`||t===`ArrowUp`,a=t===`/`;if(!r&&!i&&!a)return;let o=e.target;if(o&&(o.tagName===`INPUT`||o.tagName===`TEXTAREA`||o.tagName===`SELECT`||o.isContentEditable)||document.querySelector(`[role=dialog],[role=alertdialog]`)||document.querySelector(`[data-settings-open]`))return;if(a){e.preventDefault(),O.current?.focus();return}if(n&&o&&o!==document.body&&!D.current?.contains(o)||M.length===0)return;e.preventDefault();let s=M.findIndex(e=>e.id===_),c=s===-1?0:Math.min(Math.max(s+(r?1:-1),0),M.length-1);I(M[c].id)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[M,_]);let L=e=>{h(`task.archive`,{taskId:e.id,archived:!1}).catch(t=>d(`restore "${e.title||e.branch}"`,t))},[R,z]=(0,U.useState)(!1),[B,V]=(0,U.useState)(null);return(0,U.useEffect)(()=>{let e=!0;return ie().then(t=>{e&&z(t.archivedHistoryPreview===!0)}).catch(()=>{}),()=>{e=!1}},[]),(0,W.jsxs)(`aside`,{className:`flex w-64 shrink-0 flex-col border-r border-line bg-bg`,children:[(0,W.jsxs)(`div`,{className:`border-b border-line bg-surface/50 px-3 py-2`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Tasks`}),(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`button`,{type:`button`,onClick:()=>me(w==="default"?`recent`:`default`),className:`font-mono text-[10px] uppercase ${w===`recent`?`text-primary`:`text-muted hover:text-fg`}`,title:`Toggle task sort`,children:`sort`}),(0,W.jsxs)(`span`,{className:`font-mono text-[10px] text-muted`,children:[M.length,`/`,A.length]}),(0,W.jsx)(`button`,{type:`button`,onClick:i,className:`text-muted transition-colors hover:text-primary`,title:`Adopt an existing worktree`,"aria-label":`Adopt worktree`,children:(0,W.jsx)(de,{size:14,strokeWidth:1.9})}),(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`text-muted transition-colors hover:text-primary`,title:`New task`,"aria-label":`New task`,children:(0,W.jsx)(ee,{size:14,strokeWidth:2.2})})]})]}),(0,W.jsxs)(`label`,{className:`mt-2 flex h-8 items-center gap-2 border border-line bg-bg px-2 text-[12px] text-muted focus-within:border-line-active`,children:[(0,W.jsx)(te,{size:14,strokeWidth:1.8,className:`shrink-0 text-subtle`}),(0,W.jsx)(`input`,{ref:O,value:S,onChange:e=>J(e.target.value),onKeyDown:e=>{e.key===`Enter`&&M.length>0?(e.preventDefault(),I(M[0].id),e.currentTarget.blur()):e.key===`Escape`&&S&&(e.preventDefault(),J(``))},placeholder:`Filter tasks`,className:`min-w-0 flex-1 bg-transparent text-fg placeholder:text-subtle focus:outline-none`}),S&&(0,W.jsx)(`button`,{type:`button`,onClick:()=>J(``),className:`shrink-0 text-subtle hover:text-fg`,"aria-label":`clear task filter`,title:`Clear filter`,children:(0,W.jsx)(ne,{size:13,strokeWidth:2})})]}),(0,W.jsx)(`div`,{className:`mt-2 flex items-center gap-1`,children:[{key:`all`,label:`All`,title:`All tasks`},{key:`attention`,label:`Needs`,title:`Needs input / errored / rate-limited`}].map(e=>(0,W.jsx)(`button`,{type:`button`,onClick:()=>Y(e.key),title:e.title,className:`border px-1.5 py-0.5 text-[10px] transition-colors ${C===e.key?`border-primary bg-inset text-fg`:`border-line bg-bg text-subtle hover:border-primary hover:text-fg`}`,children:e.label},e.key))})]}),(0,W.jsxs)(`div`,{ref:D,className:`flex-1 overflow-y-auto`,children:[F?(0,W.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-4 text-[12px] text-subtle`,children:[(0,W.jsx)(H,{size:13,strokeWidth:2,className:`animate-spin`}),(0,W.jsx)(`span`,{children:`connecting…`})]}):A.length===0?(0,W.jsxs)(`div`,{className:`px-3 py-4 text-[12px] leading-relaxed text-subtle`,children:[(0,W.jsx)(`p`,{children:`No tasks yet.`}),(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`mt-3 border border-line bg-surface px-2 py-1 text-[11px] text-muted hover:border-primary hover:text-fg`,children:`+ New task`})]}):M.length===0?(0,W.jsxs)(`div`,{className:`px-3 py-4 text-[12px] leading-relaxed text-subtle`,children:[(0,W.jsx)(`div`,{children:S?`No matches for “${S}”.`:`No tasks in this status.`}),(0,W.jsx)(`button`,{type:`button`,onClick:()=>{J(``),Y(`all`)},className:`mt-3 border border-line bg-surface px-2 py-1 text-[11px] text-muted hover:border-primary hover:text-fg`,children:`Clear filter`})]}):(0,W.jsxs)(W.Fragment,{children:[N.length>0&&(0,W.jsx)(Ce,{children:`Projects`}),N.map(e=>(0,W.jsx)(we,{task:e,engine:o[e.id],job:s[e.id],changes:c[e.worktreePath],engineName:b(e),active:e.id===_,onClick:()=>I(e.id)},e.id)),P.length>0&&(0,W.jsx)(Ce,{suffix:w==="default"?void 0:w,children:`Worktrees`}),P.map(e=>(0,W.jsx)(we,{task:e,engine:o[e.id],job:s[e.id],changes:c[e.worktreePath],engineName:b(e),active:e.id===_,onClick:()=>I(e.id)},e.id))]}),!F&&j.length>0&&(0,W.jsxs)(`div`,{className:`mt-2 border-t border-line-subtle pb-2`,children:[(0,W.jsxs)(`button`,{type:`button`,onClick:()=>he(!E),className:`flex w-full items-center gap-2 px-3 py-2 text-left`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Archived`}),(0,W.jsx)(`span`,{className:`font-mono text-[10px] text-subtle`,children:j.length}),(0,W.jsx)(`span`,{className:`ml-auto font-mono text-[10px] text-subtle`,children:E?`−`:`+`})]}),E&&j.map(e=>(0,W.jsx)(Te,{task:e,onRestore:()=>L(e),onPreview:R?()=>V(e):void 0},e.id))]})]}),(0,W.jsx)(Se,{task:B,onClose:()=>V(null)}),(0,W.jsx)(`div`,{className:`border-t border-line p-2`,children:(0,W.jsxs)(`button`,{type:`button`,onClick:e,className:`flex w-full items-center gap-2 border border-line bg-surface px-2 py-2 text-left text-[12px] text-muted transition-colors hover:border-primary hover:bg-inset hover:text-fg`,children:[(0,W.jsx)(x,{size:15,strokeWidth:1.8}),(0,W.jsx)(`span`,{children:`Settings`})]})})]})}async function De(e){try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}function X(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`)}var Oe=/^\/api\/issue-assets\/[a-f0-9]{16}\/[A-Za-z0-9_-]+\.[a-z0-9]+$/;function ke(e){let t=e.trim();return Oe.test(t)?t:null}function Ae(e){let t=e.trim();return/^https?:\/\//i.test(t)?t:t.startsWith(`//`)?null:t.startsWith(`/`)||t.startsWith(`#`)||t.startsWith(`./`)||t.startsWith(`../`)?t:null}function je(e){let t=e;return t.includes(`]`)&&t.includes(`)`)&&(t=t.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,(e,t,n)=>{let r=ke(n.replace(/&/g,`&`));return r?`<img src="${X(r)}" alt="${X(t)}" loading="lazy" class="kobe-md-img">`:``})),t.includes(`]`)&&t.includes(`)`)&&(t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,t,n)=>{let r=Ae(n.replace(/&/g,`&`));return r?`<a href="${X(r)}" target="_blank" rel="noopener noreferrer" class="kobe-md-link">${t}</a>`:`${t}(${n})`})),t=t.replace(/\*\*(.+?)\*\*/g,`<strong>$1</strong>`),t=t.replace(/(^|[^*])\*([^*]+)\*/g,`$1<em>$2</em>`),t}function Z(e){return e.split(/(`[^`]+`)/g).map((e,t)=>t%2==1?`<code class="kobe-md-code">${e.slice(1,-1)}</code>`:je(e)).join(``)}function Me(e){let t=e.replace(/\r\n/g,`
|
|
2
|
+
`).split(`
|
|
3
|
+
`),n=[],r=0,i=null,a=()=>{i&&=(n.push(`</${i}>`),null)};for(;r<t.length;){let e=t[r];if(/^```/.test(e)){a();let e=[];for(r++;r<t.length&&!/^```/.test(t[r]);)e.push(X(t[r])),r++;r++,n.push(`<pre class="kobe-md-pre"><code>${e.join(`
|
|
4
|
+
`)}</code></pre>`);continue}if(/^\s*(-{3,}|\*{3,}|_{3,})\s*$/.test(e)){a(),n.push(`<hr class="kobe-md-hr" />`),r++;continue}let o=/^(#{1,6})\s+(.*)$/.exec(e);if(o){a();let e=o[1].length;n.push(`<h${e} class="kobe-md-h">${Z(X(o[2]))}</h${e}>`),r++;continue}if(/^>\s?/.test(e)){a(),n.push(`<blockquote class="kobe-md-quote">${Z(X(e.replace(/^>\s?/,``)))}</blockquote>`),r++;continue}let s=/^\s*[-*]\s+(.*)$/.exec(e);if(s){i!==`ul`&&(a(),n.push(`<ul class="kobe-md-ul">`),i=`ul`),n.push(`<li>${Z(X(s[1]))}</li>`),r++;continue}let c=/^\s*\d+\.\s+(.*)$/.exec(e);if(c){i!==`ol`&&(a(),n.push(`<ol class="kobe-md-ol">`),i=`ol`),n.push(`<li>${Z(X(c[1]))}</li>`),r++;continue}if(e.trim()===``){a(),r++;continue}a();let l=[e];for(r++;r<t.length&&t[r].trim()!==``&&!/^(#{1,6}\s|>\s?|```|\s*[-*]\s|\s*\d+\.\s|\s*(-{3,}|\*{3,}|_{3,})\s*$)/.test(t[r]);)l.push(t[r]),r++;n.push(`<p class="kobe-md-p">${Z(X(l.join(` `)))}</p>`)}return a(),n.join(`
|
|
5
|
+
`)}async function Ne(e){return(await t.get(`/api/notes`,{query:{taskId:e},label:`load notes`})).markdown??``}async function Pe(e,n){await t.put(`/api/notes`,{taskId:e,markdown:n},{label:`save notes`})}function Fe(e){switch(e){case`saving`:return`saving…`;case`saved`:return`saved`;case`error`:return`save failed`;default:return``}}var Ie=600;function Le({children:e,right:t}){return(0,W.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2`,children:[(0,W.jsx)(`span`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:e}),t]})}function Re({taskId:e,full:t=!1}){let[n,r]=(0,U.useState)(``),[i,a]=(0,U.useState)(!1),[o,s]=(0,U.useState)(!1),[c,l]=(0,U.useState)(`idle`),u=(0,U.useMemo)(()=>Me(n),[n]),d=(0,U.useRef)(null),f=(0,U.useRef)(null),p=(0,U.useRef)(null),m=(0,U.useCallback)(()=>{d.current&&=(clearTimeout(d.current),null);let e=p.current;if(!e)return;p.current=null;let{taskId:t,value:n}=e;Pe(t,n).then(()=>{f.current===t&&l(`saved`)}).catch(()=>{f.current===t&&l(`error`)})},[]);(0,U.useEffect)(()=>{if(f.current=e,m(),l(`idle`),r(``),a(!1),!e)return;let t=!1;return s(!0),Ne(e).then(n=>{!t&&f.current===e&&r(n)}).catch(()=>{!t&&f.current===e&&r(``)}).finally(()=>{t||s(!1)}),()=>{t=!0}},[e,m]),(0,U.useEffect)(()=>()=>{m()},[m]);let h=(0,U.useCallback)(t=>{if(r(t),!e)return;let n=e;l(`saving`),p.current={taskId:n,value:t},d.current&&clearTimeout(d.current),d.current=setTimeout(m,Ie)},[e,m]);return(0,W.jsxs)(`div`,{className:`flex h-full min-h-0 flex-1 flex-col bg-bg`,children:[(0,W.jsx)(Le,{right:e?(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[c!==`idle`&&(0,W.jsx)(`span`,{className:`text-[10px] ${c===`error`?`text-kobe-red`:`text-subtle`}`,children:Fe(c)}),(0,W.jsx)(`button`,{type:`button`,onClick:()=>a(e=>!e),className:`border px-1.5 py-0.5 text-[10px] transition-colors ${i?`border-primary bg-inset text-fg`:`border-line bg-bg text-muted hover:border-primary hover:text-fg`}`,title:`Toggle markdown preview`,children:i?`Edit`:`Preview`})]}):null,children:`Notes`}),(0,W.jsx)(`div`,{className:`min-h-0 flex-1 ${t?`px-0 pb-0`:`px-3 pb-3`}`,children:e?i?(0,W.jsx)(`div`,{className:`h-full w-full overflow-auto bg-surface px-4 py-3 ${t?`border-t border-line`:`rounded border border-line`}`,children:n.trim()?(0,W.jsx)(`div`,{className:`kobe-md text-[12px] leading-relaxed text-fg`,dangerouslySetInnerHTML:{__html:u}}):(0,W.jsx)(`p`,{className:`text-[12px] text-subtle`,children:`Nothing to preview yet.`})}):(0,W.jsx)(`textarea`,{value:n,onChange:e=>h(e.target.value),spellCheck:!1,placeholder:o?`loading notes…`:`Notes for this task — markdown, autosaved.`,disabled:o,className:`h-full w-full resize-none border-line bg-surface px-4 py-3 font-mono text-[12px] leading-relaxed text-fg placeholder:text-subtle focus:border-line-active focus:outline-none disabled:opacity-60 ${t?`border-x-0 border-b-0 border-t`:`rounded border`}`}):(0,W.jsx)(`div`,{className:`flex h-full items-center justify-center px-4 text-center`,children:(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`text-[12px] font-semibold text-fg`,children:`No task selected`}),(0,W.jsx)(`div`,{className:`mt-1 max-w-48 text-[12px] leading-relaxed text-subtle`,children:`Pick a task to open its web-only scratchpad.`})]})})})]})}var ze=[`backlog`,`in_progress`,`in_review`,`done`,`canceled`,`error`],Be=`DIRTY_WORKTREE`;function Ve(e){return e.replace(/_/g,` `)}function Q({name:e,value:t,mono:n=!1}){return(0,W.jsxs)(`div`,{className:`min-w-0 border-b border-line-subtle py-2 last:border-b-0`,children:[(0,W.jsx)(`div`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:e}),(0,W.jsx)(`div`,{className:`mt-1 min-w-0 truncate text-[12px] text-fg ${n?`font-mono`:``}`,title:t,children:t||`—`})]})}function $({children:e,onClick:t,disabled:n,danger:r=!1}){return(0,W.jsx)(`button`,{type:`button`,onClick:t,disabled:n,className:`border px-2 py-1 text-[11px] transition-colors disabled:opacity-40 ${r?`border-kobe-red/40 text-kobe-red hover:bg-kobe-red/10`:`border-line bg-surface text-muted hover:border-primary hover:text-fg`}`,children:e})}function He({task:e}){let[t,n]=(0,U.useState)(e?.title??``),[r,i]=(0,U.useState)(e?.branch??``),[o,s]=(0,U.useState)(null),[c,f]=(0,U.useState)(!1),p=(0,U.useRef)(null);(0,U.useEffect)(()=>()=>{p.current&&clearTimeout(p.current)},[]);let[m,v]=(0,U.useState)(null),y=re(),b=l();if((0,U.useEffect)(()=>{n(e?.title??``)},[e?.title]),(0,U.useEffect)(()=>{i(e?.branch??``)},[e?.branch]),!e)return(0,W.jsx)(`div`,{className:`flex h-full items-center justify-center px-4 text-center`,children:(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`text-[12px] font-semibold text-fg`,children:`No task selected`}),(0,W.jsx)(`div`,{className:`mt-1 max-w-48 text-[12px] leading-relaxed text-subtle`,children:`Pick a task to edit its metadata and worktree state.`})]})});let x=async(e,t)=>{s(e);try{await t()}catch(t){d(e.split(`:`)[0],t)}finally{s(null)}},S=()=>{let n=t.trim();!n||n===e.title||x(`rename`,()=>h(`task.rename`,{taskId:e.id,title:n}))},C=()=>{let t=r.trim();!t||t===e.branch||x(`branch`,()=>h(`task.setBranch`,{taskId:e.id,branch:t}))},w=()=>{De(e.worktreePath).then(e=>{e&&(f(!0),p.current&&clearTimeout(p.current),p.current=setTimeout(()=>f(!1),1200))})},T=()=>{v(null),x(`archive`,async()=>{await h(`task.archive`,{taskId:e.id,archived:!0}),a(),b({to:`/`}),await _(null)})},E=()=>{x(`restore`,()=>h(`task.archive`,{taskId:e.id,archived:!1}))},D=t=>{v(null),s(`delete`),(async()=>{try{await h(`task.delete`,{taskId:e.id,force:t}),a(),b({to:`/`}),g(null),u(`success`,`Deleted "${e.title||e.branch}"`)}catch(e){let n=e instanceof Error?e.message:String(e);!t&&n.includes(Be)?v({kind:`delete`,force:!0}):d(`delete`,e)}finally{s(null)}})()};return(0,W.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,W.jsxs)(`div`,{className:`border-b border-line px-3 py-3`,children:[(0,W.jsx)(`div`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Task`}),(0,W.jsxs)(`div`,{className:`mt-2 flex gap-2`,children:[(0,W.jsx)(`input`,{value:t,onChange:e=>n(e.target.value),onBlur:S,onKeyDown:e=>{e.key===`Enter`&&S()},className:`min-w-0 flex-1 border border-line bg-bg px-2 py-1.5 text-[12px] text-fg focus:border-line-active focus:outline-none`}),(0,W.jsx)($,{onClick:S,disabled:o===`rename`,children:`Save`})]}),e.archived&&(0,W.jsxs)(`div`,{className:`mt-2 flex items-center justify-between gap-2 border border-kobe-yellow/40 bg-kobe-yellow/10 px-2 py-1.5`,children:[(0,W.jsx)(`span`,{className:`text-[11px] text-kobe-yellow`,children:`archived`}),(0,W.jsx)($,{onClick:E,disabled:o!==null,children:`Restore`})]})]}),(0,W.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-3 py-2`,children:[e.kind===`main`?(0,W.jsx)(Q,{name:`Branch`,value:e.branch,mono:!0}):(0,W.jsxs)(`div`,{className:`min-w-0 border-b border-line-subtle py-2`,children:[(0,W.jsx)(`div`,{className:`text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Branch`}),(0,W.jsx)(`div`,{className:`mt-1 flex gap-2`,children:(0,W.jsx)(`input`,{value:r,onChange:e=>i(e.target.value),onBlur:C,onKeyDown:e=>{e.key===`Enter`&&C()},className:`min-w-0 flex-1 border border-line bg-bg px-2 py-1 font-mono text-[12px] text-fg focus:border-line-active focus:outline-none`})})]}),(0,W.jsx)(Q,{name:`Vendor`,value:e.vendor??`claude`}),(0,W.jsx)(Q,{name:`Worktree`,value:e.worktreePath,mono:!0}),(0,W.jsx)(Q,{name:`Repo`,value:e.repo,mono:!0}),(0,W.jsxs)(`div`,{className:`mt-4`,children:[(0,W.jsx)(`div`,{className:`mb-2 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Status`}),(0,W.jsx)(`div`,{className:`grid grid-cols-2 gap-1.5`,children:ze.map(t=>(0,W.jsx)(`button`,{type:`button`,onClick:()=>void x(`status:${t}`,()=>h(`task.status`,{taskId:e.id,status:t})),disabled:o!==null,className:`border px-2 py-1.5 text-left text-[11px] capitalize transition-colors disabled:opacity-40 ${e.status===t?`border-primary bg-inset text-fg`:`border-line bg-surface text-muted hover:border-primary hover:text-fg`}`,children:Ve(t)},t))})]}),(0,W.jsxs)(`div`,{className:`mt-4`,children:[(0,W.jsx)(`div`,{className:`mb-2 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Vendor`}),(0,W.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:y.map(t=>(0,W.jsx)(`button`,{type:`button`,onClick:()=>void x(`vendor:${t.id}`,()=>h(`task.setVendor`,{taskId:e.id,vendor:t.id})),disabled:o!==null,className:`border px-2 py-1 text-[11px] transition-colors disabled:opacity-40 ${(e.vendor??`claude`)===t.id?`border-primary bg-inset text-fg`:`border-line bg-surface text-muted hover:border-primary hover:text-fg`}`,children:t.label},t.id))})]}),(0,W.jsxs)(`div`,{className:`mt-4 grid grid-cols-2 gap-2`,children:[(0,W.jsx)($,{onClick:()=>void x(`pin`,()=>h(`task.pin`,{taskId:e.id,pinned:!e.pinned})),disabled:o!==null,children:e.pinned?`Unpin`:`Pin`}),(0,W.jsx)($,{onClick:()=>void x(`worktree`,()=>h(`task.ensureWorktree`,{taskId:e.id})),disabled:o!==null,children:`Ensure worktree`}),(0,W.jsx)($,{onClick:w,children:c?`Copied`:`Copy path`}),!e.archived&&(0,W.jsx)($,{onClick:()=>v({kind:`archive`}),disabled:o!==null,danger:!0,children:`Archive`})]}),e.kind!==`main`&&(0,W.jsxs)(`div`,{className:`mt-4 border-t border-line-subtle pt-3`,children:[(0,W.jsx)(`div`,{className:`mb-2 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Danger zone`}),(0,W.jsx)($,{onClick:()=>v({kind:`delete`,force:!1}),disabled:o!==null,danger:!0,children:`Delete task + worktree`})]})]}),m?.kind===`archive`&&(0,W.jsx)(R,{title:`Archive task`,body:`Archive "${e.title||e.branch}"? Its Hosted PTY sessions will be stopped; the worktree stays on disk and the task can be restored from the Archived section.`,confirmLabel:`Archive`,danger:!0,busy:o===`archive`,onConfirm:T,onCancel:()=>v(null)}),m?.kind===`delete`&&(0,W.jsx)(R,{title:m.force?`Worktree has uncommitted changes`:`Delete task`,body:m.force?`"${e.title||e.branch}" has uncommitted or untracked changes in its worktree. Force-delete discards them permanently.`:`Delete "${e.title||e.branch}"? This removes the task, kills its engine session, and removes its worktree (branch history stays in git).`,confirmLabel:m.force?`Force delete`:`Delete`,danger:!0,busy:o===`delete`,onConfirm:()=>D(m.force),onCancel:()=>v(null)})]})}function Ue({drawer:e=!1,onClose:t}={}){let[r,a]=(0,U.useState)(`overview`),{selectedTaskId:o}=n(),{tasks:s}=m(),c=o?s.find(e=>e.id===o)??null:null;return(0,W.jsxs)(`aside`,{className:e?`flex h-full w-full flex-col bg-bg`:`flex w-80 shrink-0 flex-col border-l border-line bg-bg`,children:[(0,W.jsxs)(`div`,{className:`flex h-9 shrink-0 items-stretch border-b border-line bg-surface`,children:[[`overview`,`notes`,`changes`].map(e=>(0,W.jsx)(`button`,{type:`button`,onClick:()=>a(e),className:`px-3 text-[10px] font-bold uppercase tracking-[0.12em] ${r===e?`border-b-2 border-primary text-fg`:`text-subtle hover:text-muted`}`,children:e===`overview`?`Task`:e===`notes`?`Notes`:`Changes`},e)),e&&t&&(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`ml-auto px-3 text-subtle hover:text-fg`,"aria-label":`Close tools`,children:(0,W.jsx)(ne,{size:14,strokeWidth:2})})]}),(0,W.jsx)(`div`,{className:`min-h-0 flex-1`,children:r===`overview`?(0,W.jsx)(He,{task:c}):r===`notes`?(0,W.jsx)(Re,{taskId:o,full:!0}):(0,W.jsx)(O,{worktreePath:c?.worktreePath??null,onOpenFile:e=>{o&&i(o,e)}})})]})}function We({onToggleTools:e,onShowHelp:t}){let{daemonConnected:r,streamConnected:i,tasks:a}=m(),{selectedTaskId:o}=n(),s=o?a.find(e=>e.id===o):null,c=F({daemonConnected:r,streamConnected:i});return(0,W.jsxs)(`header`,{"data-kobe-topbar":!0,className:`flex h-10 shrink-0 items-center gap-3 border-b border-line bg-surface px-3`,children:[(0,W.jsx)(L,{}),(0,W.jsx)(`span`,{className:`font-mono text-[13px] font-bold text-primary`,children:`[rove]`}),(0,W.jsx)(p,{}),s?(0,W.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`max-w-56 truncate rounded bg-inset px-2 py-0.5 text-[11px] text-fg`,children:s.title||s.branch}),(0,W.jsx)(`span`,{className:`hidden max-w-40 truncate font-mono text-[11px] text-subtle md:inline`,children:s.branch})]}):(0,W.jsx)(`span`,{className:`rounded bg-inset px-2 py-0.5 text-[11px] text-muted`,children:`Workspace`}),(0,W.jsxs)(`div`,{className:`ml-auto flex items-center gap-3 text-[11px] text-subtle`,children:[(0,W.jsxs)(`span`,{className:`hidden items-center gap-1.5 sm:flex`,title:c.title,children:[(0,W.jsx)(`span`,{className:`h-1.5 w-1.5 rounded-full ${c.ok?`bg-kobe-green`:`bg-kobe-yellow`}`}),(0,W.jsx)(`span`,{children:c.label})]}),(0,W.jsx)(`button`,{type:`button`,onClick:t,className:`hidden items-center text-muted transition-colors hover:text-fg sm:flex`,"aria-label":`Keyboard shortcuts`,title:`Keyboard shortcuts (?)`,children:(0,W.jsx)(ue,{size:15,strokeWidth:1.8})}),(0,W.jsx)(`button`,{type:`button`,onClick:e,className:`flex items-center text-muted transition-colors hover:text-fg lg:hidden`,"aria-label":`Toggle task tools`,title:`Task tools`,children:(0,W.jsx)(fe,{size:15,strokeWidth:1.8})})]})]})}function Ge(){let{tasks:e,update:t}=m(),{selectedTaskId:r}=n(),i=r?e.find(e=>e.id===r):null,a=e.filter(e=>!e.archived).length;return(0,W.jsxs)(`footer`,{className:`flex h-7 shrink-0 items-center gap-4 border-t border-line bg-surface px-3 text-[11px] text-subtle`,children:[(0,W.jsxs)(`span`,{children:[a,` task`,a===1?``:`s`]}),i&&(0,W.jsxs)(`span`,{className:`min-w-0 truncate text-muted`,children:[i.kind===`main`?`project`:`worktree`,` ·`,` `,D(i.worktreePath,54)]}),(0,W.jsx)(`span`,{className:`ml-auto`,children:t?.latest?`update ${t.latest} available`:`Rove web`})]})}function Ke(){let{settingsOpen:e}=C(),[t,n]=(0,U.useState)(!1),[r,i]=(0,U.useState)(!1);return(0,U.useEffect)(()=>{let e=e=>{e.key===`Escape`&&i(!1)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]),(0,W.jsxs)(`div`,{className:`flex h-screen flex-col overflow-hidden bg-bg text-fg`,children:[(0,W.jsx)(We,{onToggleTools:()=>i(e=>!e),onShowHelp:S}),(0,W.jsx)(f,{}),(0,W.jsxs)(`div`,{className:`flex min-h-0 flex-1`,children:[(0,W.jsx)(Ee,{onOpenSettings:b,onNewTask:E,onAdopt:()=>n(!0)}),e?(0,W.jsx)(A,{onClose:y}):(0,W.jsx)(k,{}),(0,W.jsx)(`div`,{className:`hidden lg:flex`,children:(0,W.jsx)(Ue,{})}),r&&(0,W.jsx)(`div`,{className:`fixed inset-0 z-30 flex justify-end bg-black/50 lg:hidden`,onClick:()=>i(!1),onKeyDown:e=>{e.key===`Escape`&&i(!1)},role:`presentation`,children:(0,W.jsx)(`div`,{role:`dialog`,"aria-modal":`true`,"aria-label":`Task tools`,className:`h-full w-80 max-w-[85vw] border-l border-line bg-bg shadow-2xl`,onClick:e=>e.stopPropagation(),onKeyDown:()=>{},children:(0,W.jsx)(Ue,{drawer:!0,onClose:()=>i(!1)})})})]}),(0,W.jsx)(Ge,{}),t&&(0,W.jsx)(pe,{onClose:()=>n(!1)})]})}export{Ke as AppShell};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.kobe-md>:first-child{margin-top:0}.kobe-md-h{color:var(--color-fg);margin:.9em 0 .4em;font-weight:700;line-height:1.3}.kobe-md h1.kobe-md-h{font-size:1.4em}.kobe-md h2.kobe-md-h{font-size:1.2em}.kobe-md h3.kobe-md-h{font-size:1.08em}.kobe-md-p{margin:.5em 0}.kobe-md-ul,.kobe-md-ol{margin:.5em 0;padding-left:1.4em}.kobe-md-ul{list-style:outside}.kobe-md-ol{list-style:decimal}.kobe-md-ul li,.kobe-md-ol li{margin:.15em 0}.kobe-md-quote{border-left:2px solid var(--color-line-active);color:var(--color-muted);margin:.5em 0;padding-left:.75rem}.kobe-md-code{font-family:var(--font-mono,ui-monospace, monospace);background:var(--color-inset);border:1px solid var(--color-line);border-radius:3px;padding:0 .3em;font-size:.9em}.kobe-md-pre{background:var(--color-bg);border:1px solid var(--color-line);border-radius:4px;margin:.6em 0;padding:.6rem .75rem;overflow-x:auto}.kobe-md-pre code{font-family:var(--font-mono,ui-monospace, monospace);white-space:pre;color:var(--color-muted);font-size:.92em}.kobe-md-link{color:var(--color-primary);text-decoration:underline}.kobe-md-hr{border:0;border-top:1px solid var(--color-line);margin:.9em 0}.kobe-md strong{color:var(--color-fg);font-weight:700}.kobe-md em{font-style:italic}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{l as e}from"./terminal-qBEkzc-m.js";import{f as t,y as n}from"./tabs-Dx-TnbvG.js";import{d as r}from"./createLucideIcon-CM5xLVj1.js";import{a as i,n as a,r as o}from"./toast-BXjAT0ix.js";import{n as s,t as c}from"./ViewToggle-BdPCMBWa.js";import{n as l}from"./store-uT65Mask.js";import{n as u}from"./active-task-GeQZqbJK.js";import{t as d}from"./external-store-DJlWpyYC.js";import{t as f}from"./external-link-BwT2u1hD.js";import{a as p,i as m,n as h,r as g,t as _}from"./lazy-issue-panels-0Rhl2uhh.js";import{t as v}from"./plus-BbX5qXba.js";import{t as y}from"./search-BxbFZoup.js";import{t as b}from"./x-7cB9X7Hi.js";import{n as ee,t as x}from"./ConfirmDialog-CDPOtXww.js";import{_ as S,a as C,d as te,g as w,h as T,m as E,p as D,s as ne,u as O}from"./issues-1SCRkcB0.js";var k=e(n(),1),A={query:``,repo:null};function j(e){M.update(t=>({...t,...e}))}var M=d(A);function N(){return M.useSnapshot()}function P(e){e!==M.getSnapshot().query&&j({query:e})}function F(e){e!==M.getSnapshot().repo&&j({repo:e})}function re(e){let{issueRepos:t,issueData:n,refreshIssues:r}=e,[i,a]=(0,k.useState)(!1),[s,c]=(0,k.useState)(null),[l,u]=(0,k.useState)(new Map);return(0,k.useEffect)(()=>{u(e=>{if(e.size===0)return e;let r=new Map(e),i=!1;for(let e of t){let t=n[e];if(!(!t||!t.exists))for(let n of t.issues)n.taskId&&r.delete(`${e}:${n.id}`)&&(i=!0)}return i?r:e})},[t,n]),{issueBusy:i,quickStartingId:s,pendingLinks:l,saveIssue:async(e,t,n)=>{a(!0);try{return await T(e,t,n),r([e]),!0}catch(e){return o(`update issue`,e),!1}finally{a(!1)}},deleteIssueConfirmed:async(e,t)=>{a(!0);try{return await C(e,t.id),r([e]),!0}catch(e){return o(`delete issue`,e),!1}finally{a(!1)}},quickStart:async(e,t,n,r,i)=>{if(s===null){c(t.id);try{let{taskId:a,workspaceTaskId:o}=await E(e,t,{vendor:n,effort:r,placement:i});return i!==`project`&&u(n=>{let r=new Map(n);return r.set(`${e}:${t.id}`,{repo:e,issueId:t.id,taskId:a}),r}),o}catch(e){o(`quick start issue`,e);return}finally{c(null)}}}}}var I=r();function L({repo:e,column:t,onNewIssue:n,onPeekIssue:r,onOpenTask:i,onDeleteIssue:a}){return(0,I.jsxs)(`section`,{"data-column":`${e}:${t.key}`,className:`flex h-full shrink-0 flex-col border border-transparent ${t.key===`backlog`?`w-96`:`w-72`}`,children:[(0,I.jsxs)(`div`,{className:`mb-2 flex items-baseline gap-2`,children:[(0,I.jsx)(`h2`,{className:`text-[11px] font-bold uppercase tracking-[0.12em] ${t.accent}`,children:t.title}),(0,I.jsx)(`span`,{className:`font-mono text-[10px] text-subtle`,children:t.cards.length+t.hiddenCount}),n&&(0,I.jsxs)(`button`,{type:`button`,onClick:n,className:`ml-auto flex items-center gap-0.5 text-[10px] text-subtle transition-colors hover:text-fg`,title:`New story in this project`,children:[(0,I.jsx)(v,{size:11,strokeWidth:2}),(0,I.jsx)(`span`,{children:`New story`})]})]}),(0,I.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto pb-2`,children:[t.cards.length===0?(0,I.jsx)(`div`,{className:`border border-dashed border-line-subtle p-3 text-center text-[11px] text-subtle`,children:`none`}):t.cards.map(e=>{let{issue:t}=e,n=S(t)?t.taskId:void 0;return(0,I.jsxs)(`div`,{className:`group/wrap relative`,children:[(0,I.jsx)(m,{issue:t,onOpen:()=>r(t),onDelete:()=>a(t)}),n&&(0,I.jsxs)(`button`,{type:`button`,onClick:()=>i(n),"aria-label":`Open task for issue #${t.id}`,title:`Started — open task`,className:`absolute bottom-2 right-2 flex items-center gap-1 border border-line bg-surface px-1.5 py-0.5 text-[10px] text-subtle opacity-0 transition-opacity hover:border-primary hover:text-fg focus-visible:opacity-100 group-hover/wrap:opacity-100`,children:[(0,I.jsx)(f,{size:10,strokeWidth:1.8}),(0,I.jsx)(`span`,{children:`open task`})]})]},`issue:${t.id}`)}),t.hiddenCount>0&&(0,I.jsxs)(`div`,{className:`p-2 text-center text-[10px] text-subtle`,children:[`+`,t.hiddenCount,` more — finish stories to thin this column`]})]})]})}function ie({board:e,onNewIssue:t,onPeekIssue:n,onOpenTask:r,onDeleteIssue:i}){return(0,I.jsx)(`div`,{className:`flex h-full min-w-max gap-4`,children:e.columns.map(a=>(0,I.jsx)(L,{repo:e.repo,column:a,onNewIssue:a.key===`backlog`?()=>t(e.repo):void 0,onPeekIssue:n,onOpenTask:r,onDeleteIssue:t=>i(e.repo,t)},a.key))})}function R(){let{tasks:e,hydrated:n,daemonConnected:r}=l(),{query:d,repo:f}=N(),m=i(),S=(0,k.useRef)(null),[C,T]=(0,k.useState)(null),[E,A]=(0,k.useState)(null),[j,M]=(0,k.useState)(null),[L,R]=(0,k.useState)([]);(0,k.useEffect)(()=>{let e=!1;return ne().then(t=>{e||R(t)}).catch(e=>o(`load projects`,e)),()=>{e=!0}},[]);let z=(0,k.useMemo)(()=>O(e,L),[e,L]),B=(0,k.useMemo)(()=>z.map(e=>e.repo),[z]),V=(0,k.useMemo)(()=>D(z,f),[z,f]),{data:H,pending:U,refresh:W}=p(B),{issueBusy:G,quickStartingId:K,pendingLinks:q,saveIssue:J,deleteIssueConfirmed:ae,quickStart:oe}=re({issueRepos:B,issueData:H,refreshIssues:W}),{allIssues:Y,repoChips:se,projectBoards:X,shownCount:Z,hasAnyCard:Q}=(0,k.useMemo)(()=>w({issueData:H,issueRepos:B,pendingLinks:q,query:d,repoFilter:V}),[H,B,q,d,V]);(0,k.useEffect)(()=>{C&&(Y.some(e=>e.repo===C.repo&&e.issue.id===C.id)||T(null))},[Y,C]),(0,k.useEffect)(()=>{let e=e=>{if(C||E||j||e.metaKey||e.ctrlKey||e.altKey)return;let t=e.target,n=!!t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.tagName===`SELECT`||t.isContentEditable);e.key===`/`&&!n?(e.preventDefault(),S.current?.focus()):e.key===`Escape`&&t===S.current&&d&&(e.preventDefault(),P(``))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[d,C,E,j]),(0,k.useEffect)(()=>{f!==V&&F(V)},[V,f]);let ce=!!d,$=e=>{t(e),u(e),m({to:`/task/$taskId`,params:{taskId:e}})};return(0,I.jsxs)(`div`,{className:`flex h-screen flex-col overflow-hidden bg-bg text-fg`,children:[(0,I.jsxs)(`header`,{"data-kobe-topbar":!0,className:`flex h-10 shrink-0 items-center gap-3 border-b border-line bg-surface px-3`,children:[(0,I.jsx)(ee,{}),(0,I.jsx)(`span`,{className:`font-mono text-[13px] font-bold text-primary`,children:`[rove]`}),(0,I.jsx)(c,{}),(0,I.jsxs)(`label`,{className:`flex h-7 items-center gap-1.5 border border-line bg-bg px-2 text-muted focus-within:border-line-active`,children:[(0,I.jsx)(y,{size:13,strokeWidth:1.8,className:`shrink-0 text-subtle`}),(0,I.jsx)(`input`,{ref:S,value:d,onChange:e=>P(e.target.value),placeholder:`Filter stories ( / )`,className:`w-44 bg-transparent text-[12px] text-fg placeholder:text-subtle focus:outline-none`}),d&&(0,I.jsx)(`button`,{type:`button`,onClick:()=>P(``),className:`shrink-0 text-subtle hover:text-fg`,"aria-label":`clear filter`,title:`Clear filter`,children:(0,I.jsx)(b,{size:13,strokeWidth:2})})]}),z.length>0&&(0,I.jsxs)(`label`,{className:`flex h-7 min-w-0 max-w-[24rem] items-center gap-1.5 border border-line bg-bg px-2 text-muted focus-within:border-line-active`,children:[(0,I.jsx)(`span`,{className:`shrink-0 text-[10px] font-bold uppercase tracking-[0.12em] text-subtle`,children:`Project`}),(0,I.jsx)(`select`,{value:V??``,onChange:e=>F(e.target.value),title:V??`Select project`,className:`min-w-0 flex-1 bg-transparent font-mono text-[11px] text-fg focus:outline-none`,children:z.map(e=>{let t=se.find(t=>t.repo===e.repo)?.count??0;return(0,I.jsxs)(`option`,{value:e.repo,title:e.repo,className:`bg-surface text-fg`,children:[e.label,` · `,t,` · `,e.repo]},e.repo)})})]}),(0,I.jsx)(`div`,{className:`ml-auto flex items-center gap-3 font-mono text-[11px] text-subtle`,children:(0,I.jsxs)(`span`,{children:[Z,` stor`,Z===1?`y`:`ies`]})})]}),(0,I.jsx)(s,{}),(0,I.jsx)(`div`,{className:`min-h-0 flex-1 overflow-x-auto overflow-y-hidden p-4`,children:!n||U&&!Q?(0,I.jsx)(`p`,{className:`text-[12px] text-subtle`,children:`Loading…`}):Z===0&&ce&&Q?(0,I.jsxs)(`div`,{className:`text-[12px] leading-relaxed text-subtle`,children:[(0,I.jsx)(`p`,{children:`No stories match.`}),(0,I.jsx)(`button`,{type:`button`,onClick:()=>{P(``)},className:`mt-3 border border-line bg-surface px-2 py-1 text-[11px] text-muted hover:border-primary hover:text-fg`,children:`Clear filters`})]}):Z===0&&!r?(0,I.jsx)(`p`,{className:`text-[12px] text-subtle`,children:`Can't reach the daemon — issue list may be incomplete.`}):X[0]?(0,I.jsx)(ie,{board:X[0],onNewIssue:A,onPeekIssue:e=>T({repo:X[0].repo,id:e.id}),onOpenTask:$,onDeleteIssue:(e,t)=>M({repo:e,issue:t})}):(0,I.jsxs)(`div`,{className:`text-[12px] leading-relaxed text-subtle`,children:[(0,I.jsx)(`p`,{children:`No projects yet. Create a task from the workspace to track stories against its repo.`}),(0,I.jsx)(`div`,{className:`mt-3 flex items-center gap-2`,children:(0,I.jsx)(`button`,{type:`button`,onClick:()=>m({to:`/`}),className:`border border-line bg-surface px-2 py-1 text-[11px] text-muted hover:border-primary hover:text-fg`,children:`Back to workspace`})})]})}),(()=>{let e=V??X[0]?.repo??B[0];return e?(0,I.jsx)(`button`,{type:`button`,onClick:()=>A(e),title:`New story`,"aria-label":`New story`,className:`fixed bottom-6 right-6 z-20 flex h-12 w-12 items-center justify-center rounded-full border border-primary bg-primary text-bg shadow-lg transition-transform hover:scale-105`,children:(0,I.jsx)(v,{size:22,strokeWidth:2.2})}):null})(),E&&(0,I.jsx)(_,{children:(0,I.jsx)(h,{repoRoot:E,open:!0,onClose:()=>A(null),onCreated:(e,t)=>{E&&W([E]),a(`success`,t?`Story #${e.id} created — starting its session`:`Story #${e.id} created`)}})}),(()=>{if(!C)return null;let e=Y.find(e=>e.repo===C.repo&&e.issue.id===C.id);return e?(0,I.jsx)(_,{children:(0,I.jsx)(g,{issue:e.issue,repoRoot:e.repo,busy:G,starting:K===e.issue.id,onClose:()=>T(null),onSave:t=>J(e.repo,e.issue.id,t),onStart:async({vendor:t,effort:n,placement:r,watch:i})=>{let a=await oe(e.repo,e.issue,t,n,r);i&&a?(T(null),$(a)):T(null)},onOpenSession:e.issue.taskId?()=>{let t=e.issue.taskId;T(null),t&&$(t)}:void 0,onPromptMerge:e.issue.taskId?()=>{let t=e.issue.taskId;t&&te(t,e.issue).then(()=>a(`success`,`Prompt inserted for story #${e.issue.id}`)).catch(e=>o(`prompt issue merge`,e))}:void 0},`${e.repo}:${e.issue.id}`)}):null})(),j&&(0,I.jsx)(x,{title:`Delete issue`,body:`Delete issue #${j.issue.id}: "${j.issue.title}"? This removes it from the daemon issue tracker only; it does not delete any task, branch, worktree, or engine session.`,confirmLabel:`Delete`,danger:!0,busy:G,onConfirm:()=>void ae(j.repo,j.issue).then(e=>{e&&(M(null),C?.repo===j.repo&&C.id===j.issue.id&&T(null))}),onCancel:()=>M(null)})]})}export{R as Board};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ChatTerminal-MCI1aBbT.js","assets/terminal-qBEkzc-m.js","assets/tabs-Dx-TnbvG.js","assets/createLucideIcon-CM5xLVj1.js","assets/store-uT65Mask.js","assets/rotate-cw-D-UUtiD0.js","assets/web-transport-D0bugxxv.js","assets/ChatTerminal-BrP-ENHg.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{l as e}from"./terminal-qBEkzc-m.js";import{c as t,y as n}from"./tabs-Dx-TnbvG.js";import{d as r,t as i}from"./createLucideIcon-CM5xLVj1.js";import{i as a}from"./store-uT65Mask.js";import{t as o}from"./ChatTranscript-DLthbnmB.js";import{t as s}from"./external-link-BwT2u1hD.js";import{t as c}from"./x-7cB9X7Hi.js";import{n as l,t as u}from"./activity-BjTd1D8q.js";import{t as d}from"./use-focus-trap-DNMrlNR0.js";var f=i(`clipboard-check`,[[`rect`,{width:`8`,height:`4`,x:`8`,y:`2`,rx:`1`,ry:`1`,key:`tgr4d6`}],[`path`,{d:`M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2`,key:`116196`}],[`path`,{d:`m9 14 2 2 4-4`,key:`df797q`}]]),p=i(`git-pull-request`,[[`circle`,{cx:`18`,cy:`18`,r:`3`,key:`1xkwt0`}],[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`path`,{d:`M13 6h3a2 2 0 0 1 2 2v7`,key:`1yeb86`}],[`line`,{x1:`6`,x2:`6`,y1:`9`,y2:`21`,key:`rroup`}]]),m=e(n(),1),h=r(),g=(0,m.lazy)(()=>a(()=>import(`./ChatTerminal-MCI1aBbT.js`).then(e=>({default:e.ChatTerminal})),__vite__mapDeps([0,1,2,3,4,5,6,7])));function _({task:e,engine:n,onClose:r,onOpenWorkspace:i,onReview:a,onCreatePr:_}){let[v,y]=(0,m.useState)(`engine`),[b]=(0,m.useState)(()=>t(e.id)),x=(0,m.useRef)(null);d(x,!0),(0,m.useEffect)(()=>{let e=e=>{if(e.key!==`Escape`)return;let t=e.target;t?.closest(`.xterm`)||t&&(t.tagName===`TEXTAREA`||t.tagName===`INPUT`)||(e.preventDefault(),r())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[r]);let S=l(n?.state),C=e=>`border-b-2 px-2 py-1.5 text-[11px] transition-colors ${e?`border-primary text-fg`:`border-transparent text-muted hover:text-fg`}`;return(0,h.jsxs)(`div`,{className:`fixed inset-0 z-40 flex justify-end`,children:[(0,h.jsx)(`button`,{type:`button`,"aria-label":`Close peek`,onClick:r,className:`absolute inset-0 cursor-default bg-black/40`}),(0,h.jsxs)(`div`,{ref:x,role:`dialog`,"aria-modal":`true`,"aria-label":`Session peek: ${e.title||e.branch||e.id}`,className:`relative flex h-full w-[640px] max-w-[92vw] flex-col border-l border-line bg-bg shadow-2xl`,children:[(0,h.jsxs)(`header`,{className:`flex h-10 shrink-0 items-center gap-2 border-b border-line bg-surface px-3`,children:[(0,h.jsx)(`span`,{className:`h-1.5 w-1.5 shrink-0 rounded-full ${u(n?.state)}`}),(0,h.jsx)(`span`,{className:`min-w-0 truncate text-[13px] text-fg`,children:e.title||e.branch||e.id}),(0,h.jsx)(`span`,{className:`hidden min-w-0 truncate font-mono text-[11px] text-subtle sm:inline`,children:e.branch}),S&&(0,h.jsx)(`span`,{className:`shrink-0 text-[11px] text-muted`,children:S}),(0,h.jsxs)(`div`,{className:`ml-auto flex shrink-0 items-center gap-2`,children:[a&&(0,h.jsxs)(`button`,{type:`button`,onClick:a,className:`flex items-center gap-1 text-muted transition-colors hover:text-fg`,title:`Review → done if it passes`,children:[(0,h.jsx)(f,{size:13,strokeWidth:1.8}),(0,h.jsx)(`span`,{className:`text-[11px]`,children:`Review`})]}),_&&(0,h.jsxs)(`button`,{type:`button`,onClick:_,className:`flex items-center gap-1 text-muted transition-colors hover:text-fg`,title:`Open a PR for this branch`,children:[(0,h.jsx)(p,{size:13,strokeWidth:1.8}),(0,h.jsx)(`span`,{className:`text-[11px]`,children:`PR`})]}),(0,h.jsxs)(`button`,{type:`button`,onClick:i,className:`flex items-center gap-1 text-muted transition-colors hover:text-fg`,title:`Open in workspace`,children:[(0,h.jsx)(s,{size:13,strokeWidth:1.8}),(0,h.jsx)(`span`,{className:`text-[11px]`,children:`Workspace`})]}),(0,h.jsx)(`button`,{type:`button`,onClick:r,className:`flex items-center text-muted transition-colors hover:text-fg`,"aria-label":`Close peek`,title:`Close (Esc)`,children:(0,h.jsx)(c,{size:15,strokeWidth:1.8})})]})]}),(0,h.jsxs)(`nav`,{className:`flex shrink-0 items-center gap-1 border-b border-line bg-surface px-2`,children:[(0,h.jsx)(`button`,{type:`button`,onClick:()=>y(`engine`),className:C(v===`engine`),children:`Engine`}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>y(`transcript`),className:C(v===`transcript`),children:`Transcript`})]}),(0,h.jsx)(`div`,{className:`min-h-0 flex-1`,children:v===`engine`?(0,h.jsx)(m.Suspense,{fallback:(0,h.jsx)(`div`,{className:`flex h-full items-center justify-center text-[12px] text-subtle`,children:`Loading terminal…`}),children:(0,h.jsx)(g,{tabId:b,taskId:e.id,mode:`engine`},b)}):(0,h.jsx)(o,{worktreePath:e.worktreePath,vendor:e.vendor??`claude`,title:e.title||e.branch})})]})]})}export{_ as BoardPeek};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}
|