taskproof 0.3.0__py3-none-any.whl

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.
Files changed (51) hide show
  1. taskproof/__init__.py +23 -0
  2. taskproof/__main__.py +8 -0
  3. taskproof/adapters/__init__.py +101 -0
  4. taskproof/adapters/base.py +228 -0
  5. taskproof/adapters/claude.py +46 -0
  6. taskproof/adapters/codex.py +140 -0
  7. taskproof/adapters/custom.py +61 -0
  8. taskproof/adapters/gemini.py +45 -0
  9. taskproof/adapters/opencode.py +46 -0
  10. taskproof/api/__init__.py +1 -0
  11. taskproof/api/server.py +822 -0
  12. taskproof/cli.py +1400 -0
  13. taskproof/concurrency.py +329 -0
  14. taskproof/dispatch.py +2289 -0
  15. taskproof/errors.py +55 -0
  16. taskproof/ledger.py +185 -0
  17. taskproof/models.py +155 -0
  18. taskproof/registry.py +1585 -0
  19. taskproof/schemas/result.json +58 -0
  20. taskproof/sql/schema.sql +70 -0
  21. taskproof/storage.py +372 -0
  22. taskproof/verify.py +615 -0
  23. taskproof/web/assets/MatrixView-BM8nu9s2.css +446 -0
  24. taskproof/web/assets/MatrixView-BM8nu9s2.css.gz +0 -0
  25. taskproof/web/assets/MatrixView-BMsawnxh.js +475 -0
  26. taskproof/web/assets/MatrixView-BMsawnxh.js.gz +0 -0
  27. taskproof/web/assets/ProjectsView-BcXcx5Gw.js +302 -0
  28. taskproof/web/assets/ProjectsView-BcXcx5Gw.js.gz +0 -0
  29. taskproof/web/assets/ProjectsView-CqNFL-fi.css +23 -0
  30. taskproof/web/assets/SettingsView-D_-waf0s.js +585 -0
  31. taskproof/web/assets/SettingsView-D_-waf0s.js.gz +0 -0
  32. taskproof/web/assets/SettingsView-aqTS3ubB.css +19 -0
  33. taskproof/web/assets/TaskDrawer-6JoGTH0s.js +597 -0
  34. taskproof/web/assets/TaskDrawer-6JoGTH0s.js.gz +0 -0
  35. taskproof/web/assets/TaskDrawer-N299VKzd.css +465 -0
  36. taskproof/web/assets/TaskDrawer-N299VKzd.css.gz +0 -0
  37. taskproof/web/assets/TasksView-BWhSHCHi.js +114 -0
  38. taskproof/web/assets/TasksView-BWhSHCHi.js.gz +0 -0
  39. taskproof/web/assets/TasksView-Bn08731V.css +30 -0
  40. taskproof/web/assets/icon-Dw-ohsdc.png +0 -0
  41. taskproof/web/assets/index-B-PLdDbR.js +75421 -0
  42. taskproof/web/assets/index-B-PLdDbR.js.gz +0 -0
  43. taskproof/web/assets/index-NKj7kbYl.css +1234 -0
  44. taskproof/web/assets/index-NKj7kbYl.css.gz +0 -0
  45. taskproof/web/index.html +23 -0
  46. taskproof-0.3.0.dist-info/METADATA +470 -0
  47. taskproof-0.3.0.dist-info/RECORD +51 -0
  48. taskproof-0.3.0.dist-info/WHEEL +5 -0
  49. taskproof-0.3.0.dist-info/entry_points.txt +2 -0
  50. taskproof-0.3.0.dist-info/licenses/LICENSE +201 -0
  51. taskproof-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,597 @@
