@loicngr/kobo 2.1.28 → 2.1.29

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 (132) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +4 -0
  3. package/CONFIGURATION.md +27 -22
  4. package/CONTRIBUTING.md +1 -1
  5. package/README.md +1 -1
  6. package/dist/server/services/agent/engines/claude-code/resolve-binary.js +1 -1
  7. package/dist/server/services/dev-server-service.js +68 -4
  8. package/dist/server/services/environment-check-service.js +3 -2
  9. package/docs/getting-started.md +1 -1
  10. package/docs/troubleshooting.md +1 -1
  11. package/package.json +14 -14
  12. package/src/client/dist/pwa/assets/ActivityFeed-CiTe2VUQ.js +2 -0
  13. package/src/client/dist/pwa/assets/{AutoLoopFinalReviewSettings-CK3r_fVB.js → AutoLoopFinalReviewSettings-v3jXoH_Q.js} +1 -1
  14. package/src/client/dist/pwa/assets/{ChangelogPage-CAAUEn5X.js → ChangelogPage-C5KjAOMG.js} +1 -1
  15. package/src/client/dist/pwa/assets/{ClosePopup-CRV2hxHS.js → ClosePopup-rU8Bm-mC.js} +1 -1
  16. package/src/client/dist/pwa/assets/{ComparisonPanel-BCb7vB5E.js → ComparisonPanel-XXyzPEzW.js} +2 -2
  17. package/src/client/dist/pwa/assets/CreatePage-MYCexRJu.js +2 -0
  18. package/src/client/dist/pwa/assets/{DashboardPage-XE52EABP.js → DashboardPage-DyhUu26C.js} +1 -1
  19. package/src/client/dist/pwa/assets/DiffViewer-CvsmC9d5.js +8 -0
  20. package/src/client/dist/pwa/assets/{DocumentsPanel-L4pbQfz1.js → DocumentsPanel-ItndGxeB.js} +1 -1
  21. package/src/client/dist/pwa/assets/{DrawerToggleButton-DiOJm5he.js → DrawerToggleButton-DfzS_CD8.js} +1 -1
  22. package/src/client/dist/pwa/assets/GitPanel-C1ybi9bZ.js +3 -0
  23. package/src/client/dist/pwa/assets/{HealthPage-hJY5MurK.js → HealthPage-C1u35ANL.js} +1 -1
  24. package/src/client/dist/pwa/assets/MainLayout-BEAGPqei.js +2 -0
  25. package/src/client/dist/pwa/assets/{MemoryPanel-DtEvh_b7.js → MemoryPanel-CZzI7_nY.js} +1 -1
  26. package/src/client/dist/pwa/assets/MemoryProposalList-DqNTycY1.js +1 -0
  27. package/src/client/dist/pwa/assets/{QBadge-CW3Lw-kL.js → QBadge-DiwbRpte.js} +1 -1
  28. package/src/client/dist/pwa/assets/{QBanner-BT2ZemYu.js → QBanner-Cw89HSjk.js} +1 -1
  29. package/src/client/dist/pwa/assets/QBtn-kfhHFy7Q.js +1 -0
  30. package/src/client/dist/pwa/assets/{QBtnDropdown-CWPIugs8.js → QBtnDropdown-D7ml7zHo.js} +1 -1
  31. package/src/client/dist/pwa/assets/{QBtnGroup-CnM4vSJA.js → QBtnGroup-Bioxjp9q.js} +1 -1
  32. package/src/client/dist/pwa/assets/{QBtnToggle-DccOOtbh.js → QBtnToggle-Bod-x9im.js} +1 -1
  33. package/src/client/dist/pwa/assets/{QChip-Be16M4Ig.js → QChip-DvhtPv_L.js} +1 -1
  34. package/src/client/dist/pwa/assets/{QExpansionItem-D-EGL2b3.js → QExpansionItem-BVb067oc.js} +1 -1
  35. package/src/client/dist/pwa/assets/{QItemSection-MdJ1_ZK7.js → QItemSection-ahqRK4JF.js} +1 -1
  36. package/src/client/dist/pwa/assets/{QList-Cx1UfaUm.js → QList-CAUl0v66.js} +1 -1
  37. package/src/client/dist/pwa/assets/{QMarkupTable-UhP7fVUp.js → QMarkupTable-B4LLAly-.js} +1 -1
  38. package/src/client/dist/pwa/assets/{QPage-CqkGHokx.js → QPage-DIy_mRoT.js} +1 -1
  39. package/src/client/dist/pwa/assets/{QScrollArea-BMrqK-xd.js → QScrollArea-CUDWkEHh.js} +1 -1
  40. package/src/client/dist/pwa/assets/QSelect-DOnv_ry0.js +1 -0
  41. package/src/client/dist/pwa/assets/{QSpinnerDots-xdWyaE1i.js → QSpinnerDots-Bea6hAuJ.js} +1 -1
  42. package/src/client/dist/pwa/assets/{QTooltip-Bk8dLUtU.js → QTooltip-B5QJIU3p.js} +1 -1
  43. package/src/client/dist/pwa/assets/{SchedulePanel-CuxmxCKi.js → SchedulePanel-IJOcrHgk.js} +1 -1
  44. package/src/client/dist/pwa/assets/{SearchPage-DKnQPUqY.js → SearchPage-BpTRWtne.js} +1 -1
  45. package/src/client/dist/pwa/assets/SettingsPage-CFaRN9Pk.js +9 -0
  46. package/src/client/dist/pwa/assets/{SplitWorkspacePage-WhQyX8fn.js → SplitWorkspacePage-BZ8wN4ii.js} +1 -1
  47. package/src/client/dist/pwa/assets/TerminalPanel-pY-RGBb6.js +16 -0
  48. package/src/client/dist/pwa/assets/{ToolCallItem-DYubi-J0.js → ToolCallItem-C9ksVseJ.js} +3 -3
  49. package/src/client/dist/pwa/assets/{TouchPan-DDotyYLN.js → TouchPan-DRynDIve.js} +1 -1
  50. package/src/client/dist/pwa/assets/{TourReplayButton-kAnEMcy2.js → TourReplayButton-D4h1QR6C.js} +1 -1
  51. package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-Bkj2DhOn.js +1 -0
  52. package/src/client/dist/pwa/assets/WorkspacePage-BTJnap9a.js +4 -0
  53. package/src/client/dist/pwa/assets/{browser-DVYLH8vl.js → browser-BcOi2ES2.js} +2 -2
  54. package/src/client/dist/pwa/assets/build-path-tree-mDco3pi7.js +1 -0
  55. package/src/client/dist/pwa/assets/custom-sounds-T5HKzrWh.js +1 -0
  56. package/src/client/dist/pwa/assets/{de-Bk3zQrin.js → de-suqWUSXa.js} +1 -1
  57. package/src/client/dist/pwa/assets/detached-fullscreen-CHqMxB-8.js +1 -0
  58. package/src/client/dist/pwa/assets/dom-CRPVbmiy.js +2 -0
  59. package/src/client/dist/pwa/assets/ecl-94qehhXe.js +1 -0
  60. package/src/client/dist/pwa/assets/{editor.api-BC38eXAS.js → editor.api-CRrihXg2.js} +9 -9
  61. package/src/client/dist/pwa/assets/editor.worker-xrHNhPSq.js +33 -0
  62. package/src/client/dist/pwa/assets/{efforts-TGacUPcJ.js → efforts-C-p9DzkL.js} +2 -2
  63. package/src/client/dist/pwa/assets/{es-f3xuAWA9.js → es-Dcptbz5U.js} +1 -1
  64. package/src/client/dist/pwa/assets/expand-template-gIwrPbeS.js +1 -0
  65. package/src/client/dist/pwa/assets/{format-OwxXBnDJ.js → format-DeBnwmgW.js} +48 -48
  66. package/src/client/dist/pwa/assets/{formatters-YgaCZcwJ.js → formatters-CxZZ_WTb.js} +1 -1
  67. package/src/client/dist/pwa/assets/{fr-B6c21SG3.js → fr-Db70bqVq.js} +1 -1
  68. package/src/client/dist/pwa/assets/{freemarker2-l7R42fI2.js → freemarker2-h7OLlqTn.js} +1 -1
  69. package/src/client/dist/pwa/assets/{handlebars-DFmPrgjH.js → handlebars-BCWmi1-q.js} +1 -1
  70. package/src/client/dist/pwa/assets/{html-CERIAlPM.js → html-MUMpfUBd.js} +1 -1
  71. package/src/client/dist/pwa/assets/i18n-DLprfNLs.js +1 -0
  72. package/src/client/dist/pwa/assets/index-C0MApoXN.css +1 -0
  73. package/src/client/dist/pwa/assets/index-DLoUeovT.js +20 -0
  74. package/src/client/dist/pwa/assets/{it-DUstDpC2.js → it-Cloo58Nn.js} +1 -1
  75. package/src/client/dist/pwa/assets/{javascript-BBYncplF.js → javascript-CHDwijEy.js} +1 -1
  76. package/src/client/dist/pwa/assets/{liquid-C1HqYyYU.js → liquid-dFrnLevt.js} +1 -1
  77. package/src/client/dist/pwa/assets/{mdx-E74dsP22.js → mdx-BHS7JVD4.js} +1 -1
  78. package/src/client/dist/pwa/assets/monaco-contributions-DCWZe7nX.js +53 -0
  79. package/src/client/dist/pwa/assets/{monaco.contribution-DYdn9CwR.js → monaco.contribution-Dx0gcAn4.js} +2 -2
  80. package/src/client/dist/pwa/assets/{network-auth-DTZUKbny.js → network-auth-DDMAzwYH.js} +1 -1
  81. package/src/client/dist/pwa/assets/{notify-theme-FuTL7HuS.js → notify-theme-JuVT96rq.js} +1 -1
  82. package/src/client/dist/pwa/assets/{private.use-form-DY1BkePL.js → private.use-form-BcspuzM9.js} +1 -1
  83. package/src/client/dist/pwa/assets/{project-color-_snXWYUp.js → project-color-DihsE4yN.js} +1 -1
  84. package/src/client/dist/pwa/assets/{python-DNAAGBcX.js → python-BtjZnK9y.js} +1 -1
  85. package/src/client/dist/pwa/assets/{razor-CB3g5p_T.js → razor-DBcOGz0a.js} +1 -1
  86. package/src/client/dist/pwa/assets/reactivity.esm-bundler-Dplx1ILy.js +1 -0
  87. package/src/client/dist/pwa/assets/render-chat-markdown-C9ihAYBt.js +67 -0
  88. package/src/client/dist/pwa/assets/runtime-core.esm-bundler-BAUgNzMK.js +1 -0
  89. package/src/client/dist/pwa/assets/{typescript-0kpz8bqP.js → typescript-B320c7wU.js} +1 -1
  90. package/src/client/dist/pwa/assets/{use-checkbox-v4aAbE6K.js → use-checkbox-DUxgXR4e.js} +1 -1
  91. package/src/client/dist/pwa/assets/{use-id-BrdYXce0.js → use-id-B7ieAx2m.js} +1 -1
  92. package/src/client/dist/pwa/assets/use-is-mobile-CHmaewI1.js +1 -0
  93. package/src/client/dist/pwa/assets/{use-search-index-status-D38yFOD_.js → use-search-index-status-B95GPaJP.js} +1 -1
  94. package/src/client/dist/pwa/assets/use-slide-transition-BJh9xGMa.js +1 -0
  95. package/src/client/dist/pwa/assets/use-tours-CU5oA7cz.css +1 -0
  96. package/src/client/dist/pwa/assets/use-tours-C_5R1Y5D.js +2 -0
  97. package/src/client/dist/pwa/assets/{use-worktree-restore-DUjZr44N.js → use-worktree-restore-Cj8eGE9s.js} +1 -1
  98. package/src/client/dist/pwa/assets/{workspace-templates-D-lPJQ4G.js → workspace-templates-B9UETKER.js} +1 -1
  99. package/src/client/dist/pwa/assets/{xml-BbOuqdUe.js → xml-uK8LK4OB.js} +1 -1
  100. package/src/client/dist/pwa/assets/{yaml-gasFQtfk.js → yaml-B2D1l_tz.js} +1 -1
  101. package/src/client/dist/pwa/index.html +10 -10
  102. package/src/client/dist/pwa/sw.js +1 -1
  103. package/src/client/dist/pwa/assets/ActivityFeed-D58VS9o2.js +0 -2
  104. package/src/client/dist/pwa/assets/CreatePage-DasH1Uk4.js +0 -2
  105. package/src/client/dist/pwa/assets/DiffViewer-CncKlXne.js +0 -8
  106. package/src/client/dist/pwa/assets/GitPanel-WJlzy2VJ.js +0 -3
  107. package/src/client/dist/pwa/assets/MainLayout-DgWElK7w.js +0 -2
  108. package/src/client/dist/pwa/assets/MemoryProposalList-kgFCm9zz.js +0 -1
  109. package/src/client/dist/pwa/assets/QBtn-BUSdPaf4.js +0 -1
  110. package/src/client/dist/pwa/assets/QSelect-DFWyDWCE.js +0 -1
  111. package/src/client/dist/pwa/assets/SettingsPage-CO3vIpPd.js +0 -9
  112. package/src/client/dist/pwa/assets/TerminalPanel-BY0lPq6k.js +0 -16
  113. package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-DiYt3rP3.js +0 -1
  114. package/src/client/dist/pwa/assets/WorkspacePage-K-1ce50d.js +0 -4
  115. package/src/client/dist/pwa/assets/build-path-tree-DEuOdIIk.js +0 -1
  116. package/src/client/dist/pwa/assets/custom-sounds-Ggw6V9iF.js +0 -1
  117. package/src/client/dist/pwa/assets/detached-fullscreen-Du3TcYdX.js +0 -1
  118. package/src/client/dist/pwa/assets/dom-BtYTvLeN.js +0 -2
  119. package/src/client/dist/pwa/assets/ecl-D05T4iGw.js +0 -1
  120. package/src/client/dist/pwa/assets/editor.worker-BLJF_oQx.js +0 -33
  121. package/src/client/dist/pwa/assets/expand-template-DM8gq3Mo.js +0 -1
  122. package/src/client/dist/pwa/assets/i18n-WaE4cZK9.js +0 -1
  123. package/src/client/dist/pwa/assets/index-C8zAZ-k-.css +0 -1
  124. package/src/client/dist/pwa/assets/index-CpWBGKdM.js +0 -20
  125. package/src/client/dist/pwa/assets/monaco-contributions-DHvm-kp5.js +0 -53
  126. package/src/client/dist/pwa/assets/reactivity.esm-bundler-DY1JkAEA.js +0 -1
  127. package/src/client/dist/pwa/assets/render-chat-markdown-CafzCcmu.js +0 -69
  128. package/src/client/dist/pwa/assets/runtime-core.esm-bundler-Bqg71Vll.js +0 -1
  129. package/src/client/dist/pwa/assets/use-is-mobile-CDB_rzM9.js +0 -1
  130. package/src/client/dist/pwa/assets/use-slide-transition-B_Nu6u-t.js +0 -1
  131. package/src/client/dist/pwa/assets/use-tours-BWkHp34X.js +0 -2
  132. package/src/client/dist/pwa/assets/use-tours-CTZuBZOi.css +0 -1
