@loicngr/kobo 1.11.29 → 1.11.31
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 +12 -1
- package/CHANGELOG.md +9 -0
- package/dist/server/index.js +2 -0
- package/dist/server/routes/workspace-templates.js +69 -0
- package/dist/server/routes/workspaces.js +16 -0
- package/dist/server/services/settings-defaults.js +10 -0
- package/dist/server/services/settings-service.js +20 -2
- package/dist/server/services/workspace-template-service.js +201 -0
- package/dist/server/utils/paths.js +4 -0
- package/dist/shared/codex-models.js +9 -3
- package/package.json +1 -1
- package/src/client/dist/pwa/assets/ActivityFeed-BCol76S5.js +8 -0
- package/src/client/dist/pwa/assets/{ActivityFeed-C6XSxdJ0.css → ActivityFeed-Bakgvay6.css} +1 -1
- package/src/client/dist/pwa/assets/ChangelogPage-DKJkFiU_.css +1 -0
- package/src/client/dist/pwa/assets/ChangelogPage-DoMrJJ63.js +1 -0
- package/src/client/dist/pwa/assets/{ClosePopup-CekolbY5.js → ClosePopup-BCS9Zmcz.js} +1 -1
- package/src/client/dist/pwa/assets/{ComparisonPanel-CsdFl1JL.js → ComparisonPanel-CxxMJ1J0.js} +2 -2
- package/src/client/dist/pwa/assets/CreatePage-50kxfzEj.js +2 -0
- package/src/client/dist/pwa/assets/CreatePage-DZ13xLQW.css +1 -0
- package/src/client/dist/pwa/assets/DashboardPage-DsWn5cWl.css +1 -0
- package/src/client/dist/pwa/assets/DashboardPage-NYpPmHOn.js +1 -0
- package/src/client/dist/pwa/assets/{DiffViewer-CxXPJSsu.js → DiffViewer-CUNiYtb6.js} +4 -4
- package/src/client/dist/pwa/assets/DocumentsPanel-ezV8L7at.js +1 -0
- package/src/client/dist/pwa/assets/DrawerToggleButton-DjG7OouG.js +1 -0
- package/src/client/dist/pwa/assets/GitPanel-CybZSVa0.js +3 -0
- package/src/client/dist/pwa/assets/{GitPanel-DVs5BCU-.css → GitPanel-DhjMYZMq.css} +1 -1
- package/src/client/dist/pwa/assets/HealthPage-CFZ-tdKK.css +1 -0
- package/src/client/dist/pwa/assets/HealthPage-ClDddgmP.js +1 -0
- package/src/client/dist/pwa/assets/{MainLayout-ExB0xYHB.css → MainLayout-BUTz2ks4.css} +1 -1
- package/src/client/dist/pwa/assets/MainLayout-flztOHf_.js +2 -0
- package/src/client/dist/pwa/assets/{QBtnDropdown-VaaGdcMX.js → QBtnDropdown-BEnM7WGO.js} +1 -1
- package/src/client/dist/pwa/assets/QDrawer-Bn8KqLJR.js +1 -0
- package/src/client/dist/pwa/assets/SchedulePanel-BcbLXsgt.js +1 -0
- package/src/client/dist/pwa/assets/SearchPage-B2TBhpc7.js +1 -0
- package/src/client/dist/pwa/assets/SearchPage-CVgRa025.css +1 -0
- package/src/client/dist/pwa/assets/{SettingsPage-2vdOZu1C.css → SettingsPage-CDA54yPx.css} +1 -1
- package/src/client/dist/pwa/assets/SettingsPage-CEeU5wHr.js +10 -0
- package/src/client/dist/pwa/assets/{TerminalPanel-Io_WshA3.js → TerminalPanel-CUbhouGK.js} +10 -10
- package/src/client/dist/pwa/assets/TouchPan-DTG8xcJW.js +1 -0
- package/src/client/dist/pwa/assets/TourReplayButton-CdLG2sf6.js +1 -0
- package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-DKEErIht.js +1 -0
- package/src/client/dist/pwa/assets/WorkspacePage-CDpYwmH9.js +4 -0
- package/src/client/dist/pwa/assets/{WorkspacePage-3rwxkeew.css → WorkspacePage-D3-AEaPN.css} +1 -1
- package/src/client/dist/pwa/assets/{build-path-tree-CmeIBsJq.js → build-path-tree-D-NmwzvG.js} +1 -1
- package/src/client/dist/pwa/assets/de-s-OCM5GV.js +17 -0
- package/src/client/dist/pwa/assets/{documents-DuT_pUBs.js → documents-CHf7b-Vo.js} +1 -1
- package/src/client/dist/pwa/assets/{editor.api-B7h7KULV.js → editor.api-CnC2GWxt.js} +1 -1
- package/src/client/dist/pwa/assets/{efforts-CFRBNt5s.js → efforts-DZpgeo-z.js} +1 -1
- package/src/client/dist/pwa/assets/engineFeatures-CAVTTYFB.js +1 -0
- package/src/client/dist/pwa/assets/es-Db2oG1GY.js +17 -0
- package/src/client/dist/pwa/assets/expand-template-Df6JeLIj.js +1 -0
- package/src/client/dist/pwa/assets/{format-klpA_BIb.js → format-Ub88nHdg.js} +1 -1
- package/src/client/dist/pwa/assets/fr-u2YnnwUr.js +17 -0
- package/src/client/dist/pwa/assets/{freemarker2-AB32EM-g.js → freemarker2-6Bw8swVv.js} +1 -1
- package/src/client/dist/pwa/assets/{handlebars-C87HpXgr.js → handlebars-CXP7UvsN.js} +1 -1
- package/src/client/dist/pwa/assets/{html-fZ2Q-EN9.js → html-CiH7-LQ8.js} +1 -1
- package/src/client/dist/pwa/assets/{i18n-jUVcMUna.js → i18n-CINLKqOi.js} +1 -1
- package/src/client/dist/pwa/assets/index-CVfEYP1z.js +18 -0
- package/src/client/dist/pwa/assets/it-BormzXPk.js +17 -0
- package/src/client/dist/pwa/assets/{javascript-DaRn-B3h.js → javascript-aN8WMuyC.js} +1 -1
- package/src/client/dist/pwa/assets/{liquid-BxIQD86X.js → liquid-E1ySUvbU.js} +1 -1
- package/src/client/dist/pwa/assets/{mdx-BB8ir9N_.js → mdx-BZOOfxw4.js} +1 -1
- package/src/client/dist/pwa/assets/{monaco-contributions-B0YHWDBM.js → monaco-contributions-DAArJoqj.js} +1 -1
- package/src/client/dist/pwa/assets/monaco.contribution-BqMfO6zF.js +2 -0
- package/src/client/dist/pwa/assets/{network-auth-0EqcSNjT.js → network-auth-CgMRbbZI.js} +1 -1
- package/src/client/dist/pwa/assets/{notify-theme-CJQIBqdX.js → notify-theme-DDdNd09b.js} +1 -1
- package/src/client/dist/pwa/assets/pending-diff-open-2y1wCUC0.js +1 -0
- package/src/client/dist/pwa/assets/permissionModes-BKhOcXIS.js +36 -0
- package/src/client/dist/pwa/assets/{project-color-CZmTicBX.js → project-color-DGnqx7Qm.js} +1 -1
- package/src/client/dist/pwa/assets/{python-BdCzK6Il.js → python-DLPkE6OM.js} +1 -1
- package/src/client/dist/pwa/assets/{razor-ClnzXrTz.js → razor-Co08h7m7.js} +1 -1
- package/src/client/dist/pwa/assets/{render-chat-markdown-CzR8e-Uh.js → render-chat-markdown-BtqSDXpK.js} +1 -1
- package/src/client/dist/pwa/assets/{typescript-Dk26pRlO.js → typescript-Cr3657Zk.js} +1 -1
- package/src/client/dist/pwa/assets/use-is-mobile-B-DI_sOv.js +1 -0
- package/src/client/dist/pwa/assets/use-tours-DoXhHOdJ.js +2 -0
- package/src/client/dist/pwa/assets/workspace-templates-DAalrm3k.js +1 -0
- package/src/client/dist/pwa/assets/{xml-DdBTQmk2.js → xml-i8zBw4bC.js} +1 -1
- package/src/client/dist/pwa/assets/{yaml-DTv5uGmK.js → yaml-Cc6X0dyF.js} +1 -1
- package/src/client/dist/pwa/index.html +1 -2
- package/src/client/dist/pwa/sw.js +1 -1
- package/src/client/dist/pwa/assets/ActivityFeed-Dm-h5c8M.js +0 -8
- package/src/client/dist/pwa/assets/ChangelogPage-D_WOVByV.css +0 -1
- package/src/client/dist/pwa/assets/ChangelogPage-tLjrU4kh.js +0 -1
- package/src/client/dist/pwa/assets/CreatePage-B1iRRP_d.js +0 -2
- package/src/client/dist/pwa/assets/CreatePage-DeKYK6uC.css +0 -1
- package/src/client/dist/pwa/assets/DashboardPage-BqgK4lAf.css +0 -1
- package/src/client/dist/pwa/assets/DashboardPage-CNTYrE-N.js +0 -1
- package/src/client/dist/pwa/assets/DocumentsPanel-Du7qG8uv.js +0 -1
- package/src/client/dist/pwa/assets/DrawerToggleButton-D0i0wUjb.js +0 -1
- package/src/client/dist/pwa/assets/GitPanel-tuTj7lhu.js +0 -3
- package/src/client/dist/pwa/assets/HealthPage-BbqLoFQj.css +0 -1
- package/src/client/dist/pwa/assets/HealthPage-DL_RBg9X.js +0 -1
- package/src/client/dist/pwa/assets/MainLayout-CuPokl9k.js +0 -2
- 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/SchedulePanel-CyWvfNkF.js +0 -1
- package/src/client/dist/pwa/assets/SearchPage-DdWM01rq.css +0 -1
- package/src/client/dist/pwa/assets/SearchPage-c_MuOKwZ.js +0 -1
- package/src/client/dist/pwa/assets/SettingsPage-QkPo7j0B.js +0 -10
- package/src/client/dist/pwa/assets/TouchPan-DO0Y0lcH.js +0 -1
- package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-NqQsltOl.js +0 -1
- package/src/client/dist/pwa/assets/WorkspacePage-Ct8QYOU_.js +0 -4
- package/src/client/dist/pwa/assets/de-DUTfyzTm.js +0 -17
- package/src/client/dist/pwa/assets/debounce-CDIE7CV6.js +0 -1
- package/src/client/dist/pwa/assets/engineFeatures-DmG1z2N2.js +0 -1
- package/src/client/dist/pwa/assets/es-ft4_w4dQ.js +0 -17
- package/src/client/dist/pwa/assets/expand-template-DXzAXadA.js +0 -1
- package/src/client/dist/pwa/assets/fr-SGSKyQ_T.js +0 -17
- package/src/client/dist/pwa/assets/index-BgV6UXly.js +0 -18
- package/src/client/dist/pwa/assets/it-C5q5LNGX.js +0 -17
- package/src/client/dist/pwa/assets/layout-DdQC-2Sz.js +0 -1
- package/src/client/dist/pwa/assets/monaco.contribution-Nxc5lpNj.js +0 -2
- package/src/client/dist/pwa/assets/pending-diff-open-BTLtsmQt.js +0 -1
- package/src/client/dist/pwa/assets/permissionModes-BR2CNlno.js +0 -36
- package/src/client/dist/pwa/assets/use-onboarding-BwDLVLlc.js +0 -2
- package/src/client/dist/pwa/assets/use-quasar-B2sgdABh.js +0 -1
- /package/src/client/dist/pwa/assets/{use-onboarding-CTZuBZOi.css → use-tours-CTZuBZOi.css} +0 -0
package/AGENTS.md
CHANGED
|
@@ -70,6 +70,7 @@ src/
|
|
|
70
70
|
│ │ ├── settings-defaults.ts # DEFAULT_* constants for opt-in settings (e.g. change-source-branch script)
|
|
71
71
|
│ │ ├── lifecycle-hook-service.ts # user shell hooks on session-ended / pr-merged / autoloop-disabled
|
|
72
72
|
│ │ ├── awaiting-user-reminder-service.ts # reminds about workspaces stuck in `awaiting-user`
|
|
73
|
+
│ │ ├── workspace-template-service.ts # create-form presets (workspace-templates.json) + presetFromWorkspace
|
|
73
74
|
│ │ ├── content-migration-service.ts # runtime legacy ws_events → normalised AgentEvent migration
|
|
74
75
|
│ │ ├── templates-service.ts # prompt templates CRUD (JSON file persistence, seeding)
|
|
75
76
|
│ │ ├── dev-server-service.ts # per-workspace dev server lifecycle (docker or npm process)
|
|
@@ -81,6 +82,7 @@ src/
|
|
|
81
82
|
│ ├── routes/ # Hono handlers, thin layer over services
|
|
82
83
|
│ │ ├── workspaces.ts # /api/workspaces/* — the main surface
|
|
83
84
|
│ │ ├── templates.ts # /api/templates — prompt templates CRUD
|
|
85
|
+
│ │ ├── workspace-templates.ts # /api/workspace-templates - saved create-form presets
|
|
84
86
|
│ │ ├── plans.ts # /api/workspaces/:id/plans — plan file browser (read-only)
|
|
85
87
|
│ │ ├── dev-server.ts, git.ts, notion.ts, settings.ts
|
|
86
88
|
│ ├── utils/
|
|
@@ -89,8 +91,9 @@ src/
|
|
|
89
91
|
├── client/ # Vue 3 + Quasar PWA
|
|
90
92
|
│ └── src/
|
|
91
93
|
│ ├── stores/ # pinia: workspace, websocket, settings, dev-server, templates
|
|
92
|
-
│ ├── components/ # WorkspaceList, NotionPanel, AcceptancePanel, ChatInput, GitPanel, PlansPanel, WorkspaceAttentionLabels…
|
|
94
|
+
│ ├── components/ # WorkspaceList, NotionPanel, AcceptancePanel, ChatInput, GitPanel, PlansPanel, WorkspaceAttentionLabels, HelpMenu…
|
|
93
95
|
│ ├── utils/ # expand-template, formatters, workspace-attention (CI failure / changes-requested derivation)…
|
|
96
|
+
│ ├── tours/ # declarative onboarding tours, one file per zone + registry
|
|
94
97
|
│ ├── pages/ # WorkspacePage, CreatePage, SettingsPage
|
|
95
98
|
│ └── router/
|
|
96
99
|
├── mcp-server/ # standalone MCP server spawned per workspace
|
|
@@ -244,6 +247,14 @@ One task, two engines, two sibling worktrees. `POST /api/workspaces` accepts a `
|
|
|
244
247
|
|
|
245
248
|
`computeDueReminders` holds the interval arithmetic as a near-pure function over an injected `Map<id, {firstSeenAt, remindersSent}>`, so it is unit-tested without a timer or a DB. Two rules it encodes: a workspace that leaves `awaiting-user` is dropped from the map (answering resets the clock), and a tick that finds itself several intervals behind sends **one** reminder, not one per missed interval. State is in-memory only, like the pr-watcher's caches: a restart restarts the clock.
|
|
246
249
|
|
|
250
|
+
### Workspace templates and duplication
|
|
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).
|
|
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
|
+
|
|
247
258
|
### Worktree purge
|
|
248
259
|
|
|
249
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.31
|
|
8
|
+
|
|
9
|
+
- feat(onboarding): per-zone guided tours with a help menu
|
|
10
|
+
|
|
11
|
+
## 1.11.30
|
|
12
|
+
|
|
13
|
+
- feat: workspace templates, duplication and per-engine default models
|
|
14
|
+
- feat(codex): add GPT-6 Astra to the model catalogue
|
|
15
|
+
|
|
7
16
|
## 1.11.29
|
|
8
17
|
|
|
9
18
|
- feat(comparison): task progress, activity stats and CSV export
|
package/dist/server/index.js
CHANGED
|
@@ -26,6 +26,7 @@ import settingsRouter from './routes/settings.js';
|
|
|
26
26
|
import templatesRouter from './routes/templates.js';
|
|
27
27
|
import usageRoutes from './routes/usage.js';
|
|
28
28
|
import voiceRouter from './routes/voice.js';
|
|
29
|
+
import workspaceTemplatesRouter from './routes/workspace-templates.js';
|
|
29
30
|
import workspacesRouter from './routes/workspaces.js';
|
|
30
31
|
import { getAvailableSkills, isAgentUnavailableError, reconcileOrphanSessions, restoreRetryCountsFromDb, sendMessage, setBackendPort, startAgent, startWatchdog, stopAgent, stopAllAgents, stopWatchdog, } from './services/agent/orchestrator.js';
|
|
31
32
|
import * as autoLoopService from './services/auto-loop-service.js';
|
|
@@ -164,6 +165,7 @@ app.route('/api/changelog', changelogRouter);
|
|
|
164
165
|
app.route('/api/settings', settingsRouter);
|
|
165
166
|
app.route('/api/dev-server', devServerRouter);
|
|
166
167
|
app.route('/api/templates', templatesRouter);
|
|
168
|
+
app.route('/api/workspace-templates', workspaceTemplatesRouter);
|
|
167
169
|
app.route('/api/usage', usageRoutes);
|
|
168
170
|
app.route('/api/workspaces', documentsRouter);
|
|
169
171
|
app.route('/api/workspaces', exportRouter);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import * as templates from '../services/workspace-template-service.js';
|
|
3
|
+
/** Saved presets of the create-workspace form. */
|
|
4
|
+
const app = new Hono();
|
|
5
|
+
/** Service errors carry their meaning in the message; everything else is a 500. */
|
|
6
|
+
function statusFor(message) {
|
|
7
|
+
if (message.startsWith('Invalid template name'))
|
|
8
|
+
return 400;
|
|
9
|
+
if (/^Template '.*' already exists$/.test(message))
|
|
10
|
+
return 409;
|
|
11
|
+
if (message.startsWith('Too many templates'))
|
|
12
|
+
return 422;
|
|
13
|
+
return 500;
|
|
14
|
+
}
|
|
15
|
+
app.get('/', (c) => {
|
|
16
|
+
try {
|
|
17
|
+
return c.json({ templates: templates.listWorkspaceTemplates() });
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
21
|
+
return c.json({ error: message }, 500);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
app.post('/', async (c) => {
|
|
25
|
+
try {
|
|
26
|
+
const body = await c.req.json().catch(() => null);
|
|
27
|
+
if (!body || typeof body.name !== 'string')
|
|
28
|
+
return c.json({ error: 'name is required' }, 400);
|
|
29
|
+
const template = templates.createWorkspaceTemplate({ name: body.name, preset: body.preset ?? {} });
|
|
30
|
+
return c.json({ template }, 201);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
34
|
+
return c.json({ error: message }, statusFor(message));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
app.put('/:id', async (c) => {
|
|
38
|
+
try {
|
|
39
|
+
const body = await c.req.json().catch(() => null);
|
|
40
|
+
if (!body)
|
|
41
|
+
return c.json({ error: 'Invalid JSON body' }, 400);
|
|
42
|
+
const updates = {};
|
|
43
|
+
if (typeof body.name === 'string')
|
|
44
|
+
updates.name = body.name;
|
|
45
|
+
if (body.preset !== undefined)
|
|
46
|
+
updates.preset = body.preset;
|
|
47
|
+
const template = templates.updateWorkspaceTemplate(c.req.param('id'), updates);
|
|
48
|
+
if (!template)
|
|
49
|
+
return c.json({ error: `Template '${c.req.param('id')}' not found` }, 404);
|
|
50
|
+
return c.json({ template });
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
54
|
+
return c.json({ error: message }, statusFor(message));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
app.delete('/:id', (c) => {
|
|
58
|
+
try {
|
|
59
|
+
if (!templates.deleteWorkspaceTemplate(c.req.param('id'))) {
|
|
60
|
+
return c.json({ error: `Template '${c.req.param('id')}' not found` }, 404);
|
|
61
|
+
}
|
|
62
|
+
return c.body(null, 204);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
66
|
+
return c.json({ error: message }, 500);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
export default app;
|
|
@@ -38,6 +38,7 @@ import * as wakeupService from '../services/wakeup-service.js';
|
|
|
38
38
|
import * as wsService from '../services/websocket-service.js';
|
|
39
39
|
import * as permissionPolicyService from '../services/workspace-permission-policy-service.js';
|
|
40
40
|
import * as workspaceService from '../services/workspace-service.js';
|
|
41
|
+
import { presetFromWorkspace } from '../services/workspace-template-service.js';
|
|
41
42
|
import * as purgeWorktreeService from '../services/worktree-purge-service.js';
|
|
42
43
|
import * as worktreeService from '../services/worktree-service.js';
|
|
43
44
|
import { resolveUniqueBranchAndPath } from '../utils/branch-resolver.js';
|
|
@@ -1449,6 +1450,21 @@ app.get('/:id/comparison', (c) => {
|
|
|
1449
1450
|
return c.json({ error: message }, 500);
|
|
1450
1451
|
}
|
|
1451
1452
|
});
|
|
1453
|
+
// GET /api/workspaces/:id/preset — the create-form preset this workspace would
|
|
1454
|
+
// have been created from. Read-only: "Duplicate" prefills the form with it.
|
|
1455
|
+
app.get('/:id/preset', (c) => {
|
|
1456
|
+
const id = c.req.param('id');
|
|
1457
|
+
try {
|
|
1458
|
+
const preset = presetFromWorkspace(id);
|
|
1459
|
+
if (!preset)
|
|
1460
|
+
return c.json({ error: `Workspace '${id}' not found` }, 404);
|
|
1461
|
+
return c.json({ preset });
|
|
1462
|
+
}
|
|
1463
|
+
catch (err) {
|
|
1464
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1465
|
+
return c.json({ error: message }, 500);
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1452
1468
|
// POST /api/workspaces/pr-snapshot/refresh/:id — on-demand refresh of a single
|
|
1453
1469
|
// workspace's PR snapshot, driven by the Git tab refresh button. Static prefix
|
|
1454
1470
|
// keeps it ahead of `/:id` in the Hono matcher.
|
|
@@ -75,3 +75,13 @@ export function getSettingsDefaults() {
|
|
|
75
75
|
changeSourceBranchScript: DEFAULT_CHANGE_SOURCE_BRANCH_SCRIPT,
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Model each engine starts on when nothing else is configured. `auto` used to
|
|
80
|
+
* be the seed (let the CLI pick), but a workspace created without thinking
|
|
81
|
+
* about it should land on a known, current model, not on whatever the CLI's own
|
|
82
|
+
* default happens to be that week.
|
|
83
|
+
*/
|
|
84
|
+
export const DEFAULT_MODEL_BY_ENGINE = {
|
|
85
|
+
'claude-code': 'claude-sonnet-5',
|
|
86
|
+
codex: 'gpt-5.6-terra',
|
|
87
|
+
};
|
|
@@ -9,7 +9,7 @@ import { getSettingsPath } from '../utils/paths.js';
|
|
|
9
9
|
import { InvalidWorktreesPathError, resolveGlobalWorktreesRoot, sanitizeWorktreesPath, validateWorktreesPath, } from '../utils/worktree-paths.js';
|
|
10
10
|
import { DEFAULT_NOTION_INITIAL_PROMPT, DEFAULT_SENTRY_INITIAL_PROMPT } from './initial-prompt-template-service.js';
|
|
11
11
|
import { DEFAULT_REVIEW_PROMPT_TEMPLATE } from './review-template-service.js';
|
|
12
|
-
import { DEFAULT_CHANGE_SOURCE_BRANCH_SCRIPT } from './settings-defaults.js';
|
|
12
|
+
import { DEFAULT_CHANGE_SOURCE_BRANCH_SCRIPT, DEFAULT_MODEL_BY_ENGINE } from './settings-defaults.js';
|
|
13
13
|
import { AGNOSTIC_PROMPTS } from './skill-suite-prompts.js';
|
|
14
14
|
export const DEFAULT_GIT_CONVENTIONS = `# Git conventions
|
|
15
15
|
|
|
@@ -883,6 +883,24 @@ const settingsMigrations = [
|
|
|
883
883
|
}
|
|
884
884
|
},
|
|
885
885
|
},
|
|
886
|
+
{
|
|
887
|
+
version: 57,
|
|
888
|
+
name: 'seed-default-model-per-engine',
|
|
889
|
+
migrate: ({ global }) => {
|
|
890
|
+
// Only an engine still on the seeded `auto` (or with no entry) moves to
|
|
891
|
+
// the shipped default; a model the user picked is theirs to keep.
|
|
892
|
+
const existing = global.defaultModelByEngine;
|
|
893
|
+
const map = typeof existing === 'object' && existing !== null && !Array.isArray(existing)
|
|
894
|
+
? existing
|
|
895
|
+
: {};
|
|
896
|
+
for (const [engine, model] of Object.entries(DEFAULT_MODEL_BY_ENGINE)) {
|
|
897
|
+
const current = map[engine];
|
|
898
|
+
if (typeof current !== 'string' || current.length === 0 || current === 'auto')
|
|
899
|
+
map[engine] = model;
|
|
900
|
+
}
|
|
901
|
+
global.defaultModelByEngine = map;
|
|
902
|
+
},
|
|
903
|
+
},
|
|
886
904
|
];
|
|
887
905
|
/** Current settings schema version — always equals the highest migration version. */
|
|
888
906
|
export const SETTINGS_SCHEMA_VERSION = settingsMigrations.length > 0 ? settingsMigrations[settingsMigrations.length - 1].version : 0;
|
|
@@ -912,7 +930,7 @@ function defaultSettings() {
|
|
|
912
930
|
return {
|
|
913
931
|
schemaVersion: SETTINGS_SCHEMA_VERSION,
|
|
914
932
|
global: {
|
|
915
|
-
defaultModelByEngine: {
|
|
933
|
+
defaultModelByEngine: { ...DEFAULT_MODEL_BY_ENGINE },
|
|
916
934
|
dangerouslySkipPermissions: true,
|
|
917
935
|
prPromptTemplate: DEFAULT_PR_PROMPT_TEMPLATE,
|
|
918
936
|
reviewPromptTemplate: DEFAULT_REVIEW_PROMPT_TEMPLATE,
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { nanoid } from 'nanoid';
|
|
4
|
+
import { getDb } from '../db/index.js';
|
|
5
|
+
import { getWorkspaceTemplatesPath } from '../utils/paths.js';
|
|
6
|
+
const FILE_VERSION = 1;
|
|
7
|
+
export const MAX_WORKSPACE_TEMPLATES = 100;
|
|
8
|
+
const MAX_NAME_LENGTH = 80;
|
|
9
|
+
const STRING_KEYS = [
|
|
10
|
+
'projectPath',
|
|
11
|
+
'sourceBranch',
|
|
12
|
+
'branchType',
|
|
13
|
+
'engine',
|
|
14
|
+
'model',
|
|
15
|
+
'reasoningEffort',
|
|
16
|
+
'brainstormModel',
|
|
17
|
+
'brainstormReasoningEffort',
|
|
18
|
+
'description',
|
|
19
|
+
];
|
|
20
|
+
const BOOLEAN_KEYS = ['autoLoop', 'skipSetupScript'];
|
|
21
|
+
const LIST_KEYS = ['tasks', 'acceptanceCriteria'];
|
|
22
|
+
const PERMISSION_MODES = ['plan', 'bypass', 'strict', 'interactive'];
|
|
23
|
+
const SESSION_MODES = ['per_task', 'continuous'];
|
|
24
|
+
/**
|
|
25
|
+
* Keep the known keys that carry the right type, drop everything else. An
|
|
26
|
+
* unknown or malformed field is not a reason to refuse a whole template — a
|
|
27
|
+
* hand-edited file or an older client should degrade to "that field is
|
|
28
|
+
* unset", not to an error.
|
|
29
|
+
*/
|
|
30
|
+
export function sanitizePreset(input) {
|
|
31
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input))
|
|
32
|
+
return {};
|
|
33
|
+
const raw = input;
|
|
34
|
+
const preset = {};
|
|
35
|
+
for (const key of STRING_KEYS) {
|
|
36
|
+
if (typeof raw[key] === 'string')
|
|
37
|
+
preset[key] = raw[key];
|
|
38
|
+
}
|
|
39
|
+
for (const key of BOOLEAN_KEYS) {
|
|
40
|
+
if (typeof raw[key] === 'boolean')
|
|
41
|
+
preset[key] = raw[key];
|
|
42
|
+
}
|
|
43
|
+
for (const key of LIST_KEYS) {
|
|
44
|
+
if (Array.isArray(raw[key]))
|
|
45
|
+
preset[key] = raw[key].filter((v) => typeof v === 'string');
|
|
46
|
+
}
|
|
47
|
+
if (typeof raw.agentPermissionMode === 'string' &&
|
|
48
|
+
PERMISSION_MODES.includes(raw.agentPermissionMode)) {
|
|
49
|
+
preset.agentPermissionMode = raw.agentPermissionMode;
|
|
50
|
+
}
|
|
51
|
+
if (typeof raw.autoLoopSessionMode === 'string' &&
|
|
52
|
+
SESSION_MODES.includes(raw.autoLoopSessionMode)) {
|
|
53
|
+
preset.autoLoopSessionMode = raw.autoLoopSessionMode;
|
|
54
|
+
}
|
|
55
|
+
return preset;
|
|
56
|
+
}
|
|
57
|
+
function normalizeName(name) {
|
|
58
|
+
return name.trim();
|
|
59
|
+
}
|
|
60
|
+
function assertValidName(name) {
|
|
61
|
+
if (name.length === 0 || name.length > MAX_NAME_LENGTH) {
|
|
62
|
+
throw new Error(`Invalid template name: must be 1 to ${MAX_NAME_LENGTH} characters`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function sameName(a, b) {
|
|
66
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
67
|
+
}
|
|
68
|
+
function readFile() {
|
|
69
|
+
const filePath = getWorkspaceTemplatesPath();
|
|
70
|
+
if (!existsSync(filePath))
|
|
71
|
+
return [];
|
|
72
|
+
try {
|
|
73
|
+
const parsed = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
74
|
+
if (parsed.version !== FILE_VERSION) {
|
|
75
|
+
console.warn(`[workspace-template-service] workspace-templates.json has version ${parsed.version}, expected ${FILE_VERSION}. Reading best-effort.`);
|
|
76
|
+
}
|
|
77
|
+
if (!Array.isArray(parsed.templates))
|
|
78
|
+
return [];
|
|
79
|
+
// Re-sanitise on read: the file may have been edited by hand.
|
|
80
|
+
return parsed.templates
|
|
81
|
+
.filter((t) => t &&
|
|
82
|
+
typeof t.id === 'string' &&
|
|
83
|
+
typeof t.name === 'string' &&
|
|
84
|
+
typeof t.createdAt === 'string' &&
|
|
85
|
+
typeof t.updatedAt === 'string')
|
|
86
|
+
.map((t) => ({ ...t, preset: sanitizePreset(t.preset) }));
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
// Treated as empty, never overwritten here: the next successful write is
|
|
90
|
+
// the user's, after they have seen the log line.
|
|
91
|
+
console.error('[workspace-template-service] Failed to read workspace-templates.json:', err);
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function writeFile(templates) {
|
|
96
|
+
const filePath = getWorkspaceTemplatesPath();
|
|
97
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
98
|
+
const file = { version: FILE_VERSION, templates };
|
|
99
|
+
writeFileSync(filePath, JSON.stringify(file, null, 2), 'utf-8');
|
|
100
|
+
}
|
|
101
|
+
export function listWorkspaceTemplates() {
|
|
102
|
+
return readFile();
|
|
103
|
+
}
|
|
104
|
+
/** Throws `Invalid template name`, `already exists` or `Too many templates`. */
|
|
105
|
+
export function createWorkspaceTemplate(input) {
|
|
106
|
+
const name = normalizeName(input.name);
|
|
107
|
+
assertValidName(name);
|
|
108
|
+
const templates = readFile();
|
|
109
|
+
if (templates.some((t) => sameName(t.name, name))) {
|
|
110
|
+
throw new Error(`Template '${name}' already exists`);
|
|
111
|
+
}
|
|
112
|
+
if (templates.length >= MAX_WORKSPACE_TEMPLATES) {
|
|
113
|
+
throw new Error(`Too many templates: the limit is ${MAX_WORKSPACE_TEMPLATES}`);
|
|
114
|
+
}
|
|
115
|
+
const now = new Date().toISOString();
|
|
116
|
+
const template = {
|
|
117
|
+
id: nanoid(),
|
|
118
|
+
name,
|
|
119
|
+
createdAt: now,
|
|
120
|
+
updatedAt: now,
|
|
121
|
+
preset: sanitizePreset(input.preset),
|
|
122
|
+
};
|
|
123
|
+
writeFile([...templates, template]);
|
|
124
|
+
return template;
|
|
125
|
+
}
|
|
126
|
+
/** Null for an unknown id. Throws on an invalid or duplicate name. */
|
|
127
|
+
export function updateWorkspaceTemplate(id, updates) {
|
|
128
|
+
const templates = readFile();
|
|
129
|
+
const index = templates.findIndex((t) => t.id === id);
|
|
130
|
+
if (index < 0)
|
|
131
|
+
return null;
|
|
132
|
+
const current = templates[index];
|
|
133
|
+
let name = current.name;
|
|
134
|
+
if (updates.name !== undefined) {
|
|
135
|
+
name = normalizeName(updates.name);
|
|
136
|
+
assertValidName(name);
|
|
137
|
+
if (templates.some((t) => t.id !== id && sameName(t.name, name))) {
|
|
138
|
+
throw new Error(`Template '${name}' already exists`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const updated = {
|
|
142
|
+
...current,
|
|
143
|
+
name,
|
|
144
|
+
preset: updates.preset !== undefined ? sanitizePreset(updates.preset) : current.preset,
|
|
145
|
+
updatedAt: new Date().toISOString(),
|
|
146
|
+
};
|
|
147
|
+
templates[index] = updated;
|
|
148
|
+
writeFile(templates);
|
|
149
|
+
return updated;
|
|
150
|
+
}
|
|
151
|
+
/** False for an unknown id. */
|
|
152
|
+
export function deleteWorkspaceTemplate(id) {
|
|
153
|
+
const templates = readFile();
|
|
154
|
+
const remaining = templates.filter((t) => t.id !== id);
|
|
155
|
+
if (remaining.length === templates.length)
|
|
156
|
+
return false;
|
|
157
|
+
writeFile(remaining);
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* The preset an existing workspace would have been created from. Used by
|
|
162
|
+
* "Duplicate": the create form is prefilled with it, nothing is written.
|
|
163
|
+
* Tasks and criteria come back as titles in their order, statuses dropped — a
|
|
164
|
+
* preset describes work to do, not work done.
|
|
165
|
+
*/
|
|
166
|
+
export function presetFromWorkspace(workspaceId) {
|
|
167
|
+
const db = getDb();
|
|
168
|
+
const row = db
|
|
169
|
+
.prepare(`SELECT project_path, source_branch, working_branch, engine, model, reasoning_effort,
|
|
170
|
+
agent_permission_mode, auto_loop, auto_loop_session_mode, brainstorm_model, description
|
|
171
|
+
FROM workspaces WHERE id = ?`)
|
|
172
|
+
.get(workspaceId);
|
|
173
|
+
if (!row)
|
|
174
|
+
return null;
|
|
175
|
+
const tasks = db
|
|
176
|
+
.prepare('SELECT title, is_acceptance_criterion FROM tasks WHERE workspace_id = ? ORDER BY sort_order ASC')
|
|
177
|
+
.all(workspaceId);
|
|
178
|
+
const slash = row.working_branch.indexOf('/');
|
|
179
|
+
const preset = {
|
|
180
|
+
projectPath: row.project_path,
|
|
181
|
+
sourceBranch: row.source_branch,
|
|
182
|
+
...(slash > 0 ? { branchType: row.working_branch.slice(0, slash) } : {}),
|
|
183
|
+
engine: row.engine,
|
|
184
|
+
model: row.model,
|
|
185
|
+
reasoningEffort: row.reasoning_effort,
|
|
186
|
+
autoLoop: row.auto_loop === 1,
|
|
187
|
+
...(row.brainstorm_model ? { brainstormModel: row.brainstorm_model } : {}),
|
|
188
|
+
...(row.description ? { description: row.description } : {}),
|
|
189
|
+
tasks: tasks.filter((t) => t.is_acceptance_criterion !== 1).map((t) => t.title),
|
|
190
|
+
acceptanceCriteria: tasks.filter((t) => t.is_acceptance_criterion === 1).map((t) => t.title),
|
|
191
|
+
};
|
|
192
|
+
// Route the enum-like columns through the sanitiser so a legacy value in the
|
|
193
|
+
// DB cannot leak an out-of-range mode into the form.
|
|
194
|
+
return {
|
|
195
|
+
...preset,
|
|
196
|
+
...sanitizePreset({
|
|
197
|
+
agentPermissionMode: row.agent_permission_mode,
|
|
198
|
+
autoLoopSessionMode: row.auto_loop_session_mode,
|
|
199
|
+
}),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
@@ -97,6 +97,10 @@ export function getSkillsPath() {
|
|
|
97
97
|
export function getTemplatesPath() {
|
|
98
98
|
return path.join(getKoboHome(), 'templates.json');
|
|
99
99
|
}
|
|
100
|
+
/** Saved create-form presets. Same directory as templates.json and settings.json. */
|
|
101
|
+
export function getWorkspaceTemplatesPath() {
|
|
102
|
+
return path.join(getKoboHome(), 'workspace-templates.json');
|
|
103
|
+
}
|
|
100
104
|
/**
|
|
101
105
|
* Absolute path to the compiled MCP server entry (shipped in the published
|
|
102
106
|
* package as dist/mcp-server/kobo-tasks-server.js). Returns null if not
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* editing the workspace `model` field directly. This list reflects the
|
|
6
6
|
* recommended set surfaced in the create-workspace selector.
|
|
7
7
|
*
|
|
8
|
-
* Auth caveat: the `gpt-5.6-*` family and `gpt-5.5` are
|
|
9
|
-
* reachable when authenticated via ChatGPT
|
|
10
|
-
* API-key auth is limited to `gpt-5.4` and below.
|
|
8
|
+
* Auth caveat: `gpt-6-astra`, the `gpt-5.6-*` family and `gpt-5.5` are
|
|
9
|
+
* currently only reachable when authenticated via ChatGPT
|
|
10
|
+
* (Plus/Pro/Team/Enterprise). API-key auth is limited to `gpt-5.4` and below.
|
|
11
11
|
*/
|
|
12
12
|
export const CODEX_MODELS = [
|
|
13
13
|
{
|
|
@@ -16,6 +16,12 @@ export const CODEX_MODELS = [
|
|
|
16
16
|
i18nLabelKey: 'model.auto',
|
|
17
17
|
i18nDescriptionKey: 'model.autoDescription',
|
|
18
18
|
},
|
|
19
|
+
{
|
|
20
|
+
id: 'gpt-6-astra',
|
|
21
|
+
label: 'GPT-6 Astra',
|
|
22
|
+
i18nLabelKey: 'model.gpt6astra',
|
|
23
|
+
i18nDescriptionKey: 'model.gpt6astraDescription',
|
|
24
|
+
},
|
|
19
25
|
{
|
|
20
26
|
id: 'gpt-5.6-sol',
|
|
21
27
|
label: 'GPT-5.6 Sol',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loicngr/kobo",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.31",
|
|
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",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import{B as e,C as t,St as n,wt as r,yt as i}from"./reactivity.esm-bundler-DtSZKRQB.js";import{$ as a,A as o,At as s,B as c,Dt as l,Et as u,H as d,It as f,Mt as p,Ot as m,Rt as h,Tt as g,U as _,V as v,W as y,Wt as b,X as x,Z as S,_n as C,fn as w,t as T,ut as E,w as D}from"./runtime-dom.esm-bundler-DgevF6KV.js";import{n as O}from"./vue-i18n-DtajJy_8.js";import{W as k,Z as A,b as j,l as M,t as ee,w as N}from"./QBtn-B7WFdfmy.js";import{C as P,Et as F,H as te,T as ne,kt as I,m as re,p as ie,vt as L,w as ae}from"./index-CVfEYP1z.js";import{t as oe}from"./QSpinnerDots-DWOFEezR.js";import{r as se}from"./QItemSection-CEUi4Tz0.js";import{t as ce}from"./QMarkupTable-DcoQpjPu.js";import{_ as le,b as R,x as z}from"./permissionModes-BKhOcXIS.js";import{r as ue,t as B}from"./pending-diff-open-2y1wCUC0.js";import{t as V}from"./documents-CHf7b-Vo.js";import{a as H,o as U,s as W}from"./use-tours-DoXhHOdJ.js";import{i as de,n as G,o as fe,r as pe,t as me}from"./render-chat-markdown-BtqSDXpK.js";import{a as he,i as ge,n as K,o as _e,r as ve,s as ye}from"./WorkspacePage-CDpYwmH9.js";function be(e,t){return E(`div`,e,[E(`table`,{class:`q-table`},t)])}var q={list:se,table:ce},J=[`list`,`table`,`__qtable`],xe=A({name:`QVirtualScroll`,props:{...z,type:{type:String,default:`list`,validator:e=>J.includes(e)},items:{type:Array,default:()=>[]},itemsFn:Function,itemsSize:Number,scrollTarget:I},setup(e,{slots:n,attrs:r}){let i,a=t(null),o=c(()=>e.itemsSize>=0&&e.itemsFn!==void 0?Number.parseInt(e.itemsSize,10):Array.isArray(e.items)?e.items.length:0),{virtualScrollSliceRange:d,localResetVirtualScroll:f,padVirtualScroll:h,onVirtualScrollEvt:g}=R({virtualScrollLength:o,getVirtualScrollTarget:x,getVirtualScrollEl:b}),_=c(()=>{if(o.value===0)return[];let t=(e,t)=>({index:d.value.from+t,item:e});return e.itemsFn===void 0?e.items.slice(d.value.from,d.value.to).map(t):e.itemsFn(d.value.from,d.value.to-d.value.from).map(t)}),v=c(()=>`q-virtual-scroll q-virtual-scroll`+(e.virtualScrollHorizontal?`--horizontal`:`--vertical`)+(e.scrollTarget===void 0?` scroll`:``)),y=c(()=>e.scrollTarget===void 0?{tabindex:0}:{});w(o,()=>{f()}),w(()=>e.scrollTarget,()=>{C(),S()});function b(){let e=a.value;return e===null?null:e.$el||e}function x(){return i}function S(){let t=b();t!==null&&(i=F(t,e.scrollTarget),i.addEventListener(`scroll`,g,k.passive))}function C(){i!==void 0&&(i.removeEventListener(`scroll`,g,k.passive),i=void 0)}function T(){let t=h(e.type===`list`?`div`:`tbody`,_.value.map(n.default));return n.before!==void 0&&(t=n.before().concat(t)),j(n.after,t)}return l(()=>{f()}),p(()=>{S()}),u(()=>{S()}),s(()=>{C()}),m(()=>{C()}),()=>{if(n.default===void 0){console.error(`QVirtualScroll: default scoped slot is required for rendering`);return}return e.type===`__qtable`?be({ref:a,class:`q-table__middle `+v.value},T()):E(q[e.type],{...r,ref:a,class:[r.class,v.value],...y.value},T)}}}),Se=new Set([`setup`,`cleanup`,`archive`]);function Ce(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:Se.has(e.sender)||P(e.sender)?`script`:`user`;case`session`:return`session`;default:return`agent`}}function we(e){let t=[],n=null,r=null;for(let i of e){let e=Ce(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 Te(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 Ee(e){let t=e.items[0];return`${e.speaker}:${t?Te(t):`empty`}`}function De(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 Oe(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=w(e,e=>{t(e)&&s(!0)},{immediate:!0}),i){o();return}a=setTimeout(()=>s(!1),n)})}var ke={class:`agent-error-item`},Ae={class:`agent-error-item__body`},je={class:`agent-error-item__title`},Me={class:`agent-error-item__message`},Y=U(a({__name:`AgentErrorItem`,props:{item:{}},setup(e){let t=e,{te:n}=O(),i=c(()=>{let e=`agent.error.${t.item.category}`;return n(e)?e:`agent.error.other`});return(t,n)=>(h(),y(`div`,ke,[S(M,{name:`error_outline`,size:`16px`,class:`agent-error-item__icon`}),v(`div`,Ae,[v(`div`,je,r(t.$t(i.value)),1),v(`div`,Me,r(e.item.message),1)])]))}}),[[`__scopeId`,`data-v-e98c3c02`]]),Ne={class:`text-caption text-kobo-3`},X=a({__name:`SessionEventItem`,props:{item:{}},setup(e){let t=e,n=c(()=>{switch(t.item.kind){case`started`:return`session.started`;case`ended`:return ye(t.item.detail);case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,t)=>(h(),y(`span`,Ne,r(e.$t(n.value)),1))}});function Pe(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){Z(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 Z(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=Q(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 Q(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 Fe=[`innerHTML`],Ie=U(a({__name:`TextMessageItem`,props:{item:{}},setup(e){let t=e,n=V(),r=ie(),i=H(),{t:a}=O(),o=c(()=>{let e=r.selectedWorkspaceId;return e?n.documentsFor(e).map(e=>e.path):[]}),s=c(()=>{let e=t.item;if(e.streaming)return me(e.text);let n=o.value;return pe(`${e.messageId}|${n.join(`,`)}`,e.text,e=>{let t=Pe(fe.parse(e,{async:!1,breaks:!0,gfm:!0}),n);return de(t,{addAttr:[`data-document-path`]})})});function l(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)=>(h(),y(`div`,{class:`markdown-message`,onClick:l},[v(`div`,{innerHTML:s.value},null,8,Fe),e.item.streaming?(h(),d(N,{key:0,size:`xs`,class:`q-ml-xs`})):_(``,!0)]))}}),[[`__scopeId`,`data-v-99371035`]]);function Le(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}/${ne}/${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=U(a({__name:`ToolCallItem`,props:{item:{}},setup(n){let a=n,s=t(!1),l=ie(),{t:u}=O(),f=c(()=>Be(a.item.name,a.item.input)),p=c(()=>f.value?$(f.value.filePath,l.selectedWorkspace):``),m={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`},g=c(()=>m[a.item.name]??`build`),T=c(()=>{if(f.value)return``;let e=a.item.input,t=E(e);return t?$(t,l.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 k=c(()=>{let e=f.value;return e?e.diffLines?e.diffLines:e.toolName===`Edit`&&e.oldString!==void 0&&e.newString!==void 0?Le(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}),A=c(()=>{let e=a.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`]),N=c(()=>!!(a.item.result&&A.value)&&(!j.has(a.item.name)||a.item.result?.isError===!0));function P(){s.value=!s.value}function F(){let e=f.value?.filePath,t=l.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 w(()=>a.item.result?.isError===!0,e=>{e&&(s.value=!0)},{immediate:!0}),(t,a)=>f.value?(h(),y(`div`,{key:0,class:i([`tool-row`,{"tool-row-expanded":s.value}])},[v(`div`,{class:`tool-header`,onClick:P},[S(M,{name:g.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),v(`span`,We,r(f.value.toolName===`Bash:rm`?`Bash`:f.value.toolName),1),v(`span`,{class:`tool-path`,title:f.value.filePath},r(p.value),9,Ge),S(ee,{flat:``,dense:``,round:``,size:`xs`,icon:`open_in_new`,class:`tool-open-diff`,onClick:D(F,[`stop`])},{default:C(()=>[S(W,null,{default:C(()=>[x(r(e(u)(`chat.openInGitDiff`)),1)]),_:1})]),_:1}),f.value.additions>0?(h(),y(`span`,Ke,`+`+r(f.value.additions),1)):_(``,!0),f.value.deletions>0?(h(),y(`span`,qe,`-`+r(f.value.deletions),1)):_(``,!0),n.item.result?.isError?(h(),d(M,{key:2,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-xs`})):n.item.result?(h(),d(M,{key:3,name:`check`,color:`positive`,size:`xs`,class:`q-ml-xs`})):_(``,!0),S(M,{name:s.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-auto text-kobo-3`},null,8,[`name`])]),s.value&&k.value?(h(),y(`div`,{key:0,class:`tool-diff`,onClick:a[0]||=D(()=>{},[`stop`])},[(h(!0),y(o,null,b(k.value,(e,t)=>(h(),y(`div`,{key:t,class:i([`diff-line`,{"diff-del":e.type===`del`,"diff-add":e.type===`add`,"diff-context":e.type===`context`}])},[v(`span`,Je,r(e.type===`del`?`-`:e.type===`add`?`+`:` `),1),x(r(e.content),1)],2))),128))])):_(``,!0)],2)):(h(),y(`div`,{key:1,class:i([`tool-row tool-row-generic`,{"tool-row-expanded":s.value,"tool-row--toggleable":N.value}])},[v(`div`,{class:`tool-header`,onClick:a[1]||=e=>N.value&&P()},[S(M,{name:g.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),v(`span`,Ye,r(n.item.name),1),T.value?(h(),y(`span`,{key:0,class:`tool-arg`,title:E(n.item.input)||T.value},r(T.value),9,Xe)):_(``,!0),n.item.result?.isError?(h(),d(M,{key:1,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-auto`})):n.item.result?(h(),d(M,{key:2,name:`check`,color:`positive`,size:`xs`,class:`q-ml-auto`})):_(``,!0),N.value?(h(),d(M,{key:3,name:s.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-xs text-kobo-3`},null,8,[`name`])):_(``,!0)]),s.value&&N.value?(h(),y(`div`,{key:0,class:`tool-output`,onClick:a[2]||=D(()=>{},[`stop`])},r(A.value),1)):_(``,!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=U(a({__name:`UserMessageItem`,props:{item:{}},setup(e){let n=e,r=ie(),i=c(()=>n.item.sender===`system-prompt`),a=c(()=>{let e=Qe(n.item.content,r.selectedWorkspaceId??``);return G(e)}),s=t(null),l=t(!1);function u(e){let t=e.target;if(t?.tagName!==`IMG`)return;let n=t;n.src&&(s.value=n.src,l.value=!0)}return(e,t)=>(h(),y(o,null,[i.value?(h(),d(le,{key:0,dense:``,"dense-toggle":``,label:e.$t(`chat.systemPrompt`),"header-class":`text-kobo-2 text-caption`},{default:C(()=>[v(`div`,{class:`q-py-xs markdown-user-prompt`,innerHTML:a.value},null,8,$e)]),_:1},8,[`label`])):(h(),y(`div`,{key:1,class:`markdown-message`,onClick:u},[v(`div`,{innerHTML:a.value},null,8,et)])),S(L,{modelValue:l.value,"onUpdate:modelValue":t[1]||=e=>l.value=e},{default:C(()=>[s.value?(h(),y(`img`,{key:0,src:s.value,alt:``,class:`image-lightbox-img`,onClick:t[0]||=e=>l.value=!1},null,8,tt)):_(``,!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=U(a({__name:`TurnCard`,props:{turn:{},highlighted:{type:Boolean}},emits:[`scrollTo`],setup(a,{emit:s}){let l=a,u=s,{t:f}=O(),p=t(null);function m(){let e=p.value;if(!e)return;let t=e.closest(`.q-scrollarea`)?.querySelector(`.q-scrollarea__content`);if(!t){e.scrollIntoView({behavior:`smooth`,block:`start`});return}let n=e.getBoundingClientRect().top-t.getBoundingClientRect().top;u(`scrollTo`,Math.max(0,n-8))}let g=c(()=>{switch(l.turn.speaker){case`user`:return{label:f(`chat.you`),accent:`var(--kobo-turn-user)`,badgeClass:`turn-badge-user`};case`agent`:return{label:f(`chat.agent`),accent:`var(--kobo-turn-agent)`,badgeClass:`turn-badge-agent`};case`system-prompt`:return{label:f(`chat.systemPrompt`),accent:`var(--kobo-text-3)`,badgeClass:`turn-badge-system`};case`session`:return{label:f(`chat.session`),accent:`var(--kobo-text-3)`,badgeClass:`turn-badge-session`};case`script`:{let e=l.turn.items[0],t=e?.type===`user`?e.sender:``;return{label:P(t)?f(`chat.hookScript`,{event:t.slice(5)}):f(t===`archive`?`chat.archiveScript`:t===`setup`?`chat.setupScript`:`chat.cleanupScript`),accent:`var(--kobo-success)`,badgeClass:`turn-badge-script`}}}});function w(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 T=c(()=>w(l.turn.ts)),E=c(()=>l.turn.items.flatMap(e=>e.eventIds??[]).join(` `)),D=c(()=>{let e=l.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}),k=c(()=>{let e=l.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?``:w(t,r-n<6e4)}),A=c(()=>k.value!==``),j=c(()=>l.turn.items.filter(e=>e.type===`tool`).length);return(t,s)=>(h(),y(`div`,{ref_key:`cardEl`,ref:p,class:i([`turn-card`,{"turn-card--user":a.turn.speaker===`user`,"turn-card--highlighted":a.highlighted}]),"data-event-ids":E.value,style:n({"--turn-accent":g.value.accent})},[v(`div`,it,[v(`span`,{class:i([`turn-badge`,g.value.badgeClass])},r(g.value.label),3),T.value?(h(),y(`span`,at,r(T.value),1)):_(``,!0),A.value?(h(),y(o,{key:1},[S(M,{name:`arrow_forward`,size:`10px`,color:`kobo-3`,class:`turn-time-arrow`}),v(`span`,ot,[x(r(k.value)+` `,1),S(W,null,{default:C(()=>[x(r(e(f)(`chat.lastUpdatedAt`,{time:k.value})),1)]),_:1})])],64)):_(``,!0),j.value>0?(h(),y(`span`,st,` · `+r(e(f)(`chat.nActions`,{n:j.value})),1)):_(``,!0)]),v(`div`,ct,[(h(!0),y(o,null,b(a.turn.items,t=>(h(),y(o,{key:e(Te)(t)},[t.type===`text`?(h(),d(Ie,{key:0,item:t},null,8,[`item`])):t.type===`thinking`?(h(),d(K,{key:1,item:t},null,8,[`item`])):t.type===`tool`?(h(),d(Ze,{key:2,item:t},null,8,[`item`])):t.type===`user`?(h(),d(nt,{key:3,item:t},null,8,[`item`])):t.type===`session`?(h(),d(X,{key:4,item:t},null,8,[`item`])):t.type===`error`?(h(),d(Y,{key:5,item:t},null,8,[`item`])):_(``,!0)],64))),128))]),a.turn.items.length>4?(h(),y(`div`,lt,[S(ee,{flat:``,round:``,dense:``,size:`xs`,icon:`arrow_upward`,color:`kobo-3`,class:`turn-scroll-top-btn`,onClick:m},{default:C(()=>[S(W,null,{default:C(()=>[x(r(e(f)(`chat.scrollToTurnTop`)),1)]),_:1})]),_:1})])):_(``,!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=U(a({__name:`ActivityFeed`,props:{workspaceId:{}},setup(n){let{t:i}=O(),a=n,s=te(),l=ae(),u=ie(),m=c(()=>s.isCompacting(a.workspaceId)),E=c(()=>u.selectedSessionId),D=c(()=>u.sessions.find(e=>e.id===E.value)?.engineSessionId??null),k=c(()=>{let e=u.sessions;return e.length!==0&&E.value===e[e.length-1].id});function A(e){return E.value?e?e===E.value||e===D.value:k.value:!0}let j=c(()=>(u.activityFeeds[a.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]}))),P=c(()=>{let e=u.workspaces.find(e=>e.id===a.workspaceId);return re(e?.status)}),F=ve(),ne=``,I=c(()=>{let e=s.eventsFor(a.workspaceId),t=s.timestampsFor(a.workspaceId),n=s.sessionIdsFor(a.workspaceId),r=s.eventIdsFor(a.workspaceId),i=[],o=[],c=[];for(let a=0;a<e.length;a++)A(n[a])&&(i.push(e[a]),o.push(t[a]),c.push(r[a]??null));let u=`${a.workspaceId}::${E.value??`*`}`;u!==ne&&(F=ve(),ne=u);let d=ge(F,i,o,P.value,c);return we(_e(d,j.value).filter(e=>e.type===`thinking`?!1:e.type===`session`?e.kind===`ended`?l.showVerboseSystemMessages||!he(e.detail):l.showVerboseSystemMessages:!0))}),L=c(()=>l.showVerboseSystemMessages?s.eventsFor(a.workspaceId).filter(e=>e.kind===`message:raw`).map(e=>e.content):[]),se=c(()=>{for(let e=I.value.length-1;e>=0;e--){let t=I.value[e]?.items??[];for(let e=t.length-1;e>=0;e--){let n=t[e];if(n){if(n.type===`text`&&!n.streaming)return{key:`text:${n.messageId}`,text:n.text};if(n.type===`tool`)return n.result?{key:`tool:${n.toolCallId}:end`,text:n.result.isError?i(`activity.a11y.toolFailed`,{name:n.name}):i(`activity.a11y.toolFinished`,{name:n.name})}:{key:`tool:${n.toolCallId}:start`,text:i(`activity.a11y.toolStarted`,{name:n.name})}}}}return null}),ce=t(``);w(se,(e,t)=>{if(!e||e.key===t?.key)return;let n=e.key.startsWith(`text:`)?i(`activity.a11y.agentSaid`,{text:e.text.slice(0,St)}):e.text;ce.value=n});let R=t(null),z=t(!0),B=t(!1),V=t(null),H=!1,U=t(!0),W=t(new Map);function de(e){let t=e.verticalSize-e.verticalPosition-e.verticalContainerSize;z.value=t<=Ct,H&&e.verticalPosition<=wt&&!B.value&&fe()&&ye()}function G(e,t){return`${e}:${t}`}function fe(){let e=E.value;return e?W.value.get(G(a.workspaceId,e))??!0:s.hasMoreOlderFor(a.workspaceId)}function pe(e,t,n){W.value.set(G(e,t),n)}function me(e){if(!E.value)return s.oldestIdFor(e);let t=s.eventIdsFor(e),n=s.sessionIdsFor(e);for(let e=0;e<t.length;e++){if(!A(n[e]))continue;let r=t[e];if(r)return r}}let K=null;function ye(){return K||(K=be().finally(()=>{K=null}),K)}async function be(){let e=a.workspaceId,t=E.value,n=me(e);if(!n)return;B.value=!0;let r=Date.now();try{let r=R.value;await g();let i=r?.getScroll().verticalSize??0,a=r?.getScroll().verticalPosition??0,o=new URLSearchParams({before:n,limit:`200`});t&&o.set(`session`,t);let c=fetch(`/api/workspaces/${e}/events?${o.toString()}`),l=new Promise(e=>setTimeout(e,Tt)),[d]=await Promise.all([c,l]);if(!d.ok){t?pe(e,t,!1):s.prepend(e,[],[],{oldestId:n,hasMoreOlder:!1});return}let f=await d.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),_=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&&pe(e,t,f.hasMore),s.prepend(e,_,v,{oldestId:x,hasMoreOlder:t?s.hasMoreOlderFor(e):f.hasMore,sessionIds:y,eventIds:b});for(let t of h){let n=t.payload;typeof n.content==`string`&&u.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 g(),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()-r,t=Math.max(0,Tt-e);await new Promise(e=>setTimeout(e,t+Et)),B.value=!1}}async function q(e=0){await g();let t=R.value;if(!t)return;let n=t.getScroll();t.setScrollPosition(`vertical`,n.verticalSize,e)}let J=null,Se=0;function Ce(){if(J!=null)return;let e=performance.now()-Se<Ot;J=requestAnimationFrame(()=>{J=null,Se=performance.now(),q(e?0:180)})}function Te(e){let t=R.value;t&&t.setScrollPosition(`vertical`,Math.max(0,e),250)}function ke(){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 Ae(e){let t=e.detail;if(!(t?.workspaceId!==a.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/${a.workspaceId}/events?${e}`);if(!n.ok)return;let r=await n.json(),i=r.events??[],o=i.filter(e=>e.type===`agent:event`&&e.workspaceId===a.workspaceId),c=i.filter(e=>e.type===`user:message`&&e.workspaceId===a.workspaceId);s.reset(a.workspaceId,o.map(e=>e.payload),o.map(e=>e.createdAt),{oldestId:i[0]?.id,hasMoreOlder:r.hasMore??!1,sessionIds:o.map(e=>e.sessionId),eventIds:o.map(e=>e.id)});for(let e of c){let t=e.payload;typeof t.content==`string`&&u.addActivityItem(a.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`}})}await Oe(U,e=>!e,5e3),await g(),await new Promise(e=>requestAnimationFrame(()=>requestAnimationFrame(()=>e())));let l=I.value.findIndex(e=>e.items.some(e=>e.eventIds?.includes(t.eventId)??!1));if(l<0)return;V.value=t.eventId,je.value?.scrollTo(l,`center`),Y.value=l,window.setTimeout(()=>{V.value===t.eventId&&(V.value=null)},1800)}catch(e){console.error(`[ActivityFeed] failed to focus history event:`,e)}}let je=t(null),Me=t(null),Y=t(0);function Ne(e){Y.value=e.index}let X=t(!1);async function Pe(){if(X.value)return;X.value=!0;let e=a.workspaceId;try{let t=De(I.value,Y.value);if(t<0)for(let n=0;n<15;n++){if(e!==a.workspaceId)return;if(!fe())break;let n=I.value.length;if(await ye(),await g(),e!==a.workspaceId)return;if(Y.value+=I.value.length-n,t=De(I.value,Y.value),t>=0)break}t>=0&&e===a.workspaceId&&(je.value?.scrollTo(t,`start`),Y.value=t)}finally{X.value=!1}}async function Z(){H=!1,await g(),await q(0),await new Promise(e=>requestAnimationFrame(()=>requestAnimationFrame(()=>e()))),await q(0),H=!0}let Q=c(()=>{let e=s.sessionIdsFor(a.workspaceId);if(!E.value)return e.length;let t=0;for(let n of e)A(n)&&t++;return t}),Fe=c(()=>s.eventsFor(a.workspaceId).length);async function Ie(){U.value=!0;let e=Date.now();await new Promise(e=>setTimeout(e,Dt));let t=Math.max(0,e+kt-Date.now());await Oe(Fe,e=>e>0,t),U.value=!1}w(U,async e=>{!e&&Q.value>0&&await Z(),!e&&Q.value===0&&E.value&&ze(),e||g(()=>{Me.value=R.value?.getScrollTarget()??null})}),p(()=>{window.addEventListener(`kobo:focus-history-event`,Ae),g(()=>{Me.value=R.value?.getScrollTarget()??null}),Ie(),Q.value>0&&Z(),E.value&&ze();let e=new URLSearchParams(window.location.hash.split(`?`)[1]??``).get(`eventId`);e&&(Ae(new CustomEvent(`kobo:focus-history-event`,{detail:{workspaceId:a.workspaceId,sessionId:E.value,eventId:e}})),ke())});let Le=Q.value>0;w(Q,async(e,t)=>{if(!B.value){if(!Le&&e>0){Le=!0,await Z();return}e>t&&z.value&&!B.value&&Ce()}}),f(()=>{window.removeEventListener(`kobo:focus-history-event`,Ae),J!=null&&(cancelAnimationFrame(J),J=null)}),w(()=>a.workspaceId,()=>{z.value=!0,Le=Q.value>0,H=!1,Ie(),Q.value>0&&Z()}),w(()=>u.selectedSessionId,async()=>{z.value=!0,H=!1,await Z(),ze()});let Re=new Set;async function ze(){let e=E.value;if(!e||Q.value>0)return;let t=G(a.workspaceId,e);if(!Re.has(t)){Re.add(t);try{let t=await fetch(`/api/workspaces/${a.workspaceId}/events?session=${encodeURIComponent(e)}&limit=500`);if(!t.ok)return;let n=await t.json(),r=n.events??[];if(r.length===0)return;let i=r.filter(e=>e.type===`agent:event`&&e.workspaceId===a.workspaceId),o=r.filter(e=>e.type===`user:message`&&e.workspaceId===a.workspaceId),c=i.map(e=>e.payload),l=i.map(e=>e.createdAt),d=i.map(e=>e.sessionId??null),f=i.map(e=>e.id);pe(a.workspaceId,e,n.hasMore),c.length>0&&s.prepend(a.workspaceId,c,l,{oldestId:r[0].id,hasMoreOlder:s.hasMoreOlderFor(a.workspaceId),sessionIds:d,eventIds:f});for(let e of o){let t=e.payload;typeof t.content==`string`&&u.addActivityItem(a.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`}})}await g(),await q(0)}catch(e){console.error(`[ActivityFeed] fetchSessionIfMissing failed:`,e),Re.delete(t)}}}let Be=c(()=>j.value.filter(e=>e.sender!==`system-prompt`).length);w(Be,async(e,t)=>{e>t&&(z.value=!0,await q(180))});async function $(){z.value=!0,await q(250)}return(t,n)=>U.value?(h(),y(`div`,dt,[S(oe,{size:`40px`,color:`primary`})])):(h(),y(`div`,ft,[v(`div`,{"data-testid":`activity-live-region`,class:`sr-only`,role:`log`,"aria-live":`polite`,"aria-atomic":`true`,"aria-label":t.$t(`activity.a11y.region`)},r(ce.value),9,pt),S(T,{name:`fade`},{default:C(()=>[m.value?(h(),y(`div`,mt,[S(oe,{size:`18px`,color:`primary`}),v(`span`,ht,r(t.$t(`activity.compacting`)),1)])):_(``,!0)]),_:1}),S(ue,{ref_key:`scrollRef`,ref:R,class:`activity-feed-scroll`,onScroll:de},{default:C(()=>[B.value?(h(),y(`div`,gt,[S(N,{size:`sm`}),x(` `+r(t.$t(`activity.loading_older`)),1)])):_(``,!0),S(xe,{ref_key:`virtualScrollRef`,ref:je,class:`q-pa-md`,items:I.value,"scroll-target":Me.value??void 0,"virtual-scroll-item-size":160,"virtual-scroll-slice-size":20,onVirtualScroll:Ne},{default:C(({item:t,index:n})=>[(h(),d(ut,{key:e(Ee)(t),turn:t,"data-turn-index":n,highlighted:t.items.some(e=>e.eventIds?.includes(V.value??``)??!1),onScrollTo:Te},null,8,[`turn`,`data-turn-index`,`highlighted`]))]),_:1},8,[`items`,`scroll-target`]),I.value.length===0&&L.value.length===0&&!B.value?(h(),y(`div`,_t,[S(M,{name:`forum`,size:`28px`}),v(`div`,vt,r(t.$t(`activity.empty`)),1),v(`div`,yt,r(t.$t(`activity.emptyHint`)),1)])):_(``,!0),L.value.length?(h(),y(`div`,bt,[S(le,{label:t.$t(`activity.raw_lines`,{n:L.value.length}),dense:``},{default:C(()=>[(h(!0),y(o,null,b(L.value,(e,t)=>(h(),y(`div`,{key:t,class:`text-caption text-kobo-3 q-pa-xs`},r(e),1))),128))]),_:1},8,[`label`])])):_(``,!0)]),_:1},512),v(`div`,xt,[z.value?_(``,!0):(h(),d(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:t.$t(`activity.scroll_to_bottom`),"aria-label":t.$t(`activity.scroll_to_bottom`),onClick:$},null,8,[`title`,`aria-label`])),S(ee,{round:``,dense:``,unelevated:``,color:`kobo-surface-2`,"text-color":`kobo-1`,icon:`arrow_upward`,size:`sm`,class:`activity-feed-nav-btn`,title:t.$t(`activity.prev_user_message`),"aria-label":t.$t(`activity.prev_user_message`),loading:X.value,disable:X.value,onClick:Pe},null,8,[`title`,`aria-label`,`loading`,`disable`])])]))}}),[[`__scopeId`,`data-v-01cd9f2a`]]);export{At as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.agent-error-item[data-v-e98c3c02]{gap:var(--kobo-space-sm);padding:var(--kobo-space-sm) var(--kobo-space-md);border-left:2px solid var(--kobo-danger);background:var(--kobo-surface-2);border-radius:var(--kobo-radius-sm);align-items:flex-start;display:flex}.agent-error-item__icon[data-v-e98c3c02]{color:var(--kobo-danger);flex:none;margin-top:2px}.agent-error-item__body[data-v-e98c3c02]{min-width:0}.agent-error-item__title[data-v-e98c3c02]{color:var(--kobo-text);font-weight:600}.agent-error-item__message[data-v-e98c3c02]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;word-break:break-word;font-size:12px}.markdown-message[data-v-99371035]{color:var(--kobo-text-2);word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-99371035] *{max-width:100%}.markdown-message[data-v-99371035] p{margin:0 0 .5em}.markdown-message[data-v-99371035] p:last-child{margin-bottom:0}.markdown-message[data-v-99371035] pre{background:#00000059;border-radius:4px;margin:.5em 0;padding:.5em .75em;overflow-x:auto}.markdown-message[data-v-99371035] code{word-break:break-all;background:#0000004d;border-radius:3px;padding:.1em .3em;font-size:.9em}.markdown-message[data-v-99371035] pre code{background:0 0;padding:0}.markdown-message[data-v-99371035] ul,.markdown-message[data-v-99371035] ol{margin:.25em 0 .5em;padding-left:1.5em}.markdown-message[data-v-99371035] li{margin:.15em 0}.markdown-message[data-v-99371035] a{color:var(--kobo-text-2);text-decoration:underline}.markdown-message[data-v-99371035] .document-link{color:var(--kobo-text-2);cursor:pointer;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.markdown-message[data-v-99371035] .document-link:hover{color:var(--kobo-text);-webkit-text-decoration:underline;text-decoration:underline}.markdown-message[data-v-99371035] h1,.markdown-message[data-v-99371035] h2,.markdown-message[data-v-99371035] h3,.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{margin:.5em 0 .3em;font-weight:600;line-height:1.3}.markdown-message[data-v-99371035] h1{font-size:1.25em}.markdown-message[data-v-99371035] h2{font-size:1.15em}.markdown-message[data-v-99371035] h3{font-size:1.08em}.markdown-message[data-v-99371035] h4,.markdown-message[data-v-99371035] h5,.markdown-message[data-v-99371035] h6{font-size:1em}.markdown-message[data-v-99371035] blockquote{color:#ffffffb3;border-left:3px solid #fff3;margin:.5em 0;padding-left:.75em}.markdown-message[data-v-99371035] table{border-collapse:collapse;margin:.5em 0}.markdown-message[data-v-99371035] th,.markdown-message[data-v-99371035] td{border:1px solid #ffffff26;padding:.25em .5em}.tool-row[data-v-2482adfe]{border-radius:4px;margin:0;font-size:12px}.tool-header[data-v-2482adfe]{color:var(--kobo-text-2);cursor:default;align-items:center;gap:10px;min-width:0;padding:5px 10px;display:flex}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe],.tool-row--toggleable .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:has(.tool-diff) .tool-header[data-v-2482adfe]{cursor:pointer}.tool-row:not(.tool-row-generic) .tool-header[data-v-2482adfe]:hover,.tool-row--toggleable .tool-header[data-v-2482adfe]:hover{background:#ffffff08}.tool-icon[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0}.tool-name[data-v-2482adfe]{color:var(--kobo-text-2);flex-shrink:0;font-weight:600}.tool-arg[data-v-2482adfe],.tool-path[data-v-2482adfe]{color:var(--kobo-text-3);text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%;font-family:var(--kobo-font-mono);font-size:11.5px;overflow:hidden}.tool-open-diff[data-v-2482adfe]{flex-shrink:0}.tool-path[data-v-2482adfe],.tool-arg[data-v-2482adfe]{flex:1}.tool-stat-add[data-v-2482adfe]{color:var(--kobo-success);flex-shrink:0;font-size:11px;font-weight:600}.tool-stat-del[data-v-2482adfe]{color:var(--kobo-danger);flex-shrink:0;font-size:11px;font-weight:600}.tool-diff[data-v-2482adfe]{max-height:400px;font-family:var(--kobo-font-mono);background:#0003;border-radius:4px;margin-top:4px;padding:8px 0;font-size:11px;line-height:1.5;overflow:auto}.diff-line[data-v-2482adfe]{white-space:pre;color:var(--kobo-text-2);padding:0 12px}.diff-sign[data-v-2482adfe]{width:14px;color:var(--kobo-text-disabled);-webkit-user-select:none;user-select:none;display:inline-block}.diff-add[data-v-2482adfe]{color:var(--kobo-success);background:#66bb6a1a}.diff-add .diff-sign[data-v-2482adfe]{color:var(--kobo-success)}.diff-del[data-v-2482adfe]{color:var(--kobo-danger);background:#ef53501a}.diff-del .diff-sign[data-v-2482adfe]{color:var(--kobo-danger)}.tool-output[data-v-2482adfe]{color:var(--kobo-text-2);font-family:var(--kobo-font-mono);white-space:pre-wrap;background:#00000026;border-radius:4px;max-height:8em;margin-top:4px;padding:6px 10px;font-size:11px;overflow:auto}.markdown-message[data-v-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 @@
|
|
|
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{B as e,C as t,wt as n}from"./reactivity.esm-bundler-DtSZKRQB.js";import{$ as r,A as i,H as a,Mt as o,Rt as s,U as c,V as l,W as u,Wt as d,Z as f,_n as p}from"./runtime-dom.esm-bundler-DgevF6KV.js";import{t as m}from"./QBtn-B7WFdfmy.js";import{Jt as h,Kt as g,n as _}from"./index-CVfEYP1z.js";import{i as v,n as y,o as b}from"./use-tours-DoXhHOdJ.js";import{n as x}from"./render-chat-markdown-BtqSDXpK.js";import{t as S}from"./QChip-DpUYTCOJ.js";import{n as C,t as w}from"./TourReplayButton-CdLG2sf6.js";import{t as T}from"./DrawerToggleButton-DjG7OouG.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=b(r({__name:`ChangelogPage`,setup(r){let b=_(),{scheduleAutoRun:I}=y(),L=t([]),R=t(``),z=t(!1),B=t(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 o(()=>{H(),I(`changelog`)}),(t,r)=>(s(),a(C,{class:`q-pa-md`,style:{"max-width":`900px`,margin:`0 auto`}},{default:p(()=>[l(`div`,E,[f(T,{class:`q-mr-xs`}),f(m,{flat:``,dense:``,round:``,icon:`arrow_back`,onClick:r[0]||=t=>e(b).back()}),l(`div`,D,n(t.$t(`changelog.title`)),1),f(v),f(m,{flat:``,dense:``,icon:`refresh`,loading:z.value,label:t.$t(`common.refresh`),onClick:H},null,8,[`loading`,`label`]),f(w,{"tour-id":`changelog`,class:`q-ml-xs`})]),z.value&&L.value.length===0?(s(),u(`div`,O,n(t.$t(`common.loading`)),1)):B.value?(s(),u(`div`,k,n(B.value),1)):L.value.length===0?(s(),u(`div`,A,n(t.$t(`changelog.empty`)),1)):(s(),u(`div`,j,[R.value?(s(),u(`div`,M,n(t.$t(`changelog.currentVersion`,{version:R.value})),1)):c(``,!0),(s(!0),u(i,null,d(L.value,e=>(s(),a(g,{key:e.version,dark:``,flat:``,bordered:``},{default:p(()=>[f(h,null,{default:p(()=>[l(`div`,N,[l(`div`,P,` v`+n(e.version),1),e.version===R.value?(s(),a(S,{key:0,dense:``,size:`sm`,color:`primary`,"text-color":`kobo-1`,label:t.$t(`changelog.current`),class:`q-ml-sm`},null,8,[`label`])):c(``,!0)]),l(`div`,{class:`changelog-notes`,innerHTML:V(e.notes)},null,8,F)]),_:2},1024)]),_:2},1024))),128))]))]),_:1}))}}),[[`__scopeId`,`data-v-6137cb7c`]]);export{I as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Q as e,R as t}from"./QBtn-B7WFdfmy.js";import{Ft as n,It as r}from"./index-
|
|
1
|
+
import{Q as e,R as t}from"./QBtn-B7WFdfmy.js";import{Ft as n,It as r}from"./index-CVfEYP1z.js";function i(e){return e===!1?0:e===!0||e===void 0?1:Number.parseInt(e,10)||0}var a=e({name:`close-popup`,beforeMount(e,{value:a}){let o={depth:i(a),handler(t){o.depth!==0&&setTimeout(()=>{let i=r(e);i!==void 0&&n(i,t,o.depth)},0)},handlerKey(e){t(e,13)&&o.handler(e)}};e.__qclosepopup=o,e.addEventListener(`click`,o.handler),e.addEventListener(`keyup`,o.handlerKey)},updated(e,{value:t,oldValue:n}){t!==n&&(e.__qclosepopup.depth=i(t))},beforeUnmount(e){let t=e.__qclosepopup;e.removeEventListener(`click`,t.handler),e.removeEventListener(`keyup`,t.handlerKey),delete e.__qclosepopup}});export{a as t};
|