@loicngr/kobo 1.11.30 → 1.11.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +6 -1
- package/CHANGELOG.md +9 -0
- package/dist/server/routes/workspaces.js +46 -10
- package/dist/server/services/forge/bitbucket/provider.js +2 -1
- package/dist/server/services/forge/github/provider.js +3 -2
- package/dist/server/services/forge/gitlab/provider.js +2 -1
- package/dist/server/services/forge/types.js +10 -0
- package/dist/server/services/git-stats-service.js +2 -0
- package/dist/server/utils/git-ops.js +38 -4
- package/package.json +1 -1
- package/src/client/dist/pwa/assets/{ActivityFeed-C6XSxdJ0.css → ActivityFeed-Bakgvay6.css} +1 -1
- package/src/client/dist/pwa/assets/ActivityFeed-C7tG4Cgq.js +8 -0
- package/src/client/dist/pwa/assets/ChangelogPage-DKJkFiU_.css +1 -0
- package/src/client/dist/pwa/assets/ChangelogPage-FYve4efm.js +1 -0
- package/src/client/dist/pwa/assets/ClosePopup-DLm_uRNv.js +1 -0
- package/src/client/dist/pwa/assets/ComparisonPanel-DRzYHcWf.js +2 -0
- package/src/client/dist/pwa/assets/CreatePage-CT10FMyq.js +2 -0
- package/src/client/dist/pwa/assets/CreatePage-DxOyY65u.css +1 -0
- package/src/client/dist/pwa/assets/DashboardPage-CT3XzDaz.js +1 -0
- package/src/client/dist/pwa/assets/DashboardPage-DsWn5cWl.css +1 -0
- package/src/client/dist/pwa/assets/DiffViewer-CIY7UOt6.js +8 -0
- package/src/client/dist/pwa/assets/DocumentsPanel-D2IlwigV.js +1 -0
- package/src/client/dist/pwa/assets/DrawerToggleButton-0fKZjElk.js +1 -0
- package/src/client/dist/pwa/assets/{GitPanel-DVs5BCU-.css → GitPanel-De5_E4NA.css} +1 -1
- package/src/client/dist/pwa/assets/GitPanel-DjG7-AsO.js +3 -0
- package/src/client/dist/pwa/assets/HealthPage-BJKRSg5I.js +1 -0
- package/src/client/dist/pwa/assets/HealthPage-CFZ-tdKK.css +1 -0
- package/src/client/dist/pwa/assets/MainLayout-BSHKEpzs.js +2 -0
- package/src/client/dist/pwa/assets/{MainLayout-DxYQV-Ni.css → MainLayout-BUTz2ks4.css} +1 -1
- package/src/client/dist/pwa/assets/QBadge-CWEaKfKi.js +1 -0
- package/src/client/dist/pwa/assets/QBanner-DRiFK0GP.js +1 -0
- package/src/client/dist/pwa/assets/QBtn-DqZryKOh.js +1 -0
- package/src/client/dist/pwa/assets/QBtnDropdown-Bqa7KhX7.js +1 -0
- package/src/client/dist/pwa/assets/QBtnGroup-BY6XqeTJ.js +1 -0
- package/src/client/dist/pwa/assets/QBtnToggle-CCgwqSgg.js +1 -0
- package/src/client/dist/pwa/assets/QChip-CJ6WmvGE.js +1 -0
- package/src/client/dist/pwa/assets/QDrawer-DinZbnyn.js +1 -0
- package/src/client/dist/pwa/assets/QItemSection-CjrpcdN_.js +1 -0
- package/src/client/dist/pwa/assets/QMarkupTable-MxPL53nz.js +1 -0
- package/src/client/dist/pwa/assets/QSpinnerDots-6v3Yl0T6.js +1 -0
- package/src/client/dist/pwa/assets/SchedulePanel-BDmDDRMX.js +1 -0
- package/src/client/dist/pwa/assets/SearchPage-BdisvUwr.js +1 -0
- package/src/client/dist/pwa/assets/SearchPage-CVgRa025.css +1 -0
- package/src/client/dist/pwa/assets/{SettingsPage-DHFMKY_1.css → SettingsPage-CDA54yPx.css} +1 -1
- package/src/client/dist/pwa/assets/SettingsPage-DCJgxm6J.js +9 -0
- package/src/client/dist/pwa/assets/TerminalPanel-DBnSOJ3B.js +16 -0
- package/src/client/dist/pwa/assets/TouchPan-D77wzGyc.js +1 -0
- package/src/client/dist/pwa/assets/TourReplayButton-DU2PItj-.js +1 -0
- package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-CRVNJtmB.js +1 -0
- package/src/client/dist/pwa/assets/{WorkspacePage-3rwxkeew.css → WorkspacePage-D3-AEaPN.css} +1 -1
- package/src/client/dist/pwa/assets/WorkspacePage-Dv3ED-Bt.js +4 -0
- package/src/client/dist/pwa/assets/{browser-Bg25_sDh.js → browser-sSy6JmeQ.js} +2 -2
- package/src/client/dist/pwa/assets/build-path-tree-B2-SsE87.js +1 -0
- package/src/client/dist/pwa/assets/de-D_OhjWJx.js +17 -0
- package/src/client/dist/pwa/assets/documents-D4BcPyOF.js +1 -0
- package/src/client/dist/pwa/assets/editor.api-NH9tSUby.js +413 -0
- package/src/client/dist/pwa/assets/editor.worker-CwQAd_xr.js +30 -0
- package/src/client/dist/pwa/assets/efforts-BdCfujEx.js +9 -0
- package/src/client/dist/pwa/assets/engineFeatures-6ikmzzfp.js +1 -0
- package/src/client/dist/pwa/assets/es-kxJ0xgkc.js +17 -0
- package/src/client/dist/pwa/assets/expand-template-3E9x3FGS.js +1 -0
- package/src/client/dist/pwa/assets/{format-DSh3Ghaw.js → format-CR20Lbwg.js} +30 -30
- package/src/client/dist/pwa/assets/formatters-TuKWWdWq.js +1 -0
- package/src/client/dist/pwa/assets/fr-BgQGh90C.js +17 -0
- package/src/client/dist/pwa/assets/{freemarker2-BdMCo-ui.js → freemarker2-F7dLhXbU.js} +1 -1
- package/src/client/dist/pwa/assets/{handlebars-CVUpmZRG.js → handlebars-hXFhj5eh.js} +1 -1
- package/src/client/dist/pwa/assets/{html-B9nx87id.js → html-7nsVC4pO.js} +1 -1
- package/src/client/dist/pwa/assets/{i18n-B_ietr0X.js → i18n-Djnp5xDA.js} +1 -1
- package/src/client/dist/pwa/assets/index-CUoUy6tH.css +1 -0
- package/src/client/dist/pwa/assets/index-DztjpQfb.js +20 -0
- package/src/client/dist/pwa/assets/it-BmzSIMv5.js +17 -0
- package/src/client/dist/pwa/assets/{javascript-B0F3ZRYP.js → javascript-59rTAWws.js} +1 -1
- package/src/client/dist/pwa/assets/{liquid-C2jkK9Te.js → liquid-BP6Awnwy.js} +1 -1
- package/src/client/dist/pwa/assets/{mdx-B9CyGsGZ.js → mdx-CiCpqnQ4.js} +1 -1
- package/src/client/dist/pwa/assets/monaco-contributions-DzI5nDgU.js +51 -0
- package/src/client/dist/pwa/assets/monaco.contribution-9uLUIE5c.js +2 -0
- package/src/client/dist/pwa/assets/{network-auth-CXNehcyv.js → network-auth--GlWvRqv.js} +1 -1
- package/src/client/dist/pwa/assets/{notify-theme-DzIPRvEu.js → notify-theme-DQ_bPMUo.js} +1 -1
- package/src/client/dist/pwa/assets/pending-diff-open-CK20L_pt.js +1 -0
- package/src/client/dist/pwa/assets/permissionModes-DORv0Hwo.js +36 -0
- package/src/client/dist/pwa/assets/pinia-jcytgarH.js +1 -0
- package/src/client/dist/pwa/assets/private.use-form-DVqJLg-9.js +1 -0
- package/src/client/dist/pwa/assets/{project-color-D8UVi4-G.js → project-color-DrojOIC6.js} +1 -1
- package/src/client/dist/pwa/assets/{python-D6494OxU.js → python-BfVlMXCp.js} +1 -1
- package/src/client/dist/pwa/assets/{razor-uuwEcrBe.js → razor-CxyOPnW7.js} +1 -1
- package/src/client/dist/pwa/assets/reactivity.esm-bundler-DEJj9cFv.js +1 -0
- package/src/client/dist/pwa/assets/render-chat-markdown-nZGk_TRQ.js +67 -0
- package/src/client/dist/pwa/assets/runtime-core.esm-bundler-CS0xkoG_.js +1 -0
- package/src/client/dist/pwa/assets/{typescript-umL7JrOg.js → typescript-Bke62OsW.js} +1 -1
- package/src/client/dist/pwa/assets/use-checkbox-DDRAnhSJ.js +1 -0
- package/src/client/dist/pwa/assets/use-is-mobile-ClPMtqZc.js +1 -0
- package/src/client/dist/pwa/assets/use-tours-BEdbVcQS.js +2 -0
- package/src/client/dist/pwa/assets/{workspace-templates-CkKJmfTo.js → workspace-templates-1zUtbH31.js} +1 -1
- package/src/client/dist/pwa/assets/{xml-Nu9IP_9Z.js → xml-Cg47p-KM.js} +1 -1
- package/src/client/dist/pwa/assets/{yaml-D_Py0JsF.js → yaml-Dj1MTjr-.js} +1 -1
- package/src/client/dist/pwa/index.html +8 -11
- package/src/client/dist/pwa/sw.js +1 -1
- package/src/client/dist/pwa/assets/ActivityFeed-Cx1rS3ci.js +0 -8
- package/src/client/dist/pwa/assets/ChangelogPage-2OaGEKe9.js +0 -1
- package/src/client/dist/pwa/assets/ChangelogPage-D_WOVByV.css +0 -1
- package/src/client/dist/pwa/assets/ClosePopup-CvV-0nzX.js +0 -1
- package/src/client/dist/pwa/assets/ComparisonPanel-BmUrmK4m.js +0 -2
- package/src/client/dist/pwa/assets/CreatePage-C0uUaDXT.css +0 -1
- package/src/client/dist/pwa/assets/CreatePage-Hp3O5al9.js +0 -2
- package/src/client/dist/pwa/assets/DashboardPage-BqgK4lAf.css +0 -1
- package/src/client/dist/pwa/assets/DashboardPage-Mgx1FG2b.js +0 -1
- package/src/client/dist/pwa/assets/DiffViewer-aMjhTpVF.js +0 -8
- package/src/client/dist/pwa/assets/DocumentsPanel-Cdr5b21_.js +0 -1
- package/src/client/dist/pwa/assets/DrawerToggleButton-VEVxQ39S.js +0 -1
- package/src/client/dist/pwa/assets/GitPanel-DUJ15ikk.js +0 -3
- package/src/client/dist/pwa/assets/HealthPage-BbqLoFQj.css +0 -1
- package/src/client/dist/pwa/assets/HealthPage-v_jKOByf.js +0 -1
- package/src/client/dist/pwa/assets/MainLayout-jRXQQzPm.js +0 -2
- package/src/client/dist/pwa/assets/QBadge-BgS0-MXB.js +0 -1
- package/src/client/dist/pwa/assets/QBanner-CDiXUya7.js +0 -1
- package/src/client/dist/pwa/assets/QBtn-B7WFdfmy.js +0 -1
- package/src/client/dist/pwa/assets/QBtnDropdown-pyNCwmSZ.js +0 -1
- package/src/client/dist/pwa/assets/QBtnGroup-BMQlX2YS.js +0 -1
- package/src/client/dist/pwa/assets/QBtnToggle-eMu_yinY.js +0 -1
- package/src/client/dist/pwa/assets/QChip-DpUYTCOJ.js +0 -1
- package/src/client/dist/pwa/assets/QItemSection-CEUi4Tz0.js +0 -1
- package/src/client/dist/pwa/assets/QMarkupTable-DcoQpjPu.js +0 -1
- package/src/client/dist/pwa/assets/QPage-RpDxx5ah.js +0 -1
- package/src/client/dist/pwa/assets/QSpace-D3PNLwa4.js +0 -1
- package/src/client/dist/pwa/assets/QSpinnerDots-DWOFEezR.js +0 -1
- package/src/client/dist/pwa/assets/SchedulePanel-DBc1j1k3.js +0 -1
- package/src/client/dist/pwa/assets/SearchPage-CWca6d5o.js +0 -1
- package/src/client/dist/pwa/assets/SearchPage-DdWM01rq.css +0 -1
- package/src/client/dist/pwa/assets/SettingsPage-qKa3e6W-.js +0 -10
- package/src/client/dist/pwa/assets/TerminalPanel-Dv_1sNtU.js +0 -18
- package/src/client/dist/pwa/assets/TouchPan-DPBRkGyO.js +0 -1
- package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-CevQAXwk.js +0 -1
- package/src/client/dist/pwa/assets/WorkspacePage-CEwILZ6V.js +0 -4
- package/src/client/dist/pwa/assets/build-path-tree-Cx5bCcQs.js +0 -1
- package/src/client/dist/pwa/assets/de-BUPxnXau.js +0 -17
- package/src/client/dist/pwa/assets/debounce-CDIE7CV6.js +0 -1
- package/src/client/dist/pwa/assets/documents-CN6TlZH7.js +0 -1
- package/src/client/dist/pwa/assets/editor.api-vup96nzB.js +0 -413
- package/src/client/dist/pwa/assets/editor.worker-D-m8IBMa.js +0 -30
- package/src/client/dist/pwa/assets/efforts-BcV6XR1p.js +0 -9
- package/src/client/dist/pwa/assets/engineFeatures-D9IQa3bt.js +0 -1
- package/src/client/dist/pwa/assets/es-DMnEKZ17.js +0 -17
- package/src/client/dist/pwa/assets/expand-template-Cxl3iYaV.js +0 -1
- package/src/client/dist/pwa/assets/formatters-CQ90Icr4.js +0 -1
- package/src/client/dist/pwa/assets/fr-BTolHkCj.js +0 -17
- package/src/client/dist/pwa/assets/index-6H3m6vH7.css +0 -1
- package/src/client/dist/pwa/assets/index-BePGTdV0.js +0 -18
- package/src/client/dist/pwa/assets/it-BPFSv6Pp.js +0 -17
- package/src/client/dist/pwa/assets/layout-DE4C3CX3.js +0 -1
- package/src/client/dist/pwa/assets/monaco-contributions-BZH2_u8S.js +0 -51
- package/src/client/dist/pwa/assets/monaco.contribution--NRhv52L.js +0 -2
- package/src/client/dist/pwa/assets/pending-diff-open-DoKaz8uO.js +0 -1
- package/src/client/dist/pwa/assets/permissionModes-D58HKBN0.js +0 -36
- package/src/client/dist/pwa/assets/pinia-ClsyLh3i.js +0 -1
- package/src/client/dist/pwa/assets/private.use-form-D8Yuc3aU.js +0 -1
- package/src/client/dist/pwa/assets/reactivity.esm-bundler-DtSZKRQB.js +0 -1
- package/src/client/dist/pwa/assets/render-chat-markdown-BTcSOgEc.js +0 -67
- package/src/client/dist/pwa/assets/rolldown-runtime-hePW80VL.js +0 -1
- package/src/client/dist/pwa/assets/runtime-dom.esm-bundler-DgevF6KV.js +0 -4
- package/src/client/dist/pwa/assets/use-checkbox-3io6bTPe.js +0 -1
- package/src/client/dist/pwa/assets/use-onboarding-BE2bb17E.js +0 -2
- package/src/client/dist/pwa/assets/use-quasar-0nZoDKhp.js +0 -1
- package/src/client/dist/pwa/assets/vue-i18n-DtajJy_8.js +0 -3
- /package/src/client/dist/pwa/assets/{use-onboarding-CTZuBZOi.css → use-tours-CTZuBZOi.css} +0 -0
package/AGENTS.md
CHANGED
|
@@ -91,8 +91,9 @@ src/
|
|
|
91
91
|
├── client/ # Vue 3 + Quasar PWA
|
|
92
92
|
│ └── src/
|
|
93
93
|
│ ├── stores/ # pinia: workspace, websocket, settings, dev-server, templates
|
|
94
|
-
│ ├── components/ # WorkspaceList, NotionPanel, AcceptancePanel, ChatInput, GitPanel, PlansPanel, WorkspaceAttentionLabels…
|
|
94
|
+
│ ├── components/ # WorkspaceList, NotionPanel, AcceptancePanel, ChatInput, GitPanel, PlansPanel, WorkspaceAttentionLabels, HelpMenu…
|
|
95
95
|
│ ├── utils/ # expand-template, formatters, workspace-attention (CI failure / changes-requested derivation)…
|
|
96
|
+
│ ├── tours/ # declarative onboarding tours, one file per zone + registry
|
|
96
97
|
│ ├── pages/ # WorkspacePage, CreatePage, SettingsPage
|
|
97
98
|
│ └── router/
|
|
98
99
|
├── mcp-server/ # standalone MCP server spawned per workspace
|
|
@@ -250,6 +251,10 @@ One task, two engines, two sibling worktrees. `POST /api/workspaces` accepts a `
|
|
|
250
251
|
|
|
251
252
|
`workspace-template-service.ts` persists named presets of the create form in `<KOBO_HOME>/workspace-templates.json` (same JSON pattern as `templates.json`, no SQLite migration). `sanitizePreset` keeps known keys with the right type and drops the rest, so a hand-edited file degrades to unset fields rather than errors. `presetFromWorkspace(id)` derives the same shape from an existing workspace (tasks as titles, statuses dropped); `GET /api/workspaces/:id/preset` exposes it read-only and "Duplicate" opens `/create?from=<id>` with it. On the client, `utils/workspace-preset.ts` (`capturePreset` / `applyPreset`, pure, round-trip tested) is the single bridge between the form and a preset; the create page applies the engine first and waits a tick so its engine watchers normalise model / effort / permission mode before the preset's values land. See [CONFIGURATION.md → Workspace templates and duplication](CONFIGURATION.md#workspace-templates-and-duplication).
|
|
252
253
|
|
|
254
|
+
### Onboarding tours
|
|
255
|
+
|
|
256
|
+
`src/client/src/tours/` declares one driver.js tour per zone (home, create, workspace, git-pr, settings, dashboard, health, search, changelog) as data, one file per zone plus `registry.ts` whose order is the Help menu order: each step carries a stable id, a `data-tour` anchor, an i18n key prefix and optionally `when` (a run-time gate, `anchorPresent` from `dom.ts` for the steps whose anchor is rendered conditionally), `beforeShow` (open a tab, then the engine waits for the anchor to be visible) and `clickTarget` (the anchor `beforeShow` clicks). `composables/use-tours.ts` owns the single driver instance and the seen-state (`localStorage['kobo:tours']`, step ids per tour, marked as each step is shown so leaving mid-way only replays the rest); `migrateLegacyFlag` turns the pre-tours boolean flag into a fully seen home tour. `autoRun` shows unseen steps only, never stacks over a running tour and never navigates - it bails unless the current route is the tour's route - so the main layout and the pages arm it through `scheduleAutoRun`, which delays it past their first render and clears the timer on unmount; a run refused because another tour is running is queued and replayed in registry order, and a run refused because a dialog is open is retried once. `runTour`, used by the Help menu in the sidebar (which lists every tour with its status and can reset them all) and by the per-screen replay buttons, is the only path that navigates to the tour's route first. `waitForVisible` in `dom.ts` waits until the anchor intersects the viewport, not merely until it exists in the DOM; when an anchor never shows up the engine skips that step with a console warning and does not mark it seen, so it replays next time. `SETTINGS_GROUPS` in `tours/settings.ts` groups the Settings tabs into one step each. `tours-registry.test.ts` is a drift guard with a deliberately narrow scope: it fails when a step's anchor or `clickTarget` has no matching `data-tour` attribute in a Vue source, when an i18n key is missing in one of the five locales, when a Settings tab is not in exactly one group, or when a step id listed in its hand-maintained list of gated steps has lost its `when`. It does not detect a newly conditional anchor on its own - adding a `v-if` around an anchor means adding the step id to that list. A feature that adds a screen or a Settings tab adds its step or group; step ids are never renamed once shipped.
|
|
257
|
+
|
|
253
258
|
### Worktree purge
|
|
254
259
|
|
|
255
260
|
`src/server/services/worktree-purge-service.ts` removes a workspace's worktree from disk while preserving the chat history and PR metadata. Triggered manually via `POST /api/workspaces/:id/purge-worktree` from the workspace context menu, or automatically by the pr-watcher when a PR transitions to MERGED **and** `global.autoPurgeOnPrMerged` is enabled (Settings → Worktrees toggle, settings migration v36).
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,15 @@ All notable changes to Kōbō are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/). Each release is an `## <version>`
|
|
5
5
|
section — the in-app "What's new" dialog reads this file.
|
|
6
6
|
|
|
7
|
+
## 1.11.32
|
|
8
|
+
|
|
9
|
+
- chore(deps): npm update in the server and client trees
|
|
10
|
+
- fix(git): refuse push during a rebase and prefill workspaces from a PR
|
|
11
|
+
|
|
12
|
+
## 1.11.31
|
|
13
|
+
|
|
14
|
+
- feat(onboarding): per-zone guided tours with a help menu
|
|
15
|
+
|
|
7
16
|
## 1.11.30
|
|
8
17
|
|
|
9
18
|
- feat: workspace templates, duplication and per-engine default models
|
|
@@ -3564,16 +3564,26 @@ app.post('/:id/push', async (c) => {
|
|
|
3564
3564
|
const body = await c.req.json().catch(() => ({}));
|
|
3565
3565
|
const force = body?.force === true;
|
|
3566
3566
|
const worktreePath = workspace.worktreePath;
|
|
3567
|
+
// While a rebase / merge / cherry-pick is in flight the local branch ref
|
|
3568
|
+
// has not moved yet, so `git push` would exit 0 with "Everything
|
|
3569
|
+
// up-to-date" and the user would see nothing happen. Refuse instead.
|
|
3570
|
+
const ongoing = gitOps.getOngoingGitOperation(worktreePath);
|
|
3571
|
+
if (ongoing) {
|
|
3572
|
+
return c.json({
|
|
3573
|
+
error: `Cannot push while a ${ongoing} is in progress on branch '${workspace.workingBranch}'. Finish or abort it first.`,
|
|
3574
|
+
code: 'operation_in_progress',
|
|
3575
|
+
operation: ongoing,
|
|
3576
|
+
}, 409);
|
|
3577
|
+
}
|
|
3578
|
+
let upToDate;
|
|
3567
3579
|
try {
|
|
3568
3580
|
// Only pass an options arg when force is requested — keeps the
|
|
3569
3581
|
// no-options call shape identical to before for callers/tests that
|
|
3570
3582
|
// assert on argument count.
|
|
3571
|
-
|
|
3572
|
-
await gitOps.pushBranchAsync(worktreePath, workspace.workingBranch, { force: true })
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
await gitOps.pushBranchAsync(worktreePath, workspace.workingBranch);
|
|
3576
|
-
}
|
|
3583
|
+
const result = force
|
|
3584
|
+
? await gitOps.pushBranchAsync(worktreePath, workspace.workingBranch, { force: true })
|
|
3585
|
+
: await gitOps.pushBranchAsync(worktreePath, workspace.workingBranch);
|
|
3586
|
+
upToDate = result.upToDate;
|
|
3577
3587
|
}
|
|
3578
3588
|
catch (err) {
|
|
3579
3589
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -3581,8 +3591,13 @@ app.post('/:id/push', async (c) => {
|
|
|
3581
3591
|
}
|
|
3582
3592
|
// Emit a trace into the chat feed so the user sees the action
|
|
3583
3593
|
const session = workspaceService.getActiveSession(id);
|
|
3584
|
-
wsService.emit(id, 'user:message', {
|
|
3585
|
-
|
|
3594
|
+
wsService.emit(id, 'user:message', {
|
|
3595
|
+
content: upToDate
|
|
3596
|
+
? `Nothing to push: branch ${workspace.workingBranch} is already up to date on origin`
|
|
3597
|
+
: `Pushed branch ${workspace.workingBranch} to origin`,
|
|
3598
|
+
sender: 'system-prompt',
|
|
3599
|
+
}, session?.id ?? undefined);
|
|
3600
|
+
return c.json({ ok: true, branch: workspace.workingBranch, upToDate });
|
|
3586
3601
|
}
|
|
3587
3602
|
catch (err) {
|
|
3588
3603
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -4041,8 +4056,29 @@ app.post('/:id/force-push', async (c) => {
|
|
|
4041
4056
|
const workspace = workspaceService.getWorkspace(id);
|
|
4042
4057
|
if (!workspace)
|
|
4043
4058
|
return c.json({ error: `Workspace '${id}' not found` }, 404);
|
|
4044
|
-
|
|
4045
|
-
|
|
4059
|
+
// Same guard as /push: mid-rebase the branch ref has not moved, so the
|
|
4060
|
+
// force push would be a silent "Everything up-to-date" no-op.
|
|
4061
|
+
const ongoing = gitOps.getOngoingGitOperation(workspace.worktreePath);
|
|
4062
|
+
if (ongoing) {
|
|
4063
|
+
return c.json({
|
|
4064
|
+
error: `Cannot force push while a ${ongoing} is in progress on branch '${workspace.workingBranch}'. Finish or abort it first.`,
|
|
4065
|
+
code: 'operation_in_progress',
|
|
4066
|
+
operation: ongoing,
|
|
4067
|
+
}, 409);
|
|
4068
|
+
}
|
|
4069
|
+
const { upToDate } = await gitOps.pushBranchAsync(workspace.worktreePath, workspace.workingBranch, {
|
|
4070
|
+
force: true,
|
|
4071
|
+
});
|
|
4072
|
+
if (upToDate) {
|
|
4073
|
+
// This route never traced its pushes; only the surprising no-op case is
|
|
4074
|
+
// worth a line in the chat, so the user knows why nothing changed.
|
|
4075
|
+
const session = workspaceService.getActiveSession(id);
|
|
4076
|
+
wsService.emit(id, 'user:message', {
|
|
4077
|
+
content: `Nothing to push: branch ${workspace.workingBranch} is already up to date on origin`,
|
|
4078
|
+
sender: 'system-prompt',
|
|
4079
|
+
}, session?.id ?? undefined);
|
|
4080
|
+
}
|
|
4081
|
+
return c.json({ success: true, upToDate });
|
|
4046
4082
|
}
|
|
4047
4083
|
catch (err) {
|
|
4048
4084
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -2,7 +2,7 @@ import { execFile } from 'node:child_process';
|
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
3
|
import { getGlobalSettings } from '../../settings-service.js';
|
|
4
4
|
import { parseCliJson } from '../parse-cli-json.js';
|
|
5
|
-
import { deriveReadyToMerge } from '../types.js';
|
|
5
|
+
import { deriveReadyToMerge, truncatePrBody } from '../types.js';
|
|
6
6
|
const execFileAsync = promisify(execFile);
|
|
7
7
|
function record(value) {
|
|
8
8
|
return value !== null && typeof value === 'object' ? value : {};
|
|
@@ -141,6 +141,7 @@ export function mapBitbucketPage(raw) {
|
|
|
141
141
|
isFork: Boolean(sourceId) && Boolean(destId) && sourceId !== destId,
|
|
142
142
|
isDraft: pr.draft === true,
|
|
143
143
|
updatedAt: typeof updated === 'string' ? updated : typeof updated === 'number' ? new Date(updated).toISOString() : '',
|
|
144
|
+
body: truncatePrBody(pr.description),
|
|
144
145
|
// `bkt pr list` doesn't expose CI/review status in list output; avoiding a per-row lookup call here.
|
|
145
146
|
ci: null,
|
|
146
147
|
reviewDecision: null,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { execFile } from 'node:child_process';
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
import { parseCliJson } from '../parse-cli-json.js';
|
|
5
|
-
import { deriveReadyToMerge } from '../types.js';
|
|
5
|
+
import { deriveReadyToMerge, truncatePrBody } from '../types.js';
|
|
6
6
|
const execFileAsync = promisify(execFile);
|
|
7
7
|
const CLI_TIMEOUT_MS = 30_000;
|
|
8
8
|
function cliOptions(repoPath) {
|
|
@@ -93,7 +93,7 @@ query($q:String!,$first:Int!,$after:String){
|
|
|
93
93
|
pageInfo{ hasNextPage endCursor }
|
|
94
94
|
nodes{
|
|
95
95
|
... on PullRequest {
|
|
96
|
-
number title url isDraft updatedAt
|
|
96
|
+
number title url isDraft updatedAt body
|
|
97
97
|
author{ login }
|
|
98
98
|
headRefName baseRefName isCrossRepository reviewDecision
|
|
99
99
|
commits(last:1){ nodes{ commit{ statusCheckRollup{ state } } } }
|
|
@@ -133,6 +133,7 @@ export function mapGithubSearchPage(raw) {
|
|
|
133
133
|
isFork: pr.isCrossRepository === true,
|
|
134
134
|
isDraft: pr.isDraft === true,
|
|
135
135
|
updatedAt: typeof pr.updatedAt === 'string' ? pr.updatedAt : '',
|
|
136
|
+
body: truncatePrBody(pr.body),
|
|
136
137
|
ci: typeof rollup === 'string' ? rollup : null,
|
|
137
138
|
reviewDecision: typeof decision === 'string' ? decision : null,
|
|
138
139
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { execFile } from 'node:child_process';
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
import { parseCliJson } from '../parse-cli-json.js';
|
|
5
|
-
import { deriveReadyToMerge } from '../types.js';
|
|
5
|
+
import { deriveReadyToMerge, truncatePrBody } from '../types.js';
|
|
6
6
|
const execFileAsync = promisify(execFile);
|
|
7
7
|
const CLI_TIMEOUT_MS = 30_000;
|
|
8
8
|
function cliOptions(repoPath) {
|
|
@@ -148,6 +148,7 @@ export function mapGitlabPage(raw, opts) {
|
|
|
148
148
|
isFork: mr.source_project_id !== mr.target_project_id,
|
|
149
149
|
isDraft: mr.draft === true || mr.work_in_progress === true,
|
|
150
150
|
updatedAt: typeof mr.updated_at === 'string' ? mr.updated_at : '',
|
|
151
|
+
body: truncatePrBody(mr.description),
|
|
151
152
|
// `glab mr list` carries no pipeline status; the picker shows no CI pill
|
|
152
153
|
// for GitLab rather than paying one `glab ci get` per row.
|
|
153
154
|
ci: null,
|
|
@@ -18,6 +18,16 @@ export function deriveReadyToMerge(s) {
|
|
|
18
18
|
const noConflict = s.mergeable === 'MERGEABLE' || s.mergeable === null;
|
|
19
19
|
return s.state === 'OPEN' && ciOk && !blocked && noConflict;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Cap on `PullRequestSummary.body`. The picker lists up to a page of PRs at a
|
|
23
|
+
* time and the create form only needs enough to prefill a description, so a
|
|
24
|
+
* multi-megabyte body would be pure transfer cost.
|
|
25
|
+
*/
|
|
26
|
+
export const PR_BODY_MAX_CHARS = 4000;
|
|
27
|
+
/** Normalise a raw CLI body into `PullRequestSummary.body`. */
|
|
28
|
+
export function truncatePrBody(value) {
|
|
29
|
+
return typeof value === 'string' ? value.slice(0, PR_BODY_MAX_CHARS) : '';
|
|
30
|
+
}
|
|
21
31
|
/** Thrown by write operations when the forge cannot service them. */
|
|
22
32
|
export class ForgeUnavailableError extends Error {
|
|
23
33
|
code = 'forge_unavailable';
|
|
@@ -29,6 +29,8 @@ export async function computeGitStats(workspace, prSnapshot) {
|
|
|
29
29
|
prState: prSnapshot?.state ?? null,
|
|
30
30
|
unpushedCount,
|
|
31
31
|
workingTree,
|
|
32
|
+
// Sync and local (a few stat calls); not worth a slot in the Promise.all.
|
|
33
|
+
ongoingOperation: gitOps.getOngoingGitOperation(worktreePath),
|
|
32
34
|
forge: { id: forgeProvider.id, capabilities: forgeProvider.capabilities, availability },
|
|
33
35
|
computedAt: Date.now(),
|
|
34
36
|
};
|
|
@@ -27,6 +27,10 @@ export function buildNonInteractiveGitEnv() {
|
|
|
27
27
|
...process.env,
|
|
28
28
|
GIT_TERMINAL_PROMPT: '0',
|
|
29
29
|
GIT_ASKPASS: 'echo',
|
|
30
|
+
// Several callers parse git's human-readable output ("Everything
|
|
31
|
+
// up-to-date", "already exists", "N files changed"). Pin the C locale so a
|
|
32
|
+
// translated git never silently defeats those checks.
|
|
33
|
+
LC_ALL: 'C',
|
|
30
34
|
// `GIT_ASKPASS` only covers HTTP(S) credential prompts. A passphrase-
|
|
31
35
|
// protected SSH key with no running agent still blocks `ssh` on
|
|
32
36
|
// `/dev/tty`; `BatchMode=yes` makes that interactive auth fail in ~1s
|
|
@@ -80,14 +84,23 @@ async function gitAsync(repoPath, args, timeout = READ_ONLY_GIT_TIMEOUT_MS) {
|
|
|
80
84
|
* over a slow link froze the entire app for up to a minute, heartbeat included.
|
|
81
85
|
*/
|
|
82
86
|
async function gitNetworkAsync(repoPath, args) {
|
|
83
|
-
const { stdout } = await
|
|
87
|
+
const { stdout } = await gitNetworkAsyncFull(repoPath, args);
|
|
88
|
+
return stdout;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Same as `gitNetworkAsync` but also hands back stderr: git prints push
|
|
92
|
+
* progress and the "Everything up-to-date" notice there, not on stdout, and a
|
|
93
|
+
* caller that wants to distinguish a no-op push from a real one needs it.
|
|
94
|
+
*/
|
|
95
|
+
async function gitNetworkAsyncFull(repoPath, args) {
|
|
96
|
+
const { stdout, stderr } = await execFileAsync('git', args, {
|
|
84
97
|
cwd: repoPath,
|
|
85
98
|
encoding: 'utf-8',
|
|
86
99
|
timeout: SYNC_GIT_TIMEOUT_MS,
|
|
87
100
|
maxBuffer: GIT_MAX_BUFFER_BYTES,
|
|
88
101
|
env: NON_INTERACTIVE_GIT_ENV,
|
|
89
102
|
});
|
|
90
|
-
return stdout.trimEnd();
|
|
103
|
+
return { stdout: stdout.trimEnd(), stderr: stderr.trimEnd() };
|
|
91
104
|
}
|
|
92
105
|
/** Raised when a stale `index.lock` blocks every write on a worktree. */
|
|
93
106
|
export class GitIndexLockError extends Error {
|
|
@@ -407,6 +420,22 @@ export function mergeBranch(repoPath, baseBranch, opts) {
|
|
|
407
420
|
throw new Error(`Merge of 'origin/${baseBranch}' failed: ${message}`);
|
|
408
421
|
}
|
|
409
422
|
}
|
|
423
|
+
/**
|
|
424
|
+
* Read `git push --porcelain` stdout. Each ref line is `<flag>\t<from>:<to>\t<summary>`
|
|
425
|
+
* where the flag is `=` (up to date), ` ` (fast-forward), `+` (forced), `*`
|
|
426
|
+
* (new ref), `-` (deleted) or `!` (rejected). Returns `true` when every ref is
|
|
427
|
+
* up to date, `false` when at least one moved, `null` when there is no ref
|
|
428
|
+
* line at all so the caller can fall back to another signal. Exported for tests.
|
|
429
|
+
*/
|
|
430
|
+
export function parsePushPorcelain(stdout) {
|
|
431
|
+
const flags = stdout
|
|
432
|
+
.split('\n')
|
|
433
|
+
.filter((line) => /^[=+*\-! ]\t/.test(line))
|
|
434
|
+
.map((line) => line[0]);
|
|
435
|
+
if (flags.length === 0)
|
|
436
|
+
return null;
|
|
437
|
+
return flags.every((flag) => flag === '=');
|
|
438
|
+
}
|
|
410
439
|
/**
|
|
411
440
|
* Async variants of the network operations, for the HTTP handlers.
|
|
412
441
|
*
|
|
@@ -418,12 +447,17 @@ export function mergeBranch(repoPath, baseBranch, opts) {
|
|
|
418
447
|
*/
|
|
419
448
|
export async function pushBranchAsync(repoPath, branchName, options = {}) {
|
|
420
449
|
const remote = options.remote ?? 'origin';
|
|
421
|
-
const args = ['push', '-u'];
|
|
450
|
+
const args = ['push', '-u', '--porcelain'];
|
|
422
451
|
if (options.force)
|
|
423
452
|
args.push('--force-with-lease');
|
|
424
453
|
args.push(remote, branchName);
|
|
425
454
|
try {
|
|
426
|
-
await
|
|
455
|
+
const { stdout, stderr } = await gitNetworkAsyncFull(repoPath, args);
|
|
456
|
+
// `git push` exits 0 either way. `--porcelain` gives a locale-independent
|
|
457
|
+
// per-ref status line on stdout; the stderr notice is only a fallback for
|
|
458
|
+
// a git old enough to print nothing parseable.
|
|
459
|
+
const upToDate = parsePushPorcelain(stdout) ?? stderr.includes('Everything up-to-date');
|
|
460
|
+
return { upToDate };
|
|
427
461
|
}
|
|
428
462
|
catch (err) {
|
|
429
463
|
const message = err instanceof Error ? err.message : String(err);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loicngr/kobo",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.32",
|
|
4
4
|
"description": "Kōbō — multi-workspace agent manager for Claude Code. Orchestrates isolated git worktrees with dev servers, Notion integration, and MCP tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.agent-error-item[data-v-e98c3c02]{gap:var(--kobo-space-sm);padding:var(--kobo-space-sm) var(--kobo-space-md);border-left:2px solid var(--kobo-danger);background:var(--kobo-surface-2);border-radius:var(--kobo-radius-sm);align-items:flex-start;display:flex}.agent-error-item__icon[data-v-e98c3c02]{color:var(--kobo-danger);flex:none;margin-top:2px}.agent-error-item__body[data-v-e98c3c02]{min-width:0}.agent-error-item__title[data-v-e98c3c02]{color:var(--kobo-text);font-weight:600}.agent-error-item__message[data-v-e98c3c02]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;word-break:break-word;font-size:12px}.markdown-message[data-v-99371035]{color:var(--kobo-text-2);word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-99371035] *{max-width:100%}.markdown-message[data-v-99371035] p{margin:0 0 .5em}.markdown-message[data-v-99371035] p:last-child{margin-bottom:0}.markdown-message[data-v-99371035] pre{background:#00000059;border-radius:4px;margin:.5em 0;padding:.5em .75em;overflow-x:auto}.markdown-message[data-v-99371035] code{word-break:break-all;background:#0000004d;border-radius:3px;padding:.1em .3em;font-size:.9em}.markdown-message[data-v-99371035] pre code{background:0 0;padding:0}.markdown-message[data-v-99371035] ul,.markdown-message[data-v-99371035] ol{margin:.25em 0 .5em;padding-left:1.5em}.markdown-message[data-v-99371035] li{margin:.15em 0}.markdown-message[data-v-99371035] a{color:var(--kobo-text-2);text-decoration:underline}.markdown-message[data-v-99371035] .document-link{color:var(--kobo-text-2);cursor:pointer;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.markdown-message[data-v-99371035] .document-link:hover{color:var(--kobo-text);-webkit-text-decoration:underline;text-decoration:underline}.markdown-message[data-v-99371035] h1,.markdown-message[data-v-99371035] h2,.markdown-message[data-v-99371035] h3,.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{margin:.5em 0 .3em;font-weight:600;line-height:1.3}.markdown-message[data-v-99371035] h1{font-size:1.25em}.markdown-message[data-v-99371035] h2{font-size:1.15em}.markdown-message[data-v-99371035] h3{font-size:1.08em}.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{font-size:1em}.markdown-message[data-v-99371035] blockquote{color:#ffffffb3;border-left:3px solid #fff3;margin:.5em 0;padding-left:.75em}.markdown-message[data-v-99371035] table{border-collapse:collapse;margin:.5em 0}.markdown-message[data-v-99371035] th,.markdown-message[data-v-99371035] td{border:1px solid #ffffff26;padding:.25em .5em}.tool-row[data-v-2482adfe]{border-radius:4px;margin:0;font-size:12px}.tool-header[data-v-2482adfe]{color:var(--kobo-text-2);cursor:default;align-items:center;gap:10px;min-width:0;padding:5px 10px;display:flex}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe],.tool-row--toggleable .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:has(.tool-diff) .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe]:hover,.tool-row--toggleable .tool-header[data-v-2482adfe]:hover{background:#ffffff08}.tool-icon[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0}.tool-name[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0;font-weight:600}.tool-arg[data-v-2482adfe],.tool-path[data-v-2482adfe]{color:var(--kobo-text-3);text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%;font-family:var(--kobo-font-mono);font-size:11.5px;overflow:hidden}.tool-open-diff[data-v-2482adfe]{flex-shrink:0}.tool-path[data-v-2482adfe],.tool-arg[data-v-2482adfe]{flex:1}.tool-stat-add[data-v-2482adfe]{color:var(--kobo-success);flex-shrink:0;font-size:11px;font-weight:600}.tool-stat-del[data-v-2482adfe]{color:var(--kobo-danger);flex-shrink:0;font-size:11px;font-weight:600}.tool-diff[data-v-2482adfe]{max-height:400px;font-family:var(--kobo-font-mono);background:#0003;border-radius:4px;margin-top:4px;padding:8px 0;font-size:11px;line-height:1.5;overflow:auto}.diff-line[data-v-2482adfe]{white-space:pre;color:var(--kobo-text-2);padding:0 12px}.diff-sign[data-v-2482adfe]{width:14px;color:var(--kobo-text-disabled);-webkit-user-select:none;user-select:none;display:inline-block}.diff-add[data-v-2482adfe]{color:var(--kobo-success);background:#66bb6a1a}.diff-add .diff-sign[data-v-2482adfe]{color:var(--kobo-success)}.diff-del[data-v-2482adfe]{color:var(--kobo-danger);background:#ef53501a}.diff-del .diff-sign[data-v-2482adfe]{color:var(--kobo-danger)}.tool-output[data-v-2482adfe]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;background:#00000026;border-radius:4px;max-height:8em;margin-top:4px;padding:6px 10px;font-size:11px;overflow:auto}.markdown-message[data-v-7687eb7e]{color:var(--kobo-text-2);word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-7687eb7e] *{max-width:100%}.markdown-message[data-v-7687eb7e] img{-o-object-fit:contain;object-fit:contain;cursor:zoom-in;background:#0003;border-radius:4px;max-width:180px;max-height:100px;margin:.3em 0;display:block}.markdown-message[data-v-7687eb7e] code{word-break:break-all}.markdown-message[data-v-7687eb7e] p{margin:0 0 .4em}.markdown-message[data-v-7687eb7e] p:last-child{margin-bottom:0}.markdown-message[data-v-7687eb7e] code{background:#00000040;border-radius:3px;padding:.1em .3em}.markdown-message[data-v-7687eb7e] h1,.markdown-message[data-v-7687eb7e] h2,.markdown-message[data-v-7687eb7e] h3,.markdown-message[data-v-7687eb7e] h4,.markdown-message[data-v-7687eb7e] h5,.markdown-message[data-v-7687eb7e] h6{margin:.4em 0 .25em;font-weight:600;line-height:1.3}.markdown-message[data-v-7687eb7e] h1{font-size:1.25em}.markdown-message[data-v-7687eb7e] h2{font-size:1.15em}.markdown-message[data-v-7687eb7e] h3{font-size:1.08em}.markdown-message[data-v-7687eb7e] h4,.markdown-message[data-v-7687eb7e] h5,.markdown-message[data-v-7687eb7e] h6{font-size:1em}.markdown-user-prompt[data-v-7687eb7e]{color:var(--kobo-text-2);font-size:12px;font-style:italic}.markdown-user-prompt[data-v-7687eb7e] p{margin:0 0 .4em}.markdown-user-prompt[data-v-7687eb7e] code{background:#ffffff14;border-radius:3px;padding:.1em .3em;font-style:normal}.image-lightbox-img{-o-object-fit:contain;object-fit:contain;cursor:zoom-out;background:#0000004d;border-radius:4px;max-width:92vw;max-height:92vh;display:block}.turn-card[data-v-6e61835e]{border:1px solid #ffffff14;border-left:3px solid var(--turn-accent);background:#ffffff05;border-radius:6px;min-width:0;max-width:100%;margin:14px 0;overflow:hidden}.turn-card--highlighted[data-v-6e61835e]{animation:1.8s ease-out search-highlight-6e61835e}@keyframes search-highlight-6e61835e{0%,45%{box-shadow:0 0 0 2px #818cf8f2,0 0 22px #818cf873}to{box-shadow:none}}.turn-header[data-v-6e61835e]{color:var(--kobo-text-3);background:#ffffff08;border-bottom:1px solid #ffffff0d;align-items:center;gap:8px;padding:8px 14px;font-size:11px;display:flex}.turn-badge[data-v-6e61835e]{letter-spacing:.3px;border-radius:3px;padding:2px 8px;font-size:11px;font-weight:700}.turn-badge-user[data-v-6e61835e]{color:var(--kobo-turn-user);background:#ce93d826}.turn-badge-agent[data-v-6e61835e]{color:var(--kobo-turn-agent);background:#7986cb26}.turn-badge-system[data-v-6e61835e]{color:var(--kobo-text-2);background:#75757533;font-style:italic}.turn-badge-session[data-v-6e61835e]{color:var(--kobo-text-3);background:#61616133}.turn-badge-script[data-v-6e61835e]{color:var(--kobo-success);background:#4db6ac26}.turn-time[data-v-6e61835e]{color:var(--kobo-text-disabled);font-family:var(--kobo-font-mono);font-size:11px}.turn-time-arrow[data-v-6e61835e]{opacity:.7;margin:0 -2px}.turn-time-updated[data-v-6e61835e]{color:var(--kobo-text-3)}.turn-actions[data-v-6e61835e]{color:var(--kobo-text-3);font-size:11px}.turn-body[data-v-6e61835e]{flex-direction:column;gap:12px;min-width:0;padding:14px 18px;display:flex}.turn-body[data-v-6e61835e]>*{min-width:0;max-width:100%}.turn-body[data-v-6e61835e] .tool-row+.tool-row{margin-top:-8px}.turn-scroll-top[data-v-6e61835e]{justify-content:flex-start;padding:0 8px 6px;display:flex}.turn-scroll-top-btn[data-v-6e61835e]{opacity:.5;transition:opacity .15s}.turn-scroll-top-btn[data-v-6e61835e]:hover{opacity:1}.activity-feed-wrap[data-v-03fed8f2]{width:100%;height:100%;position:relative}.activity-feed-scroll[data-v-03fed8f2]{width:100%;height:100%}.activity-feed-nav-cluster[data-v-03fed8f2]{z-index:2;align-items:center;gap:8px;display:flex;position:absolute;bottom:14px;right:14px}.activity-feed-compacting[data-v-03fed8f2]{z-index:3;background:var(--kobo-surface);border:1px solid var(--kobo-border);border-radius:6px;align-items:center;gap:8px;padding:6px 14px;display:flex;position:absolute;top:12px;left:50%;transform:translate(-50%);box-shadow:0 4px 16px #00000059}.fade-enter-active[data-v-03fed8f2],.fade-leave-active[data-v-03fed8f2]{transition:opacity .16s}.fade-enter-from[data-v-03fed8f2],.fade-leave-to[data-v-03fed8f2]{opacity:0}.activity-feed-nav-btn[data-v-03fed8f2]{opacity:.8;transition:opacity .12s}.activity-feed-nav-btn[data-v-03fed8f2]:hover{opacity:1}.activity-feed-scroll[data-v-03fed8f2] .q-scrollarea__content{max-width:100%;overflow-x:hidden}.activity-feed-switching[data-v-03fed8f2]{justify-content:center;align-items:center;width:100%;height:100%;display:flex}.activity-feed-empty[data-v-03fed8f2]{align-items:center;gap:var(--kobo-space-sm);padding:var(--kobo-space-4xl) var(--kobo-space-xl);color:var(--kobo-text-3);text-align:center;flex-direction:column;display:flex}.activity-feed-empty__title[data-v-03fed8f2]{font-family:var(--kobo-font-sans);color:var(--kobo-text-2);font-size:14px;font-weight:500}.activity-feed-empty__hint[data-v-03fed8f2]{font-family:var(--kobo-font-sans);color:var(--kobo-text-3);max-width:380px;font-size:13px}
|
|
1
|
+
.agent-error-item[data-v-e98c3c02]{gap:var(--kobo-space-sm);padding:var(--kobo-space-sm) var(--kobo-space-md);border-left:2px solid var(--kobo-danger);background:var(--kobo-surface-2);border-radius:var(--kobo-radius-sm);align-items:flex-start;display:flex}.agent-error-item__icon[data-v-e98c3c02]{color:var(--kobo-danger);flex:none;margin-top:2px}.agent-error-item__body[data-v-e98c3c02]{min-width:0}.agent-error-item__title[data-v-e98c3c02]{color:var(--kobo-text);font-weight:600}.agent-error-item__message[data-v-e98c3c02]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;word-break:break-word;font-size:12px}.markdown-message[data-v-99371035]{color:var(--kobo-text-2);word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-99371035] *{max-width:100%}.markdown-message[data-v-99371035] p{margin:0 0 .5em}.markdown-message[data-v-99371035] p:last-child{margin-bottom:0}.markdown-message[data-v-99371035] pre{background:#00000059;border-radius:4px;margin:.5em 0;padding:.5em .75em;overflow-x:auto}.markdown-message[data-v-99371035] code{word-break:break-all;background:#0000004d;border-radius:3px;padding:.1em .3em;font-size:.9em}.markdown-message[data-v-99371035] pre code{background:0 0;padding:0}.markdown-message[data-v-99371035] ul,.markdown-message[data-v-99371035] ol{margin:.25em 0 .5em;padding-left:1.5em}.markdown-message[data-v-99371035] li{margin:.15em 0}.markdown-message[data-v-99371035] a{color:var(--kobo-text-2);text-decoration:underline}.markdown-message[data-v-99371035] .document-link{color:var(--kobo-text-2);cursor:pointer;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.markdown-message[data-v-99371035] .document-link:hover{color:var(--kobo-text);-webkit-text-decoration:underline;text-decoration:underline}.markdown-message[data-v-99371035] h1,.markdown-message[data-v-99371035] h2,.markdown-message[data-v-99371035] h3,.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{margin:.5em 0 .3em;font-weight:600;line-height:1.3}.markdown-message[data-v-99371035] h1{font-size:1.25em}.markdown-message[data-v-99371035] h2{font-size:1.15em}.markdown-message[data-v-99371035] h3{font-size:1.08em}.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{font-size:1em}.markdown-message[data-v-99371035] blockquote{color:#ffffffb3;border-left:3px solid #fff3;margin:.5em 0;padding-left:.75em}.markdown-message[data-v-99371035] table{border-collapse:collapse;margin:.5em 0}.markdown-message[data-v-99371035] th,.markdown-message[data-v-99371035] td{border:1px solid #ffffff26;padding:.25em .5em}.tool-row[data-v-2482adfe]{border-radius:4px;margin:0;font-size:12px}.tool-header[data-v-2482adfe]{color:var(--kobo-text-2);cursor:default;align-items:center;gap:10px;min-width:0;padding:5px 10px;display:flex}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe],.tool-row--toggleable .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:has(.tool-diff) .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe]:hover,.tool-row--toggleable .tool-header[data-v-2482adfe]:hover{background:#ffffff08}.tool-icon[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0}.tool-name[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0;font-weight:600}.tool-arg[data-v-2482adfe],.tool-path[data-v-2482adfe]{color:var(--kobo-text-3);text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%;font-family:var(--kobo-font-mono);font-size:11.5px;overflow:hidden}.tool-open-diff[data-v-2482adfe]{flex-shrink:0}.tool-path[data-v-2482adfe],.tool-arg[data-v-2482adfe]{flex:1}.tool-stat-add[data-v-2482adfe]{color:var(--kobo-success);flex-shrink:0;font-size:11px;font-weight:600}.tool-stat-del[data-v-2482adfe]{color:var(--kobo-danger);flex-shrink:0;font-size:11px;font-weight:600}.tool-diff[data-v-2482adfe]{max-height:400px;font-family:var(--kobo-font-mono);background:#0003;border-radius:4px;margin-top:4px;padding:8px 0;font-size:11px;line-height:1.5;overflow:auto}.diff-line[data-v-2482adfe]{white-space:pre;color:var(--kobo-text-2);padding:0 12px}.diff-sign[data-v-2482adfe]{width:14px;color:var(--kobo-text-disabled);-webkit-user-select:none;user-select:none;display:inline-block}.diff-add[data-v-2482adfe]{color:var(--kobo-success);background:#66bb6a1a}.diff-add .diff-sign[data-v-2482adfe]{color:var(--kobo-success)}.diff-del[data-v-2482adfe]{color:var(--kobo-danger);background:#ef53501a}.diff-del .diff-sign[data-v-2482adfe]{color:var(--kobo-danger)}.tool-output[data-v-2482adfe]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;background:#00000026;border-radius:4px;max-height:8em;margin-top:4px;padding:6px 10px;font-size:11px;overflow:auto}.markdown-message[data-v-7687eb7e]{color:var(--kobo-text-2);word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-7687eb7e] *{max-width:100%}.markdown-message[data-v-7687eb7e] img{-o-object-fit:contain;object-fit:contain;cursor:zoom-in;background:#0003;border-radius:4px;max-width:180px;max-height:100px;margin:.3em 0;display:block}.markdown-message[data-v-7687eb7e] code{word-break:break-all}.markdown-message[data-v-7687eb7e] p{margin:0 0 .4em}.markdown-message[data-v-7687eb7e] p:last-child{margin-bottom:0}.markdown-message[data-v-7687eb7e] code{background:#00000040;border-radius:3px;padding:.1em .3em}.markdown-message[data-v-7687eb7e] h1,.markdown-message[data-v-7687eb7e] h2,.markdown-message[data-v-7687eb7e] h3,.markdown-message[data-v-7687eb7e] h4,.markdown-message[data-v-7687eb7e] h5,.markdown-message[data-v-7687eb7e] h6{margin:.4em 0 .25em;font-weight:600;line-height:1.3}.markdown-message[data-v-7687eb7e] h1{font-size:1.25em}.markdown-message[data-v-7687eb7e] h2{font-size:1.15em}.markdown-message[data-v-7687eb7e] h3{font-size:1.08em}.markdown-message[data-v-7687eb7e] h4,.markdown-message[data-v-7687eb7e] h5,.markdown-message[data-v-7687eb7e] h6{font-size:1em}.markdown-user-prompt[data-v-7687eb7e]{color:var(--kobo-text-2);font-size:12px;font-style:italic}.markdown-user-prompt[data-v-7687eb7e] p{margin:0 0 .4em}.markdown-user-prompt[data-v-7687eb7e] code{background:#ffffff14;border-radius:3px;padding:.1em .3em;font-style:normal}.image-lightbox-img{-o-object-fit:contain;object-fit:contain;cursor:zoom-out;background:#0000004d;border-radius:4px;max-width:92vw;max-height:92vh;display:block}.turn-card[data-v-6e61835e]{border:1px solid #ffffff14;border-left:3px solid var(--turn-accent);background:#ffffff05;border-radius:6px;min-width:0;max-width:100%;margin:14px 0;overflow:hidden}.turn-card--highlighted[data-v-6e61835e]{animation:1.8s ease-out search-highlight-6e61835e}@keyframes search-highlight-6e61835e{0%,45%{box-shadow:0 0 0 2px #818cf8f2,0 0 22px #818cf873}to{box-shadow:none}}.turn-header[data-v-6e61835e]{color:var(--kobo-text-3);background:#ffffff08;border-bottom:1px solid #ffffff0d;align-items:center;gap:8px;padding:8px 14px;font-size:11px;display:flex}.turn-badge[data-v-6e61835e]{letter-spacing:.3px;border-radius:3px;padding:2px 8px;font-size:11px;font-weight:700}.turn-badge-user[data-v-6e61835e]{color:var(--kobo-turn-user);background:#ce93d826}.turn-badge-agent[data-v-6e61835e]{color:var(--kobo-turn-agent);background:#7986cb26}.turn-badge-system[data-v-6e61835e]{color:var(--kobo-text-2);background:#75757533;font-style:italic}.turn-badge-session[data-v-6e61835e]{color:var(--kobo-text-3);background:#61616133}.turn-badge-script[data-v-6e61835e]{color:var(--kobo-success);background:#4db6ac26}.turn-time[data-v-6e61835e]{color:var(--kobo-text-disabled);font-family:var(--kobo-font-mono);font-size:11px}.turn-time-arrow[data-v-6e61835e]{opacity:.7;margin:0 -2px}.turn-time-updated[data-v-6e61835e]{color:var(--kobo-text-3)}.turn-actions[data-v-6e61835e]{color:var(--kobo-text-3);font-size:11px}.turn-body[data-v-6e61835e]{flex-direction:column;gap:12px;min-width:0;padding:14px 18px;display:flex}.turn-body[data-v-6e61835e]>*{min-width:0;max-width:100%}.turn-body[data-v-6e61835e] .tool-row+.tool-row{margin-top:-8px}.turn-scroll-top[data-v-6e61835e]{justify-content:flex-start;padding:0 8px 6px;display:flex}.turn-scroll-top-btn[data-v-6e61835e]{opacity:.5;transition:opacity .15s}.turn-scroll-top-btn[data-v-6e61835e]:hover{opacity:1}.activity-feed-wrap[data-v-01cd9f2a]{width:100%;height:100%;position:relative}.activity-feed-scroll[data-v-01cd9f2a]{width:100%;height:100%}.activity-feed-nav-cluster[data-v-01cd9f2a]{z-index:2;align-items:center;gap:8px;display:flex;position:absolute;bottom:14px;right:14px}.activity-feed-compacting[data-v-01cd9f2a]{z-index:3;background:var(--kobo-surface);border:1px solid var(--kobo-border);border-radius:6px;align-items:center;gap:8px;padding:6px 14px;display:flex;position:absolute;top:12px;left:50%;transform:translate(-50%);box-shadow:0 4px 16px #00000059}.fade-enter-active[data-v-01cd9f2a],.fade-leave-active[data-v-01cd9f2a]{transition:opacity .16s}.fade-enter-from[data-v-01cd9f2a],.fade-leave-to[data-v-01cd9f2a]{opacity:0}.activity-feed-nav-btn[data-v-01cd9f2a]{opacity:.8;transition:opacity .12s}.activity-feed-nav-btn[data-v-01cd9f2a]:hover{opacity:1}.activity-feed-scroll[data-v-01cd9f2a] .q-scrollarea__content{max-width:100%;overflow-x:hidden}.activity-feed-switching[data-v-01cd9f2a]{justify-content:center;align-items:center;width:100%;height:100%;display:flex}.activity-feed-empty[data-v-01cd9f2a]{align-items:center;gap:var(--kobo-space-sm);padding:var(--kobo-space-4xl) var(--kobo-space-xl);color:var(--kobo-text-3);text-align:center;flex-direction:column;display:flex}.activity-feed-empty__title[data-v-01cd9f2a]{font-family:var(--kobo-font-sans);color:var(--kobo-text-2);font-size:14px;font-weight:500}.activity-feed-empty__hint[data-v-01cd9f2a]{font-family:var(--kobo-font-sans);color:var(--kobo-text-3);max-width:380px;font-size:13px}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import{S as e,ct as t,j as n,ot as r,ut as i,v as a}from"./reactivity.esm-bundler-DEJj9cFv.js";import{C as o,F as s,K as c,L as l,N as u,O as d,P as f,_ as p,d as m,f as h,g,j as _,k as v,l as y,p as b,q as x,r as S,u as C,y as w,z as T}from"./runtime-core.esm-bundler-CS0xkoG_.js";import{J as E,b as D,ct as O,l as k,pt as A,t as ee,tt as j,w as M,y as te}from"./QBtn-DqZryKOh.js";import{C as N,H as ne,It as re,Nt as P,T as F,bt as ie,m as ae,p as oe,vt as I,w as se}from"./index-DztjpQfb.js";import{t as ce}from"./QSpinnerDots-6v3Yl0T6.js";import{r as le}from"./QItemSection-CjrpcdN_.js";import{t as L}from"./QMarkupTable-MxPL53nz.js";import{_ as ue,b as R,x as z}from"./permissionModes-DORv0Hwo.js";import{r as de,t as B}from"./pending-diff-open-CK20L_pt.js";import{t as V}from"./documents-D4BcPyOF.js";import{a as H,o as U}from"./use-tours-BEdbVcQS.js";import{i as fe,n as W,o as pe,r as me,t as he}from"./render-chat-markdown-nZGk_TRQ.js";import{a as ge,i as _e,n as G,o as ve,r as ye,s as be}from"./WorkspacePage-Dv3ED-Bt.js";function xe(e,t){return o(`div`,e,[o(`table`,{class:`q-table`},t)])}var K={list:le,table:L},q=[`list`,`table`,`__qtable`],Se=j({name:`QVirtualScroll`,props:{...z,type:{type:String,default:`list`,validator:e=>q.includes(e)},items:{type:Array,default:()=>[]},itemsFn:Function,itemsSize:Number,scrollTarget:re},setup(t,{slots:n,attrs:r}){let i,a=e(null),s=y(()=>t.itemsSize>=0&&t.itemsFn!==void 0?Number.parseInt(t.itemsSize,10):Array.isArray(t.items)?t.items.length:0),{virtualScrollSliceRange:l,localResetVirtualScroll:d,padVirtualScroll:p,onVirtualScrollEvt:m}=R({virtualScrollLength:s,getVirtualScrollTarget:S,getVirtualScrollEl:x}),h=y(()=>{if(s.value===0)return[];let e=(e,t)=>({index:l.value.from+t,item:e});return t.itemsFn===void 0?t.items.slice(l.value.from,l.value.to).map(e):t.itemsFn(l.value.from,l.value.to-l.value.from).map(e)}),g=y(()=>`q-virtual-scroll q-virtual-scroll`+(t.virtualScrollHorizontal?`--horizontal`:`--vertical`)+(t.scrollTarget===void 0?` scroll`:``)),b=y(()=>t.scrollTarget===void 0?{tabindex:0}:{});c(s,()=>{d()}),c(()=>t.scrollTarget,()=>{w(),C()});function x(){let e=a.value;return e===null?null:e.$el||e}function S(){return i}function C(){let e=x();e!==null&&(i=P(e,t.scrollTarget),i.addEventListener(`scroll`,m,E.passive))}function w(){i!==void 0&&(i.removeEventListener(`scroll`,m,E.passive),i=void 0)}function T(){let e=p(t.type===`list`?`div`:`tbody`,h.value.map(n.default));return n.before!==void 0&&(e=n.before().concat(e)),D(n.after,e)}return d(),f(()=>{C()}),v(()=>{C()}),u(()=>{w()}),_(()=>{w()}),()=>{if(n.default===void 0){console.error(`QVirtualScroll: default scoped slot is required for rendering`);return}return t.type===`__qtable`?xe({ref:a,class:`q-table__middle `+g.value,tabindex:0},T()):o(K[t.type],{...r,ref:a,class:[r.class,g.value],...b.value},T)}}}),Ce=new Set([`setup`,`cleanup`,`archive`]);function we(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:Ce.has(e.sender)||N(e.sender)?`script`:`user`;case`session`:return`session`;default:return`agent`}}function Te(e){let t=[],n=null,r=null;for(let i of e){let e=we(i),a=e===`session`||e===`system-prompt`,o=e===`script`&&i.type===`user`?`script:${i.sender}`: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 Ee(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 De(e){let t=e.items[0];return`${e.speaker}:${t?Ee(t):`empty`}`}function Oe(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 ke(e,t,n){return new Promise(r=>{let i=!1,a=null,o=null,s=e=>{i||(i=!0,a!==null&&clearTimeout(a),a=null,o?.(),r(e))};if(o=c(e,e=>{t(e)&&s(!0)},{immediate:!0}),i){o();return}a=setTimeout(()=>s(!1),n)})}var Ae={class:`agent-error-item`},je={class:`agent-error-item__body`},Me={class:`agent-error-item__title`},Ne={class:`agent-error-item__message`},J=H(w({__name:`AgentErrorItem`,props:{item:{}},setup(e){let t=e,{te:n}=I(),r=y(()=>{let e=`agent.error.${t.item.category}`;return n(e)?e:`agent.error.other`});return(t,n)=>(l(),b(`div`,Ae,[p(k,{name:`error_outline`,size:`16px`,class:`agent-error-item__icon`}),C(`div`,je,[C(`div`,Me,i(t.$t(r.value)),1),C(`div`,Ne,i(e.item.message),1)])]))}}),[[`__scopeId`,`data-v-e98c3c02`]]),Pe={class:`text-caption text-kobo-3`},Y=w({__name:`SessionEventItem`,props:{item:{}},setup(e){let t=e,n=y(()=>{switch(t.item.kind){case`started`:return`session.started`;case`ended`:return be(t.item.detail);case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,t)=>(l(),b(`span`,Pe,i(e.$t(n.value)),1))}});function Fe(e,t){if(t.length===0||e.length===0)return e;let n=[...t].sort((e,t)=>t.length-e.length),r=new DOMParser().parseFromString(`<div>${e}</div>`,`text/html`),i=r.body.firstChild;if(!i)return e;function a(e){if(e.nodeType===Node.TEXT_NODE){X(e,n,r);return}if(e.nodeName===`A`)return;let t=Array.from(e.childNodes);for(let e of t)a(e)}return a(i),i.innerHTML}function X(e,t,n){let r=e.textContent??``;if(!t.some(e=>r.includes(e)))return;let i=n.createDocumentFragment(),a=0;for(;a<r.length;){let e=Z(r,a,t);if(!e){i.appendChild(n.createTextNode(r.slice(a)));break}e.index>a&&i.appendChild(n.createTextNode(r.slice(a,e.index)));let o=n.createElement(`a`);o.className=`document-link`,o.setAttribute(`data-document-path`,e.path),o.setAttribute(`href`,`#`),o.textContent=e.path,i.appendChild(o),a=e.index+e.path.length}e.parentNode?.replaceChild(i,e)}function Z(e,t,n){let r=null;for(let i of n){let n=e.indexOf(i,t);n<0||(!r||n<r.index||n===r.index&&i.length>r.path.length)&&(r={index:n,path:i})}return r}var Ie=[`innerHTML`],Le=H(w({__name:`TextMessageItem`,props:{item:{}},setup(e){let t=e,n=V(),r=oe(),i=te(),{t:a}=I(),o=y(()=>{let e=r.selectedWorkspaceId;return e?n.documentsFor(e).map(e=>e.path):[]}),s=y(()=>{let e=t.item;if(e.streaming)return he(e.text);let n=o.value;return me(`${e.messageId}|${n.join(`,`)}`,e.text,e=>{let t=Fe(pe.parse(e,{async:!1,breaks:!0,gfm:!0}),n);return fe(t,{addAttr:[`data-document-path`]})})});function c(e){let t=e.target?.closest(`.document-link`);if(!t)return;e.preventDefault();let o=t.getAttribute(`data-document-path`),s=r.selectedWorkspaceId;o&&s&&n.openDocumentByPath(s,o).catch(e=>{console.error(`[TextMessageItem] openDocumentByPath failed:`,e),i.notify({type:`negative`,message:a(`documents.loadFailed`),position:`top`})})}return(t,n)=>(l(),b(`div`,{class:`markdown-message`,onClick:c},[C(`div`,{innerHTML:s.value},null,8,Ie),e.item.streaming?(l(),m(M,{key:0,size:`xs`,class:`q-ml-xs`})):h(``,!0)]))}}),[[`__scopeId`,`data-v-99371035`]]);function Q(e,t){let n=e.split(`
|
|
2
|
+
`),r=t.split(`
|
|
3
|
+
`),i=0;for(;i<n.length&&i<r.length&&n[i]===r[i];)i++;let a=n.length,o=r.length;for(;a>i&&o>i&&n[a-1]===r[o-1];)a--,o--;let s=n.slice(0,i).map(e=>({type:`context`,content:e})),c=n.slice(a).map(e=>({type:`context`,content:e})),l=n.slice(i,a),u=r.slice(i,o);return l.length>800||u.length>800?[...s,...l.map(e=>({type:`del`,content:e})),...u.map(e=>({type:`add`,content:e})),...c]:[...s,...Re(l,u),...c]}function Re(e,t){let n=e.length,r=t.length;if(n===0&&r===0)return[];if(n===0)return t.map(e=>({type:`add`,content:e}));if(r===0)return e.map(e=>({type:`del`,content:e}));let i=r+1,a=new Int32Array((n+1)*i);for(let o=n-1;o>=0;o--)for(let n=r-1;n>=0;n--)a[o*i+n]=e[o]===t[n]?a[(o+1)*i+(n+1)]+1:Math.max(a[(o+1)*i+n],a[o*i+(n+1)]);let o=[],s=0,c=0;for(;s<n&&c<r;)e[s]===t[c]?(o.push({type:`context`,content:e[s]}),s++,c++):a[(s+1)*i+c]>=a[s*i+(c+1)]?(o.push({type:`del`,content:e[s]}),s++):(o.push({type:`add`,content:t[c]}),c++);for(;s<n;)o.push({type:`del`,content:e[s++]});for(;c<r;)o.push({type:`add`,content:t[c++]});return o}function ze(e){let t=e.split(`
|
|
4
|
+
`),n=[],r=!1;for(let e of t){if(e.startsWith(`@@`)){r=!0;continue}(r||!e.startsWith(`+++`)&&!e.startsWith(`---`))&&(e.startsWith(`+`)?n.push({type:`add`,content:e.slice(1)}):e.startsWith(`-`)?n.push({type:`del`,content:e.slice(1)}):e.startsWith(` `)?n.push({type:`context`,content:e.slice(1)}):e.length>0&&n.push({type:`context`,content:e}))}return n}function Be(e,t){if(!t||typeof t!=`object`)return null;let n=t;if(e===`Edit`){let e=n.file_path;if(!e)return null;let t=n.old_string??``,r=n.new_string??``,i=typeof n.diff==`string`?n.diff:``;if(!t&&!r&&i.length>0){let t=ze(i);return{toolName:`Edit`,filePath:e,additions:t.filter(e=>e.type===`add`).length,deletions:t.filter(e=>e.type===`del`).length,diffLines:t}}return{toolName:`Edit`,filePath:e,oldString:t,newString:r,replaceAll:n.replace_all??!1,additions:r?r.split(`
|
|
5
|
+
`).length:0,deletions:t?t.split(`
|
|
6
|
+
`).length:0}}if(e===`Write`){let e=n.file_path;if(!e)return null;let t=n.content??``;return{toolName:`Write`,filePath:e,content:t,additions:t?t.split(`
|
|
7
|
+
`).length:0,deletions:0}}if(e===`Bash`){let e=(n.command??``).match(/^\s*rm\s+(?:-[a-zA-Z]*\s+)*(.+)/);if(e)return{toolName:`Bash:rm`,filePath:e[1].trim().replace(/["']/g,``),additions:0,deletions:1}}return null}function $(e,t){if(!e||!t?.projectPath)return e;let n=t.worktreePath;if(n){let t=Ve(e,n);if(t!==e)return t}let r=Ve(e,`${t.projectPath}/${F}/${t.workingBranch}`);return r===e?Ve(e,t.projectPath):r}function Ve(e,t){if(!t)return e;let n=He(t);return n?e.replace(RegExp(`${n}[\\\\/]+`,`g`),``).replace(RegExp(`${n}(?=\\s|$|["'\`])`,`g`),`.`):e}function He(e){let t=e.replace(/[\\/]+$/,``);return t?`${/^[\\/]+/.test(t)?`[\\\\/]+`:``}${t.split(/[\\/]+/).filter(Boolean).map(Ue).join(`[\\\\/]+`)}`:``}function Ue(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}var We={class:`tool-name`},Ge=[`title`],Ke={key:0,class:`tool-stat-add`},qe={key:1,class:`tool-stat-del`},Je={class:`diff-sign`},Ye={class:`tool-name`},Xe=[`title`],Ze=H(w({__name:`ToolCallItem`,props:{item:{}},setup(e){let t=e,o=a(!1),s=oe(),{t:u}=I(),d=y(()=>Be(t.item.name,t.item.input)),f=y(()=>d.value?$(d.value.filePath,s.selectedWorkspace):``),_={Bash:`terminal`,Read:`description`,Edit:`edit`,Write:`edit_note`,MultiEdit:`edit`,Glob:`folder_open`,Grep:`manage_search`,LS:`list`,Skill:`auto_awesome`,Task:`hub`,Agent:`hub`,TodoWrite:`checklist`,TodoRead:`checklist`,TaskCreate:`add_task`,TaskUpdate:`checklist`,TaskGet:`checklist`,TaskList:`checklist`,ToolSearch:`search`,WebFetch:`public`,WebSearch:`travel_explore`,NotebookRead:`book`,NotebookEdit:`edit_note`,SendMessage:`send`,ExitPlanMode:`check_circle_outline`,KillShell:`stop_circle`,BashOutput:`terminal`},v=y(()=>_[t.item.name]??`build`),w=y(()=>{if(d.value)return``;let e=t.item.input,n=E(e);return n?$(n,s.selectedWorkspace):``});function E(e){if(!e||typeof e!=`object`)return typeof e==`string`?e:``;let t=e;for(let e of[`file_path`,`path`,`command`,`pattern`,`query`,`url`,`skill`,`description`,`subject`,`prompt`]){let n=t[e];if(typeof n==`string`&&n.length>0)return n}for(let e of Object.values(t))if(typeof e==`string`&&e.length>0)return e;return``}let D=y(()=>{let e=d.value;return e?e.diffLines?e.diffLines:e.toolName===`Edit`&&e.oldString!==void 0&&e.newString!==void 0?Q(e.oldString,e.newString):e.toolName===`Write`&&e.content!==void 0?e.content.split(`
|
|
8
|
+
`).map(e=>({type:`add`,content:e})):e.toolName===`Bash:rm`?[{type:`del`,content:`File deleted`}]:null:null}),O=y(()=>{let e=t.item.result;if(!e)return``;if(typeof e.output==`string`)return e.output;try{return JSON.stringify(e.output)}catch{return String(e.output)}}),j=new Set([`Read`]),M=y(()=>!!(t.item.result&&O.value)&&(!j.has(t.item.name)||t.item.result?.isError===!0));function te(){o.value=!o.value}function N(){let e=d.value?.filePath,t=s.selectedWorkspace,n=t?.id,r=e?$(e,t):``;r&&!/^(?:[A-Za-z]:)?[\\/]/.test(r)&&n&&(B(n,r),window.dispatchEvent(new CustomEvent(`kobo:open-diff`,{detail:{workspaceId:n,path:r}})))}return c(()=>t.item.result?.isError===!0,e=>{e&&(o.value=!0)},{immediate:!0}),(t,a)=>d.value?(l(),b(`div`,{key:0,class:r([`tool-row`,{"tool-row-expanded":o.value}])},[C(`div`,{class:`tool-header`,onClick:te},[p(k,{name:v.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),C(`span`,We,i(d.value.toolName===`Bash:rm`?`Bash`:d.value.toolName),1),C(`span`,{class:`tool-path`,title:d.value.filePath},i(f.value),9,Ge),p(ee,{flat:``,dense:``,round:``,size:`xs`,icon:`open_in_new`,class:`tool-open-diff`,onClick:A(N,[`stop`])},{default:x(()=>[p(U,null,{default:x(()=>[g(i(n(u)(`chat.openInGitDiff`)),1)]),_:1})]),_:1}),d.value.additions>0?(l(),b(`span`,Ke,`+`+i(d.value.additions),1)):h(``,!0),d.value.deletions>0?(l(),b(`span`,qe,`-`+i(d.value.deletions),1)):h(``,!0),e.item.result?.isError?(l(),m(k,{key:2,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-xs`})):e.item.result?(l(),m(k,{key:3,name:`check`,color:`positive`,size:`xs`,class:`q-ml-xs`})):h(``,!0),p(k,{name:o.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-auto text-kobo-3`},null,8,[`name`])]),o.value&&D.value?(l(),b(`div`,{key:0,class:`tool-diff`,onClick:a[0]||=A(()=>{},[`stop`])},[(l(!0),b(S,null,T(D.value,(e,t)=>(l(),b(`div`,{key:t,class:r([`diff-line`,{"diff-del":e.type===`del`,"diff-add":e.type===`add`,"diff-context":e.type===`context`}])},[C(`span`,Je,i(e.type===`del`?`-`:e.type===`add`?`+`:` `),1),g(i(e.content),1)],2))),128))])):h(``,!0)],2)):(l(),b(`div`,{key:1,class:r([`tool-row tool-row-generic`,{"tool-row-expanded":o.value,"tool-row--toggleable":M.value}])},[C(`div`,{class:`tool-header`,onClick:a[1]||=e=>M.value&&te()},[p(k,{name:v.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),C(`span`,Ye,i(e.item.name),1),w.value?(l(),b(`span`,{key:0,class:`tool-arg`,title:E(e.item.input)||w.value},i(w.value),9,Xe)):h(``,!0),e.item.result?.isError?(l(),m(k,{key:1,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-auto`})):e.item.result?(l(),m(k,{key:2,name:`check`,color:`positive`,size:`xs`,class:`q-ml-auto`})):h(``,!0),M.value?(l(),m(k,{key:3,name:o.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-xs text-kobo-3`},null,8,[`name`])):h(``,!0)]),o.value&&M.value?(l(),b(`div`,{key:0,class:`tool-output`,onClick:a[2]||=A(()=>{},[`stop`])},i(O.value),1)):h(``,!0)],2))}}),[[`__scopeId`,`data-v-2482adfe`]]);function Qe(e,t){return t?e.replace(/\[image:\s+([^\]]+)\]/g,(e,n)=>{let r=String(n).trim();return/^(\.ai\/images\/|images\/)/.test(r)?`}/images/file?path=${encodeURIComponent(r)}`})`:e}):e}var $e=[`innerHTML`],et=[`innerHTML`],tt=[`src`],nt=H(w({__name:`UserMessageItem`,props:{item:{}},setup(e){let t=e,n=oe(),r=y(()=>t.item.sender===`system-prompt`),i=y(()=>{let e=Qe(t.item.content,n.selectedWorkspaceId??``);return W(e)}),o=a(null),s=a(!1);function c(e){let t=e.target;if(t?.tagName!==`IMG`)return;let n=t;n.src&&(o.value=n.src,s.value=!0)}return(e,t)=>(l(),b(S,null,[r.value?(l(),m(ue,{key:0,dense:``,"dense-toggle":``,label:e.$t(`chat.systemPrompt`),"header-class":`text-kobo-2 text-caption`},{default:x(()=>[C(`div`,{class:`q-py-xs markdown-user-prompt`,innerHTML:i.value},null,8,$e)]),_:1},8,[`label`])):(l(),b(`div`,{key:1,class:`markdown-message`,onClick:c},[C(`div`,{innerHTML:i.value},null,8,et)])),p(ie,{modelValue:s.value,"onUpdate:modelValue":t[1]||=e=>s.value=e},{default:x(()=>[o.value?(l(),b(`img`,{key:0,src:o.value,alt:``,class:`image-lightbox-img`,onClick:t[0]||=e=>s.value=!1},null,8,tt)):h(``,!0)]),_:1},8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-7687eb7e`]]),rt=[`data-event-ids`],it={class:`turn-header`},at={key:0,class:`turn-time`},ot={class:`turn-time turn-time-updated`},st={key:2,class:`turn-actions`},ct={class:`turn-body`},lt={key:0,class:`turn-scroll-top`},ut=H(w({__name:`TurnCard`,props:{turn:{},highlighted:{type:Boolean}},emits:[`scrollTo`],setup(e,{emit:o}){let s=e,c=o,{t:u}=I(),d=a(null);function f(){let e=d.value;if(!e)return;let t=e.closest(`.q-scrollarea`)?.querySelector(`.q-scrollarea__content`);if(!t){e.scrollIntoView({behavior:`smooth`,block:`start`});return}let n=e.getBoundingClientRect().top-t.getBoundingClientRect().top;c(`scrollTo`,Math.max(0,n-8))}let _=y(()=>{switch(s.turn.speaker){case`user`:return{label:u(`chat.you`),accent:`var(--kobo-turn-user)`,badgeClass:`turn-badge-user`};case`agent`:return{label:u(`chat.agent`),accent:`var(--kobo-turn-agent)`,badgeClass:`turn-badge-agent`};case`system-prompt`:return{label:u(`chat.systemPrompt`),accent:`var(--kobo-text-3)`,badgeClass:`turn-badge-system`};case`session`:return{label:u(`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:N(t)?u(`chat.hookScript`,{event:t.slice(5)}):u(t===`archive`?`chat.archiveScript`:t===`setup`?`chat.setupScript`:`chat.cleanupScript`),accent:`var(--kobo-success)`,badgeClass:`turn-badge-script`}}}});function v(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 w=y(()=>v(s.turn.ts)),E=y(()=>s.turn.items.flatMap(e=>e.eventIds??[]).join(` `)),D=y(()=>{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}),O=y(()=>{let e=s.turn.ts,t=D.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?``:v(t,r-n<6e4)}),A=y(()=>O.value!==``),j=y(()=>s.turn.items.filter(e=>e.type===`tool`).length);return(a,o)=>(l(),b(`div`,{ref_key:`cardEl`,ref:d,class:r([`turn-card`,{"turn-card--user":e.turn.speaker===`user`,"turn-card--highlighted":e.highlighted}]),"data-event-ids":E.value,style:t({"--turn-accent":_.value.accent})},[C(`div`,it,[C(`span`,{class:r([`turn-badge`,_.value.badgeClass])},i(_.value.label),3),w.value?(l(),b(`span`,at,i(w.value),1)):h(``,!0),A.value?(l(),b(S,{key:1},[p(k,{name:`arrow_forward`,size:`10px`,color:`kobo-3`,class:`turn-time-arrow`}),C(`span`,ot,[g(i(O.value)+` `,1),p(U,null,{default:x(()=>[g(i(n(u)(`chat.lastUpdatedAt`,{time:O.value})),1)]),_:1})])],64)):h(``,!0),j.value>0?(l(),b(`span`,st,` · `+i(n(u)(`chat.nActions`,{n:j.value})),1)):h(``,!0)]),C(`div`,ct,[(l(!0),b(S,null,T(e.turn.items,e=>(l(),b(S,{key:n(Ee)(e)},[e.type===`text`?(l(),m(Le,{key:0,item:e},null,8,[`item`])):e.type===`thinking`?(l(),m(G,{key:1,item:e},null,8,[`item`])):e.type===`tool`?(l(),m(Ze,{key:2,item:e},null,8,[`item`])):e.type===`user`?(l(),m(nt,{key:3,item:e},null,8,[`item`])):e.type===`session`?(l(),m(Y,{key:4,item:e},null,8,[`item`])):e.type===`error`?(l(),m(J,{key:5,item:e},null,8,[`item`])):h(``,!0)],64))),128))]),e.turn.items.length>4?(l(),b(`div`,lt,[p(ee,{flat:``,round:``,dense:``,size:`xs`,icon:`arrow_upward`,color:`kobo-3`,class:`turn-scroll-top-btn`,onClick:f},{default:x(()=>[p(U,null,{default:x(()=>[g(i(n(u)(`chat.scrollToTurnTop`)),1)]),_:1})]),_:1})])):h(``,!0)],14,rt))}}),[[`__scopeId`,`data-v-6e61835e`]]),dt={key:0,class:`activity-feed-switching`},ft={key:1,class:`activity-feed-wrap`,"data-tour":`ws-chat`},pt=[`aria-label`],mt={key:0,class:`activity-feed-compacting`},ht={class:`text-caption text-kobo-2`},gt={key:0,class:`text-center q-py-sm text-caption text-kobo-3`},_t={key:1,class:`activity-feed-empty q-pa-md`},vt={class:`activity-feed-empty__title`},yt={class:`activity-feed-empty__hint`},bt={key:2,class:`q-px-md q-pb-md`},xt={class:`activity-feed-nav-cluster`},St=300,Ct=60,wt=200,Tt=200,Et=400,Dt=200,Ot=180,kt=1200,At=H(w({__name:`ActivityFeed`,props:{workspaceId:{}},setup(e){let{t}=I(),r=e,o=ne(),u=se(),_=oe(),v=y(()=>o.isCompacting(r.workspaceId)),w=y(()=>_.selectedSessionId),E=y(()=>_.sessions.find(e=>e.id===w.value)?.engineSessionId??null),D=y(()=>{let e=_.sessions;return e.length!==0&&w.value===e[e.length-1].id});function A(e){return w.value?e?e===w.value||e===E.value:D.value:!0}let j=y(()=>(_.activityFeeds[r.workspaceId]??[]).filter(e=>e.type===`text`&&typeof e.content==`string`&&A(e.sessionId)).map(e=>({content:e.content,sender:e.meta?.sender??`user`,ts:e.timestamp,sessionId:e.sessionId,eventIds:[e.id]}))),te=y(()=>{let e=_.workspaces.find(e=>e.id===r.workspaceId);return ae(e?.status)}),N=ye(),re=``,P=y(()=>{let e=o.eventsFor(r.workspaceId),t=o.timestampsFor(r.workspaceId),n=o.sessionIdsFor(r.workspaceId),i=o.eventIdsFor(r.workspaceId),a=[],s=[],c=[];for(let r=0;r<e.length;r++)A(n[r])&&(a.push(e[r]),s.push(t[r]),c.push(i[r]??null));let l=`${r.workspaceId}::${w.value??`*`}`;l!==re&&(N=ye(),re=l);let d=_e(N,a,s,te.value,c);return Te(ve(d,j.value).filter(e=>e.type===`thinking`?!1:e.type===`session`?e.kind===`ended`?u.showVerboseSystemMessages||!ge(e.detail):u.showVerboseSystemMessages:!0))}),F=y(()=>u.showVerboseSystemMessages?o.eventsFor(r.workspaceId).filter(e=>e.kind===`message:raw`).map(e=>e.content):[]),ie=y(()=>{for(let e=P.value.length-1;e>=0;e--){let n=P.value[e]?.items??[];for(let e=n.length-1;e>=0;e--){let r=n[e];if(r){if(r.type===`text`&&!r.streaming)return{key:`text:${r.messageId}`,text:r.text};if(r.type===`tool`)return r.result?{key:`tool:${r.toolCallId}:end`,text:r.result.isError?t(`activity.a11y.toolFailed`,{name:r.name}):t(`activity.a11y.toolFinished`,{name:r.name})}:{key:`tool:${r.toolCallId}:start`,text:t(`activity.a11y.toolStarted`,{name:r.name})}}}}return null}),le=a(``);c(ie,(e,n)=>{if(!e||e.key===n?.key)return;let r=e.key.startsWith(`text:`)?t(`activity.a11y.agentSaid`,{text:e.text.slice(0,St)}):e.text;le.value=r});let L=a(null),R=a(!0),z=a(!1),B=a(null),V=!1,H=a(!0),U=a(new Map);function fe(e){let t=e.verticalSize-e.verticalPosition-e.verticalContainerSize;R.value=t<=Ct,V&&e.verticalPosition<=wt&&!z.value&&pe()&&be()}function W(e,t){return`${e}:${t}`}function pe(){let e=w.value;return e?U.value.get(W(r.workspaceId,e))??!0:o.hasMoreOlderFor(r.workspaceId)}function me(e,t,n){U.value.set(W(e,t),n)}function he(e){if(!w.value)return o.oldestIdFor(e);let t=o.eventIdsFor(e),n=o.sessionIdsFor(e);for(let e=0;e<t.length;e++){if(!A(n[e]))continue;let r=t[e];if(r)return r}}let G=null;function be(){return G||(G=xe().finally(()=>{G=null}),G)}async function xe(){let e=r.workspaceId,t=w.value,n=he(e);if(!n)return;z.value=!0;let i=Date.now();try{let r=L.value;await d();let i=r?.getScroll().verticalSize??0,a=r?.getScroll().verticalPosition??0,s=new URLSearchParams({before:n,limit:`200`});t&&s.set(`session`,t);let c=fetch(`/api/workspaces/${e}/events?${s.toString()}`),l=new Promise(e=>setTimeout(e,Tt)),[u]=await Promise.all([c,l]);if(!u.ok){t?me(e,t,!1):o.prepend(e,[],[],{oldestId:n,hasMoreOlder:!1});return}let f=await u.json(),p=f.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),v=m.map(e=>e.createdAt),y=m.map(e=>e.sessionId??null),b=m.map(e=>e.id),x=p.length>0?p[0].id:n;t&&me(e,t,f.hasMore),o.prepend(e,g,v,{oldestId:x,hasMoreOlder:t?o.hasMoreOlderFor(e):f.hasMore,sessionIds:y,eventIds:b});for(let t of h){let n=t.payload;typeof n.content==`string`&&_.addActivityItem(e,{id:t.id,type:`text`,content:n.content,timestamp:t.createdAt,sessionId:t.sessionId??void 0,meta:{sender:n.sender??`user`}})}if(await d(),r){let e=r.getScroll().verticalSize-i;if(e>0){let t=Math.max(a+e,250);r.setScrollPosition(`vertical`,t,0)}}}catch(e){console.error(`[ActivityFeed] failed to load older events:`,e)}finally{let e=Date.now()-i,t=Math.max(0,Tt-e);await new Promise(e=>setTimeout(e,t+Et)),z.value=!1}}async function K(e=0){await d();let t=L.value;if(!t)return;let n=t.getScroll();t.setScrollPosition(`vertical`,n.verticalSize,e)}let q=null,Ce=0;function we(){if(q!=null)return;let e=performance.now()-Ce<Ot;q=requestAnimationFrame(()=>{q=null,Ce=performance.now(),K(e?0:180)})}function Ee(e){let t=L.value;t&&t.setScrollPosition(`vertical`,Math.max(0,e),250)}function Ae(){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 je(e){let t=e.detail;if(t?.workspaceId===r.workspaceId&&t.eventId)try{let e=new URLSearchParams({around:t.eventId,limit:`200`});t.sessionId&&e.set(`session`,t.sessionId);let n=await fetch(`/api/workspaces/${r.workspaceId}/events?${e}`);if(!n.ok)return;let i=await n.json(),a=i.events??[],s=a.filter(e=>e.type===`agent:event`&&e.workspaceId===r.workspaceId),c=a.filter(e=>e.type===`user:message`&&e.workspaceId===r.workspaceId);o.reset(r.workspaceId,s.map(e=>e.payload),s.map(e=>e.createdAt),{oldestId:a[0]?.id,hasMoreOlder:i.hasMore??!1,sessionIds:s.map(e=>e.sessionId),eventIds:s.map(e=>e.id)});for(let e of c){let t=e.payload;typeof t.content==`string`&&_.addActivityItem(r.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`}})}await ke(H,e=>!e,5e3),await d(),await new Promise(e=>requestAnimationFrame(()=>requestAnimationFrame(()=>e())));let l=P.value.findIndex(e=>e.items.some(e=>e.eventIds?.includes(t.eventId)??!1));if(l<0)return;B.value=t.eventId,Me.value?.scrollTo(l,`center`),J.value=l,window.setTimeout(()=>{B.value===t.eventId&&(B.value=null)},1800)}catch(e){console.error(`[ActivityFeed] failed to focus history event:`,e)}}let Me=a(null),Ne=a(null),J=a(0);function Pe(e){J.value=e.index}let Y=a(!1);async function Fe(){if(Y.value)return;Y.value=!0;let e=r.workspaceId;try{let t=Oe(P.value,J.value);if(t<0)for(let n=0;n<15;n++){if(e!==r.workspaceId)return;if(!pe())break;let n=P.value.length;if(await be(),await d(),e!==r.workspaceId)return;if(J.value+=P.value.length-n,t=Oe(P.value,J.value),t>=0)break}t>=0&&e===r.workspaceId&&(Me.value?.scrollTo(t,`start`),J.value=t)}finally{Y.value=!1}}async function X(){V=!1,await d(),await K(0),await new Promise(e=>requestAnimationFrame(()=>requestAnimationFrame(()=>e()))),await K(0),V=!0}let Z=y(()=>{let e=o.sessionIdsFor(r.workspaceId);if(!w.value)return e.length;let t=0;for(let n of e)A(n)&&t++;return t}),Ie=y(()=>o.eventsFor(r.workspaceId).length);async function Le(){H.value=!0;let e=Date.now();await new Promise(e=>setTimeout(e,Dt));let t=Math.max(0,e+kt-Date.now());await ke(Ie,e=>e>0,t),H.value=!1}c(H,async e=>{!e&&Z.value>0&&await X(),!e&&Z.value===0&&w.value&&ze(),e||d(()=>{Ne.value=L.value?.getScrollTarget()??null})}),f(()=>{window.addEventListener(`kobo:focus-history-event`,je),d(()=>{Ne.value=L.value?.getScrollTarget()??null}),Le(),Z.value>0&&X(),w.value&&ze();let e=new URLSearchParams(window.location.hash.split(`?`)[1]??``).get(`eventId`);e&&(je(new CustomEvent(`kobo:focus-history-event`,{detail:{workspaceId:r.workspaceId,sessionId:w.value,eventId:e}})),Ae())});let Q=Z.value>0;c(Z,async(e,t)=>{if(!z.value){if(!Q&&e>0){Q=!0,await X();return}e>t&&R.value&&!z.value&&we()}}),s(()=>{window.removeEventListener(`kobo:focus-history-event`,je),q!=null&&(cancelAnimationFrame(q),q=null)}),c(()=>r.workspaceId,()=>{R.value=!0,Q=Z.value>0,V=!1,Le(),Z.value>0&&X()}),c(()=>_.selectedSessionId,async()=>{R.value=!0,V=!1,await X(),ze()});let Re=new Set;async function ze(){let e=w.value;if(!e||Z.value>0)return;let t=W(r.workspaceId,e);if(!Re.has(t)){Re.add(t);try{let t=await fetch(`/api/workspaces/${r.workspaceId}/events?session=${encodeURIComponent(e)}&limit=500`);if(!t.ok)return;let n=await t.json(),i=n.events??[];if(i.length===0)return;let a=i.filter(e=>e.type===`agent:event`&&e.workspaceId===r.workspaceId),s=i.filter(e=>e.type===`user:message`&&e.workspaceId===r.workspaceId),c=a.map(e=>e.payload),l=a.map(e=>e.createdAt),u=a.map(e=>e.sessionId??null),f=a.map(e=>e.id);me(r.workspaceId,e,n.hasMore),c.length>0&&o.prepend(r.workspaceId,c,l,{oldestId:i[0].id,hasMoreOlder:o.hasMoreOlderFor(r.workspaceId),sessionIds:u,eventIds:f});for(let e of s){let t=e.payload;typeof t.content==`string`&&_.addActivityItem(r.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`}})}await d(),await K(0)}catch(e){console.error(`[ActivityFeed] fetchSessionIfMissing failed:`,e),Re.delete(t)}}}let Be=y(()=>j.value.filter(e=>e.sender!==`system-prompt`).length);c(Be,async(e,t)=>{e>t&&(R.value=!0,await K(180))});async function $(){R.value=!0,await K(250)}return(e,t)=>H.value?(l(),b(`div`,dt,[p(ce,{size:`40px`,color:`primary`})])):(l(),b(`div`,ft,[C(`div`,{"data-testid":`activity-live-region`,class:`sr-only`,role:`log`,"aria-live":`polite`,"aria-atomic":`true`,"aria-label":e.$t(`activity.a11y.region`)},i(le.value),9,pt),p(O,{name:`fade`},{default:x(()=>[v.value?(l(),b(`div`,mt,[p(ce,{size:`18px`,color:`primary`}),C(`span`,ht,i(e.$t(`activity.compacting`)),1)])):h(``,!0)]),_:1}),p(de,{ref_key:`scrollRef`,ref:L,class:`activity-feed-scroll`,onScroll:fe},{default:x(()=>[z.value?(l(),b(`div`,gt,[p(M,{size:`sm`}),g(` `+i(e.$t(`activity.loading_older`)),1)])):h(``,!0),p(Se,{ref_key:`virtualScrollRef`,ref:Me,class:`q-pa-md`,items:P.value,"scroll-target":Ne.value??void 0,"virtual-scroll-item-size":160,"virtual-scroll-slice-size":20,onVirtualScroll:Pe},{default:x(({item:e,index:t})=>[(l(),m(ut,{key:n(De)(e),turn:e,"data-turn-index":t,highlighted:e.items.some(e=>e.eventIds?.includes(B.value??``)??!1),onScrollTo:Ee},null,8,[`turn`,`data-turn-index`,`highlighted`]))]),_:1},8,[`items`,`scroll-target`]),P.value.length===0&&F.value.length===0&&!z.value?(l(),b(`div`,_t,[p(k,{name:`forum`,size:`28px`}),C(`div`,vt,i(e.$t(`activity.empty`)),1),C(`div`,yt,i(e.$t(`activity.emptyHint`)),1)])):h(``,!0),F.value.length?(l(),b(`div`,bt,[p(ue,{label:e.$t(`activity.raw_lines`,{n:F.value.length}),dense:``},{default:x(()=>[(l(!0),b(S,null,T(F.value,(e,t)=>(l(),b(`div`,{key:t,class:`text-caption text-kobo-3 q-pa-xs`},i(e),1))),128))]),_:1},8,[`label`])])):h(``,!0)]),_:1},512),C(`div`,xt,[R.value?h(``,!0):(l(),m(ee,{key:0,round:``,dense:``,unelevated:``,color:`kobo-surface-2`,"text-color":`kobo-1`,icon:`arrow_downward`,size:`sm`,class:`activity-feed-nav-btn`,title:e.$t(`activity.scroll_to_bottom`),"aria-label":e.$t(`activity.scroll_to_bottom`),onClick:$},null,8,[`title`,`aria-label`])),p(ee,{round:``,dense:``,unelevated:``,color:`kobo-surface-2`,"text-color":`kobo-1`,icon:`arrow_upward`,size:`sm`,class:`activity-feed-nav-btn`,title:e.$t(`activity.prev_user_message`),"aria-label":e.$t(`activity.prev_user_message`),loading:Y.value,disable:Y.value,onClick:Fe},null,8,[`title`,`aria-label`,`loading`,`disable`])])]))}}),[[`__scopeId`,`data-v-01cd9f2a`]]);export{At as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.changelog-notes[data-v-6137cb7c]{color:var(--kobo-text-2);font-size:13px;line-height:1.55}.changelog-notes[data-v-6137cb7c] h3{color:var(--kobo-text);margin:.8em 0 .3em;font-size:14px;font-weight:600}.changelog-notes[data-v-6137cb7c] ul{margin:0;padding-left:1.2em}.changelog-notes[data-v-6137cb7c] li{margin:.2em 0}.changelog-notes[data-v-6137cb7c] code{background:#00000040;border-radius:3px;padding:.1em .3em;font-size:12px}.changelog-notes[data-v-6137cb7c] a{color:var(--kobo-text-2)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e,ut as t,v as n}from"./reactivity.esm-bundler-DEJj9cFv.js";import{L as r,P as i,_ as a,d as o,f as s,p as c,q as l,r as u,u as d,y as f,z as p}from"./runtime-core.esm-bundler-CS0xkoG_.js";import{t as m}from"./QBtn-DqZryKOh.js";import{en as h,n as g,nn as _}from"./index-DztjpQfb.js";import{a as v,i as y,n as b}from"./use-tours-BEdbVcQS.js";import{n as x}from"./render-chat-markdown-nZGk_TRQ.js";import{t as S}from"./QChip-CJ6WmvGE.js";import{n as C,t as w}from"./TourReplayButton-DU2PItj-.js";import{t as T}from"./DrawerToggleButton-0fKZjElk.js";var E={class:`row items-center q-mb-md`},D={class:`text-h6 q-ml-sm`},O={key:0,class:`text-kobo-3 text-center q-pa-lg`},k={key:1,class:`text-negative text-center q-pa-lg`},A={key:2,class:`text-kobo-3 text-center q-pa-lg`},j={key:3,class:`column q-gutter-md`,"data-tour":`changelog-list`},M={key:0,class:`text-caption text-kobo-3`},N={class:`row items-center q-mb-sm`},P={class:`text-subtitle1 text-kobo-2`,style:{"font-family":`var(--kobo-font-mono, monospace)`}},F=[`innerHTML`],I=v(f({__name:`ChangelogPage`,setup(f){let v=g(),{scheduleAutoRun:I}=b(),L=n([]),R=n(``),z=n(!1),B=n(null);function V(e){return x(e)}async function H(){z.value=!0,B.value=null;try{let e=await fetch(`/api/changelog`);if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();R.value=t.currentVersion??``,L.value=t.versions??[]}catch(e){B.value=e instanceof Error?e.message:String(e)}finally{z.value=!1}}return i(()=>{H(),I(`changelog`)}),(n,i)=>(r(),o(C,{class:`q-pa-md`,style:{"max-width":`900px`,margin:`0 auto`}},{default:l(()=>[d(`div`,E,[a(T,{class:`q-mr-xs`}),a(m,{flat:``,dense:``,round:``,icon:`arrow_back`,onClick:i[0]||=t=>e(v).back()}),d(`div`,D,t(n.$t(`changelog.title`)),1),a(y),a(m,{flat:``,dense:``,icon:`refresh`,loading:z.value,label:n.$t(`common.refresh`),onClick:H},null,8,[`loading`,`label`]),a(w,{"tour-id":`changelog`,class:`q-ml-xs`})]),z.value&&L.value.length===0?(r(),c(`div`,O,t(n.$t(`common.loading`)),1)):B.value?(r(),c(`div`,k,t(B.value),1)):L.value.length===0?(r(),c(`div`,A,t(n.$t(`changelog.empty`)),1)):(r(),c(`div`,j,[R.value?(r(),c(`div`,M,t(n.$t(`changelog.currentVersion`,{version:R.value})),1)):s(``,!0),(r(!0),c(u,null,p(L.value,e=>(r(),o(h,{key:e.version,dark:``,flat:``,bordered:``},{default:l(()=>[a(_,null,{default:l(()=>[d(`div`,N,[d(`div`,P,` v`+t(e.version),1),e.version===R.value?(r(),o(S,{key:0,dense:``,size:`sm`,color:`primary`,"text-color":`kobo-1`,label:n.$t(`changelog.current`),class:`q-ml-sm`},null,8,[`label`])):s(``,!0)]),d(`div`,{class:`changelog-notes`,innerHTML:V(e.notes)},null,8,F)]),_:2},1024)]),_:2},1024))),128))]))]),_:1}))}}),[[`__scopeId`,`data-v-6137cb7c`]]);export{I as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{V as e,nt as t}from"./QBtn-DqZryKOh.js";import{Ht as n,Ut as r}from"./index-DztjpQfb.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=r(t);a!==void 0&&n(a,e,i)},0)}function o(t){e(t,13)&&a(t)}var s=t({name:`close-popup`,beforeMount(e,{value:t}){e.__qclosepopup=i(t),e.addEventListener(`click`,a),e.addEventListener(`keyup`,o)},updated(e,{value:t,oldValue:n}){t!==n&&e.__qclosepopup!==void 0&&(e.__qclosepopup=i(t))},beforeUnmount(e){e.__qclosepopup!==void 0&&(e.removeEventListener(`click`,a),e.removeEventListener(`keyup`,o),e.__qclosepopup=void 0)}});export{s as t};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{ot as e,ut as t,v as n}from"./reactivity.esm-bundler-DEJj9cFv.js";import{K as r,L as i,P as ee,_ as a,d as o,f as s,g as te,l as ne,p as c,q as l,r as u,u as d,y as f,z as re}from"./runtime-core.esm-bundler-CS0xkoG_.js";import{t as p}from"./QBtn-DqZryKOh.js";import{n as ie,p as ae,vt as oe}from"./index-DztjpQfb.js";import{t as se}from"./QMarkupTable-MxPL53nz.js";import{a as m,i as h}from"./use-tours-BEdbVcQS.js";var g=[`workspace`,`engine`,`model`,`status`,`branch`,`tasks_done`,`tasks_total`,`commits`,`files_changed`,`insertions`,`deletions`,`agent_messages`,`user_messages`,`injected_prompts`,`questions`,`tool_calls`,`errors`,`input_tokens`,`output_tokens`,`sessions`,`duration_seconds`];function _(e){if(e==null)return``;let t=String(e);return/[",\r\n]/.test(t)?`"${t.replace(/"/g,`""`)}"`:t}function v(e){let t=e.map(e=>{let t=e.gitStats,n=e.activity;return[e.workspace.name,e.workspace.engine,e.workspace.model,e.workspace.status,e.workspace.workingBranch,e.tasks.done,e.tasks.total,t?.commitCount??null,t?.filesChanged??null,t?.insertions??null,t?.deletions??null,n.agentMessages,n.userMessages,n.injectedPrompts,n.questions,n.toolCalls,n.errors,n.inputTokens,n.outputTokens,n.sessions,Math.round(n.durationMs/1e3)].map(_).join(`,`)});return`${[g.join(`,`),...t].join(`\r
|
|
2
|
+
`)}`}var y={key:0,class:`comparison-panel q-pa-md`},b={class:`row items-center q-mb-sm`},x={class:`text-subtitle2`},S={class:`text-caption text-kobo-3 q-mb-sm`},C={class:`text-left`},w={class:`text-left`},T={class:`text-right`},E={class:`text-right`},D={class:`text-right`},O={class:`text-right`},k={class:`text-right`},A={class:`text-right`},j={class:`text-right`},M={class:`text-right`},N={class:`text-right`},P={class:`text-right`},F={class:`text-right`},I={class:`text-caption text-kobo-3 comparison-mono`},L={key:0,class:`text-caption text-kobo-3`},R={class:`text-right comparison-mono`},z={class:`text-right`},B={class:`text-right`},V={class:`text-right`},ce={key:0,class:`comparison-mono`},H={class:`text-kobo-success`},U={class:`text-kobo-danger q-ml-xs`},W={key:1,class:`text-kobo-3`},G={class:`text-right comparison-mono`},le=[`title`],ue={class:`text-right`},de={class:`text-right`},fe={class:`text-right comparison-mono`},pe=[`title`],me={class:`text-right`},he={class:`text-right comparison-mono`},ge={class:`text-right`},_e={key:1,class:`text-caption text-kobo-3`},ve={key:0,class:`text-caption text-kobo-warning q-mt-sm`},K=m(f({__name:`ComparisonPanel`,props:{workspaceId:{}},setup(f){let m=f;function g(e){return e<1e3?String(e):e<1e6?`${(e/1e3).toFixed(+(e<1e4))}k`:`${(e/1e6).toFixed(1)}M`}function _(e){if(e<=0)return`-`;let t=Math.round(e/1e3);if(t<60)return q(`reliability.durationSeconds`,{s:t});let n=Math.floor(t/60);return n<60?q(`reliability.durationMinutes`,{m:n,s:t%60}):q(`reliability.durationHours`,{h:Math.floor(n/60),m:n%60})}let K=ie(),ye=ae(),{t:q}=oe(),J=n([]),Y=n(!1),be={created:`workspaceStatus.created`,extracting:`workspaceStatus.extracting`,brainstorming:`workspaceStatus.brainstorming`,executing:`workspaceStatus.executing`,"awaiting-user":`workspaceStatus.awaitingUser`,completed:`workspaceStatus.completed`,idle:`workspaceStatus.idle`,error:`workspaceStatus.error`,quota:`workspaceStatus.quota`,retrying:`workspaceStatus.retrying`},X=n({});function xe(e){return X.value[e]??e}async function Se(){try{let e=await fetch(`/api/engines`);if(!e.ok)return;let t=await e.json();X.value=Object.fromEntries(t.map(e=>[e.id,e.displayName]))}catch{}}function Z(e){let t=be[e];return t?q(t):e}let Ce=ne(()=>m.workspaceId);function Q(e){return e.workspace.id===Ce.value}function we(e){ye.selectWorkspace(e),K.push({name:`workspace`,params:{id:e}})}function Te(){let e=v(J.value),t=new Blob([e],{type:`text/csv;charset=utf-8`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`kobo-comparison-${J.value[0]?.workspace.comparisonId??`comparison`}.csv`,r.click(),URL.revokeObjectURL(n)}async function $(){Y.value=!0;try{let e=await fetch(`/api/workspaces/${m.workspaceId}/comparison`);if(!e.ok){J.value=[];return}let t=await e.json();J.value=t.members??[]}catch{J.value=[]}finally{Y.value=!1}}return ee(()=>{Se(),$()}),r(()=>m.workspaceId,$),(n,r)=>J.value.length>0?(i(),c(`div`,y,[d(`div`,b,[d(`div`,x,t(n.$t(`comparison.title`)),1),a(h),a(p,{flat:``,dense:``,round:``,size:`sm`,icon:`download`,title:n.$t(`comparison.exportCsv`),onClick:Te},null,8,[`title`]),a(p,{flat:``,dense:``,round:``,size:`sm`,icon:`refresh`,loading:Y.value,onClick:$},null,8,[`loading`])]),d(`div`,S,t(n.$t(`comparison.hint`)),1),a(se,{flat:``,dense:``,dark:``,class:`comparison-table`},{default:l(()=>[d(`thead`,null,[d(`tr`,null,[d(`th`,C,t(n.$t(`comparison.engine`)),1),d(`th`,w,t(n.$t(`comparison.status`)),1),d(`th`,T,t(n.$t(`comparison.tasks`)),1),d(`th`,E,t(n.$t(`comparison.commits`)),1),d(`th`,D,t(n.$t(`comparison.files`)),1),d(`th`,O,t(n.$t(`comparison.diff`)),1),d(`th`,k,t(n.$t(`comparison.messages`)),1),d(`th`,A,t(n.$t(`comparison.questions`)),1),d(`th`,j,t(n.$t(`comparison.tools`)),1),d(`th`,M,t(n.$t(`comparison.errors`)),1),d(`th`,N,t(n.$t(`comparison.tokens`)),1),d(`th`,P,t(n.$t(`comparison.sessions`)),1),d(`th`,F,t(n.$t(`comparison.duration`)),1),r[0]||=d(`th`,null,null,-1)])]),d(`tbody`,null,[(i(!0),c(u,null,re(J.value,r=>(i(),c(`tr`,{key:r.workspace.id,class:e({"comparison-current":Q(r)})},[d(`td`,null,[d(`div`,null,t(xe(r.workspace.engine)),1),d(`div`,I,t(r.workspace.model),1)]),d(`td`,null,[te(t(Z(r.workspace.status))+` `,1),r.workspace.archivedAt?(i(),c(`span`,L,` · `+t(n.$t(`comparison.archived`)),1)):s(``,!0)]),d(`td`,R,t(r.tasks.done)+`/`+t(r.tasks.total),1),d(`td`,z,t(r.gitStats?.commitCount??`-`),1),d(`td`,B,t(r.gitStats?.filesChanged??`-`),1),d(`td`,V,[r.gitStats?(i(),c(`span`,ce,[d(`span`,H,`+`+t(r.gitStats.insertions),1),d(`span`,U,`-`+t(r.gitStats.deletions),1)])):(i(),c(`span`,W,`-`))]),d(`td`,G,[d(`span`,{title:n.$t(`comparison.messagesTitle`)},t(r.activity.agentMessages)+` / `+t(r.activity.userMessages),9,le)]),d(`td`,ue,t(r.activity.questions),1),d(`td`,de,t(r.activity.toolCalls),1),d(`td`,{class:e([`text-right`,r.activity.errors>0?`text-kobo-danger`:``])},t(r.activity.errors),3),d(`td`,fe,[d(`span`,{title:n.$t(`comparison.tokensTitle`)},t(g(r.activity.inputTokens))+` / `+t(g(r.activity.outputTokens)),9,pe)]),d(`td`,me,t(r.activity.sessions),1),d(`td`,he,t(_(r.activity.durationMs)),1),d(`td`,ge,[Q(r)?(i(),c(`span`,_e,t(n.$t(`comparison.current`)),1)):(i(),o(p,{key:0,flat:``,dense:``,"no-caps":``,size:`sm`,label:n.$t(`comparison.open`),onClick:e=>we(r.workspace.id)},null,8,[`label`,`onClick`]))])],2))),128))])]),_:1}),J.value.length<2?(i(),c(`div`,ve,t(n.$t(`comparison.incomplete`)),1)):s(``,!0)])):s(``,!0)}}),[[`__scopeId`,`data-v-95e8c6b5`]]);export{K as default};
|