package/AGENTS.md CHANGED
@@ -12,7 +12,7 @@ External `/api/mcp` and global stdio require dedicated hashed credentials with t
12
12
 
13
13
  ## Tech stack
14
14
 
15
- **Backend**: Node.js ≥ 24.15, Hono (HTTP), `ws` (WebSocket), better-sqlite3 (WAL mode), nanoid, `@modelcontextprotocol/sdk`. TypeScript throughout, `tsx` for dev, `tsc` for production build.
15
+ **Backend**: Node.js ≥ 26.12.1, Hono (HTTP), `ws` (WebSocket), better-sqlite3 (WAL mode), nanoid, `@modelcontextprotocol/sdk`. TypeScript throughout, `tsx` for dev, `tsc` for production build.
16
16
 
17
17
  **Frontend**: Vue 3, Quasar 2, Pinia, vue-router, marked + dompurify for markdown rendering. Vite via `@quasar/app-vite`, built and served as a Progressive Web App in production.
18
18
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,10 @@ 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.29
8
+
9
+ - chore: upgrade node and dependencies and fix dev server readiness
10
+
7
11
  ## 2.1.28
8
12
 
9
13
  - fix(ci): authenticate packaged mcp smoke tests
package/CONFIGURATION.md CHANGED
@@ -1293,7 +1293,7 @@ and [project/skills operations guide](./docs/vps-projects-and-skills.md).
1293
1293
 
1294
1294
  ### The image
1295
1295
 
1296
- Multi-stage `Dockerfile`, `node:24.19.0-slim` base:
1296
+ Multi-stage `Dockerfile`, `node:26.12.1-slim` base:
1297
1297
 
1298
1298
  - **Build stage**: installs root, client, and PWA deps, then runs `npm run build` (client via Quasar, server via `tsc`).
