@loicngr/kobo 2.1.0 → 2.1.2

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 (116) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/server/db/migrations.js +8 -0
  3. package/dist/server/db/schema.js +2 -0
  4. package/dist/server/routes/usage.js +28 -2
  5. package/dist/server/services/agent/engines/claude-code/engine.js +60 -7
  6. package/dist/server/services/agent/engines/codex/engine.js +1 -0
  7. package/dist/server/services/agent/engines/codex/options-builder.js +6 -1
  8. package/dist/server/services/agent/orchestrator.js +5 -1
  9. package/dist/server/services/review-service.js +6 -2
  10. package/dist/server/services/usage/reliability.js +24 -0
  11. package/package.json +10 -10
  12. package/src/client/dist/pwa/assets/ActivityFeed-CO5rOaa5.js +8 -0
  13. package/src/client/dist/pwa/assets/{ActivityFeed-BYR5x7aa.css → ActivityFeed-DCmiJP-z.css} +1 -1
  14. package/src/client/dist/pwa/assets/{ChangelogPage-BJdICFvz.js → ChangelogPage-DNRcPRtW.js} +1 -1
  15. package/src/client/dist/pwa/assets/{ClosePopup-CWjIRHxu.js → ClosePopup-BikuzYle.js} +1 -1
  16. package/src/client/dist/pwa/assets/{ComparisonPanel-2GLd8KIy.js → ComparisonPanel-DZoDqgJI.js} +1 -1
  17. package/src/client/dist/pwa/assets/{CreatePage-B9AdNJZj.js → CreatePage-wNH35uTG.js} +1 -1
  18. package/src/client/dist/pwa/assets/DashboardPage-DUyy4SzS.js +1 -0
  19. package/src/client/dist/pwa/assets/DashboardPage-XiCj24i2.css +1 -0
  20. package/src/client/dist/pwa/assets/{DiffViewer-X25vuf83.js → DiffViewer-CZ5QwXqi.js} +3 -3
  21. package/src/client/dist/pwa/assets/{DocumentsPanel-BastjrEm.js → DocumentsPanel-sBatgKA-.js} +1 -1
  22. package/src/client/dist/pwa/assets/{DrawerToggleButton-DbipGmBL.js → DrawerToggleButton-Dfvkaro0.js} +1 -1
  23. package/src/client/dist/pwa/assets/{GitPanel-CnW4iVao.js → GitPanel-B8e1olfm.js} +3 -3
  24. package/src/client/dist/pwa/assets/{HealthPage-aieNQly-.js → HealthPage-BwXYpczh.js} +1 -1
  25. package/src/client/dist/pwa/assets/MainLayout-DFXIS_wv.js +2 -0
  26. package/src/client/dist/pwa/assets/{MainLayout-Cc4XzCAy.css → MainLayout-gHENJEFQ.css} +1 -1
  27. package/src/client/dist/pwa/assets/{QBadge-FWC1zDCq.js → QBadge-CQF1smL-.js} +1 -1
  28. package/src/client/dist/pwa/assets/{QBanner-CcRI_QIy.js → QBanner-bdDA-A5g.js} +1 -1
  29. package/src/client/dist/pwa/assets/{QBtn-DEdx_Y1V.js → QBtn-CcQQrYA_.js} +1 -1
  30. package/src/client/dist/pwa/assets/{QBtnDropdown-BWy-rh45.js → QBtnDropdown-C-1EhO9J.js} +1 -1
  31. package/src/client/dist/pwa/assets/{QBtnGroup-CAoD6G0Q.js → QBtnGroup-wd5lKRXu.js} +1 -1
  32. package/src/client/dist/pwa/assets/{QBtnToggle-C_hQ2UCQ.js → QBtnToggle-BnC8rTql.js} +1 -1
  33. package/src/client/dist/pwa/assets/{QChip-DCPUhqXX.js → QChip-D75nKi-L.js} +1 -1
  34. package/src/client/dist/pwa/assets/{QExpansionItem-DfmdBGuW.js → QExpansionItem-RpMPvfxX.js} +1 -1
  35. package/src/client/dist/pwa/assets/{QItemSection-BhqphaH6.js → QItemSection-Bt9H35JJ.js} +1 -1
  36. package/src/client/dist/pwa/assets/{QList-CHm4JNP0.js → QList-D5msNbSZ.js} +1 -1
  37. package/src/client/dist/pwa/assets/{QMarkupTable-CNpiA9oq.js → QMarkupTable-D3REW6RC.js} +1 -1
  38. package/src/client/dist/pwa/assets/{QPage-BXBw2Alx.js → QPage-HAaeQ-cv.js} +1 -1
  39. package/src/client/dist/pwa/assets/{QSelect-BfqaWakg.js → QSelect-Dpru_T81.js} +1 -1
  40. package/src/client/dist/pwa/assets/{QSpinnerDots-BkFiCsH3.js → QSpinnerDots-DDsPDUH9.js} +1 -1
  41. package/src/client/dist/pwa/assets/{QTooltip-Cy0T0vk2.js → QTooltip-C31vXtse.js} +1 -1
  42. package/src/client/dist/pwa/assets/{SchedulePanel-YQPObRR3.js → SchedulePanel-D6LTiRFg.js} +1 -1
  43. package/src/client/dist/pwa/assets/{SearchPage-BoBjmItc.js → SearchPage-Dj487BdP.js} +1 -1
  44. package/src/client/dist/pwa/assets/{SettingsPage-0GtDcXRC.js → SettingsPage-CJmgFiAa.js} +1 -1
  45. package/src/client/dist/pwa/assets/{SplitWorkspacePage-4wFh65Lh.js → SplitWorkspacePage-BGSDgGIO.js} +1 -1
  46. package/src/client/dist/pwa/assets/{TerminalPanel-b70x_jqH.js → TerminalPanel-B9LDe7uG.js} +1 -1
  47. package/src/client/dist/pwa/assets/{TouchPan-CcTVcxwd.js → TouchPan-DJqqxDBF.js} +1 -1
  48. package/src/client/dist/pwa/assets/{TourReplayButton-CpEMnQS8.js → TourReplayButton-Dtv_UDaY.js} +1 -1
  49. package/src/client/dist/pwa/assets/{WorkspaceAttentionLabels-C5lTHTp2.js → WorkspaceAttentionLabels-VlJCIkwU.js} +1 -1
  50. package/src/client/dist/pwa/assets/{WorkspacePage-D_V9gNON.js → WorkspacePage-B_SlX8YB.js} +3 -3
  51. package/src/client/dist/pwa/assets/{browser-LBbxVwWf.js → browser-B15GGwtW.js} +1 -1
  52. package/src/client/dist/pwa/assets/{build-path-tree-DyvtWxb0.js → build-path-tree-CU6uXunR.js} +1 -1
  53. package/src/client/dist/pwa/assets/{codicon-Brq4_Ui5.ttf → codicon-DF1abBS2.ttf} +0 -0
  54. package/src/client/dist/pwa/assets/{custom-sounds-BpeLZUDW.js → custom-sounds-CDJsgChY.js} +1 -1
  55. package/src/client/dist/pwa/assets/de-B_Y4EArT.js +17 -0
  56. package/src/client/dist/pwa/assets/{documents-Bjx8lz-h.js → documents-Cf6nmu8Z.js} +1 -1
  57. package/src/client/dist/pwa/assets/editor-CmVjQp1O.css +1 -0
  58. package/src/client/dist/pwa/assets/editor.api-DhaLhNl-.js +420 -0
  59. package/src/client/dist/pwa/assets/editor.worker-BLJF_oQx.js +33 -0
  60. package/src/client/dist/pwa/assets/{efforts-BDHAnNUs.js → efforts-DoYZi0AZ.js} +2 -2
  61. package/src/client/dist/pwa/assets/{engineFeatures-hlEiwqt-.js → engineFeatures-C9XiCfvv.js} +1 -1
  62. package/src/client/dist/pwa/assets/es-DtsTTShP.js +17 -0
  63. package/src/client/dist/pwa/assets/{expand-template-DLDl1qPx.js → expand-template-LDLM-6iN.js} +1 -1
  64. package/src/client/dist/pwa/assets/format-2JisC3s1.js +489 -0
  65. package/src/client/dist/pwa/assets/format-DoyK4IAn.css +1 -0
  66. package/src/client/dist/pwa/assets/{formatters-CWxRHuUu.js → formatters-ZVNs2VOl.js} +1 -1
  67. package/src/client/dist/pwa/assets/fr-C82MIVrA.js +17 -0
  68. package/src/client/dist/pwa/assets/{freemarker2-MPhk0eTh.js → freemarker2-PYrDqU04.js} +1 -1
  69. package/src/client/dist/pwa/assets/{handlebars-C60ru5gR.js → handlebars-BuiY0fFf.js} +1 -1
  70. package/src/client/dist/pwa/assets/{html-ClzchR9j.js → html-Du3cjdug.js} +1 -1
  71. package/src/client/dist/pwa/assets/i18n-BumeGGx_.js +1 -0
  72. package/src/client/dist/pwa/assets/index-DolbyIM4.js +20 -0
  73. package/src/client/dist/pwa/assets/index-VMFLfvp2.css +1 -0
  74. package/src/client/dist/pwa/assets/it-BJNuTcj2.js +17 -0
  75. package/src/client/dist/pwa/assets/{javascript-C43UJmMx.js → javascript-Bb48hPli.js} +1 -1
  76. package/src/client/dist/pwa/assets/{liquid-CYTrvTKF.js → liquid-Be77iQe3.js} +1 -1
  77. package/src/client/dist/pwa/assets/{mdx-CxsXOvkQ.js → mdx-CfohNJja.js} +1 -1
  78. package/src/client/dist/pwa/assets/monaco-contributions-CyM4wsIg.js +53 -0
  79. package/src/client/dist/pwa/assets/monaco-contributions-DvnCTJI2.css +1 -0
  80. package/src/client/dist/pwa/assets/{monaco.contribution-DkjLUmyA.js → monaco.contribution-BcIfN6Mi.js} +2 -2
  81. package/src/client/dist/pwa/assets/{network-auth-CXQn2wO7.js → network-auth-B1xAaHmx.js} +1 -1
  82. package/src/client/dist/pwa/assets/{notify-theme-BrueBr2j.js → notify-theme-DvvaSyg1.js} +1 -1
  83. package/src/client/dist/pwa/assets/{pending-diff-open-B4POItbR.js → pending-diff-open-B6N0vI5n.js} +1 -1
  84. package/src/client/dist/pwa/assets/{project-color-CM3hflLH.js → project-color-Be0t12-n.js} +1 -1
  85. package/src/client/dist/pwa/assets/{python-s2IMpsoV.js → python-BNemmtx8.js} +1 -1
  86. package/src/client/dist/pwa/assets/{razor-DVNXiVBh.js → razor-3NM8iFVf.js} +1 -1
  87. package/src/client/dist/pwa/assets/render-chat-markdown-BWJNIDv3.js +69 -0
  88. package/src/client/dist/pwa/assets/{typescript-BYT_8ABE.js → typescript-DwyZ4CF7.js} +1 -1
  89. package/src/client/dist/pwa/assets/{use-checkbox-CnvHBhSK.js → use-checkbox-2xzX4yYj.js} +1 -1
  90. package/src/client/dist/pwa/assets/{use-id-wXd4c8FA.js → use-id-vOr8PRTG.js} +1 -1
  91. package/src/client/dist/pwa/assets/{use-is-mobile-DpKI3XMy.js → use-is-mobile-CJfSpTHx.js} +1 -1
  92. package/src/client/dist/pwa/assets/{use-tours-CNe8qb1q.js → use-tours-CjASQcG5.js} +1 -1
  93. package/src/client/dist/pwa/assets/{workspace-templates-tBxXE52A.js → workspace-templates-BxYxJt3S.js} +1 -1
  94. package/src/client/dist/pwa/assets/{xml-BIG-fmxk.js → xml-B1UujXdS.js} +1 -1
  95. package/src/client/dist/pwa/assets/{yaml-D7gu2CQh.js → yaml-mHN8kNgU.js} +1 -1
  96. package/src/client/dist/pwa/index.html +5 -5
  97. package/src/client/dist/pwa/sw.js +1 -1
  98. package/src/client/dist/pwa/assets/ActivityFeed-DRgetl1M.js +0 -8
  99. package/src/client/dist/pwa/assets/DashboardPage-CzVOvjSP.js +0 -1
  100. package/src/client/dist/pwa/assets/DashboardPage-D8g7_r4S.css +0 -1
  101. package/src/client/dist/pwa/assets/MainLayout-DqBbE8o4.js +0 -2
  102. package/src/client/dist/pwa/assets/de-v6i2HlE2.js +0 -17
  103. package/src/client/dist/pwa/assets/editor-BJU3Xb3h.css +0 -1
  104. package/src/client/dist/pwa/assets/editor.api-BC3PbJkx.js +0 -413
  105. package/src/client/dist/pwa/assets/editor.worker-iO5iN0DB.js +0 -33
  106. package/src/client/dist/pwa/assets/es-Bc1KgkAT.js +0 -17
  107. package/src/client/dist/pwa/assets/format-CX6Cv1cD.css +0 -1
  108. package/src/client/dist/pwa/assets/format-Q94deO3I.js +0 -435
  109. package/src/client/dist/pwa/assets/fr-ByYPK5vr.js +0 -17
  110. package/src/client/dist/pwa/assets/i18n-Sy42tm-V.js +0 -1
  111. package/src/client/dist/pwa/assets/index-0wtBh1Xt.css +0 -1
  112. package/src/client/dist/pwa/assets/index-CqZ7sDcM.js +0 -20
  113. package/src/client/dist/pwa/assets/it-BYF_88z6.js +0 -17
  114. package/src/client/dist/pwa/assets/monaco-contributions-Cb0afGfW.css +0 -1
  115. package/src/client/dist/pwa/assets/monaco-contributions-Cl4-iVpK.js +0 -51
  116. package/src/client/dist/pwa/assets/render-chat-markdown-TU6CDfD8.js +0 -69
package/CHANGELOG.md CHANGED
@@ -4,6 +4,15 @@ All notable changes to Kōbō are documented here. The format is based on
4
4
  [Keep a Changelog](https://keepachangelog.com/). Each release is an `## <version>`
5
5
  section — the in-app "What's new" dialog reads this file.
6
6
 
7
+ ## 2.1.2
8
+
9
+ - fix: read-only returning reviews, resumed-turn stdin, feed and tag filter
10
+ - chore: npm deps update
11
+
12
+ ## 2.1.1
13
+
14
+ - feat(dashboard): allow resetting the model reliability table
15
+
7
16
  ## 2.1.0
8
17
 
9
18
  - chore(deps): update dependencies
@@ -785,6 +785,14 @@ export const migrations = [
785
785
  db.exec('ALTER TABLE pending_wakeups ADD COLUMN retry_at TEXT');
786
786
  },
787
787
  },
788
+ {
789
+ version: 50,
790
+ name: 'reliability-reset',
791
+ migrate(db) {
792
+ // Single row: the dashboard reliability table ignores sessions ended before it.
793
+ db.exec('CREATE TABLE IF NOT EXISTS reliability_reset (id INTEGER PRIMARY KEY CHECK (id = 1), reset_at TEXT NOT NULL)');
794
+ },
795
+ },
788
796
  ];
789
797
  /** Current schema version — always equals the highest migration version. */
