@loicngr/kobo 1.11.32 → 1.11.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +8 -0
  3. package/dist/server/index.js +30 -15
  4. package/dist/server/routes/changelog.js +2 -23
  5. package/dist/server/routes/workspaces.js +37 -0
  6. package/dist/server/services/pr-watcher-service.js +92 -34
  7. package/dist/server/services/worktree-purge-service.js +25 -1
  8. package/dist/server/services/worktree-restore-service.js +79 -0
  9. package/dist/server/services/worktree-service.js +151 -3
  10. package/dist/server/utils/changelog.js +23 -0
  11. package/dist/server/utils/startup-display.js +71 -0
  12. package/dist/server/utils/workspace-lifecycle-guard.js +22 -0
  13. package/package.json +1 -1
  14. package/src/client/dist/pwa/assets/{ActivityFeed-C7tG4Cgq.js → ActivityFeed-CGb-YHB0.js} +1 -1
  15. package/src/client/dist/pwa/assets/{ChangelogPage-FYve4efm.js → ChangelogPage-BDVpqtWz.js} +1 -1
  16. package/src/client/dist/pwa/assets/{ClosePopup-DLm_uRNv.js → ClosePopup-ClH5KG_w.js} +1 -1
  17. package/src/client/dist/pwa/assets/{ComparisonPanel-DRzYHcWf.js → ComparisonPanel-D6kz5Q-o.js} +1 -1
  18. package/src/client/dist/pwa/assets/{CreatePage-CT10FMyq.js → CreatePage-f-C_R4o9.js} +1 -1
  19. package/src/client/dist/pwa/assets/{DashboardPage-CT3XzDaz.js → DashboardPage-C_9_IXdR.js} +1 -1
  20. package/src/client/dist/pwa/assets/{DiffViewer-CIY7UOt6.js → DiffViewer-CMjfVpAG.js} +3 -3
  21. package/src/client/dist/pwa/assets/{DocumentsPanel-D2IlwigV.js → DocumentsPanel-Yim06L6k.js} +1 -1
  22. package/src/client/dist/pwa/assets/{DrawerToggleButton-0fKZjElk.js → DrawerToggleButton-aD_LMlna.js} +1 -1
  23. package/src/client/dist/pwa/assets/{GitPanel-DjG7-AsO.js → GitPanel-x-whHRdM.js} +3 -3
  24. package/src/client/dist/pwa/assets/{HealthPage-BJKRSg5I.js → HealthPage-BNZP_1l-.js} +1 -1
  25. package/src/client/dist/pwa/assets/MainLayout-BMxAagOe.js +2 -0
  26. package/src/client/dist/pwa/assets/{MainLayout-BUTz2ks4.css → MainLayout-DfddEd0b.css} +1 -1
  27. package/src/client/dist/pwa/assets/{QBtnDropdown-Bqa7KhX7.js → QBtnDropdown-BLNdi1w5.js} +1 -1
  28. package/src/client/dist/pwa/assets/{QDrawer-DinZbnyn.js → QDrawer-C6TAn5dv.js} +1 -1
  29. package/src/client/dist/pwa/assets/{SchedulePanel-BDmDDRMX.js → SchedulePanel-D2HyVnU8.js} +1 -1
  30. package/src/client/dist/pwa/assets/{SearchPage-BdisvUwr.js → SearchPage-BG_zXo6V.js} +1 -1
  31. package/src/client/dist/pwa/assets/{SettingsPage-DCJgxm6J.js → SettingsPage-BNBeaT9t.js} +1 -1
  32. package/src/client/dist/pwa/assets/{TerminalPanel-DBnSOJ3B.js → TerminalPanel-BzUFE4eS.js} +1 -1
  33. package/src/client/dist/pwa/assets/{TouchPan-D77wzGyc.js → TouchPan-CK2rmJkA.js} +1 -1
  34. package/src/client/dist/pwa/assets/{TourReplayButton-DU2PItj-.js → TourReplayButton-DHFo5_Kk.js} +1 -1
  35. package/src/client/dist/pwa/assets/{WorkspaceAttentionLabels-CRVNJtmB.js → WorkspaceAttentionLabels-BbtPN7pb.js} +1 -1
  36. package/src/client/dist/pwa/assets/WorkspacePage-Aay3kkPT.js +4 -0
  37. package/src/client/dist/pwa/assets/{WorkspacePage-D3-AEaPN.css → WorkspacePage-ygEb8olx.css} +1 -1
  38. package/src/client/dist/pwa/assets/{browser-sSy6JmeQ.js → browser-pf20JpKz.js} +1 -1
  39. package/src/client/dist/pwa/assets/{build-path-tree-B2-SsE87.js → build-path-tree-BRLZv-pU.js} +1 -1
  40. package/src/client/dist/pwa/assets/de-CG7RYRLI.js +17 -0
  41. package/src/client/dist/pwa/assets/{documents-D4BcPyOF.js → documents-C1u794ea.js} +1 -1
  42. package/src/client/dist/pwa/assets/{editor.api-NH9tSUby.js → editor.api-BaRghNyI.js} +1 -1
  43. package/src/client/dist/pwa/assets/{efforts-BdCfujEx.js → efforts-EHbgZlde.js} +1 -1
  44. package/src/client/dist/pwa/assets/engineFeatures-DyKNpIKw.js +1 -0
  45. package/src/client/dist/pwa/assets/es-DfpfEjEu.js +17 -0
  46. package/src/client/dist/pwa/assets/{expand-template-3E9x3FGS.js → expand-template-D7OUa8G7.js} +1 -1
  47. package/src/client/dist/pwa/assets/{format-CR20Lbwg.js → format-D3dPFA-T.js} +1 -1
  48. package/src/client/dist/pwa/assets/{formatters-TuKWWdWq.js → formatters-DBdoGhB7.js} +1 -1
  49. package/src/client/dist/pwa/assets/fr-DgzZRmjM.js +17 -0
  50. package/src/client/dist/pwa/assets/{freemarker2-F7dLhXbU.js → freemarker2-DI7u6MdV.js} +1 -1
  51. package/src/client/dist/pwa/assets/{handlebars-hXFhj5eh.js → handlebars-BgkIQIEY.js} +1 -1
  52. package/src/client/dist/pwa/assets/{html-7nsVC4pO.js → html-BOPtZli3.js} +1 -1
  53. package/src/client/dist/pwa/assets/{i18n-Djnp5xDA.js → i18n-Butermk0.js} +1 -1
  54. package/src/client/dist/pwa/assets/index-BATViFoR.js +20 -0
  55. package/src/client/dist/pwa/assets/it-DKzqhjlT.js +17 -0
  56. package/src/client/dist/pwa/assets/{javascript-59rTAWws.js → javascript-Cf6-AeMO.js} +1 -1
  57. package/src/client/dist/pwa/assets/{liquid-BP6Awnwy.js → liquid-Bd9X87K-.js} +1 -1
  58. package/src/client/dist/pwa/assets/{mdx-CiCpqnQ4.js → mdx-C_ObhhDT.js} +1 -1
  59. package/src/client/dist/pwa/assets/{monaco-contributions-DzI5nDgU.js → monaco-contributions-rHxRMwAP.js} +1 -1
  60. package/src/client/dist/pwa/assets/{monaco.contribution-9uLUIE5c.js → monaco.contribution-DkNJdReE.js} +2 -2
  61. package/src/client/dist/pwa/assets/{network-auth--GlWvRqv.js → network-auth-CyD51r9F.js} +1 -1
  62. package/src/client/dist/pwa/assets/{notify-theme-DQ_bPMUo.js → notify-theme-Bnw3Xbxg.js} +1 -1
  63. package/src/client/dist/pwa/assets/{pending-diff-open-CK20L_pt.js → pending-diff-open-DsW49A6Z.js} +1 -1
  64. package/src/client/dist/pwa/assets/{permissionModes-DORv0Hwo.js → permissionModes-mF8Kofv1.js} +1 -1
  65. package/src/client/dist/pwa/assets/{project-color-DrojOIC6.js → project-color-CoEJs17L.js} +1 -1
  66. package/src/client/dist/pwa/assets/{python-BfVlMXCp.js → python-BIG7FEi1.js} +1 -1
  67. package/src/client/dist/pwa/assets/{razor-CxyOPnW7.js → razor-CNJSV12m.js} +1 -1
  68. package/src/client/dist/pwa/assets/{render-chat-markdown-nZGk_TRQ.js → render-chat-markdown-Ddq-hxhM.js} +1 -1
  69. package/src/client/dist/pwa/assets/{typescript-Bke62OsW.js → typescript-Blrg4f-0.js} +1 -1
  70. package/src/client/dist/pwa/assets/{use-tours-BEdbVcQS.js → use-tours-Cz5Zz63W.js} +2 -2
  71. package/src/client/dist/pwa/assets/{workspace-templates-1zUtbH31.js → workspace-templates-BS34DvEp.js} +1 -1
  72. package/src/client/dist/pwa/assets/{xml-Cg47p-KM.js → xml-Bv6_W6i5.js} +1 -1
  73. package/src/client/dist/pwa/assets/{yaml-Dj1MTjr-.js → yaml-DH7PMAq0.js} +1 -1
  74. package/src/client/dist/pwa/index.html +1 -1
  75. package/src/client/dist/pwa/sw.js +1 -1
  76. package/src/client/dist/pwa/assets/MainLayout-BSHKEpzs.js +0 -2
  77. package/src/client/dist/pwa/assets/WorkspacePage-Dv3ED-Bt.js +0 -4
  78. package/src/client/dist/pwa/assets/de-D_OhjWJx.js +0 -17
  79. package/src/client/dist/pwa/assets/engineFeatures-6ikmzzfp.js +0 -1
  80. package/src/client/dist/pwa/assets/es-kxJ0xgkc.js +0 -17
  81. package/src/client/dist/pwa/assets/fr-BgQGh90C.js +0 -17
  82. package/src/client/dist/pwa/assets/index-DztjpQfb.js +0 -20
  83. package/src/client/dist/pwa/assets/it-BmzSIMv5.js +0 -17
