@loicngr/kobo 1.8.9 → 1.9.1

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 (71) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +10 -0
  3. package/dist/server/db/migrations.js +18 -0
  4. package/dist/server/db/schema.js +1 -0
  5. package/dist/server/index.js +14 -2
  6. package/dist/server/middleware/network-auth-middleware.js +12 -1
  7. package/dist/server/routes/settings.js +5 -0
  8. package/dist/server/routes/workspaces.js +29 -1
  9. package/dist/server/services/network-access-service.js +23 -1
  10. package/dist/server/services/pr-watcher-service.js +15 -1
  11. package/dist/server/services/settings-service.js +16 -0
  12. package/dist/server/services/workspace-service.js +26 -0
  13. package/package.json +1 -1
  14. package/src/client/dist/spa/assets/{ActivityFeed-CFtA0ESZ.js → ActivityFeed-9SMCiAn6.js} +1 -1
  15. package/src/client/dist/spa/assets/{ChangelogPage-BRRQ3rbp.js → ChangelogPage-V-wG4ROg.js} +1 -1
  16. package/src/client/dist/spa/assets/{ClosePopup-C6lH1yCG.js → ClosePopup-BOISqscq.js} +1 -1
  17. package/src/client/dist/spa/assets/{CreatePage-BTCe-DOl.js → CreatePage-Dg_sW17N.js} +1 -1
  18. package/src/client/dist/spa/assets/{DiffViewer-4tJkKsps.js → DiffViewer-BiVY7uho.js} +3 -3
  19. package/src/client/dist/spa/assets/{HealthPage-BkEv-aMq.js → HealthPage-Bu18TAZd.js} +1 -1
  20. package/src/client/dist/spa/assets/{MainLayout-DXz5Vnxf.css → MainLayout-7nwhu8UE.css} +1 -1
  21. package/src/client/dist/spa/assets/{MainLayout-Bf9oF2M-.js → MainLayout-DCLtuMGJ.js} +3 -3
  22. package/src/client/dist/spa/assets/{QBtnToggle-xCWfa0zI.js → QBtnToggle-BEgY0AkW.js} +1 -1
  23. package/src/client/dist/spa/assets/{QChip-BdkOPqy5.js → QChip-Ccf5FEQu.js} +1 -1
  24. package/src/client/dist/spa/assets/{QExpansionItem-BDyoC1Ly.js → QExpansionItem-CYcOrwbm.js} +1 -1
  25. package/src/client/dist/spa/assets/{QScrollArea-DeI8xL_d.js → QScrollArea-BYYLivp9.js} +1 -1
  26. package/src/client/dist/spa/assets/{QSelect-DxY4RU7V.js → QSelect-DJgkh8M3.js} +1 -1
  27. package/src/client/dist/spa/assets/{QTooltip-Cpm_IfVm.js → QTooltip-epbJipNF.js} +1 -1
  28. package/src/client/dist/spa/assets/{SearchPage-eh-XyEGg.js → SearchPage-pREfSfc6.js} +1 -1
  29. package/src/client/dist/spa/assets/SettingsPage-DLBFaoj3.js +16 -0
  30. package/src/client/dist/spa/assets/SettingsPage-DR5mOiX3.css +1 -0
  31. package/src/client/dist/spa/assets/{TouchPan-DHAMpPA1.js → TouchPan-DkFNDIAU.js} +1 -1
  32. package/src/client/dist/spa/assets/WorkspacePage-DlN_zJvE.js +4 -0
  33. package/src/client/dist/spa/assets/{WorkspacePage-DauW-aqm.css → WorkspacePage-axYxoa9m.css} +1 -1
  34. package/src/client/dist/spa/assets/{build-path-tree-JfzwoWFk.js → build-path-tree-Ol62y1Kn.js} +1 -1
  35. package/src/client/dist/spa/assets/{cssMode-CqkmkxoC.js → cssMode-B6O6JP-b.js} +1 -1
  36. package/src/client/dist/spa/assets/{documents-DM1f62Ca.js → documents-XYso3qnK.js} +1 -1
  37. package/src/client/dist/spa/assets/{editor.api2-IJMSUmRN.js → editor.api2-DXnjOqbp.js} +1 -1
  38. package/src/client/dist/spa/assets/{editor.main-CR76sugj.js → editor.main-0W7zX41H.js} +2 -2
  39. package/src/client/dist/spa/assets/{expand-template-lTTAWhou.js → expand-template-BsmF6e32.js} +1 -1
  40. package/src/client/dist/spa/assets/{formatters-_8dkjSkO.js → formatters-DB4LxyaP.js} +1 -1
  41. package/src/client/dist/spa/assets/{freemarker2-DXRiOLBf.js → freemarker2-DMoM0_gk.js} +1 -1
  42. package/src/client/dist/spa/assets/{handlebars-D0LypT-N.js → handlebars-Da81JqAH.js} +1 -1
  43. package/src/client/dist/spa/assets/{html-DmKSVUQI.js → html-CaX0PPST.js} +1 -1
  44. package/src/client/dist/spa/assets/{htmlMode-D63dd2k1.js → htmlMode-vYUYLNhw.js} +1 -1
  45. package/src/client/dist/spa/assets/i18n-CIIGUi3c.js +1 -0
  46. package/src/client/dist/spa/assets/{index-DODmyTEl.js → index-02IPrCWM.js} +7 -7
  47. package/src/client/dist/spa/assets/{javascript-BAUCdi7S.js → javascript-KVXsoiIo.js} +1 -1
  48. package/src/client/dist/spa/assets/{jsonMode-COygYAf4.js → jsonMode-DxQZuUA4.js} +1 -1
  49. package/src/client/dist/spa/assets/{kobo-commands-DRr54Gj1.js → kobo-commands-DpqDgjYQ.js} +1 -1
  50. package/src/client/dist/spa/assets/{layout-CvuA9F6q.js → layout-0RUyV_n-.js} +1 -1
  51. package/src/client/dist/spa/assets/{liquid-oq8bpzTN.js → liquid-ezLYma6x.js} +1 -1
  52. package/src/client/dist/spa/assets/{lspLanguageFeatures-CVL-3CRs.js → lspLanguageFeatures-B_BCv0M4.js} +1 -1
  53. package/src/client/dist/spa/assets/{mdx-Byp34ebl.js → mdx-BatnpHIx.js} +1 -1
  54. package/src/client/dist/spa/assets/{monaco.contribution-D2h-fJiD.js → monaco.contribution-Dkhpc3_y.js} +2 -2
  55. package/src/client/dist/spa/assets/{network-auth-DfISpE97.js → network-auth-CRzlXaPk.js} +1 -1
  56. package/src/client/dist/spa/assets/{project-color-Cvt0AAeh.js → project-color-CubSkld3.js} +1 -1
  57. package/src/client/dist/spa/assets/{python-D-1c5J5l.js → python-Bj1W8loP.js} +1 -1
  58. package/src/client/dist/spa/assets/{razor-CPeWkxpV.js → razor-CuJR7SS8.js} +1 -1
  59. package/src/client/dist/spa/assets/{render-chat-markdown-DbKsA_Ux.js → render-chat-markdown-OO8yJF8P.js} +1 -1
  60. package/src/client/dist/spa/assets/{tsMode-BFEzVMJt.js → tsMode-CkPJHNND.js} +1 -1
  61. package/src/client/dist/spa/assets/{typescript-C-84YsEc.js → typescript-snHlQcwB.js} +1 -1
  62. package/src/client/dist/spa/assets/{use-onboarding-Bxi9kF5f.js → use-onboarding-DXKr7HBO.js} +1 -1
  63. package/src/client/dist/spa/assets/{use-quasar-B20UL17o.js → use-quasar-CwG_Rs2g.js} +1 -1
  64. package/src/client/dist/spa/assets/{workers-B5wOtN6Y.js → workers-BK0CNSbu.js} +1 -1
  65. package/src/client/dist/spa/assets/{xml-BjPqYcxj.js → xml-B40Ya2Q2.js} +1 -1
  66. package/src/client/dist/spa/assets/{yaml-lZDMbDzQ.js → yaml-DAP0EIwM.js} +1 -1
  67. package/src/client/dist/spa/index.html +1 -1
  68. package/src/client/dist/spa/assets/SettingsPage-DTd5pM5A.js +0 -16
  69. package/src/client/dist/spa/assets/SettingsPage-DfYhuzv0.css +0 -1
  70. package/src/client/dist/spa/assets/WorkspacePage-Cdq798Xz.js +0 -4
  71. package/src/client/dist/spa/assets/i18n-DIxccx-f.js +0 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ 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.9.1
8
+
9
+ - fix: exempt /api/health from network-auth and add local Docker compose stacks
10
+
11
+ ## 1.9.0
12
+
13
+ - feat: opt out a workspace from PR-watch (skip forge polling, keep local git stats)
14
+ - feat: official Docker image, with an example Traefik reverse-proxy stack
15
+ - feat: reverse-proxy-safe auth mode + env-var network-access bootstrap
16
+ - feat: workspace toolbar polish (aligned model badges, copy engine session ID)
17
+ - docs: document reverse-proxy mode, Docker deployment, and Codex maturity
18
+
7
19
  ## 1.8.9
8
20
 
9
21
  - docs: sync README/AGENTS.md with recent changes, dedupe CHANGELOG
package/README.md CHANGED
@@ -55,6 +55,16 @@ Open <http://localhost:3000> (or whichever port you picked). Data is persisted u
55
55
 
56
56
  Want to run from source or contribute? See [`CONTRIBUTING.md`](./CONTRIBUTING.md).
57
57
 
58
+ ### Docker
59
+
60
+ An official `Dockerfile` and three ready-to-use Compose files ship in this repository: a quick local
61
+ test stack, a Traefik-fronted local rehearsal (`kobo.localhost`, no domain needed), and a full VPS
62
+ reference (Traefik + Let's Encrypt, SSH access, optional Docker-socket passthrough for the
63
+ dev-server panel). See [`CONFIGURATION.md`](./CONFIGURATION.md#docker-deployment) for the complete
64
+ setup — every compose file, every env var, every volume mount, and the `KOBO_NETWORK_ACCESS_ENABLED`
65
+ / `KOBO_NETWORK_ACCESS_BEHIND_PROXY` env vars that bootstrap network access at container boot with
66
+ no manual step.
67
+
58
68
  ## Configuration
59
69
 
60
70
  The most common knobs:
@@ -389,6 +389,24 @@ export const migrations = [
389
389
  }
390
390
  },
391
391
  },
392
+ {
393
+ version: 30,
394
+ name: 'add-pr-watch-disabled',
395
+ migrate: (db) => {
396
+ // When set, the PR watcher skips the forge (gh/glab) call for this
397
+ // workspace every tick — no PR-status fetch, no auto-archive-on-merge,
398
+ // no auto-purge, no PR-derived attention badges. Local git stats
399
+ // (ahead/behind, changed files, rebase status) keep updating every
400
+ // tick regardless — see pr-watcher-service.ts's checkPrStatuses().
401
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='workspaces'").get();
402
+ if (!table)
403
+ return;
404
+ const cols = db.prepare('PRAGMA table_info(workspaces)').all();
405
+ if (!cols.some((c) => c.name === 'pr_watch_disabled_at')) {
406
+ db.prepare('ALTER TABLE workspaces ADD COLUMN pr_watch_disabled_at TEXT').run();
407
+ }
408
+ },
409
+ },
392
410
  ];
393
411
  /** Current schema version — always equals the highest migration version. */
394
412
  export const SCHEMA_VERSION = migrations.length > 0 ? migrations[migrations.length - 1].version : 1;
@@ -21,6 +21,7 @@ export function initSchema(db) {
21
21
  has_unread INTEGER NOT NULL DEFAULT 0,
22
22
  archived_at TEXT,
23
23
  favorited_at TEXT,
24
+ pr_watch_disabled_at TEXT,
24
25
  tags TEXT NOT NULL DEFAULT '[]',
25
26
  engine TEXT NOT NULL DEFAULT 'claude-code',
26
27
  auto_loop INTEGER NOT NULL DEFAULT 0,
@@ -31,10 +31,10 @@ import { runContentMigrationIfNeeded } from './services/content-migration-servic
31
31
  import * as cronService from './services/cron-service.js';
32
32
  import { createDailyDbBackupIfNeeded, createPreMigrationBackup } from './services/db-backup-service.js';
33
33
  import { startDevServer, stopDevServer } from './services/dev-server-service.js';
34
- import { authorizeWsUpgrade, getLanUrls, resolveBindHost } from './services/network-access-service.js';
34
+ import { authorizeWsUpgrade, generateToken, getLanUrls, resolveBindHost, resolveNetworkAccessEnvOverrides, } from './services/network-access-service.js';
35
35
  import { startPrWatcher, stopPrWatcher } from './services/pr-watcher-service.js';
36
36
  import * as quotaBackoffService from './services/quota-backoff-service.js';
37
- import { getGlobalSettings } from './services/settings-service.js';
37
+ import { getGlobalSettings, updateNetworkAccessSettings } from './services/settings-service.js';
38
38
  import { reloadDefaultTemplates } from './services/templates-service.js';
39
39
  import { createTerminal, destroyAllTerminals, getTerminal } from './services/terminal-service.js';
40
40
  import { startUsagePoller, stopUsagePoller } from './services/usage/index.js';
@@ -165,6 +165,16 @@ if (clientDistPath) {
165
165
  });
166
166
  }
167
167
  // Create HTTP server via @hono/node-server
168
+ const networkAccessEnvOverrides = resolveNetworkAccessEnvOverrides(process.env);
169
+ if (Object.keys(networkAccessEnvOverrides).length > 0) {
170
+ const patch = {
171
+ ...networkAccessEnvOverrides,
172
+ };
173
+ if (networkAccessEnvOverrides.networkAccessEnabled && !getGlobalSettings().networkAccessToken) {
174
+ patch.networkAccessToken = generateToken();
175
+ }
176
+ updateNetworkAccessSettings(patch);
177
+ }
168
178
  const bindHost = resolveBindHost(getGlobalSettings().networkAccessEnabled);