1299
1299
  - **Runtime stage**: production deps only, plus OS tooling the agents and forge CLIs need — `git`, `openssh-client` + `openssh-server`, `ripgrep`, `fd-find`, `jq`, `curl`, Python + build tools, the Docker CLI, Compose and Buildx plugins (talk to a mounted host socket, see [Volumes](#volumes)), netcat (`nc`), `gh`, `glab`, `tmux`, `vim`/`nano`, and more for interactive shell use.
@@ -1702,15 +1702,17 @@ Kōbō treats the dev server in two independent layers:
1702
1702
  | Layer | Driven by | Works for any project? |
1703
1703
  |---|---|---|
1704
1704
  | **Start / Stop** | The shell commands you configure | ✅ Yes, any shell-startable process |
1705
- | **Status badge, URL, container count, logs** | The `.container/instances/*.env` convention + Docker | ❌ No, requires the convention below |
1706
-
1707
- Configured processes can be started and stopped. Docker status, a URL and logs
1708
- require a matching instance file and running containers. Without an instance,
1709
- runtime detection returns `unknown`; the HTTP route may show the saved process
1710
- status instead, but has no URL or container logs. Without a start command, the
1711
- route returns `not_configured`.
1712
-
1713
- > **Known limitation: Docker-coupled, for now.** Status detection, the URL, the container count, and the logs viewer are currently hard-wired to Docker and to the `.container/instances/*.env` convention described below. This is a deliberate, temporary state: it works today for Docker-instance projects, and the convention is documented here so you can adopt it. An **evolution is planned** to abstract this layer, making the URL/port configurable and the running-detection engine-agnostic (e.g. a TCP probe) so the panel works for any project, Docker or not, without imposing this file layout. Until that lands, follow the contract below.
1705
+ | **Status badge, URL** | A tracked process's local readiness announcement, or the Docker convention below | Quasar (`App URL...`) and Vite/Next (`Local:`), or matching Docker containers |
1706
+ | **Container count, logs viewer** | The `.container/instances/*.env` convention + Docker | ❌ No, requires the convention below |
1707
+
1708
+ Configured processes can be started and stopped. A tracked direct process reports
1709
+ `starting` until it announces a local HTTP(S) URL in a recognized readiness line
1710
+ on stdout or stderr, then reports `running` with that URL and port. Colored output
1711
+ and lines split across chunks are supported. This observes the CLI announcement;
1712
+ it does not probe application health. Docker container status and logs require a
1713
+ matching instance file and running containers. Without a tracked process or an
1714
+ instance, runtime detection returns `unknown`; the HTTP route may show the saved
1715
+ status instead. Without a start command, the route returns `not_configured`.
1714
1716
 
1715
1717
  ### 1. Configure start / stop commands
1716
1718
 
@@ -1729,9 +1731,9 @@ How Kōbō runs them:
1729
1731
  - `DEV_DOCKER_NO_FOLLOW=1`: a hint that a Docker setup script should exit after starting its containers instead of following logs. A tracked start process reports `starting` when an instance file exists but no matching container is running yet; once containers appear, Docker status takes precedence.
1730
1732
  - `stopCommand` runs with `INSTANCE` and `PROJECT_NAME` in the environment. After it, Kōbō also unconditionally runs `docker compose -p <PROJECT_NAME> down` if a `PROJECT_NAME` was resolved, so a Docker project does not strictly need a `stopCommand` at all.
1731
1733
 
1732
- ### 2. Make the status panel light up — the `.container/instances` contract
1734
+ ### 2. Docker status — the `.container/instances` contract
1733
1735
 
1734
- For the **Running** badge, the URL, the container count, and the logs button to appear, your **start command must create an instance file**:
1736
+ For Docker detection, the URL, the container count, and the logs button to appear, your **start command must create an instance file**:
1735
1737
 
1736
1738
  ```
1737
1739
  <project-root>/.container/instances/<any-name>.env
@@ -1753,13 +1755,12 @@ The simplest correct start script therefore: read `$INSTANCE`, start your contai
1753
1755
 
1754
1756
  ### 3. Running detection and logs
1755
1757
 
1756
- - **Status**: `running` if at least one container has the exact Compose project label; `starting` if an instance file exists and the start process remains tracked but no container is running; `stopped` otherwise; `unknown` if no instance file matched.
1758
+ - **Status**: a tracked process with a recognized local readiness URL reports `running`. Otherwise, `running` if at least one container has the exact Compose project label; `starting` while the start process remains tracked; `stopped` when an instance exists but no container or process remains; `unknown` if neither a tracked process nor an instance matched.
1757
1759
  - **Logs**: the logs button runs `docker logs` on those same matched containers.
1758
1760
 
1759
- Both are **Docker-only**. A plain Node process (`npm run dev`) does not produce a
1760
- running Docker status or container logs. Writing an instance file alone is not
1761
- enough to expose a URL: status responses only include the URL when matching
1762
- containers are running. Direct processes can still be started and stopped.
1761
+ The logs viewer and container count remain **Docker-only**. Writing an instance
1762
+ file alone is not enough to expose a URL: matching containers must be running,
1763
+ or a tracked direct process must have announced its local URL.
1763
1764
 
1764
1765
  ### Minimal setups
1765
1766
 
@@ -1767,11 +1768,15 @@ containers are running. Direct processes can still be started and stopped.
1767
1768
 
1768
1769
  **Non-Docker project (e.g. Vite/Node)**: configure a foreground command such as
1769
1770
  `npm run dev`. Kōbō tracks its process group for shutdown, including children that
1770
- outlive the shell. Open the project's URL yourself; the Docker status, URL and
1771
- logs contract does not provide general process health monitoring.
1772
-
1773
- **No instance file at all**: Start/Stop run your commands; the panel uses the
1774
- saved status when available, otherwise `unknown`, with no URL or Docker logs.
1771
+ outlive the shell. Quasar's `App URL... http://localhost:9000/` and Vite/Next's
1772
+ `Local: http://localhost:5173/` announcements populate the status and URL without
1773
+ an instance file. Other output formats remain `starting`; there is no general
1774
+ process health monitoring or direct-process log viewer. Readiness URLs are kept
1775
+ only for the current launch and cleared when it stops.
1776
+
1777
+ **No instance file at all**: Start/Stop run your commands; a tracked process uses
1778
+ the direct-process detection above. Otherwise the panel uses the saved status
1779
+ when available, or `unknown`, with no URL or Docker logs.
1775
1780
 
1776
1781
  ### Kōbō shutdown
1777
1782
 
package/CONTRIBUTING.md CHANGED
@@ -4,7 +4,7 @@ Thanks for considering a contribution. This guide covers the from-source setup,
4
4
 
5
5
  ## Prerequisites
6
6
 
7
- Node.js ≥ 24.15. The repository's `.nvmrc` pins the tested version; run
7
+ Node.js ≥ 26.12.1. The repository's `.nvmrc` pins the tested version; run
8
8
  `nvm use` when using nvm.
9
9
 
10
10
  ## Setup
package/README.md CHANGED
@@ -28,7 +28,7 @@ Use [group messages](CONFIGURATION.md#group-workspace-messages) to send one inst
28
28
 
29
29
  ## Quick start
30
30
 
31
- Requires Node.js ≥ 24.15, Git, Bash and your own Claude Code **or** Codex authentication. No skill plugin or ticket integration is required. Kōbō is a local, single-user tool; each user installs their own instance.
31
+ Requires Node.js ≥ 26.12.1, Git, Bash and your own Claude Code **or** Codex authentication. No skill plugin or ticket integration is required. Kōbō is a local, single-user tool; each user installs their own instance.
32
32
 
33
33
  ```bash
34
34
  npx @loicngr/kobo@latest
@@ -3,7 +3,7 @@ const localRequire = createRequire(import.meta.url);
3
3
  /**
4
4
  * Detect the live host's platform/arch/libc from `process`. `glibcVersionRuntime`
5
5
  * lives in the diagnostic report header on glibc systems and is absent on musl.
6
- * Available since Node 12; Kōbō requires Node ≥ 20 (see AGENTS.md).
6
+ * Available since Node 12; Kōbō requires Node ≥ 26.12.1 (see AGENTS.md).
7
7
  */
8
8
  export function detectPlatform() {
9
9
  const report = process.report;
@@ -1,5 +1,7 @@
1
1
  import { execFile, spawn } from 'node:child_process';
2
2
  import { existsSync } from 'node:fs';
3
+ import { StringDecoder } from 'node:string_decoder';
4
+ import { stripVTControlCharacters } from 'node:util';
3
5
  import { resolveInstance, sanitizeBranchName } from '../utils/dev-server-instance.js';
4
6
  import { assertWorkspaceLifecycleAvailable } from '../utils/workspace-lifecycle-guard.js';
5
7
  import { getProjectSettings } from './settings-service.js';
@@ -25,6 +27,7 @@ function runCommand(command, args, options = {}) {
25
27
  // ── State ──────────────────────────────────────────────────────────────────────
26
28
  /** workspaceId -> spawned dev-server process */
27
29
  const trackedProcesses = new Map();
30
+ const directServerStatuses = new Map();
28
31
  const stoppingProcesses = new Map();
29
32
  const generations = new Map();
30
33
  let shuttingDown = false;
@@ -34,6 +37,7 @@ export function beginDevServerShutdown() {
34
37
  /** Test-only: clear the tracked-processes map between tests. */
35
38
  export function _resetTrackedProcessesForTests() {
36
39
  trackedProcesses.clear();
40
+ directServerStatuses.clear();
37
41
  stoppingProcesses.clear();
38
42
  generations.clear();
39
43
  shuttingDown = false;
@@ -74,14 +78,18 @@ export async function listRunningContainers(projectName) {
74
78
  * still running (e.g. `docker compose up -d` is pulling/building images), the
75
79
  * status is reported as `'starting'` even if no matching container is visible
76
80
  * in `docker ps` yet. This prevents the UI from flashing to `'stopped'` during
77
- * long build phases.
81
+ * long build phases. Direct processes report running and their URL after a
82
+ * recognized local readiness announcement on stdout or stderr.
78
83
  */
79
84
  export async function getStatus(projectPath, workingBranch, workspaceId) {
80
85
  const config = resolveInstance(projectPath, workingBranch);
86
+ const directStatus = workspaceId ? directServerStatuses.get(workspaceId) : undefined;
87
+ if (workspaceId && directStatus && trackedProcesses.has(workspaceId))
88
+ return { ...directStatus };
81
89
  if (!config) {
82
90
  return {
83
- status: 'unknown',
84
- instanceName: '',
91
+ status: workspaceId && trackedProcesses.has(workspaceId) ? 'starting' : 'unknown',
92
+ instanceName: workspaceId && trackedProcesses.has(workspaceId) ? sanitizeBranchName(workingBranch) : '',
85
93
  projectName: '',
86
94
  httpPort: '',
87
95
  url: '',
@@ -163,12 +171,64 @@ export function startDevServer(workspaceId) {
163
171
  const generation = (generations.get(workspaceId) ?? 0) + 1;
164
172
  generations.set(workspaceId, generation);
165
173
  trackedProcesses.set(workspaceId, proc);
166
- // Log stdout/stderr for debugging
174
+ // Parse complete lines separately per stream: CLI output and ANSI sequences
175
+ // can span arbitrary pipe chunks. Bound the unfinished line retained in memory.
176
+ const observeOutput = () => {
177
+ const decoder = new StringDecoder('utf8');
178
+ let pending = '';
179
+ return (data) => {
180
+ if (shuttingDown ||
181
+ trackedProcesses.get(workspaceId) !== proc ||
182
+ generations.get(workspaceId) !== generation ||
183
+ stoppingProcesses.has(workspaceId) ||
184
+ directServerStatuses.has(workspaceId))
185
+ return;
186
+ pending += decoder.write(data);
187
+ const lines = pending.split(/[\r\n]/);
188
+ pending = lines.pop().slice(-8192);
189
+ for (const line of lines) {
190
+ // Quasar's "App URL....." and Vite/Next's "Local:" are explicit
191
+ // readiness announcements; unrelated links in build output are not.
192
+ const match = stripVTControlCharacters(line).match(/^\s*(?:[»➜-]\s*)?(?:App URL[.\s]*|Local:\s*)(https?:\/\/\S+)\s*$/i);
193
+ if (!match)
194
+ continue;
195
+ let url;
196
+ try {
197
+ url = new URL(match[1]);
198
+ }
199
+ catch {
200
+ continue;
201
+ }
202
+ if (url.username ||
203
+ url.password ||
204
+ !['localhost', '127.0.0.1', '[::1]', '0.0.0.0', '[::]'].includes(url.hostname))
205
+ continue;
206
+ if (url.hostname === '0.0.0.0' || url.hostname === '[::]')
207
+ url.hostname = 'localhost';
208
+ const status = {
209
+ status: 'running',
210
+ instanceName,
211
+ projectName: '',
212
+ httpPort: url.port || (url.protocol === 'https:' ? '443' : '80'),
213
+ url: url.href,
214
+ containers: [],
215
+ };
216
+ directServerStatuses.set(workspaceId, status);
217
+ updateDevServerStatus(workspaceId, 'running');
218
+ emitEphemeral(workspaceId, 'devserver:status', status);
219
+ break;
220
+ }
221
+ };
222
+ };
223
+ const observeStdout = observeOutput();
224
+ const observeStderr = observeOutput();
167
225
  proc.stdout?.on('data', (data) => {
168
226
  console.log(`[dev-server:${instanceName}] ${data.toString().trim()}`);
227
+ observeStdout(data);
169
228
  });
170
229
  proc.stderr?.on('data', (data) => {
171
230
  console.error(`[dev-server:${instanceName}] ${data.toString().trim()}`);
231
+ observeStderr(data);
172
232
  });
173
233
  proc.on('exit', (code) => {
174
234
  // Shell exit does not imply that its background children have stopped.
@@ -181,6 +241,7 @@ export function startDevServer(workspaceId) {
181
241
  if (trackedProcesses.get(workspaceId) !== proc || stoppingProcesses.has(workspaceId))
182
242
  return;
183
243
  trackedProcesses.delete(workspaceId);
244
+ directServerStatuses.delete(workspaceId);
184
245
  const currentStatus = await getStatus(workspace.projectPath, workspace.workingBranch);
185
246
  if (shuttingDown || generations.get(workspaceId) !== generation || stoppingProcesses.has(workspaceId))
186
247
  return;
@@ -200,6 +261,7 @@ export function startDevServer(workspaceId) {
200
261
  // A signal failure is also an 'error' event; it does not prove process exit.
201
262
  if (!proc.pid)
202
263
  trackedProcesses.delete(workspaceId);
264
+ directServerStatuses.delete(workspaceId);
203
265
  updateDevServerStatus(workspaceId, 'error');
204
266
  console.error(`[dev-server] Process error for workspace ${workspaceId}:`, err);
205
267
  emitEphemeral(workspaceId, 'devserver:status', {
@@ -233,6 +295,7 @@ export async function stopDevServer(workspaceId) {
233
295
  if (pending)
234
296
  return pending;
235
297
  generations.set(workspaceId, (generations.get(workspaceId) ?? 0) + 1);
298
+ directServerStatuses.delete(workspaceId);
236
299
  const stopping = stopDevServerOwned(workspaceId);
237
300
  stoppingProcesses.set(workspaceId, stopping);
238
301
  try {
@@ -333,6 +396,7 @@ async function stopTrackedProcess(workspaceId) {
333
396
  throw new Error('Dev server stop is not confirmed; retry after the process exits');
334
397
  if (trackedProcesses.get(workspaceId) === tracked)
335
398
  trackedProcesses.delete(workspaceId);
399
+ directServerStatuses.delete(workspaceId);
336
400
  }
337
401
  async function stopDevServerOwned(workspaceId) {
338
402
  const workspace = getWorkspace(workspaceId);
@@ -70,9 +70,10 @@ function liveProbe() {
70
70
  }
71
71
  /** No credential files, provider calls, generated prompts, or raw process errors in this report. */
72
72
  export async function checkEnvironment(request, probe = liveProbe()) {
73
- const [major, minor] = probe.nodeVersion.split('.').map(Number);
73
+ const [major, minor, patch] = probe.nodeVersion.split('.').map(Number);
74
+ const supportedNode = major > 26 || (major === 26 && (minor > 12 || (minor === 12 && patch >= 1)));
74
75
  const checks = [
75
- { code: 'node', status: major > 24 || (major === 24 && minor >= 15) ? 'ok' : 'error' },
76
+ { code: 'node', status: supportedNode ? 'ok' : 'error' },
76
77
  { code: 'platform', status: ['linux', 'darwin'].includes(probe.platform) ? 'ok' : 'error' },
77
78
  ];
78
79
  const commandAvailable = async (command, args) => {
@@ -4,7 +4,7 @@ Kōbō is a local, single-user application that runs Claude Code or OpenAI Codex
4
4
 
5
5
  ## Requirements
6
6
 
7
- - Node.js 24.15 or later, Git and Bash, with a writable local Git repository containing at least one commit.
7
+ - Node.js 26.12.1 or later, Git and Bash, with a writable local Git repository containing at least one commit.
8
8
  - A working login or API credential for the engine you choose. Kōbō ships neither credentials nor a provider subscription. Provider usage can incur charges.
9
9
  - Linux is the locally exercised platform for this readiness change. CI is configured to exercise Linux and macOS; a configured job is not a completed compatibility test. Windows users need a Linux environment such as WSL; native Windows and WSL have not been validated in this release rehearsal.
10
10
 
@@ -6,7 +6,7 @@ Open the first-run setup from Help and run the check again after changing the se
6
6
 
7
7
  | Check | Action |
8
8
  |---|---|
9
- | Node | Use Node 24.15 or later; contributors should use `.nvmrc`. |
9
+ | Node | Use Node 26.12.1 or later; contributors should use `.nvmrc`. |
10
10
  | Git / Bash | Install the missing executable and make it available on the server's `PATH`. |
11
11
  | Project | Select a writable Git repository containing at least one commit. |
12
12
  | Storage / worktrees | Check permissions on `KOBO_HOME`, the project and configured worktree root. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loicngr/kobo",
3
- "version": "2.1.28",
3
+ "version": "2.1.29",
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",
@@ -61,7 +61,7 @@
61
61
  "quasar"
62
62
  ],
63
63
  "engines": {
64
- "node": ">=24.15.0"
64
+ "node": ">=26.12.1"
65
65
  },
66
66
  "scripts": {
67
67
  "dev": "KOBO_ENFORCE_LOCAL_HOME=1 KOBO_HOME=./data PORT=3300 KOBO_DEV_CLIENT_ORIGIN=http://localhost:8080 tsx watch src/server/index.ts",
@@ -88,32 +88,32 @@
88
88
  "security:scan": "node scripts/scan-secrets.mjs"
89
89
  },
90
90
  "dependencies": {
91
- "@anthropic-ai/claude-agent-sdk": "^0.3.287",
91
+ "@anthropic-ai/claude-agent-sdk": "^0.3.308",
92
92
  "@emnapi/core": "^1.11.3",
93
93
  "@emnapi/runtime": "^1.11.3",
94
- "@hono/node-server": "^2.1.3",
95
- "@modelcontextprotocol/sdk": "^1.31.0",
96
- "@openai/codex": "^0.159.3",
94
+ "@hono/node-server": "^2.1.5",
95
+ "@modelcontextprotocol/sdk": "^1.32.1",
96
+ "@openai/codex": "^0.163.0",
97
97
  "better-sqlite3": "^13.0.3",
98
- "cron-parser": "^5.10.1",
99
- "hono": "^4.13.12",
100
- "nanoid": "^6.0.1",
98
+ "cron-parser": "^5.10.2",
99
+ "hono": "^4.13.13",
100
+ "nanoid": "^6.0.2",
101
101
  "node-pty": "^1.1.0",
102
102
  "ws": "^8.22.0"
103
103
  },
104
104
  "devDependencies": {
105
105
  "@biomejs/biome": "2.5.14",
106
106
  "@types/better-sqlite3": "^9.6.0",
107
- "@types/node": "^26.6.4",
107
+ "@types/node": "^26.6.5",
108
108
  "@types/ws": "^8.18.2",
109
109
  "@vitest/runner": "^4.1.11",
110
- "concurrently": "^10.0.5",
110
+ "concurrently": "^10.0.6",
111
111
  "tsx": "^4.23.15",
112
112
  "typescript": "^7.0.2",
113
- "vitest": "^5.0.3"
113
+ "vitest": "^5.0.5"
114
114
  },
115
115
  "overrides": {
116
- "@hono/node-server": "^2.1.3",
117
- "shell-quote": "^1.11.0"
116
+ "@hono/node-server": "^2.1.5",
117
+ "shell-quote": "^1.12.0"
118
118
  }
119
119
  }
@@ -0,0 +1,2 @@
1
+ import{N as e,S as t,ft as n,mt as r,p as i,ut as a,v as o}from"./reactivity.esm-bundler-Dplx1ILy.js";import{C as s,F as c,J as l,L as u,N as d,O as f,P as p,T as m,Y as h,_ as g,d as _,f as v,g as y,j as ee,k as b,l as x,p as S,r as C,u as w,y as T,z as te}from"./runtime-core.esm-bundler-BAUgNzMK.js";import{$ as ne,K as re,M as E,f as ie,z as ae}from"./dom-CRPVbmiy.js";import{l as oe,t as D,u as se}from"./QBtn-kfhHFy7Q.js";import{Gt as ce,Jt as O,O as le,_t as ue,at as de,en as fe,j as pe,m as me,mt as he,pn as ge,pt as _e,rn as k,st as ve,un as A,v as ye}from"./index-DLoUeovT.js";import{t as be}from"./QSpinnerDots-Bea6hAuJ.js";import{t as xe}from"./QList-CAUl0v66.js";import{t as Se}from"./QMarkupTable-B4LLAly-.js";import{c as j,l as M,s as N}from"./QSelect-DOnv_ry0.js";import{t as P}from"./QItemSection-ahqRK4JF.js";import{t as Ce}from"./QExpansionItem-BVb067oc.js";import{a as F,c as we,r as I,t as L}from"./ToolCallItem-C9ksVseJ.js";import{t as Te}from"./QScrollArea-CUDWkEHh.js";import{a as R}from"./use-tours-C_5R1Y5D.js";import{f as Ee,g as z,m as De,p as Oe,u as ke}from"./use-worktree-restore-Cj8eGE9s.js";import{t as B}from"./QTooltip-B5QJIU3p.js";import{n as V}from"./render-chat-markdown-C9ihAYBt.js";import{n as H}from"./WorkspacePage-BTJnap9a.js";function Ae(e,t){return s(`div`,e,[s(`table`,{class:`q-table`},t)])}var je={list:xe,table:Se},U=[`list`,`table`,`__qtable`],Me=ae({name:`QVirtualScroll`,props:{...M,type:{type:String,default:`list`,validator:e=>U.includes(e)},items:{type:Array,default:()=>[]},itemsFn:Function,itemsSize:Number,scrollTarget:ge},setup(e,{slots:n,attrs:r}){let i,a=t(null),o=x(()=>e.itemsSize>=0&&e.itemsFn!==void 0?Number.parseInt(e.itemsSize,10):Array.isArray(e.items)?e.items.length:0),{virtualScrollSliceRange:c,localResetVirtualScroll:u,padVirtualScroll:f,onVirtualScrollEvt:m}=j({virtualScrollLength:o,getVirtualScrollTarget:y,getVirtualScrollEl:v}),h=x(()=>{if(o.value===0)return[];let t=(e,t)=>({index:c.value.from+t,item:e});return e.itemsFn===void 0?e.items.slice(c.value.from,c.value.to).map(t):e.itemsFn(c.value.from,c.value.to-c.value.from).map(t)}),g=x(()=>`q-virtual-scroll q-virtual-scroll`+(e.virtualScrollHorizontal?`--horizontal`:`--vertical`)+(e.scrollTarget===void 0?` scroll`:``)),_=x(()=>e.scrollTarget===void 0?{tabindex:0}:{});l(o,()=>{u()}),l(()=>e.scrollTarget,()=>{C(),S()});function v(){let e=a.value;return e===null?null:e.$el||e}function y(){return i}function S(){let t=v();t!==null&&(i=A(t,e.scrollTarget),i.addEventListener(`scroll`,m,E.passive))}function C(){i!==void 0&&(i.removeEventListener(`scroll`,m,E.passive),i=void 0)}function w(){let t=f(e.type===`list`?`div`:`tbody`,h.value.map(n.default));return n.before!==void 0&&(t=n.before().concat(t)),ie(n.after,t)}return u(),p(()=>{S()}),b(()=>{S()}),d(()=>{C()}),ee(()=>{C()}),()=>{if(n.default===void 0)console.error(`QVirtualScroll: default scoped slot is required for rendering`);else return e.type===`__qtable`?Ae({ref:a,class:`q-table__middle `+g.value,tabindex:0},w()):s(je[e.type],{...r,ref:a,class:[r.class,g.value],..._.value},w)}}}),Ne=new Set([`setup`,`cleanup`,`archive`]);function Pe(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:Ne.has(e.sender)||le(e.sender)?`script`:`user`;case`session`:return`session`;default:return`agent`}}function Fe(e){let t=[],n=null,r=null;for(let i of e){let e=Pe(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 W(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 Ie(e){let t=e.items[0];return`${e.speaker}:${t?W(t):`empty`}`}function Le(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 Re(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))};o=l(e,e=>{t(e)&&s(!0)},{immediate:!0}),i?o():a=setTimeout(()=>s(!1),n)})}var ze={class:`agent-error-item`},Be={class:`agent-error-item__body`},Ve={class:`agent-error-item__title`},G={class:`agent-error-item__message`},He=R(T({__name:`AgentErrorItem`,props:{item:{}},setup(e){let t=e,{te:n}=fe(),i=x(()=>{let e=`agent.error.${t.item.category}`;return n(e)?e:`agent.error.other`});return(t,n)=>(u(),S(`div`,ze,[g(oe,{name:`error_outline`,size:`16px`,class:`agent-error-item__icon`}),w(`div`,Be,[w(`div`,Ve,r(t.$t(i.value)),1),w(`div`,G,r(e.item.message),1)])]))}}),[[`__scopeId`,`data-v-e98c3c02`]]),Ue={class:`text-caption text-kobo-3`},We=T({__name:`SessionEventItem`,props:{item:{}},setup(e){let t=e,n=x(()=>{switch(t.item.kind){case`started`:return`session.started`;case`ended`:return z(t.item.detail);case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,t)=>(u(),S(`span`,Ue,r(e.$t(n.value)),1))}}),K=new Map;function q(){for(let e of K.values())e.controller.abort(),e.blobUrl&&URL.revokeObjectURL(e.blobUrl);K.clear()}typeof window<`u`&&(window.addEventListener(`kobo:auth-token-changed`,q),window.addEventListener(`storage`,e=>{(e.key===`kobo:network-token`||e.key===null)&&q()}));function J(e){if(!/^\/api\/workspaces\/[^/]+\/images\/file\?path=/.test(e))throw Error(`Invalid workspace image URL`);let t=K.get(e);if(!t){let n=new AbortController,r={references:0,controller:n,ready:Promise.resolve(``)};r.ready=ce(e,{signal:n.signal}).then(async e=>{if(!e.ok)throw await O(e);let t=await e.blob();if(n.signal.aborted)throw new DOMException(`Aborted`,`AbortError`);return r.blobUrl=URL.createObjectURL(t),r.blobUrl}),t=r,K.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),K.get(e)===r&&K.delete(e)))}}}function Ge(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=J(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 Ke(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 qe=[`innerHTML`],Je=[`innerHTML`],Ye=[`src`],Y=R(T({__name:`UserMessageItem`,props:{item:{},workspaceId:{}},setup(t){let n=t,{t:r}=fe(),a=x(()=>n.item.sender===`system-prompt`),s=Ge(x(()=>{let e=Ke(n.item.content,n.workspaceId);return V(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(()=>n.workspaceId,p);let m=e=>{(e.key===`kobo:network-token`||e.key===null)&&p()};window.addEventListener(`storage`,m),window.addEventListener(`kobo:auth-token-changed`,p),i(()=>{p(),window.removeEventListener(`kobo:auth-token-changed`,p),window.removeEventListener(`storage`,m)});function y(e){let t=e.target;if(t?.tagName!==`IMG`)return;let n=t;n.src&&(p(),n.dataset.koboImageUrl&&(f=J(n.dataset.koboImageUrl),f.ready.catch(p)),c.value=n.src,d.value=!0)}return(t,n)=>(u(),S(C,null,[a.value?(u(),_(Ce,{key:0,dense:``,"dense-toggle":``,label:t.$t(`chat.systemPrompt`),"header-class":`text-kobo-2 text-caption`},{default:h(()=>[w(`div`,{class:`q-py-xs markdown-message markdown-user-prompt`,innerHTML:e(s)},null,8,qe)]),_:1},8,[`label`])):(u(),S(`div`,{key:1,class:`markdown-message`,onClick:y},[w(`div`,{innerHTML:e(s)},null,8,Je)])),g(k,{modelValue:d.value,"onUpdate:modelValue":n[1]||=e=>d.value=e},{default:h(()=>[c.value?(u(),S(`img`,{key:0,src:c.value,alt:``,class:`image-lightbox-img`,onClick:n[0]||=e=>d.value=!1},null,8,Ye)):v(``,!0)]),_:1},8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-965e6297`]]),Xe=[`data-event-ids`],X={class:`turn-header`},Ze={key:0,class:`turn-time`},Qe={class:`turn-time turn-time-updated`},Z={key:2,class:`turn-actions`},$e={class:`turn-body`},et={class:`ellipsis`},tt={class:`q-px-sm q-pb-sm`},nt={key:0,class:`turn-scroll-top`},rt=R(T({__name:`TurnCard`,props:{turn:{},workspaceId:{},highlighted:{type:Boolean}},emits:[`scrollTo`],setup(t,{emit:i}){let s=t,c=i,{t:l}=fe(),d=de(),f=m(F),p=o(null);function ee(){let e=p.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 b=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:le(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 T(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 re=x(()=>T(s.turn.ts)),E=x(()=>s.turn.items.flatMap(e=>e.eventIds??[]).join(` `)),ie=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}),ae=x(()=>{let e=s.turn.ts,t=ie.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?``:T(t,r-n<6e4)}),se=x(()=>ae.value!==``);function ce(e){return we(e.origin,Object.values(d.subagents[s.workspaceId]??{}),e.type===`tool`?e.toolCallId:void 0)}function O(e){return e||l(`chat.subagentActivity`)}function ue(e){return(e.type===`text`||e.type===`thinking`||e.type===`tool`)&&e.origin?.kind===`subagent`}let pe=x(()=>{let e=[],t=new Map;for(let n of s.turn.items){if(!ue(n)){e.push({type:`item`,key:W(n),item:n});continue}let r=ce(n),i=r?.toolUseId??n.origin?.toolCallId??n.origin?.threadId??W(n),a=t.get(i);if(a){a.items.push(n);continue}let o={type:`subagent`,key:`subagent:${W(n)}`,items:[n],subagentKey:i,subagentName:r?.description||null};t.set(i,o),e.push(o)}return e});function me(e){e.origin&&f?.({origin:e.origin})}let he=x(()=>s.turn.items.filter(e=>e.type===`tool`).length);return(i,o)=>(u(),S(`div`,{ref_key:`cardEl`,ref:p,class:a([`turn-card`,{"turn-card--user":t.turn.speaker===`user`,"turn-card--highlighted":t.highlighted}]),"data-event-ids":E.value,style:n({"--turn-accent":b.value.accent})},[w(`div`,X,[w(`span`,{class:a([`turn-badge`,b.value.badgeClass])},r(b.value.label),3),re.value?(u(),S(`span`,Ze,r(re.value),1)):v(``,!0),se.value?(u(),S(C,{key:1},[g(oe,{name:`arrow_forward`,size:`10px`,color:`kobo-3`,class:`turn-time-arrow`}),w(`span`,Qe,[y(r(ae.value)+` `,1),g(B,null,{default:h(()=>[y(r(e(l)(`chat.lastUpdatedAt`,{time:ae.value})),1)]),_:1})])],64)):v(``,!0),he.value>0?(u(),S(`span`,Z,` · `+r(e(l)(`chat.nActions`,{n:he.value})),1)):v(``,!0)]),w(`div`,$e,[(u(!0),S(C,null,te(pe.value,n=>(u(),S(C,{key:n.key},[n.type===`subagent`?(u(),_(Ce,{key:0,class:`turn-subagent-activity`,dense:``,label:O(n.subagentName),caption:e(l)(`chat.nActions`,{n:n.items.length}),"default-opened":t.highlighted&&n.items.some(e=>e.eventIds?.some(e=>E.value.includes(e)))},{header:h(()=>[g(P,null,{default:h(()=>[g(N,{class:`row items-center no-wrap`,title:n.subagentName??void 0},{default:h(()=>[g(oe,{name:`hub`,size:`16px`,class:`q-mr-xs`},{default:h(()=>[g(B,null,{default:h(()=>[y(r(e(l)(`chat.subagentActivity`)),1)]),_:1})]),_:1}),w(`span`,et,r(O(n.subagentName)),1)]),_:2},1032,[`title`]),g(N,{caption:``},{default:h(()=>[y(r(e(l)(`chat.nActions`,{n:n.items.length})),1)]),_:2},1024)]),_:2},1024),g(P,{side:``},{default:h(()=>[g(D,{flat:``,round:``,dense:``,size:`sm`,icon:`open_in_new`,"aria-label":e(l)(`chat.openSubagentActivity`),onClick:ne(e=>me(n.items[0]),[`stop`])},{default:h(()=>[g(B,null,{default:h(()=>[y(r(e(l)(`chat.openSubagentActivity`)),1)]),_:1})]),_:1},8,[`aria-label`,`onClick`])]),_:2},1024)]),default:h(()=>[w(`div`,tt,[(u(!0),S(C,null,te(n.items,t=>(u(),S(C,{key:e(W)(t)},[t.type===`text`?(u(),_(I,{key:0,item:t},null,8,[`item`])):t.type===`thinking`?(u(),_(H,{key:1,item:t},null,8,[`item`])):t.type===`tool`?(u(),_(L,{key:2,item:t},null,8,[`item`])):v(``,!0)],64))),128))])]),_:2},1032,[`label`,`caption`,`default-opened`])):(u(),S(C,{key:1},[n.item.type===`text`?(u(),_(I,{key:0,item:n.item},null,8,[`item`])):n.item.type===`thinking`?(u(),_(H,{key:1,item:n.item},null,8,[`item`])):n.item.type===`tool`?(u(),_(L,{key:2,item:n.item},null,8,[`item`])):n.item.type===`user`?(u(),_(Y,{key:3,item:n.item,"workspace-id":t.workspaceId},null,8,[`item`,`workspace-id`])):n.item.type===`session`?(u(),_(We,{key:4,item:n.item},null,8,[`item`])):n.item.type===`error`?(u(),_(He,{key:5,item:n.item},null,8,[`item`])):v(``,!0)],64))],64))),128))]),t.turn.items.length>4?(u(),S(`div`,nt,[g(D,{flat:``,round:``,dense:``,size:`xs`,icon:`arrow_upward`,color:`kobo-3`,class:`turn-scroll-top-btn`,onClick:ee},{default:h(()=>[g(B,null,{default:h(()=>[y(r(e(l)(`chat.scrollToTurnTop`)),1)]),_:1})]),_:1})])):v(``,!0)],14,Xe))}}),[[`__scopeId`,`data-v-13bebb3d`]]),it={key:0,class:`activity-feed-switching`},at={key:1,class:`activity-feed-wrap`,"data-tour":`ws-chat`},ot={key:0,role:`alert`,class:`q-pa-sm text-negative`},st={key:1,"data-testid":`history-load-error`,role:`alert`,class:`q-pa-sm text-negative`},ct=[`aria-label`],lt={key:0,class:`activity-feed-compacting`},ut={class:`text-caption text-kobo-2`},dt={key:0,class:`text-center q-py-sm text-caption text-kobo-3`},ft={key:1,class:`activity-feed-empty q-pa-md`},pt={class:`activity-feed-empty__title`},mt={class:`activity-feed-empty__hint`},ht={key:2,class:`q-px-md q-pb-md`},gt=[`title`],_t={class:`ellipsis`},vt={class:`activity-feed-nav-cluster`},yt=300,bt=60,xt=200,St=180,Ct=255,wt=3,Tt=60,Et=R(T({__name:`ActivityFeed`,props:{workspaceId:{}},setup(t){let{t:n}=fe(),i=t,a=ue(),s=pe(),d=de(),m=me(),ee=x(()=>m.isCompacting(i.workspaceId)),b=x(()=>d.selectedSessionId),T=x(()=>d.sessions.find(e=>e.id===b.value)?.engineSessionId??null),ne=x(()=>{let e=d.sessions;return e.length!==0&&b.value===e[e.length-1].id});function E(e){return b.value?e?e===b.value||e===T.value:ne.value:!0}let ie=x(()=>(d.activityFeeds[i.workspaceId]??[]).filter(e=>e.type===`text`&&typeof e.content==`string`&&E(e.sessionId)).map(e=>({content:e.content,sender:e.meta?.sender??`user`,source:ye(e.meta?.source),ts:e.timestamp,sessionId:e.sessionId,eventIds:[e.id]}))),ae=x(()=>{let e=d.workspaces.find(e=>e.id===i.workspaceId);return ve(e?.status)}),le=ke(),ge=``,k=x(()=>{let e=a.eventsFor(i.workspaceId),t=a.timestampsFor(i.workspaceId),n=a.sessionIdsFor(i.workspaceId),r=a.eventIdsFor(i.workspaceId),o=[],c=[],l=[];for(let i=0;i<e.length;i++)E(n[i])&&(o.push(e[i]),c.push(t[i]),l.push(r[i]??null));let u=`${i.workspaceId}::${b.value??`*`}`;u!==ge&&(le=ke(),ge=u);let d=Ee(le,o,c,ae.value,l);return Fe(De(d,ie.value).filter(e=>e.type===`thinking`?!1:e.type===`session`?e.kind===`ended`?s.showVerboseSystemMessages||!Oe(e.detail):s.showVerboseSystemMessages:!0))}),A=x(()=>s.showVerboseSystemMessages?a.eventsFor(i.workspaceId).filter(e=>e.kind===`message:raw`).map(e=>e.content):[]),xe=x(()=>{for(let e=k.value.length-1;e>=0;e--){let t=k.value[e]?.items??[];for(let e=t.length-1;e>=0;e--){let r=t[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?n(`activity.a11y.toolFailed`,{name:r.name}):n(`activity.a11y.toolFinished`,{name:r.name})}:{key:`tool:${r.toolCallId}:start`,text:n(`activity.a11y.toolStarted`,{name:r.name})}}}}return null}),Se=o(``);l(xe,(e,t)=>{if(!e||e.key===t?.key)return;let r=e.key.startsWith(`text:`)?n(`activity.a11y.agentSaid`,{text:e.text.slice(0,yt)}):e.text;Se.value=r});let j=o(null),M=o(!0),N=o(!1),P=o(``),F=_e(),we=_e(),I=_e(),L=o(null),R=!1,z=!0,B=null,V=o(new Set),H=new Map,Ae=x(()=>{if(k.value.length>0||A.value.length>0)return!1;let e=i.workspaceId,t=b.value;return!!d.loadingSessions[e]||m.isSyncPending(e)||t!==null&&V.value.has(W(e,t))}),je=o(new Map),U=x(()=>k.value.length>0||A.value.length>0),Ne=x(()=>!!d.loadingSessions[i.workspaceId]||m.isSyncPending(i.workspaceId)||b.value!==null&&V.value.has(W(i.workspaceId,b.value)));function Pe(e){et();let t=B;if(B=e.verticalSize,t!==null&&e.verticalSize>t&&M.value&&!N.value){q(0);return}let n=e.verticalSize-e.verticalPosition-e.verticalContainerSize;M.value=n<=bt,R&&e.verticalPosition<=xt&&!N.value&&!P.value&&ze()&&He()}function W(e,t){return`${e}:${t}`}function ze(){let e=b.value;return e?je.value.get(W(i.workspaceId,e))??!0:a.hasMoreOlderFor(i.workspaceId)}function Be(e,t,n){je.value.set(W(e,t),n)}function Ve(e){if(!b.value)return a.oldestIdFor(e);let t=a.eventIdsFor(e),n=a.sessionIdsFor(e);for(let e=0;e<t.length;e++){if(!E(n[e]))continue;let r=t[e];if(r)return r}}let G=null;function He(){if(G)return G;let e=K().finally(()=>{G===e&&(G=null)});return G=e,G}function Ue(){F.abort(),we.abort(),I.abort(),N.value=!1,G=null;for(let e of V.value)Ft.delete(e);H.clear(),V.value.clear(),P.value=``}function We(){P.value=``,Mt.value===0&&b.value?It():He()}l(()=>[i.workspaceId,b.value],Ue,{flush:`sync`});async function K(){let e=i.workspaceId,t=b.value,n=Ve(e);if(!n)return;let r=F.begin();P.value=``,N.value=!0;try{let i=j.value;if(await f(),!F.isCurrent(r))return;let o=i?.getScroll().verticalSize??0,s=i?.getScroll().verticalPosition??0,c=new URLSearchParams({before:n,limit:`200`});t&&c.set(`session`,t);let l=await ce(`/api/workspaces/${e}/events?${c.toString()}`,{signal:r});if(!l.ok)throw await O(l);let u=await l.json();if(!F.isCurrent(r))return;let p=u.events??[],m=p.filter(t=>t.type===`agent:event`&&t.workspaceId===e),h=p.filter(t=>t.type===`user:message`&&t.workspaceId===e),g=m.map(e=>e.payload),_=m.map(e=>e.createdAt),v=m.map(e=>e.sessionId??null),y=m.map(e=>e.id),ee=p.length>0?p[0].id:n;t&&Be(e,t,u.hasMore),a.prepend(e,g,_,{oldestId:ee,hasMoreOlder:t?a.hasMoreOlderFor(e):u.hasMore,sessionIds:v,eventIds:y});for(let t of h){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:ye(n.source)}})}if(await f(),i&&F.isCurrent(r)){let e=i.getScroll().verticalSize-o;if(e>0){let t=Math.max(s+e,250);i.setScrollPosition(`vertical`,t,0)}}}catch(e){if(he(e)||!F.isCurrent(r))return;P.value=e instanceof Error?e.message:String(e),console.error(`[ActivityFeed] failed to load older events:`,e)}finally{F.isCurrent(r)&&(N.value=!1)}}async function q(e=0){let t=Pt();if(await f(),t!==Pt())return;let n=j.value;if(!n)return;let r=n.getScroll();n.setScrollPosition(`vertical`,r.verticalSize,e)}let J=null,Ge=0;function Ke(){if(J!=null)return;let e=performance.now()-Ge<St,t=Pt();J=requestAnimationFrame(()=>{J=null,t===Pt()&&(Ge=performance.now(),q(e?0:180))})}function qe(e){$(),M.value=!1;let t=j.value;t&&t.setScrollPosition(`vertical`,Math.max(0,e),250)}function Je(){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 Ye(e){let t=e.detail;if(t?.workspaceId!==i.workspaceId||!t.eventId)return;$(),M.value=!1;let n=I.begin(),r=i.workspaceId;try{let e=new URLSearchParams({around:t.eventId,limit:`200`});t.sessionId&&e.set(`session`,t.sessionId);let o=await ce(`/api/workspaces/${r}/events?${e}`,{signal:n});if(!o.ok)throw await O(o);let s=await o.json();if(!I.isCurrent(n))return;let c=s.events??[],l=c.filter(e=>e.type===`agent:event`&&e.workspaceId===i.workspaceId),u=c.filter(e=>e.type===`user:message`&&e.workspaceId===i.workspaceId);a.reset(i.workspaceId,l.map(e=>e.payload),l.map(e=>e.createdAt),{oldestId:c[0]?.id,hasMoreOlder:s.hasMore??!1,sessionIds:l.map(e=>e.sessionId),eventIds:l.map(e=>e.id)});for(let e of u){let t=e.payload;typeof t.content==`string`&&d.addActivityItem(i.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`,source:ye(t.source)}})}if(await Re(Ae,e=>!e,5e3),await f(),await new Promise(e=>requestAnimationFrame(()=>requestAnimationFrame(()=>e()))),!I.isCurrent(n))return;let p=k.value.findIndex(e=>e.items.some(e=>e.eventIds?.includes(t.eventId)??!1));if(p<0)return;L.value=t.eventId,Y.value?.scrollTo(p,`center`),X.value=p,window.setTimeout(()=>{L.value===t.eventId&&(L.value=null)},1800)}catch(e){if(he(e)||!I.isCurrent(n))return;P.value=e instanceof Error?e.message:String(e),console.error(`[ActivityFeed] failed to focus history event:`,e)}}let Y=o(null),Xe=o(null),X=o(0),Ze=o(!1),Qe=x(()=>{for(let e=k.value.length-1;e>=0;e--)if(k.value[e]?.speaker===`user`)return e;return-1}),Z=null;function $e(){let e=Qe.value,t=j.value?.getScrollTarget(),n=t?.querySelector(`[data-turn-index="${e}"]`);if(!n||!t){Ze.value=!1;return}let r=t.getBoundingClientRect(),i=n.getBoundingClientRect();Ze.value=i.bottom>r.top&&i.top<r.bottom}function et(){Z===null&&(Z=requestAnimationFrame(()=>{Z=null,$e()}))}function tt(e){return e.length<=Ct?e:`${e.slice(0,252)}...`}let nt=x(()=>{let e=Qe.value,t=k.value[e];if(!t||X.value<=e||Ze.value)return null;let n=t.items.filter(e=>e.type===`user`).map(e=>e.content).join(`
2
+ `).trim();return n?{index:e,content:tt(n)}:null});function Et(e){X.value=e.index,et()}function Dt(){let e=nt.value;e&&($(),M.value=!1,Y.value?.scrollTo(e.index,`start`),X.value=e.index)}let Ot=o(!1);async function kt(){if(Ot.value)return;$(),M.value=!1,Ot.value=!0;let e=i.workspaceId;try{let t=Le(k.value,X.value);if(t<0)for(let n=0;n<15;n++){if(e!==i.workspaceId)return;if(!ze())break;let n=k.value.length;if(await He(),await f(),e!==i.workspaceId)return;if(X.value+=k.value.length-n,t=Le(k.value,X.value),t>=0)break}t>=0&&e===i.workspaceId&&(Y.value?.scrollTo(t,`start`),X.value=t)}finally{Ot.value=!1}}let Q=0;function At(){return new Promise(e=>requestAnimationFrame(()=>e()))}async function jt(){if(!z||!U.value||Ae.value)return;R=!1;let e=++Q;if(await f(),e!==Q||!z||(Xe.value=j.value?.getScrollTarget()??null,await f(),e!==Q||!z))return;k.value.length>0&&Y.value?.scrollTo(k.value.length-1,`end-force`),await At();let t=-1,n=0;for(let r=0;r<Tt&&n<wt;r++){if(e!==Q||!z)return;await q(0),await At();let r=j.value?.getScroll().verticalSize??0;B=r,n=r===t?n+1:0,t=r}e===Q&&!Ne.value&&(R=!0,z=!1)}function $(){z=!1,!R&&(Q++,R=!0)}let Mt=x(()=>{let e=a.sessionIdsFor(i.workspaceId);if(!b.value)return e.length;let t=0;for(let n of e)E(n)&&t++;return t});l(Ae,async e=>{!e&&U.value&&await jt(),e||f(()=>{Xe.value=j.value?.getScrollTarget()??null,et()})}),l(Ne,(e,t)=>{!e&&t&&z&&U.value&&jt()}),p(()=>{window.addEventListener(`kobo:focus-history-event`,Ye),f(()=>{Xe.value=j.value?.getScrollTarget()??null,et()}),U.value&&jt(),b.value&&It();let e=new URLSearchParams(window.location.hash.split(`?`)[1]??``).get(`eventId`);e&&(Ye(new CustomEvent(`kobo:focus-history-event`,{detail:{workspaceId:i.workspaceId,sessionId:b.value,eventId:e}})),Je())}),l([Mt,()=>ie.value.length,()=>A.value.length],async([e,t,n])=>{N.value||z&&e+t+n>0&&await jt()}),l([Qe,()=>k.value.length],()=>{f(et)});let Nt=x(()=>a.liveAppendCountFor(i.workspaceId,E)),Pt=()=>`${i.workspaceId}\u0000${d.selectedSessionId??``}`;l([Nt,Pt],([e,t],[n,r])=>{t===r&&e>n&&M.value&&!N.value&&Ke()}),c(()=>{Q++,z=!1,Ue(),window.removeEventListener(`kobo:focus-history-event`,Ye),J!=null&&(cancelAnimationFrame(J),J=null),Z!==null&&cancelAnimationFrame(Z)}),l([()=>i.workspaceId,()=>d.selectedSessionId],()=>{Q++,z=!0,B=null,M.value=!0,R=!1,It(),U.value&&jt()});let Ft=new Set;async function It(){let e=i.workspaceId,t=b.value;if(!t||Mt.value>0)return;let n=W(e,t);if(Ft.has(n))return;Ft.add(n),V.value.add(n);let r=we.begin();H.set(n,r),P.value=``;try{let n=await ce(`/api/workspaces/${e}/events?session=${encodeURIComponent(t)}&limit=500`,{signal:r});if(!n.ok)throw await O(n);let i=await n.json();if(!we.isCurrent(r))return;let o=i.events??[];if(o.length===0)return;let s=o.filter(t=>t.type===`agent:event`&&t.workspaceId===e),c=o.filter(t=>t.type===`user:message`&&t.workspaceId===e),l=s.map(e=>e.payload),u=s.map(e=>e.createdAt),f=s.map(e=>e.sessionId??null),p=s.map(e=>e.id);Be(e,t,i.hasMore),l.length>0&&a.prepend(e,l,u,{oldestId:o[0].id,hasMoreOlder:a.hasMoreOlderFor(e),sessionIds:f,eventIds:p});for(let t of c){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:ye(n.source)}})}}catch(e){if(he(e)||!we.isCurrent(r)){H.has(n)&&H.get(n)!==r||Ft.delete(n);return}P.value=e instanceof Error?e.message:String(e),console.error(`[ActivityFeed] fetchSessionIfMissing failed:`,e),Ft.delete(n)}finally{H.get(n)===r&&(H.delete(n),V.value.delete(n))}}let Lt=x(()=>ie.value.filter(e=>e.sender===`user`).length),Rt=x(()=>(d.activityFeeds[i.workspaceId]??[]).filter(e=>e.meta?.sender===`user`&&e.meta.pending&&E(e.sessionId)).length);l([Lt,Rt,Pt],async([e,t,n],[r,i,a])=>{let o=t>i;n===a&&(o||e>r&&M.value&&!N.value&&!Ne.value)&&(M.value=!0,await q(o?180:0))});async function zt(){M.value=!0,await q(250)}return(t,n)=>Ae.value?(u(),S(`div`,it,[g(be,{size:`40px`,color:`primary`})])):(u(),S(`div`,at,[e(d).sessionsErrors[i.workspaceId]?(u(),S(`div`,ot,[y(r(t.$t(`activity.sessionsError`,{message:e(d).sessionsErrors[i.workspaceId]}))+` `,1),g(D,{flat:``,dense:``,label:t.$t(`common.retry`),onClick:n[0]||=t=>e(d).fetchSessions(i.workspaceId)},null,8,[`label`])])):v(``,!0),P.value?(u(),S(`div`,st,[y(r(t.$t(`activity.historyError`,{message:P.value}))+` `,1),g(D,{flat:``,dense:``,label:t.$t(`common.retry`),onClick:We},null,8,[`label`])])):v(``,!0),w(`div`,{"data-testid":`activity-live-region`,class:`sr-only`,role:`log`,"aria-live":`polite`,"aria-atomic":`true`,"aria-label":t.$t(`activity.a11y.region`)},r(Se.value),9,ct),g(re,{name:`fade`},{default:h(()=>[ee.value?(u(),S(`div`,lt,[g(be,{size:`18px`,color:`primary`}),w(`span`,ut,r(t.$t(`activity.compacting`)),1)])):v(``,!0)]),_:1}),g(Te,{ref_key:`scrollRef`,ref:j,class:`activity-feed-scroll`,onScroll:Pe,onWheelPassive:$,onTouchstartPassive:$,onKeydown:$},{default:h(()=>[N.value?(u(),S(`div`,dt,[g(se,{size:`sm`}),y(` `+r(t.$t(`activity.loading_older`)),1)])):v(``,!0),g(Me,{ref_key:`virtualScrollRef`,ref:Y,class:`q-pa-md`,items:k.value,"scroll-target":Xe.value??void 0,"virtual-scroll-item-size":160,"virtual-scroll-slice-size":20,onVirtualScroll:Et},{default:h(({item:t,index:n})=>[(u(),_(rt,{key:e(Ie)(t),turn:t,"workspace-id":i.workspaceId,"data-turn-index":n,highlighted:t.items.some(e=>e.eventIds?.includes(L.value??``)??!1),onScrollTo:qe},null,8,[`turn`,`workspace-id`,`data-turn-index`,`highlighted`]))]),_:1},8,[`items`,`scroll-target`]),k.value.length===0&&A.value.length===0&&!N.value?(u(),S(`div`,ft,[g(oe,{name:`forum`,size:`28px`}),w(`div`,pt,r(t.$t(`activity.empty`)),1),w(`div`,mt,r(t.$t(`activity.emptyHint`)),1)])):v(``,!0),A.value.length?(u(),S(`div`,ht,[g(Ce,{label:t.$t(`activity.raw_lines`,{n:A.value.length}),dense:``},{default:h(()=>[(u(!0),S(C,null,te(A.value,(e,t)=>(u(),S(`div`,{key:t,class:`text-caption text-kobo-3 q-pa-xs`},r(e),1))),128))]),_:1},8,[`label`])])):v(``,!0)]),_:1},512),nt.value?(u(),S(`button`,{key:2,type:`button`,class:`activity-feed-last-user`,"data-testid":`latest-user-message`,title:nt.value.content,onClick:Dt},[g(oe,{name:`person`,size:`16px`}),w(`span`,_t,r(nt.value.content),1)],8,gt)):v(``,!0),w(`div`,vt,[M.value?v(``,!0):(u(),_(D,{key:0,round:``,dense:``,unelevated:``,color:`kobo-surface-2`,"text-color":`kobo-1`,icon:`arrow_downward`,size:`sm`,class:`activity-feed-nav-btn`,title:t.$t(`activity.scroll_to_bottom`),"aria-label":t.$t(`activity.scroll_to_bottom`),onClick:zt},null,8,[`title`,`aria-label`])),g(D,{round:``,dense:``,unelevated:``,color:`kobo-surface-2`,"text-color":`kobo-1`,icon:`arrow_upward`,size:`sm`,class:`activity-feed-nav-btn`,title:t.$t(`activity.prev_user_message`),"aria-label":t.$t(`activity.prev_user_message`),loading:Ot.value,disable:Ot.value,onClick:kt},null,8,[`title`,`aria-label`,`loading`,`disable`])])]))}}),[[`__scopeId`,`data-v-58324159`]]);export{Et as default};
@@ -1 +1 @@
1
- import{M as e,pt as t,v as n}from"./reactivity.esm-bundler-DY1JkAEA.js";import{J as r,L as i,Y as a,_ as o,d as s,f as c,l,p as u,r as d,u as f,y as p}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{t as m}from"./QBtn-BUSdPaf4.js";import{Nt as h,Pt as g,bn as _,en as v,f as y,j as b,l as x,rn as S,vn as C}from"./index-CpWBGKdM.js";import{t as w}from"./QSelect-DFWyDWCE.js";import{a as T}from"./use-tours-BWkHp34X.js";import{i as E,t as D}from"./permissionModes-D-Nexnoo.js";import{t as O}from"./efforts-TGacUPcJ.js";function k(e,t){return e.engine!==t.engine||e.model!==t.model||e.reasoningEffort!==t.reasoningEffort||e.agentPermissionMode!==t.agentPermissionMode}var A={class:`text-h6`},j={class:`text-body2 text-kobo-2 q-mt-xs`},ee={class:`row q-col-gutter-sm q-mb-md`},te={class:`col-12 col-sm-6`},ne={class:`col-12 col-sm-6`},M={class:`col-12 col-sm-6`},N={class:`col-12 col-sm-6`},P={key:0,class:`text-caption text-kobo-3 q-mt-xs`},F={class:`text-caption text-kobo-3 q-mt-xs`},I={class:`text-caption text-kobo-3 q-mt-xs`},L=T(p({__name:`StartReviewDialog`,props:{modelValue:{type:Boolean},loading:{type:Boolean},workspace:{},canReturnToSession:{type:Boolean},currentSession:{},mode:{},scheduledConfiguration:{}},emits:[`update:modelValue`,`submit`],setup(e,{emit:p}){let T=e,L=p,{t:R}=v(),z=b(),B=l(()=>T.mode===`auto-loop`),V=n(``),H=n(!1),U=n(!1),W=n(`claude-code`),G=n(`auto`),K=n(`auto`),q=n(`bypass`),J=l(()=>B.value||U.value?`plan`:q.value),Y=l(()=>({engine:W.value,model:G.value,reasoningEffort:K.value,agentPermissionMode:J.value})),X=l(()=>{let e=T.currentSession;return B.value||U.value||!!T.workspace&&k(Y.value,T.workspace)||!!e?.engine&&e.engine!==W.value||G.value!==`auto`&&!!e?.model&&e.model!==G.value}),Z=l({get:()=>H.value||X.value,set:e=>{H.value=e}}),re=l(()=>[{value:`claude-code`,label:R(`workspacePage.engineClaude`)},{value:`codex`,label:R(`workspacePage.engineCodex`)}]),Q=l(()=>{let e=(E[W.value]??[]).map(e=>({value:e.value,label:R(e.i18nLabelKey)}));T.workspace?.engine===W.value&&!e.some(e=>e.value===T.workspace?.model)&&e.push({value:T.workspace.model,label:T.workspace.model});let t=T.scheduledConfiguration;return t?.engine===W.value&&!e.some(e=>e.value===t.model)&&e.push({value:t.model,label:t.model}),e}),ie=l(()=>(O[W.value]??[]).map(e=>({value:e.value,label:R(e.i18nLabelKey)}))),$=l(()=>(D[W.value]??[]).map(e=>({value:e,label:R(`agentPermissionMode.${e}`)})));r(W,()=>{let e=T.workspace,t=z.global.defaultModelByEngine[W.value];G.value=e?.engine===W.value?e.model:Q.value.some(e=>e.value===t)?t:`auto`,K.value=e?.engine===W.value?e.reasoningEffort:`auto`,$.value.some(e=>e.value===q.value)||(q.value=`plan`)},{flush:`sync`}),r([()=>T.modelValue,()=>T.workspace?.id],([e])=>{if(!e)return;let t=B.value?T.scheduledConfiguration:null;V.value=t?.additionalInstructions??``,H.value=!1,U.value=B.value,T.workspace&&(W.value=T.workspace.engine,G.value=T.workspace.model,K.value=T.workspace.reasoningEffort,q.value=T.workspace.agentPermissionMode),t&&(W.value=t.engine,G.value=t.model,K.value=t.reasoningEffort)},{immediate:!0}),r(()=>T.canReturnToSession,e=>{!e&&!B.value&&(U.value=!1)});function ae(){T.loading||L(`update:modelValue`,!1)}function oe(){!T.loading&&T.workspace&&L(`submit`,{...Y.value,additionalInstructions:V.value,newSession:Z.value,returnToSession:B.value||U.value&&T.canReturnToSession})}return(n,r)=>(i(),s(S,{"model-value":e.modelValue,persistent:e.loading,"onUpdate:modelValue":r[7]||=e=>L(`update:modelValue`,e)},{default:a(()=>[o(C,{class:`review-card text-kobo-1`},{default:a(()=>[o(_,null,{default:a(()=>[f(`div`,A,t(n.$t(B.value?`autoLoop.finalReview.title`:`review.title`)),1),f(`div`,j,t(n.$t(B.value?`autoLoop.finalReview.description`:`review.subtitle`)),1)]),_:1}),o(y,{dark:``}),o(_,{class:`q-pt-md`},{default:a(()=>[f(`div`,ee,[f(`div`,te,[o(w,{modelValue:W.value,"onUpdate:modelValue":r[0]||=e=>W.value=e,options:re.value,label:n.$t(`engine.select`),disable:e.loading,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``},null,8,[`modelValue`,`options`,`label`,`disable`])]),f(`div`,ne,[o(w,{modelValue:G.value,"onUpdate:modelValue":r[1]||=e=>G.value=e,options:Q.value,label:n.$t(`engine.model`),disable:e.loading,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``},null,8,[`modelValue`,`options`,`label`,`disable`])]),f(`div`,M,[o(w,{modelValue:K.value,"onUpdate:modelValue":r[2]||=e=>K.value=e,options:ie.value,label:n.$t(`engine.effort`),disable:e.loading,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``},null,8,[`modelValue`,`options`,`label`,`disable`])]),f(`div`,N,[o(w,{"model-value":J.value,options:$.value,label:n.$t(`agentPermissionMode.label`),disable:e.loading||U.value,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``,"onUpdate:modelValue":r[3]||=e=>q.value=e},null,8,[`model-value`,`options`,`label`,`disable`]),U.value?(i(),u(`div`,P,t(n.$t(`review.readOnlyForced`)),1)):c(``,!0)])]),o(g,{modelValue:V.value,"onUpdate:modelValue":r[4]||=e=>V.value=e,type:`textarea`,disable:e.loading,label:n.$t(`review.additionalInstructions`),placeholder:n.$t(`review.additionalInstructionsPlaceholder`),rows:4,outlined:``,dark:``,color:`primary`},null,8,[`modelValue`,`disable`,`label`,`placeholder`])]),_:1}),B.value?c(``,!0):(i(),s(_,{key:0,class:`q-pt-none`},{default:a(()=>[o(x,{modelValue:Z.value,"onUpdate:modelValue":r[5]||=e=>Z.value=e,disable:e.loading||X.value,label:n.$t(`review.newSession`),color:`primary`,dark:``},null,8,[`modelValue`,`disable`,`label`]),f(`div`,F,t(n.$t(X.value?`review.newSessionRequired`:`review.newSessionHint`)),1),Z.value?(i(),u(d,{key:0},[o(x,{modelValue:U.value,"onUpdate:modelValue":r[6]||=e=>U.value=e,disable:e.loading||!e.canReturnToSession,label:n.$t(`review.returnToSession`),color:`primary`,dark:``,class:`q-mt-md`},null,8,[`modelValue`,`disable`,`label`]),f(`div`,I,t(n.$t(e.canReturnToSession?`review.returnToSessionHint`:`review.returnUnavailable`)),1)],64)):c(``,!0)]),_:1})),o(h,{align:`right`,class:`q-pa-md`},{default:a(()=>[o(m,{flat:``,"no-caps":``,label:n.$t(`review.cancel`),color:`kobo-2`,disable:e.loading,onClick:ae},null,8,[`label`,`disable`]),o(m,{"no-caps":``,color:`primary`,label:n.$t(B.value?`autoLoop.finalReview.save`:`review.start`),loading:e.loading,disable:!e.workspace||e.loading,onClick:oe},null,8,[`label`,`loading`,`disable`])]),_:1})]),_:1})]),_:1},8,[`model-value`,`persistent`]))}}),[[`__scopeId`,`data-v-a4419350`]]),R={class:`final-review-settings`},z={class:`text-caption text-kobo-3`},B=T(p({__name:`AutoLoopFinalReviewSettings`,props:{modelValue:{},workspace:{},disabled:{type:Boolean},loading:{type:Boolean}},emits:[`update:modelValue`],setup(a,{emit:l}){let d=a,p=l,{t:h}=v(),g=n(!1),_=n(null);r(()=>d.modelValue,e=>{JSON.stringify(e)===JSON.stringify(_.value)&&(_.value=null)}),r(()=>d.workspace.id,()=>{g.value=!1,_.value=null});function y(e){d.disabled||d.loading||(e?g.value=!0:p(`update:modelValue`,null))}function b(e){!d.disabled&&!d.loading&&e.engine&&e.model&&e.reasoningEffort&&(_.value={engine:e.engine,model:e.model,reasoningEffort:e.reasoningEffort,additionalInstructions:e.additionalInstructions??``},p(`update:modelValue`,_.value),g.value=!1)}return(n,r)=>(i(),u(`div`,R,[o(x,{"model-value":!!a.modelValue,disable:a.disabled||a.loading,color:`primary`,label:e(h)(`autoLoop.finalReview.enabled`),"onUpdate:modelValue":y},null,8,[`model-value`,`disable`,`label`]),f(`p`,z,t(e(h)(`autoLoop.finalReview.hint`)),1),a.modelValue?(i(),s(m,{key:0,flat:``,dense:``,"no-caps":``,disable:a.disabled||a.loading,label:e(h)(`autoLoop.finalReview.configure`),onClick:r[0]||=e=>g.value=!0},null,8,[`disable`,`label`])):c(``,!0),o(L,{modelValue:g.value,"onUpdate:modelValue":r[1]||=e=>g.value=e,mode:`auto-loop`,loading:a.loading??!1,workspace:a.workspace,"scheduled-configuration":_.value??a.modelValue,"can-return-to-session":!0,onSubmit:b},null,8,[`modelValue`,`loading`,`workspace`,`scheduled-configuration`])]))}}),[[`__scopeId`,`data-v-b7f36f83`]]);export{L as n,B as t};
1
+ import{N as e,mt as t,v as n}from"./reactivity.esm-bundler-Dplx1ILy.js";import{J as r,L as i,Y as a,_ as o,d as s,f as c,l,p as u,r as d,u as f,y as p}from"./runtime-core.esm-bundler-BAUgNzMK.js";import{t as m}from"./QBtn-kfhHFy7Q.js";import{Nt as h,Pt as g,bn as _,en as v,f as y,j as b,l as x,rn as S,vn as C}from"./index-DLoUeovT.js";import{t as w}from"./QSelect-DOnv_ry0.js";import{a as T}from"./use-tours-C_5R1Y5D.js";import{i as E,t as D}from"./permissionModes-D-Nexnoo.js";import{t as O}from"./efforts-C-p9DzkL.js";function k(e,t){return e.engine!==t.engine||e.model!==t.model||e.reasoningEffort!==t.reasoningEffort||e.agentPermissionMode!==t.agentPermissionMode}var A={class:`text-h6`},j={class:`text-body2 text-kobo-2 q-mt-xs`},ee={class:`row q-col-gutter-sm q-mb-md`},te={class:`col-12 col-sm-6`},ne={class:`col-12 col-sm-6`},M={class:`col-12 col-sm-6`},N={class:`col-12 col-sm-6`},P={key:0,class:`text-caption text-kobo-3 q-mt-xs`},F={class:`text-caption text-kobo-3 q-mt-xs`},I={class:`text-caption text-kobo-3 q-mt-xs`},L=T(p({__name:`StartReviewDialog`,props:{modelValue:{type:Boolean},loading:{type:Boolean},workspace:{},canReturnToSession:{type:Boolean},currentSession:{},mode:{},scheduledConfiguration:{}},emits:[`update:modelValue`,`submit`],setup(e,{emit:p}){let T=e,L=p,{t:R}=v(),z=b(),B=l(()=>T.mode===`auto-loop`),V=n(``),H=n(!1),U=n(!1),W=n(`claude-code`),G=n(`auto`),K=n(`auto`),q=n(`bypass`),J=l(()=>B.value||U.value?`plan`:q.value),Y=l(()=>({engine:W.value,model:G.value,reasoningEffort:K.value,agentPermissionMode:J.value})),X=l(()=>{let e=T.currentSession;return B.value||U.value||!!T.workspace&&k(Y.value,T.workspace)||!!e?.engine&&e.engine!==W.value||G.value!==`auto`&&!!e?.model&&e.model!==G.value}),Z=l({get:()=>H.value||X.value,set:e=>{H.value=e}}),re=l(()=>[{value:`claude-code`,label:R(`workspacePage.engineClaude`)},{value:`codex`,label:R(`workspacePage.engineCodex`)}]),Q=l(()=>{let e=(E[W.value]??[]).map(e=>({value:e.value,label:R(e.i18nLabelKey)}));T.workspace?.engine===W.value&&!e.some(e=>e.value===T.workspace?.model)&&e.push({value:T.workspace.model,label:T.workspace.model});let t=T.scheduledConfiguration;return t?.engine===W.value&&!e.some(e=>e.value===t.model)&&e.push({value:t.model,label:t.model}),e}),ie=l(()=>(O[W.value]??[]).map(e=>({value:e.value,label:R(e.i18nLabelKey)}))),$=l(()=>(D[W.value]??[]).map(e=>({value:e,label:R(`agentPermissionMode.${e}`)})));r(W,()=>{let e=T.workspace,t=z.global.defaultModelByEngine[W.value];G.value=e?.engine===W.value?e.model:Q.value.some(e=>e.value===t)?t:`auto`,K.value=e?.engine===W.value?e.reasoningEffort:`auto`,$.value.some(e=>e.value===q.value)||(q.value=`plan`)},{flush:`sync`}),r([()=>T.modelValue,()=>T.workspace?.id],([e])=>{if(!e)return;let t=B.value?T.scheduledConfiguration:null;V.value=t?.additionalInstructions??``,H.value=!1,U.value=B.value,T.workspace&&(W.value=T.workspace.engine,G.value=T.workspace.model,K.value=T.workspace.reasoningEffort,q.value=T.workspace.agentPermissionMode),t&&(W.value=t.engine,G.value=t.model,K.value=t.reasoningEffort)},{immediate:!0}),r(()=>T.canReturnToSession,e=>{!e&&!B.value&&(U.value=!1)});function ae(){T.loading||L(`update:modelValue`,!1)}function oe(){!T.loading&&T.workspace&&L(`submit`,{...Y.value,additionalInstructions:V.value,newSession:Z.value,returnToSession:B.value||U.value&&T.canReturnToSession})}return(n,r)=>(i(),s(S,{"model-value":e.modelValue,persistent:e.loading,"onUpdate:modelValue":r[7]||=e=>L(`update:modelValue`,e)},{default:a(()=>[o(C,{class:`review-card text-kobo-1`},{default:a(()=>[o(_,null,{default:a(()=>[f(`div`,A,t(n.$t(B.value?`autoLoop.finalReview.title`:`review.title`)),1),f(`div`,j,t(n.$t(B.value?`autoLoop.finalReview.description`:`review.subtitle`)),1)]),_:1}),o(y,{dark:``}),o(_,{class:`q-pt-md`},{default:a(()=>[f(`div`,ee,[f(`div`,te,[o(w,{modelValue:W.value,"onUpdate:modelValue":r[0]||=e=>W.value=e,options:re.value,label:n.$t(`engine.select`),disable:e.loading,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``},null,8,[`modelValue`,`options`,`label`,`disable`])]),f(`div`,ne,[o(w,{modelValue:G.value,"onUpdate:modelValue":r[1]||=e=>G.value=e,options:Q.value,label:n.$t(`engine.model`),disable:e.loading,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``},null,8,[`modelValue`,`options`,`label`,`disable`])]),f(`div`,M,[o(w,{modelValue:K.value,"onUpdate:modelValue":r[2]||=e=>K.value=e,options:ie.value,label:n.$t(`engine.effort`),disable:e.loading,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``},null,8,[`modelValue`,`options`,`label`,`disable`])]),f(`div`,N,[o(w,{"model-value":J.value,options:$.value,label:n.$t(`agentPermissionMode.label`),disable:e.loading||U.value,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``,"onUpdate:modelValue":r[3]||=e=>q.value=e},null,8,[`model-value`,`options`,`label`,`disable`]),U.value?(i(),u(`div`,P,t(n.$t(`review.readOnlyForced`)),1)):c(``,!0)])]),o(g,{modelValue:V.value,"onUpdate:modelValue":r[4]||=e=>V.value=e,type:`textarea`,disable:e.loading,label:n.$t(`review.additionalInstructions`),placeholder:n.$t(`review.additionalInstructionsPlaceholder`),rows:4,outlined:``,dark:``,color:`primary`},null,8,[`modelValue`,`disable`,`label`,`placeholder`])]),_:1}),B.value?c(``,!0):(i(),s(_,{key:0,class:`q-pt-none`},{default:a(()=>[o(x,{modelValue:Z.value,"onUpdate:modelValue":r[5]||=e=>Z.value=e,disable:e.loading||X.value,label:n.$t(`review.newSession`),color:`primary`,dark:``},null,8,[`modelValue`,`disable`,`label`]),f(`div`,F,t(n.$t(X.value?`review.newSessionRequired`:`review.newSessionHint`)),1),Z.value?(i(),u(d,{key:0},[o(x,{modelValue:U.value,"onUpdate:modelValue":r[6]||=e=>U.value=e,disable:e.loading||!e.canReturnToSession,label:n.$t(`review.returnToSession`),color:`primary`,dark:``,class:`q-mt-md`},null,8,[`modelValue`,`disable`,`label`]),f(`div`,I,t(n.$t(e.canReturnToSession?`review.returnToSessionHint`:`review.returnUnavailable`)),1)],64)):c(``,!0)]),_:1})),o(h,{align:`right`,class:`q-pa-md`},{default:a(()=>[o(m,{flat:``,"no-caps":``,label:n.$t(`review.cancel`),color:`kobo-2`,disable:e.loading,onClick:ae},null,8,[`label`,`disable`]),o(m,{"no-caps":``,color:`primary`,label:n.$t(B.value?`autoLoop.finalReview.save`:`review.start`),loading:e.loading,disable:!e.workspace||e.loading,onClick:oe},null,8,[`label`,`loading`,`disable`])]),_:1})]),_:1})]),_:1},8,[`model-value`,`persistent`]))}}),[[`__scopeId`,`data-v-a4419350`]]),R={class:`final-review-settings`},z={class:`text-caption text-kobo-3`},B=T(p({__name:`AutoLoopFinalReviewSettings`,props:{modelValue:{},workspace:{},disabled:{type:Boolean},loading:{type:Boolean}},emits:[`update:modelValue`],setup(a,{emit:l}){let d=a,p=l,{t:h}=v(),g=n(!1),_=n(null);r(()=>d.modelValue,e=>{JSON.stringify(e)===JSON.stringify(_.value)&&(_.value=null)}),r(()=>d.workspace.id,()=>{g.value=!1,_.value=null});function y(e){d.disabled||d.loading||(e?g.value=!0:p(`update:modelValue`,null))}function b(e){!d.disabled&&!d.loading&&e.engine&&e.model&&e.reasoningEffort&&(_.value={engine:e.engine,model:e.model,reasoningEffort:e.reasoningEffort,additionalInstructions:e.additionalInstructions??``},p(`update:modelValue`,_.value),g.value=!1)}return(n,r)=>(i(),u(`div`,R,[o(x,{"model-value":!!a.modelValue,disable:a.disabled||a.loading,color:`primary`,label:e(h)(`autoLoop.finalReview.enabled`),"onUpdate:modelValue":y},null,8,[`model-value`,`disable`,`label`]),f(`p`,z,t(e(h)(`autoLoop.finalReview.hint`)),1),a.modelValue?(i(),s(m,{key:0,flat:``,dense:``,"no-caps":``,disable:a.disabled||a.loading,label:e(h)(`autoLoop.finalReview.configure`),onClick:r[0]||=e=>g.value=!0},null,8,[`disable`,`label`])):c(``,!0),o(L,{modelValue:g.value,"onUpdate:modelValue":r[1]||=e=>g.value=e,mode:`auto-loop`,loading:a.loading??!1,workspace:a.workspace,"scheduled-configuration":_.value??a.modelValue,"can-return-to-session":!0,onSubmit:b},null,8,[`modelValue`,`loading`,`workspace`,`scheduled-configuration`])]))}}),[[`__scopeId`,`data-v-b7f36f83`]]);export{L as n,B as t};
@@ -1 +1 @@
1
- import{M as e,pt as t,v as n}from"./reactivity.esm-bundler-DY1JkAEA.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-Bqg71Vll.js";import{t as m}from"./QBtn-BUSdPaf4.js";import{Gt as h,Jt as g,a as _,bn as v,vn as y}from"./index-CpWBGKdM.js";import{a as b,i as x,n as S}from"./use-tours-BWkHp34X.js";import{n as C}from"./render-chat-markdown-CafzCcmu.js";import{t as w}from"./QChip-Be16M4Ig.js";import{t as T}from"./QPage-CqkGHokx.js";import{t as E}from"./DrawerToggleButton-DiOJm5he.js";import{t as D}from"./TourReplayButton-kAnEMcy2.js";var O={class:`row items-center q-mb-md`},k={class:`text-h6 q-ml-sm`},A={key:0,class:`text-kobo-3 text-center q-pa-lg`},j={key:1,class:`text-negative text-center q-pa-lg`},M={key:2,class:`text-kobo-3 text-center q-pa-lg`},N={key:3,class:`column q-gutter-md`,"data-tour":`changelog-list`},P={key:0,class:`text-caption text-kobo-3`},F={class:`row items-center q-mb-sm`},I={class:`text-subtitle1 text-kobo-2`,style:{"font-family":`var(--kobo-font-mono, monospace)`}},L=[`innerHTML`],R=b(f({__name:`ChangelogPage`,setup(f){let b=_(),{scheduleAutoRun:R}=S(),z=n([]),B=n(``),V=n(!1),H=n(null);function U(e){return C(e)}async function W(){V.value=!0,H.value=null;try{let e=await h(`/api/changelog`);if(!e.ok)throw await g(e);let t=await e.json();B.value=t.currentVersion??``,z.value=t.versions??[]}catch(e){H.value=e instanceof Error?e.message:String(e)}finally{V.value=!1}}return i(()=>{W(),R(`changelog`)}),(n,i)=>(r(),s(T,{class:`q-pa-md`,style:{"max-width":`900px`,margin:`0 auto`}},{default:a(()=>[d(`div`,O,[o(E,{class:`q-mr-xs`}),o(m,{flat:``,dense:``,round:``,icon:`arrow_back`,onClick:i[0]||=t=>e(b).back()}),d(`div`,k,t(n.$t(`changelog.title`)),1),o(x),o(m,{flat:``,dense:``,icon:`refresh`,loading:V.value,label:n.$t(`common.refresh`),onClick:W},null,8,[`loading`,`label`]),o(D,{"tour-id":`changelog`,class:`q-ml-xs`})]),V.value&&z.value.length===0?(r(),l(`div`,A,t(n.$t(`common.loading`)),1)):H.value?(r(),l(`div`,j,t(H.value),1)):z.value.length===0?(r(),l(`div`,M,t(n.$t(`changelog.empty`)),1)):(r(),l(`div`,N,[B.value?(r(),l(`div`,P,t(n.$t(`changelog.currentVersion`,{version:B.value})),1)):c(``,!0),(r(!0),l(u,null,p(z.value,e=>(r(),s(y,{key:e.version,dark:``,flat:``,bordered:``},{default:a(()=>[o(v,null,{default:a(()=>[d(`div`,F,[d(`div`,I,` v`+t(e.version),1),e.version===B.value?(r(),s(w,{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:U(e.notes)},null,8,L)]),_:2},1024)]),_:2},1024))),128))]))]),_:1}))}}),[[`__scopeId`,`data-v-4032778f`]]);export{R as default};
1
+ import{N as e,mt as t,v as n}from"./reactivity.esm-bundler-Dplx1ILy.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-BAUgNzMK.js";import{t as m}from"./QBtn-kfhHFy7Q.js";import{Gt as h,Jt as g,a as _,bn as v,vn as y}from"./index-DLoUeovT.js";import{a as b,i as x,n as S}from"./use-tours-C_5R1Y5D.js";import{n as C}from"./render-chat-markdown-C9ihAYBt.js";import{t as w}from"./QChip-DvhtPv_L.js";import{t as T}from"./QPage-DIy_mRoT.js";import{t as E}from"./DrawerToggleButton-DfzS_CD8.js";import{t as D}from"./TourReplayButton-D4h1QR6C.js";var O={class:`row items-center q-mb-md`},k={class:`text-h6 q-ml-sm`},A={key:0,class:`text-kobo-3 text-center q-pa-lg`},j={key:1,class:`text-negative text-center q-pa-lg`},M={key:2,class:`text-kobo-3 text-center q-pa-lg`},N={key:3,class:`column q-gutter-md`,"data-tour":`changelog-list`},P={key:0,class:`text-caption text-kobo-3`},F={class:`row items-center q-mb-sm`},I={class:`text-subtitle1 text-kobo-2`,style:{"font-family":`var(--kobo-font-mono, monospace)`}},L=[`innerHTML`],R=b(f({__name:`ChangelogPage`,setup(f){let b=_(),{scheduleAutoRun:R}=S(),z=n([]),B=n(``),V=n(!1),H=n(null);function U(e){return C(e)}async function W(){V.value=!0,H.value=null;try{let e=await h(`/api/changelog`);if(!e.ok)throw await g(e);let t=await e.json();B.value=t.currentVersion??``,z.value=t.versions??[]}catch(e){H.value=e instanceof Error?e.message:String(e)}finally{V.value=!1}}return i(()=>{W(),R(`changelog`)}),(n,i)=>(r(),s(T,{class:`q-pa-md`,style:{"max-width":`900px`,margin:`0 auto`}},{default:a(()=>[d(`div`,O,[o(E,{class:`q-mr-xs`}),o(m,{flat:``,dense:``,round:``,icon:`arrow_back`,onClick:i[0]||=t=>e(b).back()}),d(`div`,k,t(n.$t(`changelog.title`)),1),o(x),o(m,{flat:``,dense:``,icon:`refresh`,loading:V.value,label:n.$t(`common.refresh`),onClick:W},null,8,[`loading`,`label`]),o(D,{"tour-id":`changelog`,class:`q-ml-xs`})]),V.value&&z.value.length===0?(r(),l(`div`,A,t(n.$t(`common.loading`)),1)):H.value?(r(),l(`div`,j,t(H.value),1)):z.value.length===0?(r(),l(`div`,M,t(n.$t(`changelog.empty`)),1)):(r(),l(`div`,N,[B.value?(r(),l(`div`,P,t(n.$t(`changelog.currentVersion`,{version:B.value})),1)):c(``,!0),(r(!0),l(u,null,p(z.value,e=>(r(),s(y,{key:e.version,dark:``,flat:``,bordered:``},{default:a(()=>[o(v,null,{default:a(()=>[d(`div`,F,[d(`div`,I,` v`+t(e.version),1),e.version===B.value?(r(),s(w,{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:U(e.notes)},null,8,L)]),_:2},1024)]),_:2},1024))),128))]))]),_:1}))}}),[[`__scopeId`,`data-v-4032778f`]]);export{R as default};
@@ -1 +1 @@
1
- import{B as e,E as t}from"./dom-BtYTvLeN.js";import{m as n,p as r}from"./detached-fullscreen-Du3TcYdX.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(e){t(e,13)&&a(e)}var s=e({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{B as e,E as t}from"./dom-CRPVbmiy.js";import{m as n,p as r}from"./detached-fullscreen-CHqMxB-8.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(e){t(e,13)&&a(e)}var s=e({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{lt as e,pt as t,v as n}from"./reactivity.esm-bundler-DY1JkAEA.js";import{J as r,L as i,P as ee,Y as a,_ as o,d as te,f as s,g as c,l,p as u,r as ne,u as d,y as f,z as re}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{t as p}from"./QBtn-BUSdPaf4.js";import{Gt as m,a as h,at as ie,en as ae}from"./index-CpWBGKdM.js";import{t as oe}from"./QMarkupTable-UhP7fVUp.js";import{a as g,i as _}from"./use-tours-BWkHp34X.js";var v=[`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 y(e){if(e==null)return``;let t=String(e);return/[",\r\n]/.test(t)?`"${t.replace(/"/g,`""`)}"`:t}function b(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(y).join(`,`)});return`${[v.join(`,`),...t].join(`\r
2
- `)}`}var x={key:0,class:`comparison-panel q-pa-md`},S={class:`row items-center q-mb-sm`},C={class:`text-subtitle2`},w={class:`text-caption text-kobo-3 q-mb-sm`},T={class:`text-left`},E={class:`text-left`},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-right`},L={class:`text-right`},R={class:`text-caption text-kobo-3 comparison-mono`},z={key:0,class:`text-caption text-kobo-3`},B={class:`text-right comparison-mono`},V={class:`text-right`},H={class:`text-right`},U={class:`text-right`},se={key:0,class:`comparison-mono`},W={class:`text-kobo-success`},G={class:`text-kobo-danger q-ml-xs`},K={key:1,class:`text-kobo-3`},ce={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`},q=g(f({__name:`ComparisonPanel`,props:{workspaceId:{}},setup(f){let g=f;function v(e){return e<1e3?String(e):e<1e6?`${(e/1e3).toFixed(+(e<1e4))}k`:`${(e/1e6).toFixed(1)}M`}function y(e){if(e<=0)return`-`;let t=Math.round(e/1e3);if(t<60)return J(`reliability.durationSeconds`,{s:t});let n=Math.floor(t/60);return n<60?J(`reliability.durationMinutes`,{m:n,s:t%60}):J(`reliability.durationHours`,{h:Math.floor(n/60),m:n%60})}let q=h(),ye=ie(),{t:J}=ae(),Y=n([]),X=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`},Z=n({});function xe(e){return Z.value[e]??e}async function Se(){try{let e=await m(`/api/engines`);if(!e.ok)return;let t=await e.json();Z.value=Object.fromEntries(t.map(e=>[e.id,e.displayName]))}catch{}}function Ce(e){let t=be[e];return t?J(t):e}let we=l(()=>g.workspaceId);function Q(e){return e.workspace.id===we.value}function Te(e){ye.selectWorkspace(e),q.push({name:`workspace`,params:{id:e}})}function Ee(){let e=b(Y.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-${Y.value[0]?.workspace.comparisonId??`comparison`}.csv`,r.click(),URL.revokeObjectURL(n)}async function $(){X.value=!0;try{let e=await m(`/api/workspaces/${g.workspaceId}/comparison`);if(!e.ok){Y.value=[];return}let t=await e.json();Y.value=t.members??[]}catch{Y.value=[]}finally{X.value=!1}}return ee(()=>{Se(),$()}),r(()=>g.workspaceId,$),(n,r)=>Y.value.length>0?(i(),u(`div`,x,[d(`div`,S,[d(`div`,C,t(n.$t(`comparison.title`)),1),o(_),o(p,{flat:``,dense:``,round:``,size:`sm`,icon:`download`,title:n.$t(`comparison.exportCsv`),onClick:Ee},null,8,[`title`]),o(p,{flat:``,dense:``,round:``,size:`sm`,icon:`refresh`,loading:X.value,onClick:$},null,8,[`loading`])]),d(`div`,w,t(n.$t(`comparison.hint`)),1),o(oe,{flat:``,dense:``,dark:``,class:`comparison-table`},{default:a(()=>[d(`thead`,null,[d(`tr`,null,[d(`th`,T,t(n.$t(`comparison.engine`)),1),d(`th`,E,t(n.$t(`comparison.status`)),1),d(`th`,D,t(n.$t(`comparison.tasks`)),1),d(`th`,O,t(n.$t(`comparison.commits`)),1),d(`th`,k,t(n.$t(`comparison.files`)),1),d(`th`,A,t(n.$t(`comparison.diff`)),1),d(`th`,j,t(n.$t(`comparison.messages`)),1),d(`th`,M,t(n.$t(`comparison.questions`)),1),d(`th`,N,t(n.$t(`comparison.tools`)),1),d(`th`,P,t(n.$t(`comparison.errors`)),1),d(`th`,F,t(n.$t(`comparison.tokens`)),1),d(`th`,I,t(n.$t(`comparison.sessions`)),1),d(`th`,L,t(n.$t(`comparison.duration`)),1),r[0]||=d(`th`,null,null,-1)])]),d(`tbody`,null,[(i(!0),u(ne,null,re(Y.value,r=>(i(),u(`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`,R,t(r.workspace.model),1)]),d(`td`,null,[c(t(Ce(r.workspace.status))+` `,1),r.workspace.archivedAt?(i(),u(`span`,z,` · `+t(n.$t(`comparison.archived`)),1)):s(``,!0)]),d(`td`,B,t(r.tasks.done)+`/`+t(r.tasks.total),1),d(`td`,V,t(r.gitStats?.commitCount??`-`),1),d(`td`,H,t(r.gitStats?.filesChanged??`-`),1),d(`td`,U,[r.gitStats?(i(),u(`span`,se,[d(`span`,W,`+`+t(r.gitStats.insertions),1),d(`span`,G,`-`+t(r.gitStats.deletions),1)])):(i(),u(`span`,K,`-`))]),d(`td`,ce,[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(v(r.activity.inputTokens))+` / `+t(v(r.activity.outputTokens)),9,pe)]),d(`td`,me,t(r.activity.sessions),1),d(`td`,he,t(y(r.activity.durationMs)),1),d(`td`,ge,[Q(r)?(i(),u(`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=>Te(r.workspace.id)},null,8,[`label`,`onClick`]))])],2))),128))])]),_:1}),Y.value.length<2?(i(),u(`div`,ve,t(n.$t(`comparison.incomplete`)),1)):s(``,!0)])):s(``,!0)}}),[[`__scopeId`,`data-v-bda71e6d`]]);export{q as default};
1
+ import{mt as e,ut as t,v as n}from"./reactivity.esm-bundler-Dplx1ILy.js";import{J as r,L as i,P as ee,Y as a,_ as o,d as te,f as s,g as c,l,p as u,r as ne,u as d,y as f,z as re}from"./runtime-core.esm-bundler-BAUgNzMK.js";import{t as p}from"./QBtn-kfhHFy7Q.js";import{Gt as m,a as h,at as ie,en as ae}from"./index-DLoUeovT.js";import{t as oe}from"./QMarkupTable-B4LLAly-.js";import{a as g,i as _}from"./use-tours-C_5R1Y5D.js";var v=[`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 y(e){if(e==null)return``;let t=String(e);return/[",\r\n]/.test(t)?`"${t.replace(/"/g,`""`)}"`:t}function b(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(y).join(`,`)});return`${[v.join(`,`),...t].join(`\r
2
+ `)}`}var x={key:0,class:`comparison-panel q-pa-md`},S={class:`row items-center q-mb-sm`},C={class:`text-subtitle2`},w={class:`text-caption text-kobo-3 q-mb-sm`},T={class:`text-left`},E={class:`text-left`},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-right`},L={class:`text-right`},R={class:`text-caption text-kobo-3 comparison-mono`},z={key:0,class:`text-caption text-kobo-3`},B={class:`text-right comparison-mono`},V={class:`text-right`},H={class:`text-right`},U={class:`text-right`},se={key:0,class:`comparison-mono`},W={class:`text-kobo-success`},G={class:`text-kobo-danger q-ml-xs`},K={key:1,class:`text-kobo-3`},ce={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`},q=g(f({__name:`ComparisonPanel`,props:{workspaceId:{}},setup(f){let g=f;function v(e){return e<1e3?String(e):e<1e6?`${(e/1e3).toFixed(+(e<1e4))}k`:`${(e/1e6).toFixed(1)}M`}function y(e){if(e<=0)return`-`;let t=Math.round(e/1e3);if(t<60)return J(`reliability.durationSeconds`,{s:t});let n=Math.floor(t/60);return n<60?J(`reliability.durationMinutes`,{m:n,s:t%60}):J(`reliability.durationHours`,{h:Math.floor(n/60),m:n%60})}let q=h(),ye=ie(),{t:J}=ae(),Y=n([]),X=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`},Z=n({});function xe(e){return Z.value[e]??e}async function Se(){try{let e=await m(`/api/engines`);if(!e.ok)return;let t=await e.json();Z.value=Object.fromEntries(t.map(e=>[e.id,e.displayName]))}catch{}}function Ce(e){let t=be[e];return t?J(t):e}let we=l(()=>g.workspaceId);function Q(e){return e.workspace.id===we.value}function Te(e){ye.selectWorkspace(e),q.push({name:`workspace`,params:{id:e}})}function Ee(){let e=b(Y.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-${Y.value[0]?.workspace.comparisonId??`comparison`}.csv`,r.click(),URL.revokeObjectURL(n)}async function $(){X.value=!0;try{let e=await m(`/api/workspaces/${g.workspaceId}/comparison`);if(!e.ok){Y.value=[];return}let t=await e.json();Y.value=t.members??[]}catch{Y.value=[]}finally{X.value=!1}}return ee(()=>{Se(),$()}),r(()=>g.workspaceId,$),(n,r)=>Y.value.length>0?(i(),u(`div`,x,[d(`div`,S,[d(`div`,C,e(n.$t(`comparison.title`)),1),o(_),o(p,{flat:``,dense:``,round:``,size:`sm`,icon:`download`,title:n.$t(`comparison.exportCsv`),onClick:Ee},null,8,[`title`]),o(p,{flat:``,dense:``,round:``,size:`sm`,icon:`refresh`,loading:X.value,onClick:$},null,8,[`loading`])]),d(`div`,w,e(n.$t(`comparison.hint`)),1),o(oe,{flat:``,dense:``,dark:``,class:`comparison-table`},{default:a(()=>[d(`thead`,null,[d(`tr`,null,[d(`th`,T,e(n.$t(`comparison.engine`)),1),d(`th`,E,e(n.$t(`comparison.status`)),1),d(`th`,D,e(n.$t(`comparison.tasks`)),1),d(`th`,O,e(n.$t(`comparison.commits`)),1),d(`th`,k,e(n.$t(`comparison.files`)),1),d(`th`,A,e(n.$t(`comparison.diff`)),1),d(`th`,j,e(n.$t(`comparison.messages`)),1),d(`th`,M,e(n.$t(`comparison.questions`)),1),d(`th`,N,e(n.$t(`comparison.tools`)),1),d(`th`,P,e(n.$t(`comparison.errors`)),1),d(`th`,F,e(n.$t(`comparison.tokens`)),1),d(`th`,I,e(n.$t(`comparison.sessions`)),1),d(`th`,L,e(n.$t(`comparison.duration`)),1),r[0]||=d(`th`,null,null,-1)])]),d(`tbody`,null,[(i(!0),u(ne,null,re(Y.value,r=>(i(),u(`tr`,{key:r.workspace.id,class:t({"comparison-current":Q(r)})},[d(`td`,null,[d(`div`,null,e(xe(r.workspace.engine)),1),d(`div`,R,e(r.workspace.model),1)]),d(`td`,null,[c(e(Ce(r.workspace.status))+` `,1),r.workspace.archivedAt?(i(),u(`span`,z,` · `+e(n.$t(`comparison.archived`)),1)):s(``,!0)]),d(`td`,B,e(r.tasks.done)+`/`+e(r.tasks.total),1),d(`td`,V,e(r.gitStats?.commitCount??`-`),1),d(`td`,H,e(r.gitStats?.filesChanged??`-`),1),d(`td`,U,[r.gitStats?(i(),u(`span`,se,[d(`span`,W,`+`+e(r.gitStats.insertions),1),d(`span`,G,`-`+e(r.gitStats.deletions),1)])):(i(),u(`span`,K,`-`))]),d(`td`,ce,[d(`span`,{title:n.$t(`comparison.messagesTitle`)},e(r.activity.agentMessages)+` / `+e(r.activity.userMessages),9,le)]),d(`td`,ue,e(r.activity.questions),1),d(`td`,de,e(r.activity.toolCalls),1),d(`td`,{class:t([`text-right`,r.activity.errors>0?`text-kobo-danger`:``])},e(r.activity.errors),3),d(`td`,fe,[d(`span`,{title:n.$t(`comparison.tokensTitle`)},e(v(r.activity.inputTokens))+` / `+e(v(r.activity.outputTokens)),9,pe)]),d(`td`,me,e(r.activity.sessions),1),d(`td`,he,e(y(r.activity.durationMs)),1),d(`td`,ge,[Q(r)?(i(),u(`span`,_e,e(n.$t(`comparison.current`)),1)):(i(),te(p,{key:0,flat:``,dense:``,"no-caps":``,size:`sm`,label:n.$t(`comparison.open`),onClick:e=>Te(r.workspace.id)},null,8,[`label`,`onClick`]))])],2))),128))])]),_:1}),Y.value.length<2?(i(),u(`div`,ve,e(n.$t(`comparison.incomplete`)),1)):s(``,!0)])):s(``,!0)}}),[[`__scopeId`,`data-v-bda71e6d`]]);export{q as default};