790
798
  export const SCHEMA_VERSION = migrations.length > 0 ? migrations[migrations.length - 1].version : 1;
@@ -209,6 +209,8 @@ export function initSchema(db) {
209
209
  );
210
210
  CREATE INDEX IF NOT EXISTS idx_workspace_activity_created ON workspace_activity(created_at);
211
211
 
212
+ CREATE TABLE IF NOT EXISTS reliability_reset (id INTEGER PRIMARY KEY CHECK (id = 1), reset_at TEXT NOT NULL);
213
+
212
214
  CREATE INDEX IF NOT EXISTS idx_tasks_workspace_id ON tasks(workspace_id);
213
215
  CREATE INDEX IF NOT EXISTS idx_agent_sessions_workspace_id ON agent_sessions(workspace_id);
214
216
  CREATE INDEX IF NOT EXISTS idx_ws_events_workspace_id ON ws_events(workspace_id);
@@ -1,12 +1,38 @@
1
1
  import { Hono } from 'hono';
2
2
  import { getDb } from '../db/index.js';
3
3
  import { refreshNow } from '../services/usage/poller.js';
4
- import { computeEngineReliability } from '../services/usage/reliability.js';
4
+ import { clearReliabilityReset, computeEngineReliability, getReliabilityResetAt, resetReliability, } from '../services/usage/reliability.js';
5
5
  const app = new Hono();
6
6
  // GET /api/usage/reliability — how each engine and model actually behaved.