1
+ import { d as defineComponent, c as createElementBlock, F as Fragment, y as createTextVNode, t as toDisplayString, h as computed, o as openBlock, V as metaFor, _ as _export_sfc, i as useBoardStore, u as useI18n, k as watch, W as onBeforeUnmount, x as createBlock, l as withCtx, f as unref, U as ref, p as resolveComponent, b as createBaseVNode, e as createVNode, w as withKeys, a as withModifiers, n as normalizeClass, X as withDirectives, Y as vShow, r as renderList, g as createCommentVNode, Z as formatBytes, $ as byteLength, a0 as LOG_MAX_LINES, a1 as highlightSegments, a2 as shouldStickBottom, a3 as nextTick, s as useRoute, v as useRouter, a4 as ABNORMAL, a5 as countMatches, a6 as matchLineIndexes, a7 as stripAnsi } from "./index-B-PLdDbR.js";
2
+ const _hoisted_1$1 = ["data-status", "data-shape"];
3
+ const _hoisted_2$1 = {
4
+ key: 0,
5
+ class: "dot"
6
+ };
7
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
8
+ __name: "StatusMark",
9
+ props: {
10
+ status: {},
11
+ shape: { default: "glyph" }
12
+ },
13
+ setup(__props) {
14
+ const props = __props;
15
+ const meta = computed(() => metaFor(props.status));
16
+ return (_ctx, _cache) => {
17
+ return openBlock(), createElementBlock("span", {
18
+ class: "tp-mark",
19
+ "data-status": meta.value.id,
20
+ "data-shape": __props.shape
21
+ }, [
22
+ __props.shape === "dot" ? (openBlock(), createElementBlock("span", _hoisted_2$1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
23
+ createTextVNode(toDisplayString(meta.value.glyph), 1)
24
+ ], 64))
25
+ ], 8, _hoisted_1$1);
26
+ };
27
+ }
28
+ });
29
+ const StatusMark = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-7a91d873"]]);
30
+ function shortTime(value) {
31
+ if (!value) return "—";
32
+ const match = value.match(/T(\d{2}:\d{2}:\d{2})/);
33
+ return match ? match[1] : value;
34
+ }
35
+ function duration(startedAt, finishedAt) {
36
+ if (!startedAt) return "—";
37
+ const start = Date.parse(startedAt);
38
+ const end = finishedAt ? Date.parse(finishedAt) : Date.now();
39
+ if (Number.isNaN(start) || Number.isNaN(end)) return "—";
40
+ const total = Math.max(0, Math.round((end - start) / 1e3));
41
+ const minutes = Math.floor(total / 60);
42
+ const seconds = total % 60;
43
+ return `${minutes}m${String(seconds).padStart(2, "0")}s`;
44
+ }
45
+ function payloadLine(payload) {
46
+ if (payload == null) return "";
47
+ if (typeof payload !== "object") return String(payload);
48
+ const parts = [];
49
+ for (const [key, value] of Object.entries(payload)) {
50
+ if (value === null || value === void 0 || value === "") continue;
51
+ if (Array.isArray(value)) {
52
+ parts.push(`${key} ${value.length}`);
53
+ } else if (typeof value === "object") {
54
+ parts.push(`${key} {...}`);
55
+ } else {
56
+ parts.push(`${key} ${String(value)}`);
57
+ }
58
+ }
59
+ return parts.join(" · ");
60
+ }
61
+ function eventSummary(name, payload) {
62
+ const p = payload ?? {};
63
+ const cap = (value, limit = 160) => value.length > limit ? `${value.slice(0, limit)}…` : value;
64
+ switch (name) {
65
+ case "started":
66
+ return [p.adapter, p.group, p.worktree ? "worktree" : null].filter(Boolean).join(" · ");
67
+ case "result_schema":
68
+ if (p.enabled === false) return "off";
69
+ return String(p.path ?? "").split("/").pop() || "—";
70
+ case "adapter":
71
+ return [
72
+ p.exit_code != null ? `exit ${p.exit_code}` : null,
73
+ p.degraded ? "degraded" : null
74
+ ].filter(Boolean).join(" · ");
75
+ case "verify":
76
+ return [p.status, p.exit_code != null ? `exit ${p.exit_code}` : null].filter(Boolean).join(" · ");
77
+ case "done":
78
+ return [p.verify, p.files_changed != null ? String(p.files_changed) : null].filter(Boolean).join(" · ");
79
+ case "failed":
80
+ return cap(String(p.reason ?? p.stage ?? payloadLine(payload)));
81
+ case "forbidden": {
82
+ const paths = Array.isArray(p.paths) ? p.paths.join(", ") : "";
83
+ return cap(paths || payloadLine(payload));
84
+ }
85
+ default:
86
+ return cap(payloadLine(payload));
87
+ }
88
+ }
89
+ function isBadEvent(name, payload) {
90
+ const p = payload ?? {};
91
+ if (["failed", "forbidden", "blocked", "timeout", "cancelled"].includes(name)) return true;
92
+ if (name === "verify") return p.status === "FAILED";
93
+ if (name === "adapter") return typeof p.exit_code === "number" && p.exit_code !== 0;
94
+ return false;
95
+ }
96
+ const DRAWER_MOUNT_RETRIES = 3;
97
+ function shouldRetryDrawerMount(state, retries = DRAWER_MOUNT_RETRIES) {
98
+ return state.open && !state.mounted && state.attempt < retries;
99
+ }
100
+ function drawerMountKey(attempt) {
101
+ return `drawer-${attempt}`;
102
+ }
103
+ const _hoisted_1 = { class: "dh" };
104
+ const _hoisted_2 = ["data-status"];
105
+ const _hoisted_3 = { class: "cid" };
106
+ const _hoisted_4 = { class: "dur" };
107
+ const _hoisted_5 = ["aria-label"];
108
+ const _hoisted_6 = {
109
+ class: "dtabs",
110
+ role: "tablist"
111
+ };
112
+ const _hoisted_7 = ["aria-selected"];
113
+ const _hoisted_8 = ["aria-selected"];
114
+ const _hoisted_9 = { class: "dbody" };
115
+ const _hoisted_10 = { class: "sec" };
116
+ const _hoisted_11 = { class: "full" };
117
+ const _hoisted_12 = { class: "sec" };
118
+ const _hoisted_13 = ["data-off"];
119
+ const _hoisted_14 = { class: "tl" };
120
+ const _hoisted_15 = { class: "t" };
121
+ const _hoisted_16 = { class: "k" };
122
+ const _hoisted_17 = { class: "g" };
123
+ const _hoisted_18 = {
124
+ key: 0,
125
+ class: "d"
126
+ };
127
+ const _hoisted_19 = {
128
+ key: 0,
129
+ class: "ev"
130
+ };
131
+ const _hoisted_20 = {
132
+ key: 0,
133
+ class: "sec"
134
+ };
135
+ const _hoisted_21 = { class: "vrow" };
136
+ const _hoisted_22 = { class: "vlabel" };
137
+ const _hoisted_23 = {
138
+ key: 0,
139
+ class: "vcmd"
140
+ };
141
+ const _hoisted_24 = {
142
+ key: 0,
143
+ class: "side claim"
144
+ };
145
+ const _hoisted_25 = { class: "body" };
146
+ const _hoisted_26 = {
147
+ key: 1,
148
+ class: "rule"
149
+ };
150
+ const _hoisted_27 = { class: "side ev" };
151
+ const _hoisted_28 = { class: "logpanel" };
152
+ const _hoisted_29 = { class: "logbar" };
153
+ const _hoisted_30 = ["value", "placeholder", "aria-label"];
154
+ const _hoisted_31 = { class: "logcount" };
155
+ const _hoisted_32 = ["aria-label", "disabled"];
156
+ const _hoisted_33 = ["aria-label", "disabled"];
157
+ const _hoisted_34 = { class: "logscope" };
158
+ const _hoisted_35 = {
159
+ key: 0,
160
+ class: "lognone"
161
+ };
162
+ const _hoisted_36 = {
163
+ key: 0,
164
+ class: "lognote"
165
+ };
166
+ const _hoisted_37 = {
167
+ key: 1,
168
+ class: "lognote"
169
+ };
170
+ const _hoisted_38 = {
171
+ key: 2,
172
+ class: "logerr"
173
+ };
174
+ const _hoisted_39 = {
175
+ key: 0,
176
+ class: "logempty"
177
+ };
178
+ const _hoisted_40 = ["data-line"];
179
+ const _hoisted_41 = {
180
+ key: 1,
181
+ class: "none"
182
+ };
183
+ const _sfc_main = /* @__PURE__ */ defineComponent({
184
+ __name: "TaskDrawer",
185
+ setup(__props) {
186
+ const store = useBoardStore();
187
+ const route = useRoute();
188
+ const router = useRouter();
189
+ const { t, te } = useI18n();
190
+ const open = computed(() => typeof route.params.taskId === "string" && route.params.taskId !== "");
191
+ const task = computed(() => store.detail?.task ?? null);
192
+ const events = computed(() => store.detail?.events ?? []);
193
+ const tab = computed(() => route.query.tab === "log" ? "log" : "overview");
194
+ const liveTask = computed(() => {
195
+ const status = task.value?.status;
196
+ return store.polling && (status === "running" || status === "verifying");
197
+ });
198
+ const timeline = computed(
199
+ () => events.value.map((event) => ({
200
+ t: shortTime(event.ts),
201
+ k: te(`event.${event.event}`) ? t(`event.${event.event}`) : event.event,
202
+ g: event.event === "adapter" || event.event === "verify" ? "" : "",
203
+ d: eventSummary(event.event, event.payload),
204
+ bad: isBadEvent(event.event, event.payload)
205
+ }))
206
+ );
207
+ const verify = computed(() => task.value?.verify_exit ?? null);
208
+ const verifyText = computed(
209
+ () => verify.value == null ? t("ev.notrun") : `exit ${verify.value}`
210
+ );
211
+ const dur = computed(() => duration(task.value?.started_at ?? null, task.value?.finished_at ?? null));
212
+ const started = computed(() => shortTime(task.value?.started_at));
213
+ const ended = computed(() => task.value?.finished_at ? shortTime(task.value.finished_at) : t("drawer.now"));
214
+ function close() {
215
+ const name = typeof route.name === "string" ? route.name : "matrix";
216
+ void router.push({ name, query: route.query });
217
+ }
218
+ function go(nextTab) {
219
+ const name = typeof route.name === "string" ? route.name : "matrix";
220
+ const id = typeof route.params.taskId === "string" ? route.params.taskId : "";
221
+ const query2 = { ...route.query };
222
+ if (nextTab === "log") query2.tab = "log";
223
+ else delete query2.tab;
224
+ void router.push({ name, params: { taskId: id }, query: query2 });
225
+ }
226
+ function onVisible(value) {
227
+ if (!value) close();
228
+ }
229
+ const showClaim = computed(() => ABNORMAL.includes(task.value?.status ?? ""));
230
+ const logDisplay = computed(() => stripAnsi(store.logText));
231
+ const logLines = computed(() => logDisplay.value === "" ? [] : logDisplay.value.split("\n"));
232
+ const query = ref("");
233
+ const matchCount = computed(() => countMatches(logDisplay.value, query.value));
234
+ const hitLines = computed(() => matchLineIndexes(logDisplay.value, query.value));
235
+ const currentHit = ref(0);
236
+ const hitPosition = computed(() => matchCount.value ? currentHit.value + 1 : 0);
237
+ watch(query, () => currentHit.value = 0);
238
+ const logEl = ref(null);
239
+ const stuck = ref(true);
240
+ const newLines = ref(0);
241
+ function onLogScroll() {
242
+ const el = logEl.value;
243
+ if (!el) return;
244
+ if (shouldStickBottom(el.scrollTop, el.scrollHeight, el.clientHeight)) {
245
+ stuck.value = true;
246
+ newLines.value = 0;
247
+ } else {
248
+ stuck.value = false;
249
+ }
250
+ }
251
+ function scrollToBottom() {
252
+ const el = logEl.value;
253
+ if (el) el.scrollTop = el.scrollHeight;
254
+ }
255
+ watch(
256
+ () => logDisplay.value,
257
+ async (now, before) => {
258
+ if (before === void 0 || now === before) return;
259
+ const beforeLines = before === "" ? 0 : before.split("\n").length;
260
+ const afterLines = logLines.value.length;
261
+ await nextTick();
262
+ if (stuck.value) scrollToBottom();
263
+ else if (afterLines > beforeLines) newLines.value += afterLines - beforeLines;
264
+ }
265
+ );
266
+ watch(
267
+ () => store.logTaskId,
268
+ () => {
269
+ stuck.value = true;
270
+ newLines.value = 0;
271
+ query.value = "";
272
+ void nextTick(scrollToBottom);
273
+ }
274
+ );
275
+ function jumpBottom() {
276
+ stuck.value = true;
277
+ newLines.value = 0;
278
+ scrollToBottom();
279
+ void nextTick(scrollToBottom);
280
+ }
281
+ function isCurrentHitLine(index) {
282
+ return hitLines.value[currentHit.value] === index;
283
+ }
284
+ function scrollHitIntoView() {
285
+ const el = logEl.value;
286
+ const line = hitLines.value[currentHit.value];
287
+ if (!el || line == null) return;
288
+ const target = el.querySelector(`[data-line="${line}"]`);
289
+ if (!target) return;
290
+ const delta = target.getBoundingClientRect().top - el.getBoundingClientRect().top;
291
+ el.scrollTop += delta - el.clientHeight / 2 + target.clientHeight / 2;
292
+ }
293
+ function goToHit(index) {
294
+ const total = hitLines.value.length;
295
+ if (!total) return;
296
+ currentHit.value = (index % total + total) % total;
297
+ void nextTick(scrollHitIntoView);
298
+ }
299
+ function nextHit() {
300
+ goToHit(currentHit.value + 1);
301
+ }
302
+ function prevHit() {
303
+ goToHit(currentHit.value - 1);
304
+ }
305
+ function onQuery(value) {
306
+ query.value = value;
307
+ }
308
+ const copied = ref(false);
309
+ let copiedTimer;
310
+ async function copyLog() {
311
+ if (!navigator.clipboard) return;
312
+ try {
313
+ await navigator.clipboard.writeText(store.logText);
314
+ copied.value = true;
315
+ if (copiedTimer) clearTimeout(copiedTimer);
316
+ copiedTimer = setTimeout(() => copied.value = false, 1200);
317
+ } catch {
318
+ }
319
+ }
320
+ watch(
321
+ [open, tab, () => route.params.taskId],
322
+ ([isOpen, whichTab, id]) => {
323
+ if (isOpen && whichTab === "log" && typeof id === "string" && id) store.startLog(id);
324
+ else store.stopLog();
325
+ },
326
+ { immediate: true }
327
+ );
328
+ onBeforeUnmount(() => {
329
+ store.stopLog();
330
+ if (copiedTimer) clearTimeout(copiedTimer);
331
+ });
332
+ let lastFocused = null;
333
+ watch(open, (isOpen) => {
334
+ if (isOpen) {
335
+ lastFocused = document.activeElement ?? null;
336
+ } else {
337
+ const target = lastFocused;
338
+ lastFocused = null;
339
+ void nextTick(() => target?.focus?.());
340
+ }
341
+ });
342
+ watch(
343
+ () => route.params.taskId,
344
+ (id) => {
345
+ if (typeof id === "string" && id) void store.openTask(id);
346
+ else store.closeTask();
347
+ },
348
+ { immediate: true }
349
+ );
350
+ const mountAttempt = ref(0);
351
+ function drawerIsInDocument() {
352
+ return document.querySelector(".tp-drawer") !== null;
353
+ }
354
+ watch([open, mountAttempt], async () => {
355
+ if (!open.value) {
356
+ mountAttempt.value = 0;
357
+ return;
358
+ }
359
+ await nextTick();
360
+ if (shouldRetryDrawerMount({
361
+ open: open.value,
362
+ mounted: drawerIsInDocument(),
363
+ attempt: mountAttempt.value
364
+ })) {
365
+ mountAttempt.value += 1;
366
+ }
367
+ });
368
+ return (_ctx, _cache) => {
369
+ const _component_el_drawer = resolveComponent("el-drawer");
370
+ return openBlock(), createBlock(_component_el_drawer, {
371
+ key: unref(drawerMountKey)(mountAttempt.value),
372
+ "model-value": open.value,
373
+ size: 520,
374
+ direction: "rtl",
375
+ "with-header": false,
376
+ class: "tp-drawer",
377
+ "onUpdate:modelValue": onVisible
378
+ }, {
379
+ default: withCtx(() => [
380
+ task.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
381
+ createBaseVNode("div", _hoisted_1, [
382
+ createBaseVNode("span", {
383
+ class: "sc",
384
+ "data-status": task.value.status
385
+ }, [
386
+ createVNode(StatusMark, {
387
+ status: task.value.status,
388
+ shape: "dot"
389
+ }, null, 8, ["status"]),
390
+ createTextVNode(" " + toDisplayString(unref(t)(`status.${task.value.status}`)), 1)
391
+ ], 8, _hoisted_2),
392
+ createBaseVNode("span", _hoisted_3, toDisplayString(task.value.id), 1),
393
+ createBaseVNode("span", _hoisted_4, [
394
+ createTextVNode(toDisplayString(dur.value), 1),
395
+ _cache[8] || (_cache[8] = createBaseVNode("br", null, null, -1)),
396
+ createTextVNode(toDisplayString(started.value) + " → " + toDisplayString(ended.value), 1)
397
+ ]),
398
+ createBaseVNode("button", {
399
+ class: "x",
400
+ type: "button",
401
+ "aria-label": unref(t)("drawer.close"),
402
+ onClick: close
403
+ }, "✕", 8, _hoisted_5)
404
+ ]),
405
+ createBaseVNode("div", _hoisted_6, [
406
+ createBaseVNode("button", {
407
+ role: "tab",
408
+ type: "button",
409
+ "aria-selected": tab.value === "overview",
410
+ class: normalizeClass({ on: tab.value === "overview" }),
411
+ onClick: _cache[0] || (_cache[0] = ($event) => go("overview")),
412
+ onKeydown: [
413
+ _cache[1] || (_cache[1] = withKeys(withModifiers(($event) => go("overview"), ["prevent"]), ["enter"])),
414
+ _cache[2] || (_cache[2] = withKeys(withModifiers(($event) => go("overview"), ["prevent"]), ["space"]))
415
+ ]
416
+ }, toDisplayString(unref(t)("drawer.tab.overview")), 43, _hoisted_7),
417
+ createBaseVNode("button", {
418
+ role: "tab",
419
+ type: "button",
420
+ "aria-selected": tab.value === "log",
421
+ class: normalizeClass({ on: tab.value === "log" }),
422
+ onClick: _cache[3] || (_cache[3] = ($event) => go("log")),
423
+ onKeydown: [
424
+ _cache[4] || (_cache[4] = withKeys(withModifiers(($event) => go("log"), ["prevent"]), ["enter"])),
425
+ _cache[5] || (_cache[5] = withKeys(withModifiers(($event) => go("log"), ["prevent"]), ["space"]))
426
+ ]
427
+ }, toDisplayString(unref(t)("drawer.tab.log")), 43, _hoisted_8)
428
+ ]),
429
+ withDirectives(createBaseVNode("div", _hoisted_9, [
430
+ createBaseVNode("section", _hoisted_10, [
431
+ createBaseVNode("h4", null, toDisplayString(unref(t)("drawer.brief")), 1),
432
+ createBaseVNode("pre", _hoisted_11, toDisplayString(task.value.brief), 1)
433
+ ]),
434
+ createBaseVNode("section", _hoisted_12, [
435
+ createBaseVNode("h4", null, [
436
+ createTextVNode(toDisplayString(unref(t)("drawer.timeline")) + " ", 1),
437
+ createBaseVNode("span", {
438
+ class: "live",
439
+ "data-off": unref(store).polling ? null : ""
440
+ }, [
441
+ _cache[9] || (_cache[9] = createBaseVNode("i", null, null, -1)),
442
+ createTextVNode(toDisplayString(unref(store).polling ? unref(t)("live.on") : unref(t)("live.off")), 1)
443
+ ], 8, _hoisted_13)
444
+ ]),
445
+ createBaseVNode("ol", _hoisted_14, [
446
+ (openBlock(true), createElementBlock(Fragment, null, renderList(timeline.value, (entry, index) => {
447
+ return openBlock(), createElementBlock("li", {
448
+ key: index,
449
+ class: normalizeClass(["ev", { now: liveTask.value && index === timeline.value.length - 1, isbad: entry.bad }])
450
+ }, [
451
+ _cache[10] || (_cache[10] = createBaseVNode("span", { class: "dot" }, null, -1)),
452
+ createBaseVNode("span", _hoisted_15, toDisplayString(entry.t), 1),
453
+ createBaseVNode("span", _hoisted_16, toDisplayString(entry.k), 1),
454
+ createBaseVNode("span", _hoisted_17, toDisplayString(entry.g), 1),
455
+ entry.d ? (openBlock(), createElementBlock("span", _hoisted_18, toDisplayString(entry.d), 1)) : createCommentVNode("", true)
456
+ ], 2);
457
+ }), 128)),
458
+ !timeline.value.length ? (openBlock(), createElementBlock("li", _hoisted_19, [..._cache[11] || (_cache[11] = [
459
+ createBaseVNode("span", { class: "dot" }, null, -1),
460
+ createBaseVNode("span", { class: "t" }, "—", -1)
461
+ ])])) : createCommentVNode("", true)
462
+ ])
463
+ ]),
464
+ verify.value != null ? (openBlock(), createElementBlock("section", _hoisted_20, [
465
+ createBaseVNode("h4", null, [
466
+ createTextVNode(toDisplayString(unref(t)("drawer.verdict")), 1),
467
+ createBaseVNode("em", null, "— " + toDisplayString(unref(t)("verdict.by")), 1)
468
+ ]),
469
+ createBaseVNode("div", _hoisted_21, [
470
+ createBaseVNode("span", {
471
+ class: normalizeClass(["vdot", { bad: verify.value !== 0 }])
472
+ }, null, 2),
473
+ createBaseVNode("span", _hoisted_22, toDisplayString(unref(t)(verify.value === 0 ? "verdict.passed" : "verdict.failed")), 1),
474
+ createBaseVNode("span", {
475
+ class: normalizeClass(["vcode", { bad: verify.value !== 0 }])
476
+ }, "exit " + toDisplayString(verify.value), 3)
477
+ ]),
478
+ task.value.verify_cmd ? (openBlock(), createElementBlock("p", _hoisted_23, toDisplayString(task.value.verify_cmd), 1)) : createCommentVNode("", true)
479
+ ])) : createCommentVNode("", true),
480
+ createBaseVNode("div", {
481
+ class: normalizeClass(["duel", { solo: !showClaim.value }])
482
+ }, [
483
+ showClaim.value ? (openBlock(), createElementBlock("div", _hoisted_24, [
484
+ createBaseVNode("h5", null, toDisplayString(unref(t)("drawer.claim")), 1),
485
+ createBaseVNode("p", _hoisted_25, toDisplayString(task.value.reasoning || unref(t)("drawer.noClaim")), 1)
486
+ ])) : createCommentVNode("", true),
487
+ showClaim.value ? (openBlock(), createElementBlock("div", _hoisted_26)) : createCommentVNode("", true),
488
+ createBaseVNode("div", _hoisted_27, [
489
+ createBaseVNode("h5", null, toDisplayString(unref(t)("drawer.evidence")), 1),
490
+ createBaseVNode("dl", null, [
491
+ createBaseVNode("dt", null, toDisplayString(unref(t)("ev.exit")), 1),
492
+ createBaseVNode("dd", null, toDisplayString(task.value.exit_code ?? "—"), 1),
493
+ createBaseVNode("dt", null, toDisplayString(unref(t)("ev.verify")), 1),
494
+ createBaseVNode("dd", {
495
+ class: normalizeClass({ bad: verify.value != null && verify.value !== 0, good: verify.value === 0 })
496
+ }, toDisplayString(verifyText.value), 3),
497
+ createBaseVNode("dt", null, toDisplayString(unref(t)("ev.files")), 1),
498
+ createBaseVNode("dd", null, toDisplayString(task.value.files_changed_live ?? task.value.files_changed ?? 0), 1),
499
+ createBaseVNode("dt", null, toDisplayString(unref(t)("ev.adapter")), 1),
500
+ createBaseVNode("dd", null, toDisplayString(task.value.adapter ?? "—") + toDisplayString(task.value.model ? ` · ${task.value.model}` : ""), 1),
501
+ createBaseVNode("dt", null, toDisplayString(unref(t)("ev.group")), 1),
502
+ createBaseVNode("dd", null, toDisplayString(task.value.group_name ?? "—"), 1),
503
+ createBaseVNode("dt", null, toDisplayString(unref(t)("ev.lane")), 1),
504
+ createBaseVNode("dd", null, toDisplayString(task.value.project), 1)
505
+ ])
506
+ ])
507
+ ], 2)
508
+ ], 512), [
509
+ [vShow, tab.value === "overview"]
510
+ ]),
511
+ withDirectives(createBaseVNode("div", _hoisted_28, [
512
+ createBaseVNode("div", _hoisted_29, [
513
+ createBaseVNode("input", {
514
+ class: "logq",
515
+ type: "search",
516
+ value: query.value,
517
+ placeholder: unref(t)("log.search.placeholder"),
518
+ "aria-label": unref(t)("log.search.placeholder"),
519
+ onInput: _cache[6] || (_cache[6] = ($event) => onQuery($event.target.value))
520
+ }, null, 40, _hoisted_30),
521
+ createBaseVNode("span", _hoisted_31, toDisplayString(hitPosition.value) + " / " + toDisplayString(matchCount.value), 1),
522
+ createBaseVNode("button", {
523
+ type: "button",
524
+ class: "lognav",
525
+ "aria-label": unref(t)("log.search.prev"),
526
+ disabled: !matchCount.value,
527
+ onClick: prevHit
528
+ }, " ↑ ", 8, _hoisted_32),
529
+ createBaseVNode("button", {
530
+ type: "button",
531
+ class: "lognav",
532
+ "aria-label": unref(t)("log.search.next"),
533
+ disabled: !matchCount.value,
534
+ onClick: nextHit
535
+ }, " ↓ ", 8, _hoisted_33),
536
+ createBaseVNode("button", {
537
+ type: "button",
538
+ class: "logact",
539
+ onClick: copyLog
540
+ }, toDisplayString(copied.value ? unref(t)("log.copied") : unref(t)("log.copy")), 1),
541
+ createBaseVNode("button", {
542
+ type: "button",
543
+ class: "logact",
544
+ onClick: _cache[7] || (_cache[7] = ($event) => unref(store).refreshLog())
545
+ }, toDisplayString(unref(t)("log.refresh")), 1)
546
+ ]),
547
+ createBaseVNode("p", _hoisted_34, [
548
+ createTextVNode(toDisplayString(unref(t)("log.search.scope", { n: unref(formatBytes)(unref(byteLength)(unref(store).logText)) })) + " ", 1),
549
+ query.value && !matchCount.value ? (openBlock(), createElementBlock("span", _hoisted_35, toDisplayString(unref(t)("log.search.none")), 1)) : createCommentVNode("", true)
550
+ ]),
551
+ unref(store).logOmitted > 0 ? (openBlock(), createElementBlock("p", _hoisted_36, toDisplayString(unref(t)("log.omitted", { n: unref(formatBytes)(unref(store).logOmitted) })), 1)) : createCommentVNode("", true),
552
+ unref(store).logTruncated ? (openBlock(), createElementBlock("p", _hoisted_37, toDisplayString(unref(t)("log.truncated", { n: unref(LOG_MAX_LINES) })), 1)) : createCommentVNode("", true),
553
+ unref(store).logError ? (openBlock(), createElementBlock("p", _hoisted_38, toDisplayString(unref(store).logError), 1)) : createCommentVNode("", true),
554
+ createBaseVNode("div", {
555
+ ref_key: "logEl",
556
+ ref: logEl,
557
+ class: "logscroll",
558
+ onScroll: onLogScroll
559
+ }, [
560
+ !logLines.value.length && !unref(store).logError ? (openBlock(), createElementBlock("p", _hoisted_39, toDisplayString(unref(t)("log.empty")), 1)) : createCommentVNode("", true),
561
+ (openBlock(true), createElementBlock(Fragment, null, renderList(logLines.value, (line, index) => {
562
+ return openBlock(), createElementBlock("div", {
563
+ key: index,
564
+ class: normalizeClass(["logline", { cur: isCurrentHitLine(index) }]),
565
+ "data-line": index
566
+ }, [
567
+ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(highlightSegments)(line, query.value), (seg, si) => {
568
+ return openBlock(), createElementBlock("span", {
569
+ key: si,
570
+ class: normalizeClass({ hit: seg.hit })
571
+ }, toDisplayString(seg.text), 3);
572
+ }), 128))
573
+ ], 10, _hoisted_40);
574
+ }), 128))
575
+ ], 544),
576
+ !stuck.value ? (openBlock(), createElementBlock("button", {
577
+ key: 3,
578
+ type: "button",
579
+ class: "logjump",
580
+ onClick: jumpBottom
581
+ }, toDisplayString(unref(t)("log.jumpBottom", { n: newLines.value })), 1)) : createCommentVNode("", true)
582
+ ], 512), [
583
+ [vShow, tab.value === "log"]
584
+ ])
585
+ ], 64)) : (openBlock(), createElementBlock("p", _hoisted_41, toDisplayString(unref(t)("drawer.noTask")), 1))
586
+ ]),
587
+ _: 1
588
+ }, 8, ["model-value"]);
589
+ };
590
+ }
591
+ });
592
+ const TaskDrawer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-10de8666"]]);
593
+ export {
594
+ StatusMark as S,
595
+ TaskDrawer as T,
596
+ duration as d
597
+ };