@@ -1,4 +1,4 @@
1
- import { execFileSync } from 'node:child_process';
1
+ import { execFile, execFileSync } from 'node:child_process';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { isGitBranchExistsError } from '../utils/git-ops.js';
@@ -50,11 +50,10 @@ function projectRelativeWorktreePath(projectPath, worktreePath) {
50
50
  return null;
51
51
  return relativePath;
52
52
  }
53
- function addToExclude(projectPath, worktreePath) {
53
+ function addToExclude(projectPath, worktreePath, excludeFile = getExcludeFilePath(projectPath)) {
54
54
  const relativePath = projectRelativeWorktreePath(projectPath, worktreePath);
55
55
  if (!relativePath)
56
56
  return;
57
- const excludeFile = getExcludeFilePath(projectPath);
58
57
  // Ensure the .git/info directory exists
59
58
  const infoDir = path.dirname(excludeFile);
60
59
  if (!fs.existsSync(infoDir)) {
@@ -279,3 +278,152 @@ export function listOrphanWorktrees(projectPath, attachedPaths) {
279
278
  suggestedSourceBranch: detectSourceBranch(projectPath, wt.path, wt.branch),
280
279
  }));
281
280
  }
281
+ export class WorktreeCheckoutError extends Error {
282
+ code;
283
+ constructor(code, message) {
284
+ super(message);
285
+ this.code = code;
286
+ this.name = 'WorktreeCheckoutError';
287
+ }
288
+ }
289
+ const restoreGitEnv = () => ({ ...process.env, LC_ALL: 'C', LANG: 'C', GIT_TERMINAL_PROMPT: '0' });
290
+ function restoreGit(cwd, args) {
291
+ return execFileSync('git', ['-c', 'core.hooksPath=/dev/null', ...args], {
292
+ cwd,
293
+ encoding: 'utf8',
294
+ stdio: ['ignore', 'pipe', 'pipe'],
295
+ timeout: 30_000,
296
+ env: restoreGitEnv(),
297
+ }).replace(/\n$/, '');
298
+ }
299
+ /** NUL delimiters preserve quoted, whitespace and newline-containing worktree paths. */
300
+ function restoreRegistrations(projectPath) {
301
+ return restoreGit(projectPath, ['worktree', 'list', '--porcelain', '-z'])
302
+ .split('\0\0')
303
+ .filter(Boolean)
304
+ .map((block) => {
305
+ const fields = block.split('\0');
306
+ return {
307
+ path: fields.find((field) => field.startsWith('worktree '))?.slice(9) ?? '',
308
+ branch: fields.find((field) => field.startsWith('branch '))?.slice(7) ?? '',
309
+ };
310
+ });
311
+ }
312
+ function commonGitDirectory(cwd) {
313
+ return fs.realpathSync(restoreGit(cwd, ['rev-parse', '--path-format=absolute', '--git-common-dir']));
314
+ }
315
+ /** Accept only the exact registered root in the same repository on the expected branch. */
316
+ export function isMatchingWorkspaceWorktree(input) {
317
+ try {
318
+ if (!fs.lstatSync(input.worktreePath).isDirectory())
319
+ return false;
320
+ const target = fs.realpathSync(input.worktreePath);
321
+ if (fs.realpathSync(restoreGit(input.worktreePath, ['rev-parse', '--show-toplevel'])) !== target)
322
+ return false;
323
+ if (commonGitDirectory(input.projectPath) !== commonGitDirectory(input.worktreePath))
324
+ return false;
325
+ const ref = `refs/heads/${input.workingBranch}`;
326
+ if (restoreGit(input.worktreePath, ['symbolic-ref', 'HEAD']) !== ref)
327
+ return false;
328
+ return restoreRegistrations(input.projectPath).some((entry) => canonicalize(entry.path) === target && entry.branch === ref);
329
+ }
330
+ catch {
331
+ return false;
332
+ }
333
+ }
334
+ function restorePathExists(target) {
335
+ try {
336
+ fs.lstatSync(target);
337
+ return true;
338
+ }
339
+ catch (err) {
340
+ if (err.code === 'ENOENT')
341
+ return false;
342
+ throw err;
343
+ }
344
+ }
345
+ function resolveRestoreCommit(projectPath, ref) {
346
+ try {
347
+ return restoreGit(projectPath, ['rev-parse', '--verify', '--end-of-options', `${ref}^{commit}`]);
348
+ }
349
+ catch {
350
+ return null;
351
+ }
352
+ }
353
+ /** Caller must already hold withGitRepoLock(projectPath). Never resets or replaces a checkout. */
354
+ export async function restoreWorktreeCheckoutUnlocked(input) {
355
+ const { projectPath, workingBranch } = input;
356
+ const worktreePath = path.resolve(input.worktreePath);
357
+ try {
358
+ commonGitDirectory(projectPath);
359
+ }
360
+ catch {
361
+ throw new WorktreeCheckoutError('project-unavailable', 'The project Git repository is unavailable. Restore its location first.');
362
+ }
363
+ try {
364
+ if (workingBranch.startsWith('-'))
365
+ throw new Error('Branch names cannot start with a dash');
366
+ restoreGit(projectPath, ['check-ref-format', `refs/heads/${workingBranch}`]);
367
+ if (restorePathExists(worktreePath)) {
368
+ if (!isMatchingWorkspaceWorktree(input)) {
369
+ throw new WorktreeCheckoutError('path-conflict', 'The destination is occupied by a different checkout or directory. Move it before retrying.');
370
+ }
371
+ return { source: 'existing-worktree', headCommitSha: restoreGit(worktreePath, ['rev-parse', '--verify', 'HEAD']) };
372
+ }
373
+ const registrations = restoreRegistrations(projectPath);
374
+ // Do not globally prune: another missing checkout may still need its registration.
375
+ if (registrations.some((entry) => path.resolve(entry.path) === worktreePath)) {
376
+ throw new WorktreeCheckoutError('path-conflict', 'Git still registers the missing destination. Repair that worktree registration before retrying.');
377
+ }
378
+ if (registrations.some((entry) => entry.branch === `refs/heads/${workingBranch}`)) {
379
+ throw new WorktreeCheckoutError('branch-in-use', 'The working branch is already checked out elsewhere. Free that checkout before retrying.');
380
+ }
381
+ let source = 'local-branch';
382
+ const localCommit = resolveRestoreCommit(projectPath, `refs/heads/${workingBranch}`);
383
+ let commit = localCommit;
384
+ if (!commit) {
385
+ source = 'saved-commit';
386
+ commit =
387
+ input.headCommitSha && /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/i.test(input.headCommitSha)
388
+ ? resolveRestoreCommit(projectPath, input.headCommitSha)
389
+ : null;
390
+ if (!commit) {
391
+ source = 'remote-branch';
392
+ try {
393
+ await new Promise((resolve, reject) => {
394
+ execFile('git', ['-c', 'core.hooksPath=/dev/null', 'fetch', '--no-tags', 'origin', `refs/heads/${workingBranch}`], {
395
+ cwd: projectPath,
396
+ timeout: 60_000,
397
+ env: restoreGitEnv(),
398
+ }, (error) => (error ? reject(error) : resolve()));
399
+ });
400
+ commit = resolveRestoreCommit(projectPath, 'FETCH_HEAD');
401
+ }
402
+ catch {
403
+ // Avoid exposing remote credentials embedded in Git error output.
404
+ }
405
+ if (!commit) {
406
+ throw new WorktreeCheckoutError('recovery-source-unavailable', 'No local branch, saved commit or reachable origin branch is available. Check origin access or recover the branch manually.');
407
+ }
408
+ }
409
+ }
410
+ // Recheck after the asynchronous fetch, including empty directories and dangling links.
411
+ if (restorePathExists(worktreePath)) {
412
+ throw new WorktreeCheckoutError('path-conflict', 'The destination appeared during recovery. Move the conflicting directory before retrying.');
413
+ }
414
+ if (localCommit)
415
+ restoreGit(projectPath, ['worktree', 'add', '--', worktreePath, workingBranch]);
416
+ else
417
+ restoreGit(projectPath, ['worktree', 'add', '-b', workingBranch, '--', worktreePath, commit]);
418
+ if (!isMatchingWorkspaceWorktree(input)) {
419
+ throw new WorktreeCheckoutError('git-failed', 'The restored checkout could not be verified. Inspect the checkout before retrying.');
420
+ }
421
+ addToExclude(projectPath, worktreePath, path.join(commonGitDirectory(projectPath), 'info', 'exclude'));
422
+ return { source, headCommitSha: restoreGit(worktreePath, ['rev-parse', '--verify', 'HEAD']) };
423
+ }
424
+ catch (err) {
425
+ if (err instanceof WorktreeCheckoutError)
426
+ throw err;
427
+ throw new WorktreeCheckoutError('git-failed', 'Git could not restore the worktree. Check the branch name, repository permissions and worktree registrations.');
428
+ }
429
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Parse a Keep-a-Changelog markdown file into ordered version sections. Each
3
+ * `## <version>` heading starts a new entry; everything until the next heading
4
+ * is its notes. A leading `v` on the version is stripped.
5
+ */
6
+ export function parseChangelog(markdown) {
7
+ const entries = [];
8
+ let current = null;
9
+ for (const line of markdown.split('\n')) {
10
+ const heading = line.match(/^##\s+v?(\d+\.\d+\.\d+[\w./-]*)\s*$/);
11
+ if (heading) {
12
+ if (current)
13
+ entries.push({ version: current.version, notes: current.lines.join('\n').trim() });
14
+ current = { version: heading[1], lines: [] };
15
+ }
16
+ else if (current) {
17
+ current.lines.push(line);
18
+ }
19
+ }
20
+ if (current)
21
+ entries.push({ version: current.version, notes: current.lines.join('\n').trim() });
22
+ return entries;
23
+ }
@@ -0,0 +1,71 @@
1
+ import fs from 'node:fs';
2
+ import { stripVTControlCharacters } from 'node:util';
3
+ import { parseChangelog } from './changelog.js';
4
+ /** Optional package asset: a missing changelog must never prevent startup. */
5
+ export function readStartupNotes(file) {
6
+ try {
7
+ return fs.readFileSync(file, 'utf-8');
8
+ }
9
+ catch {
10
+ return '';
11
+ }
12
+ }
13
+ function plainHighlight(line) {
14
+ const text = stripVTControlCharacters(line)
15
+ .replace(/!?\[([^\]]+)\]\([^)]*\)/g, '$1')
16
+ .replace(/[*`~]/g, '')
17
+ .replace(/\s+/g, ' ')
18
+ .trim();
19
+ return text.length > 92 ? `${text.slice(0, 91).trimEnd()}…` : text;
20
+ }
21
+ export function formatStartupBanner(options) {
22
+ const style = (code, text) => (options.color ? `\x1b[${code}m${text}\x1b[0m` : text);
23
+ const url = options.devClientOrigin?.trim().replace(/\/+$/, '') || `http://localhost:${options.port}`;
24
+ const lines = [
25
+ '',
26
+ ` ${style(1, '工房 Kōbō')} ${style(2, `v${options.version}`)}`,
27
+ ` ${style(2, 'Your development workshop')}`,
28
+ '',
29
+ ` ${style(32, '✓')} Server ready`,
30
+ ` → ${style(1, url)}`,
31
+ ];
32
+ if (options.networkEnabled) {
33
+ for (const lanUrl of options.lanUrls ?? [])
34
+ lines.push(` LAN: ${lanUrl}`);
35
+ if (options.token)
36
+ lines.push(` Token: ${options.token}`);
37
+ }
38
+ const release = parseChangelog(options.changelog ?? '').find((entry) => entry.version === options.version);
39
+ const highlights = (release?.notes ?? '')
40
+ .split('\n')
41
+ .filter((line) => /^[-*+]\s+/.test(line))
42
+ .map((line) => plainHighlight(line.slice(2)))
43
+ .filter(Boolean);
44
+ if (highlights.length > 0) {
45
+ lines.push('', ` ${style(1, `What’s new · ${options.version}`)}`);
46
+ for (const highlight of highlights.slice(0, 5))
47
+ lines.push(` • ${highlight}`);
48
+ lines.push(` Full changelog: ${url}/#/changelog`);
49
+ }
50
+ lines.push('', ` ${style(2, options.networkEnabled ? 'Network access enabled' : 'Local access only')}`, ` ${style(2, 'Ctrl+C to stop')}`, '');
51
+ return lines.join('\n');
52
+ }
53
+ /** Only animate an interactive terminal; redirected logs stay plain text. */
54
+ export function startStartupSpinner() {
55
+ if (!process.stderr.isTTY || process.env.TERM === 'dumb')
56
+ return () => { };
57
+ const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
58
+ let frame = 0;
59
+ const render = () => process.stderr.write(`\r ${frames[frame++ % frames.length]} Starting Kōbō…`);
60
+ render();
61
+ const timer = setInterval(render, 80);
62
+ timer.unref();
63
+ return () => {
64
+ clearInterval(timer);
65
+ process.stderr.write('\r\x1b[2K');
66
+ };
67
+ }
68
+ export function startupDebug(message) {
69
+ if (process.env.KOBO_VERBOSE === '1')
70
+ console.log(message);
71
+ }
@@ -0,0 +1,22 @@
1
+ const busyWorkspaces = new Set();
2
+ export class WorkspaceLifecycleBusyError extends Error {
3
+ code = 'workspace-busy';
4
+ constructor() {
5
+ super('Another workspace operation is in progress. Wait for it to finish and retry.');
6
+ }
7
+ }
8
+ export function isWorkspaceLifecycleBusy(id) {
9
+ return busyWorkspaces.has(id);
10
+ }
11
+ /** Exclude competing restore/purge/delete operations, including their awaits. */
12
+ export async function withWorkspaceLifecycleGuard(id, action) {
13
+ if (busyWorkspaces.has(id))
14
+ throw new WorkspaceLifecycleBusyError();
15
+ busyWorkspaces.add(id);
16
+ try {
17
+ return await action();
18
+ }
19
+ finally {
20
+ busyWorkspaces.delete(id);
21
+ }
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loicngr/kobo",
3
- "version": "1.11.32",
3
+ "version": "1.11.34",
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,4 +1,4 @@
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(`
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-BATViFoR.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-mF8Kofv1.js";import{r as de,t as B}from"./pending-diff-open-DsW49A6Z.js";import{t as V}from"./documents-C1u794ea.js";import{a as H,o as U}from"./use-tours-Cz5Zz63W.js";import{i as fe,n as W,o as pe,r as me,t as he}from"./render-chat-markdown-Ddq-hxhM.js";import{a as ge,i as _e,n as G,o as ve,r as ye,s as be}from"./WorkspacePage-Aay3kkPT.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
2
  `),r=t.split(`
3
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
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(`
@@ -1 +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};
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-BATViFoR.js";import{a as v,i as y,n as b}from"./use-tours-Cz5Zz63W.js";import{n as x}from"./render-chat-markdown-Ddq-hxhM.js";import{t as S}from"./QChip-CJ6WmvGE.js";import{n as C,t as w}from"./TourReplayButton-DHFo5_Kk.js";import{t as T}from"./DrawerToggleButton-aD_LMlna.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};
@@ -1 +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};
1
+ import{V as e,nt as t}from"./QBtn-DqZryKOh.js";import{Ht as n,Ut as r}from"./index-BATViFoR.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};
@@ -1,2 +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
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-BATViFoR.js";import{t as se}from"./QMarkupTable-MxPL53nz.js";import{a as m,i as h}from"./use-tours-Cz5Zz63W.js";var g=[`workspace`,`engine`,`model`,`status`,`branch`,`tasks_done`,`tasks_total`,`commits`,`files_changed`,`insertions`,`deletions`,`agent_messages`,`user_messages`,`injected_prompts`,`questions`,`tool_calls`,`errors`,`input_tokens`,`output_tokens`,`sessions`,`duration_seconds`];function _(e){if(e==null)return``;let t=String(e);return/[",\r\n]/.test(t)?`"${t.replace(/"/g,`""`)}"`:t}function v(e){let t=e.map(e=>{let t=e.gitStats,n=e.activity;return[e.workspace.name,e.workspace.engine,e.workspace.model,e.workspace.status,e.workspace.workingBranch,e.tasks.done,e.tasks.total,t?.commitCount??null,t?.filesChanged??null,t?.insertions??null,t?.deletions??null,n.agentMessages,n.userMessages,n.injectedPrompts,n.questions,n.toolCalls,n.errors,n.inputTokens,n.outputTokens,n.sessions,Math.round(n.durationMs/1e3)].map(_).join(`,`)});return`${[g.join(`,`),...t].join(`\r
2
2
  `)}`}var y={key:0,class:`comparison-panel q-pa-md`},b={class:`row items-center q-mb-sm`},x={class:`text-subtitle2`},S={class:`text-caption text-kobo-3 q-mb-sm`},C={class:`text-left`},w={class:`text-left`},T={class:`text-right`},E={class:`text-right`},D={class:`text-right`},O={class:`text-right`},k={class:`text-right`},A={class:`text-right`},j={class:`text-right`},M={class:`text-right`},N={class:`text-right`},P={class:`text-right`},F={class:`text-right`},I={class:`text-caption text-kobo-3 comparison-mono`},L={key:0,class:`text-caption text-kobo-3`},R={class:`text-right comparison-mono`},z={class:`text-right`},B={class:`text-right`},V={class:`text-right`},ce={key:0,class:`comparison-mono`},H={class:`text-kobo-success`},U={class:`text-kobo-danger q-ml-xs`},W={key:1,class:`text-kobo-3`},G={class:`text-right comparison-mono`},le=[`title`],ue={class:`text-right`},de={class:`text-right`},fe={class:`text-right comparison-mono`},pe=[`title`],me={class:`text-right`},he={class:`text-right comparison-mono`},ge={class:`text-right`},_e={key:1,class:`text-caption text-kobo-3`},ve={key:0,class:`text-caption text-kobo-warning q-mt-sm`},K=m(f({__name:`ComparisonPanel`,props:{workspaceId:{}},setup(f){let m=f;function g(e){return e<1e3?String(e):e<1e6?`${(e/1e3).toFixed(+(e<1e4))}k`:`${(e/1e6).toFixed(1)}M`}function _(e){if(e<=0)return`-`;let t=Math.round(e/1e3);if(t<60)return q(`reliability.durationSeconds`,{s:t});let n=Math.floor(t/60);return n<60?q(`reliability.durationMinutes`,{m:n,s:t%60}):q(`reliability.durationHours`,{h:Math.floor(n/60),m:n%60})}let K=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};