169
179
  const server = serve({
170
180
  fetch: app.fetch,
@@ -176,6 +186,7 @@ const server = serve({
176
186
  console.log(`Server running — network access ON (port ${info.port})`);
177
187
  for (const url of getLanUrls(info.port))
178
188
  console.log(` LAN: ${url}`);
189
+ console.log(` Token: ${getGlobalSettings().networkAccessToken}`);
179
190
  }
180
191
  else {
181
192
  console.log(`Server running at http://localhost:${info.port} (localhost only)`);
@@ -392,6 +403,7 @@ server.on('upgrade', (request, socket, head) => {
392
403
  rawUrl: request.url,
393
404
  enabled: wsGlobal.networkAccessEnabled,
394
405
  expectedToken: wsGlobal.networkAccessToken,
406
+ trustLoopback: !wsGlobal.networkAccessBehindProxy,
395
407
  })) {
396
408
  console.warn(`[network-auth] WS 401 (missing/invalid token) from ${request.socket.remoteAddress ?? 'unknown'} ${pathname}`);
397
409
  socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
@@ -4,11 +4,21 @@ import { getGlobalSettings } from '../services/settings-service.js';
4
4
  /**
5
5
  * Gates non-loopback requests behind the network-access token.
6
6
  *
7
- * Loopback requests always pass (the host machine's own usage is frictionless).
7
+ * Loopback requests pass without a token (the host machine's own usage is
8
+ * frictionless) — unless `networkAccessBehindProxy` is enabled, in which case
9
+ * loopback is treated like any other address (see network-access-service.ts).
8
10
  * The client IP comes only from the OS socket via getConnInfo, never from
9
11
  * X-Forwarded-For, so a remote client cannot spoof a loopback address.
12
+ *
13
+ * `/api/health` is always exempt, regardless of `networkAccessBehindProxy`:
14
+ * it exposes only `{ status, version }` (nothing sensitive), and Docker's own
15
+ * HEALTHCHECK / a Compose healthcheck / an orchestrator's liveness probe has
16
+ * no way to supply the runtime-generated token — without this exemption, a
17
+ * "behind a reverse proxy" deployment's own container never reports healthy.
10
18
  */
11
19
  export const networkAuthMiddleware = async (c, next) => {
20
+ if (c.req.path === '/api/health')
21
+ return next();
12
22
  const address = getConnInfo(c).remote.address;
13
23
  const global = getGlobalSettings();
14
24
  const decision = evaluateNetworkAccess({
@@ -16,6 +26,7 @@ export const networkAuthMiddleware = async (c, next) => {
16
26
  enabled: global.networkAccessEnabled,
17
27
  expectedToken: global.networkAccessToken,
18
28
  providedToken: c.req.header('X-Kobo-Token'),
29
+ trustLoopback: !global.networkAccessBehindProxy,
19
30
  });
20
31
  if (decision.allow)
21
32
  return next();
@@ -54,6 +54,7 @@ app.get('/network', (c) => {
54
54
  return c.json({
55
55
  enabled: global.networkAccessEnabled,
56
56
  token: global.networkAccessToken,
57
+ behindProxy: global.networkAccessBehindProxy,
57
58
  urls: getLanUrls(getBackendPort()),
58
59
  });
59
60
  }
@@ -81,10 +82,14 @@ app.post('/network', async (c) => {
81
82
  if (body.regenerate) {
82
83
  patch.networkAccessToken = generateToken();
83
84
  }
85
+ if (typeof body.behindProxy === 'boolean' && body.behindProxy !== current.networkAccessBehindProxy) {
86
+ patch.networkAccessBehindProxy = body.behindProxy;
87
+ }
84
88
  const updated = settingsService.updateNetworkAccessSettings(patch);
85
89
  return c.json({
86
90
  enabled: updated.networkAccessEnabled,
87
91
  token: updated.networkAccessToken,
92
+ behindProxy: updated.networkAccessBehindProxy,
88
93
  urls: getLanUrls(getBackendPort()),
89
94
  restartRequired,
90
95
  });
@@ -24,7 +24,7 @@ import { computeGitStats } from '../services/git-stats-service.js';
24
24
  import { DEFAULT_NOTION_INITIAL_PROMPT, DEFAULT_SENTRY_INITIAL_PROMPT, renderNotionInitialPrompt, renderSentryInitialPrompt, } from '../services/initial-prompt-template-service.js';
25
25
  import * as notionService from '../services/notion-service.js';
26
26
  import { renderPrTemplate } from '../services/pr-template-service.js';
27
- import { getAllGitStats, getAllPrSnapshots, refreshPrSnapshot } from '../services/pr-watcher-service.js';
27
+ import { clearPrSnapshotCache, getAllGitStats, getAllPrSnapshots, refreshPrSnapshot, } from '../services/pr-watcher-service.js';
28
28
  import * as quotaBackoffService from '../services/quota-backoff-service.js';
29
29
  import { getActiveReviewTemplate, renderReviewTemplate } from '../services/review-template-service.js';
30
30
  import * as sentryService from '../services/sentry-service.js';
@@ -1686,6 +1686,34 @@ app.delete('/:id/favorite', (c) => {
1686
1686
  return c.json({ error: msg }, status);
1687
1687
  }
1688
1688
  });
1689
+ // POST /api/workspaces/:id/pr-watch-disabled — skip PR-watcher forge polling for this workspace
1690
+ app.post('/:id/pr-watch-disabled', (c) => {
1691
+ const { id } = c.req.param();
1692
+ try {
1693
+ const ws = workspaceService.setPrWatchDisabled(id);
1694
+ clearPrSnapshotCache(id);
1695
+ return c.json(ws);
1696
+ }
1697
+ catch (err) {
1698
+ const msg = err instanceof Error ? err.message : 'Unknown error';
1699
+ const status = msg.includes('not found') ? 404 : 500;
1700
+ return c.json({ error: msg }, status);
1701
+ }
1702
+ });
1703
+ // DELETE /api/workspaces/:id/pr-watch-disabled — resume PR-watcher forge polling, refresh immediately
1704
+ app.delete('/:id/pr-watch-disabled', async (c) => {
1705
+ const { id } = c.req.param();
1706
+ try {
1707
+ const ws = workspaceService.setPrWatchEnabled(id);
1708
+ const prSnapshot = await refreshPrSnapshot(id).catch(() => null);
1709
+ return c.json({ workspace: ws, prSnapshot });
1710
+ }
1711
+ catch (err) {
1712
+ const msg = err instanceof Error ? err.message : 'Unknown error';
1713
+ const status = msg.includes('not found') ? 404 : 500;
1714
+ return c.json({ error: msg }, status);
1715
+ }
1716
+ });
1689
1717
  // PUT /api/workspaces/:id/tags — replace the workspace's tag list
1690
1718
  app.put('/:id/tags', async (c) => {
1691
1719
  const { id } = c.req.param();
@@ -41,7 +41,8 @@ export function tokenMatches(provided, expected) {
41
41
  }
42
42
  /** Core gate decision shared by the HTTP middleware and the WS upgrade guard. */
43
43
  export function evaluateNetworkAccess(params) {
44
- if (isLoopbackAddress(params.address))
44
+ const trustLoopback = params.trustLoopback ?? true;
45
+ if (trustLoopback && isLoopbackAddress(params.address))
45
46
  return { allow: true, status: 200 };
46
47
  if (!params.enabled)
47
48
  return { allow: false, status: 403 };
@@ -63,5 +64,26 @@ export function authorizeWsUpgrade(params) {
63
64
  enabled: params.enabled,
64
65
  expectedToken: params.expectedToken,
65
66
  providedToken,
67
+ trustLoopback: params.trustLoopback,
66
68
  }).allow;
67
69
  }
70
+ /**
71
+ * Reads KOBO_NETWORK_ACCESS_ENABLED / KOBO_NETWORK_ACCESS_BEHIND_PROXY and
72
+ * returns only the fields an env var actually specifies — an unset env var
73
+ * means "leave current settings alone" (key omitted from the result); a SET
74
+ * env var always produces a decisive true/false, even for a value that isn't
75
+ * literally "true"/"1" (an explicit non-true value is a deliberate "off",
76
+ * not "don't touch"). Re-applied on every server boot — see index.ts.
77
+ */
78
+ export function resolveNetworkAccessEnvOverrides(env) {
79
+ const overrides = {};
80
+ if (env.KOBO_NETWORK_ACCESS_ENABLED !== undefined) {
81
+ overrides.networkAccessEnabled =
82
+ env.KOBO_NETWORK_ACCESS_ENABLED === 'true' || env.KOBO_NETWORK_ACCESS_ENABLED === '1';
83
+ }
84
+ if (env.KOBO_NETWORK_ACCESS_BEHIND_PROXY !== undefined) {
85
+ overrides.networkAccessBehindProxy =
86
+ env.KOBO_NETWORK_ACCESS_BEHIND_PROXY === 'true' || env.KOBO_NETWORK_ACCESS_BEHIND_PROXY === '1';
87
+ }
88
+ return overrides;
89
+ }
@@ -45,6 +45,13 @@ export function getAllGitStats() {
45
45
  }
46
46
  return out;
47
47
  }
48
+ /** Drops a single workspace's cached PR snapshot — called when PR-watch is
49
+ * disabled for it, so a stale "Ready to merge"-style badge doesn't linger
50
+ * after the toggle (the watcher loop skips, rather than clears, a disabled
51
+ * workspace's entry, so this must be done explicitly by the caller). */
52
+ export function clearPrSnapshotCache(workspaceId) {
53
+ lastKnownPr.delete(workspaceId);
54
+ }
48
55
  /**
49
56
  * Test-only escape hatch — drops the in-memory cache so each test starts
50
57
  * from a clean slate. Not part of the public API.
@@ -109,7 +116,14 @@ export async function checkPrStatuses() {
109
116
  if (!fs.existsSync(ws.worktreePath))
110
117
  continue;
111
118
  try {
112
- const pr = await getForgeProvider(resolveForge(ws.projectPath)).getPrStatus(ws.worktreePath, ws.workingBranch);
119
+ // Opt-out: skip the forge call entirely for a workspace with PR-watch
120
+ // disabled — no PR-status fetch, no auto-archive/purge, no PR-derived
121
+ // badges. Git stats (below) still run every tick regardless; the
122
+ // existing `if (!pr) continue` further down already handles a null
123
+ // `pr` correctly (same path taken by a workspace with no PR yet).
124
+ const pr = ws.prWatchDisabledAt
125
+ ? null
126
+ : await getForgeProvider(resolveForge(ws.projectPath)).getPrStatus(ws.worktreePath, ws.workingBranch);
113
127
  // Detect a PR base change BEFORE computing git stats so the new base
114
128
  // is used in commitCount / behindCount / diffStats. Otherwise the
115
129
  // user keeps seeing stale ahead/behind counts vs the OLD base until
@@ -654,6 +654,18 @@ const settingsMigrations = [
654
654
  }
655
655
  },
656
656
  },
657
+ {
658
+ version: 41,
659
+ name: 'add-network-access-behind-proxy',
660
+ migrate: ({ global }) => {
661
+ // Disables the loopback-trust bypass when true — every request needs
662
+ // the token, even ones that look like they came from 127.0.0.1. Only
663
+ // meaningful when networkAccessEnabled is also true.
664
+ if (typeof global.networkAccessBehindProxy !== 'boolean') {
665
+ global.networkAccessBehindProxy = false;
666
+ }
667
+ },
668
+ },
657
669
  ];
658
670
  /** Current settings schema version — always equals the highest migration version. */
659
671
  export const SETTINGS_SCHEMA_VERSION = settingsMigrations.length > 0 ? settingsMigrations[settingsMigrations.length - 1].version : 0;
@@ -702,6 +714,7 @@ function defaultSettings() {
702
714
  autoPurgeOnPrMerged: false,
703
715
  networkAccessEnabled: false,
704
716
  networkAccessToken: '',
717
+ networkAccessBehindProxy: false,
705
718
  browserNotifications: true,
706
719
  audioNotifications: true,
707
720
  audioNotificationSound: 'hey.mp3',
@@ -1139,6 +1152,9 @@ export function updateNetworkAccessSettings(patch) {
1139
1152
  if (typeof patch.networkAccessToken === 'string') {
1140
1153
  settings.global.networkAccessToken = patch.networkAccessToken;
1141
1154
  }
1155
+ if (typeof patch.networkAccessBehindProxy === 'boolean') {
1156
+ settings.global.networkAccessBehindProxy = patch.networkAccessBehindProxy;
1157
+ }
1142
1158
  writeSettings(settings, { backup: true });
1143
1159
  return settings.global;
1144
1160
  }
@@ -54,6 +54,7 @@ function mapWorkspace(row) {
54
54
  hasUnread: row.has_unread === 1,
55
55
  archivedAt: row.archived_at,
56
56
  favoritedAt: row.favorited_at,
57
+ prWatchDisabledAt: row.pr_watch_disabled_at,
57
58
  tags: parseTags(row.tags),
58
59
  description: row.description,
59
60
  agentDescription: row.agent_description,
@@ -599,6 +600,31 @@ export function unsetFavorite(id) {
599
600
  }
600
601
  return getWorkspace(id);
601
602
  }
603
+ /** Skip the PR watcher's forge (gh/glab) call for this workspace every tick — no PR-status fetch,
604
+ * no auto-archive-on-merge, no auto-purge. Local git stats keep updating regardless. */
605
+ export function setPrWatchDisabled(id) {
606
+ const db = getDb();
607
+ const now = new Date().toISOString();
608
+ const result = db
609
+ .prepare('UPDATE workspaces SET pr_watch_disabled_at = ?, updated_at = ? WHERE id = ?')
610
+ .run(now, now, id);
611
+ if (result.changes === 0) {
612
+ throw new Error(`Workspace '${id}' not found`);
613
+ }
614
+ return getWorkspace(id);
615
+ }
616
+ /** Resume PR-watcher forge polling for this workspace. */
617
+ export function setPrWatchEnabled(id) {
618
+ const db = getDb();
619
+ const now = new Date().toISOString();
620
+ const result = db
621
+ .prepare('UPDATE workspaces SET pr_watch_disabled_at = NULL, updated_at = ? WHERE id = ?')
622
+ .run(now, id);
623
+ if (result.changes === 0) {
624
+ throw new Error(`Workspace '${id}' not found`);
625
+ }
626
+ return getWorkspace(id);
627
+ }
602
628
  /** Maximum tag length (characters) and max number of tags per workspace. */
603
629
  export const MAX_TAG_LENGTH = 50;
604
630
  export const MAX_WORKSPACE_TAGS = 50;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loicngr/kobo",
3
- "version": "1.8.9",
3
+ "version": "1.9.1",
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{$ as e,B as t,F as n,I as r,R as i,S as a,U as o,W as s,_ as c,at as l,b as u,c as d,ct as f,g as p,h as m,it as h,k as g,m as _,n as v,p as y,s as b,st as x,y as S}from"./vue.runtime.esm-bundler-JZnIeD9D.js";import{l as C,t as w}from"./QIcon-C6E-oEjI.js";import{B as T,C as E,N as D,S as O,d as k,p as A,x as j,z as ee}from"./index-DODmyTEl.js";import{t as te}from"./QSpinnerDots-DIV68-cV.js";import{t as M}from"./QTooltip-Cpm_IfVm.js";import{t as N}from"./QExpansionItem-BDyoC1Ly.js";import{t as ne}from"./QScrollArea-DeI8xL_d.js";import{t as re}from"./documents-DM1f62Ca.js";import{i as ie,n as ae,t as P}from"./render-chat-markdown-DbKsA_Ux.js";import{t as F}from"./_plugin-vue_export-helper-BDNMzG2s.js";function oe(e,t,n=!0){let r=[],i=new Map,a=new Map;for(let n=0;n<e.length;n++){let o=e[n],s=t?.[n];switch(o.kind){case`message:text`:{let e=i.get(o.messageId);if(e)e.text+=o.text,e.streaming=o.streaming;else{let e={type:`text`,messageId:o.messageId,text:o.text,streaming:o.streaming,ts:s};i.set(o.messageId,e),r.push(e)}break}case`message:end`:{let e=i.get(o.messageId);e&&(e.streaming=!1);break}case`message:thinking`:r.push({type:`thinking`,messageId:o.messageId,text:o.text,ts:s});break;case`tool:call`:{let e={type:`tool`,toolCallId:o.toolCallId,name:o.name,input:o.input,ts:s};a.set(o.toolCallId,e),r.push(e);break}case`tool:result`:{let e=a.get(o.toolCallId);e&&(e.result={output:o.output,isError:o.isError});break}case`session:started`:r.push({type:`session`,kind:`started`,detail:{engineSessionId:o.engineSessionId,model:o.model},ts:s});break;case`session:ended`:r.push({type:`session`,kind:`ended`,detail:{reason:o.reason,exitCode:o.exitCode},ts:s});break;case`session:compacted`:r.push({type:`session`,kind:`compacted`,ts:s});break;case`session:compacting`:case`session:brainstorm-complete`:case`session:user-input-requested`:case`message:raw`:case`skills:discovered`:case`usage`:case`rate_limit`:case`subagent:progress`:case`error`:break;default:}}let o=null;for(let e of r)e.type===`text`&&e.streaming&&(o&&(o.streaming=!1),o=e);return o&&!n&&(o.streaming=!1),r}function se(e,t){if(t.length===0)return e;let n=t.map(e=>({type:`user`,content:e.content,sender:e.sender,ts:e.ts})),r=[...e,...n];r.sort((e,t)=>{let n=e.ts??``,r=t.ts??``;return n===r?0:n?r?n<r?-1:1:-1:1});let i;for(let e of r)e.type===`user`&&e.sender!==`system-prompt`&&e.ts&&(!i||e.ts>i)&&(i=e.ts);if(i)for(let e of r)e.type===`text`&&e.streaming&&(!e.ts||e.ts<i)&&(e.streaming=!1);return r}var I=new Set([`setup`,`cleanup`,`archive`]);function L(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:I.has(e.sender)?`script`:`user`;case`session`:return`session`;default:return`agent`}}function ce(e){let t=[],n=null,r=null;for(let i of e){let e=L(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}var R={class:`text-caption text-grey-6`},z=a({__name:`SessionEventItem`,props:{item:{}},setup(e){let t=e,n=y(()=>{switch(t.item.kind){case`started`:return`session.started`;case`ended`:return`session.ended`;case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,t)=>(i(),c(`span`,R,f(e.$t(n.value)),1))}});function le(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){ue(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 ue(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=B(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 B(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 V=[`innerHTML`],H=F(a({__name:`TextMessageItem`,props:{item:{}},setup(e){let t=e,n=re(),r=k(),a=y(()=>{let e=r.selectedWorkspaceId;return e?n.documentsFor(e).map(e=>e.path):[]}),o=y(()=>ae(le(ie.parse(t.item.text,{async:!1,breaks:!0,gfm:!0}),a.value),{addAttr:[`data-document-path`]}));function s(e){let t=e.target?.closest(`.document-link`);if(!t)return;e.preventDefault();let i=t.getAttribute(`data-document-path`),a=r.selectedWorkspaceId;!i||!a||n.openDocumentByPath(a,i)}return(t,n)=>(i(),c(`div`,{class:`markdown-message`,onClick:s},[_(`div`,{innerHTML:o.value},null,8,V),e.item.streaming?(i(),m(C,{key:0,size:`xs`,class:`q-ml-xs`})):p(``,!0)]))}}),[[`__scopeId`,`data-v-1b7bd8ca`]]),de={key:0,class:`text-caption text-grey-5`,style:{"font-style":`italic`}},U=[`innerHTML`],W={key:1,style:{"white-space":`pre-wrap`}},G=F(a({__name:`ThinkingItem`,props:{item:{}},setup(e){let t=e,n=y(()=>t.item.text.trim().slice(0,100)),r=y(()=>t.item.text.trim().length>0),a=y(()=>t.item.text.trim().length>100),o=y(()=>P(t.item.text));return(t,l)=>r.value?(i(),c(`div`,de,[a.value?(i(),m(N,{key:0,dense:``,"dense-toggle":``,label:n.value,"header-class":`text-grey-5 text-caption`,style:{"font-style":`italic`}},{default:s(()=>[_(`div`,{class:`q-py-xs markdown-thinking`,innerHTML:o.value},null,8,U)]),_:1},8,[`label`])):(i(),c(`span`,W,f(e.item.text),1))])):p(``,!0)}}),[[`__scopeId`,`data-v-7f45ed94`]]);function K(e,t){let n=e.split(`
1
+ import{$ as e,B as t,F as n,I as r,R as i,S as a,U as o,W as s,_ as c,at as l,b as u,c as d,ct as f,g as p,h as m,it as h,k as g,m as _,n as v,p as y,s as b,st as x,y as S}from"./vue.runtime.esm-bundler-JZnIeD9D.js";import{l as C,t as w}from"./QIcon-C6E-oEjI.js";import{B as T,C as E,N as D,S as O,d as k,p as A,x as j,z as ee}from"./index-02IPrCWM.js";import{t as te}from"./QSpinnerDots-DIV68-cV.js";import{t as M}from"./QTooltip-epbJipNF.js";import{t as N}from"./QExpansionItem-CYcOrwbm.js";import{t as ne}from"./QScrollArea-BYYLivp9.js";import{t as re}from"./documents-XYso3qnK.js";import{i as ie,n as ae,t as P}from"./render-chat-markdown-OO8yJF8P.js";import{t as F}from"./_plugin-vue_export-helper-BDNMzG2s.js";function oe(e,t,n=!0){let r=[],i=new Map,a=new Map;for(let n=0;n<e.length;n++){let o=e[n],s=t?.[n];switch(o.kind){case`message:text`:{let e=i.get(o.messageId);if(e)e.text+=o.text,e.streaming=o.streaming;else{let e={type:`text`,messageId:o.messageId,text:o.text,streaming:o.streaming,ts:s};i.set(o.messageId,e),r.push(e)}break}case`message:end`:{let e=i.get(o.messageId);e&&(e.streaming=!1);break}case`message:thinking`:r.push({type:`thinking`,messageId:o.messageId,text:o.text,ts:s});break;case`tool:call`:{let e={type:`tool`,toolCallId:o.toolCallId,name:o.name,input:o.input,ts:s};a.set(o.toolCallId,e),r.push(e);break}case`tool:result`:{let e=a.get(o.toolCallId);e&&(e.result={output:o.output,isError:o.isError});break}case`session:started`:r.push({type:`session`,kind:`started`,detail:{engineSessionId:o.engineSessionId,model:o.model},ts:s});break;case`session:ended`:r.push({type:`session`,kind:`ended`,detail:{reason:o.reason,exitCode:o.exitCode},ts:s});break;case`session:compacted`:r.push({type:`session`,kind:`compacted`,ts:s});break;case`session:compacting`:case`session:brainstorm-complete`:case`session:user-input-requested`:case`message:raw`:case`skills:discovered`:case`usage`:case`rate_limit`:case`subagent:progress`:case`error`:break;default:}}let o=null;for(let e of r)e.type===`text`&&e.streaming&&(o&&(o.streaming=!1),o=e);return o&&!n&&(o.streaming=!1),r}function se(e,t){if(t.length===0)return e;let n=t.map(e=>({type:`user`,content:e.content,sender:e.sender,ts:e.ts})),r=[...e,...n];r.sort((e,t)=>{let n=e.ts??``,r=t.ts??``;return n===r?0:n?r?n<r?-1:1:-1:1});let i;for(let e of r)e.type===`user`&&e.sender!==`system-prompt`&&e.ts&&(!i||e.ts>i)&&(i=e.ts);if(i)for(let e of r)e.type===`text`&&e.streaming&&(!e.ts||e.ts<i)&&(e.streaming=!1);return r}var I=new Set([`setup`,`cleanup`,`archive`]);function L(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:I.has(e.sender)?`script`:`user`;case`session`:return`session`;default:return`agent`}}function ce(e){let t=[],n=null,r=null;for(let i of e){let e=L(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}var R={class:`text-caption text-grey-6`},z=a({__name:`SessionEventItem`,props:{item:{}},setup(e){let t=e,n=y(()=>{switch(t.item.kind){case`started`:return`session.started`;case`ended`:return`session.ended`;case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,t)=>(i(),c(`span`,R,f(e.$t(n.value)),1))}});function le(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){ue(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 ue(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=B(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 B(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 V=[`innerHTML`],H=F(a({__name:`TextMessageItem`,props:{item:{}},setup(e){let t=e,n=re(),r=k(),a=y(()=>{let e=r.selectedWorkspaceId;return e?n.documentsFor(e).map(e=>e.path):[]}),o=y(()=>ae(le(ie.parse(t.item.text,{async:!1,breaks:!0,gfm:!0}),a.value),{addAttr:[`data-document-path`]}));function s(e){let t=e.target?.closest(`.document-link`);if(!t)return;e.preventDefault();let i=t.getAttribute(`data-document-path`),a=r.selectedWorkspaceId;!i||!a||n.openDocumentByPath(a,i)}return(t,n)=>(i(),c(`div`,{class:`markdown-message`,onClick:s},[_(`div`,{innerHTML:o.value},null,8,V),e.item.streaming?(i(),m(C,{key:0,size:`xs`,class:`q-ml-xs`})):p(``,!0)]))}}),[[`__scopeId`,`data-v-1b7bd8ca`]]),de={key:0,class:`text-caption text-grey-5`,style:{"font-style":`italic`}},U=[`innerHTML`],W={key:1,style:{"white-space":`pre-wrap`}},G=F(a({__name:`ThinkingItem`,props:{item:{}},setup(e){let t=e,n=y(()=>t.item.text.trim().slice(0,100)),r=y(()=>t.item.text.trim().length>0),a=y(()=>t.item.text.trim().length>100),o=y(()=>P(t.item.text));return(t,l)=>r.value?(i(),c(`div`,de,[a.value?(i(),m(N,{key:0,dense:``,"dense-toggle":``,label:n.value,"header-class":`text-grey-5 text-caption`,style:{"font-style":`italic`}},{default:s(()=>[_(`div`,{class:`q-py-xs markdown-thinking`,innerHTML:o.value},null,8,U)]),_:1},8,[`label`])):(i(),c(`span`,W,f(e.item.text),1))])):p(``,!0)}}),[[`__scopeId`,`data-v-7f45ed94`]]);function K(e,t){let n=e.split(`
2
2
  `),r=t.split(`
3
3
  `),i=n.length,a=r.length,o=Array.from({length:i+1},()=>Array(a+1).fill(0));for(let e=i-1;e>=0;e--)for(let t=a-1;t>=0;t--)n[e]===r[t]?o[e][t]=o[e+1][t+1]+1:o[e][t]=Math.max(o[e+1][t],o[e][t+1]);let s=[],c=0,l=0;for(;c<i&&l<a;)n[c]===r[l]?(s.push({type:`context`,content:n[c]}),c++,l++):o[c+1][l]>=o[c][l+1]?(s.push({type:`del`,content:n[c]}),c++):(s.push({type:`add`,content:r[l]}),l++);for(;c<i;)s.push({type:`del`,content:n[c++]});for(;l<a;)s.push({type:`add`,content:r[l++]});return s}function fe(e){let t=e.split(`
4
4
  `),n=[];for(let e of t)e.startsWith(`@@`)||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 pe(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=fe(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{$ as e,B as t,F as n,R as r,S as i,W as a,_ as o,b as s,c,ct as l,g as u,h as d,it as f,m as p}from"./vue.runtime.esm-bundler-JZnIeD9D.js";import{N as m,gt as h,mt as g,s as _}from"./index-DODmyTEl.js";import{t as v}from"./render-chat-markdown-DbKsA_Ux.js";import{t as y}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{t as b}from"./QSpace-ezNrZkuj.js";import{t as x}from"./QChip-BdkOPqy5.js";import{t as S}from"./QPage-D3rjwA1l.js";var C={class:`row items-center q-mb-md`},w={class:`text-h6 q-ml-sm`},T={key:0,class:`text-grey-6 text-center q-pa-lg`},E={key:1,class:`text-negative text-center q-pa-lg`},D={key:2,class:`text-grey-6 text-center q-pa-lg`},O={key:3,class:`column q-gutter-md`},k={key:0,class:`text-caption text-grey-6`},A={class:`row items-center q-mb-sm`},j={class:`text-subtitle1 text-indigo-3`,style:{"font-family":`var(--kobo-font-mono, monospace)`}},M=[`innerHTML`],N=y(i({__name:`ChangelogPage`,setup(i){let y=_(),N=e([]),P=e(``),F=e(!1),I=e(null);function L(e){return v(e)}async function R(){F.value=!0,I.value=null;try{let e=await fetch(`/api/changelog`);if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();P.value=t.currentVersion??``,N.value=t.versions??[]}catch(e){I.value=e instanceof Error?e.message:String(e)}finally{F.value=!1}}return n(R),(e,n)=>(r(),d(S,{class:`q-pa-md`,style:{"max-width":`900px`,margin:`0 auto`}},{default:a(()=>[p(`div`,C,[s(m,{flat:``,dense:``,round:``,icon:`arrow_back`,onClick:n[0]||=e=>f(y).back()}),p(`div`,w,l(e.$t(`changelog.title`)),1),s(b),s(m,{flat:``,dense:``,icon:`refresh`,loading:F.value,label:e.$t(`common.refresh`),onClick:R},null,8,[`loading`,`label`])]),F.value&&N.value.length===0?(r(),o(`div`,T,l(e.$t(`common.loading`)),1)):I.value?(r(),o(`div`,E,l(I.value),1)):N.value.length===0?(r(),o(`div`,D,l(e.$t(`changelog.empty`)),1)):(r(),o(`div`,O,[P.value?(r(),o(`div`,k,l(e.$t(`changelog.currentVersion`,{version:P.value})),1)):u(``,!0),(r(!0),o(c,null,t(N.value,t=>(r(),d(g,{key:t.version,dark:``,flat:``,bordered:``},{default:a(()=>[s(h,null,{default:a(()=>[p(`div`,A,[p(`div`,j,` v`+l(t.version),1),t.version===P.value?(r(),d(x,{key:0,dense:``,size:`sm`,color:`indigo-7`,"text-color":`grey-2`,label:e.$t(`changelog.current`),class:`q-ml-sm`},null,8,[`label`])):u(``,!0)]),p(`div`,{class:`changelog-notes`,innerHTML:L(t.notes)},null,8,M)]),_:2},1024)]),_:2},1024))),128))]))]),_:1}))}}),[[`__scopeId`,`data-v-ed73d661`]]);export{N as default};
1
+ import{$ as e,B as t,F as n,R as r,S as i,W as a,_ as o,b as s,c,ct as l,g as u,h as d,it as f,m as p}from"./vue.runtime.esm-bundler-JZnIeD9D.js";import{N as m,gt as h,mt as g,s as _}from"./index-02IPrCWM.js";import{t as v}from"./render-chat-markdown-OO8yJF8P.js";import{t as y}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{t as b}from"./QSpace-ezNrZkuj.js";import{t as x}from"./QChip-Ccf5FEQu.js";import{t as S}from"./QPage-D3rjwA1l.js";var C={class:`row items-center q-mb-md`},w={class:`text-h6 q-ml-sm`},T={key:0,class:`text-grey-6 text-center q-pa-lg`},E={key:1,class:`text-negative text-center q-pa-lg`},D={key:2,class:`text-grey-6 text-center q-pa-lg`},O={key:3,class:`column q-gutter-md`},k={key:0,class:`text-caption text-grey-6`},A={class:`row items-center q-mb-sm`},j={class:`text-subtitle1 text-indigo-3`,style:{"font-family":`var(--kobo-font-mono, monospace)`}},M=[`innerHTML`],N=y(i({__name:`ChangelogPage`,setup(i){let y=_(),N=e([]),P=e(``),F=e(!1),I=e(null);function L(e){return v(e)}async function R(){F.value=!0,I.value=null;try{let e=await fetch(`/api/changelog`);if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();P.value=t.currentVersion??``,N.value=t.versions??[]}catch(e){I.value=e instanceof Error?e.message:String(e)}finally{F.value=!1}}return n(R),(e,n)=>(r(),d(S,{class:`q-pa-md`,style:{"max-width":`900px`,margin:`0 auto`}},{default:a(()=>[p(`div`,C,[s(m,{flat:``,dense:``,round:``,icon:`arrow_back`,onClick:n[0]||=e=>f(y).back()}),p(`div`,w,l(e.$t(`changelog.title`)),1),s(b),s(m,{flat:``,dense:``,icon:`refresh`,loading:F.value,label:e.$t(`common.refresh`),onClick:R},null,8,[`loading`,`label`])]),F.value&&N.value.length===0?(r(),o(`div`,T,l(e.$t(`common.loading`)),1)):I.value?(r(),o(`div`,E,l(I.value),1)):N.value.length===0?(r(),o(`div`,D,l(e.$t(`changelog.empty`)),1)):(r(),o(`div`,O,[P.value?(r(),o(`div`,k,l(e.$t(`changelog.currentVersion`,{version:P.value})),1)):u(``,!0),(r(!0),o(c,null,t(N.value,t=>(r(),d(g,{key:t.version,dark:``,flat:``,bordered:``},{default:a(()=>[s(h,null,{default:a(()=>[p(`div`,A,[p(`div`,j,` v`+l(t.version),1),t.version===P.value?(r(),d(x,{key:0,dense:``,size:`sm`,color:`indigo-7`,"text-color":`grey-2`,label:e.$t(`changelog.current`),class:`q-ml-sm`},null,8,[`label`])):u(``,!0)]),p(`div`,{class:`changelog-notes`,innerHTML:L(t.notes)},null,8,M)]),_:2},1024)]),_:2},1024))),128))]))]),_:1}))}}),[[`__scopeId`,`data-v-ed73d661`]]);export{N as default};
@@ -1 +1 @@
1
- import{P as e,b as t}from"./QIcon-C6E-oEjI.js";import{nt as n,rt as r}from"./index-DODmyTEl.js";var i={left:!0,right:!0,up:!0,down:!0,horizontal:!0,vertical:!0},a=Object.keys(i);i.all=!0;function o(e){let t={};for(let n of a)e[n]&&(t[n]=!0);return Object.keys(t).length===0?i:(t.horizontal?t.left=t.right=!0:t.left&&t.right&&(t.horizontal=!0),t.vertical?t.up=t.down=!0:t.up&&t.down&&(t.vertical=!0),t.horizontal&&t.vertical&&(t.all=!0),t)}var s=[`INPUT`,`TEXTAREA`];function c(e,t){return t.event===void 0&&e.target!==void 0&&!e.target.draggable&&typeof t.handler==`function`&&!s.includes(e.target.nodeName.toUpperCase())&&(e.qClonedBy===void 0||!e.qClonedBy.includes(t.uid))}function l(e){return e===!1?0:e===!0||e===void 0?1:Number.parseInt(e,10)||0}var u=e({name:`close-popup`,beforeMount(e,{value:i}){let a={depth:l(i),handler(t){a.depth!==0&&setTimeout(()=>{let i=r(e);i!==void 0&&n(i,t,a.depth)},0)},handlerKey(e){t(e,13)&&a.handler(e)}};e.__qclosepopup=a,e.addEventListener(`click`,a.handler),e.addEventListener(`keyup`,a.handlerKey)},updated(e,{value:t,oldValue:n}){t!==n&&(e.__qclosepopup.depth=l(t))},beforeUnmount(e){let t=e.__qclosepopup;e.removeEventListener(`click`,t.handler),e.removeEventListener(`keyup`,t.handlerKey),delete e.__qclosepopup}});export{o as n,c as r,u as t};
1
+ import{P as e,b as t}from"./QIcon-C6E-oEjI.js";import{nt as n,rt as r}from"./index-02IPrCWM.js";var i={left:!0,right:!0,up:!0,down:!0,horizontal:!0,vertical:!0},a=Object.keys(i);i.all=!0;function o(e){let t={};for(let n of a)e[n]&&(t[n]=!0);return Object.keys(t).length===0?i:(t.horizontal?t.left=t.right=!0:t.left&&t.right&&(t.horizontal=!0),t.vertical?t.up=t.down=!0:t.up&&t.down&&(t.vertical=!0),t.horizontal&&t.vertical&&(t.all=!0),t)}var s=[`INPUT`,`TEXTAREA`];function c(e,t){return t.event===void 0&&e.target!==void 0&&!e.target.draggable&&typeof t.handler==`function`&&!s.includes(e.target.nodeName.toUpperCase())&&(e.qClonedBy===void 0||!e.qClonedBy.includes(t.uid))}function l(e){return e===!1?0:e===!0||e===void 0?1:Number.parseInt(e,10)||0}var u=e({name:`close-popup`,beforeMount(e,{value:i}){let a={depth:l(i),handler(t){a.depth!==0&&setTimeout(()=>{let i=r(e);i!==void 0&&n(i,t,a.depth)},0)},handlerKey(e){t(e,13)&&a.handler(e)}};e.__qclosepopup=a,e.addEventListener(`click`,a.handler),e.addEventListener(`keyup`,a.handlerKey)},updated(e,{value:t,oldValue:n}){t!==n&&(e.__qclosepopup.depth=l(t))},beforeUnmount(e){let t=e.__qclosepopup;e.removeEventListener(`click`,t.handler),e.removeEventListener(`keyup`,t.handlerKey),delete e.__qclosepopup}});export{o as n,c as r,u as t};
@@ -1,2 +1,2 @@
1
- import{$ as e,B as t,F as n,I as r,O as i,R as a,S as ee,U as te,W as o,_ as s,at as ne,b as c,c as re,ct as l,g as u,h as d,it as f,k as ie,m as p,n as ae,o as oe,ot as se,p as m,s as h,w as ce,y as g}from"./vue.runtime.esm-bundler-JZnIeD9D.js";import{t as _}from"./QIcon-C6E-oEjI.js";import{t as le}from"./QSeparator-DWTCQxsa.js";import{t as v}from"./QInput-BF8x4RTv.js";import{E as ue,N as y,d as de,l as fe,s as pe,x as me,z as he}from"./index-DODmyTEl.js";import{t as ge}from"./QSpinnerDots-DIV68-cV.js";import{n as b,r as x,t as _e}from"./use-quasar-B20UL17o.js";import{l as S,t as C}from"./QSelect-DxY4RU7V.js";import{t as w}from"./QTooltip-Cpm_IfVm.js";import{t as ve}from"./QExpansionItem-BDyoC1Ly.js";import{t as ye}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{t as be}from"./QSpace-ezNrZkuj.js";import{t as xe}from"./QBtnToggle-xCWfa0zI.js";import{i as Se}from"./project-color-Cvt0AAeh.js";import{t as Ce}from"./QPage-D3rjwA1l.js";import{a as we,i as Te,n as Ee,r as De,t as Oe}from"./expand-template-lTTAWhou.js";import{i as ke,r as Ae,t as je}from"./permissionModes-6jhegAm-.js";var Me=`kobo:create-page-prefs`;function T(){try{let e=localStorage.getItem(Me);return e===null?void 0:JSON.parse(e)}catch{return}}function Ne(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Pe(){let e=T();if(!Ne(e))return{};let t={};return typeof e.projectPath==`string`&&e.projectPath.length>0&&(t.projectPath=e.projectPath),typeof e.autoLoop==`boolean`&&(t.autoLoop=e.autoLoop),(e.autoLoopSessionMode===`per_task`||e.autoLoopSessionMode===`continuous`)&&(t.autoLoopSessionMode=e.autoLoopSessionMode),typeof e.brainstormModel==`string`&&e.brainstormModel.length>0&&(t.brainstormModel=e.brainstormModel),t}function Fe(e){try{localStorage.setItem(Me,JSON.stringify(e))}catch{}}var Ie={class:`create-inner`},Le={class:`create-title text-center text-weight-bold q-mb-lg text-grey-3`},Re={class:`create-card rounded-borders`},ze={class:`card-top-bar row items-center q-px-md q-py-xs`},Be={class:`model-badge cursor-default row items-center q-gutter-xs`},Ve={class:`text-indigo-3 text-weight-medium text-caption`},He={key:0,class:`notion-url-wrap`},Ue={key:0,class:`notion-error text-caption q-px-md q-pb-xs text-red-5`},We={key:1,class:`notion-valid text-caption q-px-md q-pb-xs text-green-4`},Ge={key:2,class:`notion-peek-choice q-px-md q-pb-sm`},Ke={class:`text-caption text-grey-4 q-mb-sm`},qe={class:`row q-gutter-sm`},Je={class:`peek-card-text`},Ye={class:`peek-card-title`},Xe={class:`peek-card-desc`},Ze={class:`peek-card-text`},Qe={class:`peek-card-title`},$e={class:`peek-card-desc`},et={key:0,class:`sentry-url-wrap`},tt={key:0,class:`sentry-error text-caption q-px-md q-pb-xs text-red-5`},nt={key:1,class:`sentry-valid text-caption q-px-md q-pb-xs text-red-4`},rt={class:`card-name-wrap`},it={class:`card-textarea-wrap`},at={class:`row items-center justify-end q-px-sm q-pb-xs q-gutter-sm`},ot={key:0,class:`row items-center text-caption text-amber-6`},st={class:`manual-hint q-px-md q-py-sm text-caption text-grey-6`},ct={class:`q-pa-sm manual-section-body`},lt={class:`row items-center q-gutter-sm q-mb-sm`},ut={class:`col text-caption text-grey-4`},dt={class:`q-pa-sm manual-section-body`},ft={class:`row items-center q-gutter-sm q-mb-sm`},pt={class:`col text-caption text-grey-4`},mt={class:`card-bottom-bar`},ht={class:`row q-col-gutter-xs q-px-xs`},gt={key:0,class:`col-12 col-sm-6 col-md-3`},_t={class:`bottom-select-label row items-center no-wrap`},vt={class:`col-12 col-sm-6 col-md-3`},yt={class:`bottom-select-label row items-center no-wrap`},bt={key:0,class:`text-grey-5 q-mr-xs`},xt={class:`col-12 col-sm-6 col-md-3`},St={class:`bottom-select-label row items-center no-wrap`},Ct={class:`col-12 col-md-3`},wt={class:`bottom-select-label row items-center no-wrap`},Tt={class:`row q-col-gutter-xs q-pa-xs col-12 items-center justify-center`},Et={class:`col-12 col-md-auto`},Dt={key:0,class:`col-12 col-md-auto`},Ot={key:1,class:`col-12 col-md-auto`},kt={class:`bottom-select-label row items-center no-wrap`},At={class:`text-grey-5 q-mr-xs`},jt={class:`row q-col-gutter-xs q-pa-xs col-12 items-center justify-center`},Mt={class:`col-12 col-md-auto`},Nt={class:`col-12 col-md-auto`},Pt={class:`row q-col-gutter-xs q-px-xs bottom-row-git`},Ft={class:`col-12 col-md-4`},It={key:0,class:`col-12 col-md-4`},Lt={class:`bottom-select-label row items-center no-wrap`},Rt={key:1,class:`col-12 col-md-4`},zt={class:`bottom-select-label row items-center no-wrap`},Bt={class:`col-12 col-md-4`},Vt={class:`bottom-select-label row items-center no-wrap`},Ht={class:`row justify-center q-px-sm q-py-sm`},Ut={class:`create-hint text-center text-body2 q-mt-md text-grey-8`},Wt=6e4,E=ye(ee({__name:`CreatePage`,setup(ee){function ye(e){return e.disabled===!0}let Me=pe(),T=_e(),Ne=de(),E=me(),{t:D}=he(),Gt=e([]),Kt=e(``),O=e(``),qt=e(null),Jt=e(``),k=e(!1),A=e(!1),Yt=e(null),Xt=e(null),Zt=e([]),Qt=e(null),j=e(``),M=e(!1),N=e(`claude-opus-4-8`),P=e(`claude-opus-4-8`),F=e(`auto`),I=e(``),L=e(null),R=e(`feature`),z=e(!1),$t=m(()=>E.global.voiceEnabled),en=e([]),B=e(`claude-code`),tn=m(()=>en.value.find(e=>e.id===B.value)),nn=m(()=>en.value.map(e=>({value:e.id,label:e.displayName}))),rn=m(()=>E.global.branchPrefixes.map(e=>({label:`${e}/`,value:e}))),an=[`plan`,`bypass`,`strict`,`interactive`];function on(e,t){let n=e?E.getProjectByPath(e):void 0,r=n?.agentPermissionMode;if(typeof r==`string`&&an.includes(r))return r;let i=E.global.defaultPermissionModeByEngine?.[t];return typeof i==`string`&&an.includes(i)?i:n?.dangerouslySkipPermissions??E.global.dangerouslySkipPermissions??!0?`bypass`:t===`codex`?`plan`:`interactive`}let V=e(on(``,B.value)),sn=m(()=>{switch(V.value){case`plan`:return`visibility`;case`bypass`:return`flash_on`;case`strict`:return`lock`;case`interactive`:return`security`}}),cn=m(()=>(je[B.value]??an).map(e=>({value:e,label:D(`agentPermissionMode.${e}`),disabled:e===`plan`&&X.value}))),H=e([]),ln=e([]),un=e(!1),dn=e(!1);function fn(e,t){t(()=>{ln.value=e?H.value.filter(t=>t.toLowerCase().includes(e.toLowerCase())):H.value})}let pn=ue();function mn(){return qt.value?.nativeEl??null}let{showSkills:hn,selectedSkillIndex:U,groupedDropdown:gn,flatDropdown:W,fetchSkills:_n,detectSlashFragment:vn,replaceFragmentWith:yn,closeDropdown:bn}=Te(O,mn,{excludeKoboCommands:!0});_n(),te(O,async()=>{await ie(),await vn()});function xn(e){if(e.type===`template`){let t=pn.templates.find(t=>t.slug===e.name);if(!t)return;yn(Ee(t.content,Oe({workspace:null,gitStats:null,sessionName:null}))),bn();return}yn(`/${e.name} `),bn()}function Sn(e){!hn.value||W.value.length===0||(e.key===`ArrowDown`?(e.preventDefault(),U.value=(U.value+1)%W.value.length):e.key===`ArrowUp`?(e.preventDefault(),U.value=(U.value-1+W.value.length)%W.value.length):e.key===`Enter`&&!e.shiftKey&&!e.ctrlKey&&!e.metaKey?(e.preventDefault(),xn(W.value[U.value])):e.key===`Escape`&&(e.preventDefault(),bn()))}async function Cn(){if(!(!$t.value||k.value||A.value)){if(!navigator.mediaDevices?.getUserMedia||typeof MediaRecorder>`u`){T.notify({type:`warning`,message:D(`voice.notSupported`),position:`top`,timeout:4e3});return}try{let e=await navigator.mediaDevices.getUserMedia({audio:!0});Xt.value=e,Zt.value=[];let t=MediaRecorder.isTypeSupported(`audio/webm`)?`audio/webm`:``,n=t?new MediaRecorder(e,{mimeType:t}):new MediaRecorder(e);n.ondataavailable=e=>{e.data&&e.data.size>0&&Zt.value.push(e.data)},n.start(),Yt.value=n,k.value=!0,Qt.value=setTimeout(()=>{G(),T.notify({type:`info`,message:D(`voice.maxDurationReached`),position:`top`,timeout:3500})},Wt)}catch{T.notify({type:`negative`,message:D(`voice.errorMicPermission`),position:`top`,timeout:5e3})}}}async function G(){if(!k.value)return;let e=Yt.value;if(!e)return;k.value=!1,A.value=!0,Qt.value&&=(clearTimeout(Qt.value),null);let t=await new Promise(t=>{e.onstop=()=>t(new Blob(Zt.value,{type:`audio/webm`})),e.stop()});try{if(t.size===0)throw Error(`MIC_AUDIO_INVALID`);let e=new FormData;e.append(`audio`,t,`voice.webm`),e.append(`language`,E.global.voiceLanguage||`auto`);let n=await fetch(`/api/voice/transcribe`,{method:`POST`,body:e});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(String(e.code??e.error??`HTTP_${n.status}`))}let r=await n.json();r.text?.trim()&&(O.value=O.value?`${O.value.trimEnd()} ${r.text.trim()}`:r.text.trim())}catch(e){let t=e instanceof Error?e.message:`TRANSCRIPTION_FAILED`;T.notify({type:`negative`,message:D({VOICE_DISABLED:`voice.errorDisabled`,MODEL_NOT_CONFIGURED:`voice.errorModelMissing`,MODEL_NOT_INSTALLED:`voice.errorModelNotInstalled`,VOICE_RUNTIME_MISSING:`voice.errorRuntimeMissing`,MIC_AUDIO_INVALID:`voice.errorAudioInvalid`,LANGUAGE_INVALID:`voice.errorLanguageInvalid`,TRANSCRIPTION_TIMEOUT:`voice.errorTranscription`}[t]??`voice.errorTranscription`),position:`top`,timeout:5e3})}finally{Yt.value=null,Zt.value=[],Xt.value?.getTracks().forEach(e=>{e.stop()}),Xt.value=null,A.value=!1}}function wn(e){return $t.value?E.global.voicePttKey===`ctrl+space`?e.ctrlKey&&e.code===`Space`:e.key===`Alt`:!1}function Tn(e){!wn(e)||e.repeat||(e.preventDefault(),Cn())}function En(e){wn(e)&&(e.preventDefault(),G())}function Dn(){k.value&&G()}function On(){document.visibilityState!==`visible`&&k.value&&G()}let K=m(()=>(ke[B.value]??Ae).map(e=>({label:D(e.i18nLabelKey),value:e.value,description:D(e.i18nDescriptionKey)})));te(B,()=>{let e=K.value.map(e=>e.value);if(e.length>0){let t=E.global.defaultModelByEngine?.[B.value];typeof t==`string`&&e.includes(t)?N.value=t:e.includes(N.value)||(N.value=e.includes(`auto`)?`auto`:e[0]??`auto`)}e.length>0&&!e.includes(P.value)&&(P.value=e.includes(`auto`)?`auto`:e[0]??`auto`);let t=je[B.value]??[];t.length>0&&!t.includes(V.value)&&(V.value=on(I.value,B.value));let n=(De[B.value]??[]).map(e=>e.value);n.length>0&&!n.includes(F.value)&&(F.value=n.includes(`auto`)?`auto`:n[0]??`auto`)});function kn(e){let t=e.indexOf(`:`);return t>=0?e.slice(t+1).trim():e}let An=m(()=>(De[B.value]??De[`claude-code`]).map(e=>({value:e.value,label:kn(D(e.i18nLabelKey)),description:D(e.i18nDescriptionKey)}))),q=m(()=>{let e=j.value.trim();return e.startsWith(`https://www.notion.so/`)||e.startsWith(`https://app.notion.com/`)}),jn=m(()=>/[?&]p=[0-9a-f]{32}(?:[&#]|$)/i.test(j.value)),J=e(`panel`);function Mn(){let e=j.value.trim();return J.value===`parent`&&jn.value?e.replace(/([?&])p=[0-9a-f]{32}(?=[&#]|$)/i,`$1`).replace(/([?&])pm=[a-z]+(?=[&#]|$)/i,`$1`).replace(/[?&]+$/,``).replace(/\?&/,`?`):e}let Nn=e([]),Pn=e([]),Fn=e(``),In=e(``),Ln=m(()=>!M.value||!q.value);function Rn(){let e=Fn.value.trim();e&&(Nn.value.push(e),Fn.value=``)}function zn(e){Nn.value.splice(e,1)}function Bn(){let e=In.value.trim();e&&(Pn.value.push(e),In.value=``)}function Vn(e){Pn.value.splice(e,1)}function Hn(){M.value=!M.value,M.value||(j.value=``)}let Y=e(!1),X=e(!1),Un=e(`per_task`);te(()=>X.value,e=>{e&&V.value!==`bypass`&&(V.value=`bypass`)});function Wn(){X.value=!X.value,X.value&&(P.value=N.value)}let Z=e(``),Gn=m(()=>/\/issues\/\d+/.test(Z.value.trim()));function Kn(){Y.value=!Y.value,Y.value||(Z.value=``)}let Q=e(!1),$=e(null),qn=e([]),Jn=e(!1);async function Yn(){if(!I.value.trim()){qn.value=[];return}Jn.value=!0;try{qn.value=await Ne.fetchOrphanWorktrees(I.value.trim())}catch{qn.value=[]}finally{Jn.value=!1}}function Xn(){Q.value=!Q.value,Q.value?(M.value=!1,j.value=``,Y.value=!1,Z.value=``,z.value=!0,Yn()):$.value=null}te(I,()=>{$.value=null,Q.value&&Yn()}),te($,e=>{if(!e)return;let t=qn.value.find(t=>t.path===e);t&&(L.value=t.suggestedSourceBranch),z.value=!0});async function Zn(e){if(!e.trim()){H.value=[],L.value=null;return}un.value=!0;try{let t=await fetch(`/api/git/branches?path=${encodeURIComponent(e.trim())}`);if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.json();H.value=n.local??n.branches??[],H.value.length>0&&!L.value&&(L.value=H.value[0]??null)}catch{H.value=[],L.value=null}finally{un.value=!1}}function Qn(e){let t=E.getProjectByPath(e);if(t){t.defaultSourceBranch&&(L.value=t.defaultSourceBranch);let e=t.taskPromptTemplate??``;(O.value===``||O.value===Jt.value)&&(O.value=e,Jt.value=e);let n=K.value.map(e=>e.value);if(t.defaultModel&&n.includes(t.defaultModel))N.value=t.defaultModel;else{let e=E.global.defaultModelByEngine?.[B.value];typeof e==`string`&&n.includes(e)&&(N.value=e)}}V.value=on(e,B.value)}let $n=null;te(I,e=>{$n&&clearTimeout($n),$n=setTimeout(()=>{L.value=null,Zn(e),Qn(e)},500)});function er(e,t){let n=e.toLowerCase();t(()=>{Gt.value=E.projectPaths.filter(e=>e.toLowerCase().includes(n)||Se(e).toLowerCase().includes(n))})}function tr(e){I.value=E.projectPaths.find(t=>Se(t)===e)??e}n(async()=>{await E.fetchSettings();let e=E.global.branchPrefixes;e.length>0&&!e.includes(R.value)&&(R.value=e[0]);let t=Pe();t.autoLoop===!0&&(X.value=!0),t.autoLoopSessionMode===`continuous`&&(Un.value=`continuous`),t.autoLoop===!0&&t.brainstormModel&&(P.value=t.brainstormModel),t.projectPath&&E.projectPaths.includes(t.projectPath)&&(I.value=t.projectPath),V.value=on(I.value,B.value);try{let e=await fetch(`/api/engines`);e.ok&&(en.value=await e.json())}catch{}{let e=K.value.map(e=>e.value),t=E.global.defaultModelByEngine?.[B.value];typeof t==`string`&&e.includes(t)?N.value=t:e.length>0&&!e.includes(N.value)&&(N.value=e.includes(`auto`)?`auto`:e[0]??`auto`)}{let e=K.value.map(e=>e.value);e.length>0&&!e.includes(P.value)&&(P.value=e.includes(`auto`)?`auto`:e[0]??`auto`)}window.addEventListener(`keydown`,Tn),window.addEventListener(`keyup`,En),window.addEventListener(`blur`,Dn),document.addEventListener(`visibilitychange`,On)}),r(()=>{$n&&clearTimeout($n),window.removeEventListener(`keydown`,Tn),window.removeEventListener(`keyup`,En),window.removeEventListener(`blur`,Dn),document.removeEventListener(`visibilitychange`,On),Qt.value&&=(clearTimeout(Qt.value),null),k.value&&G()});function nr(e){return e.normalize(`NFD`).replace(/[\u0300-\u036f]/g,``).toLowerCase().replace(/[^a-z0-9\s-]/g,``).trim().replace(/\s+/g,`-`).replace(/-+/g,`-`).substring(0,50)}function rr(){return Kt.value.trim()?Kt.value.trim().substring(0,80):!M.value&&!Y.value&&O.value.trim()&&(O.value.trim().split(`
1
+ import{$ as e,B as t,F as n,I as r,O as i,R as a,S as ee,U as te,W as o,_ as s,at as ne,b as c,c as re,ct as l,g as u,h as d,it as f,k as ie,m as p,n as ae,o as oe,ot as se,p as m,s as h,w as ce,y as g}from"./vue.runtime.esm-bundler-JZnIeD9D.js";import{t as _}from"./QIcon-C6E-oEjI.js";import{t as le}from"./QSeparator-DWTCQxsa.js";import{t as v}from"./QInput-BF8x4RTv.js";import{E as ue,N as y,d as de,l as fe,s as pe,x as me,z as he}from"./index-02IPrCWM.js";import{t as ge}from"./QSpinnerDots-DIV68-cV.js";import{n as b,r as x,t as _e}from"./use-quasar-CwG_Rs2g.js";import{l as S,t as C}from"./QSelect-DJgkh8M3.js";import{t as w}from"./QTooltip-epbJipNF.js";import{t as ve}from"./QExpansionItem-CYcOrwbm.js";import{t as ye}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{t as be}from"./QSpace-ezNrZkuj.js";import{t as xe}from"./QBtnToggle-BEgY0AkW.js";import{i as Se}from"./project-color-CubSkld3.js";import{t as Ce}from"./QPage-D3rjwA1l.js";import{a as we,i as Te,n as Ee,r as De,t as Oe}from"./expand-template-BsmF6e32.js";import{i as ke,r as Ae,t as je}from"./permissionModes-6jhegAm-.js";var Me=`kobo:create-page-prefs`;function T(){try{let e=localStorage.getItem(Me);return e===null?void 0:JSON.parse(e)}catch{return}}function Ne(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Pe(){let e=T();if(!Ne(e))return{};let t={};return typeof e.projectPath==`string`&&e.projectPath.length>0&&(t.projectPath=e.projectPath),typeof e.autoLoop==`boolean`&&(t.autoLoop=e.autoLoop),(e.autoLoopSessionMode===`per_task`||e.autoLoopSessionMode===`continuous`)&&(t.autoLoopSessionMode=e.autoLoopSessionMode),typeof e.brainstormModel==`string`&&e.brainstormModel.length>0&&(t.brainstormModel=e.brainstormModel),t}function Fe(e){try{localStorage.setItem(Me,JSON.stringify(e))}catch{}}var Ie={class:`create-inner`},Le={class:`create-title text-center text-weight-bold q-mb-lg text-grey-3`},Re={class:`create-card rounded-borders`},ze={class:`card-top-bar row items-center q-px-md q-py-xs`},Be={class:`model-badge cursor-default row items-center q-gutter-xs`},Ve={class:`text-indigo-3 text-weight-medium text-caption`},He={key:0,class:`notion-url-wrap`},Ue={key:0,class:`notion-error text-caption q-px-md q-pb-xs text-red-5`},We={key:1,class:`notion-valid text-caption q-px-md q-pb-xs text-green-4`},Ge={key:2,class:`notion-peek-choice q-px-md q-pb-sm`},Ke={class:`text-caption text-grey-4 q-mb-sm`},qe={class:`row q-gutter-sm`},Je={class:`peek-card-text`},Ye={class:`peek-card-title`},Xe={class:`peek-card-desc`},Ze={class:`peek-card-text`},Qe={class:`peek-card-title`},$e={class:`peek-card-desc`},et={key:0,class:`sentry-url-wrap`},tt={key:0,class:`sentry-error text-caption q-px-md q-pb-xs text-red-5`},nt={key:1,class:`sentry-valid text-caption q-px-md q-pb-xs text-red-4`},rt={class:`card-name-wrap`},it={class:`card-textarea-wrap`},at={class:`row items-center justify-end q-px-sm q-pb-xs q-gutter-sm`},ot={key:0,class:`row items-center text-caption text-amber-6`},st={class:`manual-hint q-px-md q-py-sm text-caption text-grey-6`},ct={class:`q-pa-sm manual-section-body`},lt={class:`row items-center q-gutter-sm q-mb-sm`},ut={class:`col text-caption text-grey-4`},dt={class:`q-pa-sm manual-section-body`},ft={class:`row items-center q-gutter-sm q-mb-sm`},pt={class:`col text-caption text-grey-4`},mt={class:`card-bottom-bar`},ht={class:`row q-col-gutter-xs q-px-xs`},gt={key:0,class:`col-12 col-sm-6 col-md-3`},_t={class:`bottom-select-label row items-center no-wrap`},vt={class:`col-12 col-sm-6 col-md-3`},yt={class:`bottom-select-label row items-center no-wrap`},bt={key:0,class:`text-grey-5 q-mr-xs`},xt={class:`col-12 col-sm-6 col-md-3`},St={class:`bottom-select-label row items-center no-wrap`},Ct={class:`col-12 col-md-3`},wt={class:`bottom-select-label row items-center no-wrap`},Tt={class:`row q-col-gutter-xs q-pa-xs col-12 items-center justify-center`},Et={class:`col-12 col-md-auto`},Dt={key:0,class:`col-12 col-md-auto`},Ot={key:1,class:`col-12 col-md-auto`},kt={class:`bottom-select-label row items-center no-wrap`},At={class:`text-grey-5 q-mr-xs`},jt={class:`row q-col-gutter-xs q-pa-xs col-12 items-center justify-center`},Mt={class:`col-12 col-md-auto`},Nt={class:`col-12 col-md-auto`},Pt={class:`row q-col-gutter-xs q-px-xs bottom-row-git`},Ft={class:`col-12 col-md-4`},It={key:0,class:`col-12 col-md-4`},Lt={class:`bottom-select-label row items-center no-wrap`},Rt={key:1,class:`col-12 col-md-4`},zt={class:`bottom-select-label row items-center no-wrap`},Bt={class:`col-12 col-md-4`},Vt={class:`bottom-select-label row items-center no-wrap`},Ht={class:`row justify-center q-px-sm q-py-sm`},Ut={class:`create-hint text-center text-body2 q-mt-md text-grey-8`},Wt=6e4,E=ye(ee({__name:`CreatePage`,setup(ee){function ye(e){return e.disabled===!0}let Me=pe(),T=_e(),Ne=de(),E=me(),{t:D}=he(),Gt=e([]),Kt=e(``),O=e(``),qt=e(null),Jt=e(``),k=e(!1),A=e(!1),Yt=e(null),Xt=e(null),Zt=e([]),Qt=e(null),j=e(``),M=e(!1),N=e(`claude-opus-4-8`),P=e(`claude-opus-4-8`),F=e(`auto`),I=e(``),L=e(null),R=e(`feature`),z=e(!1),$t=m(()=>E.global.voiceEnabled),en=e([]),B=e(`claude-code`),tn=m(()=>en.value.find(e=>e.id===B.value)),nn=m(()=>en.value.map(e=>({value:e.id,label:e.displayName}))),rn=m(()=>E.global.branchPrefixes.map(e=>({label:`${e}/`,value:e}))),an=[`plan`,`bypass`,`strict`,`interactive`];function on(e,t){let n=e?E.getProjectByPath(e):void 0,r=n?.agentPermissionMode;if(typeof r==`string`&&an.includes(r))return r;let i=E.global.defaultPermissionModeByEngine?.[t];return typeof i==`string`&&an.includes(i)?i:n?.dangerouslySkipPermissions??E.global.dangerouslySkipPermissions??!0?`bypass`:t===`codex`?`plan`:`interactive`}let V=e(on(``,B.value)),sn=m(()=>{switch(V.value){case`plan`:return`visibility`;case`bypass`:return`flash_on`;case`strict`:return`lock`;case`interactive`:return`security`}}),cn=m(()=>(je[B.value]??an).map(e=>({value:e,label:D(`agentPermissionMode.${e}`),disabled:e===`plan`&&X.value}))),H=e([]),ln=e([]),un=e(!1),dn=e(!1);function fn(e,t){t(()=>{ln.value=e?H.value.filter(t=>t.toLowerCase().includes(e.toLowerCase())):H.value})}let pn=ue();function mn(){return qt.value?.nativeEl??null}let{showSkills:hn,selectedSkillIndex:U,groupedDropdown:gn,flatDropdown:W,fetchSkills:_n,detectSlashFragment:vn,replaceFragmentWith:yn,closeDropdown:bn}=Te(O,mn,{excludeKoboCommands:!0});_n(),te(O,async()=>{await ie(),await vn()});function xn(e){if(e.type===`template`){let t=pn.templates.find(t=>t.slug===e.name);if(!t)return;yn(Ee(t.content,Oe({workspace:null,gitStats:null,sessionName:null}))),bn();return}yn(`/${e.name} `),bn()}function Sn(e){!hn.value||W.value.length===0||(e.key===`ArrowDown`?(e.preventDefault(),U.value=(U.value+1)%W.value.length):e.key===`ArrowUp`?(e.preventDefault(),U.value=(U.value-1+W.value.length)%W.value.length):e.key===`Enter`&&!e.shiftKey&&!e.ctrlKey&&!e.metaKey?(e.preventDefault(),xn(W.value[U.value])):e.key===`Escape`&&(e.preventDefault(),bn()))}async function Cn(){if(!(!$t.value||k.value||A.value)){if(!navigator.mediaDevices?.getUserMedia||typeof MediaRecorder>`u`){T.notify({type:`warning`,message:D(`voice.notSupported`),position:`top`,timeout:4e3});return}try{let e=await navigator.mediaDevices.getUserMedia({audio:!0});Xt.value=e,Zt.value=[];let t=MediaRecorder.isTypeSupported(`audio/webm`)?`audio/webm`:``,n=t?new MediaRecorder(e,{mimeType:t}):new MediaRecorder(e);n.ondataavailable=e=>{e.data&&e.data.size>0&&Zt.value.push(e.data)},n.start(),Yt.value=n,k.value=!0,Qt.value=setTimeout(()=>{G(),T.notify({type:`info`,message:D(`voice.maxDurationReached`),position:`top`,timeout:3500})},Wt)}catch{T.notify({type:`negative`,message:D(`voice.errorMicPermission`),position:`top`,timeout:5e3})}}}async function G(){if(!k.value)return;let e=Yt.value;if(!e)return;k.value=!1,A.value=!0,Qt.value&&=(clearTimeout(Qt.value),null);let t=await new Promise(t=>{e.onstop=()=>t(new Blob(Zt.value,{type:`audio/webm`})),e.stop()});try{if(t.size===0)throw Error(`MIC_AUDIO_INVALID`);let e=new FormData;e.append(`audio`,t,`voice.webm`),e.append(`language`,E.global.voiceLanguage||`auto`);let n=await fetch(`/api/voice/transcribe`,{method:`POST`,body:e});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(String(e.code??e.error??`HTTP_${n.status}`))}let r=await n.json();r.text?.trim()&&(O.value=O.value?`${O.value.trimEnd()} ${r.text.trim()}`:r.text.trim())}catch(e){let t=e instanceof Error?e.message:`TRANSCRIPTION_FAILED`;T.notify({type:`negative`,message:D({VOICE_DISABLED:`voice.errorDisabled`,MODEL_NOT_CONFIGURED:`voice.errorModelMissing`,MODEL_NOT_INSTALLED:`voice.errorModelNotInstalled`,VOICE_RUNTIME_MISSING:`voice.errorRuntimeMissing`,MIC_AUDIO_INVALID:`voice.errorAudioInvalid`,LANGUAGE_INVALID:`voice.errorLanguageInvalid`,TRANSCRIPTION_TIMEOUT:`voice.errorTranscription`}[t]??`voice.errorTranscription`),position:`top`,timeout:5e3})}finally{Yt.value=null,Zt.value=[],Xt.value?.getTracks().forEach(e=>{e.stop()}),Xt.value=null,A.value=!1}}function wn(e){return $t.value?E.global.voicePttKey===`ctrl+space`?e.ctrlKey&&e.code===`Space`:e.key===`Alt`:!1}function Tn(e){!wn(e)||e.repeat||(e.preventDefault(),Cn())}function En(e){wn(e)&&(e.preventDefault(),G())}function Dn(){k.value&&G()}function On(){document.visibilityState!==`visible`&&k.value&&G()}let K=m(()=>(ke[B.value]??Ae).map(e=>({label:D(e.i18nLabelKey),value:e.value,description:D(e.i18nDescriptionKey)})));te(B,()=>{let e=K.value.map(e=>e.value);if(e.length>0){let t=E.global.defaultModelByEngine?.[B.value];typeof t==`string`&&e.includes(t)?N.value=t:e.includes(N.value)||(N.value=e.includes(`auto`)?`auto`:e[0]??`auto`)}e.length>0&&!e.includes(P.value)&&(P.value=e.includes(`auto`)?`auto`:e[0]??`auto`);let t=je[B.value]??[];t.length>0&&!t.includes(V.value)&&(V.value=on(I.value,B.value));let n=(De[B.value]??[]).map(e=>e.value);n.length>0&&!n.includes(F.value)&&(F.value=n.includes(`auto`)?`auto`:n[0]??`auto`)});function kn(e){let t=e.indexOf(`:`);return t>=0?e.slice(t+1).trim():e}let An=m(()=>(De[B.value]??De[`claude-code`]).map(e=>({value:e.value,label:kn(D(e.i18nLabelKey)),description:D(e.i18nDescriptionKey)}))),q=m(()=>{let e=j.value.trim();return e.startsWith(`https://www.notion.so/`)||e.startsWith(`https://app.notion.com/`)}),jn=m(()=>/[?&]p=[0-9a-f]{32}(?:[&#]|$)/i.test(j.value)),J=e(`panel`);function Mn(){let e=j.value.trim();return J.value===`parent`&&jn.value?e.replace(/([?&])p=[0-9a-f]{32}(?=[&#]|$)/i,`$1`).replace(/([?&])pm=[a-z]+(?=[&#]|$)/i,`$1`).replace(/[?&]+$/,``).replace(/\?&/,`?`):e}let Nn=e([]),Pn=e([]),Fn=e(``),In=e(``),Ln=m(()=>!M.value||!q.value);function Rn(){let e=Fn.value.trim();e&&(Nn.value.push(e),Fn.value=``)}function zn(e){Nn.value.splice(e,1)}function Bn(){let e=In.value.trim();e&&(Pn.value.push(e),In.value=``)}function Vn(e){Pn.value.splice(e,1)}function Hn(){M.value=!M.value,M.value||(j.value=``)}let Y=e(!1),X=e(!1),Un=e(`per_task`);te(()=>X.value,e=>{e&&V.value!==`bypass`&&(V.value=`bypass`)});function Wn(){X.value=!X.value,X.value&&(P.value=N.value)}let Z=e(``),Gn=m(()=>/\/issues\/\d+/.test(Z.value.trim()));function Kn(){Y.value=!Y.value,Y.value||(Z.value=``)}let Q=e(!1),$=e(null),qn=e([]),Jn=e(!1);async function Yn(){if(!I.value.trim()){qn.value=[];return}Jn.value=!0;try{qn.value=await Ne.fetchOrphanWorktrees(I.value.trim())}catch{qn.value=[]}finally{Jn.value=!1}}function Xn(){Q.value=!Q.value,Q.value?(M.value=!1,j.value=``,Y.value=!1,Z.value=``,z.value=!0,Yn()):$.value=null}te(I,()=>{$.value=null,Q.value&&Yn()}),te($,e=>{if(!e)return;let t=qn.value.find(t=>t.path===e);t&&(L.value=t.suggestedSourceBranch),z.value=!0});async function Zn(e){if(!e.trim()){H.value=[],L.value=null;return}un.value=!0;try{let t=await fetch(`/api/git/branches?path=${encodeURIComponent(e.trim())}`);if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.json();H.value=n.local??n.branches??[],H.value.length>0&&!L.value&&(L.value=H.value[0]??null)}catch{H.value=[],L.value=null}finally{un.value=!1}}function Qn(e){let t=E.getProjectByPath(e);if(t){t.defaultSourceBranch&&(L.value=t.defaultSourceBranch);let e=t.taskPromptTemplate??``;(O.value===``||O.value===Jt.value)&&(O.value=e,Jt.value=e);let n=K.value.map(e=>e.value);if(t.defaultModel&&n.includes(t.defaultModel))N.value=t.defaultModel;else{let e=E.global.defaultModelByEngine?.[B.value];typeof e==`string`&&n.includes(e)&&(N.value=e)}}V.value=on(e,B.value)}let $n=null;te(I,e=>{$n&&clearTimeout($n),$n=setTimeout(()=>{L.value=null,Zn(e),Qn(e)},500)});function er(e,t){let n=e.toLowerCase();t(()=>{Gt.value=E.projectPaths.filter(e=>e.toLowerCase().includes(n)||Se(e).toLowerCase().includes(n))})}function tr(e){I.value=E.projectPaths.find(t=>Se(t)===e)??e}n(async()=>{await E.fetchSettings();let e=E.global.branchPrefixes;e.length>0&&!e.includes(R.value)&&(R.value=e[0]);let t=Pe();t.autoLoop===!0&&(X.value=!0),t.autoLoopSessionMode===`continuous`&&(Un.value=`continuous`),t.autoLoop===!0&&t.brainstormModel&&(P.value=t.brainstormModel),t.projectPath&&E.projectPaths.includes(t.projectPath)&&(I.value=t.projectPath),V.value=on(I.value,B.value);try{let e=await fetch(`/api/engines`);e.ok&&(en.value=await e.json())}catch{}{let e=K.value.map(e=>e.value),t=E.global.defaultModelByEngine?.[B.value];typeof t==`string`&&e.includes(t)?N.value=t:e.length>0&&!e.includes(N.value)&&(N.value=e.includes(`auto`)?`auto`:e[0]??`auto`)}{let e=K.value.map(e=>e.value);e.length>0&&!e.includes(P.value)&&(P.value=e.includes(`auto`)?`auto`:e[0]??`auto`)}window.addEventListener(`keydown`,Tn),window.addEventListener(`keyup`,En),window.addEventListener(`blur`,Dn),document.addEventListener(`visibilitychange`,On)}),r(()=>{$n&&clearTimeout($n),window.removeEventListener(`keydown`,Tn),window.removeEventListener(`keyup`,En),window.removeEventListener(`blur`,Dn),document.removeEventListener(`visibilitychange`,On),Qt.value&&=(clearTimeout(Qt.value),null),k.value&&G()});function nr(e){return e.normalize(`NFD`).replace(/[\u0300-\u036f]/g,``).toLowerCase().replace(/[^a-z0-9\s-]/g,``).trim().replace(/\s+/g,`-`).replace(/-+/g,`-`).substring(0,50)}function rr(){return Kt.value.trim()?Kt.value.trim().substring(0,80):!M.value&&!Y.value&&O.value.trim()&&(O.value.trim().split(`
2
2
  `)[0]??``).substring(0,80)||`workspace`}function ir(e){let t=(e.split(`/`).pop()??``).split(`-`);t.length>1&&/^[0-9a-f]{12,}$/i.test(t[t.length-1])&&t.pop();let n=t.join(`-`).toLowerCase(),r=n.match(/tk-(\d+)/);if(r){let e=`TK-${r[1]}`,t=n.replace(/tk-\d+/i,``).replace(/-+/g,`-`).replace(/^-|-$/g,``).substring(0,40);return t?`${e}--${t}`:e}return n.substring(0,50)||`task-${Date.now()}`}function ar(){return M.value&&!q.value?D(`createPage.validationNotionUrl`):Y.value&&!Gn.value?D(`createPage.sentryValidation`):!M.value&&!Y.value&&!O.value.trim()?D(`createPage.validationDescription`):!M.value&&!Y.value&&(!rr()||rr()===`workspace`)&&!Kt.value.trim()&&!O.value.trim()?D(`createPage.validationName`):I.value.trim()?L.value?null:D(`createPage.validationBranch`):D(`createPage.validationPath`)}async function or(){let e=ar();if(e){T.notify({type:`negative`,message:e,position:`top`});return}if(Q.value&&!$.value){T.notify({type:`negative`,message:D(`createPage.pickWorktreeRequired`),position:`top`});return}dn.value=!0;try{let e=rr(),t;t=M.value&&q.value?ir(Mn()):e===`workspace`?`task-${Date.now()}`:nr(e);let n=`${R.value}/${t}`,r={name:e,projectPath:I.value.trim(),sourceBranch:L.value,...Q.value&&$.value?{worktreePath:$.value,skipSetupScript:!0}:{workingBranch:n},engine:B.value,model:N.value,reasoningEffort:F.value,...M.value&&q.value?{notionUrl:Mn()}:{},...Y.value&&Gn.value?{sentryUrl:Z.value.trim()}:{},...Ln.value&&Nn.value.length>0?{tasks:Nn.value}:{},...Ln.value&&Pn.value.length>0?{acceptanceCriteria:Pn.value}:{},...z.value&&!Q.value?{skipSetupScript:!0}:{},...O.value.trim()?{description:O.value.trim()}:{},...X.value?{autoLoop:!0,autoLoopSessionMode:Un.value,brainstormModel:P.value}:{},agentPermissionMode:X.value&&V.value===`plan`?`bypass`:V.value},i=await Ne.createWorkspace(r);i._branchAdjusted&&T.notify({type:`info`,message:D(`createPage.branchAdjusted`,{branch:i.workingBranch}),position:`top`,timeout:6e3}),Fe({projectPath:I.value.trim(),autoLoop:X.value,autoLoopSessionMode:Un.value,...X.value?{brainstormModel:P.value}:{}}),fe().subscribe(i.id),Ne.selectWorkspace(i.id),Me.push({name:`workspace`,params:{id:i.id}})}catch{T.notify({type:`negative`,message:D(`createPage.errorCreating`),position:`top`})}finally{dn.value=!1}}return(e,n)=>(a(),d(Ce,{class:`create-page flex flex-center column`},{default:o(()=>[p(`div`,Ie,[p(`div`,Le,l(e.$t(`createPage.title`)),1),p(`div`,Re,[p(`div`,ze,[p(`span`,Be,[c(_,{name:`auto_awesome`,size:`14px`,color:`indigo-4`}),p(`span`,Ve,l(tn.value?.displayName??e.$t(`createPage.claudeCode`)),1)]),c(be),c(y,{flat:``,dense:``,"no-caps":``,size:`sm`,color:M.value?`green-4`:`grey-5`,class:`notion-toggle-btn text-caption rounded-borders`,disable:Q.value,onClick:Hn},{default:o(()=>[c(_,{name:`description`,size:`14px`,class:`q-mr-xs`}),g(` `+l(M.value?e.$t(`createPage.notionEnabled`):e.$t(`createPage.importNotion`)),1)]),_:1},8,[`color`,`disable`]),c(y,{flat:``,dense:``,"no-caps":``,size:`sm`,color:Y.value?`red-4`:`grey-5`,class:`sentry-toggle-btn text-caption rounded-borders q-ml-sm`,disable:Q.value,onClick:Kn},{default:o(()=>[c(_,{name:`bug_report`,size:`14px`,class:`q-mr-xs`}),g(` `+l(Y.value?e.$t(`createPage.sentryEnabled`):e.$t(`createPage.importSentry`)),1)]),_:1},8,[`color`,`disable`])]),c(le,{color:`grey-9`}),c(ae,{name:`slide`},{default:o(()=>[M.value?(a(),s(`div`,He,[c(v,{modelValue:j.value,"onUpdate:modelValue":n[0]||=e=>j.value=e,borderless:``,dense:``,placeholder:e.$t(`createPage.notionPlaceholder`),class:`notion-url-input`,"input-class":`notion-url-input-inner`},{prepend:o(()=>[c(_,{name:`link`,size:`16px`,color:q.value?`green-4`:`grey-6`},null,8,[`color`])]),_:1},8,[`modelValue`,`placeholder`]),j.value.trim()&&!q.value?(a(),s(`div`,Ue,l(e.$t(`createPage.notionValidation`)),1)):u(``,!0),q.value?(a(),s(`div`,We,l(e.$t(`createPage.notionAutoExtract`)),1)):u(``,!0),q.value&&jn.value?(a(),s(`div`,Ge,[p(`div`,Ke,[c(_,{name:`info`,size:`14px`,color:`indigo-4`,class:`q-mr-xs`}),g(` `+l(e.$t(`createPage.notionPanelChoiceLabel`)),1)]),p(`div`,qe,[p(`button`,{type:`button`,class:ne([`peek-card col`,{"peek-card--active":J.value===`panel`}]),onClick:n[1]||=e=>J.value=`panel`},[c(_,{name:`article`,size:`22px`,class:`peek-card-icon`}),p(`div`,Je,[p(`div`,Ye,l(e.$t(`createPage.notionPanelOption`)),1),p(`div`,Xe,l(e.$t(`createPage.notionPanelOptionDesc`)),1)]),J.value===`panel`?(a(),d(_,{key:0,name:`check_circle`,size:`18px`,color:`indigo-4`,class:`peek-card-check`})):u(``,!0)],2),p(`button`,{type:`button`,class:ne([`peek-card col`,{"peek-card--active":J.value===`parent`}]),onClick:n[2]||=e=>J.value=`parent`},[c(_,{name:`folder_open`,size:`22px`,class:`peek-card-icon`}),p(`div`,Ze,[p(`div`,Qe,l(e.$t(`createPage.notionParentOption`)),1),p(`div`,$e,l(e.$t(`createPage.notionParentOptionDesc`)),1)]),J.value===`parent`?(a(),d(_,{key:0,name:`check_circle`,size:`18px`,color:`indigo-4`,class:`peek-card-check`})):u(``,!0)],2)])])):u(``,!0)])):u(``,!0)]),_:1}),M.value?(a(),d(le,{key:0,color:`grey-9`})):u(``,!0),c(ae,{name:`slide`},{default:o(()=>[Y.value?(a(),s(`div`,et,[c(v,{modelValue:Z.value,"onUpdate:modelValue":n[3]||=e=>Z.value=e,borderless:``,dense:``,placeholder:e.$t(`createPage.sentryPlaceholder`),class:`sentry-url-input`,"input-class":`sentry-url-input-inner`},{prepend:o(()=>[c(_,{name:`link`,size:`16px`,color:Gn.value?`red-4`:`grey-6`},null,8,[`color`])]),_:1},8,[`modelValue`,`placeholder`]),Z.value.trim()&&!Gn.value?(a(),s(`div`,tt,l(e.$t(`createPage.sentryValidation`)),1)):u(``,!0),Gn.value?(a(),s(`div`,nt,l(e.$t(`createPage.sentryAutoExtract`)),1)):u(``,!0)])):u(``,!0)]),_:1}),Y.value?(a(),d(le,{key:1,color:`grey-9`})):u(``,!0),p(`div`,rt,[c(v,{modelValue:Kt.value,"onUpdate:modelValue":n[4]||=e=>Kt.value=e,borderless:``,dense:``,placeholder:M.value&&q.value?e.$t(`createPage.workspaceName`):e.$t(`createPage.workspaceNamePlaceholder`),class:`name-input`,"input-class":`name-input-inner`},null,8,[`modelValue`,`placeholder`])]),c(le,{color:`grey-9`}),p(`div`,it,[c(v,{ref_key:`descriptionRef`,ref:qt,modelValue:O.value,"onUpdate:modelValue":n[5]||=e=>O.value=e,type:`textarea`,borderless:``,autogrow:``,rows:3,placeholder:M.value?e.$t(`createPage.instructions`):e.$t(`createPage.instructionsPlaceholder`),class:`create-textarea`,"input-class":`create-textarea-input`,onKeydown:[Sn,oe(h(or,[`ctrl`]),[`enter`]),oe(h(or,[`meta`]),[`enter`])]},null,8,[`modelValue`,`placeholder`,`onKeydown`]),p(`div`,at,[A.value?(a(),s(`div`,ot,[c(ge,{size:`14px`,color:`amber-6`,class:`q-mr-xs`}),p(`span`,null,l(e.$t(`voice.transcribing`)),1)])):u(``,!0),c(y,{flat:``,dense:``,size:`sm`,icon:A.value?`hourglass_top`:k.value?`mic`:`mic_none`,color:k.value?`red-5`:A.value?`amber-6`:`grey-6`,disable:!$t.value||A.value,class:ne({"voice-btn--recording":k.value}),onMousedown:h(Cn,[`prevent`]),onMouseup:h(G,[`prevent`]),onMouseleave:h(G,[`prevent`]),onTouchstart:h(Cn,[`prevent`]),onTouchend:h(G,[`prevent`])},{default:o(()=>[c(w,null,{default:o(()=>[g(l(A.value?e.$t(`voice.transcribing`):k.value?e.$t(`voice.recording`):e.$t(`voice.holdToTalk`)),1)]),_:1})]),_:1},8,[`icon`,`color`,`disable`,`class`])]),f(hn)&&f(W).length>0?(a(),d(we,{key:0,class:`create-slash-popup`,"grouped-dropdown":f(gn),"flat-dropdown":f(W),"selected-index":f(U),onSelect:xn},null,8,[`grouped-dropdown`,`flat-dropdown`,`selected-index`])):u(``,!0)]),c(le,{color:`grey-9`}),Ln.value?(a(),s(re,{key:2},[p(`div`,st,l(e.$t(`createPage.manualHint`)),1),c(ve,{dark:``,dense:``,label:e.$t(`createPage.tasks`,{count:Nn.value.length}),"header-class":`text-grey-4 manual-expansion-header`,class:`manual-expansion q-mx-sm`},{default:o(()=>[p(`div`,ct,[p(`div`,lt,[c(v,{modelValue:Fn.value,"onUpdate:modelValue":n[6]||=e=>Fn.value=e,dark:``,dense:``,borderless:``,placeholder:e.$t(`createPage.addTask`),class:`col manual-input`,"input-class":`manual-input-inner`,onKeydown:oe(h(Rn,[`prevent`]),[`enter`])},null,8,[`modelValue`,`placeholder`,`onKeydown`]),c(y,{flat:``,dense:``,round:``,icon:`add`,color:`indigo-4`,disable:!Fn.value.trim(),onClick:Rn},{default:o(()=>[c(w,null,{default:o(()=>[g(l(e.$t(`tooltip.addTask`)),1)]),_:1})]),_:1},8,[`disable`])]),(a(!0),s(re,null,t(Nn.value,(t,n)=>(a(),s(`div`,{key:`task-${n}`,class:`row items-center q-py-xs manual-item`},[p(`span`,ut,l(t),1),c(y,{flat:``,dense:``,round:``,icon:`close`,size:`xs`,color:`grey-6`,onClick:e=>zn(n)},{default:o(()=>[c(w,null,{default:o(()=>[g(l(e.$t(`tooltip.removeTask`)),1)]),_:1})]),_:1},8,[`onClick`])]))),128))])]),_:1},8,[`label`]),c(ve,{dark:``,dense:``,label:e.$t(`createPage.acceptanceCriteria`,{count:Pn.value.length}),"header-class":`text-grey-4 manual-expansion-header`,class:`manual-expansion q-mx-sm q-mb-sm`},{default:o(()=>[p(`div`,dt,[p(`div`,ft,[c(v,{modelValue:In.value,"onUpdate:modelValue":n[7]||=e=>In.value=e,dark:``,dense:``,borderless:``,placeholder:e.$t(`createPage.addCriterion`),class:`col manual-input`,"input-class":`manual-input-inner`,onKeydown:oe(h(Bn,[`prevent`]),[`enter`])},null,8,[`modelValue`,`placeholder`,`onKeydown`]),c(y,{flat:``,dense:``,round:``,icon:`add`,color:`indigo-4`,disable:!In.value.trim(),onClick:Bn},{default:o(()=>[c(w,null,{default:o(()=>[g(l(e.$t(`tooltip.addCriterion`)),1)]),_:1})]),_:1},8,[`disable`])]),(a(!0),s(re,null,t(Pn.value,(t,n)=>(a(),s(`div`,{key:`crit-${n}`,class:`row items-center q-py-xs manual-item`},[p(`span`,pt,l(t),1),c(y,{flat:``,dense:``,round:``,icon:`close`,size:`xs`,color:`grey-6`,onClick:e=>Vn(n)},{default:o(()=>[c(w,null,{default:o(()=>[g(l(e.$t(`tooltip.removeCriterion`)),1)]),_:1})]),_:1},8,[`onClick`])]))),128))])]),_:1},8,[`label`]),c(le,{color:`grey-9`})],64)):u(``,!0),p(`div`,mt,[p(`div`,ht,[nn.value.length>0?(a(),s(`div`,gt,[c(C,{modelValue:B.value,"onUpdate:modelValue":n[8]||=e=>B.value=e,options:nn.value,dense:``,borderless:``,class:`bottom-select rounded-borders`,"hide-dropdown-icon":``,"emit-value":``,"map-options":``,"option-value":`value`,"option-label":`label`},{selected:o(()=>[p(`span`,_t,[c(_,{name:`hub`,size:`12px`,color:`grey-5`,class:`q-mr-xs`}),g(` `+l(nn.value.find(e=>e.value===B.value)?.label??B.value)+` `,1),c(_,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),default:o(()=>[c(w,null,{default:o(()=>[g(l(e.$t(`engine.select`)),1)]),_:1})]),_:1},8,[`modelValue`,`options`])])):u(``,!0),p(`div`,vt,[c(C,{modelValue:N.value,"onUpdate:modelValue":n[9]||=e=>N.value=e,options:K.value,dense:``,borderless:``,class:`bottom-select rounded-borders model-select`,"hide-dropdown-icon":``,"emit-value":``,"map-options":``,"option-value":`value`,"option-label":`label`},{selected:o(()=>[p(`span`,yt,[X.value?(a(),s(`span`,bt,l(e.$t(`autoLoop.executionModelPrefix`)),1)):u(``,!0),g(` `+l(K.value.find(e=>e.value===N.value)?.label??N.value)+` `,1),c(_,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),option:o(({opt:e,itemProps:t})=>[c(x,i(t,{class:`model-option`}),{default:o(()=>[c(b,null,{default:o(()=>[c(S,{class:`text-white`},{default:o(()=>[g(l(e.label),1)]),_:2},1024),c(S,{caption:``,class:`text-grey-5`},{default:o(()=>[g(l(e.description),1)]),_:2},1024)]),_:2},1024)]),_:2},1040)]),default:o(()=>[X.value?(a(),d(w,{key:0},{default:o(()=>[g(l(e.$t(`autoLoop.executionModelTooltip`)),1)]),_:1})):u(``,!0)]),_:1},8,[`modelValue`,`options`])]),p(`div`,xt,[c(C,{modelValue:F.value,"onUpdate:modelValue":n[10]||=e=>F.value=e,options:An.value,dense:``,borderless:``,class:`bottom-select rounded-borders`,"hide-dropdown-icon":``,"emit-value":``,"map-options":``,"option-value":`value`,"option-label":`label`},{selected:o(()=>[p(`span`,St,[c(_,{name:`psychology`,size:`12px`,color:`grey-5`,class:`q-mr-xs`}),g(` `+l(An.value.find(e=>e.value===F.value)?.label??F.value)+` `,1),c(_,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),option:o(({opt:e,itemProps:t})=>[c(x,se(ce(t)),{default:o(()=>[c(b,null,{default:o(()=>[c(S,{class:`text-white`},{default:o(()=>[g(l(e.label),1)]),_:2},1024),c(S,{caption:``,class:`text-grey-5`},{default:o(()=>[g(l(e.description),1)]),_:2},1024)]),_:2},1024)]),_:2},1040)]),_:1},8,[`modelValue`,`options`])]),p(`div`,Ct,[c(C,{modelValue:V.value,"onUpdate:modelValue":n[11]||=e=>V.value=e,options:cn.value,disable:X.value,dense:``,borderless:``,class:`bottom-select rounded-borders`,"hide-dropdown-icon":``,"emit-value":``,"map-options":``,"option-value":`value`,"option-label":`label`,"option-disable":ye},{selected:o(()=>[p(`span`,wt,[c(_,{name:sn.value,size:`12px`,color:`amber-6`,class:`q-mr-xs`},null,8,[`name`]),g(` `+l(cn.value.find(e=>e.value===V.value)?.label??V.value)+` `,1),X.value?u(``,!0):(a(),d(_,{key:0,name:`expand_more`,size:`12px`,color:`grey-5`}))])]),default:o(()=>[c(w,null,{default:o(()=>[g(l(X.value?e.$t(`agentPermissionMode.autoLoopLocked`):e.$t(`agentPermissionMode.tooltip`)),1)]),_:1})]),_:1},8,[`modelValue`,`options`,`disable`])])]),p(`div`,Tt,[p(`div`,Et,[c(y,{flat:``,dense:``,size:`sm`,"no-caps":``,icon:X.value?`autorenew`:`sync_disabled`,color:X.value?`amber-4`:`grey-5`,label:e.$t(`autoLoop.startInMode`),class:`skip-setup-btn`,onClick:Wn},{default:o(()=>[c(w,null,{default:o(()=>[g(l(e.$t(`autoLoop.startInMode`)),1)]),_:1})]),_:1},8,[`icon`,`color`,`label`])]),X.value?(a(),s(`div`,Dt,[c(xe,{modelValue:Un.value,"onUpdate:modelValue":n[12]||=e=>Un.value=e,dense:``,"no-caps":``,size:`sm`,"toggle-color":`indigo-8`,color:`grey-9`,"text-color":`grey-5`,options:[{label:e.$t(`autoLoop.sessionMode.perTask`),value:`per_task`,icon:`restart_alt`},{label:e.$t(`autoLoop.sessionMode.continuous`),value:`continuous`,icon:`link`}]},{default:o(()=>[c(w,null,{default:o(()=>[g(l(Un.value===`continuous`?e.$t(`autoLoop.sessionMode.continuousTooltip`):e.$t(`autoLoop.sessionMode.perTaskTooltip`)),1)]),_:1})]),_:1},8,[`modelValue`,`options`])])):u(``,!0),X.value?(a(),s(`div`,Ot,[c(C,{modelValue:P.value,"onUpdate:modelValue":n[13]||=e=>P.value=e,options:K.value,dense:``,borderless:``,class:`bottom-select rounded-borders model-select`,"hide-dropdown-icon":``,"emit-value":``,"map-options":``,"option-value":`value`,"option-label":`label`},{selected:o(()=>[p(`span`,kt,[c(_,{name:`tips_and_updates`,size:`12px`,color:`amber-6`,class:`q-mr-xs`}),p(`span`,At,l(e.$t(`autoLoop.brainstormModelPrefix`)),1),g(` `+l(K.value.find(e=>e.value===P.value)?.label??P.value)+` `,1),c(_,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),option:o(({opt:e,itemProps:t})=>[c(x,i(t,{class:`model-option`}),{default:o(()=>[c(b,null,{default:o(()=>[c(S,{class:`text-white`},{default:o(()=>[g(l(e.label),1)]),_:2},1024),c(S,{caption:``,class:`text-grey-5`},{default:o(()=>[g(l(e.description),1)]),_:2},1024)]),_:2},1024)]),_:2},1040)]),default:o(()=>[c(w,null,{default:o(()=>[g(l(e.$t(`autoLoop.brainstormModelTooltip`)),1)]),_:1})]),_:1},8,[`modelValue`,`options`])])):u(``,!0)]),p(`div`,jt,[p(`div`,Mt,[c(y,{flat:``,dense:``,size:`sm`,"no-caps":``,icon:z.value?`play_disabled`:`play_circle`,color:z.value?`orange-4`:`grey-5`,label:e.$t(`createPage.skipSetupScript`),class:`skip-setup-btn`,onClick:n[14]||=e=>z.value=!z.value},{default:o(()=>[c(w,null,{default:o(()=>[g(l(e.$t(`createPage.skipSetupScript`)),1)]),_:1})]),_:1},8,[`icon`,`color`,`label`])]),p(`div`,Nt,[c(y,{flat:``,dense:``,size:`sm`,"no-caps":``,icon:`folder_open`,color:Q.value?`cyan-4`:`grey-5`,label:Q.value?e.$t(`createPage.attachWorktreeEnabled`):e.$t(`createPage.attachWorktreeToggle`),class:`skip-setup-btn`,onClick:Xn},null,8,[`color`,`label`])])]),p(`div`,Pt,[p(`div`,Ft,[c(C,{modelValue:I.value,"onUpdate:modelValue":n[15]||=e=>I.value=e,options:Gt.value,dense:``,borderless:``,"use-input":``,"fill-input":``,"hide-selected":``,"input-debounce":`0`,"new-value-mode":`add`,class:`bottom-select rounded-borders repo-select`,"hide-dropdown-icon":``,"input-class":I.value?``:`repo-input-empty`,placeholder:e.$t(`createPage.projectPath`),behavior:f(E).projectPaths.length>0?`menu`:`dialog`,"option-label":e=>e?f(Se)(e):``,onFilter:er,onInputValue:tr},{prepend:o(()=>[c(_,{name:`folder`,size:`14px`,color:`grey-5`})]),option:o(({opt:e,itemProps:t})=>[c(x,se(ce(t)),{default:o(()=>[c(b,null,{default:o(()=>[c(S,null,{default:o(()=>[g(l(f(Se)(e)),1)]),_:2},1024),c(S,{caption:``},{default:o(()=>[g(l(e),1)]),_:2},1024)]),_:2},1024)]),_:2},1040)]),"no-option":o(()=>[c(x,null,{default:o(()=>[c(b,{class:`text-grey-6 text-caption`},{default:o(()=>[g(l(e.$t(`createPage.enterPath`)),1)]),_:1})]),_:1})]),_:1},8,[`modelValue`,`options`,`input-class`,`placeholder`,`behavior`,`option-label`])]),Q.value?u(``,!0):(a(),s(`div`,It,[c(C,{modelValue:R.value,"onUpdate:modelValue":n[16]||=e=>R.value=e,options:rn.value,"emit-value":``,"map-options":``,dense:``,borderless:``,class:`bottom-select rounded-borders branch-type-select`,"hide-dropdown-icon":``},{selected:o(()=>[p(`span`,Lt,[c(_,{name:`account_tree`,size:`12px`,color:`grey-5`,class:`q-mr-xs`}),g(` `+l(R.value)+`/ `,1),c(_,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),default:o(()=>[c(w,null,{default:o(()=>[g(l(e.$t(`createPage.branchType`)),1)]),_:1})]),_:1},8,[`modelValue`,`options`])])),Q.value?(a(),s(`div`,Rt,[c(C,{modelValue:$.value,"onUpdate:modelValue":n[17]||=e=>$.value=e,options:qn.value,"option-label":`branch`,"option-value":`path`,"emit-value":``,"map-options":``,"use-input":``,dense:``,borderless:``,class:`bottom-select rounded-borders worktree-select`,"hide-dropdown-icon":``,loading:Jn.value,disable:!I.value.trim()||Jn.value},{selected:o(()=>[p(`span`,zt,[c(_,{name:`folder_open`,size:`12px`,color:`cyan-5`,class:`q-mr-xs`}),g(` `+l($.value?qn.value.find(e=>e.path===$.value)?.branch??$.value:e.$t(`createPage.worktreePickerLabel`))+` `,1),c(_,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),option:o(e=>[c(x,se(ce(e.itemProps)),{default:o(()=>[c(b,null,{default:o(()=>[c(S,null,{default:o(()=>[g(l(e.opt.branch),1)]),_:2},1024),c(S,{caption:``},{default:o(()=>[g(l(e.opt.path),1)]),_:2},1024)]),_:2},1024)]),_:2},1040)]),"no-option":o(()=>[c(x,null,{default:o(()=>[c(b,{class:`text-grey-6 text-caption`},{default:o(()=>[g(l(I.value.trim()?e.$t(`createPage.noOrphanWorktrees`):e.$t(`createPage.enterPath`)),1)]),_:1})]),_:1})]),_:1},8,[`modelValue`,`options`,`loading`,`disable`])])):u(``,!0),p(`div`,Bt,[c(C,{modelValue:L.value,"onUpdate:modelValue":n[18]||=e=>L.value=e,options:ln.value,dense:``,borderless:``,class:`bottom-select rounded-borders branch-select`,"hide-dropdown-icon":``,"use-input":``,"input-debounce":`0`,loading:un.value,disable:!I.value.trim()||un.value,onFilter:fn},{selected:o(()=>[p(`span`,Vt,[c(_,{name:`call_split`,size:`12px`,color:`grey-5`,class:`q-mr-xs`}),g(` `+l(L.value??e.$t(`createPage.branch`))+` `,1),c(_,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),"no-option":o(()=>[c(x,null,{default:o(()=>[c(b,{class:`text-grey-6 text-caption`},{default:o(()=>[g(l(I.value.trim()?e.$t(`createPage.noBranches`):e.$t(`createPage.enterPath`)),1)]),_:1})]),_:1})]),_:1},8,[`modelValue`,`options`,`loading`,`disable`])])])]),p(`div`,Ht,[c(y,{label:e.$t(`createPage.create`),"no-caps":``,unelevated:``,class:`create-btn text-weight-bold rounded-borders`,loading:dn.value,disable:dn.value||Q.value&&!$.value,onClick:or},null,8,[`label`,`loading`,`disable`])])]),p(`div`,Ut,l(M.value?e.$t(`createPage.notionExtractHint`):e.$t(`createPage.notionImportHint`)),1)])]),_:1}))}}),[[`__scopeId`,`data-v-0767cd07`]]);export{E as default};