7
7
  app.get('/reliability', (c) => {
8
8
  try {
9
- return c.json({ engines: computeEngineReliability(getDb()) });
9
+ const db = getDb();
10
+ return c.json({ engines: computeEngineReliability(db), resetAt: getReliabilityResetAt(db) });
11
+ }
12
+ catch (err) {
13
+ const message = err instanceof Error ? err.message : String(err);
14
+ return c.json({ error: message }, 500);
15
+ }
16
+ });
17
+ // POST /api/usage/reliability/reset - count again from now. Sessions are kept.
18
+ // Declared before `/:providerId/refresh` so the static path is never captured.
19
+ app.post('/reliability/reset', (c) => {
20
+ try {
21
+ const db = getDb();
22
+ const resetAt = resetReliability(db);
23
+ return c.json({ engines: computeEngineReliability(db), resetAt });
24
+ }
25
+ catch (err) {
26
+ const message = err instanceof Error ? err.message : String(err);
27
+ return c.json({ error: message }, 500);
28
+ }
29
+ });
30
+ // DELETE /api/usage/reliability/reset - count the whole history again.
31
+ app.delete('/reliability/reset', (c) => {
32
+ try {
33
+ const db = getDb();
34
+ clearReliabilityReset(db);
35
+ return c.json({ engines: computeEngineReliability(db), resetAt: null });
10
36
  }
11
37
  catch (err) {
12
38
  const message = err instanceof Error ? err.message : String(err);
@@ -43,6 +43,16 @@ export const COMPACTION_STALL_TIMEOUT_MS = 10 * 60_000;
43
43
  // `inputStream.close()`/the result-drain watchdog forever. Generous window:
44
44
  // legitimate subagents can run for several minutes.
45
45
  export const SUBAGENT_STALL_TIMEOUT_MS = 10 * 60_000;
46
+ /** After the last background subagent completes, the CLI normally resumes the
47
+ * parent on its own. Closing the input before that continuation starts makes
48
+ * every permission request of it fail with "Stream closed", so wait this long
49
+ * for a parent message before draining a stream that did not continue. */
50
+ export const BACKGROUND_CONTINUATION_GRACE_MS = 60_000;
51
+ /** A `result` does not always end the stream: resuming a session killed
52
+ * mid-turn first settles the interrupted turn with an empty result, then
53
+ * runs the new prompt right away. Wait this long for a follow-up before
54
+ * closing the input it still needs for permission requests. */
55
+ export const RESULT_CONTINUATION_GRACE_MS = 3_000;
46
56
  const MAX_PENDING_USER_MESSAGES = 20;
47
57
  function toMcpServersMap(specs) {
48
58
  if (!specs || specs.length === 0)
@@ -125,6 +135,16 @@ export function createClaudeCodeEngine() {
125
135
  const isInteractive = options.agentPermissionMode === 'interactive';
126
136
  const canUseTool = (toolName, input, ctx) => {
127
137
  const toolCallId = typeof ctx.toolUseID === 'string' && ctx.toolUseID.length > 0 ? ctx.toolUseID : `tu_${nanoid()}`;
138
+ // Plan mode alone is not read-only here: the non-interactive allow below
139
+ // would approve ExitPlanMode and then every edit. Anything that needs a
140
+ // permission, a question included, is refused outright instead.
141
+ if (options.readOnly) {
142
+ return Promise.resolve({
143
+ behavior: 'deny',
144
+ message: 'This is a read-only review session: do not modify anything or ask the user. Put the finding in your final report instead.',
145
+ interrupt: false,
146
+ });
147
+ }
128
148
  // Non-interactive modes: the SDK has already applied its permissionMode
129
149
  // rules before reaching us, so allow through unchanged. AskUserQuestion
130
150
  // is the exception — it always defers to the user.
@@ -406,6 +426,33 @@ export function createClaudeCodeEngine() {
406
426
  clearTimeout(resultDrainTimer);
407
427
  resultDrainTimer = undefined;
408
428
  };
429
+ // Drain for a stream that may still continue: after a result, or after
430
+ // the last background subagent completed. Any new init or parent
431
+ // message cancels it, and that continuation's own `result` re-arms it.
432
+ let continuationGraceTimer;
433
+ const clearContinuationGrace = () => {
434
+ if (!continuationGraceTimer)
435
+ return;
436
+ clearTimeout(continuationGraceTimer);
437
+ continuationGraceTimer = undefined;
438
+ };
439
+ const armContinuationGrace = (delayMs) => {
440
+ clearContinuationGrace();
441
+ continuationGraceTimer = setTimeout(() => {
442
+ continuationGraceTimer = undefined;
443
+ if (activeSubagentTaskIds.size > 0 ||
444
+ pendingResolvers.size > 0 ||
445
+ pendingToolCallIds.size > 0 ||
446
+ inputStream.hasUnansweredInput(completedResponses))
447
+ return;
448
+ // Settled only now: a result the CLI follows up on (e.g. a resumed
449
+ // turn's empty result) must not hide the busy banner meanwhile.
450
+ emitTurnCompletedIfSettled();
451
+ inputStream.close();
452
+ armResultDrainWatchdog();
453
+ }, delayMs);
454
+ continuationGraceTimer.unref?.();
455
+ };
409
456
  // Safety net for the "waiting on a background subagent" branch below:
410
457
  // if `activeSubagentToolCallIds` never empties (a missed/unrecognised
411
458
  // terminal notification), the workspace would otherwise stay `executing`
@@ -447,6 +494,11 @@ export function createClaudeCodeEngine() {
447
494
  // progress notifications alone do not end the between-turn wait.
448
495
  if (msg.type === 'assistant' || msg.type === 'user' || msg.type === 'stream_event') {
449
496
  waitingForBackground = false;
497
+ clearContinuationGrace();
498
+ }
499
+ else if (msg.type === 'system' && msg.subtype === 'init') {
500
+ // A new run starts on this stream (e.g. after a resumed turn's empty result).
501
+ clearContinuationGrace();
450
502
  }
451
503
  // This SDK message proves that any drain condition armed by a
452
504
  // *previous* message is no longer current. A drain armed while
@@ -501,14 +553,15 @@ export function createClaudeCodeEngine() {
501
553
  else if (ev.kind === 'tool:result')
502
554
  pendingToolCallIds.delete(ev.toolCallId);
503
555
  }
504
- // After a settled result, the last background completion can
505
- // drain the stream without waiting for another result.
556
+ // After a settled result, the last background completion drains
557
+ // the stream only if the parent does not continue (see
558
+ // BACKGROUND_CONTINUATION_GRACE_MS): its continuation still needs
559
+ // the input for permission requests.
506
560
  if (subagentStallTimer &&
507
561
  activeSubagentTaskIds.size === 0 &&
508
562
  !inputStream.hasUnansweredInput(completedResponses)) {
509
563
  clearSubagentStallWatchdog();
510
- inputStream.close();
511
- armResultDrainWatchdog();
564
+ armContinuationGrace(BACKGROUND_CONTINUATION_GRACE_MS);
512
565
  }
513
566
  for (const ev of events) {
514
567
  if (ev.kind === 'session:started')
@@ -527,15 +580,14 @@ export function createClaudeCodeEngine() {
527
580
  reevaluateLivenessPause();
528
581
  if (msg.type === 'result') {
529
582
  waitingForBackground = false;
583
+ clearContinuationGrace();
530
584
  pendingToolCallIds.clear();
531
585
  completedResponses++;
532
- emitTurnCompletedIfSettled();
533
586
  // A queued forced message starts the next response on this same SDK stream.
534
587
  if (!inputStream.hasUnansweredInput(completedResponses)) {
535
588
  if (activeSubagentTaskIds.size === 0) {
536
589
  clearSubagentStallWatchdog();
537
- inputStream.close();
538
- armResultDrainWatchdog();
590
+ armContinuationGrace(RESULT_CONTINUATION_GRACE_MS);
539
591
  }
540
592
  else {
541
593
  waitingForBackground = true;
@@ -581,6 +633,7 @@ export function createClaudeCodeEngine() {
581
633
  // iterator has exited — clear it so a healthy run never triggers a
582
634
  // stray abort after it already ended.
583
635
  clearResultDrainWatchdog();
636
+ clearContinuationGrace();
584
637
  turnLiveness.stop();
585
638
  clearSubagentStallWatchdog();
586
639
  clearCompactionStallTimer();
@@ -77,6 +77,7 @@ export function createCodexEngine() {
77
77
  model: options.model,
78
78
  effort: options.effort,
79
79
  agentPermissionMode: options.agentPermissionMode ?? 'bypass',
80
+ readOnly: options.readOnly,
80
81
  resumeFromEngineSessionId: options.resumeFromEngineSessionId,
81
82
  workingDir: options.workingDir,
82
83
  mcpServers: options.mcpServers,
@@ -38,6 +38,10 @@ export function buildCodexOptions(input) {
38
38
  threadParams.approvalPolicy = 'unless-trusted';
39
39
  break;
40
40
  }
41
+ if (input.readOnly) {
42
+ threadParams.sandbox = 'read-only';
43
+ threadParams.approvalPolicy = 'never';
44
+ }
41
45
  // Model: omit when undefined or 'auto', let Codex use its default
42
46
  if (input.model && input.model !== 'auto') {
43
47
  threadParams.model = input.model;
@@ -70,7 +74,8 @@ export function buildCodexOptions(input) {
70
74
  // model/effort because collaborationMode takes precedence over them. Automatic
71
75
  // model selection is filled from thread/start or thread/resume by the engine.
72
76
  const collaborationMode = {
73
- mode: input.agentPermissionMode === 'plan' ? 'plan' : 'default',
77
+ // A read-only review must not stop on a plan-mode question (see readOnly).
78
+ mode: input.agentPermissionMode === 'plan' && !input.readOnly ? 'plan' : 'default',
74
79
  settings: {
75
80
  ...(threadParams.model ? { model: threadParams.model } : {}),
76
81
  reasoning_effort: threadParams.modelReasoningEffort ?? null,
@@ -1373,6 +1373,9 @@ export function startAgent(workspaceId, workingDir, prompt, model, resume = fals
1373
1373
  activateSession(workspaceId, agentSessionId);
1374
1374
  captureTaskProgressBaseline(workspaceId, agentSessionId);
1375
1375
  const settings = ws ? readEffectiveSettingsSafe(ws.projectPath) : readEffectiveSettingsSafe(workingDir);
1376
+ // A review whose report returns to the original session must end by itself:
1377
+ // enforce read-only plan mode here, not only through its prompt.
1378
+ const readOnly = getReviewReturn(workspaceId, agentSessionId) !== null;
1376
1379
  const unavailableIntegrations = [];
1377
1380
  const integrationServers = buildIntegrationMcpServers(getGlobalSettings(), (name) => unavailableIntegrations.push(name));
1378
1381
  const options = {
@@ -1382,7 +1385,8 @@ export function startAgent(workspaceId, workingDir, prompt, model, resume = fals
1382
1385
  model,
1383
1386
  effort: reasoningEffort,
1384
1387
  // Cascade: explicit caller override → workspace setting → 'bypass'.
1385
- agentPermissionMode: agentPermissionMode ?? ws?.agentPermissionMode ?? 'bypass',
1388
+ agentPermissionMode: readOnly ? 'plan' : (agentPermissionMode ?? ws?.agentPermissionMode ?? 'bypass'),
1389
+ readOnly,
1386
1390
  resumeFromEngineSessionId,
1387
1391
  backendUrl: `http://127.0.0.1:${backendPort}`,
1388
1392
  koboHome: (() => {
@@ -44,7 +44,8 @@ function resolveConfiguration(workspace, body) {
44
44
  engine: engineId,
45
45
  model: body.model ?? (changedEngine ? 'auto' : workspace.model),
46
46
  reasoningEffort: body.reasoningEffort ?? (changedEngine ? 'auto' : workspace.reasoningEffort),
47
- agentPermissionMode: body.agentPermissionMode ?? workspace.agentPermissionMode,
47
+ // A review that hands its report back must end by itself: always read-only.
48
+ agentPermissionMode: body.returnToSession ? 'plan' : (body.agentPermissionMode ?? workspace.agentPermissionMode),
48
49
  };
49
50
  // Preserve an existing custom model when unchanged; reject incompatible selections.
50
51
  if ((changedEngine || config.model !== workspace.model) &&
@@ -115,9 +116,12 @@ export async function startWorkspaceReview(id, input) {
115
116
  baseCommit,
116
117
  additionalInstructions: (body.additionalInstructions ?? '').trim(),
117
118
  });
119
+ // The return fires only when the review session ends by itself: a reviewer
120
+ // that starts fixing, or waits on a question, never hands back.
118
121
  if (body.returnToSession)
119
122
  rendered +=
120
- '\n\nFinish with a standalone summary of your review findings, including severity, file/line references, recommended fixes and any remaining uncertainty. This final message will be handed back to the original agent session. Do not rely on earlier messages to explain your findings.';
123
+ '\n\nThis is a read-only review session; these rules override any template instruction or skill that suggests fixing issues. Do not modify, create or delete files, and do not commit or push: the original agent session applies the fixes. Running read-only checks such as tests or linters is fine. Do not ask the user questions or wait for input: note any decision that needs the user in your summary instead.' +
124
+ '\n\nFinish with a standalone summary of your review findings, including severity, file/line references, recommended fixes and any remaining uncertainty. This final message will be handed back to the original agent session. Do not rely on earlier messages to explain your findings.';
121
125
  assertWorkspaceLifecycleAvailable(id);
122
126
  const current = workspaceService.getWorkspace(id);
123
127
  if (!current || current.archivedAt || current.worktreePurgedAt || current.status === 'compacting')
@@ -1,3 +1,22 @@
1
+ /**
2
+ * Instant from which the reliability table counts again, or null to count the
3
+ * whole history. Sessions are never deleted: a reset only hides older ones.
4
+ */
5
+ export function getReliabilityResetAt(db) {
6
+ const row = db.prepare('SELECT reset_at FROM reliability_reset WHERE id = 1').get();
7
+ return row?.reset_at ?? null;
8
+ }
9
+ /** Start counting again from `now`. Replaces any earlier reset. */
10
+ export function resetReliability(db, now = new Date()) {
11
+ const resetAt = now.toISOString();
12
+ db.prepare(`INSERT INTO reliability_reset (id, reset_at) VALUES (1, ?)
13
+ ON CONFLICT(id) DO UPDATE SET reset_at = excluded.reset_at`).run(resetAt);
14
+ return resetAt;
15
+ }
16
+ /** Count the whole history again. */
17
+ export function clearReliabilityReset(db) {
18
+ db.prepare('DELETE FROM reliability_reset WHERE id = 1').run();
19
+ }
1
20
  function median(values) {
2
21
  if (values.length === 0)
3
22
  return null;
@@ -21,8 +40,13 @@ export function computeEngineReliability(db) {
21
40
  FROM agent_sessions
22
41
  WHERE ended_at IS NOT NULL`)
23
42
  .all();
43
+ // Compared as parsed instants: string order breaks on offsets and formats.
44
+ const resetAt = getReliabilityResetAt(db);
45
+ const since = resetAt ? Date.parse(resetAt) : Number.NaN;
24
46
  const groups = new Map();
25
47
  for (const session of rows) {
48
+ if (!Number.isNaN(since) && !(Date.parse(session.ended_at ?? '') >= since))
49
+ continue;
26
50
  const engine = session.engine ?? 'unknown';
27
51
  const model = session.model ?? 'unknown';
28
52
  const key = `${engine}\u0000${model}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loicngr/kobo",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "Kōbō — local multi-workspace orchestrator for Claude Code and OpenAI Codex, with isolated Git worktrees, live review and optional automation.",
5
5
  "type": "module",
6
6
  "license": "GPL-3.0-or-later",
@@ -81,29 +81,29 @@
81
81
  "security:scan": "node scripts/scan-secrets.mjs"
82
82
  },
83
83
  "dependencies": {
84
- "@anthropic-ai/claude-agent-sdk": "^0.3.280",
84
+ "@anthropic-ai/claude-agent-sdk": "^0.3.283",
85
85
  "@emnapi/core": "^1.11.3",
86
86
  "@emnapi/runtime": "^1.11.3",
87
87
  "@hono/node-server": "^2.1.1",
88
- "@modelcontextprotocol/sdk": "^1.30.0",
89
- "@openai/codex": "^0.154.0",
88
+ "@modelcontextprotocol/sdk": "^1.30.1",
89
+ "@openai/codex": "^0.158.0",
90
90
  "better-sqlite3": "^13.0.3",
91
91
  "cron-parser": "^5.10.1",
92
- "hono": "^4.13.8",
92
+ "hono": "^4.13.10",
93
93
  "nanoid": "^6.0.1",
94
94
  "node-pty": "^1.1.0",
95
- "ws": "^8.21.3"
95
+ "ws": "^8.22.0"
96
96
  },
97
97
  "devDependencies": {
98
- "@biomejs/biome": "2.5.7",
98
+ "@biomejs/biome": "2.5.14",
99
99
  "@types/better-sqlite3": "^9.6.0",
100
- "@types/node": "^26.6.2",
100
+ "@types/node": "^26.6.3",
101
101
  "@types/ws": "^8.18.1",
102
102
  "@vitest/runner": "^4.1.11",
103
103
  "concurrently": "^10.0.5",
104
104
  "tsx": "^4.23.15",
105
- "typescript": "^6.0.3",
106
- "vitest": "^4.1.11"
105
+ "typescript": "^7.0.2",
106
+ "vitest": "^5.0.2"
107
107
  },
108
108
  "overrides": {
109
109
  "@hono/node-server": "^2.1.1",
@@ -0,0 +1,8 @@
1
+ import{S as e,ct as t,j as n,ot as r,p as i,ut as a,v as o}from"./reactivity.esm-bundler-Bo9anJjg.js";import{C as s,F as c,J as l,L as u,N as d,O as f,P as p,Y as m,_ as h,d as g,f as _,g as v,j as y,k as b,l as x,p as S,r as C,u as w,y as T,z as ee}from"./runtime-core.esm-bundler-CNFKm4ij.js";import{J as E,b as D,ct as te,l as O,pt as k,t as ne,tt as A,w as re,y as ie}from"./QBtn-CcQQrYA_.js";import{Bt as ae,O as oe,Rt as j,T as M,Xt as N,g as se,j as P,nt as ce,p as le,qt as ue,rt as de,ut as fe}from"./index-DolbyIM4.js";import{t as pe}from"./QSpinnerDots-DDsPDUH9.js";import{t as me}from"./QList-D5msNbSZ.js";import{t as F}from"./QMarkupTable-D3REW6RC.js";import{c as I,l as L}from"./QSelect-Dpru_T81.js";import{t as he}from"./QExpansionItem-RpMPvfxX.js";import{r as ge,t as R}from"./pending-diff-open-B6N0vI5n.js";import{t as z}from"./documents-Cf6nmu8Z.js";import{a as B}from"./use-tours-CjASQcG5.js";import{t as V}from"./QTooltip-C31vXtse.js";import{i as _e,n as ve,o as H,r as ye,t as be}from"./render-chat-markdown-BWJNIDv3.js";import{a as xe,i as Se,n as Ce,o as we,r as Te,s as U}from"./WorkspacePage-B_SlX8YB.js";function Ee(e,t){return s(`div`,e,[s(`table`,{class:`q-table`},t)])}var De={list:me,table:F},W=[`list`,`table`,`__qtable`],Oe=A({name:`QVirtualScroll`,props:{...L,type:{type:String,default:`list`,validator:e=>W.includes(e)},items:{type:Array,default:()=>[]},itemsFn:Function,itemsSize:Number,scrollTarget:N},setup(t,{slots:n,attrs:r}){let i,a=e(null),o=x(()=>t.itemsSize>=0&&t.itemsFn!==void 0?Number.parseInt(t.itemsSize,10):Array.isArray(t.items)?t.items.length:0),{virtualScrollSliceRange:c,localResetVirtualScroll:u,padVirtualScroll:f,onVirtualScrollEvt:m}=I({virtualScrollLength:o,getVirtualScrollTarget:S,getVirtualScrollEl:v}),h=x(()=>{if(o.value===0)return[];let e=(e,t)=>({index:c.value.from+t,item:e});return t.itemsFn===void 0?t.items.slice(c.value.from,c.value.to).map(e):t.itemsFn(c.value.from,c.value.to-c.value.from).map(e)}),g=x(()=>`q-virtual-scroll q-virtual-scroll`+(t.virtualScrollHorizontal?`--horizontal`:`--vertical`)+(t.scrollTarget===void 0?` scroll`:``)),_=x(()=>t.scrollTarget===void 0?{tabindex:0}:{});l(o,()=>{u()}),l(()=>t.scrollTarget,()=>{w(),C()});function v(){let e=a.value;return e===null?null:e.$el||e}function S(){return i}function C(){let e=v();e!==null&&(i=ue(e,t.scrollTarget),i.addEventListener(`scroll`,m,E.passive))}function w(){i!==void 0&&(i.removeEventListener(`scroll`,m,E.passive),i=void 0)}function T(){let e=f(t.type===`list`?`div`:`tbody`,h.value.map(n.default));return n.before!==void 0&&(e=n.before().concat(e)),D(n.after,e)}return u(),p(()=>{C()}),b(()=>{C()}),d(()=>{w()}),y(()=>{w()}),()=>{if(n.default===void 0){console.error(`QVirtualScroll: default scoped slot is required for rendering`);return}return t.type===`__qtable`?Ee({ref:a,class:`q-table__middle `+g.value,tabindex:0},T()):s(De[t.type],{...r,ref:a,class:[r.class,g.value],..._.value},T)}}}),G=new Set([`setup`,`cleanup`,`archive`]);function ke(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:G.has(e.sender)||M(e.sender)?`script`:`user`;case`session`:return`session`;default:return`agent`}}function Ae(e){let t=[],n=null,r=null;for(let i of e){let e=ke(i),a=e===`session`||e===`system-prompt`,o=e===`script`&&i.type===`user`?`script:${i.sender}`:e===`user`&&i.type===`user`&&i.source?JSON.stringify([`mcp`,i.source.transport,i.source.clientName]):e;!n||r!==o||a?(n={speaker:e,ts:i.ts,items:[i]},r=o,t.push(n),a&&(n=null)):n.items.push(i)}return t}function je(e){switch(e.type){case`text`:return`text:${e.messageId}`;case`thinking`:return`thinking:${e.messageId}:${e.eventIds?.[0]??e.ts??``}`;case`tool`:return`tool:${e.toolCallId}`;case`session`:return`session:${e.kind}:${e.eventIds?.[0]??e.ts??``}`;case`user`:return`user:${e.eventIds?.[0]??`${e.sender}:${e.ts??``}`}`;case`error`:return`error:${e.eventIds?.[0]??`${e.category}:${e.ts??``}`}`}}function Me(e){let t=e.items[0];return`${e.speaker}:${t?je(t):`empty`}`}function Ne(e,t){let n=Math.min(t,e.length)-1;for(let t=n;t>=0;t--)if(e[t]?.speaker===`user`)return t;return-1}function Pe(e,t,n){return new Promise(r=>{let i=!1,a=null,o=null,s=e=>{i||(i=!0,a!==null&&clearTimeout(a),a=null,o?.(),r(e))};if(o=l(e,e=>{t(e)&&s(!0)},{immediate:!0}),i){o();return}a=setTimeout(()=>s(!1),n)})}var Fe={class:`agent-error-item`},Ie={class:`agent-error-item__body`},Le={class:`agent-error-item__title`},Re={class:`agent-error-item__message`},ze=B(T({__name:`AgentErrorItem`,props:{item:{}},setup(e){let t=e,{te:n}=j(),r=x(()=>{let e=`agent.error.${t.item.category}`;return n(e)?e:`agent.error.other`});return(t,n)=>(u(),S(`div`,Fe,[h(O,{name:`error_outline`,size:`16px`,class:`agent-error-item__icon`}),w(`div`,Ie,[w(`div`,Le,a(t.$t(r.value)),1),w(`div`,Re,a(e.item.message),1)])]))}}),[[`__scopeId`,`data-v-e98c3c02`]]),K={class:`text-caption text-kobo-3`},Be=T({__name:`SessionEventItem`,props:{item:{}},setup(e){let t=e,n=x(()=>{switch(t.item.kind){case`started`:return`session.started`;case`ended`:return U(t.item.detail);case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,t)=>(u(),S(`span`,K,a(e.$t(n.value)),1))}});function q(e,t){if(t.length===0||e.length===0)return e;let n=[...t].sort((e,t)=>t.length-e.length),r=new DOMParser().parseFromString(`<div>${e}</div>`,`text/html`),i=r.body.firstChild;if(!i)return e;function a(e){if(e.nodeType===Node.TEXT_NODE){Ve(e,n,r);return}if(e.nodeName===`A`)return;let t=Array.from(e.childNodes);for(let e of t)a(e)}return a(i),i.innerHTML}function Ve(e,t,n){let r=e.textContent??``;if(!t.some(e=>r.includes(e)))return;let i=n.createDocumentFragment(),a=0;for(;a<r.length;){let e=J(r,a,t);if(!e){i.appendChild(n.createTextNode(r.slice(a)));break}e.index>a&&i.appendChild(n.createTextNode(r.slice(a,e.index)));let o=n.createElement(`a`);o.className=`document-link`,o.setAttribute(`data-document-path`,e.path),o.setAttribute(`href`,`#`),o.textContent=e.path,i.appendChild(o),a=e.index+e.path.length}e.parentNode?.replaceChild(i,e)}function J(e,t,n){let r=null;for(let i of n){let n=e.indexOf(i,t);n<0||(!r||n<r.index||n===r.index&&i.length>r.path.length)&&(r={index:n,path:i})}return r}var He=[`innerHTML`],Y=B(T({__name:`TextMessageItem`,props:{item:{}},setup(e){let t=e,n=z(),r=ce(),i=ie(),{t:a}=j(),o=x(()=>{let e=r.selectedWorkspaceId;return e?n.documentsFor(e).map(e=>e.path):[]}),s=x(()=>{let e=t.item;if(e.streaming)return be(e.text);let n=o.value;return ye(`${e.messageId}|${n.join(`,`)}`,e.text,e=>{let t=q(H.parse(e,{async:!1,breaks:!0,gfm:!0}),n);return _e(t,{addAttr:[`data-document-path`]})})});function c(e){let t=e.target?.closest(`.document-link`);if(!t)return;e.preventDefault();let o=t.getAttribute(`data-document-path`),s=r.selectedWorkspaceId;o&&s&&n.openDocumentByPath(s,o).catch(e=>{console.error(`[TextMessageItem] openDocumentByPath failed:`,e),i.notify({type:`negative`,message:a(`documents.loadFailed`),position:`top`})})}return(t,n)=>(u(),S(`div`,{class:`markdown-message`,onClick:c},[w(`div`,{innerHTML:s.value},null,8,He),e.item.streaming?(u(),g(re,{key:0,size:`xs`,class:`q-ml-xs`})):_(``,!0)]))}}),[[`__scopeId`,`data-v-99371035`]]);function Ue(e,t){let n=e.split(`
2
+ `),r=t.split(`
3
+ `),i=0;for(;i<n.length&&i<r.length&&n[i]===r[i];)i++;let a=n.length,o=r.length;for(;a>i&&o>i&&n[a-1]===r[o-1];)a--,o--;let s=n.slice(0,i).map(e=>({type:`context`,content:e})),c=n.slice(a).map(e=>({type:`context`,content:e})),l=n.slice(i,a),u=r.slice(i,o);return l.length>800||u.length>800?[...s,...l.map(e=>({type:`del`,content:e})),...u.map(e=>({type:`add`,content:e})),...c]:[...s,...X(l,u),...c]}function X(e,t){let n=e.length,r=t.length;if(n===0&&r===0)return[];if(n===0)return t.map(e=>({type:`add`,content:e}));if(r===0)return e.map(e=>({type:`del`,content:e}));let i=r+1,a=new Int32Array((n+1)*i);for(let o=n-1;o>=0;o--)for(let n=r-1;n>=0;n--)a[o*i+n]=e[o]===t[n]?a[(o+1)*i+(n+1)]+1:Math.max(a[(o+1)*i+n],a[o*i+(n+1)]);let o=[],s=0,c=0;for(;s<n&&c<r;)e[s]===t[c]?(o.push({type:`context`,content:e[s]}),s++,c++):a[(s+1)*i+c]>=a[s*i+(c+1)]?(o.push({type:`del`,content:e[s]}),s++):(o.push({type:`add`,content:t[c]}),c++);for(;s<n;)o.push({type:`del`,content:e[s++]});for(;c<r;)o.push({type:`add`,content:t[c++]});return o}function We(e){let t=e.split(`
4
+ `),n=[],r=!1;for(let e of t){if(e.startsWith(`@@`)){r=!0;continue}(r||!e.startsWith(`+++`)&&!e.startsWith(`---`))&&(e.startsWith(`+`)?n.push({type:`add`,content:e.slice(1)}):e.startsWith(`-`)?n.push({type:`del`,content:e.slice(1)}):e.startsWith(` `)?n.push({type:`context`,content:e.slice(1)}):e.length>0&&n.push({type:`context`,content:e}))}return n}function Ge(e,t){if(!t||typeof t!=`object`)return null;let n=t;if(e===`Edit`){let e=n.file_path;if(!e)return null;let t=n.old_string??``,r=n.new_string??``,i=typeof n.diff==`string`?n.diff:``;if(!t&&!r&&i.length>0){let t=We(i);return{toolName:`Edit`,filePath:e,additions:t.filter(e=>e.type===`add`).length,deletions:t.filter(e=>e.type===`del`).length,diffLines:t}}return{toolName:`Edit`,filePath:e,oldString:t,newString:r,replaceAll:n.replace_all??!1,additions:r?r.split(`
5
+ `).length:0,deletions:t?t.split(`
6
+ `).length:0}}if(e===`Write`){let e=n.file_path;if(!e)return null;let t=n.content??``;return{toolName:`Write`,filePath:e,content:t,additions:t?t.split(`
7
+ `).length:0,deletions:0}}if(e===`Bash`){let e=(n.command??``).match(/^\s*rm\s+(?:-[a-zA-Z]*\s+)*(.+)/);if(e)return{toolName:`Bash:rm`,filePath:e[1].trim().replace(/["']/g,``),additions:0,deletions:1}}return null}function Z(e,t){if(!e||!t?.projectPath)return e;let n=t.worktreePath;if(n){let t=Q(e,n);if(t!==e)return t}let r=Q(e,`${t.projectPath}/${P}/${t.workingBranch}`);return r===e?Q(e,t.projectPath):r}function Q(e,t){if(!t)return e;let n=Ke(t);return n?e.replace(RegExp(`${n}[\\\\/]+`,`g`),``).replace(RegExp(`${n}(?=\\s|$|["'\`])`,`g`),`.`):e}function Ke(e){let t=e.replace(/[\\/]+$/,``);return t?`${/^[\\/]+/.test(t)?`[\\\\/]+`:``}${t.split(/[\\/]+/).filter(Boolean).map(qe).join(`[\\\\/]+`)}`:``}function qe(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}var Je={class:`tool-name`},Ye=[`title`],Xe={key:0,class:`tool-stat-add`},Ze={key:1,class:`tool-stat-del`},Qe={class:`diff-sign`},$e={class:`tool-name`},et=[`title`],tt=B(T({__name:`ToolCallItem`,props:{item:{}},setup(e){let t=e,i=o(!1),s=ce(),{t:c}=j(),d=x(()=>Ge(t.item.name,t.item.input)),f=x(()=>d.value?Z(d.value.filePath,s.selectedWorkspace):``),p={Bash:`terminal`,Read:`description`,Edit:`edit`,Write:`edit_note`,MultiEdit:`edit`,Glob:`folder_open`,Grep:`manage_search`,LS:`list`,Skill:`auto_awesome`,Task:`hub`,Agent:`hub`,TodoWrite:`checklist`,TodoRead:`checklist`,TaskCreate:`add_task`,TaskUpdate:`checklist`,TaskGet:`checklist`,TaskList:`checklist`,ToolSearch:`search`,WebFetch:`public`,WebSearch:`travel_explore`,NotebookRead:`book`,NotebookEdit:`edit_note`,SendMessage:`send`,ExitPlanMode:`check_circle_outline`,KillShell:`stop_circle`,BashOutput:`terminal`},y=x(()=>p[t.item.name]??`build`),b=x(()=>{if(d.value)return``;let e=t.item.input,n=T(e);return n?Z(n,s.selectedWorkspace):``});function T(e){if(!e||typeof e!=`object`)return typeof e==`string`?e:``;let t=e;for(let e of[`file_path`,`path`,`command`,`pattern`,`query`,`url`,`skill`,`description`,`subject`,`prompt`]){let n=t[e];if(typeof n==`string`&&n.length>0)return n}for(let e of Object.values(t))if(typeof e==`string`&&e.length>0)return e;return``}let E=x(()=>{let e=d.value;return e?e.diffLines?e.diffLines:e.toolName===`Edit`&&e.oldString!==void 0&&e.newString!==void 0?Ue(e.oldString,e.newString):e.toolName===`Write`&&e.content!==void 0?e.content.split(`
8
+ `).map(e=>({type:`add`,content:e})):e.toolName===`Bash:rm`?[{type:`del`,content:`File deleted`}]:null:null}),D=x(()=>{let e=t.item.result;if(!e)return``;if(typeof e.output==`string`)return e.output;try{return JSON.stringify(e.output)}catch{return String(e.output)}}),te=new Set([`Read`]),A=x(()=>!!(t.item.result&&D.value)&&(!te.has(t.item.name)||t.item.result?.isError===!0));function re(){i.value=!i.value}function ie(){let e=d.value?.filePath,t=s.selectedWorkspace,n=t?.id,r=e?Z(e,t):``;r&&!/^(?:[A-Za-z]:)?[\\/]/.test(r)&&n&&(R(n,r),window.dispatchEvent(new CustomEvent(`kobo:open-diff`,{detail:{workspaceId:n,path:r}})))}return l(()=>t.item.result?.isError===!0,e=>{e&&(i.value=!0)},{immediate:!0}),(t,o)=>d.value?(u(),S(`div`,{key:0,class:r([`tool-row`,{"tool-row-expanded":i.value}])},[w(`div`,{class:`tool-header`,onClick:re},[h(O,{name:y.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),w(`span`,Je,a(d.value.toolName===`Bash:rm`?`Bash`:d.value.toolName),1),w(`span`,{class:`tool-path`,title:d.value.filePath},a(f.value),9,Ye),h(ne,{flat:``,dense:``,round:``,size:`xs`,icon:`open_in_new`,class:`tool-open-diff`,onClick:k(ie,[`stop`])},{default:m(()=>[h(V,null,{default:m(()=>[v(a(n(c)(`chat.openInGitDiff`)),1)]),_:1})]),_:1}),d.value.additions>0?(u(),S(`span`,Xe,`+`+a(d.value.additions),1)):_(``,!0),d.value.deletions>0?(u(),S(`span`,Ze,`-`+a(d.value.deletions),1)):_(``,!0),e.item.result?.isError?(u(),g(O,{key:2,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-xs`})):e.item.result?(u(),g(O,{key:3,name:`check`,color:`positive`,size:`xs`,class:`q-ml-xs`})):_(``,!0),h(O,{name:i.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-auto text-kobo-3`},null,8,[`name`])]),i.value&&E.value?(u(),S(`div`,{key:0,class:`tool-diff`,onClick:o[0]||=k(()=>{},[`stop`])},[(u(!0),S(C,null,ee(E.value,(e,t)=>(u(),S(`div`,{key:t,class:r([`diff-line`,{"diff-del":e.type===`del`,"diff-add":e.type===`add`,"diff-context":e.type===`context`}])},[w(`span`,Qe,a(e.type===`del`?`-`:e.type===`add`?`+`:` `),1),v(a(e.content),1)],2))),128))])):_(``,!0)],2)):(u(),S(`div`,{key:1,class:r([`tool-row tool-row-generic`,{"tool-row-expanded":i.value,"tool-row--toggleable":A.value}])},[w(`div`,{class:`tool-header`,onClick:o[1]||=e=>A.value&&re()},[h(O,{name:y.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),w(`span`,$e,a(e.item.name),1),b.value?(u(),S(`span`,{key:0,class:`tool-arg`,title:T(e.item.input)||b.value},a(b.value),9,et)):_(``,!0),e.item.result?.isError?(u(),g(O,{key:1,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-auto`})):e.item.result?(u(),g(O,{key:2,name:`check`,color:`positive`,size:`xs`,class:`q-ml-auto`})):_(``,!0),A.value?(u(),g(O,{key:3,name:i.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-xs text-kobo-3`},null,8,[`name`])):_(``,!0)]),i.value&&A.value?(u(),S(`div`,{key:0,class:`tool-output`,onClick:o[2]||=k(()=>{},[`stop`])},a(D.value),1)):_(``,!0)],2))}}),[[`__scopeId`,`data-v-2482adfe`]]),$=new Map;function nt(){for(let e of $.values())e.controller.abort(),e.blobUrl&&URL.revokeObjectURL(e.blobUrl);$.clear()}typeof window<`u`&&(window.addEventListener(`kobo:auth-token-changed`,nt),window.addEventListener(`storage`,e=>{(e.key===`kobo:network-token`||e.key===null)&&nt()}));function rt(e){if(!/^\/api\/workspaces\/[^/]+\/images\/file\?path=/.test(e))throw Error(`Invalid workspace image URL`);let t=$.get(e);if(!t){let n=new AbortController,r={references:0,controller:n,ready:Promise.resolve(``)},i=setTimeout(()=>n.abort(),3e4);r.ready=fetch(e,{signal:n.signal}).then(async e=>{if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.blob();if(n.signal.aborted)throw new DOMException(`Aborted`,`AbortError`);return r.blobUrl=URL.createObjectURL(t),r.blobUrl}).finally(()=>clearTimeout(i)),t=r,$.set(e,t)}t.references++;let n=!1,r=t;return{ready:r.ready,release(){n||(n=!0,!(--r.references>0)&&(r.controller.abort(),r.blobUrl&&URL.revokeObjectURL(r.blobUrl),$.get(e)===r&&$.delete(e)))}}}function it(e,t){let n=o(``),r=o(0),a=()=>{r.value++},s=e=>{(e.key===`kobo:network-token`||e.key===null)&&a()};return window.addEventListener(`kobo:auth-token-changed`,a),window.addEventListener(`storage`,s),i(()=>{window.removeEventListener(`kobo:auth-token-changed`,a),window.removeEventListener(`storage`,s)}),l([e,r],([e],r,i)=>{let a=!0,o=[],s=document.createElement(`template`);s.innerHTML=e;for(let e of s.content.querySelectorAll(`img`)){let r=e.getAttribute(`src`)??``;if(e.removeAttribute(`data-kobo-image-url`),!/^\/api\/workspaces\/[^/]+\/images\/file\?path=/.test(r))continue;e.removeAttribute(`src`);let i=rt(r);o.push(i),i.ready.then(t=>{a&&(e.setAttribute(`src`,t),e.setAttribute(`data-kobo-image-url`,r),n.value=s.innerHTML)}).catch(()=>{a&&(e.setAttribute(`title`,t()),n.value=s.innerHTML)})}n.value=s.innerHTML,i(()=>{a=!1;for(let e of o)e.release()})},{immediate:!0}),n}function at(e,t){return t?e.replace(/\[image:\s+([^\]]+)\]/g,(e,n)=>{let r=String(n).trim();return/^(\.ai\/images\/|images\/)/.test(r)?`![${r}](${`/api/workspaces/${encodeURIComponent(t)}/images/file?path=${encodeURIComponent(r)}`})`:e}):e}var ot=[`innerHTML`],st=[`innerHTML`],ct=[`src`],lt=B(T({__name:`UserMessageItem`,props:{item:{},workspaceId:{}},setup(e){let t=e,{t:r}=j(),a=x(()=>t.item.sender===`system-prompt`),s=it(x(()=>{let e=at(t.item.content,t.workspaceId);return ve(e)}),()=>r(`network.login.unreachable`)),c=o(null),d=o(!1),f;function p(){d.value=!1,c.value=null,f?.release(),f=void 0}l(d,e=>{e||p()}),l(()=>t.workspaceId,p);let v=e=>{(e.key===`kobo:network-token`||e.key===null)&&p()};window.addEventListener(`storage`,v),window.addEventListener(`kobo:auth-token-changed`,p),i(()=>{p(),window.removeEventListener(`kobo:auth-token-changed`,p),window.removeEventListener(`storage`,v)});function y(e){let t=e.target;if(t?.tagName!==`IMG`)return;let n=t;n.src&&(p(),n.dataset.koboImageUrl&&(f=rt(n.dataset.koboImageUrl),f.ready.catch(p)),c.value=n.src,d.value=!0)}return(e,t)=>(u(),S(C,null,[a.value?(u(),g(he,{key:0,dense:``,"dense-toggle":``,label:e.$t(`chat.systemPrompt`),"header-class":`text-kobo-2 text-caption`},{default:m(()=>[w(`div`,{class:`q-py-xs markdown-user-prompt`,innerHTML:n(s)},null,8,ot)]),_:1},8,[`label`])):(u(),S(`div`,{key:1,class:`markdown-message`,onClick:y},[w(`div`,{innerHTML:n(s)},null,8,st)])),h(ae,{modelValue:d.value,"onUpdate:modelValue":t[1]||=e=>d.value=e},{default:m(()=>[c.value?(u(),S(`img`,{key:0,src:c.value,alt:``,class:`image-lightbox-img`,onClick:t[0]||=e=>d.value=!1},null,8,ct)):_(``,!0)]),_:1},8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-db2fc622`]]),ut=[`data-event-ids`],dt={class:`turn-header`},ft={key:0,class:`turn-time`},pt={class:`turn-time turn-time-updated`},mt={key:2,class:`turn-actions`},ht={class:`turn-body`},gt={key:0,class:`turn-scroll-top`},_t=B(T({__name:`TurnCard`,props:{turn:{},workspaceId:{},highlighted:{type:Boolean}},emits:[`scrollTo`],setup(e,{emit:i}){let s=e,c=i,{t:l}=j(),d=o(null);function f(){let e=d.value;if(!e)return;let t=e.closest(`.q-scrollarea`)?.querySelector(`.q-scrollarea__content`);if(!t){e.scrollIntoView({behavior:`smooth`,block:`start`});return}let n=e.getBoundingClientRect().top-t.getBoundingClientRect().top;c(`scrollTo`,Math.max(0,n-8))}let p=x(()=>{switch(s.turn.speaker){case`user`:{let e=s.turn.items[0],t=e?.type===`user`?e.source:void 0;return{label:t?l(`chat.externalLlm`,{name:t.clientName}):l(`chat.you`),accent:`var(--kobo-turn-user)`,badgeClass:`turn-badge-user`}}case`agent`:return{label:l(`chat.agent`),accent:`var(--kobo-turn-agent)`,badgeClass:`turn-badge-agent`};case`system-prompt`:return{label:l(`chat.systemPrompt`),accent:`var(--kobo-text-3)`,badgeClass:`turn-badge-system`};case`session`:return{label:l(`chat.session`),accent:`var(--kobo-text-3)`,badgeClass:`turn-badge-session`};case`script`:{let e=s.turn.items[0],t=e?.type===`user`?e.sender:``;return{label:M(t)?l(`chat.hookScript`,{event:t.slice(5)}):l(t===`archive`?`chat.archiveScript`:t===`setup`?`chat.setupScript`:`chat.cleanupScript`),accent:`var(--kobo-success)`,badgeClass:`turn-badge-script`}}}});function y(e,t=!1){if(!e)return``;let n=new Date(e);return Number.isNaN(n.getTime())?``:n.toLocaleTimeString(void 0,t?{hour:`2-digit`,minute:`2-digit`,second:`2-digit`}:{hour:`2-digit`,minute:`2-digit`})}let b=x(()=>y(s.turn.ts)),T=x(()=>s.turn.items.flatMap(e=>e.eventIds??[]).join(` `)),E=x(()=>{let e=s.turn.items;if(e.length===0)return null;for(let t=e.length-1;t>=0;t--){let n=e[t].ts;if(n)return n}return null}),D=x(()=>{let e=s.turn.ts,t=E.value;if(!t||!e||t===e)return``;let n=new Date(e).getTime(),r=new Date(t).getTime();return Number.isNaN(n)||Number.isNaN(r)||r<=n?``:y(t,r-n<6e4)}),te=x(()=>D.value!==``),k=x(()=>s.turn.items.filter(e=>e.type===`tool`).length);return(i,o)=>(u(),S(`div`,{ref_key:`cardEl`,ref:d,class:r([`turn-card`,{"turn-card--user":e.turn.speaker===`user`,"turn-card--highlighted":e.highlighted}]),"data-event-ids":T.value,style:t({"--turn-accent":p.value.accent})},[w(`div`,dt,[w(`span`,{class:r([`turn-badge`,p.value.badgeClass])},a(p.value.label),3),b.value?(u(),S(`span`,ft,a(b.value),1)):_(``,!0),te.value?(u(),S(C,{key:1},[h(O,{name:`arrow_forward`,size:`10px`,color:`kobo-3`,class:`turn-time-arrow`}),w(`span`,pt,[v(a(D.value)+` `,1),h(V,null,{default:m(()=>[v(a(n(l)(`chat.lastUpdatedAt`,{time:D.value})),1)]),_:1})])],64)):_(``,!0),k.value>0?(u(),S(`span`,mt,` · `+a(n(l)(`chat.nActions`,{n:k.value})),1)):_(``,!0)]),w(`div`,ht,[(u(!0),S(C,null,ee(e.turn.items,t=>(u(),S(C,{key:n(je)(t)},[t.type===`text`?(u(),g(Y,{key:0,item:t},null,8,[`item`])):t.type===`thinking`?(u(),g(Ce,{key:1,item:t},null,8,[`item`])):t.type===`tool`?(u(),g(tt,{key:2,item:t},null,8,[`item`])):t.type===`user`?(u(),g(lt,{key:3,item:t,"workspace-id":e.workspaceId},null,8,[`item`,`workspace-id`])):t.type===`session`?(u(),g(Be,{key:4,item:t},null,8,[`item`])):t.type===`error`?(u(),g(ze,{key:5,item:t},null,8,[`item`])):_(``,!0)],64))),128))]),e.turn.items.length>4?(u(),S(`div`,gt,[h(ne,{flat:``,round:``,dense:``,size:`xs`,icon:`arrow_upward`,color:`kobo-3`,class:`turn-scroll-top-btn`,onClick:f},{default:m(()=>[h(V,null,{default:m(()=>[v(a(n(l)(`chat.scrollToTurnTop`)),1)]),_:1})]),_:1})])):_(``,!0)],14,ut))}}),[[`__scopeId`,`data-v-c0e24cbd`]]),vt={key:0,class:`activity-feed-switching`},yt={key:1,class:`activity-feed-wrap`,"data-tour":`ws-chat`},bt=[`aria-label`],xt={key:0,class:`activity-feed-compacting`},St={class:`text-caption text-kobo-2`},Ct={key:0,class:`text-center q-py-sm text-caption text-kobo-3`},wt={key:1,class:`activity-feed-empty q-pa-md`},Tt={class:`activity-feed-empty__title`},Et={class:`activity-feed-empty__hint`},Dt={key:2,class:`q-px-md q-pb-md`},Ot={class:`activity-feed-nav-cluster`},kt=300,At=60,jt=200,Mt=180,Nt=3,Pt=60,Ft=B(T({__name:`ActivityFeed`,props:{workspaceId:{}},setup(e){let{t}=j(),r=e,i=fe(),s=oe(),d=ce(),y=le(),b=x(()=>y.isCompacting(r.workspaceId)),T=x(()=>d.selectedSessionId),E=x(()=>d.sessions.find(e=>e.id===T.value)?.engineSessionId??null),D=x(()=>{let e=d.sessions;return e.length!==0&&T.value===e[e.length-1].id});function k(e){return T.value?e?e===T.value||e===E.value:D.value:!0}let A=x(()=>(d.activityFeeds[r.workspaceId]??[]).filter(e=>e.type===`text`&&typeof e.content==`string`&&k(e.sessionId)).map(e=>({content:e.content,sender:e.meta?.sender??`user`,source:se(e.meta?.source),ts:e.timestamp,sessionId:e.sessionId,eventIds:[e.id]}))),ie=x(()=>{let e=d.workspaces.find(e=>e.id===r.workspaceId);return de(e?.status)}),ae=Te(),M=``,N=x(()=>{let e=i.eventsFor(r.workspaceId),t=i.timestampsFor(r.workspaceId),n=i.sessionIdsFor(r.workspaceId),a=i.eventIdsFor(r.workspaceId),o=[],c=[],l=[];for(let r=0;r<e.length;r++)k(n[r])&&(o.push(e[r]),c.push(t[r]),l.push(a[r]??null));let u=`${r.workspaceId}::${T.value??`*`}`;u!==M&&(ae=Te(),M=u);let d=Se(ae,o,c,ie.value,l);return Ae(we(d,A.value).filter(e=>e.type===`thinking`?!1:e.type===`session`?e.kind===`ended`?s.showVerboseSystemMessages||!xe(e.detail):s.showVerboseSystemMessages:!0))}),P=x(()=>s.showVerboseSystemMessages?i.eventsFor(r.workspaceId).filter(e=>e.kind===`message:raw`).map(e=>e.content):[]),ue=x(()=>{for(let e=N.value.length-1;e>=0;e--){let n=N.value[e]?.items??[];for(let e=n.length-1;e>=0;e--){let r=n[e];if(r){if(r.type===`text`&&!r.streaming)return{key:`text:${r.messageId}`,text:r.text};if(r.type===`tool`)return r.result?{key:`tool:${r.toolCallId}:end`,text:r.result.isError?t(`activity.a11y.toolFailed`,{name:r.name}):t(`activity.a11y.toolFinished`,{name:r.name})}:{key:`tool:${r.toolCallId}:start`,text:t(`activity.a11y.toolStarted`,{name:r.name})}}}}return null}),me=o(``);l(ue,(e,n)=>{if(!e||e.key===n?.key)return;let r=e.key.startsWith(`text:`)?t(`activity.a11y.agentSaid`,{text:e.text.slice(0,kt)}):e.text;me.value=r});let F=o(null),I=o(!0),L=o(!1),R=o(null),z=!1,B=o(new Set),V=x(()=>{if(N.value.length>0||P.value.length>0)return!1;let e=r.workspaceId,t=T.value;return!!d.loadingSessions[e]||y.isSyncPending(e)||t!==null&&B.value.has(H(e,t))}),_e=o(new Map);function ve(e){let t=e.verticalSize-e.verticalPosition-e.verticalContainerSize;I.value=t<=At,z&&e.verticalPosition<=jt&&!L.value&&ye()&&Ee()}function H(e,t){return`${e}:${t}`}function ye(){let e=T.value;return e?_e.value.get(H(r.workspaceId,e))??!0:i.hasMoreOlderFor(r.workspaceId)}function be(e,t,n){_e.value.set(H(e,t),n)}function Ce(e){if(!T.value)return i.oldestIdFor(e);let t=i.eventIdsFor(e),n=i.sessionIdsFor(e);for(let e=0;e<t.length;e++){if(!k(n[e]))continue;let r=t[e];if(r)return r}}let U=null;function Ee(){return U||(U=De().finally(()=>{U=null}),U)}async function De(){let e=r.workspaceId,t=T.value,n=Ce(e);if(n){L.value=!0;try{let r=F.value;await f();let a=r?.getScroll().verticalSize??0,o=r?.getScroll().verticalPosition??0,s=new URLSearchParams({before:n,limit:`200`});t&&s.set(`session`,t);let c=await fetch(`/api/workspaces/${e}/events?${s.toString()}`);if(!c.ok){t?be(e,t,!1):i.prepend(e,[],[],{oldestId:n,hasMoreOlder:!1});return}let l=await c.json(),u=l.events??[],p=u.filter(t=>t.type===`agent:event`&&t.workspaceId===e),m=u.filter(t=>t.type===`user:message`&&t.workspaceId===e),h=p.map(e=>e.payload),g=p.map(e=>e.createdAt),_=p.map(e=>e.sessionId??null),v=p.map(e=>e.id),y=u.length>0?u[0].id:n;t&&be(e,t,l.hasMore),i.prepend(e,h,g,{oldestId:y,hasMoreOlder:t?i.hasMoreOlderFor(e):l.hasMore,sessionIds:_,eventIds:v});for(let t of m){let n=t.payload;typeof n.content==`string`&&d.addActivityItem(e,{id:t.id,type:`text`,content:n.content,timestamp:t.createdAt,sessionId:t.sessionId??void 0,meta:{sender:n.sender??`user`,source:se(n.source)}})}if(await f(),r){let e=r.getScroll().verticalSize-a;if(e>0){let t=Math.max(o+e,250);r.setScrollPosition(`vertical`,t,0)}}}catch(e){console.error(`[ActivityFeed] failed to load older events:`,e)}finally{L.value=!1}}}async function W(e=0){await f();let t=F.value;if(!t)return;let n=t.getScroll();t.setScrollPosition(`vertical`,n.verticalSize,e)}let G=null,ke=0;function je(){if(G!=null)return;let e=performance.now()-ke<Mt;G=requestAnimationFrame(()=>{G=null,ke=performance.now(),W(e?0:180)})}function Fe(e){let t=F.value;t&&t.setScrollPosition(`vertical`,Math.max(0,e),250)}function Ie(){let e=window.location.hash,t=e.indexOf(`?`);if(t===-1||!new URLSearchParams(e.slice(t+1)).has(`eventId`))return;let n=e.slice(0,t);window.history.replaceState(window.history.state,``,`${window.location.pathname}${window.location.search}${n}`)}async function Le(e){let t=e.detail;if(t?.workspaceId===r.workspaceId&&t.eventId)try{let e=new URLSearchParams({around:t.eventId,limit:`200`});t.sessionId&&e.set(`session`,t.sessionId);let n=await fetch(`/api/workspaces/${r.workspaceId}/events?${e}`);if(!n.ok)return;let a=await n.json(),o=a.events??[],s=o.filter(e=>e.type===`agent:event`&&e.workspaceId===r.workspaceId),c=o.filter(e=>e.type===`user:message`&&e.workspaceId===r.workspaceId);i.reset(r.workspaceId,s.map(e=>e.payload),s.map(e=>e.createdAt),{oldestId:o[0]?.id,hasMoreOlder:a.hasMore??!1,sessionIds:s.map(e=>e.sessionId),eventIds:s.map(e=>e.id)});for(let e of c){let t=e.payload;typeof t.content==`string`&&d.addActivityItem(r.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`,source:se(t.source)}})}await Pe(V,e=>!e,5e3),await f(),await new Promise(e=>requestAnimationFrame(()=>requestAnimationFrame(()=>e())));let l=N.value.findIndex(e=>e.items.some(e=>e.eventIds?.includes(t.eventId)??!1));if(l<0)return;R.value=t.eventId,Re.value?.scrollTo(l,`center`),K.value=l,window.setTimeout(()=>{R.value===t.eventId&&(R.value=null)},1800)}catch(e){console.error(`[ActivityFeed] failed to focus history event:`,e)}}let Re=o(null),ze=o(null),K=o(0);function Be(e){K.value=e.index}let q=o(!1);async function Ve(){if(q.value)return;q.value=!0;let e=r.workspaceId;try{let t=Ne(N.value,K.value);if(t<0)for(let n=0;n<15;n++){if(e!==r.workspaceId)return;if(!ye())break;let n=N.value.length;if(await Ee(),await f(),e!==r.workspaceId)return;if(K.value+=N.value.length-n,t=Ne(N.value,K.value),t>=0)break}t>=0&&e===r.workspaceId&&(Re.value?.scrollTo(t,`start`),K.value=t)}finally{q.value=!1}}let J=0;function He(){return new Promise(e=>requestAnimationFrame(()=>e()))}async function Y(){z=!1;let e=++J;await f();let t=-1,n=0;for(let r=0;r<Pt&&n<Nt;r++){if(e!==J)return;await W(0),await He();let r=F.value?.getScroll().verticalSize??0;n=r===t?n+1:0,t=r}e===J&&(z=!0)}function Ue(){z||=(J++,!0)}let X=x(()=>{let e=i.sessionIdsFor(r.workspaceId);if(!T.value)return e.length;let t=0;for(let n of e)k(n)&&t++;return t});l(V,async e=>{!e&&X.value>0&&await Y(),e||f(()=>{ze.value=F.value?.getScrollTarget()??null})}),p(()=>{window.addEventListener(`kobo:focus-history-event`,Le),f(()=>{ze.value=F.value?.getScrollTarget()??null}),X.value>0&&Y(),T.value&&Ke();let e=new URLSearchParams(window.location.hash.split(`?`)[1]??``).get(`eventId`);e&&(Le(new CustomEvent(`kobo:focus-history-event`,{detail:{workspaceId:r.workspaceId,sessionId:T.value,eventId:e}})),Ie())});let We=X.value>0;l(X,async e=>{L.value||!We&&e>0&&(We=!0,await Y())});let Ge=x(()=>i.liveAppendCountFor(r.workspaceId,k)),Z=()=>`${r.workspaceId}\u0000${d.selectedSessionId??``}`;l([Ge,Z],([e,t],[n,r])=>{t===r&&e>n&&I.value&&!L.value&&je()}),c(()=>{window.removeEventListener(`kobo:focus-history-event`,Le),G!=null&&(cancelAnimationFrame(G),G=null)}),l(()=>r.workspaceId,()=>{I.value=!0,We=X.value>0,z=!1,Ke(),X.value>0&&Y()}),l(()=>d.selectedSessionId,async()=>{I.value=!0,z=!1,Ke(),await Y()});let Q=new Set;async function Ke(){let e=r.workspaceId,t=T.value;if(!t||X.value>0)return;let n=H(e,t);if(!Q.has(n)){Q.add(n),B.value.add(n);try{let a=await fetch(`/api/workspaces/${e}/events?session=${encodeURIComponent(t)}&limit=500`);if(!a.ok){Q.delete(n);return}let o=await a.json(),s=o.events??[];if(s.length===0)return;let c=s.filter(t=>t.type===`agent:event`&&t.workspaceId===e),l=s.filter(t=>t.type===`user:message`&&t.workspaceId===e),u=c.map(e=>e.payload),p=c.map(e=>e.createdAt),m=c.map(e=>e.sessionId??null),h=c.map(e=>e.id);be(e,t,o.hasMore),u.length>0&&i.prepend(e,u,p,{oldestId:s[0].id,hasMoreOlder:i.hasMoreOlderFor(e),sessionIds:m,eventIds:h});for(let t of l){let n=t.payload;typeof n.content==`string`&&d.addActivityItem(e,{id:t.id,type:`text`,content:n.content,timestamp:t.createdAt,sessionId:t.sessionId??void 0,meta:{sender:n.sender??`user`,source:se(n.source)}})}await f(),r.workspaceId===e&&T.value===t&&await W(0)}catch(e){console.error(`[ActivityFeed] fetchSessionIfMissing failed:`,e),Q.delete(n)}finally{B.value.delete(n)}}}let qe=x(()=>A.value.filter(e=>e.sender!==`system-prompt`).length);l([qe,Z],async([e,t],[n,r])=>{t===r&&e>n&&(I.value=!0,await W(180))});async function Je(){I.value=!0,await W(250)}return(e,t)=>V.value?(u(),S(`div`,vt,[h(pe,{size:`40px`,color:`primary`})])):(u(),S(`div`,yt,[w(`div`,{"data-testid":`activity-live-region`,class:`sr-only`,role:`log`,"aria-live":`polite`,"aria-atomic":`true`,"aria-label":e.$t(`activity.a11y.region`)},a(me.value),9,bt),h(te,{name:`fade`},{default:m(()=>[b.value?(u(),S(`div`,xt,[h(pe,{size:`18px`,color:`primary`}),w(`span`,St,a(e.$t(`activity.compacting`)),1)])):_(``,!0)]),_:1}),h(ge,{ref_key:`scrollRef`,ref:F,class:`activity-feed-scroll`,onScroll:ve,onWheelPassive:Ue,onTouchstartPassive:Ue,onKeydown:Ue},{default:m(()=>[L.value?(u(),S(`div`,Ct,[h(re,{size:`sm`}),v(` `+a(e.$t(`activity.loading_older`)),1)])):_(``,!0),h(Oe,{ref_key:`virtualScrollRef`,ref:Re,class:`q-pa-md`,items:N.value,"scroll-target":ze.value??void 0,"virtual-scroll-item-size":160,"virtual-scroll-slice-size":20,onVirtualScroll:Be},{default:m(({item:e,index:t})=>[(u(),g(_t,{key:n(Me)(e),turn:e,"workspace-id":r.workspaceId,"data-turn-index":t,highlighted:e.items.some(e=>e.eventIds?.includes(R.value??``)??!1),onScrollTo:Fe},null,8,[`turn`,`workspace-id`,`data-turn-index`,`highlighted`]))]),_:1},8,[`items`,`scroll-target`]),N.value.length===0&&P.value.length===0&&!L.value?(u(),S(`div`,wt,[h(O,{name:`forum`,size:`28px`}),w(`div`,Tt,a(e.$t(`activity.empty`)),1),w(`div`,Et,a(e.$t(`activity.emptyHint`)),1)])):_(``,!0),P.value.length?(u(),S(`div`,Dt,[h(he,{label:e.$t(`activity.raw_lines`,{n:P.value.length}),dense:``},{default:m(()=>[(u(!0),S(C,null,ee(P.value,(e,t)=>(u(),S(`div`,{key:t,class:`text-caption text-kobo-3 q-pa-xs`},a(e),1))),128))]),_:1},8,[`label`])])):_(``,!0)]),_:1},512),w(`div`,Ot,[I.value?_(``,!0):(u(),g(ne,{key:0,round:``,dense:``,unelevated:``,color:`kobo-surface-2`,"text-color":`kobo-1`,icon:`arrow_downward`,size:`sm`,class:`activity-feed-nav-btn`,title:e.$t(`activity.scroll_to_bottom`),"aria-label":e.$t(`activity.scroll_to_bottom`),onClick:Je},null,8,[`title`,`aria-label`])),h(ne,{round:``,dense:``,unelevated:``,color:`kobo-surface-2`,"text-color":`kobo-1`,icon:`arrow_upward`,size:`sm`,class:`activity-feed-nav-btn`,title:e.$t(`activity.prev_user_message`),"aria-label":e.$t(`activity.prev_user_message`),loading:q.value,disable:q.value,onClick:Ve},null,8,[`title`,`aria-label`,`loading`,`disable`])])]))}}),[[`__scopeId`,`data-v-028e8af5`]]);export{Ft as default};
@@ -1 +1 @@
1
- .agent-error-item[data-v-e98c3c02]{gap:var(--kobo-space-sm);padding:var(--kobo-space-sm) var(--kobo-space-md);border-left:2px solid var(--kobo-danger);background:var(--kobo-surface-2);border-radius:var(--kobo-radius-sm);align-items:flex-start;display:flex}.agent-error-item__icon[data-v-e98c3c02]{color:var(--kobo-danger);flex:none;margin-top:2px}.agent-error-item__body[data-v-e98c3c02]{min-width:0}.agent-error-item__title[data-v-e98c3c02]{color:var(--kobo-text);font-weight:600}.agent-error-item__message[data-v-e98c3c02]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;word-break:break-word;font-size:12px}.markdown-message[data-v-99371035]{color:var(--kobo-text-2);word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-99371035] *{max-width:100%}.markdown-message[data-v-99371035] p{margin:0 0 .5em}.markdown-message[data-v-99371035] p:last-child{margin-bottom:0}.markdown-message[data-v-99371035] pre{background:#00000059;border-radius:4px;margin:.5em 0;padding:.5em .75em;overflow-x:auto}.markdown-message[data-v-99371035] code{word-break:break-all;background:#0000004d;border-radius:3px;padding:.1em .3em;font-size:.9em}.markdown-message[data-v-99371035] pre code{background:0 0;padding:0}.markdown-message[data-v-99371035] ul,.markdown-message[data-v-99371035] ol{margin:.25em 0 .5em;padding-left:1.5em}.markdown-message[data-v-99371035] li{margin:.15em 0}.markdown-message[data-v-99371035] a{color:var(--kobo-text-2);text-decoration:underline}.markdown-message[data-v-99371035] .document-link{color:var(--kobo-text-2);cursor:pointer;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.markdown-message[data-v-99371035] .document-link:hover{color:var(--kobo-text);-webkit-text-decoration:underline;text-decoration:underline}.markdown-message[data-v-99371035] h1,.markdown-message[data-v-99371035] h2,.markdown-message[data-v-99371035] h3,.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{margin:.5em 0 .3em;font-weight:600;line-height:1.3}.markdown-message[data-v-99371035] h1{font-size:1.25em}.markdown-message[data-v-99371035] h2{font-size:1.15em}.markdown-message[data-v-99371035] h3{font-size:1.08em}.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{font-size:1em}.markdown-message[data-v-99371035] blockquote{color:#ffffffb3;border-left:3px solid #fff3;margin:.5em 0;padding-left:.75em}.markdown-message[data-v-99371035] table{border-collapse:collapse;margin:.5em 0}.markdown-message[data-v-99371035] th,.markdown-message[data-v-99371035] td{border:1px solid #ffffff26;padding:.25em .5em}.tool-row[data-v-2482adfe]{border-radius:4px;margin:0;font-size:12px}.tool-header[data-v-2482adfe]{color:var(--kobo-text-2);cursor:default;align-items:center;gap:10px;min-width:0;padding:5px 10px;display:flex}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe],.tool-row--toggleable .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:has(.tool-diff) .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe]:hover,.tool-row--toggleable .tool-header[data-v-2482adfe]:hover{background:#ffffff08}.tool-icon[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0}.tool-name[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0;font-weight:600}.tool-arg[data-v-2482adfe],.tool-path[data-v-2482adfe]{color:var(--kobo-text-3);text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%;font-family:var(--kobo-font-mono);font-size:11.5px;overflow:hidden}.tool-open-diff[data-v-2482adfe]{flex-shrink:0}.tool-path[data-v-2482adfe],.tool-arg[data-v-2482adfe]{flex:1}.tool-stat-add[data-v-2482adfe]{color:var(--kobo-success);flex-shrink:0;font-size:11px;font-weight:600}.tool-stat-del[data-v-2482adfe]{color:var(--kobo-danger);flex-shrink:0;font-size:11px;font-weight:600}.tool-diff[data-v-2482adfe]{max-height:400px;font-family:var(--kobo-font-mono);background:#0003;border-radius:4px;margin-top:4px;padding:8px 0;font-size:11px;line-height:1.5;overflow:auto}.diff-line[data-v-2482adfe]{white-space:pre;color:var(--kobo-text-2);padding:0 12px}.diff-sign[data-v-2482adfe]{width:14px;color:var(--kobo-text-disabled);-webkit-user-select:none;user-select:none;display:inline-block}.diff-add[data-v-2482adfe]{color:var(--kobo-success);background:#66bb6a1a}.diff-add .diff-sign[data-v-2482adfe]{color:var(--kobo-success)}.diff-del[data-v-2482adfe]{color:var(--kobo-danger);background:#ef53501a}.diff-del .diff-sign[data-v-2482adfe]{color:var(--kobo-danger)}.tool-output[data-v-2482adfe]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;background:#00000026;border-radius:4px;max-height:8em;margin-top:4px;padding:6px 10px;font-size:11px;overflow:auto}.markdown-message[data-v-db2fc622]{color:var(--kobo-text-2);word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-db2fc622] *{max-width:100%}.markdown-message[data-v-db2fc622] img{-o-object-fit:contain;object-fit:contain;cursor:zoom-in;background:#0003;border-radius:4px;max-width:180px;max-height:100px;margin:.3em 0;display:block}.markdown-message[data-v-db2fc622] code{word-break:break-all}.markdown-message[data-v-db2fc622] p{margin:0 0 .4em}.markdown-message[data-v-db2fc622] p:last-child{margin-bottom:0}.markdown-message[data-v-db2fc622] code{background:#00000040;border-radius:3px;padding:.1em .3em}.markdown-message[data-v-db2fc622] h1,.markdown-message[data-v-db2fc622] h2,.markdown-message[data-v-db2fc622] h3,.markdown-message[data-v-db2fc622] h4,.markdown-message[data-v-db2fc622] h5,.markdown-message[data-v-db2fc622] h6{margin:.4em 0 .25em;font-weight:600;line-height:1.3}.markdown-message[data-v-db2fc622] h1{font-size:1.25em}.markdown-message[data-v-db2fc622] h2{font-size:1.15em}.markdown-message[data-v-db2fc622] h3{font-size:1.08em}.markdown-message[data-v-db2fc622] h4,.markdown-message[data-v-db2fc622] h5,.markdown-message[data-v-db2fc622] h6{font-size:1em}.markdown-user-prompt[data-v-db2fc622]{color:var(--kobo-text-2);font-size:12px;font-style:italic}.markdown-user-prompt[data-v-db2fc622] p{margin:0 0 .4em}.markdown-user-prompt[data-v-db2fc622] code{background:#ffffff14;border-radius:3px;padding:.1em .3em;font-style:normal}.image-lightbox-img{-o-object-fit:contain;object-fit:contain;cursor:zoom-out;background:#0000004d;border-radius:4px;max-width:92vw;max-height:92vh;display:block}.turn-card[data-v-c0e24cbd]{border:1px solid #ffffff14;border-left:3px solid var(--turn-accent);background:#ffffff05;border-radius:6px;min-width:0;max-width:100%;margin:14px 0;overflow:hidden}.turn-card--highlighted[data-v-c0e24cbd]{animation:1.8s ease-out search-highlight-c0e24cbd}@keyframes search-highlight-c0e24cbd{0%,45%{box-shadow:0 0 0 2px #818cf8f2,0 0 22px #818cf873}to{box-shadow:none}}.turn-header[data-v-c0e24cbd]{color:var(--kobo-text-3);background:#ffffff08;border-bottom:1px solid #ffffff0d;align-items:center;gap:8px;padding:8px 14px;font-size:11px;display:flex}.turn-badge[data-v-c0e24cbd]{letter-spacing:.3px;border-radius:3px;padding:2px 8px;font-size:11px;font-weight:700}.turn-badge-user[data-v-c0e24cbd]{color:var(--kobo-turn-user);background:#ce93d826}.turn-badge-agent[data-v-c0e24cbd]{color:var(--kobo-turn-agent);background:#7986cb26}.turn-badge-system[data-v-c0e24cbd]{color:var(--kobo-text-2);background:#75757533;font-style:italic}.turn-badge-session[data-v-c0e24cbd]{color:var(--kobo-text-3);background:#61616133}.turn-badge-script[data-v-c0e24cbd]{color:var(--kobo-success);background:#4db6ac26}.turn-time[data-v-c0e24cbd]{color:var(--kobo-text-disabled);font-family:var(--kobo-font-mono);font-size:11px}.turn-time-arrow[data-v-c0e24cbd]{opacity:.7;margin:0 -2px}.turn-time-updated[data-v-c0e24cbd]{color:var(--kobo-text-3)}.turn-actions[data-v-c0e24cbd]{color:var(--kobo-text-3);font-size:11px}.turn-body[data-v-c0e24cbd]{flex-direction:column;gap:12px;min-width:0;padding:14px 18px;display:flex}.turn-body[data-v-c0e24cbd]>*{min-width:0;max-width:100%}.turn-body[data-v-c0e24cbd] .tool-row+.tool-row{margin-top:-8px}.turn-scroll-top[data-v-c0e24cbd]{justify-content:flex-start;padding:0 8px 6px;display:flex}.turn-scroll-top-btn[data-v-c0e24cbd]{opacity:.5;transition:opacity .15s}.turn-scroll-top-btn[data-v-c0e24cbd]:hover{opacity:1}.activity-feed-wrap[data-v-de033437]{width:100%;height:100%;position:relative}.activity-feed-scroll[data-v-de033437]{width:100%;height:100%}.activity-feed-nav-cluster[data-v-de033437]{z-index:2;align-items:center;gap:8px;display:flex;position:absolute;bottom:14px;right:14px}.activity-feed-compacting[data-v-de033437]{z-index:3;background:var(--kobo-surface);border:1px solid var(--kobo-border);border-radius:6px;align-items:center;gap:8px;padding:6px 14px;display:flex;position:absolute;top:12px;left:50%;transform:translate(-50%);box-shadow:0 4px 16px #00000059}.fade-enter-active[data-v-de033437],.fade-leave-active[data-v-de033437]{transition:opacity .16s}.fade-enter-from[data-v-de033437],.fade-leave-to[data-v-de033437]{opacity:0}.activity-feed-nav-btn[data-v-de033437]{opacity:.8;transition:opacity .12s}.activity-feed-nav-btn[data-v-de033437]:hover{opacity:1}.activity-feed-scroll[data-v-de033437] .q-scrollarea__content{max-width:100%;overflow-x:hidden}.activity-feed-switching[data-v-de033437]{justify-content:center;align-items:center;width:100%;height:100%;display:flex}.activity-feed-empty[data-v-de033437]{align-items:center;gap:var(--kobo-space-sm);padding:var(--kobo-space-4xl) var(--kobo-space-xl);color:var(--kobo-text-3);text-align:center;flex-direction:column;display:flex}.activity-feed-empty__title[data-v-de033437]{font-family:var(--kobo-font-sans);color:var(--kobo-text-2);font-size:14px;font-weight:500}.activity-feed-empty__hint[data-v-de033437]{font-family:var(--kobo-font-sans);color:var(--kobo-text-3);max-width:380px;font-size:13px}
1
+ .agent-error-item[data-v-e98c3c02]{gap:var(--kobo-space-sm);padding:var(--kobo-space-sm) var(--kobo-space-md);border-left:2px solid var(--kobo-danger);background:var(--kobo-surface-2);border-radius:var(--kobo-radius-sm);align-items:flex-start;display:flex}.agent-error-item__icon[data-v-e98c3c02]{color:var(--kobo-danger);flex:none;margin-top:2px}.agent-error-item__body[data-v-e98c3c02]{min-width:0}.agent-error-item__title[data-v-e98c3c02]{color:var(--kobo-text);font-weight:600}.agent-error-item__message[data-v-e98c3c02]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;word-break:break-word;font-size:12px}.markdown-message[data-v-99371035]{color:var(--kobo-text-2);word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-99371035] *{max-width:100%}.markdown-message[data-v-99371035] p{margin:0 0 .5em}.markdown-message[data-v-99371035] p:last-child{margin-bottom:0}.markdown-message[data-v-99371035] pre{background:#00000059;border-radius:4px;margin:.5em 0;padding:.5em .75em;overflow-x:auto}.markdown-message[data-v-99371035] code{word-break:break-all;background:#0000004d;border-radius:3px;padding:.1em .3em;font-size:.9em}.markdown-message[data-v-99371035] pre code{background:0 0;padding:0}.markdown-message[data-v-99371035] ul,.markdown-message[data-v-99371035] ol{margin:.25em 0 .5em;padding-left:1.5em}.markdown-message[data-v-99371035] li{margin:.15em 0}.markdown-message[data-v-99371035] a{color:var(--kobo-text-2);text-decoration:underline}.markdown-message[data-v-99371035] .document-link{color:var(--kobo-text-2);cursor:pointer;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.markdown-message[data-v-99371035] .document-link:hover{color:var(--kobo-text);-webkit-text-decoration:underline;text-decoration:underline}.markdown-message[data-v-99371035] h1,.markdown-message[data-v-99371035] h2,.markdown-message[data-v-99371035] h3,.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{margin:.5em 0 .3em;font-weight:600;line-height:1.3}.markdown-message[data-v-99371035] h1{font-size:1.25em}.markdown-message[data-v-99371035] h2{font-size:1.15em}.markdown-message[data-v-99371035] h3{font-size:1.08em}.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{font-size:1em}.markdown-message[data-v-99371035] blockquote{color:#ffffffb3;border-left:3px solid #fff3;margin:.5em 0;padding-left:.75em}.markdown-message[data-v-99371035] table{border-collapse:collapse;margin:.5em 0}.markdown-message[data-v-99371035] th,.markdown-message[data-v-99371035] td{border:1px solid #ffffff26;padding:.25em .5em}.tool-row[data-v-2482adfe]{border-radius:4px;margin:0;font-size:12px}.tool-header[data-v-2482adfe]{color:var(--kobo-text-2);cursor:default;align-items:center;gap:10px;min-width:0;padding:5px 10px;display:flex}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe],.tool-row--toggleable .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:has(.tool-diff) .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe]:hover,.tool-row--toggleable .tool-header[data-v-2482adfe]:hover{background:#ffffff08}.tool-icon[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0}.tool-name[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0;font-weight:600}.tool-arg[data-v-2482adfe],.tool-path[data-v-2482adfe]{color:var(--kobo-text-3);text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%;font-family:var(--kobo-font-mono);font-size:11.5px;overflow:hidden}.tool-open-diff[data-v-2482adfe]{flex-shrink:0}.tool-path[data-v-2482adfe],.tool-arg[data-v-2482adfe]{flex:1}.tool-stat-add[data-v-2482adfe]{color:var(--kobo-success);flex-shrink:0;font-size:11px;font-weight:600}.tool-stat-del[data-v-2482adfe]{color:var(--kobo-danger);flex-shrink:0;font-size:11px;font-weight:600}.tool-diff[data-v-2482adfe]{max-height:400px;font-family:var(--kobo-font-mono);background:#0003;border-radius:4px;margin-top:4px;padding:8px 0;font-size:11px;line-height:1.5;overflow:auto}.diff-line[data-v-2482adfe]{white-space:pre;color:var(--kobo-text-2);padding:0 12px}.diff-sign[data-v-2482adfe]{width:14px;color:var(--kobo-text-disabled);-webkit-user-select:none;user-select:none;display:inline-block}.diff-add[data-v-2482adfe]{color:var(--kobo-success);background:#66bb6a1a}.diff-add .diff-sign[data-v-2482adfe]{color:var(--kobo-success)}.diff-del[data-v-2482adfe]{color:var(--kobo-danger);background:#ef53501a}.diff-del .diff-sign[data-v-2482adfe]{color:var(--kobo-danger)}.tool-output[data-v-2482adfe]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;background:#00000026;border-radius:4px;max-height:8em;margin-top:4px;padding:6px 10px;font-size:11px;overflow:auto}.markdown-message[data-v-db2fc622]{color:var(--kobo-text-2);word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-db2fc622] *{max-width:100%}.markdown-message[data-v-db2fc622] img{-o-object-fit:contain;object-fit:contain;cursor:zoom-in;background:#0003;border-radius:4px;max-width:180px;max-height:100px;margin:.3em 0;display:block}.markdown-message[data-v-db2fc622] code{word-break:break-all}.markdown-message[data-v-db2fc622] p{margin:0 0 .4em}.markdown-message[data-v-db2fc622] p:last-child{margin-bottom:0}.markdown-message[data-v-db2fc622] code{background:#00000040;border-radius:3px;padding:.1em .3em}.markdown-message[data-v-db2fc622] h1,.markdown-message[data-v-db2fc622] h2,.markdown-message[data-v-db2fc622] h3,.markdown-message[data-v-db2fc622] h4,.markdown-message[data-v-db2fc622] h5,.markdown-message[data-v-db2fc622] h6{margin:.4em 0 .25em;font-weight:600;line-height:1.3}.markdown-message[data-v-db2fc622] h1{font-size:1.25em}.markdown-message[data-v-db2fc622] h2{font-size:1.15em}.markdown-message[data-v-db2fc622] h3{font-size:1.08em}.markdown-message[data-v-db2fc622] h4,.markdown-message[data-v-db2fc622] h5,.markdown-message[data-v-db2fc622] h6{font-size:1em}.markdown-user-prompt[data-v-db2fc622]{color:var(--kobo-text-2);font-size:12px;font-style:italic}.markdown-user-prompt[data-v-db2fc622] p{margin:0 0 .4em}.markdown-user-prompt[data-v-db2fc622] code{background:#ffffff14;border-radius:3px;padding:.1em .3em;font-style:normal}.image-lightbox-img{-o-object-fit:contain;object-fit:contain;cursor:zoom-out;background:#0000004d;border-radius:4px;max-width:92vw;max-height:92vh;display:block}.turn-card[data-v-c0e24cbd]{border:1px solid #ffffff14;border-left:3px solid var(--turn-accent);background:#ffffff05;border-radius:6px;min-width:0;max-width:100%;margin:14px 0;overflow:hidden}.turn-card--highlighted[data-v-c0e24cbd]{animation:1.8s ease-out search-highlight-c0e24cbd}@keyframes search-highlight-c0e24cbd{0%,45%{box-shadow:0 0 0 2px #818cf8f2,0 0 22px #818cf873}to{box-shadow:none}}.turn-header[data-v-c0e24cbd]{color:var(--kobo-text-3);background:#ffffff08;border-bottom:1px solid #ffffff0d;align-items:center;gap:8px;padding:8px 14px;font-size:11px;display:flex}.turn-badge[data-v-c0e24cbd]{letter-spacing:.3px;border-radius:3px;padding:2px 8px;font-size:11px;font-weight:700}.turn-badge-user[data-v-c0e24cbd]{color:var(--kobo-turn-user);background:#ce93d826}.turn-badge-agent[data-v-c0e24cbd]{color:var(--kobo-turn-agent);background:#7986cb26}.turn-badge-system[data-v-c0e24cbd]{color:var(--kobo-text-2);background:#75757533;font-style:italic}.turn-badge-session[data-v-c0e24cbd]{color:var(--kobo-text-3);background:#61616133}.turn-badge-script[data-v-c0e24cbd]{color:var(--kobo-success);background:#4db6ac26}.turn-time[data-v-c0e24cbd]{color:var(--kobo-text-disabled);font-family:var(--kobo-font-mono);font-size:11px}.turn-time-arrow[data-v-c0e24cbd]{opacity:.7;margin:0 -2px}.turn-time-updated[data-v-c0e24cbd]{color:var(--kobo-text-3)}.turn-actions[data-v-c0e24cbd]{color:var(--kobo-text-3);font-size:11px}.turn-body[data-v-c0e24cbd]{flex-direction:column;gap:12px;min-width:0;padding:14px 18px;display:flex}.turn-body[data-v-c0e24cbd]>*{min-width:0;max-width:100%}.turn-body[data-v-c0e24cbd] .tool-row+.tool-row{margin-top:-8px}.turn-scroll-top[data-v-c0e24cbd]{justify-content:flex-start;padding:0 8px 6px;display:flex}.turn-scroll-top-btn[data-v-c0e24cbd]{opacity:.5;transition:opacity .15s}.turn-scroll-top-btn[data-v-c0e24cbd]:hover{opacity:1}.activity-feed-wrap[data-v-028e8af5]{width:100%;height:100%;position:relative}.activity-feed-scroll[data-v-028e8af5]{width:100%;height:100%}.activity-feed-nav-cluster[data-v-028e8af5]{z-index:2;align-items:center;gap:8px;display:flex;position:absolute;bottom:14px;right:14px}.activity-feed-compacting[data-v-028e8af5]{z-index:3;background:var(--kobo-surface);border:1px solid var(--kobo-border);border-radius:6px;align-items:center;gap:8px;padding:6px 14px;display:flex;position:absolute;top:12px;left:50%;transform:translate(-50%);box-shadow:0 4px 16px #00000059}.fade-enter-active[data-v-028e8af5],.fade-leave-active[data-v-028e8af5]{transition:opacity .16s}.fade-enter-from[data-v-028e8af5],.fade-leave-to[data-v-028e8af5]{opacity:0}.activity-feed-nav-btn[data-v-028e8af5]{opacity:.8;transition:opacity .12s}.activity-feed-nav-btn[data-v-028e8af5]:hover{opacity:1}.activity-feed-scroll[data-v-028e8af5] .q-scrollarea__content{max-width:100%;overflow-x:hidden}.activity-feed-switching[data-v-028e8af5]{justify-content:center;align-items:center;width:100%;height:100%;display:flex}.activity-feed-empty[data-v-028e8af5]{align-items:center;gap:var(--kobo-space-sm);padding:var(--kobo-space-4xl) var(--kobo-space-xl);color:var(--kobo-text-3);text-align:center;flex-direction:column;display:flex}.activity-feed-empty__title[data-v-028e8af5]{font-family:var(--kobo-font-sans);color:var(--kobo-text-2);font-size:14px;font-weight:500}.activity-feed-empty__hint[data-v-028e8af5]{font-family:var(--kobo-font-sans);color:var(--kobo-text-3);max-width:380px;font-size:13px}
@@ -1 +1 @@
1
- import{j as e,ut as t,v as n}from"./reactivity.esm-bundler-Bo9anJjg.js";import{L as r,P as i,Y as a,_ as o,d as s,f as c,p as l,r as u,u as d,y as f,z as p}from"./runtime-core.esm-bundler-CNFKm4ij.js";import{t as m}from"./QBtn-DEdx_Y1V.js";import{i as h,rn as g,tn as _}from"./index-CqZ7sDcM.js";import{a as v,i as y,n as b}from"./use-tours-CNe8qb1q.js";import{n as x}from"./render-chat-markdown-TU6CDfD8.js";import{t as S}from"./QChip-DCPUhqXX.js";import{t as C}from"./QPage-BXBw2Alx.js";import{t as w}from"./DrawerToggleButton-DbipGmBL.js";import{t as T}from"./TourReplayButton-CpEMnQS8.js";var E={class:`row items-center q-mb-md`},D={class:`text-h6 q-ml-sm`},O={key:0,class:`text-kobo-3 text-center q-pa-lg`},k={key:1,class:`text-negative text-center q-pa-lg`},A={key:2,class:`text-kobo-3 text-center q-pa-lg`},j={key:3,class:`column q-gutter-md`,"data-tour":`changelog-list`},M={key:0,class:`text-caption text-kobo-3`},N={class:`row items-center q-mb-sm`},P={class:`text-subtitle1 text-kobo-2`,style:{"font-family":`var(--kobo-font-mono, monospace)`}},F=[`innerHTML`],I=v(f({__name:`ChangelogPage`,setup(f){let v=h(),{scheduleAutoRun:I}=b(),L=n([]),R=n(``),z=n(!1),B=n(null);function V(e){return x(e)}async function H(){z.value=!0,B.value=null;try{let e=await fetch(`/api/changelog`);if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();R.value=t.currentVersion??``,L.value=t.versions??[]}catch(e){B.value=e instanceof Error?e.message:String(e)}finally{z.value=!1}}return i(()=>{H(),I(`changelog`)}),(n,i)=>(r(),s(C,{class:`q-pa-md`,style:{"max-width":`900px`,margin:`0 auto`}},{default:a(()=>[d(`div`,E,[o(w,{class:`q-mr-xs`}),o(m,{flat:``,dense:``,round:``,icon:`arrow_back`,onClick:i[0]||=t=>e(v).back()}),d(`div`,D,t(n.$t(`changelog.title`)),1),o(y),o(m,{flat:``,dense:``,icon:`refresh`,loading:z.value,label:n.$t(`common.refresh`),onClick:H},null,8,[`loading`,`label`]),o(T,{"tour-id":`changelog`,class:`q-ml-xs`})]),z.value&&L.value.length===0?(r(),l(`div`,O,t(n.$t(`common.loading`)),1)):B.value?(r(),l(`div`,k,t(B.value),1)):L.value.length===0?(r(),l(`div`,A,t(n.$t(`changelog.empty`)),1)):(r(),l(`div`,j,[R.value?(r(),l(`div`,M,t(n.$t(`changelog.currentVersion`,{version:R.value})),1)):c(``,!0),(r(!0),l(u,null,p(L.value,e=>(r(),s(_,{key:e.version,dark:``,flat:``,bordered:``},{default:a(()=>[o(g,null,{default:a(()=>[d(`div`,N,[d(`div`,P,` v`+t(e.version),1),e.version===R.value?(r(),s(S,{key:0,dense:``,size:`sm`,color:`primary`,"text-color":`kobo-1`,label:n.$t(`changelog.current`),class:`q-ml-sm`},null,8,[`label`])):c(``,!0)]),d(`div`,{class:`changelog-notes`,innerHTML:V(e.notes)},null,8,F)]),_:2},1024)]),_:2},1024))),128))]))]),_:1}))}}),[[`__scopeId`,`data-v-6137cb7c`]]);export{I as default};
1
+ import{j as e,ut as t,v as n}from"./reactivity.esm-bundler-Bo9anJjg.js";import{L as r,P as i,Y as a,_ as o,d as s,f as c,p as l,r as u,u as d,y as f,z as p}from"./runtime-core.esm-bundler-CNFKm4ij.js";import{t as m}from"./QBtn-CcQQrYA_.js";import{i as h,rn as g,tn as _}from"./index-DolbyIM4.js";import{a as v,i as y,n as b}from"./use-tours-CjASQcG5.js";import{n as x}from"./render-chat-markdown-BWJNIDv3.js";import{t as S}from"./QChip-D75nKi-L.js";import{t as C}from"./QPage-HAaeQ-cv.js";import{t as w}from"./DrawerToggleButton-Dfvkaro0.js";import{t as T}from"./TourReplayButton-Dtv_UDaY.js";var E={class:`row items-center q-mb-md`},D={class:`text-h6 q-ml-sm`},O={key:0,class:`text-kobo-3 text-center q-pa-lg`},k={key:1,class:`text-negative text-center q-pa-lg`},A={key:2,class:`text-kobo-3 text-center q-pa-lg`},j={key:3,class:`column q-gutter-md`,"data-tour":`changelog-list`},M={key:0,class:`text-caption text-kobo-3`},N={class:`row items-center q-mb-sm`},P={class:`text-subtitle1 text-kobo-2`,style:{"font-family":`var(--kobo-font-mono, monospace)`}},F=[`innerHTML`],I=v(f({__name:`ChangelogPage`,setup(f){let v=h(),{scheduleAutoRun:I}=b(),L=n([]),R=n(``),z=n(!1),B=n(null);function V(e){return x(e)}async function H(){z.value=!0,B.value=null;try{let e=await fetch(`/api/changelog`);if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();R.value=t.currentVersion??``,L.value=t.versions??[]}catch(e){B.value=e instanceof Error?e.message:String(e)}finally{z.value=!1}}return i(()=>{H(),I(`changelog`)}),(n,i)=>(r(),s(C,{class:`q-pa-md`,style:{"max-width":`900px`,margin:`0 auto`}},{default:a(()=>[d(`div`,E,[o(w,{class:`q-mr-xs`}),o(m,{flat:``,dense:``,round:``,icon:`arrow_back`,onClick:i[0]||=t=>e(v).back()}),d(`div`,D,t(n.$t(`changelog.title`)),1),o(y),o(m,{flat:``,dense:``,icon:`refresh`,loading:z.value,label:n.$t(`common.refresh`),onClick:H},null,8,[`loading`,`label`]),o(T,{"tour-id":`changelog`,class:`q-ml-xs`})]),z.value&&L.value.length===0?(r(),l(`div`,O,t(n.$t(`common.loading`)),1)):B.value?(r(),l(`div`,k,t(B.value),1)):L.value.length===0?(r(),l(`div`,A,t(n.$t(`changelog.empty`)),1)):(r(),l(`div`,j,[R.value?(r(),l(`div`,M,t(n.$t(`changelog.currentVersion`,{version:R.value})),1)):c(``,!0),(r(!0),l(u,null,p(L.value,e=>(r(),s(_,{key:e.version,dark:``,flat:``,bordered:``},{default:a(()=>[o(g,null,{default:a(()=>[d(`div`,N,[d(`div`,P,` v`+t(e.version),1),e.version===R.value?(r(),s(S,{key:0,dense:``,size:`sm`,color:`primary`,"text-color":`kobo-1`,label:n.$t(`changelog.current`),class:`q-ml-sm`},null,8,[`label`])):c(``,!0)]),d(`div`,{class:`changelog-notes`,innerHTML:V(e.notes)},null,8,F)]),_:2},1024)]),_:2},1024))),128))]))]),_:1}))}}),[[`__scopeId`,`data-v-6137cb7c`]]);export{I as default};
@@ -1 +1 @@
1
- import{V as e,nt as t}from"./QBtn-DEdx_Y1V.js";import{m as n,p as r}from"./use-id-wXd4c8FA.js";function i(e){return e===!1?0:e===!0||e===void 0?1:Number.parseInt(e,10)||0}function a(e){let t=e.currentTarget,i=t.__qclosepopup;i!==0&&setTimeout(()=>{let a=n(t);a!==void 0&&r(a,e,i)},0)}function o(t){e(t,13)&&a(t)}var s=t({name:`close-popup`,beforeMount(e,{value:t}){e.__qclosepopup=i(t),e.addEventListener(`click`,a),e.addEventListener(`keyup`,o)},updated(e,{value:t,oldValue:n}){t!==n&&e.__qclosepopup!==void 0&&(e.__qclosepopup=i(t))},beforeUnmount(e){e.__qclosepopup!==void 0&&(e.removeEventListener(`click`,a),e.removeEventListener(`keyup`,o),e.__qclosepopup=void 0)}});export{s as t};
1
+ import{V as e,nt as t}from"./QBtn-CcQQrYA_.js";import{m as n,p as r}from"./use-id-vOr8PRTG.js";function i(e){return e===!1?0:e===!0||e===void 0?1:Number.parseInt(e,10)||0}function a(e){let t=e.currentTarget,i=t.__qclosepopup;i!==0&&setTimeout(()=>{let a=n(t);a!==void 0&&r(a,e,i)},0)}function o(t){e(t,13)&&a(t)}var s=t({name:`close-popup`,beforeMount(e,{value:t}){e.__qclosepopup=i(t),e.addEventListener(`click`,a),e.addEventListener(`keyup`,o)},updated(e,{value:t,oldValue:n}){t!==n&&e.__qclosepopup!==void 0&&(e.__qclosepopup=i(t))},beforeUnmount(e){e.__qclosepopup!==void 0&&(e.removeEventListener(`click`,a),e.removeEventListener(`keyup`,o),e.__qclosepopup=void 0)}});export{s as t};
@@ -1,2 +1,2 @@
1
- import{ot as e,ut as t,v as n}from"./reactivity.esm-bundler-Bo9anJjg.js";import{J as r,L as i,P as a,Y as ee,_ as o,d as te,f as s,g as ne,l as c,p as l,r as u,u as d,y as f,z as re}from"./runtime-core.esm-bundler-CNFKm4ij.js";import{t as p}from"./QBtn-DEdx_Y1V.js";import{Rt as ie,i as ae,nt as oe}from"./index-CqZ7sDcM.js";import{t as se}from"./QMarkupTable-CNpiA9oq.js";import{a as m,i as h}from"./use-tours-CNe8qb1q.js";var g=[`workspace`,`engine`,`model`,`status`,`branch`,`tasks_done`,`tasks_total`,`commits`,`files_changed`,`insertions`,`deletions`,`agent_messages`,`user_messages`,`injected_prompts`,`questions`,`tool_calls`,`errors`,`input_tokens`,`output_tokens`,`sessions`,`duration_seconds`];function _(e){if(e==null)return``;let t=String(e);return/[",\r\n]/.test(t)?`"${t.replace(/"/g,`""`)}"`:t}function v(e){let t=e.map(e=>{let t=e.gitStats,n=e.activity;return[e.workspace.name,e.workspace.engine,e.workspace.model,e.workspace.status,e.workspace.workingBranch,e.tasks.done,e.tasks.total,t?.commitCount??null,t?.filesChanged??null,t?.insertions??null,t?.deletions??null,n.agentMessages,n.userMessages,n.injectedPrompts,n.questions,n.toolCalls,n.errors,n.inputTokens,n.outputTokens,n.sessions,Math.round(n.durationMs/1e3)].map(_).join(`,`)});return`${[g.join(`,`),...t].join(`\r
1
+ import{ot as e,ut as t,v as n}from"./reactivity.esm-bundler-Bo9anJjg.js";import{J as r,L as i,P as a,Y as ee,_ as o,d as te,f as s,g as ne,l as c,p as l,r as u,u as d,y as f,z as re}from"./runtime-core.esm-bundler-CNFKm4ij.js";import{t as p}from"./QBtn-CcQQrYA_.js";import{Rt as ie,i as ae,nt as oe}from"./index-DolbyIM4.js";import{t as se}from"./QMarkupTable-D3REW6RC.js";import{a as m,i as h}from"./use-tours-CjASQcG5.js";var g=[`workspace`,`engine`,`model`,`status`,`branch`,`tasks_done`,`tasks_total`,`commits`,`files_changed`,`insertions`,`deletions`,`agent_messages`,`user_messages`,`injected_prompts`,`questions`,`tool_calls`,`errors`,`input_tokens`,`output_tokens`,`sessions`,`duration_seconds`];function _(e){if(e==null)return``;let t=String(e);return/[",\r\n]/.test(t)?`"${t.replace(/"/g,`""`)}"`:t}function v(e){let t=e.map(e=>{let t=e.gitStats,n=e.activity;return[e.workspace.name,e.workspace.engine,e.workspace.model,e.workspace.status,e.workspace.workingBranch,e.tasks.done,e.tasks.total,t?.commitCount??null,t?.filesChanged??null,t?.insertions??null,t?.deletions??null,n.agentMessages,n.userMessages,n.injectedPrompts,n.questions,n.toolCalls,n.errors,n.inputTokens,n.outputTokens,n.sessions,Math.round(n.durationMs/1e3)].map(_).join(`,`)});return`${[g.join(`,`),...t].join(`\r
2
2
  `)}`}var y={key:0,class:`comparison-panel q-pa-md`},b={class:`row items-center q-mb-sm`},x={class:`text-subtitle2`},S={class:`text-caption text-kobo-3 q-mb-sm`},C={class:`text-left`},w={class:`text-left`},T={class:`text-right`},E={class:`text-right`},D={class:`text-right`},O={class:`text-right`},k={class:`text-right`},A={class:`text-right`},j={class:`text-right`},M={class:`text-right`},N={class:`text-right`},P={class:`text-right`},F={class:`text-right`},I={class:`text-caption text-kobo-3 comparison-mono`},L={key:0,class:`text-caption text-kobo-3`},R={class:`text-right comparison-mono`},z={class:`text-right`},B={class:`text-right`},V={class:`text-right`},ce={key:0,class:`comparison-mono`},H={class:`text-kobo-success`},U={class:`text-kobo-danger q-ml-xs`},W={key:1,class:`text-kobo-3`},G={class:`text-right comparison-mono`},le=[`title`],ue={class:`text-right`},de={class:`text-right`},fe={class:`text-right comparison-mono`},pe=[`title`],me={class:`text-right`},he={class:`text-right comparison-mono`},ge={class:`text-right`},_e={key:1,class:`text-caption text-kobo-3`},ve={key:0,class:`text-caption text-kobo-warning q-mt-sm`},K=m(f({__name:`ComparisonPanel`,props:{workspaceId:{}},setup(f){let m=f;function g(e){return e<1e3?String(e):e<1e6?`${(e/1e3).toFixed(+(e<1e4))}k`:`${(e/1e6).toFixed(1)}M`}function _(e){if(e<=0)return`-`;let t=Math.round(e/1e3);if(t<60)return q(`reliability.durationSeconds`,{s:t});let n=Math.floor(t/60);return n<60?q(`reliability.durationMinutes`,{m:n,s:t%60}):q(`reliability.durationHours`,{h:Math.floor(n/60),m:n%60})}let K=ae(),ye=oe(),{t:q}=ie(),J=n([]),Y=n(!1),be={created:`workspaceStatus.created`,extracting:`workspaceStatus.extracting`,brainstorming:`workspaceStatus.brainstorming`,executing:`workspaceStatus.executing`,compacting:`workspaceStatus.compacting`,"awaiting-user":`workspaceStatus.awaitingUser`,completed:`workspaceStatus.completed`,idle:`workspaceStatus.idle`,error:`workspaceStatus.error`,quota:`workspaceStatus.quota`,retrying:`workspaceStatus.retrying`},X=n({});function xe(e){return X.value[e]??e}async function Se(){try{let e=await fetch(`/api/engines`);if(!e.ok)return;let t=await e.json();X.value=Object.fromEntries(t.map(e=>[e.id,e.displayName]))}catch{}}function Z(e){let t=be[e];return t?q(t):e}let Ce=c(()=>m.workspaceId);function Q(e){return e.workspace.id===Ce.value}function we(e){ye.selectWorkspace(e),K.push({name:`workspace`,params:{id:e}})}function Te(){let e=v(J.value),t=new Blob([e],{type:`text/csv;charset=utf-8`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`kobo-comparison-${J.value[0]?.workspace.comparisonId??`comparison`}.csv`,r.click(),URL.revokeObjectURL(n)}async function $(){Y.value=!0;try{let e=await fetch(`/api/workspaces/${m.workspaceId}/comparison`);if(!e.ok){J.value=[];return}let t=await e.json();J.value=t.members??[]}catch{J.value=[]}finally{Y.value=!1}}return a(()=>{Se(),$()}),r(()=>m.workspaceId,$),(n,r)=>J.value.length>0?(i(),l(`div`,y,[d(`div`,b,[d(`div`,x,t(n.$t(`comparison.title`)),1),o(h),o(p,{flat:``,dense:``,round:``,size:`sm`,icon:`download`,title:n.$t(`comparison.exportCsv`),onClick:Te},null,8,[`title`]),o(p,{flat:``,dense:``,round:``,size:`sm`,icon:`refresh`,loading:Y.value,onClick:$},null,8,[`loading`])]),d(`div`,S,t(n.$t(`comparison.hint`)),1),o(se,{flat:``,dense:``,dark:``,class:`comparison-table`},{default:ee(()=>[d(`thead`,null,[d(`tr`,null,[d(`th`,C,t(n.$t(`comparison.engine`)),1),d(`th`,w,t(n.$t(`comparison.status`)),1),d(`th`,T,t(n.$t(`comparison.tasks`)),1),d(`th`,E,t(n.$t(`comparison.commits`)),1),d(`th`,D,t(n.$t(`comparison.files`)),1),d(`th`,O,t(n.$t(`comparison.diff`)),1),d(`th`,k,t(n.$t(`comparison.messages`)),1),d(`th`,A,t(n.$t(`comparison.questions`)),1),d(`th`,j,t(n.$t(`comparison.tools`)),1),d(`th`,M,t(n.$t(`comparison.errors`)),1),d(`th`,N,t(n.$t(`comparison.tokens`)),1),d(`th`,P,t(n.$t(`comparison.sessions`)),1),d(`th`,F,t(n.$t(`comparison.duration`)),1),r[0]||=d(`th`,null,null,-1)])]),d(`tbody`,null,[(i(!0),l(u,null,re(J.value,r=>(i(),l(`tr`,{key:r.workspace.id,class:e({"comparison-current":Q(r)})},[d(`td`,null,[d(`div`,null,t(xe(r.workspace.engine)),1),d(`div`,I,t(r.workspace.model),1)]),d(`td`,null,[ne(t(Z(r.workspace.status))+` `,1),r.workspace.archivedAt?(i(),l(`span`,L,` · `+t(n.$t(`comparison.archived`)),1)):s(``,!0)]),d(`td`,R,t(r.tasks.done)+`/`+t(r.tasks.total),1),d(`td`,z,t(r.gitStats?.commitCount??`-`),1),d(`td`,B,t(r.gitStats?.filesChanged??`-`),1),d(`td`,V,[r.gitStats?(i(),l(`span`,ce,[d(`span`,H,`+`+t(r.gitStats.insertions),1),d(`span`,U,`-`+t(r.gitStats.deletions),1)])):(i(),l(`span`,W,`-`))]),d(`td`,G,[d(`span`,{title:n.$t(`comparison.messagesTitle`)},t(r.activity.agentMessages)+` / `+t(r.activity.userMessages),9,le)]),d(`td`,ue,t(r.activity.questions),1),d(`td`,de,t(r.activity.toolCalls),1),d(`td`,{class:e([`text-right`,r.activity.errors>0?`text-kobo-danger`:``])},t(r.activity.errors),3),d(`td`,fe,[d(`span`,{title:n.$t(`comparison.tokensTitle`)},t(g(r.activity.inputTokens))+` / `+t(g(r.activity.outputTokens)),9,pe)]),d(`td`,me,t(r.activity.sessions),1),d(`td`,he,t(_(r.activity.durationMs)),1),d(`td`,ge,[Q(r)?(i(),l(`span`,_e,t(n.$t(`comparison.current`)),1)):(i(),te(p,{key:0,flat:``,dense:``,"no-caps":``,size:`sm`,label:n.$t(`comparison.open`),onClick:e=>we(r.workspace.id)},null,8,[`label`,`onClick`]))])],2))),128))])]),_:1}),J.value.length<2?(i(),l(`div`,ve,t(n.$t(`comparison.incomplete`)),1)):s(``,!0)])):s(``,!0)}}),[[`__scopeId`,`data-v-e1a1dbcc`]]);export{K as default};