@loicngr/kobo 1.6.12 → 1.6.13

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 (78) hide show
  1. package/README.md +10 -6
  2. package/dist/mcp-server/kobo-tasks-handlers.js +2 -2
  3. package/dist/server/db/migrations.js +24 -0
  4. package/dist/server/db/schema.js +10 -0
  5. package/dist/server/index.js +27 -4
  6. package/dist/server/routes/documents.js +2 -2
  7. package/dist/server/routes/git.js +21 -0
  8. package/dist/server/routes/health.js +2 -2
  9. package/dist/server/routes/images.js +3 -3
  10. package/dist/server/routes/usage.js +18 -0
  11. package/dist/server/routes/workspaces.js +207 -81
  12. package/dist/server/services/agent/engines/claude-code/args-builder.js +2 -0
  13. package/dist/server/services/agent/orchestrator.js +1 -1
  14. package/dist/server/services/auto-loop-service.js +22 -4
  15. package/dist/server/services/dev-server-service.js +2 -5
  16. package/dist/server/services/settings-service.js +18 -2
  17. package/dist/server/services/usage/db.js +29 -0
  18. package/dist/server/services/usage/index.js +2 -0
  19. package/dist/server/services/usage/poller.js +52 -0
  20. package/dist/server/services/usage/providers/claude-code.js +93 -0
  21. package/dist/server/services/usage/types.js +1 -0
  22. package/dist/server/services/wakeup-service.js +2 -2
  23. package/dist/server/services/websocket-service.js +14 -0
  24. package/dist/server/services/workspace-service.js +28 -3
  25. package/dist/server/services/worktree-service.js +50 -0
  26. package/dist/server/utils/mcp-client.js +7 -0
  27. package/dist/shared/auto-loop-prompts.js +46 -8
  28. package/package.json +1 -1
  29. package/src/client/dist/spa/assets/{ActivityFeed-6Xg7qNfy.js → ActivityFeed-BsY3-q5d.js} +1 -1
  30. package/src/client/dist/spa/assets/CreatePage-Cdhkkx-X.js +2 -0
  31. package/src/client/dist/spa/assets/CreatePage-PRvhol1N.css +1 -0
  32. package/src/client/dist/spa/assets/{DiffViewer-T111s7BH.js → DiffViewer-DXcoEtVq.js} +2 -2
  33. package/src/client/dist/spa/assets/{HealthPage-1VakQ0x_.js → HealthPage-BSyGqDRu.js} +1 -1
  34. package/src/client/dist/spa/assets/{MainLayout-Ci-CETJi.css → MainLayout-D2SfvksB.css} +1 -1
  35. package/src/client/dist/spa/assets/{MainLayout-w7DoW3yz.js → MainLayout-EYaLqjJx.js} +17 -17
  36. package/src/client/dist/spa/assets/{SearchPage-CcldJX8i.js → SearchPage-Bgx02GOH.js} +1 -1
  37. package/src/client/dist/spa/assets/SettingsPage-BTSOovDV.js +1 -0
  38. package/src/client/dist/spa/assets/SettingsPage-CwLELxfl.css +1 -0
  39. package/src/client/dist/spa/assets/WorkspacePage-C5MZx1sZ.css +1 -0
  40. package/src/client/dist/spa/assets/WorkspacePage-C8dJWu-n.js +4 -0
  41. package/src/client/dist/spa/assets/{build-path-tree-DbuI5yRz.js → build-path-tree-D-2LpB2J.js} +1 -1
  42. package/src/client/dist/spa/assets/{cssMode-DhpmJAZc.js → cssMode-DVBmJp-B.js} +1 -1
  43. package/src/client/dist/spa/assets/{documents-fVD9RJth.js → documents-Ck8VwvpQ.js} +1 -1
  44. package/src/client/dist/spa/assets/{editor.api-DCvwHsju.js → editor.api-DgbPJaK4.js} +1 -1
  45. package/src/client/dist/spa/assets/{editor.main-CRtPC0iL.js → editor.main-BqqoRfAU.js} +3 -3
  46. package/src/client/dist/spa/assets/{expand-template-BIra7NIw.js → expand-template-bkCTc78P.js} +1 -1
  47. package/src/client/dist/spa/assets/{freemarker2-C9UOErQw.js → freemarker2-CgaW0Q0y.js} +1 -1
  48. package/src/client/dist/spa/assets/{handlebars-DmZ2-ZcJ.js → handlebars-BSs5PdXe.js} +1 -1
  49. package/src/client/dist/spa/assets/{html-ButyxlXG.js → html-C9wlJaMs.js} +1 -1
  50. package/src/client/dist/spa/assets/{htmlMode-C-defy1b.js → htmlMode-DaRssGJk.js} +1 -1
  51. package/src/client/dist/spa/assets/i18n-BSNIShFg.js +1 -0
  52. package/src/client/dist/spa/assets/index-odgA9x8A.js +2 -0
  53. package/src/client/dist/spa/assets/{javascript-B6zVweIF.js → javascript-D0VYhsc-.js} +1 -1
  54. package/src/client/dist/spa/assets/{jsonMode-CttMw-EY.js → jsonMode-B57EaUNS.js} +1 -1
  55. package/src/client/dist/spa/assets/kobo-commands-D-9dbM70.js +11 -0
  56. package/src/client/dist/spa/assets/{liquid-tGpdE1YW.js → liquid-gP2gg7sw.js} +1 -1
  57. package/src/client/dist/spa/assets/{mdx-Cy5mpQoy.js → mdx-HhXcZn_S.js} +1 -1
  58. package/src/client/dist/spa/assets/{models-DdAQDnqk.js → models-CJC61gWE.js} +1 -1
  59. package/src/client/dist/spa/assets/{monaco.contribution-DtdkkTgR.js → monaco.contribution-ChJg8bwd.js} +2 -2
  60. package/src/client/dist/spa/assets/{python-hLOxMbm9.js → python-DM6FfMV3.js} +1 -1
  61. package/src/client/dist/spa/assets/{razor-tqHFRROa.js → razor-XifsxhTG.js} +1 -1
  62. package/src/client/dist/spa/assets/stats-C3n1k51k.js +1 -0
  63. package/src/client/dist/spa/assets/{tsMode-MJKgZYsJ.js → tsMode-B8gurPqG.js} +1 -1
  64. package/src/client/dist/spa/assets/{typescript-CWTqB5lb.js → typescript-CZKTCOjl.js} +1 -1
  65. package/src/client/dist/spa/assets/{xml-ByDBLBVa.js → xml-CtZPkb7Q.js} +1 -1
  66. package/src/client/dist/spa/assets/{yaml-BiTCWZ38.js → yaml-D5IEE5M-.js} +1 -1
  67. package/src/client/dist/spa/index.html +1 -1
  68. package/src/mcp-server/kobo-tasks-handlers.ts +3 -2
  69. package/src/client/dist/spa/assets/CreatePage-BQu7mQjm.css +0 -1
  70. package/src/client/dist/spa/assets/CreatePage-CrRGDs5V.js +0 -2
  71. package/src/client/dist/spa/assets/SettingsPage-CLMCHMpz.css +0 -1
  72. package/src/client/dist/spa/assets/SettingsPage-CMyeaz63.js +0 -1
  73. package/src/client/dist/spa/assets/WorkspacePage-Bw9xhTDR.js +0 -4
  74. package/src/client/dist/spa/assets/WorkspacePage-_1mty_a4.css +0 -1
  75. package/src/client/dist/spa/assets/i18n-C8aJvuyS.js +0 -1
  76. package/src/client/dist/spa/assets/index-DAbX631s.js +0 -2
  77. package/src/client/dist/spa/assets/kobo-commands-CD7ERFxp.js +0 -10
  78. package/src/client/dist/spa/assets/rate-limit-labels-BaD9dQtl.js +0 -1
@@ -228,6 +228,11 @@ function defaultProjectSettings(projectPath) {
228
228
  startCommand: '',
229
229
  stopCommand: '',
230
230
  },
231
+ e2e: {
232
+ framework: '',
233
+ skill: '',
234
+ prompt: '',
235
+ },
231
236
  };
232
237
  }
