@loicngr/kobo 1.7.2 → 1.7.4
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/dist/mcp-server/kobo-tasks-handlers.js +8 -1
- package/dist/server/routes/health.js +12 -6
- package/dist/server/routes/settings.js +16 -0
- package/dist/server/routes/workspaces.js +207 -4
- package/dist/server/services/agent/orchestrator.js +3 -0
- package/dist/server/services/auto-loop-service.js +7 -1
- package/dist/server/services/initial-prompt-template-service.js +48 -0
- package/dist/server/services/review-template-service.js +58 -0
- package/dist/server/services/settings-service.js +70 -3
- package/dist/server/services/wakeup-service.js +9 -1
- package/dist/server/services/worktree-service.js +2 -2
- package/dist/server/utils/git-ops.js +130 -9
- package/dist/server/utils/project-slug.js +52 -0
- package/dist/server/utils/worktree-paths.js +12 -10
- package/package.json +1 -1
- package/src/client/dist/spa/assets/ActivityFeed-ClJLeAXJ.js +7 -0
- package/src/client/dist/spa/assets/{ActivityFeed-LXnbg3ff.css → ActivityFeed-DVBfmJWJ.css} +1 -1
- package/src/client/dist/spa/assets/{ClosePopup-BP025_cK.js → ClosePopup-D_UAdwkA.js} +1 -1
- package/src/client/dist/spa/assets/CreatePage-BOkt0Psl.js +2 -0
- package/src/client/dist/spa/assets/CreatePage-DssmsAsV.css +1 -0
- package/src/client/dist/spa/assets/DiffViewer-Dls1jFCN.js +7 -0
- package/src/client/dist/spa/assets/{DiffViewer-D1Sdu307.css → DiffViewer-wFfQ9tcY.css} +1 -1
- package/src/client/dist/spa/assets/{HealthPage-CkHv5qMK.js → HealthPage-CMxH3SBS.js} +1 -1
- package/src/client/dist/spa/assets/{MainLayout-l91ohFQA.js → MainLayout-DHNIerYJ.js} +17 -17
- package/src/client/dist/spa/assets/MainLayout-DKurmqtk.css +1 -0
- package/src/client/dist/spa/assets/{QExpansionItem-BaQJkGb-.js → QExpansionItem-CH1ipL9n.js} +1 -1
- package/src/client/dist/spa/assets/{QMenu-DgWZe7Uh.js → QMenu-B4xMxMGd.js} +1 -1
- package/src/client/dist/spa/assets/{QTabPanels-CjpZTIJg.js → QTabPanels-D2ks0UIA.js} +1 -1
- package/src/client/dist/spa/assets/{QTooltip-D_hSPb7r.js → QTooltip-fDNzBEfN.js} +1 -1
- package/src/client/dist/spa/assets/{SearchPage-B1WhFCUf.js → SearchPage-BEnZ-CLq.js} +1 -1
- package/src/client/dist/spa/assets/SettingsPage-CMyeQ9_u.css +1 -0
- package/src/client/dist/spa/assets/SettingsPage-DeCbWvPb.js +1 -0
- package/src/client/dist/spa/assets/{TouchPan-1PETKHN0.js → TouchPan-DoE24Io3.js} +1 -1
- package/src/client/dist/spa/assets/{WorkspacePage-D3MBshNH.js → WorkspacePage-DFAFT5OW.js} +3 -3
- package/src/client/dist/spa/assets/{WorkspacePage-d_B0-LNG.css → WorkspacePage-eymEd4kx.css} +1 -1
- package/src/client/dist/spa/assets/{build-path-tree-w3SEPAbh.js → build-path-tree-B1Lvvqto.js} +1 -1
- package/src/client/dist/spa/assets/{cssMode-B6CD4qMI.js → cssMode-AlflsawW.js} +1 -1
- package/src/client/dist/spa/assets/{editor.api-wizjkvCK.js → editor.api-DtvjQlUm.js} +1 -1
- package/src/client/dist/spa/assets/{editor.main-Bn6fpPLF.js → editor.main-Ccy_gjVD.js} +3 -3
- package/src/client/dist/spa/assets/{expand-template-Cu5GSLCM.js → expand-template-AQsvbQ8_.js} +1 -1
- package/src/client/dist/spa/assets/{freemarker2-DW-DFUis.js → freemarker2-DdQktlXK.js} +1 -1
- package/src/client/dist/spa/assets/{handlebars-CSSQFRHS.js → handlebars-CE3ee2NH.js} +1 -1
- package/src/client/dist/spa/assets/{html-Ba5lfQna.js → html-CCKX8Xv9.js} +1 -1
- package/src/client/dist/spa/assets/{htmlMode-ocrlHn5h.js → htmlMode-Dh8jDJum.js} +1 -1
- package/src/client/dist/spa/assets/i18n-BOsrrRj4.js +1 -0
- package/src/client/dist/spa/assets/index-_ZaIBxd6.js +2 -0
- package/src/client/dist/spa/assets/{javascript-DL3j24x3.js → javascript-DhmZNdUp.js} +1 -1
- package/src/client/dist/spa/assets/{jsonMode-CtFp2BJe.js → jsonMode-B0xAtnNK.js} +1 -1
- package/src/client/dist/spa/assets/{liquid-B_GGNnlJ.js → liquid-ByL0HpZ0.js} +1 -1
- package/src/client/dist/spa/assets/{mdx-BXe8MrIz.js → mdx-DX4pehAZ.js} +1 -1
- package/src/client/dist/spa/assets/{models-BMOYJtwv.js → models-ClWoqWeC.js} +1 -1
- package/src/client/dist/spa/assets/{monaco.contribution-DSSRKV2r.js → monaco.contribution-Fegh8Y1Y.js} +2 -2
- package/src/client/dist/spa/assets/{notifications-CG-oL2m2.js → notifications-OnPq4FrH.js} +1 -1
- package/src/client/dist/spa/assets/purify.es-BWZjBa9F.js +60 -0
- package/src/client/dist/spa/assets/{python-DPtBXcrE.js → python-COS2MM8n.js} +1 -1
- package/src/client/dist/spa/assets/{razor-y1p5VjhT.js → razor-Cc3xCJU7.js} +1 -1
- package/src/client/dist/spa/assets/render-chat-markdown-DcGIpMoe.js +1 -0
- package/src/client/dist/spa/assets/{tsMode-CV2CQlAd.js → tsMode-eQIJjERk.js} +1 -1
- package/src/client/dist/spa/assets/{typescript-DsjWQLAN.js → typescript-DwIlacVU.js} +1 -1
- package/src/client/dist/spa/assets/{use-panel-D2MjPZiL.js → use-panel-D-8nAQns.js} +1 -1
- package/src/client/dist/spa/assets/{xml-AQhpP8em.js → xml-DP-09Aih.js} +1 -1
- package/src/client/dist/spa/assets/{yaml-zZFlU7RD.js → yaml-BhrtimeA.js} +1 -1
- package/src/client/dist/spa/index.html +2 -2
- package/src/mcp-server/kobo-tasks-handlers.ts +10 -1
- package/src/client/dist/spa/assets/ActivityFeed-B85xav_e.js +0 -7
- package/src/client/dist/spa/assets/CreatePage-BE3xfQsC.css +0 -1
- package/src/client/dist/spa/assets/CreatePage-DyR33jFM.js +0 -2
- package/src/client/dist/spa/assets/DiffViewer-CqhpTkym.js +0 -7
- package/src/client/dist/spa/assets/MainLayout-B07zv82Z.css +0 -1
- package/src/client/dist/spa/assets/QScrollArea-usfgatuS.js +0 -1
- package/src/client/dist/spa/assets/SettingsPage-B7S5fXGG.js +0 -1
- package/src/client/dist/spa/assets/SettingsPage-kHd651y8.css +0 -1
- package/src/client/dist/spa/assets/i18n-CqK8B0Nz.js +0 -1
- package/src/client/dist/spa/assets/index-DE3PxEjy.js +0 -2
- package/src/client/dist/spa/assets/marked.esm-D4t0_2pc.js +0 -60
|
@@ -4,7 +4,9 @@ import { WORKTREES_PATH } from '../../shared/consts.js';
|
|
|
4
4
|
import { listClaudeMcpEntries } from '../utils/mcp-client.js';
|
|
5
5
|
import { getSettingsPath } from '../utils/paths.js';
|
|
6
6
|
import { InvalidWorktreesPathError, resolveGlobalWorktreesRoot, sanitizeWorktreesPath, validateWorktreesPath, } from '../utils/worktree-paths.js';
|
|
7
|
-
|
|
7
|
+
import { DEFAULT_NOTION_INITIAL_PROMPT, DEFAULT_SENTRY_INITIAL_PROMPT } from './initial-prompt-template-service.js';
|
|
8
|
+
import { DEFAULT_REVIEW_PROMPT_TEMPLATE } from './review-template-service.js';
|
|
9
|
+
export const DEFAULT_GIT_CONVENTIONS = `# Git conventions
|
|
8
10
|
|
|
9
11
|
## Commits
|
|
10
12
|
- Use Conventional Commits: \`type(scope): subject\`
|
|
@@ -29,7 +31,7 @@ const DEFAULT_GIT_CONVENTIONS = `# Git conventions
|
|
|
29
31
|
- Never skip hooks (--no-verify) unless the user explicitly asks
|
|
30
32
|
- Always inspect \`git status\` and \`git diff\` before staging
|
|
31
33
|
`;
|
|
32
|
-
const DEFAULT_PR_PROMPT_TEMPLATE = `A pull request has been opened: {{pr_url}} (#{{pr_number}})
|
|
34
|
+
export const DEFAULT_PR_PROMPT_TEMPLATE = `A pull request has been opened: {{pr_url}} (#{{pr_number}})
|
|
33
35
|
|
|
34
36
|
Context:
|
|
35
37
|
- Workspace: {{workspace_name}}
|
|
@@ -60,7 +62,9 @@ export const DEFAULT_FINALIZATION_PROMPT = `Run final quality checks before clos
|
|
|
60
62
|
1. Verify all other tasks are marked \`done\`. If any remain \`pending\`, stop and report.
|
|
61
63
|
2. Run the project's linters, type-checkers, and tests (see CLAUDE.md or package.json scripts).
|
|
62
64
|
3. If any check fails, create a new regular task at the end of the list with a title like \`Fix lint failure in X\` (NO \`[FINAL]\` or \`[E2E]\` prefix — it must use the default iteration prompt) and mark this \`[FINAL]\` task as \`done\`. The auto-loop will pick up the fix on the next iteration. The finalization mechanism is single-shot per grooming pass; if you want quality checks to re-run after the fix, mark the fix task \`done\` and re-trigger grooming manually.
|
|
63
|
-
4. If everything passes, mark this task as \`done
|
|
65
|
+
4. If everything passes, mark this task as \`done\`.
|
|
66
|
+
|
|
67
|
+
HARD RULE: Do NOT open a pull request, do NOT run \`gh pr create\` or any equivalent command. The finalization step never opens a PR — that is a separate, explicit user action via the "Open PR" button.`;
|
|
64
68
|
/** Default workspace tags seeded on fresh install and on settings upgrade. */
|
|
65
69
|
export const DEFAULT_WORKSPACE_TAGS = [
|
|
66
70
|
'bug',
|
|
@@ -219,6 +223,49 @@ const settingsMigrations = [
|
|
|
219
223
|
}
|
|
220
224
|
},
|
|
221
225
|
},
|
|
226
|
+
{
|
|
227
|
+
version: 14,
|
|
228
|
+
name: 'add-worktrees-prefix-by-project',
|
|
229
|
+
migrate({ global }) {
|
|
230
|
+
if (typeof global.worktreesPrefixByProject !== 'boolean') {
|
|
231
|
+
global.worktreesPrefixByProject = false;
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
version: 15,
|
|
237
|
+
name: 'add-review-prompt-template',
|
|
238
|
+
migrate({ global, projects }) {
|
|
239
|
+
if (typeof global.reviewPromptTemplate !== 'string') {
|
|
240
|
+
global.reviewPromptTemplate = DEFAULT_REVIEW_PROMPT_TEMPLATE;
|
|
241
|
+
}
|
|
242
|
+
for (const p of projects) {
|
|
243
|
+
if (typeof p.reviewPromptTemplate !== 'string') {
|
|
244
|
+
p.reviewPromptTemplate = '';
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
version: 16,
|
|
251
|
+
name: 'add-notion-sentry-initial-prompts',
|
|
252
|
+
migrate({ global, projects }) {
|
|
253
|
+
if (typeof global.notionInitialPromptTemplate !== 'string') {
|
|
254
|
+
global.notionInitialPromptTemplate = DEFAULT_NOTION_INITIAL_PROMPT;
|
|
255
|
+
}
|
|
256
|
+
if (typeof global.sentryInitialPromptTemplate !== 'string') {
|
|
257
|
+
global.sentryInitialPromptTemplate = DEFAULT_SENTRY_INITIAL_PROMPT;
|
|
258
|
+
}
|
|
259
|
+
for (const p of projects) {
|
|
260
|
+
if (typeof p.notionInitialPromptTemplate !== 'string') {
|
|
261
|
+
p.notionInitialPromptTemplate = '';
|
|
262
|
+
}
|
|
263
|
+
if (typeof p.sentryInitialPromptTemplate !== 'string') {
|
|
264
|
+
p.sentryInitialPromptTemplate = '';
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
},
|
|
222
269
|
];
|
|
223
270
|
/** Current settings schema version — always equals the highest migration version. */
|
|
224
271
|
export const SETTINGS_SCHEMA_VERSION = settingsMigrations.length > 0 ? settingsMigrations[settingsMigrations.length - 1].version : 0;
|
|
@@ -249,6 +296,9 @@ function defaultSettings() {
|
|
|
249
296
|
defaultModel: 'claude-opus-4-7',
|
|
250
297
|
dangerouslySkipPermissions: true,
|
|
251
298
|
prPromptTemplate: DEFAULT_PR_PROMPT_TEMPLATE,
|
|
299
|
+
reviewPromptTemplate: DEFAULT_REVIEW_PROMPT_TEMPLATE,
|
|
300
|
+
notionInitialPromptTemplate: DEFAULT_NOTION_INITIAL_PROMPT,
|
|
301
|
+
sentryInitialPromptTemplate: DEFAULT_SENTRY_INITIAL_PROMPT,
|
|
252
302
|
gitConventions: DEFAULT_GIT_CONVENTIONS,
|
|
253
303
|
editorCommand: '',
|
|
254
304
|
browserNotifications: true,
|
|
@@ -262,6 +312,7 @@ function defaultSettings() {
|
|
|
262
312
|
sentryMcpKey: '',
|
|
263
313
|
tags: [...DEFAULT_WORKSPACE_TAGS],
|
|
264
314
|
worktreesPath: WORKTREES_PATH,
|
|
315
|
+
worktreesPrefixByProject: false,
|
|
265
316
|
},
|
|
266
317
|
projects: [],
|
|
267
318
|
};
|
|
@@ -274,6 +325,9 @@ function defaultProjectSettings(projectPath) {
|
|
|
274
325
|
defaultModel: '',
|
|
275
326
|
dangerouslySkipPermissions: true,
|
|
276
327
|
prPromptTemplate: '',
|
|
328
|
+
reviewPromptTemplate: '',
|
|
329
|
+
notionInitialPromptTemplate: '',
|
|
330
|
+
sentryInitialPromptTemplate: '',
|
|
277
331
|
gitConventions: '',
|
|
278
332
|
setupScript: '',
|
|
279
333
|
devServer: {
|
|
@@ -447,6 +501,9 @@ export function getEffectiveSettings(projectPath) {
|
|
|
447
501
|
model: settings.global.defaultModel,
|
|
448
502
|
dangerouslySkipPermissions: settings.global.dangerouslySkipPermissions,
|
|
449
503
|
prPromptTemplate: settings.global.prPromptTemplate,
|
|
504
|
+
reviewPromptTemplate: settings.global.reviewPromptTemplate,
|
|
505
|
+
notionInitialPromptTemplate: settings.global.notionInitialPromptTemplate,
|
|
506
|
+
sentryInitialPromptTemplate: settings.global.sentryInitialPromptTemplate,
|
|
450
507
|
gitConventions: settings.global.gitConventions,
|
|
451
508
|
sourceBranch: '',
|
|
452
509
|
devServer: null,
|
|
@@ -459,6 +516,9 @@ export function getEffectiveSettings(projectPath) {
|
|
|
459
516
|
model: project.defaultModel || settings.global.defaultModel,
|
|
460
517
|
dangerouslySkipPermissions: project.dangerouslySkipPermissions ?? settings.global.dangerouslySkipPermissions,
|
|
461
518
|
prPromptTemplate: project.prPromptTemplate || settings.global.prPromptTemplate,
|
|
519
|
+
reviewPromptTemplate: project.reviewPromptTemplate || settings.global.reviewPromptTemplate,
|
|
520
|
+
notionInitialPromptTemplate: project.notionInitialPromptTemplate || settings.global.notionInitialPromptTemplate,
|
|
521
|
+
sentryInitialPromptTemplate: project.sentryInitialPromptTemplate || settings.global.sentryInitialPromptTemplate,
|
|
462
522
|
gitConventions: project.gitConventions || settings.global.gitConventions,
|
|
463
523
|
sourceBranch: project.defaultSourceBranch,
|
|
464
524
|
devServer: project.devServer,
|
|
@@ -474,6 +534,9 @@ export function updateGlobalSettings(data) {
|
|
|
474
534
|
'defaultModel',
|
|
475
535
|
'dangerouslySkipPermissions',
|
|
476
536
|
'prPromptTemplate',
|
|
537
|
+
'reviewPromptTemplate',
|
|
538
|
+
'notionInitialPromptTemplate',
|
|
539
|
+
'sentryInitialPromptTemplate',
|
|
477
540
|
'gitConventions',
|
|
478
541
|
'editorCommand',
|
|
479
542
|
'browserNotifications',
|
|
@@ -487,6 +550,7 @@ export function updateGlobalSettings(data) {
|
|
|
487
550
|
'sentryMcpKey',
|
|
488
551
|
'tags',
|
|
489
552
|
'worktreesPath',
|
|
553
|
+
'worktreesPrefixByProject',
|
|
490
554
|
];
|
|
491
555
|
const filtered = pickKnownKeys(data, allowedGlobalKeys);
|
|
492
556
|
if (filtered.tags !== undefined) {
|
|
@@ -532,6 +596,9 @@ export function upsertProject(projectPath, data) {
|
|
|
532
596
|
'defaultModel',
|
|
533
597
|
'dangerouslySkipPermissions',
|
|
534
598
|
'prPromptTemplate',
|
|
599
|
+
'reviewPromptTemplate',
|
|
600
|
+
'notionInitialPromptTemplate',
|
|
601
|
+
'sentryInitialPromptTemplate',
|
|
535
602
|
'gitConventions',
|
|
536
603
|
'setupScript',
|
|
537
604
|
'devServer',
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getDb } from '../db/index.js';
|
|
2
|
+
import { slugifyProjectName } from '../utils/project-slug.js';
|
|
2
3
|
import { resolveWorkspaceWorktreePath } from '../utils/worktree-paths.js';
|
|
3
4
|
import * as orchestrator from './agent/orchestrator.js';
|
|
5
|
+
import * as settingsService from './settings-service.js';
|
|
4
6
|
import { emitEphemeral } from './websocket-service.js';
|
|
5
7
|
const MIN_DELAY_SECONDS = 60;
|
|
6
8
|
const MAX_DELAY_SECONDS = 3600;
|
|
@@ -132,7 +134,13 @@ function fire(workspaceId) {
|
|
|
132
134
|
emitEphemeral(workspaceId, 'wakeup:skipped', { reason: 'fire-failed' });
|
|
133
135
|
return;
|
|
134
136
|
}
|
|
135
|
-
const
|
|
137
|
+
const globalSettings = settingsService.getGlobalSettings();
|
|
138
|
+
const projectSettings = settingsService.getProjectSettings(wsRow.project_path);
|
|
139
|
+
const projectSlug = globalSettings.worktreesPrefixByProject
|
|
140
|
+
? slugifyProjectName(projectSettings?.displayName ?? '', wsRow.project_path)
|
|
141
|
+
: undefined;
|
|
142
|
+
const worktreePath = wsRow.worktree_path ??
|
|
143
|
+
resolveWorkspaceWorktreePath(wsRow.project_path, wsRow.working_branch, globalSettings.worktreesPath, projectSlug);
|
|
136
144
|
// Narrow against the four known values; unknowns → 'bypass'.
|
|
137
145
|
const stored = wsRow.agent_permission_mode;
|
|
138
146
|
const agentPermissionMode = stored === 'plan' || stored === 'strict' || stored === 'interactive' ? stored : 'bypass';
|
|
@@ -49,12 +49,12 @@ function removeFromExclude(projectPath, worktreePath) {
|
|
|
49
49
|
fs.writeFileSync(excludeFile, trimmed ? `${trimmed}\n` : '', 'utf-8');
|
|
50
50
|
}
|
|
51
51
|
/** Create a git worktree for the given branch. Returns the worktree path. */
|
|
52
|
-
export function createWorktree(projectPath, branchName, sourceBranch, worktreesPath) {
|
|
52
|
+
export function createWorktree(projectPath, branchName, sourceBranch, worktreesPath, projectSlug) {
|
|
53
53
|
const worktreesDir = resolveWorktreesRoot(projectPath, worktreesPath);
|
|
54
54
|
if (!fs.existsSync(worktreesDir)) {
|
|
55
55
|
fs.mkdirSync(worktreesDir, { recursive: true });
|
|
56
56
|
}
|
|
57
|
-
const worktreePath = resolveWorkspaceWorktreePath(projectPath, branchName, worktreesPath);
|
|
57
|
+
const worktreePath = resolveWorkspaceWorktreePath(projectPath, branchName, worktreesPath, projectSlug);
|
|
58
58
|
try {
|
|
59
59
|
// Use origin/<sourceBranch> as the base so the worktree starts from the
|
|
60
60
|
// freshly-fetched remote ref (fetchSourceBranch is always called first).
|
|
@@ -4,7 +4,14 @@ import { join } from 'node:path';
|
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
const execFileAsync = promisify(execFileCb);
|
|
6
6
|
function git(repoPath, args) {
|
|
7
|
-
|
|
7
|
+
// `trimEnd` (not `trim`): some git outputs are column-aligned and the LEADING
|
|
8
|
+
// space carries information. The classic case is `git status --porcelain`,
|
|
9
|
+
// where each line is `XY filename` and X is " " when the index has no
|
|
10
|
+
// change. Stripping that leading space silently shifts every column by one
|
|
11
|
+
// and makes `line.substring(3)` chop the first character of the filename
|
|
12
|
+
// (e.g. `front/foo` → `ront/foo`). Trailing whitespace (the final `\n` git
|
|
13
|
+
// always appends) still goes — that's what every caller expects.
|
|
14
|
+
return execFileSync('git', args, { cwd: repoPath, encoding: 'utf-8' }).trimEnd();
|
|
8
15
|
}
|
|
9
16
|
/** Return the name of the currently checked-out branch. */
|
|
10
17
|
export function getCurrentBranch(repoPath) {
|
|
@@ -267,6 +274,22 @@ export function getCommitCount(repoPath, base, head) {
|
|
|
267
274
|
return 0;
|
|
268
275
|
}
|
|
269
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Count commits in `base` that are not in `head` — i.e. how far `head` lags
|
|
279
|
+
* behind `base`. Mirrors `getCommitCount` but in reverse direction.
|
|
280
|
+
* Returns 0 on failure.
|
|
281
|
+
*/
|
|
282
|
+
export function getCommitsBehind(repoPath, base, head) {
|
|
283
|
+
try {
|
|
284
|
+
const ref = resolveBase(repoPath, base);
|
|
285
|
+
const output = git(repoPath, ['rev-list', '--count', `${head}..${ref}`]);
|
|
286
|
+
const n = parseInt(output.trim(), 10);
|
|
287
|
+
return Number.isFinite(n) ? n : 0;
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return 0;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
270
293
|
/** Return structured diff shortstat between two refs (three-dot merge base). */
|
|
271
294
|
export function getStructuredDiffStatsBetween(repoPath, base, head) {
|
|
272
295
|
try {
|
|
@@ -340,6 +363,40 @@ export function listBranchCommits(repoPath, sourceBranch, workingBranch, limit =
|
|
|
340
363
|
}
|
|
341
364
|
return commits;
|
|
342
365
|
}
|
|
366
|
+
/**
|
|
367
|
+
* List commits on `sourceBranch` that are NOT yet on `workingBranch` —
|
|
368
|
+
* i.e. commits the working branch is "behind" by. Mirror of `listBranchCommits`
|
|
369
|
+
* in the opposite direction. Up to `limit` commits, most recent first.
|
|
370
|
+
*/
|
|
371
|
+
export function listCommitsBehind(repoPath, sourceBranch, workingBranch, limit = 50) {
|
|
372
|
+
const sourceRef = resolveBase(repoPath, sourceBranch);
|
|
373
|
+
const FORMAT = '--pretty=format:%H%x00%h%x00%s%x00%an%x00%aI';
|
|
374
|
+
let raw;
|
|
375
|
+
try {
|
|
376
|
+
raw = git(repoPath, ['log', `${workingBranch}..${sourceRef}`, `--max-count=${limit}`, FORMAT]);
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
return [];
|
|
380
|
+
}
|
|
381
|
+
if (!raw)
|
|
382
|
+
return [];
|
|
383
|
+
const commits = [];
|
|
384
|
+
for (const line of raw.split('\n')) {
|
|
385
|
+
if (!line)
|
|
386
|
+
continue;
|
|
387
|
+
const [sha, shortSha, subject, author, date] = line.split('\x00');
|
|
388
|
+
if (!sha)
|
|
389
|
+
continue;
|
|
390
|
+
commits.push({
|
|
391
|
+
sha,
|
|
392
|
+
shortSha: shortSha ?? '',
|
|
393
|
+
subject: subject ?? '',
|
|
394
|
+
author: author ?? '',
|
|
395
|
+
date: date ?? '',
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
return commits;
|
|
399
|
+
}
|
|
343
400
|
/** Get the GitHub PR URL for a branch using `gh pr view`. Returns null if no PR exists. */
|
|
344
401
|
export function getPrUrl(repoPath, branchName) {
|
|
345
402
|
try {
|
|
@@ -626,17 +683,38 @@ export function getWorkingTreeStatus(repoPath) {
|
|
|
626
683
|
return { staged: 0, modified: 0, untracked: 0 };
|
|
627
684
|
}
|
|
628
685
|
}
|
|
629
|
-
/**
|
|
630
|
-
|
|
686
|
+
/**
|
|
687
|
+
* Count commits ahead of `origin/<workingBranch>`. Returns `-1` when the remote
|
|
688
|
+
* ref does not exist (i.e. the branch has never been pushed).
|
|
689
|
+
*
|
|
690
|
+
* We deliberately use `origin/<workingBranch>` instead of the local `@{u}`
|
|
691
|
+
* upstream pointer: Kōbō creates worktrees with `git worktree add -b <new>
|
|
692
|
+
* <path> origin/<sourceBranch>`, so `@{u}` points at `origin/<sourceBranch>`,
|
|
693
|
+
* NOT at the working branch's remote sibling. Comparing HEAD with that wrong
|
|
694
|
+
* upstream silently reported "0 unpushed" for never-pushed branches that
|
|
695
|
+
* happened to be aligned with their source — surfacing as a false "Pushé"
|
|
696
|
+
* label in the GitPanel.
|
|
697
|
+
*/
|
|
698
|
+
export function getUnpushedCount(repoPath, workingBranch) {
|
|
699
|
+
const remoteRef = `origin/${workingBranch}`;
|
|
700
|
+
try {
|
|
701
|
+
execFileSync('git', ['rev-parse', '--verify', remoteRef], {
|
|
702
|
+
cwd: repoPath,
|
|
703
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
catch {
|
|
707
|
+
return -1; // branch never pushed (no remote ref)
|
|
708
|
+
}
|
|
631
709
|
try {
|
|
632
|
-
const output = execFileSync('git', ['rev-list',
|
|
710
|
+
const output = execFileSync('git', ['rev-list', `${remoteRef}..HEAD`, '--count'], {
|
|
633
711
|
cwd: repoPath,
|
|
634
712
|
encoding: 'utf-8',
|
|
635
713
|
}).trim();
|
|
636
714
|
return parseInt(output, 10) || 0;
|
|
637
715
|
}
|
|
638
716
|
catch {
|
|
639
|
-
return -1;
|
|
717
|
+
return -1;
|
|
640
718
|
}
|
|
641
719
|
}
|
|
642
720
|
/** Return raw `git diff --shortstat` output between two refs (three-dot). */
|
|
@@ -648,6 +726,21 @@ export function getDiffStatsBetween(repoPath, base, head) {
|
|
|
648
726
|
return '';
|
|
649
727
|
}
|
|
650
728
|
}
|
|
729
|
+
/**
|
|
730
|
+
* Return `git diff --stat HEAD` output (working tree vs HEAD) as a single string.
|
|
731
|
+
* Empty string if the working tree is clean or the command fails. Best-effort: never throws.
|
|
732
|
+
*/
|
|
733
|
+
export function getWorkingTreeDiffStats(repoPath) {
|
|
734
|
+
try {
|
|
735
|
+
return execFileSync('git', ['diff', '--stat', 'HEAD'], {
|
|
736
|
+
cwd: repoPath,
|
|
737
|
+
encoding: 'utf-8',
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
catch {
|
|
741
|
+
return '';
|
|
742
|
+
}
|
|
743
|
+
}
|
|
651
744
|
// ── Async versions ───────────────────────────────────────────────────────────
|
|
652
745
|
// Non-blocking alternatives for hot paths (pr-watcher, route handlers).
|
|
653
746
|
/** Async version of getPrUrl. Returns null if no PR exists. */
|
|
@@ -684,16 +777,44 @@ export async function getPrStatusAsync(repoPath, branchName) {
|
|
|
684
777
|
return null;
|
|
685
778
|
}
|
|
686
779
|
}
|
|
687
|
-
/**
|
|
688
|
-
|
|
780
|
+
/**
|
|
781
|
+
* Async version of `getUnpushedCount`. Same `origin/<workingBranch>` semantic:
|
|
782
|
+
* returns `-1` when the remote ref does not exist (never pushed), `0` when
|
|
783
|
+
* pushed and aligned, `>0` when pushed but ahead.
|
|
784
|
+
*/
|
|
785
|
+
export async function getUnpushedCountAsync(repoPath, workingBranch) {
|
|
786
|
+
const remoteRef = `origin/${workingBranch}`;
|
|
787
|
+
try {
|
|
788
|
+
await execFileAsync('git', ['rev-parse', '--verify', remoteRef], { cwd: repoPath });
|
|
789
|
+
}
|
|
790
|
+
catch {
|
|
791
|
+
return -1; // branch never pushed (no remote ref)
|
|
792
|
+
}
|
|
689
793
|
try {
|
|
690
|
-
const { stdout } = await execFileAsync('git', ['rev-list',
|
|
794
|
+
const { stdout } = await execFileAsync('git', ['rev-list', `${remoteRef}..HEAD`, '--count'], {
|
|
691
795
|
cwd: repoPath,
|
|
692
796
|
encoding: 'utf-8',
|
|
693
797
|
});
|
|
694
798
|
return parseInt(stdout.trim(), 10) || 0;
|
|
695
799
|
}
|
|
696
800
|
catch {
|
|
697
|
-
return -1;
|
|
801
|
+
return -1;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Best-effort async `git fetch <remote> <branch>`. Never throws — by contract,
|
|
806
|
+
* suitable for both fire-and-forget and `await` use without try/catch at the
|
|
807
|
+
* call site. Logs a warning on failure but resolves cleanly.
|
|
808
|
+
*
|
|
809
|
+
* Mirrors the sync `fetchSourceBranch` sibling, including the optional `remote`
|
|
810
|
+
* parameter (defaults to `'origin'`).
|
|
811
|
+
*/
|
|
812
|
+
export async function fetchSourceBranchAsync(repoPath, branch, remote = 'origin') {
|
|
813
|
+
try {
|
|
814
|
+
await execFileAsync('git', ['fetch', remote, branch], { cwd: repoPath });
|
|
815
|
+
}
|
|
816
|
+
catch (err) {
|
|
817
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
818
|
+
console.warn(`[git-ops] fetchSourceBranchAsync(${remote}/${branch}) failed: ${msg}`);
|
|
698
819
|
}
|
|
699
820
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
const WINDOWS_RESERVED = new Set([
|
|
3
|
+
'con',
|
|
4
|
+
'prn',
|
|
5
|
+
'aux',
|
|
6
|
+
'nul',
|
|
7
|
+
'com1',
|
|
8
|
+
'com2',
|
|
9
|
+
'com3',
|
|
10
|
+
'com4',
|
|
11
|
+
'com5',
|
|
12
|
+
'com6',
|
|
13
|
+
'com7',
|
|
14
|
+
'com8',
|
|
15
|
+
'com9',
|
|
16
|
+
'lpt1',
|
|
17
|
+
'lpt2',
|
|
18
|
+
'lpt3',
|
|
19
|
+
'lpt4',
|
|
20
|
+
'lpt5',
|
|
21
|
+
'lpt6',
|
|
22
|
+
'lpt7',
|
|
23
|
+
'lpt8',
|
|
24
|
+
'lpt9',
|
|
25
|
+
]);
|
|
26
|
+
function slugifyOne(value) {
|
|
27
|
+
return value
|
|
28
|
+
.normalize('NFD')
|
|
29
|
+
.replace(/[̀-ͯ]/g, '')
|
|
30
|
+
.toLowerCase()
|
|
31
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
32
|
+
.replace(/^-+|-+$/g, '');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Produce a cross-OS-safe directory name (Linux + macOS + Windows) from a
|
|
36
|
+
* project's display name, falling back to the path basename and finally to
|
|
37
|
+
* the literal `'project'`. Output is guaranteed to be non-empty and to avoid
|
|
38
|
+
* Windows reserved names (CON, PRN, COM1..9, LPT1..9, AUX, NUL).
|
|
39
|
+
*/
|
|
40
|
+
export function slugifyProjectName(displayName, projectPath) {
|
|
41
|
+
const fromDisplay = slugifyOne((displayName ?? '').trim());
|
|
42
|
+
if (fromDisplay)
|
|
43
|
+
return guard(fromDisplay);
|
|
44
|
+
const basename = path.basename(projectPath ?? '');
|
|
45
|
+
const fromBasename = slugifyOne(basename);
|
|
46
|
+
if (fromBasename)
|
|
47
|
+
return guard(fromBasename);
|
|
48
|
+
return 'project';
|
|
49
|
+
}
|
|
50
|
+
function guard(slug) {
|
|
51
|
+
return WINDOWS_RESERVED.has(slug) ? `${slug}-project` : slug;
|
|
52
|
+
}
|
|
@@ -115,20 +115,22 @@ export function resolveGlobalWorktreesRoot(configuredPath) {
|
|
|
115
115
|
return flavor.isAbsolute(expanded) ? flavor.normalize(expanded) : null;
|
|
116
116
|
}
|
|
117
117
|
/** Resolve the full on-disk path for a workspace worktree. */
|
|
118
|
-
export function resolveWorkspaceWorktreePath(projectPath, workingBranch, configuredPath) {
|
|
118
|
+
export function resolveWorkspaceWorktreePath(projectPath, workingBranch, configuredPath, projectSlug) {
|
|
119
119
|
const root = resolveWorktreesRoot(projectPath, configuredPath);
|
|
120
|
-
|
|
120
|
+
const flavor = pathFlavor(projectPath, root);
|
|
121
|
+
const slugSegment = projectSlug && projectSlug.length > 0 ? [projectSlug] : [];
|
|
122
|
+
return flavor.join(root, ...slugSegment, ...branchPathSegments(workingBranch));
|
|
121
123
|
}
|
|
122
124
|
/** Resolve a renamed worktree next to its current path when the current path still matches its branch. */
|
|
123
|
-
export function resolveSiblingWorkspaceWorktreePath(projectPath, worktreePath, currentBranch, nextBranch) {
|
|
125
|
+
export function resolveSiblingWorkspaceWorktreePath(projectPath, worktreePath, currentBranch, nextBranch, projectSlug) {
|
|
124
126
|
const flavor = pathFlavor(projectPath, worktreePath);
|
|
125
127
|
const normalizedWorktreePath = flavor.normalize(worktreePath);
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
const comparableSuffix = flavor === path.win32 ?
|
|
130
|
-
const root =
|
|
131
|
-
? normalizedWorktreePath.slice(0, -
|
|
128
|
+
const slugSegment = projectSlug && projectSlug.length > 0 ? [projectSlug] : [];
|
|
129
|
+
const currentSuffix = `${flavor.sep}${flavor.join(...slugSegment, ...branchPathSegments(currentBranch))}`;
|
|
130
|
+
const comparablePath = flavor === path.win32 ? normalizedWorktreePath.toLowerCase() : normalizedWorktreePath;
|
|
131
|
+
const comparableSuffix = flavor === path.win32 ? currentSuffix.toLowerCase() : currentSuffix;
|
|
132
|
+
const root = comparablePath.endsWith(comparableSuffix)
|
|
133
|
+
? normalizedWorktreePath.slice(0, -currentSuffix.length)
|
|
132
134
|
: resolveWorktreesRoot(projectPath);
|
|
133
|
-
return flavor.join(root, ...branchPathSegments(nextBranch));
|
|
135
|
+
return flavor.join(root, ...slugSegment, ...branchPathSegments(nextBranch));
|
|
134
136
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loicngr/kobo",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.4",
|
|
4
4
|
"description": "Kōbō — multi-workspace agent manager for Claude Code. Orchestrates isolated git worktrees with dev servers, Notion integration, and MCP tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -0,0 +1,7 @@
|
|
|
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{U as b,l as x,t as S}from"./QIcon-BJuyqdsT.js";import{c as C,s as w}from"./notifications-OnPq4FrH.js";import{t as T}from"./QBtn-a6jxWjmW.js";import{n as E}from"./vue-i18n-BcfTCFFS.js";import{d as D,g as O,l as k,p as A}from"./index-_ZaIBxd6.js";import{t as j}from"./QSpinnerDots-CszPQQ9J.js";import{t as M}from"./QTooltip-fDNzBEfN.js";import{t as N}from"./QExpansionItem-CH1ipL9n.js";import{n as ee,r as te,t as P}from"./render-chat-markdown-DcGIpMoe.js";import{n as F}from"./purify.es-BWZjBa9F.js";import{t as I}from"./documents-kx0vLfSG.js";import{t as L}from"./_plugin-vue_export-helper-Cj6tcsj6.js";function ne(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`session:user-input-requested`:case`message:raw`:case`skills:discovered`:case`usage`:case`rate_limit`:case`subagent:progress`:case`error`:break;default:}}let o=null;for(let e of r)e.type===`text`&&e.streaming&&(o&&(o.streaming=!1),o=e);return o&&!n&&(o.streaming=!1),r}function re(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 ie(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))}});function V(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=H(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 H(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 U=[`innerHTML`],W=L(v({__name:`TextMessageItem`,props:{item:{}},setup(e){let n=e,r=I(),i=k(),a=p(()=>{let e=i.selectedWorkspaceId;return e?r.documentsFor(e).map(e=>e.path):[]}),o=p(()=>ee(V(F.parse(n.item.text,{async:!1,breaks:!0,gfm:!0}),a.value),{addAttr:[`data-document-path`]}));function s(e){let t=e.target?.closest(`.document-link`);if(!t)return;e.preventDefault();let 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:s},[_(`div`,{innerHTML:o.value},null,8,U),e.item.streaming?(t(),l(x,{key:0,size:`xs`,class:`q-ml-xs`})):u(``,!0)]))}}),[[`__scopeId`,`data-v-1b7bd8ca`]]),oe={key:0,class:`text-caption text-grey-5`,style:{"font-style":`italic`}},G=[`innerHTML`],K={key:1,style:{"white-space":`pre-wrap`}},se=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(()=>P(n.item.text));return(n,d)=>i.value?(t(),m(`div`,oe,[a.value?(t(),l(N,{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,G)]),_:1},8,[`label`])):(t(),m(`span`,K,c(e.item.text),1))])):u(``,!0)}}),[[`__scopeId`,`data-v-7f45ed94`]]);function ce(e,t){let n=e.split(`
|
|
2
|
+
`),r=t.split(`
|
|
3
|
+
`),i=n.length,a=r.length,o=Array.from({length:i+1},()=>Array(a+1).fill(0));for(let e=i-1;e>=0;e--)for(let t=a-1;t>=0;t--)n[e]===r[t]?o[e][t]=o[e+1][t+1]+1:o[e][t]=Math.max(o[e+1][t],o[e][t+1]);let s=[],c=0,l=0;for(;c<i&&l<a;)n[c]===r[l]?(s.push({type:`context`,content:n[c]}),c++,l++):o[c+1][l]>=o[c][l+1]?(s.push({type:`del`,content:n[c]}),c++):(s.push({type:`add`,content:r[l]}),l++);for(;c<i;)s.push({type:`del`,content:n[c++]});for(;l<a;)s.push({type:`add`,content:r[l++]});return s}function q(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(`
|
|
4
|
+
`).length:0,deletions:t?t.split(`
|
|
5
|
+
`).length:0}}if(e===`Write`){let e=n.file_path;if(!e)return null;let t=n.content??``;return{toolName:`Write`,filePath:e,content:t,additions:t?t.split(`
|
|
6
|
+
`).length:0,deletions:0}}if(e===`Bash`){let e=(n.command??``).match(/^\s*rm\s+(?:-[a-zA-Z]*\s+)*(.+)/);if(e)return{toolName:`Bash:rm`,filePath:e[1].trim().replace(/["']/g,``),additions:0,deletions:1}}return null}function le(e,t){if(!e||!t?.projectPath)return e;let n=t.worktreePath;if(n){let t=J(e,n);if(t!==e)return t}let r=J(e,`${t.projectPath}/${C}/${t.workingBranch}`);return r===e?J(e,t.projectPath):r}function J(e,t){if(!t)return e;let n=ue(t);return n?e.replace(RegExp(`${n}[\\\\/]+`,`g`),``).replace(RegExp(`${n}(?=\\s|$|["'\`])`,`g`),`.`):e}function ue(e){let t=e.replace(/[\\/]+$/,``);return t?`${/^[\\/]+/.test(t)?`[\\\\/]+`:``}${t.split(/[\\/]+/).filter(Boolean).map(Y).join(`[\\\\/]+`)}`:``}function Y(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}var X={class:`tool-name`},de=[`title`],fe={key:0,class:`tool-stat-add`},Z={key:1,class:`tool-stat-del`},Q={class:`diff-sign`},$={class:`tool-name`},pe=[`title`],me=L(v({__name:`ToolCallItem`,props:{item:{}},setup(e){let i=e,o=a(!1),g=k(),v=p(()=>q(i.item.name,i.item.input)),y=p(()=>v.value?le(v.value.filePath,g.selectedWorkspace):``),x={Bash:`terminal`,Read:`description`,Edit:`edit`,Write:`edit_note`,MultiEdit:`edit`,Glob:`folder_open`,Grep:`manage_search`,LS:`list`,Skill:`auto_awesome`,Task:`hub`,Agent:`hub`,TodoWrite:`checklist`,TodoRead:`checklist`,ToolSearch:`search`,WebFetch:`public`,WebSearch:`travel_explore`,NotebookRead:`book`,NotebookEdit:`edit_note`,SendMessage:`send`,ExitPlanMode:`check_circle_outline`,KillShell:`stop_circle`,BashOutput:`terminal`},C=p(()=>x[i.item.name]??`build`),w=p(()=>{if(v.value)return``;let e=i.item.input,t=T(e);return t?le(t,g.selectedWorkspace):``});function T(e){if(!e||typeof e!=`object`)return typeof e==`string`?e:``;let t=e;for(let e of[`file_path`,`path`,`command`,`pattern`,`query`,`url`,`skill`,`description`,`subject`,`prompt`]){let n=t[e];if(typeof n==`string`&&n.length>0)return n}for(let e of Object.values(t))if(typeof e==`string`&&e.length>0)return e;return``}let E=p(()=>{let e=v.value;return e?e.toolName===`Edit`&&e.oldString!==void 0&&e.newString!==void 0?ce(e.oldString,e.newString):e.toolName===`Write`&&e.content!==void 0?e.content.split(`
|
|
7
|
+
`).map(e=>({type:`add`,content:e})):e.toolName===`Bash:rm`?[{type:`del`,content:`File deleted`}]:null:null}),D=p(()=>{let e=i.item.result;if(!e)return``;if(typeof e.output==`string`)return e.output;try{return JSON.stringify(e.output)}catch{return String(e.output)}}),O=new Set([`Read`]),A=p(()=>!!(i.item.result&&D.value)&&(!O.has(i.item.name)||i.item.result?.isError===!0));function j(){o.value=!o.value}return n(()=>i.item.result?.isError===!0,e=>{e&&(o.value=!0)},{immediate:!0}),(n,i)=>v.value?(t(),m(`div`,{key:0,class:s([`tool-row`,{"tool-row-expanded":o.value}])},[_(`div`,{class:`tool-header`,onClick:j},[d(S,{name:C.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),_(`span`,X,c(v.value.toolName===`Bash:rm`?`Bash`:v.value.toolName),1),_(`span`,{class:`tool-path`,title:v.value.filePath},c(y.value),9,de),v.value.additions>0?(t(),m(`span`,fe,`+`+c(v.value.additions),1)):u(``,!0),v.value.deletions>0?(t(),m(`span`,Z,`-`+c(v.value.deletions),1)):u(``,!0),e.item.result?.isError?(t(),l(S,{key:2,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-xs`})):e.item.result?(t(),l(S,{key:3,name:`check`,color:`positive`,size:`xs`,class:`q-ml-xs`})):u(``,!0),d(S,{name:o.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-auto text-grey-6`},null,8,[`name`])]),o.value&&E.value?(t(),m(`div`,{key:0,class:`tool-diff`,onClick:i[0]||=b(()=>{},[`stop`])},[(t(!0),m(h,null,r(E.value,(e,n)=>(t(),m(`div`,{key:n,class:s([`diff-line`,{"diff-del":e.type===`del`,"diff-add":e.type===`add`,"diff-context":e.type===`context`}])},[_(`span`,Q,c(e.type===`del`?`-`:e.type===`add`?`+`:` `),1),f(c(e.content),1)],2))),128))])):u(``,!0)],2)):(t(),m(`div`,{key:1,class:s([`tool-row tool-row-generic`,{"tool-row-expanded":o.value,"tool-row--toggleable":A.value}])},[_(`div`,{class:`tool-header`,onClick:i[1]||=e=>A.value&&j()},[d(S,{name:C.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),_(`span`,$,c(e.item.name),1),w.value?(t(),m(`span`,{key:0,class:`tool-arg`,title:T(e.item.input)||w.value},c(w.value),9,pe)):u(``,!0),e.item.result?.isError?(t(),l(S,{key:1,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-auto`})):e.item.result?(t(),l(S,{key:2,name:`check`,color:`positive`,size:`xs`,class:`q-ml-auto`})):u(``,!0),A.value?(t(),l(S,{key:3,name:o.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-xs text-grey-6`},null,8,[`name`])):u(``,!0)]),o.value&&A.value?(t(),m(`div`,{key:0,class:`tool-output`,onClick:i[2]||=b(()=>{},[`stop`])},c(D.value),1)):u(``,!0)],2))}}),[[`__scopeId`,`data-v-b1fcd20d`]]);function he(e,t){return t?e.replace(/\[image:\s+([^\]]+)\]/g,(e,n)=>{let r=String(n).trim();return/^(\.ai\/images\/|images\/)/.test(r)?`}/images/file?path=${encodeURIComponent(r)}`})`:e}):e}var ge=[`innerHTML`],_e=[`innerHTML`],ve=[`src`],ye=L(v({__name:`UserMessageItem`,props:{item:{}},setup(e){let n=e,r=k(),i=p(()=>n.item.sender===`system-prompt`),s=p(()=>P(he(n.item.content,r.selectedWorkspaceId??``))),c=a(null),f=a(!1);function g(e){let t=e.target;if(t?.tagName!==`IMG`)return;let n=t;n.src&&(c.value=n.src,f.value=!0)}return(e,n)=>(t(),m(h,null,[i.value?(t(),l(N,{key:0,dense:``,"dense-toggle":``,label:e.$t(`chat.systemPrompt`),"header-class":`text-grey-5 text-caption`},{default:o(()=>[_(`div`,{class:`q-py-xs markdown-user-prompt`,innerHTML:s.value},null,8,ge)]),_:1},8,[`label`])):(t(),m(`div`,{key:1,class:`markdown-message`,onClick:g},[_(`div`,{innerHTML:s.value},null,8,_e)])),d(O,{modelValue:f.value,"onUpdate:modelValue":n[1]||=e=>f.value=e},{default:o(()=>[c.value?(t(),m(`img`,{key:0,src:c.value,alt:``,class:`image-lightbox-img`,onClick:n[0]||=e=>f.value=!1},null,8,ve)):u(``,!0)]),_:1},8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-f34be4c5`]]),be={class:`turn-header`},xe={key:0,class:`turn-time`},Se={class:`turn-time turn-time-updated`},Ce={key:2,class:`turn-actions`},we={class:`turn-body`},Te={key:0,class:`turn-scroll-top`},Ee=L(v({__name:`TurnCard`,props:{turn:{}},emits:[`scrollTo`],setup(e,{emit:n}){let i=e,v=n,{t:b}=E(),x=a(null);function C(){let e=x.value;if(!e)return;let t=e.closest(`.q-scrollarea`)?.querySelector(`.q-scrollarea__content`);if(!t){e.scrollIntoView({behavior:`smooth`,block:`start`});return}let n=e.getBoundingClientRect().top-t.getBoundingClientRect().top;v(`scrollTo`,Math.max(0,n-8))}let w=p(()=>{switch(i.turn.speaker){case`user`:return{label:b(`chat.you`),accent:`#ce93d8`,badgeClass:`turn-badge-user`};case`agent`:return{label:b(`chat.agent`),accent:`#7986cb`,badgeClass:`turn-badge-agent`};case`system-prompt`:return{label:b(`chat.systemPrompt`),accent:`#757575`,badgeClass:`turn-badge-system`};case`session`:return{label:b(`chat.session`),accent:`#616161`,badgeClass:`turn-badge-session`}}});function D(e,t=!1){if(!e)return``;let n=new Date(e);return Number.isNaN(n.getTime())?``:n.toLocaleTimeString(void 0,t?{hour:`2-digit`,minute:`2-digit`,second:`2-digit`}:{hour:`2-digit`,minute:`2-digit`})}let O=p(()=>D(i.turn.ts)),k=p(()=>{let e=i.turn.items;if(e.length===0)return null;for(let t=e.length-1;t>=0;t--){let n=e[t].ts;if(n)return n}return null}),A=p(()=>{let e=i.turn.ts,t=k.value;if(!t||!e||t===e)return``;let n=new Date(e).getTime(),r=new Date(t).getTime();return Number.isNaN(n)||Number.isNaN(r)||r<=n?``:D(t,r-n<6e4)}),j=p(()=>A.value!==``),N=p(()=>i.turn.items.filter(e=>e.type===`tool`).length);return(n,i)=>(t(),m(`div`,{ref_key:`cardEl`,ref:x,class:s([`turn-card`,{"turn-card--user":e.turn.speaker===`user`}]),style:y({"--turn-accent":w.value.accent})},[_(`div`,be,[_(`span`,{class:s([`turn-badge`,w.value.badgeClass])},c(w.value.label),3),O.value?(t(),m(`span`,xe,c(O.value),1)):u(``,!0),j.value?(t(),m(h,{key:1},[d(S,{name:`arrow_forward`,size:`10px`,color:`grey-7`,class:`turn-time-arrow`}),_(`span`,Se,[f(c(A.value)+` `,1),d(M,null,{default:o(()=>[f(c(g(b)(`chat.lastUpdatedAt`,{time:A.value})),1)]),_:1})])],64)):u(``,!0),N.value>0?(t(),m(`span`,Ce,` · `+c(g(b)(`chat.nActions`,{n:N.value})),1)):u(``,!0)]),_(`div`,we,[(t(!0),m(h,null,r(e.turn.items,(e,n)=>(t(),m(h,{key:n},[e.type===`text`?(t(),l(W,{key:0,item:e},null,8,[`item`])):e.type===`thinking`?(t(),l(se,{key:1,item:e},null,8,[`item`])):e.type===`tool`?(t(),l(me,{key:2,item:e},null,8,[`item`])):e.type===`user`?(t(),l(ye,{key:3,item:e},null,8,[`item`])):e.type===`session`?(t(),l(B,{key:4,item:e},null,8,[`item`])):u(``,!0)],64))),128))]),e.turn.items.length>4?(t(),m(`div`,Te,[d(T,{flat:``,round:``,dense:``,size:`xs`,icon:`arrow_upward`,color:`grey-6`,class:`turn-scroll-top-btn`,onClick:C},{default:o(()=>[d(M,null,{default:o(()=>[f(c(g(b)(`chat.scrollToTurnTop`)),1)]),_:1})]),_:1})])):u(``,!0)],6))}}),[[`__scopeId`,`data-v-4729e0cc`]]),De={key:0,class:`activity-feed-switching`},Oe={key:1,class:`activity-feed-wrap`},ke={key:0,class:`text-center q-py-sm text-caption text-grey-6`},Ae={class:`q-pa-md`},je={key:1,class:`q-px-md q-pb-md`},Me={class:`activity-feed-nav-cluster`},Ne=60,Pe=200,Fe=200,Ie=400,Le=200,Re=L(v({__name:`ActivityFeed`,props:{workspaceId:{}},setup(s){let g=s,v=A(),y=w(),b=k(),S=p(()=>b.selectedSessionId),C=p(()=>b.sessions.find(e=>e.id===S.value)?.engineSessionId??null),E=p(()=>{let e=b.sessions;return e.length===0?!1:S.value===e[e.length-1].id});function O(e){return S.value?e?e===S.value||e===C.value:E.value:!0}let M=p(()=>(b.activityFeeds[g.workspaceId]??[]).filter(e=>e.type===`text`&&typeof e.content==`string`&&O(e.sessionId)).map(e=>({content:e.content,sender:e.meta?.sender??`user`,ts:e.timestamp,sessionId:e.sessionId}))),ee=p(()=>D(b.workspaces.find(e=>e.id===g.workspaceId)?.status)),P=p(()=>{let e=v.eventsFor(g.workspaceId),t=v.timestampsFor(g.workspaceId),n=v.sessionIdsFor(g.workspaceId),r=[],i=[];for(let a=0;a<e.length;a++)O(n[a])&&(r.push(e[a]),i.push(t[a]));let a=re(ne(r,i,ee.value),M.value);return ie(y.showVerboseSystemMessages?a:a.filter(e=>e.type!==`session`))}),F=p(()=>y.showVerboseSystemMessages?v.eventsFor(g.workspaceId).filter(e=>e.kind===`message:raw`).map(e=>e.content):[]),I=a(null),L=a(!0),R=a(!1),z=!1,B=a(!0),V=a(new Map);function ae(e){L.value=e.verticalSize-e.verticalPosition-e.verticalContainerSize<=Ne,z&&e.verticalPosition<=Pe&&!R.value&&U()&&G()}function H(e,t){return`${e}:${t}`}function U(){let e=S.value;return e?V.value.get(H(g.workspaceId,e))??!0:v.hasMoreOlderFor(g.workspaceId)}function W(e,t,n){V.value.set(H(e,t),n)}function oe(e){if(!S.value)return v.oldestIdFor(e);let t=v.eventIdsFor(e),n=v.sessionIdsFor(e);for(let e=0;e<t.length;e++){if(!O(n[e]))continue;let r=t[e];if(r)return r}}async function G(){let t=g.workspaceId,n=S.value,r=oe(t);if(!r)return;R.value=!0;let i=Date.now();try{let i=I.value,a=i?.getScroll().verticalSize??0,o=i?.getScroll().verticalPosition??0,s=new URLSearchParams({before:r,limit:`200`});n&&s.set(`session`,n);let c=fetch(`/api/workspaces/${t}/events?${s.toString()}`),l=new Promise(e=>setTimeout(e,Fe)),[u]=await Promise.all([c,l]);if(!u.ok){n?W(t,n,!1):v.prepend(t,[],[],{oldestId:r,hasMoreOlder:!1});return}let d=await u.json(),f=d.events??[],p=f.filter(e=>e.type===`agent:event`&&e.workspaceId===t),m=f.filter(e=>e.type===`user:message`&&e.workspaceId===t),h=p.map(e=>e.payload),g=p.map(e=>e.createdAt),_=p.map(e=>e.sessionId??null),y=p.map(e=>e.id),x=f.length>0?f[0].id:r;n&&W(t,n,d.hasMore),v.prepend(t,h,g,{oldestId:x,hasMoreOlder:n?v.hasMoreOlderFor(t):d.hasMore,sessionIds:_,eventIds:y});for(let e of m){let n=e.payload;typeof n.content==`string`&&b.addActivityItem(t,{id:e.id,type:`text`,content:n.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:n.sender??`user`}})}if(await e(),i){let e=i.getScroll().verticalSize-a;if(e>0){let t=Math.max(o+e,Pe+50);i.setScrollPosition(`vertical`,t,0)}}}catch(e){console.error(`[ActivityFeed] failed to load older events:`,e)}finally{let e=Date.now()-i,t=Math.max(0,Fe-e);await new Promise(e=>setTimeout(e,t+Ie)),R.value=!1}}async function K(t=0){await e();let n=I.value;if(!n)return;let r=n.getScroll();n.setScrollPosition(`vertical`,r.verticalSize,t)}function se(e){let t=I.value;t&&t.setScrollPosition(`vertical`,Math.max(0,e),250)}let ce=a([]),q=a(null);function le(){let e=P.value,t=ce.value,n=[];if(t.length===e.length){for(let r=0;r<e.length;r++){if(e[r].speaker!==`user`)continue;let i=t[r]?.$el;i&&n.push(i)}if(n.length>0)return n}let r=q.value?.parentElement;if(r){let e=r.querySelectorAll(`.turn-card--user`);for(let t of e)n.push(t)}return n}function J(){let e=I.value;if(!e)return null;let t=q.value;if(!t)return null;let n=e.getScroll().verticalPosition,r=t.getBoundingClientRect().top,i=null;for(let e of le()){let t=e.getBoundingClientRect().top-r;if(t<n-40)i=t;else break}return i}async function ue(){let t=I.value;if(!t)return;let n=J();if(n===null)for(let t=0;t<15&&U();t++){for(;R.value;)await new Promise(e=>setTimeout(e,50));if(await G(),await e(),n=J(),n!==null)break}n!==null&&t.setScrollPosition(`vertical`,Math.max(0,n-12),250)}async function Y(){z=!1,await e(),await K(0),requestAnimationFrame(()=>{requestAnimationFrame(()=>{z=!0})})}let X=p(()=>{let e=v.sessionIdsFor(g.workspaceId);if(!S.value)return e.length;let t=0;for(let n of e)O(n)&&t++;return t}),de=p(()=>v.eventsFor(g.workspaceId).length);async function fe(){B.value=!0;let e=Date.now();await new Promise(e=>setTimeout(e,Le));let t=e+5e3;for(;de.value===0&&Date.now()<t;)await new Promise(e=>setTimeout(e,50));B.value=!1}n(B,async e=>{!e&&X.value>0&&await Y(),!e&&X.value===0&&S.value&&$()}),i(()=>{fe(),X.value>0&&Y(),S.value&&$()});let Z=!1;n(X,async(e,t)=>{if(!Z&&e>0){Z=!0,await Y();return}e>t&&L.value&&!R.value&&await K(180)}),n(()=>g.workspaceId,()=>{L.value=!0,Z=!1,z=!1,fe(),X.value>0&&Y()}),n(()=>b.selectedSessionId,async()=>{L.value=!0,z=!1,await Y(),$()});let Q=new Set;async function $(){let t=S.value;if(!t||X.value>0)return;let n=H(g.workspaceId,t);if(!Q.has(n)){Q.add(n);try{let n=await fetch(`/api/workspaces/${g.workspaceId}/events?session=${encodeURIComponent(t)}&limit=500`);if(!n.ok)return;let r=await n.json(),i=r.events??[];if(i.length===0)return;let a=i.filter(e=>e.type===`agent:event`&&e.workspaceId===g.workspaceId),o=i.filter(e=>e.type===`user:message`&&e.workspaceId===g.workspaceId),s=a.map(e=>e.payload),c=a.map(e=>e.createdAt),l=a.map(e=>e.sessionId??null),u=a.map(e=>e.id);W(g.workspaceId,t,r.hasMore),s.length>0&&v.prepend(g.workspaceId,s,c,{oldestId:i[0].id,hasMoreOlder:v.hasMoreOlderFor(g.workspaceId),sessionIds:l,eventIds:u});for(let e of o){let t=e.payload;typeof t.content==`string`&&b.addActivityItem(g.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`}})}await e(),await K(0)}catch(e){console.error(`[ActivityFeed] fetchSessionIfMissing failed:`,e),Q.delete(n)}}}n(p(()=>M.value.filter(e=>e.sender!==`system-prompt`).length),async(e,t)=>{e>t&&(L.value=!0,await K(180))});async function pe(){L.value=!0,await K(250)}return(e,n)=>B.value?(t(),m(`div`,De,[d(j,{size:`40px`,color:`indigo-4`})])):(t(),m(`div`,Oe,[d(te,{ref_key:`scrollRef`,ref:I,class:`activity-feed-scroll`,onScroll:ae},{default:o(()=>[_(`div`,{ref_key:`contentOriginRef`,ref:q,class:`content-origin-marker`},null,512),R.value?(t(),m(`div`,ke,[d(x,{size:`sm`}),f(` `+c(e.$t(`activity.loading_older`)),1)])):u(``,!0),_(`div`,Ae,[(t(!0),m(h,null,r(P.value,(e,n)=>(t(),l(Ee,{key:n,ref_for:!0,ref_key:`turnRefs`,ref:ce,turn:e,onScrollTo:se},null,8,[`turn`]))),128))]),F.value.length?(t(),m(`div`,je,[d(N,{label:e.$t(`activity.raw_lines`,{n:F.value.length}),dense:``},{default:o(()=>[(t(!0),m(h,null,r(F.value,(e,n)=>(t(),m(`div`,{key:n,class:`text-caption text-grey q-pa-xs`},c(e),1))),128))]),_:1},8,[`label`])])):u(``,!0)]),_:1},512),_(`div`,Me,[L.value?u(``,!0):(t(),l(T,{key:0,round:``,dense:``,unelevated:``,color:`grey-9`,"text-color":`grey-3`,icon:`arrow_downward`,size:`sm`,class:`activity-feed-nav-btn`,title:e.$t(`activity.scroll_to_bottom`),onClick:pe},null,8,[`title`])),d(T,{round:``,dense:``,unelevated:``,color:`grey-9`,"text-color":`grey-3`,icon:`arrow_upward`,size:`sm`,class:`activity-feed-nav-btn`,title:e.$t(`activity.prev_user_message`),onClick:ue},null,8,[`title`])])]))}}),[[`__scopeId`,`data-v-2cb1aa26`]]);export{Re as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.markdown-message[data-v-
|
|
1
|
+
.markdown-message[data-v-1b7bd8ca]{color:#e0e0e0;word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-1b7bd8ca] *{max-width:100%}.markdown-message[data-v-1b7bd8ca] p{margin:0 0 .5em}.markdown-message[data-v-1b7bd8ca] p:last-child{margin-bottom:0}.markdown-message[data-v-1b7bd8ca] pre{background:#00000059;border-radius:4px;margin:.5em 0;padding:.5em .75em;overflow-x:auto}.markdown-message[data-v-1b7bd8ca] code{word-break:break-all;background:#0000004d;border-radius:3px;padding:.1em .3em;font-size:.9em}.markdown-message[data-v-1b7bd8ca] pre code{background:0 0;padding:0}.markdown-message[data-v-1b7bd8ca] ul,.markdown-message[data-v-1b7bd8ca] ol{margin:.25em 0 .5em;padding-left:1.5em}.markdown-message[data-v-1b7bd8ca] li{margin:.15em 0}.markdown-message[data-v-1b7bd8ca] a{color:#7986cb;text-decoration:underline}.markdown-message[data-v-1b7bd8ca] .document-link{color:#9fa8da;cursor:pointer;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.markdown-message[data-v-1b7bd8ca] .document-link:hover{color:#c5cae9;-webkit-text-decoration:underline;text-decoration:underline}.markdown-message[data-v-1b7bd8ca] h1,.markdown-message[data-v-1b7bd8ca] h2,.markdown-message[data-v-1b7bd8ca] h3,.markdown-message[data-v-1b7bd8ca] h4,.markdown-message[data-v-1b7bd8ca] h5,.markdown-message[data-v-1b7bd8ca] h6{margin:.5em 0 .3em;font-weight:600;line-height:1.3}.markdown-message[data-v-1b7bd8ca] h1{font-size:1.25em}.markdown-message[data-v-1b7bd8ca] h2{font-size:1.15em}.markdown-message[data-v-1b7bd8ca] h3{font-size:1.08em}.markdown-message[data-v-1b7bd8ca] h4,.markdown-message[data-v-1b7bd8ca] h5,.markdown-message[data-v-1b7bd8ca] h6{font-size:1em}.markdown-message[data-v-1b7bd8ca] blockquote{color:#ffffffb3;border-left:3px solid #fff3;margin:.5em 0;padding-left:.75em}.markdown-message[data-v-1b7bd8ca] table{border-collapse:collapse;margin:.5em 0}.markdown-message[data-v-1b7bd8ca] th,.markdown-message[data-v-1b7bd8ca] td{border:1px solid #ffffff26;padding:.25em .5em}.markdown-thinking[data-v-7f45ed94] p{margin:0 0 .4em}.markdown-thinking[data-v-7f45ed94] p:last-child{margin-bottom:0}.markdown-thinking[data-v-7f45ed94] code{background:#ffffff14;border-radius:3px;padding:.1em .3em}.tool-row[data-v-b1fcd20d]{border-radius:4px;margin:0;font-size:12px}.tool-header[data-v-b1fcd20d]{color:#bbb;cursor:default;align-items:center;gap:10px;min-width:0;padding:5px 10px;display:flex}.tool-row:not(.tool-row-generic) .tool-header[data-v-b1fcd20d],.tool-row--toggleable .tool-header[data-v-b1fcd20d]{cursor:pointer}.tool-row:has(.tool-diff) .tool-header[data-v-b1fcd20d]{cursor:pointer}.tool-row:not(.tool-row-generic) .tool-header[data-v-b1fcd20d]:hover,.tool-row--toggleable .tool-header[data-v-b1fcd20d]:hover{background:#ffffff08}.tool-icon[data-v-b1fcd20d]{color:#9fbce0;flex-shrink:0}.tool-name[data-v-b1fcd20d]{color:#d0d0d0;flex-shrink:0;font-weight:600}.tool-arg[data-v-b1fcd20d],.tool-path[data-v-b1fcd20d]{color:#999;text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11.5px;overflow:hidden}.tool-path[data-v-b1fcd20d],.tool-arg[data-v-b1fcd20d]{flex:1}.tool-stat-add[data-v-b1fcd20d]{color:#66bb6a;flex-shrink:0;font-size:11px;font-weight:600}.tool-stat-del[data-v-b1fcd20d]{color:#ef5350;flex-shrink:0;font-size:11px;font-weight:600}.tool-diff[data-v-b1fcd20d]{background:#0003;border-radius:4px;max-height:400px;margin-top:4px;padding:8px 0;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px;line-height:1.5;overflow:auto}.diff-line[data-v-b1fcd20d]{white-space:pre;color:#bbb;padding:0 12px}.diff-sign[data-v-b1fcd20d]{color:#555;-webkit-user-select:none;user-select:none;width:14px;display:inline-block}.diff-add[data-v-b1fcd20d]{color:#c8e6c9;background:#66bb6a1a}.diff-add .diff-sign[data-v-b1fcd20d]{color:#66bb6a}.diff-del[data-v-b1fcd20d]{color:#ffcdd2;background:#ef53501a}.diff-del .diff-sign[data-v-b1fcd20d]{color:#ef5350}.tool-output[data-v-b1fcd20d]{color:#aaa;white-space:pre-wrap;background:#00000026;border-radius:4px;max-height:8em;margin-top:4px;padding:6px 10px;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px;overflow:auto}.markdown-message[data-v-f34be4c5]{color:#e0e0e0;word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-f34be4c5] *{max-width:100%}.markdown-message[data-v-f34be4c5] img{-o-object-fit:contain;object-fit:contain;cursor:zoom-in;background:#0003;border-radius:4px;max-width:180px;max-height:100px;margin:.3em 0;display:block}.markdown-message[data-v-f34be4c5] code{word-break:break-all}.markdown-message[data-v-f34be4c5] p{margin:0 0 .4em}.markdown-message[data-v-f34be4c5] p:last-child{margin-bottom:0}.markdown-message[data-v-f34be4c5] code{background:#00000040;border-radius:3px;padding:.1em .3em}.markdown-message[data-v-f34be4c5] h1,.markdown-message[data-v-f34be4c5] h2,.markdown-message[data-v-f34be4c5] h3,.markdown-message[data-v-f34be4c5] h4,.markdown-message[data-v-f34be4c5] h5,.markdown-message[data-v-f34be4c5] h6{margin:.4em 0 .25em;font-weight:600;line-height:1.3}.markdown-message[data-v-f34be4c5] h1{font-size:1.25em}.markdown-message[data-v-f34be4c5] h2{font-size:1.15em}.markdown-message[data-v-f34be4c5] h3{font-size:1.08em}.markdown-message[data-v-f34be4c5] h4,.markdown-message[data-v-f34be4c5] h5,.markdown-message[data-v-f34be4c5] h6{font-size:1em}.markdown-user-prompt[data-v-f34be4c5]{color:#aaa;font-size:12px;font-style:italic}.markdown-user-prompt[data-v-f34be4c5] p{margin:0 0 .4em}.markdown-user-prompt[data-v-f34be4c5] code{background:#ffffff14;border-radius:3px;padding:.1em .3em;font-style:normal}.image-lightbox-img{-o-object-fit:contain;object-fit:contain;cursor:zoom-out;background:#0000004d;border-radius:4px;max-width:92vw;max-height:92vh;display:block}.turn-card[data-v-4729e0cc]{border:1px solid #ffffff14;border-left:3px solid var(--turn-accent);background:#ffffff05;border-radius:6px;min-width:0;max-width:100%;margin:14px 0;overflow:hidden}.turn-header[data-v-4729e0cc]{color:#888;background:#ffffff08;border-bottom:1px solid #ffffff0d;align-items:center;gap:8px;padding:8px 14px;font-size:11px;display:flex}.turn-badge[data-v-4729e0cc]{letter-spacing:.3px;border-radius:3px;padding:2px 8px;font-size:11px;font-weight:700}.turn-badge-user[data-v-4729e0cc]{color:#ce93d8;background:#ce93d826}.turn-badge-agent[data-v-4729e0cc]{color:#7986cb;background:#7986cb26}.turn-badge-system[data-v-4729e0cc]{color:#bdbdbd;background:#75757533;font-style:italic}.turn-badge-session[data-v-4729e0cc]{color:#9e9e9e;background:#61616133}.turn-time[data-v-4729e0cc]{color:#666;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px}.turn-time-arrow[data-v-4729e0cc]{opacity:.7;margin:0 -2px}.turn-time-updated[data-v-4729e0cc]{color:#8891a3}.turn-actions[data-v-4729e0cc]{color:#777;font-size:11px}.turn-body[data-v-4729e0cc]{flex-direction:column;gap:12px;min-width:0;padding:14px 18px;display:flex}.turn-body[data-v-4729e0cc]>*{min-width:0;max-width:100%}.turn-body[data-v-4729e0cc] .tool-row+.tool-row{margin-top:-8px}.turn-scroll-top[data-v-4729e0cc]{justify-content:flex-start;padding:0 8px 6px;display:flex}.turn-scroll-top-btn[data-v-4729e0cc]{opacity:.5;transition:opacity .15s}.turn-scroll-top-btn[data-v-4729e0cc]:hover{opacity:1}.activity-feed-wrap[data-v-2cb1aa26]{width:100%;height:100%;position:relative}.activity-feed-scroll[data-v-2cb1aa26]{width:100%;height:100%}.activity-feed-nav-cluster[data-v-2cb1aa26]{z-index:2;align-items:center;gap:8px;display:flex;position:absolute;bottom:14px;right:14px}.activity-feed-nav-btn[data-v-2cb1aa26]{opacity:.8;transition:opacity .12s}.activity-feed-nav-btn[data-v-2cb1aa26]:hover{opacity:1}.content-origin-marker[data-v-2cb1aa26]{pointer-events:none;width:0;height:0;margin:0;padding:0}.activity-feed-scroll[data-v-2cb1aa26] .q-scrollarea__content{max-width:100%;overflow-x:hidden}.activity-feed-switching[data-v-2cb1aa26]{justify-content:center;align-items:center;width:100%;height:100%;display:flex}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{F as e,b as t}from"./QIcon-BJuyqdsT.js";import{C as n,w as r}from"./notifications-
|
|
1
|
+
import{F as e,b as t}from"./QIcon-BJuyqdsT.js";import{C as n,w as r}from"./notifications-OnPq4FrH.js";function i(e){if(e===!1)return 0;if(e===!0||e===void 0)return 1;let t=parseInt(e,10);return isNaN(t)?0:t}var a=e({name:`close-popup`,beforeMount(e,{value:a}){let o={depth:i(a),handler(t){o.depth!==0&&setTimeout(()=>{let i=r(e);i!==void 0&&n(i,t,o.depth)})},handlerKey(e){t(e,13)===!0&&o.handler(e)}};e.__qclosepopup=o,e.addEventListener(`click`,o.handler),e.addEventListener(`keyup`,o.handlerKey)},updated(e,{value:t,oldValue:n}){t!==n&&(e.__qclosepopup.depth=i(t))},beforeUnmount(e){let t=e.__qclosepopup;e.removeEventListener(`click`,t.handler),e.removeEventListener(`keyup`,t.handlerKey),delete e.__qclosepopup}});export{a as t};
|