@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.
- package/README.md +10 -6
- package/dist/mcp-server/kobo-tasks-handlers.js +2 -2
- package/dist/server/db/migrations.js +24 -0
- package/dist/server/db/schema.js +10 -0
- package/dist/server/index.js +27 -4
- package/dist/server/routes/documents.js +2 -2
- package/dist/server/routes/git.js +21 -0
- package/dist/server/routes/health.js +2 -2
- package/dist/server/routes/images.js +3 -3
- package/dist/server/routes/usage.js +18 -0
- package/dist/server/routes/workspaces.js +207 -81
- package/dist/server/services/agent/engines/claude-code/args-builder.js +2 -0
- package/dist/server/services/agent/orchestrator.js +1 -1
- package/dist/server/services/auto-loop-service.js +22 -4
- package/dist/server/services/dev-server-service.js +2 -5
- package/dist/server/services/settings-service.js +18 -2
- package/dist/server/services/usage/db.js +29 -0
- package/dist/server/services/usage/index.js +2 -0
- package/dist/server/services/usage/poller.js +52 -0
- package/dist/server/services/usage/providers/claude-code.js +93 -0
- package/dist/server/services/usage/types.js +1 -0
- package/dist/server/services/wakeup-service.js +2 -2
- package/dist/server/services/websocket-service.js +14 -0
- package/dist/server/services/workspace-service.js +28 -3
- package/dist/server/services/worktree-service.js +50 -0
- package/dist/server/utils/mcp-client.js +7 -0
- package/dist/shared/auto-loop-prompts.js +46 -8
- package/package.json +1 -1
- package/src/client/dist/spa/assets/{ActivityFeed-6Xg7qNfy.js → ActivityFeed-BsY3-q5d.js} +1 -1
- package/src/client/dist/spa/assets/CreatePage-Cdhkkx-X.js +2 -0
- package/src/client/dist/spa/assets/CreatePage-PRvhol1N.css +1 -0
- package/src/client/dist/spa/assets/{DiffViewer-T111s7BH.js → DiffViewer-DXcoEtVq.js} +2 -2
- package/src/client/dist/spa/assets/{HealthPage-1VakQ0x_.js → HealthPage-BSyGqDRu.js} +1 -1
- package/src/client/dist/spa/assets/{MainLayout-Ci-CETJi.css → MainLayout-D2SfvksB.css} +1 -1
- package/src/client/dist/spa/assets/{MainLayout-w7DoW3yz.js → MainLayout-EYaLqjJx.js} +17 -17
- package/src/client/dist/spa/assets/{SearchPage-CcldJX8i.js → SearchPage-Bgx02GOH.js} +1 -1
- package/src/client/dist/spa/assets/SettingsPage-BTSOovDV.js +1 -0
- package/src/client/dist/spa/assets/SettingsPage-CwLELxfl.css +1 -0
- package/src/client/dist/spa/assets/WorkspacePage-C5MZx1sZ.css +1 -0
- package/src/client/dist/spa/assets/WorkspacePage-C8dJWu-n.js +4 -0
- package/src/client/dist/spa/assets/{build-path-tree-DbuI5yRz.js → build-path-tree-D-2LpB2J.js} +1 -1
- package/src/client/dist/spa/assets/{cssMode-DhpmJAZc.js → cssMode-DVBmJp-B.js} +1 -1
- package/src/client/dist/spa/assets/{documents-fVD9RJth.js → documents-Ck8VwvpQ.js} +1 -1
- package/src/client/dist/spa/assets/{editor.api-DCvwHsju.js → editor.api-DgbPJaK4.js} +1 -1
- package/src/client/dist/spa/assets/{editor.main-CRtPC0iL.js → editor.main-BqqoRfAU.js} +3 -3
- package/src/client/dist/spa/assets/{expand-template-BIra7NIw.js → expand-template-bkCTc78P.js} +1 -1
- package/src/client/dist/spa/assets/{freemarker2-C9UOErQw.js → freemarker2-CgaW0Q0y.js} +1 -1
- package/src/client/dist/spa/assets/{handlebars-DmZ2-ZcJ.js → handlebars-BSs5PdXe.js} +1 -1
- package/src/client/dist/spa/assets/{html-ButyxlXG.js → html-C9wlJaMs.js} +1 -1
- package/src/client/dist/spa/assets/{htmlMode-C-defy1b.js → htmlMode-DaRssGJk.js} +1 -1
- package/src/client/dist/spa/assets/i18n-BSNIShFg.js +1 -0
- package/src/client/dist/spa/assets/index-odgA9x8A.js +2 -0
- package/src/client/dist/spa/assets/{javascript-B6zVweIF.js → javascript-D0VYhsc-.js} +1 -1
- package/src/client/dist/spa/assets/{jsonMode-CttMw-EY.js → jsonMode-B57EaUNS.js} +1 -1
- package/src/client/dist/spa/assets/kobo-commands-D-9dbM70.js +11 -0
- package/src/client/dist/spa/assets/{liquid-tGpdE1YW.js → liquid-gP2gg7sw.js} +1 -1
- package/src/client/dist/spa/assets/{mdx-Cy5mpQoy.js → mdx-HhXcZn_S.js} +1 -1
- package/src/client/dist/spa/assets/{models-DdAQDnqk.js → models-CJC61gWE.js} +1 -1
- package/src/client/dist/spa/assets/{monaco.contribution-DtdkkTgR.js → monaco.contribution-ChJg8bwd.js} +2 -2
- package/src/client/dist/spa/assets/{python-hLOxMbm9.js → python-DM6FfMV3.js} +1 -1
- package/src/client/dist/spa/assets/{razor-tqHFRROa.js → razor-XifsxhTG.js} +1 -1
- package/src/client/dist/spa/assets/stats-C3n1k51k.js +1 -0
- package/src/client/dist/spa/assets/{tsMode-MJKgZYsJ.js → tsMode-B8gurPqG.js} +1 -1
- package/src/client/dist/spa/assets/{typescript-CWTqB5lb.js → typescript-CZKTCOjl.js} +1 -1
- package/src/client/dist/spa/assets/{xml-ByDBLBVa.js → xml-CtZPkb7Q.js} +1 -1
- package/src/client/dist/spa/assets/{yaml-BiTCWZ38.js → yaml-D5IEE5M-.js} +1 -1
- package/src/client/dist/spa/index.html +1 -1
- package/src/mcp-server/kobo-tasks-handlers.ts +3 -2
- package/src/client/dist/spa/assets/CreatePage-BQu7mQjm.css +0 -1
- package/src/client/dist/spa/assets/CreatePage-CrRGDs5V.js +0 -2
- package/src/client/dist/spa/assets/SettingsPage-CLMCHMpz.css +0 -1
- package/src/client/dist/spa/assets/SettingsPage-CMyeaz63.js +0 -1
- package/src/client/dist/spa/assets/WorkspacePage-Bw9xhTDR.js +0 -4
- package/src/client/dist/spa/assets/WorkspacePage-_1mty_a4.css +0 -1
- package/src/client/dist/spa/assets/i18n-C8aJvuyS.js +0 -1
- package/src/client/dist/spa/assets/index-DAbX631s.js +0 -2
- package/src/client/dist/spa/assets/kobo-commands-CD7ERFxp.js +0 -10
- 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,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 (
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
* `
|
|
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
|
|
15
|
-
|
|
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
|
-
|
|
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.
|
|
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-
|
|
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}
|