233
238
  function pickKnownKeys(data, allowedKeys) {
@@ -434,7 +439,7 @@ export function updateGlobalSettings(data) {
434
439
  writeSettings(settings, { backup: true });
435
440
  return settings.global;
436
441
  }
437
- /** Create or update project-specific settings. Merges devServer fields on update. */
442
+ /** Create or update project-specific settings. Merges devServer and e2e fields on update. */
438
443
  export function upsertProject(projectPath, data) {
439
444
  const allowedProjectKeys = [
440
445
  'displayName',
@@ -445,23 +450,31 @@ export function upsertProject(projectPath, data) {
445
450
  'gitConventions',
446
451
  'setupScript',
447
452
  'devServer',
453
+ 'e2e',
448
454
  ];
449
455
  const allowedDevServerKeys = ['startCommand', 'stopCommand'];
456
+ const allowedE2eKeys = ['framework', 'skill', 'prompt'];
450
457
  const filtered = pickKnownKeys(data, allowedProjectKeys);
451
458
  if (filtered.devServer) {
452
459
  filtered.devServer = pickKnownKeys(filtered.devServer, allowedDevServerKeys);
453
460
  }
461
+ if (filtered.e2e) {
462
+ filtered.e2e = pickKnownKeys(filtered.e2e, allowedE2eKeys);
463
+ }
454
464
  const settings = readSettings();
455
465
  const idx = settings.projects.findIndex((p) => p.path === projectPath);
456
466
  if (idx >= 0) {
457
- // Update existing project — merge devServer separately to allow partial updates
467
+ // Update existing project — merge devServer and e2e separately to allow partial updates
458
468
  const existing = settings.projects[idx];
459
469
  const updatedDevServer = filtered.devServer ? { ...existing.devServer, ...filtered.devServer } : existing.devServer;
470
+ const existingE2e = existing.e2e ?? defaultProjectSettings(projectPath).e2e;
471
+ const updatedE2e = filtered.e2e ? { ...existingE2e, ...filtered.e2e } : existingE2e;
460
472
  settings.projects[idx] = {
461
473
  ...existing,
462
474
  ...filtered,
463
475
  path: projectPath,
464
476
  devServer: updatedDevServer,
477
+ e2e: updatedE2e,
465
478
  };
466
479
  }
467
480
  else {
@@ -474,6 +487,9 @@ export function upsertProject(projectPath, data) {
474
487
  if (filtered.devServer) {
475
488
  newProject.devServer = { ...defaultProjectSettings(projectPath).devServer, ...filtered.devServer };
476
489
  }
490
+ if (filtered.e2e) {
491
+ newProject.e2e = { ...defaultProjectSettings(projectPath).e2e, ...filtered.e2e };
492
+ }
477
493
  settings.projects.push(newProject);
478
494
  }
479
495
  writeSettings(settings, { backup: true });
@@ -0,0 +1,29 @@
1
+ import { getDb } from '../../db/index.js';
2
+ function rowToSnapshot(row) {
3
+ const buckets = JSON.parse(row.buckets_json);
4
+ const snap = {
5
+ providerId: row.provider_id,
6
+ status: row.status,
7
+ buckets,
8
+ fetchedAt: row.fetched_at,
9
+ };
10
+ if (row.error_message !== null) {
11
+ snap.errorMessage = row.error_message;
12
+ }
13
+ return snap;
14
+ }
15
+ export function upsertUsageSnapshot(snap) {
16
+ const db = getDb();
17
+ db.prepare(`INSERT INTO usage_snapshots (provider_id, status, error_message, buckets_json, fetched_at)
18
+ VALUES (?, ?, ?, ?, ?)
19
+ ON CONFLICT(provider_id) DO UPDATE SET
20
+ status = excluded.status,
21
+ error_message = excluded.error_message,
22
+ buckets_json = excluded.buckets_json,
23
+ fetched_at = excluded.fetched_at`).run(snap.providerId, snap.status, snap.errorMessage ?? null, JSON.stringify(snap.buckets), snap.fetchedAt);
24
+ }
25
+ export function getAllPersistedSnapshots() {
26
+ const db = getDb();
27
+ const rows = db.prepare('SELECT * FROM usage_snapshots ORDER BY provider_id').all();
28
+ return rows.map(rowToSnapshot);
29
+ }
@@ -0,0 +1,2 @@
1
+ export { getAllPersistedSnapshots } from './db.js';
2
+ export { refreshNow, startUsagePoller, stopUsagePoller } from './poller.js';
@@ -0,0 +1,52 @@
1
+ import { broadcastAll } from '../websocket-service.js';
2
+ import { upsertUsageSnapshot } from './db.js';
3
+ import { createClaudeCodeProvider } from './providers/claude-code.js';
4
+ export const POLL_INTERVAL_MS = 60_000;
5
+ const DEFAULT_PROVIDERS = [createClaudeCodeProvider()];
6
+ let providers = DEFAULT_PROVIDERS;
7
+ let intervalHandle = null;
8
+ function persistAndBroadcast(snap) {
9
+ upsertUsageSnapshot(snap);
10
+ broadcastAll('usage:snapshot', { providerId: snap.providerId, snapshot: snap });
11
+ }
12
+ async function tick() {
13
+ for (const provider of providers) {
14
+ try {
15
+ if (!(await provider.isAvailable()))
16
+ continue;
17
+ const snap = await provider.fetchSnapshot();
18
+ persistAndBroadcast(snap);
19
+ }
20
+ catch (err) {
21
+ console.error('[usage-poller] tick failed for provider', provider.id, err);
22
+ }
23
+ }
24
+ }
25
+ export function startUsagePoller() {
26
+ if (intervalHandle !== null)
27
+ return;
28
+ void tick();
29
+ intervalHandle = setInterval(() => {
30
+ void tick();
31
+ }, POLL_INTERVAL_MS);
32
+ }
33
+ export function stopUsagePoller() {
34
+ if (intervalHandle === null)
35
+ return;
36
+ clearInterval(intervalHandle);
37
+ intervalHandle = null;
38
+ }
39
+ // Bypasses `isAvailable()` — a manual refresh always returns a snapshot,
40
+ // even an `unauthenticated` one, so the UI gets feedback on the click.
41
+ export async function refreshNow(providerId) {
42
+ const provider = providers.find((p) => p.id === providerId);
43
+ if (!provider)
44
+ return null;
45
+ const snap = await provider.fetchSnapshot();
46
+ persistAndBroadcast(snap);
47
+ return snap;
48
+ }
49
+ // Test seam — pass `null` to restore the default provider list.
50
+ export function _setProvidersForTest(list) {
51
+ providers = list ?? DEFAULT_PROVIDERS;
52
+ }
@@ -0,0 +1,93 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ const API_URL = 'https://api.anthropic.com/api/oauth/usage';
5
+ const BETA_HEADER = 'oauth-2025-04-20';
6
+ const FETCH_TIMEOUT_MS = 10_000;
7
+ function credentialsFilePath() {
8
+ const dir = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), '.claude');
9
+ return path.join(dir, '.credentials.json');
10
+ }
11
+ async function readAccessToken() {
12
+ try {
13
+ const raw = await fs.readFile(credentialsFilePath(), 'utf8');
14
+ const parsed = JSON.parse(raw);
15
+ const token = parsed?.claudeAiOauth?.accessToken;
16
+ return typeof token === 'string' && token.length > 0 ? token : null;
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ function mapBucket(id, raw) {
23
+ const utilization = typeof raw?.utilization === 'number' ? raw.utilization : 0;
24
+ const resetsAt = typeof raw?.resets_at === 'string' ? raw.resets_at : undefined;
25
+ return {
26
+ id,
27
+ label: id,
28
+ usedPct: utilization,
29
+ resetsAt,
30
+ };
31
+ }
32
+ export function createClaudeCodeProvider() {
33
+ return {
34
+ id: 'claude-code',
35
+ displayName: 'Claude Code',
36
+ async isAvailable() {
37
+ return (await readAccessToken()) !== null;
38
+ },
39
+ async fetchSnapshot() {
40
+ const fetchedAt = new Date().toISOString();
41
+ const token = await readAccessToken();
42
+ if (!token) {
43
+ return {
44
+ providerId: 'claude-code',
45
+ status: 'unauthenticated',
46
+ buckets: [],
47
+ fetchedAt,
48
+ };
49
+ }
50
+ const controller = new AbortController();
51
+ const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
52
+ try {
53
+ const res = await fetch(API_URL, {
54
+ headers: {
55
+ Authorization: `Bearer ${token}`,
56
+ 'anthropic-beta': BETA_HEADER,
57
+ },
58
+ signal: controller.signal,
59
+ });
60
+ if (!res.ok) {
61
+ return {
62
+ providerId: 'claude-code',
63
+ status: 'error',
64
+ errorMessage: `HTTP ${res.status}`,
65
+ buckets: [],
66
+ fetchedAt,
67
+ };
68
+ }
69
+ const body = (await res.json());
70
+ const buckets = [mapBucket('five_hour', body.five_hour), mapBucket('seven_day', body.seven_day)];
71
+ return {
72
+ providerId: 'claude-code',
73
+ status: 'ok',
74
+ buckets,
75
+ fetchedAt,
76
+ };
77
+ }
78
+ catch (err) {
79
+ const errorMessage = err instanceof Error ? err.message : String(err);
80
+ return {
81
+ providerId: 'claude-code',
82
+ status: 'error',
83
+ errorMessage,
84
+ buckets: [],
85
+ fetchedAt,
86
+ };
87
+ }
88
+ finally {
89
+ clearTimeout(timeout);
90
+ }
91
+ },
92
+ };
93
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -125,14 +125,14 @@ function fire(workspaceId) {
125
125
  return;
126
126
  }
127
127
  const wsRow = db
128
- .prepare(`SELECT project_path, working_branch, model, permission_mode, reasoning_effort
128
+ .prepare(`SELECT project_path, working_branch, worktree_path, model, permission_mode, reasoning_effort
129
129
  FROM workspaces WHERE id = ?`)
130
130
  .get(workspaceId);
131
131
  if (!wsRow) {
132
132
  emitEphemeral(workspaceId, 'wakeup:skipped', { reason: 'fire-failed' });
133
133
  return;
134
134
  }
135
- const worktreePath = path.join(wsRow.project_path, '.worktrees', wsRow.working_branch);
135
+ const worktreePath = wsRow.worktree_path ?? path.join(wsRow.project_path, '.worktrees', wsRow.working_branch);
136
136
  // Defensive: narrow `permission_mode` against the two known values rather
137
137
  // than trusting the DB column shape. Any unexpected value falls back to
138
138
  // the safer 'auto-accept'.
@@ -1,5 +1,6 @@
1
1
  import { nanoid } from 'nanoid';
2
2
  import { getDb } from '../db/index.js';
3
+ import { getAllPersistedSnapshots } from './usage/db.js';
3
4
  // ── State ──────────────────────────────────────────────────────────────────────
4
5
  /** Maps each WS client to the set of workspaceIds they are subscribed to */
5
6
  const clients = new Map();
@@ -13,6 +14,19 @@ export function setMessageHandler(handler) {
13
14
  export function handleConnection(ws) {
14
15
  // Register client with empty subscription set
15
16
  clients.set(ws, new Set());
17
+ // Push the latest persisted snapshot per provider so the client renders
18
+ // immediately instead of waiting up to POLL_INTERVAL_MS for the next tick.
19
+ try {
20
+ for (const snap of getAllPersistedSnapshots()) {
21
+ ws.send(JSON.stringify({
22
+ type: 'usage:snapshot',
23
+ payload: { providerId: snap.providerId, snapshot: snap },
24
+ }));
25
+ }
26
+ }
27
+ catch (err) {
28
+ console.error('[ws] usage hydration failed:', err);
29
+ }
16
30
  ws.on('message', (data) => {
17
31
  let msg;
18
32
  try {
@@ -43,6 +43,8 @@ function mapWorkspace(row) {
43
43
  autoLoopReady: row.auto_loop_ready === 1,
44
44
  noProgressStreak: row.no_progress_streak ?? 0,
45
45
  permissionProfile: (row.permission_profile ?? 'bypass'),
46
+ worktreePath: row.worktree_path ?? '',
47
+ worktreeOwned: row.worktree_owned === 1,
46
48
  createdAt: row.created_at,
47
49
  updatedAt: row.updated_at,
48
50
  };
@@ -78,10 +80,15 @@ export function createWorkspace(data) {
78
80
  const db = getDb();
79
81
  const now = new Date().toISOString();
80
82
  const id = nanoid();
83
+ const computedWorktreePath = data.worktreePath ?? `${data.projectPath}/.worktrees/${data.workingBranch}`;
84
+ const owned = data.worktreeOwned ?? true;
81
85
  db.prepare(`
82
- INSERT INTO workspaces (id, name, project_path, source_branch, working_branch, status, notion_url, notion_page_id, sentry_url, model, reasoning_effort, permission_mode, engine, created_at, updated_at)
83
- VALUES (?, ?, ?, ?, ?, 'created', ?, ?, ?, ?, ?, ?, ?, ?, ?)
84
- `).run(id, data.name, data.projectPath, data.sourceBranch, data.workingBranch, data.notionUrl ?? null, data.notionPageId ?? null, data.sentryUrl ?? null, data.model ?? 'claude-opus-4-7', data.reasoningEffort ?? 'auto', data.permissionMode ?? 'auto-accept', data.engine ?? 'claude-code', now, now);
86
+ INSERT INTO workspaces (
87
+ id, name, project_path, source_branch, working_branch, status,
88
+ notion_url, notion_page_id, sentry_url, worktree_path, worktree_owned,
89
+ model, reasoning_effort, permission_mode, engine, created_at, updated_at
90
+ ) VALUES (?, ?, ?, ?, ?, 'created', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
91
+ `).run(id, data.name, data.projectPath, data.sourceBranch, data.workingBranch, data.notionUrl ?? null, data.notionPageId ?? null, data.sentryUrl ?? null, computedWorktreePath, owned ? 1 : 0, data.model ?? 'claude-opus-4-7', data.reasoningEffort ?? 'auto', data.permissionMode ?? 'auto-accept', data.engine ?? 'claude-code', now, now);
85
92
  return getWorkspace(id);
86
93
  }
87
94
  /** Fetch a single workspace by ID, or null if not found. */
@@ -114,6 +121,12 @@ export function updateWorkspaceStatus(id, status) {
114
121
  if (!workspace) {
115
122
  throw new Error(`Workspace '${id}' not found`);
116
123
  }
124
+ // Self-transition is a no-op. Some failure paths fan out (e.g. engine emits
125
+ // an error event AND the process exits non-zero), and both try to mark the
126
+ // workspace 'error' — the second call shouldn't throw.
127
+ if (workspace.status === status) {
128
+ return workspace;
129
+ }
117
130
  const allowedTransitions = VALID_TRANSITIONS[workspace.status];
118
131
  if (!allowedTransitions.includes(status)) {
119
132
  throw new Error(`Invalid status transition from '${workspace.status}' to '${status}'. Allowed: ${allowedTransitions.join(', ')}`);
@@ -187,6 +200,18 @@ export function updateWorkingBranch(id, workingBranch) {
187
200
  }
188
201
  return getWorkspace(id);
189
202
  }
203
+ /** Update the on-disk worktree path. Used by rename / resync-branch on owned worktrees. */
204
+ export function updateWorktreePath(id, newPath) {
205
+ const db = getDb();
206
+ const now = new Date().toISOString();
207
+ const result = db
208
+ .prepare('UPDATE workspaces SET worktree_path = ?, updated_at = ? WHERE id = ?')
209
+ .run(newPath, now, id);
210
+ if (result.changes === 0) {
211
+ throw new Error(`Workspace '${id}' not found`);
212
+ }
213
+ return getWorkspace(id);
214
+ }
190
215
  /** Update the agent's permission mode (auto-accept vs plan/read-only). */
191
216
  export function updateWorkspacePermissionMode(id, permissionMode) {
192
217
  const db = getDb();
@@ -118,3 +118,53 @@ export function worktreeExists(projectPath, branchName) {
118
118
  return false;
119
119
  }
120
120
  }
121
+ function canonicalize(p) {
122
+ try {
123
+ return fs.realpathSync(p);
124
+ }
125
+ catch {
126
+ return p;
127
+ }
128
+ }
129
+ function detectSourceBranch(projectPath, worktreePath, branch) {
130
+ // 1. Branch's tracked upstream (configured locally)
131
+ try {
132
+ const upstream = git(worktreePath, ['config', '--get', `branch.${branch}.merge`]);
133
+ if (upstream)
134
+ return upstream.replace(/^refs\/heads\//, '');
135
+ }
136
+ catch {
137
+ /* no upstream configured */
138
+ }
139
+ // 2. Repo's default branch (origin/HEAD)
140
+ try {
141
+ const head = git(projectPath, ['symbolic-ref', 'refs/remotes/origin/HEAD']);
142
+ if (head)
143
+ return head.replace(/^refs\/remotes\/origin\//, '');
144
+ }
145
+ catch {
146
+ /* no origin/HEAD */
147
+ }
148
+ // 3. Final fallback
149
+ return 'main';
150
+ }
151
+ /**
152
+ * List worktrees of a project that are NOT yet attached to a Kōbō workspace.
153
+ * The main worktree is excluded. Detached HEAD worktrees are excluded (no
154
+ * branch to anchor a workspace to). Both sides of the path comparison are
155
+ * canonicalized to defeat symlinks / trailing-slash variants.
156
+ */
157
+ export function listOrphanWorktrees(projectPath, attachedPaths) {
158
+ const canonAttached = new Set(Array.from(attachedPaths).map(canonicalize));
159
+ const canonProject = canonicalize(projectPath);
160
+ return listWorktrees(projectPath)
161
+ .filter((wt) => canonicalize(wt.path) !== canonProject)
162
+ .filter((wt) => !!wt.branch && wt.branch !== '(detached HEAD)')
163
+ .filter((wt) => !canonAttached.has(canonicalize(wt.path)))
164
+ .map((wt) => ({
165
+ path: wt.path,
166
+ branch: wt.branch,
167
+ head: wt.head,
168
+ suggestedSourceBranch: detectSourceBranch(projectPath, wt.path, wt.branch),
169
+ }));
170
+ }
@@ -59,6 +59,13 @@ export function spawnMcpProcess(command, args, env) {
59
59
  stdio: ['pipe', 'pipe', 'pipe'],
60
60
  env,
61
61
  });
62
+ // Defensive default 'error' listener: a ChildProcess that emits 'error'
63
+ // without any listener crashes the whole Node process (Unhandled 'error').
64
+ // Callers may attach their own listener for typed handling — listeners are
65
+ // additive on EventEmitter so this default never blocks them.
66
+ mcpProcess.on('error', (err) => {
67
+ console.error(`[mcp] spawn '${command}' failed: ${err.message}`);
68
+ });
62
69
  mcpProcess.stderr?.on('data', (data) => {
63
70
  if (process.env.DEBUG_MCP_STDERR) {
64
71
  console.error('[mcp stderr]', data.toString());
@@ -6,21 +6,59 @@
6
6
  * injected at workspace creation when autoLoop=true). Keeping these two
7
7
  * paths aligned was a copy-paste hazard — this file eliminates that.
8
8
  *
9
- * `AUTO_LOOP_GROOMING_STEPS` is the numbered workflow, ready to be spliced
10
- * into a larger prompt with a one-line intro.
9
+ * `buildAutoLoopGroomingSteps(e2e)` is the numbered workflow, ready to be
10
+ * spliced into a larger prompt with a one-line intro. When `e2e.framework`
11
+ * is set, an additional step 4 covers E2E regression coverage and the
12
+ * `kobo__mark_auto_loop_ready` call moves to step 5.
13
+ *
14
+ * `buildE2eIterationBlock(e2e)` returns the override block injected into
15
+ * the per-iteration prompt for tasks whose title starts with `[E2E]`.
11
16
  *
12
17
  * `AUTO_LOOP_HARD_RULES` is the trailing hard-rules block, same for both.
13
18
  */
14
- export const AUTO_LOOP_GROOMING_STEPS = `1. Call \`kobo__list_tasks\` FIRST to inspect any pre-existing tasks (they may have been seeded from Notion, a template, or the CreatePage form).
15
- 2. If tasks already exist: DO NOT delete or recreate them from scratch. Read each one, judge whether it is atomic and implementable in one session with clear completion criteria. Improve them in place:
19
+ export const PREP_AUTOLOOP_INTRO = `You are preparing this workspace for Kōbō auto-loop mode. This is a GROOMING session only — DO NOT implement anything, DO NOT write or edit code, DO NOT run tests or builds, DO NOT invoke \`superpowers:executing-plans\` or any implementation skill. Your ONLY job is to curate the Kōbō task list via MCP tools.`;
20
+ export function buildAutoLoopGroomingSteps(e2e) {
21
+ const steps = [
22
+ `1. Call \`kobo__list_tasks\` FIRST to inspect any pre-existing tasks (they may have been seeded from Notion, a template, or the CreatePage form).`,
23
+ `2. If tasks already exist: DO NOT delete or recreate them from scratch. Read each one, judge whether it is atomic and implementable in one session with clear completion criteria. Improve them in place:
16
24
  - Use \`kobo__update_task\` to rename unclear titles, add completion criteria, or flip \`is_acceptance_criterion\` when needed.
17
25
  - Use \`kobo__create_task\` to SPLIT a task that is too large into smaller atomic pieces (keep the original only if it still makes sense, otherwise update it to one of the split pieces and create the rest).
18
- - Use \`kobo__create_task\` to ADD missing acceptance criteria or missing implementation steps the plan requires.
19
- 3. If no tasks exist:
26
+ - Use \`kobo__create_task\` to ADD missing acceptance criteria or missing implementation steps the plan requires.`,
27
+ `3. If no tasks exist:
20
28
  - If a plan file exists in \`docs/superpowers/plans/\` or similar, read it and derive the task list from it.
21
29
  - If no plan exists, ask the user what the workspace goal is and propose tasks accordingly.
22
- - Create the tasks via \`kobo__create_task\`. For each task, decide \`is_acceptance_criterion\` appropriately.
23
- 4. Call \`kobo__mark_auto_loop_ready\`. This will automatically start the auto-loop, which will pick up the tasks one by one in fresh sessions.`;
30
+ - Create the tasks via \`kobo__create_task\`. For each task, decide \`is_acceptance_criterion\` appropriately.`,
31
+ ];
32
+ if (e2e.framework) {
33
+ const skillHint = e2e.skill ? `Use the \`${e2e.skill}\` skill for this task. ` : '';
34
+ const promptHint = e2e.prompt ? `Additional guidance: ${e2e.prompt}` : '';
35
+ steps.push(`4. **E2E review**: walk the task list and identify which tasks produce user-visible behavior (UI flows, form submissions, page renders, etc.). For each one that warrants regression coverage, INSERT a follow-up sub-task with title prefixed \`[E2E] \` describing the test to write. Place it in \`sort_order\` directly after the parent task. Skip tasks that don't produce user-visible behavior (refactors, infra, internal services) and briefly justify your choices in chat. The project uses \`${e2e.framework}\`. ${skillHint}${promptHint}`.trim());
36
+ steps.push(`5. Call \`kobo__mark_auto_loop_ready\`. This will automatically start the auto-loop, which will pick up the tasks one by one in fresh sessions.`);
37
+ }
38
+ else {
39
+ steps.push(`4. Call \`kobo__mark_auto_loop_ready\`. This will automatically start the auto-loop, which will pick up the tasks one by one in fresh sessions.`);
40
+ }
41
+ return steps.join('\n');
42
+ }
43
+ /** @deprecated Use buildAutoLoopGroomingSteps({ framework: '', skill: '', prompt: '' }) instead. */
44
+ export const AUTO_LOOP_GROOMING_STEPS = buildAutoLoopGroomingSteps({ framework: '', skill: '', prompt: '' });
45
+ export function buildE2eIterationBlock(e2e) {
46
+ if (!e2e.framework)
47
+ return '';
48
+ const skillLine = e2e.skill ? `Use the \`${e2e.skill}\` skill for this task.\n` : '';
49
+ const promptLine = e2e.prompt ? `Additional guidance: ${e2e.prompt}\n` : '';
50
+ return `
51
+ This is an **E2E regression test** task.
52
+
53
+ Project E2E framework: ${e2e.framework}
54
+ ${skillLine}${promptLine}
55
+ Hard rules specific to E2E tasks (these **override** the corresponding rules in the standard 8 steps below — read them before steps 3-4):
56
+ 1. Write the test source file in the project's existing E2E directory (look at \`cypress/\`, \`e2e/\`, \`tests/e2e/\`, or follow the skill / guidance above). Reuse existing fixtures and patterns.
57
+ 2. Try to run the tests locally. If they pass, great.
58
+ 3. **If the environment is broken** (Docker down, browser missing, port busy, dependencies not installed, etc.) — do NOT spend iterations debugging infra. **Override of step 4 of the standard prompt below**: you do NOT need to fix failing tests in this case. Commit the test source file with a message like \`test(e2e): add regression for <feature>\`, then call \`kobo__mark_task_done\` with a note in the chat: \`E2E test written but not executed locally — <reason>. Replay once env is restored.\`
59
+ 4. The code-review gate (step 6 of the standard prompt) still applies — the reviewer checks that the test is meaningful, not that it ran.
60
+ `;
61
+ }
24
62
  export const AUTO_LOOP_HARD_RULES = `Hard rules:
25
63
  - Do NOT touch any source file. No Edit, no Write, no Bash that changes the repo.
26
64
  - Do NOT run \`kill\`, \`pkill\`, \`killall\`, \`pgrep -k\`, or any process-killing command — you may tear down the Kōbō server itself or sibling dev servers.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loicngr/kobo",
3
- "version": "1.6.12",
3
+ "version": "1.6.13",
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{E as e,F as t,H as n,L as r,M as i,Q as a,U as o,_t as s,bt as c,d as l,f as u,g as d,h as f,l as p,p as m,r as h,rt as g,u as _,v,yt as y}from"./runtime-core.esm-bundler-C3IgBgY5.js";import{L as b,l as x,t as S}from"./QIcon-B0-pH3Qs.js";import{n as C,t as w}from"./settings-CAILUJXO.js";import{t as T}from"./QBtn-DHwAb18J.js";import{n as E}from"./vue-i18n-BJlZEYnA.js";import{S as D,b as O,g as k,v as A}from"./index-DAbX631s.js";import{t as j}from"./QSpinnerDots-DEiRooBD.js";import{t as M}from"./QExpansionItem-CWw6ZujM.js";import{t as ee}from"./QScrollArea-DpCqRRE0.js";import{t as N}from"./QTooltip-BIDjo2hJ.js";import{n as P,r as F,t as I}from"./documents-fVD9RJth.js";import{t as L}from"./_plugin-vue_export-helper-r4mAJOHR.js";function te(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:brainstorm-complete`: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 ne(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}function R(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:`user`;case`session`:return`session`;default:return`agent`}}function re(e){let t=[],n=null;for(let r of e){let e=R(r),i=e===`session`||e===`system-prompt`;!n||n.speaker!==e||i?(n={speaker:e,ts:r.ts,items:[r]},t.push(n),i&&(n=null)):n.items.push(r)}return t}var z={class:`text-caption text-grey-6`},B=v({__name:`SessionEventItem`,props:{item:{}},setup(e){let n=e,r=p(()=>{switch(n.item.kind){case`started`:return`session.started`;case`ended`:return`session.ended`;case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,n)=>(t(),m(`span`,z,c(e.$t(r.value)),1))}}),V={key:0,class:`message-choices q-mt-sm`},ie={class:`choice-key text-weight-medium`},H={class:`choice-label q-ml-xs ellipsis`},U=L(v({__name:`MessageChoices`,props:{choices:{},active:{type:Boolean}},setup(e){let n=e,i=k(),a=A();function s(e){if(!n.active)return;let t=a.selectedWorkspaceId;if(!t)return;let r=`${e.key}. ${e.label}`,o=a.selectedSessionId??void 0;i.sendChatMessage(t,r,o),a.addActivityItem(t,{id:`user-${Date.now()}`,type:`text`,content:r,timestamp:new Date().toISOString(),sessionId:o,meta:{sender:`user`,pending:!0}})}return(n,i)=>e.choices.length>0&&e.active?(t(),m(`div`,V,[(t(!0),m(h,null,r(e.choices,e=>(t(),l(T,{key:e.key,flat:``,dense:``,"no-caps":``,size:`sm`,color:`indigo-3`,class:`message-choice-btn q-mr-xs q-mb-xs`,onClick:t=>s(e)},{default:o(()=>[_(`span`,ie,c(e.key)+`.`,1),_(`span`,H,c(e.label),1)]),_:2},1032,[`onClick`]))),128))])):u(``,!0)}}),[[`__scopeId`,`data-v-4df976cb`]]),W=5,G=/^\s*(?:[-*]|\d+\.)\s+(?:\*\*([A-Za-z0-9])\.?\*\*|([A-Za-z])\.)\s+(.+?)\s*$/;function K(e){if(!e)return null;let t=e.split(`
1
+ import{E as e,F as t,H as n,L as r,M as i,Q as a,U as o,_t as s,bt as c,d as l,f as u,g as d,h as f,l as p,p as m,r as h,rt as g,u as _,v,yt as y}from"./runtime-core.esm-bundler-C3IgBgY5.js";import{L as b,l as x,t as S}from"./QIcon-B0-pH3Qs.js";import{n as C,t as w}from"./settings-CAILUJXO.js";import{t as T}from"./QBtn-DHwAb18J.js";import{n as E}from"./vue-i18n-BJlZEYnA.js";import{S as D,b as O,g as k,v as A}from"./index-odgA9x8A.js";import{t as j}from"./QSpinnerDots-DEiRooBD.js";import{t as M}from"./QExpansionItem-CWw6ZujM.js";import{t as ee}from"./QScrollArea-DpCqRRE0.js";import{t as N}from"./QTooltip-BIDjo2hJ.js";import{n as P,r as F,t as I}from"./documents-Ck8VwvpQ.js";import{t as L}from"./_plugin-vue_export-helper-r4mAJOHR.js";function te(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:brainstorm-complete`: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 ne(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}function R(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:`user`;case`session`:return`session`;default:return`agent`}}function re(e){let t=[],n=null;for(let r of e){let e=R(r),i=e===`session`||e===`system-prompt`;!n||n.speaker!==e||i?(n={speaker:e,ts:r.ts,items:[r]},t.push(n),i&&(n=null)):n.items.push(r)}return t}var z={class:`text-caption text-grey-6`},B=v({__name:`SessionEventItem`,props:{item:{}},setup(e){let n=e,r=p(()=>{switch(n.item.kind){case`started`:return`session.started`;case`ended`:return`session.ended`;case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,n)=>(t(),m(`span`,z,c(e.$t(r.value)),1))}}),V={key:0,class:`message-choices q-mt-sm`},ie={class:`choice-key text-weight-medium`},H={class:`choice-label q-ml-xs ellipsis`},U=L(v({__name:`MessageChoices`,props:{choices:{},active:{type:Boolean}},setup(e){let n=e,i=k(),a=A();function s(e){if(!n.active)return;let t=a.selectedWorkspaceId;if(!t)return;let r=`${e.key}. ${e.label}`,o=a.selectedSessionId??void 0;i.sendChatMessage(t,r,o),a.addActivityItem(t,{id:`user-${Date.now()}`,type:`text`,content:r,timestamp:new Date().toISOString(),sessionId:o,meta:{sender:`user`,pending:!0}})}return(n,i)=>e.choices.length>0&&e.active?(t(),m(`div`,V,[(t(!0),m(h,null,r(e.choices,e=>(t(),l(T,{key:e.key,flat:``,dense:``,"no-caps":``,size:`sm`,color:`indigo-3`,class:`message-choice-btn q-mr-xs q-mb-xs`,onClick:t=>s(e)},{default:o(()=>[_(`span`,ie,c(e.key)+`.`,1),_(`span`,H,c(e.label),1)]),_:2},1032,[`onClick`]))),128))])):u(``,!0)}}),[[`__scopeId`,`data-v-4df976cb`]]),W=5,G=/^\s*(?:[-*]|\d+\.)\s+(?:\*\*([A-Za-z0-9])\.?\*\*|([A-Za-z])\.)\s+(.+?)\s*$/;function K(e){if(!e)return null;let t=e.split(`
2
2
  `),n=0;for(;n<t.length;){let e=t[n].match(G);if(!e){n++;continue}let r=n,i=[{key:e[1]??e[2],label:e[3]}],a=n+1;for(;a<t.length;){let e=t[a];if(e.trim()===``){if(a+1<t.length&&t[a+1].trim()===``)break;a++;continue}let n=e.match(G);if(!n)break;i.push({key:n[1]??n[2],label:n[3]}),a++}if(i.length>=2){let e=Math.max(0,r-W);if(t.slice(e,r).join(` `).includes(`?`))return{choices:i}}n=a}return null}function q(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){ae(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 ae(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=oe(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 oe(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 J=[`innerHTML`],se=L(v({__name:`TextMessageItem`,props:{item:{},isLatestTurn:{type:Boolean}},setup(e){let n=e,r=I(),i=A(),a=p(()=>{let e=i.selectedWorkspaceId;return e?r.documentsFor(e).map(e=>e.path):[]}),o=p(()=>{let e=q(P.parse(n.item.text,{async:!1,breaks:!0,gfm:!0}),a.value);return F.sanitize(e,{ADD_ATTR:[`data-document-path`]})}),s=p(()=>K(n.item.text));function c(e){let t=e.target?.closest(`.document-link`);if(!t)return;e.preventDefault();let n=t.getAttribute(`data-document-path`),a=i.selectedWorkspaceId;!n||!a||r.openDocumentByPath(a,n)}return(n,r)=>(t(),m(`div`,{class:`markdown-message`,onClick:c},[_(`div`,{innerHTML:o.value},null,8,J),e.item.streaming?(t(),l(x,{key:0,size:`xs`,class:`q-ml-xs`})):u(``,!0),s.value?(t(),l(U,{key:1,choices:s.value.choices,active:!!e.isLatestTurn&&!e.item.streaming},null,8,[`choices`,`active`])):u(``,!0)]))}}),[[`__scopeId`,`data-v-fc35e8ee`]]),ce={key:0,class:`text-caption text-grey-5`,style:{"font-style":`italic`}},le=[`innerHTML`],Y={key:1,style:{"white-space":`pre-wrap`}},X=L(v({__name:`ThinkingItem`,props:{item:{}},setup(e){let n=e,r=p(()=>n.item.text.trim().slice(0,100)),i=p(()=>n.item.text.trim().length>0),a=p(()=>n.item.text.trim().length>100),s=p(()=>{let e=P.parse(n.item.text,{async:!1,breaks:!0,gfm:!0});return F.sanitize(e)});return(n,d)=>i.value?(t(),m(`div`,ce,[a.value?(t(),l(M,{key:0,dense:``,"dense-toggle":``,label:r.value,"header-class":`text-grey-5 text-caption`,style:{"font-style":`italic`}},{default:o(()=>[_(`div`,{class:`q-py-xs markdown-thinking`,innerHTML:s.value},null,8,le)]),_:1},8,[`label`])):(t(),m(`span`,Y,c(e.item.text),1))])):u(``,!0)}}),[[`__scopeId`,`data-v-e9fb9f90`]]);function ue(e,t){let n=e.split(`
3
3
  `),r=t.split(`
4
4
  `),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 de(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??``;return{toolName:`Edit`,filePath:e,oldString:t,newString:r,replaceAll:n.replace_all??!1,additions:r?r.split(`
@@ -0,0 +1,2 @@
1
+ import{E as e,F as t,H as n,L as r,M as ee,N as te,Q as i,T as ne,U as a,_t as re,bt as o,d as s,f as c,g as l,h as u,l as d,p as f,r as ie,rt as p,u as m,v as ae,vt as oe,x as se}from"./runtime-core.esm-bundler-C3IgBgY5.js";import{I as ce,L as le,M as ue,t as h}from"./QIcon-B0-pH3Qs.js";import{t as g}from"./QSeparator-DNSiXYrN.js";import{t as de}from"./settings-CAILUJXO.js";import{t as _}from"./QBtn-DHwAb18J.js";import{n as fe}from"./vue-i18n-BJlZEYnA.js";import{g as pe,i as v,m as me,v as he,w as ge}from"./index-odgA9x8A.js";import{n as y,t as b}from"./QItemSection-CiY_LK5Y.js";import{t as x}from"./QItemLabel-Codqjisk.js";import{t as _e}from"./QExpansionItem-CWw6ZujM.js";import{t as S}from"./QTooltip-BIDjo2hJ.js";import{t as ve}from"./_plugin-vue_export-helper-r4mAJOHR.js";import{t as ye}from"./QSpace-BNr0AftG.js";import{t as be}from"./use-quasar-Cc4smfg5.js";import{n as C,t as xe}from"./models-CJC61gWE.js";import{t as Se}from"./QPage-yqdKDG7-.js";import{i as Ce,n as we,r as Te,t as Ee}from"./expand-template-bkCTc78P.js";var De={class:`create-inner`},Oe={class:`create-title text-center text-weight-bold q-mb-lg text-grey-3`},ke={class:`create-card rounded-borders`},Ae={class:`card-top-bar row items-center q-px-md q-py-xs`},je={class:`model-badge cursor-default row items-center q-gutter-xs`},Me={class:`text-indigo-3 text-weight-medium text-caption`},Ne={key:0,class:`notion-url-wrap`},Pe={key:0,class:`notion-error text-caption q-px-md q-pb-xs text-red-5`},Fe={key:1,class:`notion-valid text-caption q-px-md q-pb-xs text-green-4`},Ie={key:2,class:`notion-peek-choice q-px-md q-pb-sm`},Le={class:`text-caption text-grey-4 q-mb-sm`},Re={class:`row q-gutter-sm`},ze={class:`peek-card-text`},Be={class:`peek-card-title`},Ve={class:`peek-card-desc`},He={class:`peek-card-text`},Ue={class:`peek-card-title`},We={class:`peek-card-desc`},Ge={key:0,class:`sentry-url-wrap`},Ke={key:0,class:`sentry-error text-caption q-px-md q-pb-xs text-red-5`},qe={key:1,class:`sentry-valid text-caption q-px-md q-pb-xs text-red-4`},Je={class:`card-name-wrap`},Ye={class:`card-textarea-wrap`},Xe={class:`manual-hint q-px-md q-py-sm text-caption text-grey-6`},Ze={class:`q-pa-sm manual-section-body`},Qe={class:`row items-center q-gutter-sm q-mb-sm`},$e={class:`col text-caption text-grey-4`},et={class:`q-pa-sm manual-section-body`},tt={class:`row items-center q-gutter-sm q-mb-sm`},nt={class:`col text-caption text-grey-4`},rt={class:`card-bottom-bar`},it={class:`row q-col-gutter-xs q-px-xs`},at={key:0,class:`col-12 col-sm-6 col-md-3`},ot={class:`bottom-select-label row items-center no-wrap`},st={class:`col-12 col-sm-6 col-md-3`},ct={class:`bottom-select-label row items-center no-wrap`},lt={class:`col-12 col-sm-6 col-md-3`},ut={class:`bottom-select-label row items-center no-wrap`},dt={class:`col-12 col-sm-6 col-md-3`},ft={class:`bottom-select-label row items-center no-wrap`},pt={class:`row q-col-gutter-xs q-pa-xs col-12 items-center justify-center`},mt={class:`col-12 col-md-auto`},ht={class:`col-12 col-md-auto`},gt={class:`col-12 col-md-auto`},_t={class:`row q-col-gutter-xs q-px-xs bottom-row-git`},vt={class:`col-12 col-md-4`},yt={key:0,class:`col-12 col-md-4`},bt={class:`bottom-select-label row items-center no-wrap`},xt={key:1,class:`col-12 col-md-4`},St={class:`bottom-select-label row items-center no-wrap`},Ct={class:`col-12 col-md-4`},wt={class:`bottom-select-label row items-center no-wrap`},Tt={class:`row justify-center q-px-sm q-py-sm`},Et={class:`create-hint text-center text-body2 q-mt-md text-grey-8`},Dt=ve(ae({__name:`CreatePage`,setup(ae){let ve=me(),Dt=be(),Ot=he(),w=de(),{t:T}=fe(),kt=i([]),E=i(``),D=i(``),At=i(null),O=i(``),k=i(!1),A=i(`claude-opus-4-7`),j=i(`auto`),M=i(``),N=i(null),jt=i(`feature`),P=i(!1),Mt=i([]),F=i(`claude-code`),Nt=d(()=>Mt.value.find(e=>e.id===F.value)),Pt=d(()=>Mt.value.map(e=>({value:e.id,label:e.displayName}))),Ft=d(()=>(Nt.value?.capabilities.permissionModes??[`auto-accept`,`plan`]).map(e=>({value:e,label:T(`engine.permission.${e}`)}))),It=[{label:`feature/`,value:`feature`},{label:`fix/`,value:`fix`},{label:`hotfix/`,value:`hotfix`},{label:`chore/`,value:`chore`},{label:`refactor/`,value:`refactor`},{label:`docs/`,value:`docs`},{label:`test/`,value:`test`}],I=i(w.global.defaultPermissionMode||`plan`),L=i([]),Lt=i([]),Rt=i(!1),zt=i(!1);function Bt(e,t){t(()=>{Lt.value=e?L.value.filter(t=>t.toLowerCase().includes(e.toLowerCase())):L.value})}let Vt=ge();function Ht(){return At.value?.nativeEl??null}let{showSkills:Ut,selectedSkillIndex:R,groupedDropdown:Wt,flatDropdown:z,fetchSkills:Gt,detectSlashFragment:Kt,replaceFragmentWith:qt,closeDropdown:Jt}=Te(D,Ht,{excludeKoboCommands:!0});Gt(),n(D,async()=>{await e(),await Kt()});function Yt(e){if(e.type===`template`){let t=Vt.templates.find(t=>t.slug===e.name);if(!t)return;qt(we(t.content,Ee({workspace:null,gitStats:null,sessionName:null}))),Jt();return}qt(`/${e.name} `),Jt()}function Xt(e){!Ut.value||z.value.length===0||(e.key===`ArrowDown`?(e.preventDefault(),R.value=(R.value+1)%z.value.length):e.key===`ArrowUp`?(e.preventDefault(),R.value=(R.value-1+z.value.length)%z.value.length):e.key===`Enter`&&!e.shiftKey&&!e.ctrlKey&&!e.metaKey?(e.preventDefault(),Yt(z.value[R.value])):e.key===`Escape`&&(e.preventDefault(),Jt()))}let Zt=d(()=>xe.map(e=>({label:T(e.i18nLabelKey),value:e.value,description:T(e.i18nDescriptionKey)})));function B(e){let t=e.indexOf(`:`);return t>=0?e.slice(t+1).trim():e}let Qt=d(()=>[{label:B(T(`reasoning.auto`)),value:`auto`,description:T(`reasoning.autoDescription`)},{label:B(T(`reasoning.low`)),value:`low`,description:T(`reasoning.lowDescription`)},{label:B(T(`reasoning.medium`)),value:`medium`,description:T(`reasoning.mediumDescription`)},{label:B(T(`reasoning.high`)),value:`high`,description:T(`reasoning.highDescription`)},{label:B(T(`reasoning.xhigh`)),value:`xhigh`,description:T(`reasoning.xhighDescription`)},{label:B(T(`reasoning.max`)),value:`max`,description:T(`reasoning.maxDescription`)}]),V=d(()=>O.value.trim().startsWith(`https://www.notion.so/`)),$t=d(()=>/[?&]p=[0-9a-f]{32}(?:[&#]|$)/i.test(O.value)),H=i(`panel`);function en(){let e=O.value.trim();return H.value===`parent`&&$t.value?e.replace(/([?&])p=[0-9a-f]{32}(?=[&#]|$)/i,`$1`).replace(/([?&])pm=[a-z]+(?=[&#]|$)/i,`$1`).replace(/[?&]+$/,``).replace(/\?&/,`?`):e}let U=i([]),W=i([]),G=i(``),K=i(``),tn=d(()=>!k.value||!V.value);function nn(){let e=G.value.trim();e&&(U.value.push(e),G.value=``)}function rn(e){U.value.splice(e,1)}function an(){let e=K.value.trim();e&&(W.value.push(e),K.value=``)}function on(e){W.value.splice(e,1)}function sn(){k.value=!k.value,k.value||(O.value=``)}let q=i(!1),J=i(!1),Y=i(``),cn=d(()=>/\/issues\/\d+/.test(Y.value.trim()));function ln(){q.value=!q.value,q.value||(Y.value=``)}let X=i(!1),Z=i(null),Q=i([]),un=i(!1);async function dn(){if(!M.value.trim()){Q.value=[];return}un.value=!0;try{Q.value=await Ot.fetchOrphanWorktrees(M.value.trim())}catch{Q.value=[]}finally{un.value=!1}}function fn(){X.value=!X.value,X.value?(k.value=!1,O.value=``,q.value=!1,Y.value=``,P.value=!0,dn()):Z.value=null}n(M,()=>{Z.value=null,X.value&&dn()}),n(Z,e=>{if(!e)return;let t=Q.value.find(t=>t.path===e);t&&(N.value=t.suggestedSourceBranch),P.value=!0});async function pn(e){if(!e.trim()){L.value=[],N.value=null;return}Rt.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();L.value=n.local??n.branches??[],L.value.length>0&&!N.value&&(N.value=L.value[0]??null)}catch{L.value=[],N.value=null}finally{Rt.value=!1}}function mn(e){let t=w.getProjectByPath(e);t&&(t.defaultSourceBranch&&(N.value=t.defaultSourceBranch),t.defaultModel?A.value=t.defaultModel:w.global.defaultModel&&(A.value=w.global.defaultModel))}let $=null;n(M,e=>{$&&clearTimeout($),$=setTimeout(()=>{N.value=null,pn(e),mn(e)},500)});function hn(e,t){t(()=>{kt.value=w.projectPaths.filter(t=>t.toLowerCase().includes(e.toLowerCase()))})}ee(async()=>{w.fetchSettings();try{let e=await fetch(`/api/engines`);e.ok&&(Mt.value=await e.json())}catch{}}),te(()=>{$&&clearTimeout($)});function gn(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 _n(){return E.value.trim()?E.value.trim().substring(0,80):!k.value&&!q.value&&D.value.trim()&&(D.value.trim().split(`
2
+ `)[0]??``).substring(0,80)||`workspace`}function vn(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 yn(){return k.value&&!V.value?T(`createPage.validationNotionUrl`):q.value&&!cn.value?T(`createPage.sentryValidation`):!k.value&&!q.value&&!D.value.trim()?T(`createPage.validationDescription`):!k.value&&!q.value&&(!_n()||_n()===`workspace`)&&!E.value.trim()&&!D.value.trim()?T(`createPage.validationName`):M.value.trim()?N.value?null:T(`createPage.validationBranch`):T(`createPage.validationPath`)}async function bn(){let e=yn();if(e){Dt.notify({type:`negative`,message:e,position:`top`});return}if(X.value&&!Z.value){Dt.notify({type:`negative`,message:T(`createPage.pickWorktreeRequired`),position:`top`});return}zt.value=!0;try{let e=_n(),t;t=k.value&&V.value?vn(en()):e===`workspace`?`task-${Date.now()}`:gn(e);let n=`${jt.value}/${t}`,r={name:e,projectPath:M.value.trim(),sourceBranch:N.value,...X.value&&Z.value?{worktreePath:Z.value,skipSetupScript:!0}:{workingBranch:n},engine:F.value,model:A.value,reasoningEffort:j.value,...k.value&&V.value?{notionUrl:en()}:{},...q.value&&cn.value?{sentryUrl:Y.value.trim()}:{},...tn.value&&U.value.length>0?{tasks:U.value}:{},...tn.value&&W.value.length>0?{acceptanceCriteria:W.value}:{},...P.value&&!X.value?{skipSetupScript:!0}:{},...D.value.trim()?{description:D.value.trim()}:{},...J.value?{autoLoop:!0}:{},permissionMode:J.value?`auto-accept`:I.value},ee=await Ot.createWorkspace(r);pe().subscribe(ee.id),Ot.selectWorkspace(ee.id),ve.push({name:`workspace`,params:{id:ee.id}})}catch{Dt.notify({type:`negative`,message:T(`createPage.errorCreating`),position:`top`})}finally{zt.value=!1}}return(e,n)=>(t(),s(Se,{class:`create-page flex flex-center column`},{default:a(()=>[m(`div`,De,[m(`div`,Oe,o(e.$t(`createPage.title`)),1),m(`div`,ke,[m(`div`,Ae,[m(`span`,je,[l(h,{name:`auto_awesome`,size:`14px`,color:`indigo-4`}),m(`span`,Me,o(Nt.value?.displayName??e.$t(`createPage.claudeCode`)),1)]),l(ye),l(_,{flat:``,dense:``,"no-caps":``,size:`sm`,color:k.value?`green-4`:`grey-5`,class:`notion-toggle-btn text-caption rounded-borders`,disable:X.value,onClick:sn},{default:a(()=>[l(h,{name:`description`,size:`14px`,class:`q-mr-xs`}),u(` `+o(k.value?e.$t(`createPage.notionEnabled`):e.$t(`createPage.importNotion`)),1)]),_:1},8,[`color`,`disable`]),l(_,{flat:``,dense:``,"no-caps":``,size:`sm`,color:q.value?`red-4`:`grey-5`,class:`sentry-toggle-btn text-caption rounded-borders q-ml-sm`,disable:X.value,onClick:ln},{default:a(()=>[l(h,{name:`bug_report`,size:`14px`,class:`q-mr-xs`}),u(` `+o(q.value?e.$t(`createPage.sentryEnabled`):e.$t(`createPage.importSentry`)),1)]),_:1},8,[`color`,`disable`])]),l(g,{color:`grey-9`}),l(ue,{name:`slide`},{default:a(()=>[k.value?(t(),f(`div`,Ne,[l(v,{modelValue:O.value,"onUpdate:modelValue":n[0]||=e=>O.value=e,borderless:``,dense:``,placeholder:e.$t(`createPage.notionPlaceholder`),class:`notion-url-input`,"input-class":`notion-url-input-inner`},{prepend:a(()=>[l(h,{name:`link`,size:`16px`,color:V.value?`green-4`:`grey-6`},null,8,[`color`])]),_:1},8,[`modelValue`,`placeholder`]),O.value.trim()&&!V.value?(t(),f(`div`,Pe,o(e.$t(`createPage.notionValidation`)),1)):c(``,!0),V.value?(t(),f(`div`,Fe,o(e.$t(`createPage.notionAutoExtract`)),1)):c(``,!0),V.value&&$t.value?(t(),f(`div`,Ie,[m(`div`,Le,[l(h,{name:`info`,size:`14px`,color:`indigo-4`,class:`q-mr-xs`}),u(` `+o(e.$t(`createPage.notionPanelChoiceLabel`)),1)]),m(`div`,Re,[m(`button`,{type:`button`,class:re([`peek-card col`,{"peek-card--active":H.value===`panel`}]),onClick:n[1]||=e=>H.value=`panel`},[l(h,{name:`article`,size:`22px`,class:`peek-card-icon`}),m(`div`,ze,[m(`div`,Be,o(e.$t(`createPage.notionPanelOption`)),1),m(`div`,Ve,o(e.$t(`createPage.notionPanelOptionDesc`)),1)]),H.value===`panel`?(t(),s(h,{key:0,name:`check_circle`,size:`18px`,color:`indigo-4`,class:`peek-card-check`})):c(``,!0)],2),m(`button`,{type:`button`,class:re([`peek-card col`,{"peek-card--active":H.value===`parent`}]),onClick:n[2]||=e=>H.value=`parent`},[l(h,{name:`folder_open`,size:`22px`,class:`peek-card-icon`}),m(`div`,He,[m(`div`,Ue,o(e.$t(`createPage.notionParentOption`)),1),m(`div`,We,o(e.$t(`createPage.notionParentOptionDesc`)),1)]),H.value===`parent`?(t(),s(h,{key:0,name:`check_circle`,size:`18px`,color:`indigo-4`,class:`peek-card-check`})):c(``,!0)],2)])])):c(``,!0)])):c(``,!0)]),_:1}),k.value?(t(),s(g,{key:0,color:`grey-9`})):c(``,!0),l(ue,{name:`slide`},{default:a(()=>[q.value?(t(),f(`div`,Ge,[l(v,{modelValue:Y.value,"onUpdate:modelValue":n[3]||=e=>Y.value=e,borderless:``,dense:``,placeholder:e.$t(`createPage.sentryPlaceholder`),class:`sentry-url-input`,"input-class":`sentry-url-input-inner`},{prepend:a(()=>[l(h,{name:`link`,size:`16px`,color:cn.value?`red-4`:`grey-6`},null,8,[`color`])]),_:1},8,[`modelValue`,`placeholder`]),Y.value.trim()&&!cn.value?(t(),f(`div`,Ke,o(e.$t(`createPage.sentryValidation`)),1)):c(``,!0),cn.value?(t(),f(`div`,qe,o(e.$t(`createPage.sentryAutoExtract`)),1)):c(``,!0)])):c(``,!0)]),_:1}),q.value?(t(),s(g,{key:1,color:`grey-9`})):c(``,!0),m(`div`,Je,[l(v,{modelValue:E.value,"onUpdate:modelValue":n[4]||=e=>E.value=e,borderless:``,dense:``,placeholder:k.value&&V.value?e.$t(`createPage.workspaceName`):e.$t(`createPage.workspaceNamePlaceholder`),class:`name-input`,"input-class":`name-input-inner`},null,8,[`modelValue`,`placeholder`])]),l(g,{color:`grey-9`}),m(`div`,Ye,[l(v,{ref_key:`descriptionRef`,ref:At,modelValue:D.value,"onUpdate:modelValue":n[5]||=e=>D.value=e,type:`textarea`,borderless:``,autogrow:``,rows:3,placeholder:k.value?e.$t(`createPage.instructions`):e.$t(`createPage.instructionsPlaceholder`),class:`create-textarea`,"input-class":`create-textarea-input`,onKeydown:[Xt,ce(le(bn,[`ctrl`]),[`enter`]),ce(le(bn,[`meta`]),[`enter`])]},null,8,[`modelValue`,`placeholder`,`onKeydown`]),p(Ut)&&p(z).length>0?(t(),s(Ce,{key:0,class:`create-slash-popup`,"grouped-dropdown":p(Wt),"flat-dropdown":p(z),"selected-index":p(R),onSelect:Yt},null,8,[`grouped-dropdown`,`flat-dropdown`,`selected-index`])):c(``,!0)]),l(g,{color:`grey-9`}),tn.value?(t(),f(ie,{key:2},[m(`div`,Xe,o(e.$t(`createPage.manualHint`)),1),l(_e,{dark:``,dense:``,label:e.$t(`createPage.tasks`,{count:U.value.length}),"header-class":`text-grey-4 manual-expansion-header`,class:`manual-expansion q-mx-sm`},{default:a(()=>[m(`div`,Ze,[m(`div`,Qe,[l(v,{modelValue:G.value,"onUpdate:modelValue":n[6]||=e=>G.value=e,dark:``,dense:``,borderless:``,placeholder:e.$t(`createPage.addTask`),class:`col manual-input`,"input-class":`manual-input-inner`,onKeydown:ce(le(nn,[`prevent`]),[`enter`])},null,8,[`modelValue`,`placeholder`,`onKeydown`]),l(_,{flat:``,dense:``,round:``,icon:`add`,color:`indigo-4`,disable:!G.value.trim(),onClick:nn},{default:a(()=>[l(S,null,{default:a(()=>[u(o(e.$t(`tooltip.addTask`)),1)]),_:1})]),_:1},8,[`disable`])]),(t(!0),f(ie,null,r(U.value,(n,r)=>(t(),f(`div`,{key:`task-${r}`,class:`row items-center q-py-xs manual-item`},[m(`span`,$e,o(n),1),l(_,{flat:``,dense:``,round:``,icon:`close`,size:`xs`,color:`grey-6`,onClick:e=>rn(r)},{default:a(()=>[l(S,null,{default:a(()=>[u(o(e.$t(`tooltip.removeTask`)),1)]),_:1})]),_:1},8,[`onClick`])]))),128))])]),_:1},8,[`label`]),l(_e,{dark:``,dense:``,label:e.$t(`createPage.acceptanceCriteria`,{count:W.value.length}),"header-class":`text-grey-4 manual-expansion-header`,class:`manual-expansion q-mx-sm q-mb-sm`},{default:a(()=>[m(`div`,et,[m(`div`,tt,[l(v,{modelValue:K.value,"onUpdate:modelValue":n[7]||=e=>K.value=e,dark:``,dense:``,borderless:``,placeholder:e.$t(`createPage.addCriterion`),class:`col manual-input`,"input-class":`manual-input-inner`,onKeydown:ce(le(an,[`prevent`]),[`enter`])},null,8,[`modelValue`,`placeholder`,`onKeydown`]),l(_,{flat:``,dense:``,round:``,icon:`add`,color:`indigo-4`,disable:!K.value.trim(),onClick:an},{default:a(()=>[l(S,null,{default:a(()=>[u(o(e.$t(`tooltip.addCriterion`)),1)]),_:1})]),_:1},8,[`disable`])]),(t(!0),f(ie,null,r(W.value,(n,r)=>(t(),f(`div`,{key:`crit-${r}`,class:`row items-center q-py-xs manual-item`},[m(`span`,nt,o(n),1),l(_,{flat:``,dense:``,round:``,icon:`close`,size:`xs`,color:`grey-6`,onClick:e=>on(r)},{default:a(()=>[l(S,null,{default:a(()=>[u(o(e.$t(`tooltip.removeCriterion`)),1)]),_:1})]),_:1},8,[`onClick`])]))),128))])]),_:1},8,[`label`]),l(g,{color:`grey-9`})],64)):c(``,!0),m(`div`,rt,[m(`div`,it,[Pt.value.length>0?(t(),f(`div`,at,[l(C,{modelValue:F.value,"onUpdate:modelValue":n[8]||=e=>F.value=e,options:Pt.value,dense:``,borderless:``,class:`bottom-select rounded-borders`,"hide-dropdown-icon":``,"emit-value":``,"map-options":``,"option-value":`value`,"option-label":`label`},{selected:a(()=>[m(`span`,ot,[l(h,{name:`hub`,size:`12px`,color:`grey-5`,class:`q-mr-xs`}),u(` `+o(Pt.value.find(e=>e.value===F.value)?.label??F.value)+` `,1),l(h,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),default:a(()=>[l(S,null,{default:a(()=>[u(o(e.$t(`engine.select`)),1)]),_:1})]),_:1},8,[`modelValue`,`options`])])):c(``,!0),m(`div`,st,[l(C,{modelValue:A.value,"onUpdate:modelValue":n[9]||=e=>A.value=e,options:Zt.value,dense:``,borderless:``,class:`bottom-select rounded-borders model-select`,"hide-dropdown-icon":``,"emit-value":``,"map-options":``,"option-value":`value`,"option-label":`label`},{selected:a(()=>[m(`span`,ct,[u(o(Zt.value.find(e=>e.value===A.value)?.label??A.value)+` `,1),l(h,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),option:a(({opt:e,itemProps:t})=>[l(y,ne(t,{class:`model-option`}),{default:a(()=>[l(b,null,{default:a(()=>[l(x,{class:`text-white`},{default:a(()=>[u(o(e.label),1)]),_:2},1024),l(x,{caption:``,class:`text-grey-5`},{default:a(()=>[u(o(e.description),1)]),_:2},1024)]),_:2},1024)]),_:2},1040)]),_:1},8,[`modelValue`,`options`])]),m(`div`,lt,[l(C,{modelValue:j.value,"onUpdate:modelValue":n[10]||=e=>j.value=e,options:Qt.value,dense:``,borderless:``,class:`bottom-select rounded-borders`,"hide-dropdown-icon":``,"emit-value":``,"map-options":``,"option-value":`value`,"option-label":`label`},{selected:a(()=>[m(`span`,ut,[l(h,{name:`psychology`,size:`12px`,color:`grey-5`,class:`q-mr-xs`}),u(` `+o(Qt.value.find(e=>e.value===j.value)?.label??j.value)+` `,1),l(h,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),option:a(({opt:e,itemProps:t})=>[l(y,oe(se(t)),{default:a(()=>[l(b,null,{default:a(()=>[l(x,{class:`text-white`},{default:a(()=>[u(o(e.label),1)]),_:2},1024),l(x,{caption:``,class:`text-grey-5`},{default:a(()=>[u(o(e.description),1)]),_:2},1024)]),_:2},1024)]),_:2},1040)]),_:1},8,[`modelValue`,`options`])]),m(`div`,dt,[l(C,{modelValue:I.value,"onUpdate:modelValue":n[11]||=e=>I.value=e,options:Ft.value,disable:J.value,dense:``,borderless:``,class:`bottom-select rounded-borders`,"hide-dropdown-icon":``,"emit-value":``,"map-options":``,"option-value":`value`,"option-label":`label`},{selected:a(()=>[m(`span`,ft,[l(h,{name:J.value?`flash_on`:I.value===`plan`?`visibility`:`flash_on`,size:`12px`,color:`amber-6`,class:`q-mr-xs`},null,8,[`name`]),u(` `+o(J.value?Ft.value.find(e=>e.value===`auto-accept`)?.label??`auto-accept`:Ft.value.find(e=>e.value===I.value)?.label??I.value)+` `,1),J.value?c(``,!0):(t(),s(h,{key:0,name:`expand_more`,size:`12px`,color:`grey-5`}))])]),default:a(()=>[l(S,null,{default:a(()=>[u(o(J.value?e.$t(`createPage.permissionLockedByAutoLoop`):e.$t(`engine.permission`)),1)]),_:1})]),_:1},8,[`modelValue`,`options`,`disable`])])]),m(`div`,pt,[m(`div`,mt,[l(_,{flat:``,dense:``,size:`sm`,"no-caps":``,icon:J.value?`autorenew`:`sync_disabled`,color:J.value?`amber-4`:`grey-5`,label:e.$t(`autoLoop.startInMode`),class:`skip-setup-btn`,onClick:n[12]||=e=>J.value=!J.value},{default:a(()=>[l(S,null,{default:a(()=>[u(o(e.$t(`autoLoop.startInMode`)),1)]),_:1})]),_:1},8,[`icon`,`color`,`label`])]),m(`div`,ht,[l(_,{flat:``,dense:``,size:`sm`,"no-caps":``,icon:P.value?`play_disabled`:`play_circle`,color:P.value?`orange-4`:`grey-5`,label:e.$t(`createPage.skipSetupScript`),class:`skip-setup-btn`,onClick:n[13]||=e=>P.value=!P.value},{default:a(()=>[l(S,null,{default:a(()=>[u(o(e.$t(`createPage.skipSetupScript`)),1)]),_:1})]),_:1},8,[`icon`,`color`,`label`])]),m(`div`,gt,[l(_,{flat:``,dense:``,size:`sm`,"no-caps":``,icon:`folder_open`,color:X.value?`cyan-4`:`grey-5`,label:X.value?e.$t(`createPage.attachWorktreeEnabled`):e.$t(`createPage.attachWorktreeToggle`),class:`skip-setup-btn`,onClick:fn},null,8,[`color`,`label`])])]),m(`div`,_t,[m(`div`,vt,[l(C,{modelValue:M.value,"onUpdate:modelValue":n[14]||=e=>M.value=e,options:kt.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":M.value?``:`repo-input-empty`,placeholder:e.$t(`createPage.projectPath`),behavior:p(w).projectPaths.length>0?`menu`:`dialog`,onFilter:hn,onInputValue:n[15]||=e=>{M.value=e}},{prepend:a(()=>[l(h,{name:`folder`,size:`14px`,color:`grey-5`})]),"no-option":a(()=>[l(y,null,{default:a(()=>[l(b,{class:`text-grey-6 text-caption`},{default:a(()=>[u(o(e.$t(`createPage.enterPath`)),1)]),_:1})]),_:1})]),_:1},8,[`modelValue`,`options`,`input-class`,`placeholder`,`behavior`])]),X.value?c(``,!0):(t(),f(`div`,yt,[l(C,{modelValue:jt.value,"onUpdate:modelValue":n[16]||=e=>jt.value=e,options:It,"emit-value":``,"map-options":``,dense:``,borderless:``,class:`bottom-select rounded-borders branch-type-select`,"hide-dropdown-icon":``},{selected:a(()=>[m(`span`,bt,[l(h,{name:`account_tree`,size:`12px`,color:`grey-5`,class:`q-mr-xs`}),u(` `+o(jt.value)+`/ `,1),l(h,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),default:a(()=>[l(S,null,{default:a(()=>[u(o(e.$t(`createPage.branchType`)),1)]),_:1})]),_:1},8,[`modelValue`])])),X.value?(t(),f(`div`,xt,[l(C,{modelValue:Z.value,"onUpdate:modelValue":n[17]||=e=>Z.value=e,options:Q.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:un.value,disable:!M.value.trim()||un.value},{selected:a(()=>[m(`span`,St,[l(h,{name:`folder_open`,size:`12px`,color:`cyan-5`,class:`q-mr-xs`}),u(` `+o(Z.value?Q.value.find(e=>e.path===Z.value)?.branch??Z.value:e.$t(`createPage.worktreePickerLabel`))+` `,1),l(h,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),option:a(e=>[l(y,oe(se(e.itemProps)),{default:a(()=>[l(b,null,{default:a(()=>[l(x,null,{default:a(()=>[u(o(e.opt.branch),1)]),_:2},1024),l(x,{caption:``},{default:a(()=>[u(o(e.opt.path),1)]),_:2},1024)]),_:2},1024)]),_:2},1040)]),"no-option":a(()=>[l(y,null,{default:a(()=>[l(b,{class:`text-grey-6 text-caption`},{default:a(()=>[u(o(M.value.trim()?e.$t(`createPage.noOrphanWorktrees`):e.$t(`createPage.enterPath`)),1)]),_:1})]),_:1})]),_:1},8,[`modelValue`,`options`,`loading`,`disable`])])):c(``,!0),m(`div`,Ct,[l(C,{modelValue:N.value,"onUpdate:modelValue":n[18]||=e=>N.value=e,options:Lt.value,dense:``,borderless:``,class:`bottom-select rounded-borders branch-select`,"hide-dropdown-icon":``,"use-input":``,"input-debounce":`0`,loading:Rt.value,disable:!M.value.trim()||Rt.value,onFilter:Bt},{selected:a(()=>[m(`span`,wt,[l(h,{name:`call_split`,size:`12px`,color:`grey-5`,class:`q-mr-xs`}),u(` `+o(N.value??e.$t(`createPage.branch`))+` `,1),l(h,{name:`expand_more`,size:`12px`,color:`grey-5`})])]),"no-option":a(()=>[l(y,null,{default:a(()=>[l(b,{class:`text-grey-6 text-caption`},{default:a(()=>[u(o(M.value.trim()?e.$t(`createPage.noBranches`):e.$t(`createPage.enterPath`)),1)]),_:1})]),_:1})]),_:1},8,[`modelValue`,`options`,`loading`,`disable`])])])]),m(`div`,Tt,[l(_,{label:e.$t(`createPage.create`),"no-caps":``,unelevated:``,class:`create-btn text-weight-bold rounded-borders`,loading:zt.value,disable:zt.value||X.value&&!Z.value,onClick:bn},null,8,[`label`,`loading`,`disable`])])]),m(`div`,Et,o(k.value?e.$t(`createPage.notionExtractHint`):e.$t(`createPage.notionImportHint`)),1)])]),_:1}))}}),[[`__scopeId`,`data-v-99035e1e`]]);export{Dt as default};
@@ -0,0 +1 @@
1
+ .create-page[data-v-99035e1e]{background-color:#1a1a2e;min-height:100%;padding:48px 24px}.create-inner[data-v-99035e1e]{width:100%;max-width:700px}.create-title[data-v-99035e1e]{font-size:24px;line-height:1.3}.create-card[data-v-99035e1e]{background:#224;border:1px solid #444;overflow:hidden}.card-top-bar[data-v-99035e1e]{background:#1e1e3a;min-height:36px}.card-name-wrap[data-v-99035e1e]{background:#224;padding:8px 16px 4px}.card-name-wrap[data-v-99035e1e] .q-field__control{height:32px;min-height:32px;padding:0}.card-name-wrap[data-v-99035e1e] input{color:#e0e0e0;font-size:15px;font-weight:500}.card-name-wrap[data-v-99035e1e] input::placeholder{color:#555}.card-textarea-wrap[data-v-99035e1e]{background:#224;position:relative}.create-slash-popup[data-v-99035e1e]{z-index:9999;position:absolute;top:calc(100% + 4px);left:12px;right:12px}.repo-select[data-v-99035e1e]{min-width:160px;max-width:260px}.repo-select[data-v-99035e1e] .q-field__prepend{align-items:center;height:auto;padding-top:0}.create-textarea[data-v-99035e1e]{color:#d0d0d0;width:100%;padding:12px 16px 4px}.create-textarea[data-v-99035e1e] .q-field__control{padding:0}.create-textarea[data-v-99035e1e] textarea{color:#d0d0d0;resize:none;min-height:100px;font-size:14px;line-height:1.6}.create-textarea[data-v-99035e1e] textarea::placeholder{color:#666}.notion-toggle-btn[data-v-99035e1e]{background:#333;padding:2px 10px}.notion-url-wrap[data-v-99035e1e]{background:#1e1e3a;padding:8px 0 0}.notion-url-input[data-v-99035e1e]{padding:0 12px}.notion-url-input[data-v-99035e1e] .q-field__control{height:36px;min-height:36px;padding:0}.notion-url-input[data-v-99035e1e] input{color:#d0d0d0;font-size:13px}.notion-url-input[data-v-99035e1e] input::placeholder{color:#555;font-size:12px}.notion-error[data-v-99035e1e],.notion-valid[data-v-99035e1e]{padding-bottom:6px}.notion-peek-choice[data-v-99035e1e]{padding-top:4px}.peek-card[data-v-99035e1e]{cursor:pointer;text-align:left;color:#e0e0e0;font-family:inherit;font-size:inherit;background:#ffffff08;border:1px solid #ffffff14;border-radius:8px;align-items:center;gap:10px;padding:10px 12px;transition:background .15s,border-color .15s,transform .1s;display:flex;position:relative}.peek-card[data-v-99035e1e]:hover{background:#ffffff0f;border-color:#6c63ff66}.peek-card[data-v-99035e1e]:active{transform:scale(.99)}.peek-card--active[data-v-99035e1e]{background:#6c63ff1f;border-color:#6c63ffd9;box-shadow:0 0 0 1px #6c63ff66}.peek-card--active .peek-card-icon[data-v-99035e1e]{color:#8a82ff}.peek-card--active .peek-card-title[data-v-99035e1e]{color:#fff}.peek-card-icon[data-v-99035e1e]{color:#999;flex-shrink:0}.peek-card-text[data-v-99035e1e]{flex:1;min-width:0;line-height:1.25}.peek-card-title[data-v-99035e1e]{color:#d0d0d0;font-size:12px;font-weight:600}.peek-card-desc[data-v-99035e1e]{color:#888;margin-top:2px;font-size:10.5px}.peek-card-check[data-v-99035e1e]{flex-shrink:0}.sentry-toggle-btn[data-v-99035e1e]{background:#333;padding:2px 10px}.sentry-url-wrap[data-v-99035e1e]{background:#1e1e3a;padding:8px 0 0}.sentry-url-input[data-v-99035e1e]{padding:0 12px}.sentry-url-input[data-v-99035e1e] .q-field__control{height:36px;min-height:36px;padding:0}.sentry-url-input[data-v-99035e1e] input{color:#d0d0d0;font-size:13px}.sentry-url-input[data-v-99035e1e] input::placeholder{color:#555;font-size:12px}.sentry-error[data-v-99035e1e],.sentry-valid[data-v-99035e1e]{padding-bottom:6px}.slide-enter-active[data-v-99035e1e],.slide-leave-active[data-v-99035e1e]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-99035e1e],.slide-leave-to[data-v-99035e1e]{opacity:0;max-height:0}.slide-enter-to[data-v-99035e1e],.slide-leave-from[data-v-99035e1e]{opacity:1;max-height:120px}.card-bottom-bar[data-v-99035e1e]{background:#1e1e3a}.skip-setup-btn[data-v-99035e1e]{min-height:28px;padding:2px 10px;font-size:11px}.skip-setup-btn[data-v-99035e1e] .q-btn__content{gap:4px}.skip-setup-btn[data-v-99035e1e] .q-icon{font-size:14px}.bottom-row-git .bottom-select-label[data-v-99035e1e]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bottom-row-git .bottom-select.repo-select[data-v-99035e1e] input{color:#bbb;padding:0 4px;font-size:11px}.bottom-row-git .bottom-select.repo-select[data-v-99035e1e] input::placeholder{color:#666;font-style:italic}.bottom-select[data-v-99035e1e]{background:#333;height:28px;padding:0 6px}.bottom-select[data-v-99035e1e] .q-field__control{height:28px;min-height:28px;padding:0}.bottom-select[data-v-99035e1e] .q-field__native{min-height:unset;padding:0}.bottom-select-label[data-v-99035e1e]{color:#bbb;gap:2px;font-size:11px}.bottom-sep[data-v-99035e1e]{color:#555;padding:0 2px;font-size:12px;line-height:1}.repo-path-wrap[data-v-99035e1e]{background:#333;border-radius:6px;height:28px;padding:0 8px}.repo-input[data-v-99035e1e]{min-width:140px}.repo-input[data-v-99035e1e] .q-field__control{height:28px;min-height:28px;padding:0}.repo-input[data-v-99035e1e] input{color:#bbb;font-size:11px}.repo-input[data-v-99035e1e] input::placeholder{color:#666;font-size:11px}.branch-select[data-v-99035e1e]{min-width:80px}.create-btn[data-v-99035e1e]{color:#fff;background:#4f46e5;min-width:220px;height:32px;padding:0 32px;font-size:13px}.create-btn[data-v-99035e1e] .q-btn__content{height:32px}.create-hint[data-v-99035e1e]{line-height:1.5}.fade-enter-active[data-v-99035e1e],.fade-leave-active[data-v-99035e1e]{transition:opacity .2s}.fade-enter-from[data-v-99035e1e],.fade-leave-to[data-v-99035e1e]{opacity:0}.manual-hint[data-v-99035e1e]{background:#1e1e3a;line-height:1.4}.manual-expansion[data-v-99035e1e]{background:#1e1e3a;border:1px solid #333;border-radius:4px;margin-top:6px;overflow:hidden}.manual-expansion[data-v-99035e1e] .manual-expansion-header{min-height:32px;padding:4px 10px;font-size:12px}.manual-expansion[data-v-99035e1e] .q-expansion-item__content,.manual-section-body[data-v-99035e1e]{background:#1a1a2e}.manual-input[data-v-99035e1e] .q-field__control{height:26px;min-height:26px;padding:0}.manual-input[data-v-99035e1e] input{color:#e0e0e0;font-size:12px}.manual-input[data-v-99035e1e] input::placeholder{color:#555}.manual-item[data-v-99035e1e]{border-top:1px solid #ffffff0a}.manual-item[data-v-99035e1e]:first-child{border-top:none}