@loicngr/kobo 2.1.24 → 2.1.26
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/AGENTS.md +39 -0
- package/CHANGELOG.md +8 -0
- package/CONFIGURATION.md +107 -0
- package/README.md +2 -1
- package/dist/server/routes/usage.js +24 -0
- package/dist/server/routes/workspaces.js +41 -7
- package/dist/server/services/agent/engines/claude-code/engine.js +2 -0
- package/dist/server/services/agent/engines/claude-code/progress-reporting-hook.js +99 -0
- package/dist/server/services/forge/github/provider.js +4 -2
- package/dist/server/services/forge/types.js +0 -1
- package/dist/server/services/provider-accounts-service.js +202 -0
- package/dist/server/services/usage/poller.js +44 -3
- package/dist/server/utils/git-ops.js +29 -20
- package/dist/shared/forge-merge.js +5 -0
- package/dist/shared/progress-bar-prompts.js +1 -1
- package/dist/shared/provider-accounts.js +1 -0
- package/package.json +1 -1
- package/src/client/dist/pwa/assets/{ActivityFeed-BYspOKKg.js → ActivityFeed-DfYrVNEh.js} +1 -1
- package/src/client/dist/pwa/assets/{AutoLoopFinalReviewSettings-DXX3CqrY.js → AutoLoopFinalReviewSettings-DOr41E2Y.js} +1 -1
- package/src/client/dist/pwa/assets/{ChangelogPage-DKkI5IU-.js → ChangelogPage-DOCgZMpn.js} +1 -1
- package/src/client/dist/pwa/assets/{ComparisonPanel-Cw5Dkan0.js → ComparisonPanel-b5nTBjK6.js} +1 -1
- package/src/client/dist/pwa/assets/{CreatePage-B7PLFOH6.js → CreatePage-B7VPHEqm.js} +1 -1
- package/src/client/dist/pwa/assets/{DashboardPage-Dw8nfkYR.js → DashboardPage-dBpJaQSb.js} +1 -1
- package/src/client/dist/pwa/assets/DiffViewer-BLQz2Qyx.js +8 -0
- package/src/client/dist/pwa/assets/{DiffViewer-DEPOa3D7.css → DiffViewer-XzCvEKLJ.css} +1 -1
- package/src/client/dist/pwa/assets/{DocumentsPanel-CH0KzdJV.js → DocumentsPanel-AqLx0MzB.js} +1 -1
- package/src/client/dist/pwa/assets/{DrawerToggleButton-CZVpU8HH.js → DrawerToggleButton-BLWaFgh0.js} +1 -1
- package/src/client/dist/pwa/assets/GitPanel-Ba7ltCsM.js +3 -0
- package/src/client/dist/pwa/assets/{GitPanel-CNFtj6k0.css → GitPanel-CRaLJzjc.css} +1 -1
- package/src/client/dist/pwa/assets/{HealthPage-DnPp8GSx.js → HealthPage-DeryVLyz.js} +1 -1
- package/src/client/dist/pwa/assets/{MainLayout-1PaKfzdy.js → MainLayout-B2XvjdWi.js} +2 -2
- package/src/client/dist/pwa/assets/{MemoryPanel-BarliK2r.js → MemoryPanel-B34DENtz.js} +1 -1
- package/src/client/dist/pwa/assets/{MemoryProposalList-BtVjVPp7.js → MemoryProposalList-BpN_OU8J.js} +1 -1
- package/src/client/dist/pwa/assets/{QBtnDropdown-Rzurb7nO.js → QBtnDropdown-BPcK_rVs.js} +1 -1
- package/src/client/dist/pwa/assets/{QExpansionItem-CaKEBcyx.js → QExpansionItem-CpwQ8L_F.js} +1 -1
- package/src/client/dist/pwa/assets/{QScrollArea-hrsAyyJf.js → QScrollArea-BkNSVl7s.js} +1 -1
- package/src/client/dist/pwa/assets/{QSelect-Dr7rAt6u.js → QSelect-DrLpbvcr.js} +1 -1
- package/src/client/dist/pwa/assets/{QTooltip-CNMsXTmD.js → QTooltip-Dp8fitHV.js} +1 -1
- package/src/client/dist/pwa/assets/{SchedulePanel-nDw2eZ9K.js → SchedulePanel-Ck8LKDCa.js} +1 -1
- package/src/client/dist/pwa/assets/{SearchPage-BXJ6iVt1.js → SearchPage-BAUZg1zq.js} +1 -1
- package/src/client/dist/pwa/assets/{SettingsPage-SHpE2q9Z.js → SettingsPage-Cj6kSVT5.js} +1 -1
- package/src/client/dist/pwa/assets/{SplitWorkspacePage-tfZ1kAdZ.js → SplitWorkspacePage-CH8OHmtn.js} +1 -1
- package/src/client/dist/pwa/assets/{TerminalPanel-Cw8R7lAw.js → TerminalPanel-CBmZ0IzQ.js} +1 -1
- package/src/client/dist/pwa/assets/{ToolCallItem-DEKhFJEv.js → ToolCallItem-CLtGTV6w.js} +1 -1
- package/src/client/dist/pwa/assets/{TouchPan-DybGzRRK.js → TouchPan-9SH2dx6m.js} +1 -1
- package/src/client/dist/pwa/assets/{TourReplayButton-BNdlAZUR.js → TourReplayButton-Dw4sGf9B.js} +1 -1
- package/src/client/dist/pwa/assets/{WorkspaceAttentionLabels-B0H9omcK.js → WorkspaceAttentionLabels-wd_sObJa.js} +1 -1
- package/src/client/dist/pwa/assets/WorkspacePage-BEBwwr81.css +1 -0
- package/src/client/dist/pwa/assets/WorkspacePage-D4ODPOG-.js +4 -0
- package/src/client/dist/pwa/assets/{browser-DUTZhU-w.js → browser-CC4W8r76.js} +1 -1
- package/src/client/dist/pwa/assets/{build-path-tree-ZThcsIN5.js → build-path-tree-BBuyB-my.js} +1 -1
- package/src/client/dist/pwa/assets/{custom-sounds-CquHn2gw.js → custom-sounds-BbPNRzAs.js} +1 -1
- package/src/client/dist/pwa/assets/{de-B3H0T-ft.js → de-D9VzPDGF.js} +2 -2
- package/src/client/dist/pwa/assets/{editor.api-pSvhgban.js → editor.api-BwfxvQ88.js} +1 -1
- package/src/client/dist/pwa/assets/{efforts-DJaFsLgd.js → efforts-B3I7w5bs.js} +1 -1
- package/src/client/dist/pwa/assets/{es-B4lACW6k.js → es-3R4MJuTt.js} +2 -2
- package/src/client/dist/pwa/assets/{expand-template-C5D_p5eV.js → expand-template-Ci9UjnxZ.js} +1 -1
- package/src/client/dist/pwa/assets/{format-DRfnkeRP.js → format-CJIzi3Vf.js} +1 -1
- package/src/client/dist/pwa/assets/{formatters-Cog2icjt.js → formatters-DQ8cP7nO.js} +1 -1
- package/src/client/dist/pwa/assets/{fr-3uNi02Jz.js → fr-DXwDVnJ4.js} +2 -2
- package/src/client/dist/pwa/assets/{freemarker2-W-OLsqOk.js → freemarker2-DbpVO-cL.js} +1 -1
- package/src/client/dist/pwa/assets/{handlebars-Kt5RbWuO.js → handlebars-BHve0PpA.js} +1 -1
- package/src/client/dist/pwa/assets/{html-D5VKPBbB.js → html-BhUkdFPz.js} +1 -1
- package/src/client/dist/pwa/assets/i18n-CGLQAADf.js +1 -0
- package/src/client/dist/pwa/assets/{index-BZwhT2-I.js → index-CNcXBpzz.js} +3 -3
- package/src/client/dist/pwa/assets/{it-DtFWyLHb.js → it-T9AjnG42.js} +2 -2
- package/src/client/dist/pwa/assets/{javascript-DBjx8Bg2.js → javascript-BLAorPa3.js} +1 -1
- package/src/client/dist/pwa/assets/{liquid-DYT4a7D7.js → liquid-CJGF-h-f.js} +1 -1
- package/src/client/dist/pwa/assets/{mdx-9L1kysEY.js → mdx-Cm0oNz_l.js} +1 -1
- package/src/client/dist/pwa/assets/{monaco-contributions-DAme5TZS.js → monaco-contributions-nBg6wf05.js} +1 -1
- package/src/client/dist/pwa/assets/{monaco.contribution-C58k7TPw.js → monaco.contribution-hr9s26Ud.js} +2 -2
- package/src/client/dist/pwa/assets/{network-auth-BDUlgV-U.js → network-auth-C850jGfI.js} +1 -1
- package/src/client/dist/pwa/assets/{notify-theme-DrQB-mrb.js → notify-theme-EcbxuH_8.js} +1 -1
- package/src/client/dist/pwa/assets/{project-color-BlV5PUUW.js → project-color-vDuTaTJn.js} +1 -1
- package/src/client/dist/pwa/assets/{python-DJIlKr-Y.js → python-BEjbzFAQ.js} +1 -1
- package/src/client/dist/pwa/assets/{razor-CC3uqdaH.js → razor-BJPT7Wxx.js} +1 -1
- package/src/client/dist/pwa/assets/{typescript-BnnkT9oE.js → typescript-DPqM46Ef.js} +1 -1
- package/src/client/dist/pwa/assets/{use-search-index-status-CExdHIar.js → use-search-index-status-BwwrB410.js} +1 -1
- package/src/client/dist/pwa/assets/{use-tours-DOUjqO2f.js → use-tours-B0KtCS9w.js} +1 -1
- package/src/client/dist/pwa/assets/{use-worktree-restore-zIOYNIcb.js → use-worktree-restore-tzd2FESU.js} +1 -1
- package/src/client/dist/pwa/assets/{workspace-templates-DXJG6flv.js → workspace-templates-CubzsZUU.js} +1 -1
- package/src/client/dist/pwa/assets/{xml-DJtVmsJT.js → xml-C6SVzw5_.js} +1 -1
- package/src/client/dist/pwa/assets/{yaml-Dwuw8FcP.js → yaml-OpCqnv4g.js} +1 -1
- package/src/client/dist/pwa/index.html +1 -1
- package/src/client/dist/pwa/sw.js +1 -1
- package/src/mcp-server/README.md +8 -0
- package/src/client/dist/pwa/assets/DiffViewer-DFlDwkmd.js +0 -8
- package/src/client/dist/pwa/assets/GitPanel-DjKL30gM.js +0 -3
- package/src/client/dist/pwa/assets/WorkspacePage-B-82Rw9T.css +0 -1
- package/src/client/dist/pwa/assets/WorkspacePage-tWGXnmrz.js +0 -4
- package/src/client/dist/pwa/assets/i18n-CEzCwMir.js +0 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { withUsageAccountSwitch } from './usage/poller.js';
|
|
5
|
+
const ERRORS = {
|
|
6
|
+
accounts_unknown_provider: [404, 'Unknown account provider.'],
|
|
7
|
+
accounts_invalid_account: [400, 'Invalid account selection.'],
|
|
8
|
+
accounts_not_found: [404, 'Account is no longer available.'],
|
|
9
|
+
accounts_disabled: [409, 'Account is disabled.'],
|
|
10
|
+
accounts_unavailable: [503, 'Account switching is unavailable.'],
|
|
11
|
+
accounts_unsupported_environment: [409, 'Account switching is unsupported in this runtime environment.'],
|
|
12
|
+
accounts_command_failed: [502, 'Account operation failed.'],
|
|
13
|
+
accounts_busy: [429, 'Account operations are busy.'],
|
|
14
|
+
};
|
|
15
|
+
export class ProviderAccountsError extends Error {
|
|
16
|
+
code;
|
|
17
|
+
status;
|
|
18
|
+
constructor(code) {
|
|
19
|
+
super(ERRORS[code][1]);
|
|
20
|
+
this.code = code;
|
|
21
|
+
this.status = ERRORS[code][0];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// ccswap shares backup/config state across providers. Keep validation and the
|
|
25
|
+
// post-switch read in the same queue, not just the mutating child process.
|
|
26
|
+
let operations = Promise.resolve();
|
|
27
|
+
let queued = 0;
|
|
28
|
+
function serialize(operation) {
|
|
29
|
+
if (queued >= 32)
|
|
30
|
+
return Promise.reject(new ProviderAccountsError('accounts_busy'));
|
|
31
|
+
queued++;
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
let expired = false;
|
|
34
|
+
const timeout = setTimeout(() => {
|
|
35
|
+
expired = true;
|
|
36
|
+
reject(new ProviderAccountsError('accounts_busy'));
|
|
37
|
+
}, 5_000);
|
|
38
|
+
const result = operations
|
|
39
|
+
.then(async () => {
|
|
40
|
+
clearTimeout(timeout);
|
|
41
|
+
// The caller has already received busy; never perform a delayed switch.
|
|
42
|
+
if (expired)
|
|
43
|
+
return;
|
|
44
|
+
resolve(await operation());
|
|
45
|
+
})
|
|
46
|
+
.catch(reject);
|
|
47
|
+
operations = result.finally(() => {
|
|
48
|
+
queued--;
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function providerId(value) {
|
|
53
|
+
if (value !== 'claude-code' && value !== 'codex')
|
|
54
|
+
throw new ProviderAccountsError('accounts_unknown_provider');
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
function assertRuntime(provider) {
|
|
58
|
+
if (provider !== 'claude-code')
|
|
59
|
+
return;
|
|
60
|
+
// ccswap 0.37 writes the regular active store, not Claude's separate secure
|
|
61
|
+
// store override or macOS's hashed Keychain service for ANY nonempty
|
|
62
|
+
// CLAUDE_CONFIG_DIR, even when it explicitly names the default directory.
|
|
63
|
+
const config = process.env.CLAUDE_CONFIG_DIR;
|
|
64
|
+
if (process.env.CLAUDE_SECURESTORAGE_CONFIG_DIR !== undefined || (process.platform === 'darwin' && config)) {
|
|
65
|
+
throw new ProviderAccountsError('accounts_unsupported_environment');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function run(args, allowEmpty = false) {
|
|
69
|
+
return new Promise((resolve, reject) => {
|
|
70
|
+
// Inherit the actual server/container identity and homes. Never invoke a
|
|
71
|
+
// shell, docker, SSH, or resolve a binary relative to a workspace checkout.
|
|
72
|
+
execFile('ccswap', args, {
|
|
73
|
+
encoding: 'utf8',
|
|
74
|
+
shell: false,
|
|
75
|
+
killSignal: 'SIGKILL',
|
|
76
|
+
timeout: 30_000,
|
|
77
|
+
maxBuffer: 1024 * 1024,
|
|
78
|
+
cwd: os.homedir(),
|
|
79
|
+
env: process.env,
|
|
80
|
+
}, (error, stdout) => {
|
|
81
|
+
if (error) {
|
|
82
|
+
reject(new ProviderAccountsError(error.code === 'ENOENT' ? 'accounts_unavailable' : 'accounts_command_failed'));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (allowEmpty && !stdout.trim()) {
|
|
86
|
+
resolve(null);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
resolve(JSON.parse(stdout));
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
reject(new ProviderAccountsError('accounts_command_failed'));
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function object(value) {
|
|
99
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
100
|
+
}
|
|
101
|
+
function display(value) {
|
|
102
|
+
return typeof value === 'string'
|
|
103
|
+
? value
|
|
104
|
+
.replace(/[\p{Cc}\p{Cf}]/gu, '')
|
|
105
|
+
.trim()
|
|
106
|
+
.slice(0, 320)
|
|
107
|
+
: '';
|
|
108
|
+
}
|
|
109
|
+
async function list(provider) {
|
|
110
|
+
const home = provider === 'codex' ? process.env.CODEX_HOME : process.env.CLAUDE_CONFIG_DIR;
|
|
111
|
+
// Agent subprocesses run in their worktrees, the quota provider in the server
|
|
112
|
+
// cwd, and ccswap in HOME. Relative (including empty) overrides cannot name
|
|
113
|
+
// the same credential store reliably. Require an absolute path or no override.
|
|
114
|
+
if (home !== undefined && !path.isAbsolute(home)) {
|
|
115
|
+
throw new ProviderAccountsError('accounts_unsupported_environment');
|
|
116
|
+
}
|
|
117
|
+
const raw = await run(provider === 'codex' ? ['codex', 'list', '--json'] : ['list', '--provider', 'claude', '--json']);
|
|
118
|
+
if (!object(raw) ||
|
|
119
|
+
!Array.isArray(raw.accounts) ||
|
|
120
|
+
raw.accounts.length > 1000 ||
|
|
121
|
+
(provider === 'claude-code' ? raw.schemaVersion !== 1 : raw.provider !== 'codex')) {
|
|
122
|
+
throw new ProviderAccountsError('accounts_command_failed');
|
|
123
|
+
}
|
|
124
|
+
const seen = new Set();
|
|
125
|
+
const accounts = raw.accounts.map((row) => {
|
|
126
|
+
if (!object(row) ||
|
|
127
|
+
typeof row.number !== 'number' ||
|
|
128
|
+
!Number.isSafeInteger(row.number) ||
|
|
129
|
+
row.number < 1 ||
|
|
130
|
+
typeof row.active !== 'boolean' ||
|
|
131
|
+
(row.disabled !== undefined && typeof row.disabled !== 'boolean')) {
|
|
132
|
+
throw new ProviderAccountsError('accounts_command_failed');
|
|
133
|
+
}
|
|
134
|
+
const id = String(row.number);
|
|
135
|
+
if (seen.has(id))
|
|
136
|
+
throw new ProviderAccountsError('accounts_command_failed');
|
|
137
|
+
seen.add(id);
|
|
138
|
+
return {
|
|
139
|
+
id,
|
|
140
|
+
email: display(row.email),
|
|
141
|
+
label: display(provider === 'codex' ? row.label : row.alias) || display(row.organizationName),
|
|
142
|
+
active: row.active,
|
|
143
|
+
disabled: row.disabled === true,
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
return { available: true, accounts };
|
|
147
|
+
}
|
|
148
|
+
export async function listProviderAccounts(value) {
|
|
149
|
+
const provider = providerId(value);
|
|
150
|
+
return serialize(async () => {
|
|
151
|
+
try {
|
|
152
|
+
return await list(provider);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
if (error instanceof ProviderAccountsError && error.code === 'accounts_unavailable')
|
|
156
|
+
return { available: false, accounts: [] };
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
export function validateAccountId(accountId) {
|
|
162
|
+
if (typeof accountId !== 'string' || !/^[1-9]\d{0,15}$/.test(accountId) || !Number.isSafeInteger(Number(accountId))) {
|
|
163
|
+
throw new ProviderAccountsError('accounts_invalid_account');
|
|
164
|
+
}
|
|
165
|
+
return accountId;
|
|
166
|
+
}
|
|
167
|
+
export async function switchProviderAccount(value, accountId) {
|
|
168
|
+
const provider = providerId(value);
|
|
169
|
+
const selectedId = validateAccountId(accountId);
|
|
170
|
+
return serialize(async () => {
|
|
171
|
+
assertRuntime(provider);
|
|
172
|
+
const current = await list(provider);
|
|
173
|
+
const selected = current.accounts.find((account) => account.id === selectedId);
|
|
174
|
+
if (!selected)
|
|
175
|
+
throw new ProviderAccountsError('accounts_not_found');
|
|
176
|
+
if (selected.disabled)
|
|
177
|
+
throw new ProviderAccountsError('accounts_disabled');
|
|
178
|
+
const change = async () => {
|
|
179
|
+
const raw = await run(provider === 'codex' ? ['codex', 'switch', selectedId, '--json'] : ['switch', selectedId, '--json'], provider === 'codex');
|
|
180
|
+
// ccswap 0.37's Codex dispatcher discards the switch return value.
|
|
181
|
+
// Empty stdout is accepted only here; the following list must confirm it.
|
|
182
|
+
if (provider === 'codex' && raw === null)
|
|
183
|
+
return;
|
|
184
|
+
if (!object(raw) ||
|
|
185
|
+
typeof raw.switched !== 'boolean' ||
|
|
186
|
+
!object(raw.to) ||
|
|
187
|
+
raw.to.number !== Number(selectedId) ||
|
|
188
|
+
(provider === 'claude-code' && raw.schemaVersion !== 1)) {
|
|
189
|
+
throw new ProviderAccountsError('accounts_command_failed');
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
if (provider === 'claude-code')
|
|
193
|
+
await withUsageAccountSwitch(provider, change);
|
|
194
|
+
else
|
|
195
|
+
await change();
|
|
196
|
+
const updated = await list(provider);
|
|
197
|
+
if (!updated.accounts.some((account) => account.id === selectedId && account.active)) {
|
|
198
|
+
throw new ProviderAccountsError('accounts_command_failed');
|
|
199
|
+
}
|
|
200
|
+
return updated;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
@@ -8,17 +8,23 @@ export const POLL_INTERVAL_MS = 5 * 60_000;
|
|
|
8
8
|
const DEFAULT_PROVIDERS = [createClaudeCodeProvider()];
|
|
9
9
|
let providers = DEFAULT_PROVIDERS;
|
|
10
10
|
let intervalHandle = null;
|
|
11
|
+
const generations = new Map();
|
|
12
|
+
const switchingProviders = new Set();
|
|
13
|
+
const latest = new Map();
|
|
11
14
|
function persistAndBroadcast(snap) {
|
|
12
15
|
upsertUsageSnapshot(snap);
|
|
16
|
+
latest.set(snap.providerId, snap);
|
|
13
17
|
broadcastAll('usage:snapshot', { providerId: snap.providerId, snapshot: snap });
|
|
14
18
|
}
|
|
15
19
|
async function tick() {
|
|
16
20
|
for (const provider of providers) {
|
|
17
21
|
try {
|
|
18
|
-
|
|
22
|
+
const generation = generations.get(provider.id) ?? 0;
|
|
23
|
+
if (switchingProviders.has(provider.id) || !(await provider.isAvailable()))
|
|
19
24
|
continue;
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
if (generation !== (generations.get(provider.id) ?? 0))
|
|
26
|
+
continue;
|
|
27
|
+
await refreshNow(provider.id);
|
|
22
28
|
}
|
|
23
29
|
catch (err) {
|
|
24
30
|
console.error('[usage-poller] tick failed for provider', provider.id, err);
|
|
@@ -45,11 +51,46 @@ export async function refreshNow(providerId) {
|
|
|
45
51
|
const provider = providers.find((p) => p.id === providerId);
|
|
46
52
|
if (!provider)
|
|
47
53
|
return null;
|
|
54
|
+
if (switchingProviders.has(providerId))
|
|
55
|
+
return latest.get(providerId) ?? null;
|
|
56
|
+
const generation = generations.get(providerId) ?? 0;
|
|
48
57
|
const snap = await provider.fetchSnapshot();
|
|
58
|
+
// A request started with old credentials must not restore them in SQLite,
|
|
59
|
+
// WebSocket clients, or its own delayed HTTP refresh response.
|
|
60
|
+
if (generation !== (generations.get(providerId) ?? 0))
|
|
61
|
+
return latest.get(providerId) ?? null;
|
|
49
62
|
persistAndBroadcast(snap);
|
|
50
63
|
return snap;
|
|
51
64
|
}
|
|
65
|
+
/** Invalidate before changing credentials, including uncertain CLI failures. */
|
|
66
|
+
export async function withUsageAccountSwitch(providerId, operation) {
|
|
67
|
+
generations.set(providerId, (generations.get(providerId) ?? 0) + 1);
|
|
68
|
+
switchingProviders.add(providerId);
|
|
69
|
+
try {
|
|
70
|
+
persistAndBroadcast({
|
|
71
|
+
providerId,
|
|
72
|
+
status: 'error',
|
|
73
|
+
buckets: [],
|
|
74
|
+
fetchedAt: new Date().toISOString(),
|
|
75
|
+
errorMessage: 'Account credentials are changing. Refresh usage after the switch.',
|
|
76
|
+
});
|
|
77
|
+
return await operation();
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
switchingProviders.delete(providerId);
|
|
81
|
+
try {
|
|
82
|
+
await refreshNow(providerId);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Quota refresh failure must not turn a successful account mutation into
|
|
86
|
+
// a failed switch or replace the original command error. Keep empty data.
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
52
90
|
// Test seam — pass `null` to restore the default provider list.
|
|
53
91
|
export function _setProvidersForTest(list) {
|
|
54
92
|
providers = list ?? DEFAULT_PROVIDERS;
|
|
93
|
+
generations.clear();
|
|
94
|
+
switchingProviders.clear();
|
|
95
|
+
latest.clear();
|
|
55
96
|
}
|
|
@@ -1045,27 +1045,27 @@ export function getChangedFiles(repoPath, base, includeUntracked = false) {
|
|
|
1045
1045
|
}
|
|
1046
1046
|
return files;
|
|
1047
1047
|
}
|
|
1048
|
-
/**
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
* included: uncommitted edits aren't about to be pushed. Returns an empty
|
|
1052
|
-
* list if there is no remote tracking branch yet.
|
|
1053
|
-
*/
|
|
1054
|
-
export function getUnpushedChangedFiles(repoPath, branchName, remote = 'origin') {
|
|
1055
|
-
const remoteRef = `${remote}/${branchName}`;
|
|
1056
|
-
// Bail out cleanly if the remote branch doesn't exist (branch never pushed).
|
|
1048
|
+
/** Local changes relative to the pushed branch, including staged and working-tree edits. */
|
|
1049
|
+
export function getUnpushedChangedFiles(repoPath, branchName, remote = 'origin', sourceBranch = 'HEAD') {
|
|
1050
|
+
let ref = `${remote}/${branchName}`;
|
|
1057
1051
|
try {
|
|
1058
|
-
git(repoPath, ['rev-parse', '--verify',
|
|
1052
|
+
git(repoPath, ['rev-parse', '--verify', ref]);
|
|
1059
1053
|
}
|
|
1060
1054
|
catch {
|
|
1061
|
-
|
|
1062
|
-
}
|
|
1063
|
-
const files = [];
|
|
1064
|
-
try {
|
|
1065
|
-
files.push(...parseNameStatus(git(repoPath, ['diff', '--name-status', '-z', `${remoteRef}..HEAD`])));
|
|
1055
|
+
ref = resolveBase(repoPath, sourceBranch);
|
|
1066
1056
|
}
|
|
1067
|
-
|
|
1068
|
-
|
|
1057
|
+
const files = parseNameStatus(git(repoPath, ['diff', '--name-status', '-z', ref, '--']));
|
|
1058
|
+
const untracked = git(repoPath, ['ls-files', '--others', '--exclude-standard', '-z']);
|
|
1059
|
+
return withUntrackedFiles(files, untracked);
|
|
1060
|
+
}
|
|
1061
|
+
/** Preserve NUL-delimited filenames and deduplicate tracked/untracked transitions. */
|
|
1062
|
+
function withUntrackedFiles(files, output) {
|
|
1063
|
+
const seen = new Set(files.map((file) => file.path));
|
|
1064
|
+
for (const filePath of output.split('\0')) {
|
|
1065
|
+
if (filePath && !seen.has(filePath)) {
|
|
1066
|
+
files.push({ path: filePath, status: 'untracked' });
|
|
1067
|
+
seen.add(filePath);
|
|
1068
|
+
}
|
|
1069
1069
|
}
|
|
1070
1070
|
return files;
|
|
1071
1071
|
}
|
|
@@ -1555,16 +1555,25 @@ export async function getChangedFilesBetweenAsync(repoPath, fromRef, toRef) {
|
|
|
1555
1555
|
return [];
|
|
1556
1556
|
}
|
|
1557
1557
|
}
|
|
1558
|
-
|
|
1558
|
+
/** Use the source branch until this working branch has been pushed for the first time. */
|
|
1559
|
+
export async function resolveUnpushedBaseAsync(repoPath, branchName, sourceBranch = 'HEAD', remote = 'origin') {
|
|
1559
1560
|
const ref = `${remote}/${branchName}`;
|
|
1560
1561
|
try {
|
|
1561
1562
|
await gitAsync(repoPath, ['rev-parse', '--verify', ref]);
|
|
1562
|
-
return
|
|
1563
|
+
return ref;
|
|
1563
1564
|
}
|
|
1564
1565
|
catch {
|
|
1565
|
-
return
|
|
1566
|
+
return resolveBaseAsync(repoPath, sourceBranch);
|
|
1566
1567
|
}
|
|
1567
1568
|
}
|
|
1569
|
+
export async function getUnpushedChangedFilesAsync(repoPath, branchName, remote = 'origin', sourceBranch = 'HEAD') {
|
|
1570
|
+
const ref = await resolveUnpushedBaseAsync(repoPath, branchName, sourceBranch, remote);
|
|
1571
|
+
const [changes, untracked] = await Promise.all([
|
|
1572
|
+
gitAsync(repoPath, ['diff', '--name-status', '-z', ref, '--']),
|
|
1573
|
+
gitAsync(repoPath, ['ls-files', '--others', '--exclude-standard', '-z']),
|
|
1574
|
+
]);
|
|
1575
|
+
return withUntrackedFiles(parseNameStatus(changes), untracked);
|
|
1576
|
+
}
|
|
1568
1577
|
export async function getChangedFilesAsync(repoPath, base, includeUntracked = false) {
|
|
1569
1578
|
const ref = await resolveBaseAsync(repoPath, base);
|
|
1570
1579
|
const [committed, working] = await Promise.allSettled([
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Explicit PR merge strategies. Availability is declared by each forge provider. */
|
|
2
|
+
export const MERGE_METHODS = ['merge', 'squash', 'rebase'];
|
|
3
|
+
export function isMergeMethod(value) {
|
|
4
|
+
return typeof value === 'string' && MERGE_METHODS.some((method) => method === value);
|
|
5
|
+
}
|
|
@@ -4,7 +4,7 @@ export const PROGRESS_BAR_PROMPT = `<kobo-progress-reporting>
|
|
|
4
4
|
${PROGRESS_BAR_PLAN_EXCEPTION}
|
|
5
5
|
For each long-running activity (tests, audits, builds or delegated work), follow this reporting lifecycle:
|
|
6
6
|
1. Call create_progress_bar with a clear label, current step and stable activity_key. Save its returned id and sequence; creating a bar is only the start of reporting.
|
|
7
|
-
2. Call update_progress_bar with that id and an increasing sequence: update the same bar at each actual phase change or meaningful completed milestone, including during a long phase. Even without a measured percentage, report the current step; omit both current and total for step-only updates. Use measured numbers only when known. Never invent percentages, poll, send unchanged updates or start timer-driven reporting loops; follow tool retry guidance.
|
|
7
|
+
2. Call update_progress_bar with that id and an increasing sequence: update the same bar at each actual phase change or meaningful completed milestone, including during a long phase. Even without a measured percentage, report the current step; omit both current and total for step-only updates. Use measured numbers only when known: when tests report a total or your activity has a fixed checklist, provide current and total together and advance current only as those items actually finish. A step-only update changes the label, not the gauge; null numbers mean no percentage is available. Never invent percentages, poll, send unchanged updates or start timer-driven reporting loops; follow tool retry guidance.
|
|
8
8
|
3. Call finish_progress_bar on that id before your final report (or return to the parent) when the activity's succeeded/failed outcome is known. Do not declare ongoing background work finished merely because you are yielding control.
|
|
9
9
|
Pass this requirement to all subagents when delegating: each reports and finishes its own long activity through inherited Kōbō MCP tools; the parent must not duplicate it. If a custom subagent lacks these tools, the parent reports its observed milestones and outcome instead. Subagents must not schedule or replace workspace wakeups; the parent coordinates follow-up.
|
|
10
10
|
A dismissed bar stays hidden: continue without recreating it; dismissal is not cancellation. Reporting never substitutes for verification, and an interrupted reporter does not prove background work stopped. After resume, use new activity keys for new work; do not reopen finished activities.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loicngr/kobo",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.26",
|
|
4
4
|
"description": "Kōbō — local multi-workspace orchestrator for Claude Code and OpenAI Codex, with isolated Git worktrees, live review and optional automation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{M as e,S as t,dt as n,lt as r,p as i,pt as a,v as o}from"./reactivity.esm-bundler-DY1JkAEA.js";import{C as s,F as c,J as l,L as u,N as d,O as f,P as p,T as m,Y as h,_ as g,d as _,f as v,g as y,j as ee,k as b,l as x,p as S,r as C,u as w,y as T,z as te}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{$ as ne,K as re,M as E,f as ie,z as ae}from"./dom-BtYTvLeN.js";import{l as oe,t as D,u as se}from"./QBtn-BUSdPaf4.js";import{Kt as ce,O as le,Qt as ue,Ut as O,_t as de,at as fe,cn as pe,dn as k,j as me,m as he,mt as ge,pt as _e,st as ve,tn as A,v as ye}from"./index-BZwhT2-I.js";import{t as be}from"./QSpinnerDots-xdWyaE1i.js";import{t as xe}from"./QList-Cx1UfaUm.js";import{t as Se}from"./QMarkupTable-UhP7fVUp.js";import{c as j,l as M,s as N}from"./QSelect-Dr7rAt6u.js";import{t as P}from"./QItemSection-MdJ1_ZK7.js";import{t as Ce}from"./QExpansionItem-CaKEBcyx.js";import{a as F,c as we,r as I,t as L}from"./ToolCallItem-DEKhFJEv.js";import{t as Te}from"./QScrollArea-hrsAyyJf.js";import{a as R}from"./use-tours-DOUjqO2f.js";import{f as Ee,g as z,m as De,p as Oe,u as ke}from"./use-worktree-restore-zIOYNIcb.js";import{t as B}from"./QTooltip-CNMsXTmD.js";import{n as V}from"./render-chat-markdown-CafzCcmu.js";import{n as H}from"./WorkspacePage-tWGXnmrz.js";function Ae(e,t){return s(`div`,e,[s(`table`,{class:`q-table`},t)])}var je={list:xe,table:Se},U=[`list`,`table`,`__qtable`],Me=ae({name:`QVirtualScroll`,props:{...M,type:{type:String,default:`list`,validator:e=>U.includes(e)},items:{type:Array,default:()=>[]},itemsFn:Function,itemsSize:Number,scrollTarget:k},setup(e,{slots:n,attrs:r}){let i,a=t(null),o=x(()=>e.itemsSize>=0&&e.itemsFn!==void 0?Number.parseInt(e.itemsSize,10):Array.isArray(e.items)?e.items.length:0),{virtualScrollSliceRange:c,localResetVirtualScroll:u,padVirtualScroll:f,onVirtualScrollEvt:m}=j({virtualScrollLength:o,getVirtualScrollTarget:y,getVirtualScrollEl:v}),h=x(()=>{if(o.value===0)return[];let t=(e,t)=>({index:c.value.from+t,item:e});return e.itemsFn===void 0?e.items.slice(c.value.from,c.value.to).map(t):e.itemsFn(c.value.from,c.value.to-c.value.from).map(t)}),g=x(()=>`q-virtual-scroll q-virtual-scroll`+(e.virtualScrollHorizontal?`--horizontal`:`--vertical`)+(e.scrollTarget===void 0?` scroll`:``)),_=x(()=>e.scrollTarget===void 0?{tabindex:0}:{});l(o,()=>{u()}),l(()=>e.scrollTarget,()=>{C(),S()});function v(){let e=a.value;return e===null?null:e.$el||e}function y(){return i}function S(){let t=v();t!==null&&(i=pe(t,e.scrollTarget),i.addEventListener(`scroll`,m,E.passive))}function C(){i!==void 0&&(i.removeEventListener(`scroll`,m,E.passive),i=void 0)}function w(){let t=f(e.type===`list`?`div`:`tbody`,h.value.map(n.default));return n.before!==void 0&&(t=n.before().concat(t)),ie(n.after,t)}return u(),p(()=>{S()}),b(()=>{S()}),d(()=>{C()}),ee(()=>{C()}),()=>{if(n.default===void 0){console.error(`QVirtualScroll: default scoped slot is required for rendering`);return}return e.type===`__qtable`?Ae({ref:a,class:`q-table__middle `+g.value,tabindex:0},w()):s(je[e.type],{...r,ref:a,class:[r.class,g.value],..._.value},w)}}}),Ne=new Set([`setup`,`cleanup`,`archive`]);function Pe(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:Ne.has(e.sender)||le(e.sender)?`script`:`user`;case`session`:return`session`;default:return`agent`}}function Fe(e){let t=[],n=null,r=null;for(let i of e){let e=Pe(i),a=e===`session`||e===`system-prompt`,o=e===`script`&&i.type===`user`?`script:${i.sender}`:e===`user`&&i.type===`user`&&i.source?JSON.stringify([`mcp`,i.source.transport,i.source.clientName]):e;!n||r!==o||a?(n={speaker:e,ts:i.ts,items:[i]},r=o,t.push(n),a&&(n=null)):n.items.push(i)}return t}function W(e){switch(e.type){case`text`:return`text:${e.messageId}`;case`thinking`:return`thinking:${e.messageId}:${e.eventIds?.[0]??e.ts??``}`;case`tool`:return`tool:${e.toolCallId}`;case`session`:return`session:${e.kind}:${e.eventIds?.[0]??e.ts??``}`;case`user`:return`user:${e.eventIds?.[0]??`${e.sender}:${e.ts??``}`}`;case`error`:return`error:${e.eventIds?.[0]??`${e.category}:${e.ts??``}`}`}}function Ie(e){let t=e.items[0];return`${e.speaker}:${t?W(t):`empty`}`}function Le(e,t){let n=Math.min(t,e.length)-1;for(let t=n;t>=0;t--)if(e[t]?.speaker===`user`)return t;return-1}function Re(e,t,n){return new Promise(r=>{let i=!1,a=null,o=null,s=e=>{i||(i=!0,a!==null&&clearTimeout(a),a=null,o?.(),r(e))};if(o=l(e,e=>{t(e)&&s(!0)},{immediate:!0}),i){o();return}a=setTimeout(()=>s(!1),n)})}var ze={class:`agent-error-item`},Be={class:`agent-error-item__body`},Ve={class:`agent-error-item__title`},G={class:`agent-error-item__message`},He=R(T({__name:`AgentErrorItem`,props:{item:{}},setup(e){let t=e,{te:n}=ue(),r=x(()=>{let e=`agent.error.${t.item.category}`;return n(e)?e:`agent.error.other`});return(t,n)=>(u(),S(`div`,ze,[g(oe,{name:`error_outline`,size:`16px`,class:`agent-error-item__icon`}),w(`div`,Be,[w(`div`,Ve,a(t.$t(r.value)),1),w(`div`,G,a(e.item.message),1)])]))}}),[[`__scopeId`,`data-v-e98c3c02`]]),Ue={class:`text-caption text-kobo-3`},We=T({__name:`SessionEventItem`,props:{item:{}},setup(e){let t=e,n=x(()=>{switch(t.item.kind){case`started`:return`session.started`;case`ended`:return z(t.item.detail);case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,t)=>(u(),S(`span`,Ue,a(e.$t(n.value)),1))}}),K=new Map;function q(){for(let e of K.values())e.controller.abort(),e.blobUrl&&URL.revokeObjectURL(e.blobUrl);K.clear()}typeof window<`u`&&(window.addEventListener(`kobo:auth-token-changed`,q),window.addEventListener(`storage`,e=>{(e.key===`kobo:network-token`||e.key===null)&&q()}));function J(e){if(!/^\/api\/workspaces\/[^/]+\/images\/file\?path=/.test(e))throw Error(`Invalid workspace image URL`);let t=K.get(e);if(!t){let n=new AbortController,r={references:0,controller:n,ready:Promise.resolve(``)};r.ready=O(e,{signal:n.signal}).then(async e=>{if(!e.ok)throw await ce(e);let t=await e.blob();if(n.signal.aborted)throw new DOMException(`Aborted`,`AbortError`);return r.blobUrl=URL.createObjectURL(t),r.blobUrl}),t=r,K.set(e,t)}t.references++;let n=!1,r=t;return{ready:r.ready,release(){n||(n=!0,!(--r.references>0)&&(r.controller.abort(),r.blobUrl&&URL.revokeObjectURL(r.blobUrl),K.get(e)===r&&K.delete(e)))}}}function Ge(e,t){let n=o(``),r=o(0),a=()=>{r.value++},s=e=>{(e.key===`kobo:network-token`||e.key===null)&&a()};return window.addEventListener(`kobo:auth-token-changed`,a),window.addEventListener(`storage`,s),i(()=>{window.removeEventListener(`kobo:auth-token-changed`,a),window.removeEventListener(`storage`,s)}),l([e,r],([e],r,i)=>{let a=!0,o=[],s=document.createElement(`template`);s.innerHTML=e;for(let e of s.content.querySelectorAll(`img`)){let r=e.getAttribute(`src`)??``;if(e.removeAttribute(`data-kobo-image-url`),!/^\/api\/workspaces\/[^/]+\/images\/file\?path=/.test(r))continue;e.removeAttribute(`src`);let i=J(r);o.push(i),i.ready.then(t=>{a&&(e.setAttribute(`src`,t),e.setAttribute(`data-kobo-image-url`,r),n.value=s.innerHTML)}).catch(()=>{a&&(e.setAttribute(`title`,t()),n.value=s.innerHTML)})}n.value=s.innerHTML,i(()=>{a=!1;for(let e of o)e.release()})},{immediate:!0}),n}function Ke(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 qe=[`innerHTML`],Je=[`innerHTML`],Ye=[`src`],Y=R(T({__name:`UserMessageItem`,props:{item:{},workspaceId:{}},setup(t){let n=t,{t:r}=ue(),a=x(()=>n.item.sender===`system-prompt`),s=Ge(x(()=>{let e=Ke(n.item.content,n.workspaceId);return V(e)}),()=>r(`network.login.unreachable`)),c=o(null),d=o(!1),f;function p(){d.value=!1,c.value=null,f?.release(),f=void 0}l(d,e=>{e||p()}),l(()=>n.workspaceId,p);let m=e=>{(e.key===`kobo:network-token`||e.key===null)&&p()};window.addEventListener(`storage`,m),window.addEventListener(`kobo:auth-token-changed`,p),i(()=>{p(),window.removeEventListener(`kobo:auth-token-changed`,p),window.removeEventListener(`storage`,m)});function y(e){let t=e.target;if(t?.tagName!==`IMG`)return;let n=t;n.src&&(p(),n.dataset.koboImageUrl&&(f=J(n.dataset.koboImageUrl),f.ready.catch(p)),c.value=n.src,d.value=!0)}return(t,n)=>(u(),S(C,null,[a.value?(u(),_(Ce,{key:0,dense:``,"dense-toggle":``,label:t.$t(`chat.systemPrompt`),"header-class":`text-kobo-2 text-caption`},{default:h(()=>[w(`div`,{class:`q-py-xs markdown-message markdown-user-prompt`,innerHTML:e(s)},null,8,qe)]),_:1},8,[`label`])):(u(),S(`div`,{key:1,class:`markdown-message`,onClick:y},[w(`div`,{innerHTML:e(s)},null,8,Je)])),g(A,{modelValue:d.value,"onUpdate:modelValue":n[1]||=e=>d.value=e},{default:h(()=>[c.value?(u(),S(`img`,{key:0,src:c.value,alt:``,class:`image-lightbox-img`,onClick:n[0]||=e=>d.value=!1},null,8,Ye)):v(``,!0)]),_:1},8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-965e6297`]]),Xe=[`data-event-ids`],X={class:`turn-header`},Ze={key:0,class:`turn-time`},Qe={class:`turn-time turn-time-updated`},$e={key:2,class:`turn-actions`},et={class:`turn-body`},tt={class:`ellipsis`},nt={class:`q-px-sm q-pb-sm`},rt={key:0,class:`turn-scroll-top`},it=R(T({__name:`TurnCard`,props:{turn:{},workspaceId:{},highlighted:{type:Boolean}},emits:[`scrollTo`],setup(t,{emit:i}){let s=t,c=i,{t:l}=ue(),d=fe(),f=m(F),p=o(null);function ee(){let e=p.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;c(`scrollTo`,Math.max(0,n-8))}let b=x(()=>{switch(s.turn.speaker){case`user`:{let e=s.turn.items[0],t=e?.type===`user`?e.source:void 0;return{label:t?l(`chat.externalLlm`,{name:t.clientName}):l(`chat.you`),accent:`var(--kobo-turn-user)`,badgeClass:`turn-badge-user`}}case`agent`:return{label:l(`chat.agent`),accent:`var(--kobo-turn-agent)`,badgeClass:`turn-badge-agent`};case`system-prompt`:return{label:l(`chat.systemPrompt`),accent:`var(--kobo-text-3)`,badgeClass:`turn-badge-system`};case`session`:return{label:l(`chat.session`),accent:`var(--kobo-text-3)`,badgeClass:`turn-badge-session`};case`script`:{let e=s.turn.items[0],t=e?.type===`user`?e.sender:``;return{label:le(t)?l(`chat.hookScript`,{event:t.slice(5)}):l(t===`archive`?`chat.archiveScript`:t===`setup`?`chat.setupScript`:`chat.cleanupScript`),accent:`var(--kobo-success)`,badgeClass:`turn-badge-script`}}}});function T(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 re=x(()=>T(s.turn.ts)),E=x(()=>s.turn.items.flatMap(e=>e.eventIds??[]).join(` `)),ie=x(()=>{let e=s.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}),ae=x(()=>{let e=s.turn.ts,t=ie.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?``:T(t,r-n<6e4)}),se=x(()=>ae.value!==``);function ce(e){return we(e.origin,Object.values(d.subagents[s.workspaceId]??{}),e.type===`tool`?e.toolCallId:void 0)}function O(e){return e||l(`chat.subagentActivity`)}function de(e){return(e.type===`text`||e.type===`thinking`||e.type===`tool`)&&e.origin?.kind===`subagent`}let pe=x(()=>{let e=[],t=new Map;for(let n of s.turn.items){if(!de(n)){e.push({type:`item`,key:W(n),item:n});continue}let r=ce(n),i=r?.toolUseId??n.origin?.toolCallId??n.origin?.threadId??W(n),a=t.get(i);if(a){a.items.push(n);continue}let o={type:`subagent`,key:`subagent:${W(n)}`,items:[n],subagentKey:i,subagentName:r?.description||null};t.set(i,o),e.push(o)}return e});function k(e){e.origin&&f?.({origin:e.origin})}let me=x(()=>s.turn.items.filter(e=>e.type===`tool`).length);return(i,o)=>(u(),S(`div`,{ref_key:`cardEl`,ref:p,class:r([`turn-card`,{"turn-card--user":t.turn.speaker===`user`,"turn-card--highlighted":t.highlighted}]),"data-event-ids":E.value,style:n({"--turn-accent":b.value.accent})},[w(`div`,X,[w(`span`,{class:r([`turn-badge`,b.value.badgeClass])},a(b.value.label),3),re.value?(u(),S(`span`,Ze,a(re.value),1)):v(``,!0),se.value?(u(),S(C,{key:1},[g(oe,{name:`arrow_forward`,size:`10px`,color:`kobo-3`,class:`turn-time-arrow`}),w(`span`,Qe,[y(a(ae.value)+` `,1),g(B,null,{default:h(()=>[y(a(e(l)(`chat.lastUpdatedAt`,{time:ae.value})),1)]),_:1})])],64)):v(``,!0),me.value>0?(u(),S(`span`,$e,` · `+a(e(l)(`chat.nActions`,{n:me.value})),1)):v(``,!0)]),w(`div`,et,[(u(!0),S(C,null,te(pe.value,n=>(u(),S(C,{key:n.key},[n.type===`subagent`?(u(),_(Ce,{key:0,class:`turn-subagent-activity`,dense:``,label:O(n.subagentName),caption:e(l)(`chat.nActions`,{n:n.items.length}),"default-opened":t.highlighted&&n.items.some(e=>e.eventIds?.some(e=>E.value.includes(e)))},{header:h(()=>[g(P,null,{default:h(()=>[g(N,{class:`row items-center no-wrap`,title:n.subagentName??void 0},{default:h(()=>[g(oe,{name:`hub`,size:`16px`,class:`q-mr-xs`},{default:h(()=>[g(B,null,{default:h(()=>[y(a(e(l)(`chat.subagentActivity`)),1)]),_:1})]),_:1}),w(`span`,tt,a(O(n.subagentName)),1)]),_:2},1032,[`title`]),g(N,{caption:``},{default:h(()=>[y(a(e(l)(`chat.nActions`,{n:n.items.length})),1)]),_:2},1024)]),_:2},1024),g(P,{side:``},{default:h(()=>[g(D,{flat:``,round:``,dense:``,size:`sm`,icon:`open_in_new`,"aria-label":e(l)(`chat.openSubagentActivity`),onClick:ne(e=>k(n.items[0]),[`stop`])},{default:h(()=>[g(B,null,{default:h(()=>[y(a(e(l)(`chat.openSubagentActivity`)),1)]),_:1})]),_:1},8,[`aria-label`,`onClick`])]),_:2},1024)]),default:h(()=>[w(`div`,nt,[(u(!0),S(C,null,te(n.items,t=>(u(),S(C,{key:e(W)(t)},[t.type===`text`?(u(),_(I,{key:0,item:t},null,8,[`item`])):t.type===`thinking`?(u(),_(H,{key:1,item:t},null,8,[`item`])):t.type===`tool`?(u(),_(L,{key:2,item:t},null,8,[`item`])):v(``,!0)],64))),128))])]),_:2},1032,[`label`,`caption`,`default-opened`])):(u(),S(C,{key:1},[n.item.type===`text`?(u(),_(I,{key:0,item:n.item},null,8,[`item`])):n.item.type===`thinking`?(u(),_(H,{key:1,item:n.item},null,8,[`item`])):n.item.type===`tool`?(u(),_(L,{key:2,item:n.item},null,8,[`item`])):n.item.type===`user`?(u(),_(Y,{key:3,item:n.item,"workspace-id":t.workspaceId},null,8,[`item`,`workspace-id`])):n.item.type===`session`?(u(),_(We,{key:4,item:n.item},null,8,[`item`])):n.item.type===`error`?(u(),_(He,{key:5,item:n.item},null,8,[`item`])):v(``,!0)],64))],64))),128))]),t.turn.items.length>4?(u(),S(`div`,rt,[g(D,{flat:``,round:``,dense:``,size:`xs`,icon:`arrow_upward`,color:`kobo-3`,class:`turn-scroll-top-btn`,onClick:ee},{default:h(()=>[g(B,null,{default:h(()=>[y(a(e(l)(`chat.scrollToTurnTop`)),1)]),_:1})]),_:1})])):v(``,!0)],14,Xe))}}),[[`__scopeId`,`data-v-13bebb3d`]]),at={key:0,class:`activity-feed-switching`},ot={key:1,class:`activity-feed-wrap`,"data-tour":`ws-chat`},st={key:0,role:`alert`,class:`q-pa-sm text-negative`},ct={key:1,"data-testid":`history-load-error`,role:`alert`,class:`q-pa-sm text-negative`},lt=[`aria-label`],ut={key:0,class:`activity-feed-compacting`},dt={class:`text-caption text-kobo-2`},ft={key:0,class:`text-center q-py-sm text-caption text-kobo-3`},pt={key:1,class:`activity-feed-empty q-pa-md`},mt={class:`activity-feed-empty__title`},ht={class:`activity-feed-empty__hint`},gt={key:2,class:`q-px-md q-pb-md`},_t=[`title`],vt={class:`ellipsis`},yt={class:`activity-feed-nav-cluster`},bt=300,xt=60,St=200,Ct=180,wt=255,Tt=3,Et=60,Dt=R(T({__name:`ActivityFeed`,props:{workspaceId:{}},setup(t){let{t:n}=ue(),r=t,i=de(),s=me(),d=fe(),m=he(),ee=x(()=>m.isCompacting(r.workspaceId)),b=x(()=>d.selectedSessionId),T=x(()=>d.sessions.find(e=>e.id===b.value)?.engineSessionId??null),ne=x(()=>{let e=d.sessions;return e.length!==0&&b.value===e[e.length-1].id});function E(e){return b.value?e?e===b.value||e===T.value:ne.value:!0}let ie=x(()=>(d.activityFeeds[r.workspaceId]??[]).filter(e=>e.type===`text`&&typeof e.content==`string`&&E(e.sessionId)).map(e=>({content:e.content,sender:e.meta?.sender??`user`,source:ye(e.meta?.source),ts:e.timestamp,sessionId:e.sessionId,eventIds:[e.id]}))),ae=x(()=>{let e=d.workspaces.find(e=>e.id===r.workspaceId);return ve(e?.status)}),le=ke(),pe=``,k=x(()=>{let e=i.eventsFor(r.workspaceId),t=i.timestampsFor(r.workspaceId),n=i.sessionIdsFor(r.workspaceId),a=i.eventIdsFor(r.workspaceId),o=[],c=[],l=[];for(let r=0;r<e.length;r++)E(n[r])&&(o.push(e[r]),c.push(t[r]),l.push(a[r]??null));let u=`${r.workspaceId}::${b.value??`*`}`;u!==pe&&(le=ke(),pe=u);let d=Ee(le,o,c,ae.value,l);return Fe(De(d,ie.value).filter(e=>e.type===`thinking`?!1:e.type===`session`?e.kind===`ended`?s.showVerboseSystemMessages||!Oe(e.detail):s.showVerboseSystemMessages:!0))}),A=x(()=>s.showVerboseSystemMessages?i.eventsFor(r.workspaceId).filter(e=>e.kind===`message:raw`).map(e=>e.content):[]),xe=x(()=>{for(let e=k.value.length-1;e>=0;e--){let t=k.value[e]?.items??[];for(let e=t.length-1;e>=0;e--){let r=t[e];if(r){if(r.type===`text`&&!r.streaming)return{key:`text:${r.messageId}`,text:r.text};if(r.type===`tool`)return r.result?{key:`tool:${r.toolCallId}:end`,text:r.result.isError?n(`activity.a11y.toolFailed`,{name:r.name}):n(`activity.a11y.toolFinished`,{name:r.name})}:{key:`tool:${r.toolCallId}:start`,text:n(`activity.a11y.toolStarted`,{name:r.name})}}}}return null}),Se=o(``);l(xe,(e,t)=>{if(!e||e.key===t?.key)return;let r=e.key.startsWith(`text:`)?n(`activity.a11y.agentSaid`,{text:e.text.slice(0,bt)}):e.text;Se.value=r});let j=o(null),M=o(!0),N=o(!1),P=o(``),F=_e(),we=_e(),I=_e(),L=o(null),R=!1,z=!0,B=null,V=o(new Set),H=new Map,Ae=x(()=>{if(k.value.length>0||A.value.length>0)return!1;let e=r.workspaceId,t=b.value;return!!d.loadingSessions[e]||m.isSyncPending(e)||t!==null&&V.value.has(W(e,t))}),je=o(new Map),U=x(()=>k.value.length>0||A.value.length>0),Ne=x(()=>!!d.loadingSessions[r.workspaceId]||m.isSyncPending(r.workspaceId)||b.value!==null&&V.value.has(W(r.workspaceId,b.value)));function Pe(e){tt();let t=B;if(B=e.verticalSize,t!==null&&e.verticalSize>t&&M.value&&!N.value){q(0);return}let n=e.verticalSize-e.verticalPosition-e.verticalContainerSize;M.value=n<=xt,R&&e.verticalPosition<=St&&!N.value&&!P.value&&ze()&&He()}function W(e,t){return`${e}:${t}`}function ze(){let e=b.value;return e?je.value.get(W(r.workspaceId,e))??!0:i.hasMoreOlderFor(r.workspaceId)}function Be(e,t,n){je.value.set(W(e,t),n)}function Ve(e){if(!b.value)return i.oldestIdFor(e);let t=i.eventIdsFor(e),n=i.sessionIdsFor(e);for(let e=0;e<t.length;e++){if(!E(n[e]))continue;let r=t[e];if(r)return r}}let G=null;function He(){if(G)return G;let e=K().finally(()=>{G===e&&(G=null)});return G=e,G}function Ue(){F.abort(),we.abort(),I.abort(),N.value=!1,G=null;for(let e of V.value)Ft.delete(e);H.clear(),V.value.clear(),P.value=``}function We(){P.value=``,Nt.value===0&&b.value?It():He()}l(()=>[r.workspaceId,b.value],Ue,{flush:`sync`});async function K(){let e=r.workspaceId,t=b.value,n=Ve(e);if(!n)return;let a=F.begin();P.value=``,N.value=!0;try{let r=j.value;if(await f(),!F.isCurrent(a))return;let o=r?.getScroll().verticalSize??0,s=r?.getScroll().verticalPosition??0,c=new URLSearchParams({before:n,limit:`200`});t&&c.set(`session`,t);let l=await O(`/api/workspaces/${e}/events?${c.toString()}`,{signal:a});if(!l.ok)throw await ce(l);let u=await l.json();if(!F.isCurrent(a))return;let p=u.events??[],m=p.filter(t=>t.type===`agent:event`&&t.workspaceId===e),h=p.filter(t=>t.type===`user:message`&&t.workspaceId===e),g=m.map(e=>e.payload),_=m.map(e=>e.createdAt),v=m.map(e=>e.sessionId??null),y=m.map(e=>e.id),ee=p.length>0?p[0].id:n;t&&Be(e,t,u.hasMore),i.prepend(e,g,_,{oldestId:ee,hasMoreOlder:t?i.hasMoreOlderFor(e):u.hasMore,sessionIds:v,eventIds:y});for(let t of h){let n=t.payload;typeof n.content==`string`&&d.addActivityItem(e,{id:t.id,type:`text`,content:n.content,timestamp:t.createdAt,sessionId:t.sessionId??void 0,meta:{sender:n.sender??`user`,source:ye(n.source)}})}if(await f(),r&&F.isCurrent(a)){let e=r.getScroll().verticalSize-o;if(e>0){let t=Math.max(s+e,250);r.setScrollPosition(`vertical`,t,0)}}}catch(e){if(ge(e)||!F.isCurrent(a))return;P.value=e instanceof Error?e.message:String(e),console.error(`[ActivityFeed] failed to load older events:`,e)}finally{F.isCurrent(a)&&(N.value=!1)}}async function q(e=0){let t=$();if(await f(),t!==$())return;let n=j.value;if(!n)return;let r=n.getScroll();n.setScrollPosition(`vertical`,r.verticalSize,e)}let J=null,Ge=0;function Ke(){if(J!=null)return;let e=performance.now()-Ge<Ct,t=$();J=requestAnimationFrame(()=>{J=null,t===$()&&(Ge=performance.now(),q(e?0:180))})}function qe(e){Q(),M.value=!1;let t=j.value;t&&t.setScrollPosition(`vertical`,Math.max(0,e),250)}function Je(){let e=window.location.hash,t=e.indexOf(`?`);if(t===-1||!new URLSearchParams(e.slice(t+1)).has(`eventId`))return;let n=e.slice(0,t);window.history.replaceState(window.history.state,``,`${window.location.pathname}${window.location.search}${n}`)}async function Ye(e){let t=e.detail;if(t?.workspaceId!==r.workspaceId||!t.eventId)return;Q(),M.value=!1;let n=I.begin(),a=r.workspaceId;try{let e=new URLSearchParams({around:t.eventId,limit:`200`});t.sessionId&&e.set(`session`,t.sessionId);let o=await O(`/api/workspaces/${a}/events?${e}`,{signal:n});if(!o.ok)throw await ce(o);let s=await o.json();if(!I.isCurrent(n))return;let c=s.events??[],l=c.filter(e=>e.type===`agent:event`&&e.workspaceId===r.workspaceId),u=c.filter(e=>e.type===`user:message`&&e.workspaceId===r.workspaceId);i.reset(r.workspaceId,l.map(e=>e.payload),l.map(e=>e.createdAt),{oldestId:c[0]?.id,hasMoreOlder:s.hasMore??!1,sessionIds:l.map(e=>e.sessionId),eventIds:l.map(e=>e.id)});for(let e of u){let t=e.payload;typeof t.content==`string`&&d.addActivityItem(r.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`,source:ye(t.source)}})}if(await Re(Ae,e=>!e,5e3),await f(),await new Promise(e=>requestAnimationFrame(()=>requestAnimationFrame(()=>e()))),!I.isCurrent(n))return;let p=k.value.findIndex(e=>e.items.some(e=>e.eventIds?.includes(t.eventId)??!1));if(p<0)return;L.value=t.eventId,Y.value?.scrollTo(p,`center`),X.value=p,window.setTimeout(()=>{L.value===t.eventId&&(L.value=null)},1800)}catch(e){if(ge(e)||!I.isCurrent(n))return;P.value=e instanceof Error?e.message:String(e),console.error(`[ActivityFeed] failed to focus history event:`,e)}}let Y=o(null),Xe=o(null),X=o(0),Ze=o(!1),Qe=x(()=>{for(let e=k.value.length-1;e>=0;e--)if(k.value[e]?.speaker===`user`)return e;return-1}),$e=null;function et(){let e=Qe.value,t=j.value?.getScrollTarget(),n=t?.querySelector(`[data-turn-index="${e}"]`);if(!n||!t){Ze.value=!1;return}let r=t.getBoundingClientRect(),i=n.getBoundingClientRect();Ze.value=i.bottom>r.top&&i.top<r.bottom}function tt(){$e===null&&($e=requestAnimationFrame(()=>{$e=null,et()}))}function nt(e){return e.length<=wt?e:`${e.slice(0,252)}...`}let rt=x(()=>{let e=Qe.value,t=k.value[e];if(!t||X.value<=e||Ze.value)return null;let n=t.items.filter(e=>e.type===`user`).map(e=>e.content).join(`
|
|
1
|
+
import{M as e,S as t,dt as n,lt as r,p as i,pt as a,v as o}from"./reactivity.esm-bundler-DY1JkAEA.js";import{C as s,F as c,J as l,L as u,N as d,O as f,P as p,T as m,Y as h,_ as g,d as _,f as v,g as y,j as ee,k as b,l as x,p as S,r as C,u as w,y as T,z as te}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{$ as ne,K as re,M as E,f as ie,z as ae}from"./dom-BtYTvLeN.js";import{l as oe,t as D,u as se}from"./QBtn-BUSdPaf4.js";import{Kt as ce,O as le,Qt as ue,Ut as O,_t as de,at as fe,cn as pe,dn as k,j as me,m as he,mt as ge,pt as _e,st as ve,tn as A,v as ye}from"./index-CNcXBpzz.js";import{t as be}from"./QSpinnerDots-xdWyaE1i.js";import{t as xe}from"./QList-Cx1UfaUm.js";import{t as Se}from"./QMarkupTable-UhP7fVUp.js";import{c as j,l as M,s as N}from"./QSelect-DrLpbvcr.js";import{t as P}from"./QItemSection-MdJ1_ZK7.js";import{t as Ce}from"./QExpansionItem-CpwQ8L_F.js";import{a as F,c as we,r as I,t as L}from"./ToolCallItem-CLtGTV6w.js";import{t as Te}from"./QScrollArea-BkNSVl7s.js";import{a as R}from"./use-tours-B0KtCS9w.js";import{f as Ee,g as z,m as De,p as Oe,u as ke}from"./use-worktree-restore-tzd2FESU.js";import{t as B}from"./QTooltip-Dp8fitHV.js";import{n as V}from"./render-chat-markdown-CafzCcmu.js";import{n as H}from"./WorkspacePage-D4ODPOG-.js";function Ae(e,t){return s(`div`,e,[s(`table`,{class:`q-table`},t)])}var je={list:xe,table:Se},U=[`list`,`table`,`__qtable`],Me=ae({name:`QVirtualScroll`,props:{...M,type:{type:String,default:`list`,validator:e=>U.includes(e)},items:{type:Array,default:()=>[]},itemsFn:Function,itemsSize:Number,scrollTarget:k},setup(e,{slots:n,attrs:r}){let i,a=t(null),o=x(()=>e.itemsSize>=0&&e.itemsFn!==void 0?Number.parseInt(e.itemsSize,10):Array.isArray(e.items)?e.items.length:0),{virtualScrollSliceRange:c,localResetVirtualScroll:u,padVirtualScroll:f,onVirtualScrollEvt:m}=j({virtualScrollLength:o,getVirtualScrollTarget:y,getVirtualScrollEl:v}),h=x(()=>{if(o.value===0)return[];let t=(e,t)=>({index:c.value.from+t,item:e});return e.itemsFn===void 0?e.items.slice(c.value.from,c.value.to).map(t):e.itemsFn(c.value.from,c.value.to-c.value.from).map(t)}),g=x(()=>`q-virtual-scroll q-virtual-scroll`+(e.virtualScrollHorizontal?`--horizontal`:`--vertical`)+(e.scrollTarget===void 0?` scroll`:``)),_=x(()=>e.scrollTarget===void 0?{tabindex:0}:{});l(o,()=>{u()}),l(()=>e.scrollTarget,()=>{C(),S()});function v(){let e=a.value;return e===null?null:e.$el||e}function y(){return i}function S(){let t=v();t!==null&&(i=pe(t,e.scrollTarget),i.addEventListener(`scroll`,m,E.passive))}function C(){i!==void 0&&(i.removeEventListener(`scroll`,m,E.passive),i=void 0)}function w(){let t=f(e.type===`list`?`div`:`tbody`,h.value.map(n.default));return n.before!==void 0&&(t=n.before().concat(t)),ie(n.after,t)}return u(),p(()=>{S()}),b(()=>{S()}),d(()=>{C()}),ee(()=>{C()}),()=>{if(n.default===void 0){console.error(`QVirtualScroll: default scoped slot is required for rendering`);return}return e.type===`__qtable`?Ae({ref:a,class:`q-table__middle `+g.value,tabindex:0},w()):s(je[e.type],{...r,ref:a,class:[r.class,g.value],..._.value},w)}}}),Ne=new Set([`setup`,`cleanup`,`archive`]);function Pe(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:Ne.has(e.sender)||le(e.sender)?`script`:`user`;case`session`:return`session`;default:return`agent`}}function Fe(e){let t=[],n=null,r=null;for(let i of e){let e=Pe(i),a=e===`session`||e===`system-prompt`,o=e===`script`&&i.type===`user`?`script:${i.sender}`:e===`user`&&i.type===`user`&&i.source?JSON.stringify([`mcp`,i.source.transport,i.source.clientName]):e;!n||r!==o||a?(n={speaker:e,ts:i.ts,items:[i]},r=o,t.push(n),a&&(n=null)):n.items.push(i)}return t}function W(e){switch(e.type){case`text`:return`text:${e.messageId}`;case`thinking`:return`thinking:${e.messageId}:${e.eventIds?.[0]??e.ts??``}`;case`tool`:return`tool:${e.toolCallId}`;case`session`:return`session:${e.kind}:${e.eventIds?.[0]??e.ts??``}`;case`user`:return`user:${e.eventIds?.[0]??`${e.sender}:${e.ts??``}`}`;case`error`:return`error:${e.eventIds?.[0]??`${e.category}:${e.ts??``}`}`}}function Ie(e){let t=e.items[0];return`${e.speaker}:${t?W(t):`empty`}`}function Le(e,t){let n=Math.min(t,e.length)-1;for(let t=n;t>=0;t--)if(e[t]?.speaker===`user`)return t;return-1}function Re(e,t,n){return new Promise(r=>{let i=!1,a=null,o=null,s=e=>{i||(i=!0,a!==null&&clearTimeout(a),a=null,o?.(),r(e))};if(o=l(e,e=>{t(e)&&s(!0)},{immediate:!0}),i){o();return}a=setTimeout(()=>s(!1),n)})}var ze={class:`agent-error-item`},Be={class:`agent-error-item__body`},Ve={class:`agent-error-item__title`},G={class:`agent-error-item__message`},He=R(T({__name:`AgentErrorItem`,props:{item:{}},setup(e){let t=e,{te:n}=ue(),r=x(()=>{let e=`agent.error.${t.item.category}`;return n(e)?e:`agent.error.other`});return(t,n)=>(u(),S(`div`,ze,[g(oe,{name:`error_outline`,size:`16px`,class:`agent-error-item__icon`}),w(`div`,Be,[w(`div`,Ve,a(t.$t(r.value)),1),w(`div`,G,a(e.item.message),1)])]))}}),[[`__scopeId`,`data-v-e98c3c02`]]),Ue={class:`text-caption text-kobo-3`},We=T({__name:`SessionEventItem`,props:{item:{}},setup(e){let t=e,n=x(()=>{switch(t.item.kind){case`started`:return`session.started`;case`ended`:return z(t.item.detail);case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,t)=>(u(),S(`span`,Ue,a(e.$t(n.value)),1))}}),K=new Map;function q(){for(let e of K.values())e.controller.abort(),e.blobUrl&&URL.revokeObjectURL(e.blobUrl);K.clear()}typeof window<`u`&&(window.addEventListener(`kobo:auth-token-changed`,q),window.addEventListener(`storage`,e=>{(e.key===`kobo:network-token`||e.key===null)&&q()}));function J(e){if(!/^\/api\/workspaces\/[^/]+\/images\/file\?path=/.test(e))throw Error(`Invalid workspace image URL`);let t=K.get(e);if(!t){let n=new AbortController,r={references:0,controller:n,ready:Promise.resolve(``)};r.ready=O(e,{signal:n.signal}).then(async e=>{if(!e.ok)throw await ce(e);let t=await e.blob();if(n.signal.aborted)throw new DOMException(`Aborted`,`AbortError`);return r.blobUrl=URL.createObjectURL(t),r.blobUrl}),t=r,K.set(e,t)}t.references++;let n=!1,r=t;return{ready:r.ready,release(){n||(n=!0,!(--r.references>0)&&(r.controller.abort(),r.blobUrl&&URL.revokeObjectURL(r.blobUrl),K.get(e)===r&&K.delete(e)))}}}function Ge(e,t){let n=o(``),r=o(0),a=()=>{r.value++},s=e=>{(e.key===`kobo:network-token`||e.key===null)&&a()};return window.addEventListener(`kobo:auth-token-changed`,a),window.addEventListener(`storage`,s),i(()=>{window.removeEventListener(`kobo:auth-token-changed`,a),window.removeEventListener(`storage`,s)}),l([e,r],([e],r,i)=>{let a=!0,o=[],s=document.createElement(`template`);s.innerHTML=e;for(let e of s.content.querySelectorAll(`img`)){let r=e.getAttribute(`src`)??``;if(e.removeAttribute(`data-kobo-image-url`),!/^\/api\/workspaces\/[^/]+\/images\/file\?path=/.test(r))continue;e.removeAttribute(`src`);let i=J(r);o.push(i),i.ready.then(t=>{a&&(e.setAttribute(`src`,t),e.setAttribute(`data-kobo-image-url`,r),n.value=s.innerHTML)}).catch(()=>{a&&(e.setAttribute(`title`,t()),n.value=s.innerHTML)})}n.value=s.innerHTML,i(()=>{a=!1;for(let e of o)e.release()})},{immediate:!0}),n}function Ke(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 qe=[`innerHTML`],Je=[`innerHTML`],Ye=[`src`],Y=R(T({__name:`UserMessageItem`,props:{item:{},workspaceId:{}},setup(t){let n=t,{t:r}=ue(),a=x(()=>n.item.sender===`system-prompt`),s=Ge(x(()=>{let e=Ke(n.item.content,n.workspaceId);return V(e)}),()=>r(`network.login.unreachable`)),c=o(null),d=o(!1),f;function p(){d.value=!1,c.value=null,f?.release(),f=void 0}l(d,e=>{e||p()}),l(()=>n.workspaceId,p);let m=e=>{(e.key===`kobo:network-token`||e.key===null)&&p()};window.addEventListener(`storage`,m),window.addEventListener(`kobo:auth-token-changed`,p),i(()=>{p(),window.removeEventListener(`kobo:auth-token-changed`,p),window.removeEventListener(`storage`,m)});function y(e){let t=e.target;if(t?.tagName!==`IMG`)return;let n=t;n.src&&(p(),n.dataset.koboImageUrl&&(f=J(n.dataset.koboImageUrl),f.ready.catch(p)),c.value=n.src,d.value=!0)}return(t,n)=>(u(),S(C,null,[a.value?(u(),_(Ce,{key:0,dense:``,"dense-toggle":``,label:t.$t(`chat.systemPrompt`),"header-class":`text-kobo-2 text-caption`},{default:h(()=>[w(`div`,{class:`q-py-xs markdown-message markdown-user-prompt`,innerHTML:e(s)},null,8,qe)]),_:1},8,[`label`])):(u(),S(`div`,{key:1,class:`markdown-message`,onClick:y},[w(`div`,{innerHTML:e(s)},null,8,Je)])),g(A,{modelValue:d.value,"onUpdate:modelValue":n[1]||=e=>d.value=e},{default:h(()=>[c.value?(u(),S(`img`,{key:0,src:c.value,alt:``,class:`image-lightbox-img`,onClick:n[0]||=e=>d.value=!1},null,8,Ye)):v(``,!0)]),_:1},8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-965e6297`]]),Xe=[`data-event-ids`],X={class:`turn-header`},Ze={key:0,class:`turn-time`},Qe={class:`turn-time turn-time-updated`},$e={key:2,class:`turn-actions`},et={class:`turn-body`},tt={class:`ellipsis`},nt={class:`q-px-sm q-pb-sm`},rt={key:0,class:`turn-scroll-top`},it=R(T({__name:`TurnCard`,props:{turn:{},workspaceId:{},highlighted:{type:Boolean}},emits:[`scrollTo`],setup(t,{emit:i}){let s=t,c=i,{t:l}=ue(),d=fe(),f=m(F),p=o(null);function ee(){let e=p.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;c(`scrollTo`,Math.max(0,n-8))}let b=x(()=>{switch(s.turn.speaker){case`user`:{let e=s.turn.items[0],t=e?.type===`user`?e.source:void 0;return{label:t?l(`chat.externalLlm`,{name:t.clientName}):l(`chat.you`),accent:`var(--kobo-turn-user)`,badgeClass:`turn-badge-user`}}case`agent`:return{label:l(`chat.agent`),accent:`var(--kobo-turn-agent)`,badgeClass:`turn-badge-agent`};case`system-prompt`:return{label:l(`chat.systemPrompt`),accent:`var(--kobo-text-3)`,badgeClass:`turn-badge-system`};case`session`:return{label:l(`chat.session`),accent:`var(--kobo-text-3)`,badgeClass:`turn-badge-session`};case`script`:{let e=s.turn.items[0],t=e?.type===`user`?e.sender:``;return{label:le(t)?l(`chat.hookScript`,{event:t.slice(5)}):l(t===`archive`?`chat.archiveScript`:t===`setup`?`chat.setupScript`:`chat.cleanupScript`),accent:`var(--kobo-success)`,badgeClass:`turn-badge-script`}}}});function T(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 re=x(()=>T(s.turn.ts)),E=x(()=>s.turn.items.flatMap(e=>e.eventIds??[]).join(` `)),ie=x(()=>{let e=s.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}),ae=x(()=>{let e=s.turn.ts,t=ie.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?``:T(t,r-n<6e4)}),se=x(()=>ae.value!==``);function ce(e){return we(e.origin,Object.values(d.subagents[s.workspaceId]??{}),e.type===`tool`?e.toolCallId:void 0)}function O(e){return e||l(`chat.subagentActivity`)}function de(e){return(e.type===`text`||e.type===`thinking`||e.type===`tool`)&&e.origin?.kind===`subagent`}let pe=x(()=>{let e=[],t=new Map;for(let n of s.turn.items){if(!de(n)){e.push({type:`item`,key:W(n),item:n});continue}let r=ce(n),i=r?.toolUseId??n.origin?.toolCallId??n.origin?.threadId??W(n),a=t.get(i);if(a){a.items.push(n);continue}let o={type:`subagent`,key:`subagent:${W(n)}`,items:[n],subagentKey:i,subagentName:r?.description||null};t.set(i,o),e.push(o)}return e});function k(e){e.origin&&f?.({origin:e.origin})}let me=x(()=>s.turn.items.filter(e=>e.type===`tool`).length);return(i,o)=>(u(),S(`div`,{ref_key:`cardEl`,ref:p,class:r([`turn-card`,{"turn-card--user":t.turn.speaker===`user`,"turn-card--highlighted":t.highlighted}]),"data-event-ids":E.value,style:n({"--turn-accent":b.value.accent})},[w(`div`,X,[w(`span`,{class:r([`turn-badge`,b.value.badgeClass])},a(b.value.label),3),re.value?(u(),S(`span`,Ze,a(re.value),1)):v(``,!0),se.value?(u(),S(C,{key:1},[g(oe,{name:`arrow_forward`,size:`10px`,color:`kobo-3`,class:`turn-time-arrow`}),w(`span`,Qe,[y(a(ae.value)+` `,1),g(B,null,{default:h(()=>[y(a(e(l)(`chat.lastUpdatedAt`,{time:ae.value})),1)]),_:1})])],64)):v(``,!0),me.value>0?(u(),S(`span`,$e,` · `+a(e(l)(`chat.nActions`,{n:me.value})),1)):v(``,!0)]),w(`div`,et,[(u(!0),S(C,null,te(pe.value,n=>(u(),S(C,{key:n.key},[n.type===`subagent`?(u(),_(Ce,{key:0,class:`turn-subagent-activity`,dense:``,label:O(n.subagentName),caption:e(l)(`chat.nActions`,{n:n.items.length}),"default-opened":t.highlighted&&n.items.some(e=>e.eventIds?.some(e=>E.value.includes(e)))},{header:h(()=>[g(P,null,{default:h(()=>[g(N,{class:`row items-center no-wrap`,title:n.subagentName??void 0},{default:h(()=>[g(oe,{name:`hub`,size:`16px`,class:`q-mr-xs`},{default:h(()=>[g(B,null,{default:h(()=>[y(a(e(l)(`chat.subagentActivity`)),1)]),_:1})]),_:1}),w(`span`,tt,a(O(n.subagentName)),1)]),_:2},1032,[`title`]),g(N,{caption:``},{default:h(()=>[y(a(e(l)(`chat.nActions`,{n:n.items.length})),1)]),_:2},1024)]),_:2},1024),g(P,{side:``},{default:h(()=>[g(D,{flat:``,round:``,dense:``,size:`sm`,icon:`open_in_new`,"aria-label":e(l)(`chat.openSubagentActivity`),onClick:ne(e=>k(n.items[0]),[`stop`])},{default:h(()=>[g(B,null,{default:h(()=>[y(a(e(l)(`chat.openSubagentActivity`)),1)]),_:1})]),_:1},8,[`aria-label`,`onClick`])]),_:2},1024)]),default:h(()=>[w(`div`,nt,[(u(!0),S(C,null,te(n.items,t=>(u(),S(C,{key:e(W)(t)},[t.type===`text`?(u(),_(I,{key:0,item:t},null,8,[`item`])):t.type===`thinking`?(u(),_(H,{key:1,item:t},null,8,[`item`])):t.type===`tool`?(u(),_(L,{key:2,item:t},null,8,[`item`])):v(``,!0)],64))),128))])]),_:2},1032,[`label`,`caption`,`default-opened`])):(u(),S(C,{key:1},[n.item.type===`text`?(u(),_(I,{key:0,item:n.item},null,8,[`item`])):n.item.type===`thinking`?(u(),_(H,{key:1,item:n.item},null,8,[`item`])):n.item.type===`tool`?(u(),_(L,{key:2,item:n.item},null,8,[`item`])):n.item.type===`user`?(u(),_(Y,{key:3,item:n.item,"workspace-id":t.workspaceId},null,8,[`item`,`workspace-id`])):n.item.type===`session`?(u(),_(We,{key:4,item:n.item},null,8,[`item`])):n.item.type===`error`?(u(),_(He,{key:5,item:n.item},null,8,[`item`])):v(``,!0)],64))],64))),128))]),t.turn.items.length>4?(u(),S(`div`,rt,[g(D,{flat:``,round:``,dense:``,size:`xs`,icon:`arrow_upward`,color:`kobo-3`,class:`turn-scroll-top-btn`,onClick:ee},{default:h(()=>[g(B,null,{default:h(()=>[y(a(e(l)(`chat.scrollToTurnTop`)),1)]),_:1})]),_:1})])):v(``,!0)],14,Xe))}}),[[`__scopeId`,`data-v-13bebb3d`]]),at={key:0,class:`activity-feed-switching`},ot={key:1,class:`activity-feed-wrap`,"data-tour":`ws-chat`},st={key:0,role:`alert`,class:`q-pa-sm text-negative`},ct={key:1,"data-testid":`history-load-error`,role:`alert`,class:`q-pa-sm text-negative`},lt=[`aria-label`],ut={key:0,class:`activity-feed-compacting`},dt={class:`text-caption text-kobo-2`},ft={key:0,class:`text-center q-py-sm text-caption text-kobo-3`},pt={key:1,class:`activity-feed-empty q-pa-md`},mt={class:`activity-feed-empty__title`},ht={class:`activity-feed-empty__hint`},gt={key:2,class:`q-px-md q-pb-md`},_t=[`title`],vt={class:`ellipsis`},yt={class:`activity-feed-nav-cluster`},bt=300,xt=60,St=200,Ct=180,wt=255,Tt=3,Et=60,Dt=R(T({__name:`ActivityFeed`,props:{workspaceId:{}},setup(t){let{t:n}=ue(),r=t,i=de(),s=me(),d=fe(),m=he(),ee=x(()=>m.isCompacting(r.workspaceId)),b=x(()=>d.selectedSessionId),T=x(()=>d.sessions.find(e=>e.id===b.value)?.engineSessionId??null),ne=x(()=>{let e=d.sessions;return e.length!==0&&b.value===e[e.length-1].id});function E(e){return b.value?e?e===b.value||e===T.value:ne.value:!0}let ie=x(()=>(d.activityFeeds[r.workspaceId]??[]).filter(e=>e.type===`text`&&typeof e.content==`string`&&E(e.sessionId)).map(e=>({content:e.content,sender:e.meta?.sender??`user`,source:ye(e.meta?.source),ts:e.timestamp,sessionId:e.sessionId,eventIds:[e.id]}))),ae=x(()=>{let e=d.workspaces.find(e=>e.id===r.workspaceId);return ve(e?.status)}),le=ke(),pe=``,k=x(()=>{let e=i.eventsFor(r.workspaceId),t=i.timestampsFor(r.workspaceId),n=i.sessionIdsFor(r.workspaceId),a=i.eventIdsFor(r.workspaceId),o=[],c=[],l=[];for(let r=0;r<e.length;r++)E(n[r])&&(o.push(e[r]),c.push(t[r]),l.push(a[r]??null));let u=`${r.workspaceId}::${b.value??`*`}`;u!==pe&&(le=ke(),pe=u);let d=Ee(le,o,c,ae.value,l);return Fe(De(d,ie.value).filter(e=>e.type===`thinking`?!1:e.type===`session`?e.kind===`ended`?s.showVerboseSystemMessages||!Oe(e.detail):s.showVerboseSystemMessages:!0))}),A=x(()=>s.showVerboseSystemMessages?i.eventsFor(r.workspaceId).filter(e=>e.kind===`message:raw`).map(e=>e.content):[]),xe=x(()=>{for(let e=k.value.length-1;e>=0;e--){let t=k.value[e]?.items??[];for(let e=t.length-1;e>=0;e--){let r=t[e];if(r){if(r.type===`text`&&!r.streaming)return{key:`text:${r.messageId}`,text:r.text};if(r.type===`tool`)return r.result?{key:`tool:${r.toolCallId}:end`,text:r.result.isError?n(`activity.a11y.toolFailed`,{name:r.name}):n(`activity.a11y.toolFinished`,{name:r.name})}:{key:`tool:${r.toolCallId}:start`,text:n(`activity.a11y.toolStarted`,{name:r.name})}}}}return null}),Se=o(``);l(xe,(e,t)=>{if(!e||e.key===t?.key)return;let r=e.key.startsWith(`text:`)?n(`activity.a11y.agentSaid`,{text:e.text.slice(0,bt)}):e.text;Se.value=r});let j=o(null),M=o(!0),N=o(!1),P=o(``),F=_e(),we=_e(),I=_e(),L=o(null),R=!1,z=!0,B=null,V=o(new Set),H=new Map,Ae=x(()=>{if(k.value.length>0||A.value.length>0)return!1;let e=r.workspaceId,t=b.value;return!!d.loadingSessions[e]||m.isSyncPending(e)||t!==null&&V.value.has(W(e,t))}),je=o(new Map),U=x(()=>k.value.length>0||A.value.length>0),Ne=x(()=>!!d.loadingSessions[r.workspaceId]||m.isSyncPending(r.workspaceId)||b.value!==null&&V.value.has(W(r.workspaceId,b.value)));function Pe(e){tt();let t=B;if(B=e.verticalSize,t!==null&&e.verticalSize>t&&M.value&&!N.value){q(0);return}let n=e.verticalSize-e.verticalPosition-e.verticalContainerSize;M.value=n<=xt,R&&e.verticalPosition<=St&&!N.value&&!P.value&&ze()&&He()}function W(e,t){return`${e}:${t}`}function ze(){let e=b.value;return e?je.value.get(W(r.workspaceId,e))??!0:i.hasMoreOlderFor(r.workspaceId)}function Be(e,t,n){je.value.set(W(e,t),n)}function Ve(e){if(!b.value)return i.oldestIdFor(e);let t=i.eventIdsFor(e),n=i.sessionIdsFor(e);for(let e=0;e<t.length;e++){if(!E(n[e]))continue;let r=t[e];if(r)return r}}let G=null;function He(){if(G)return G;let e=K().finally(()=>{G===e&&(G=null)});return G=e,G}function Ue(){F.abort(),we.abort(),I.abort(),N.value=!1,G=null;for(let e of V.value)Ft.delete(e);H.clear(),V.value.clear(),P.value=``}function We(){P.value=``,Nt.value===0&&b.value?It():He()}l(()=>[r.workspaceId,b.value],Ue,{flush:`sync`});async function K(){let e=r.workspaceId,t=b.value,n=Ve(e);if(!n)return;let a=F.begin();P.value=``,N.value=!0;try{let r=j.value;if(await f(),!F.isCurrent(a))return;let o=r?.getScroll().verticalSize??0,s=r?.getScroll().verticalPosition??0,c=new URLSearchParams({before:n,limit:`200`});t&&c.set(`session`,t);let l=await O(`/api/workspaces/${e}/events?${c.toString()}`,{signal:a});if(!l.ok)throw await ce(l);let u=await l.json();if(!F.isCurrent(a))return;let p=u.events??[],m=p.filter(t=>t.type===`agent:event`&&t.workspaceId===e),h=p.filter(t=>t.type===`user:message`&&t.workspaceId===e),g=m.map(e=>e.payload),_=m.map(e=>e.createdAt),v=m.map(e=>e.sessionId??null),y=m.map(e=>e.id),ee=p.length>0?p[0].id:n;t&&Be(e,t,u.hasMore),i.prepend(e,g,_,{oldestId:ee,hasMoreOlder:t?i.hasMoreOlderFor(e):u.hasMore,sessionIds:v,eventIds:y});for(let t of h){let n=t.payload;typeof n.content==`string`&&d.addActivityItem(e,{id:t.id,type:`text`,content:n.content,timestamp:t.createdAt,sessionId:t.sessionId??void 0,meta:{sender:n.sender??`user`,source:ye(n.source)}})}if(await f(),r&&F.isCurrent(a)){let e=r.getScroll().verticalSize-o;if(e>0){let t=Math.max(s+e,250);r.setScrollPosition(`vertical`,t,0)}}}catch(e){if(ge(e)||!F.isCurrent(a))return;P.value=e instanceof Error?e.message:String(e),console.error(`[ActivityFeed] failed to load older events:`,e)}finally{F.isCurrent(a)&&(N.value=!1)}}async function q(e=0){let t=$();if(await f(),t!==$())return;let n=j.value;if(!n)return;let r=n.getScroll();n.setScrollPosition(`vertical`,r.verticalSize,e)}let J=null,Ge=0;function Ke(){if(J!=null)return;let e=performance.now()-Ge<Ct,t=$();J=requestAnimationFrame(()=>{J=null,t===$()&&(Ge=performance.now(),q(e?0:180))})}function qe(e){Q(),M.value=!1;let t=j.value;t&&t.setScrollPosition(`vertical`,Math.max(0,e),250)}function Je(){let e=window.location.hash,t=e.indexOf(`?`);if(t===-1||!new URLSearchParams(e.slice(t+1)).has(`eventId`))return;let n=e.slice(0,t);window.history.replaceState(window.history.state,``,`${window.location.pathname}${window.location.search}${n}`)}async function Ye(e){let t=e.detail;if(t?.workspaceId!==r.workspaceId||!t.eventId)return;Q(),M.value=!1;let n=I.begin(),a=r.workspaceId;try{let e=new URLSearchParams({around:t.eventId,limit:`200`});t.sessionId&&e.set(`session`,t.sessionId);let o=await O(`/api/workspaces/${a}/events?${e}`,{signal:n});if(!o.ok)throw await ce(o);let s=await o.json();if(!I.isCurrent(n))return;let c=s.events??[],l=c.filter(e=>e.type===`agent:event`&&e.workspaceId===r.workspaceId),u=c.filter(e=>e.type===`user:message`&&e.workspaceId===r.workspaceId);i.reset(r.workspaceId,l.map(e=>e.payload),l.map(e=>e.createdAt),{oldestId:c[0]?.id,hasMoreOlder:s.hasMore??!1,sessionIds:l.map(e=>e.sessionId),eventIds:l.map(e=>e.id)});for(let e of u){let t=e.payload;typeof t.content==`string`&&d.addActivityItem(r.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`,source:ye(t.source)}})}if(await Re(Ae,e=>!e,5e3),await f(),await new Promise(e=>requestAnimationFrame(()=>requestAnimationFrame(()=>e()))),!I.isCurrent(n))return;let p=k.value.findIndex(e=>e.items.some(e=>e.eventIds?.includes(t.eventId)??!1));if(p<0)return;L.value=t.eventId,Y.value?.scrollTo(p,`center`),X.value=p,window.setTimeout(()=>{L.value===t.eventId&&(L.value=null)},1800)}catch(e){if(ge(e)||!I.isCurrent(n))return;P.value=e instanceof Error?e.message:String(e),console.error(`[ActivityFeed] failed to focus history event:`,e)}}let Y=o(null),Xe=o(null),X=o(0),Ze=o(!1),Qe=x(()=>{for(let e=k.value.length-1;e>=0;e--)if(k.value[e]?.speaker===`user`)return e;return-1}),$e=null;function et(){let e=Qe.value,t=j.value?.getScrollTarget(),n=t?.querySelector(`[data-turn-index="${e}"]`);if(!n||!t){Ze.value=!1;return}let r=t.getBoundingClientRect(),i=n.getBoundingClientRect();Ze.value=i.bottom>r.top&&i.top<r.bottom}function tt(){$e===null&&($e=requestAnimationFrame(()=>{$e=null,et()}))}function nt(e){return e.length<=wt?e:`${e.slice(0,252)}...`}let rt=x(()=>{let e=Qe.value,t=k.value[e];if(!t||X.value<=e||Ze.value)return null;let n=t.items.filter(e=>e.type===`user`).map(e=>e.content).join(`
|
|
2
2
|
`).trim();return n?{index:e,content:nt(n)}:null});function Dt(e){X.value=e.index,tt()}function Ot(){let e=rt.value;e&&(Q(),M.value=!1,Y.value?.scrollTo(e.index,`start`),X.value=e.index)}let kt=o(!1);async function At(){if(kt.value)return;Q(),M.value=!1,kt.value=!0;let e=r.workspaceId;try{let t=Le(k.value,X.value);if(t<0)for(let n=0;n<15;n++){if(e!==r.workspaceId)return;if(!ze())break;let n=k.value.length;if(await He(),await f(),e!==r.workspaceId)return;if(X.value+=k.value.length-n,t=Le(k.value,X.value),t>=0)break}t>=0&&e===r.workspaceId&&(Y.value?.scrollTo(t,`start`),X.value=t)}finally{kt.value=!1}}let Z=0;function jt(){return new Promise(e=>requestAnimationFrame(()=>e()))}async function Mt(){if(!z||!U.value||Ae.value)return;R=!1;let e=++Z;if(await f(),e!==Z||!z||(Xe.value=j.value?.getScrollTarget()??null,await f(),e!==Z||!z))return;k.value.length>0&&Y.value?.scrollTo(k.value.length-1,`end-force`),await jt();let t=-1,n=0;for(let r=0;r<Et&&n<Tt;r++){if(e!==Z||!z)return;await q(0),await jt();let r=j.value?.getScroll().verticalSize??0;B=r,n=r===t?n+1:0,t=r}e===Z&&!Ne.value&&(R=!0,z=!1)}function Q(){z=!1,!R&&(Z++,R=!0)}let Nt=x(()=>{let e=i.sessionIdsFor(r.workspaceId);if(!b.value)return e.length;let t=0;for(let n of e)E(n)&&t++;return t});l(Ae,async e=>{!e&&U.value&&await Mt(),e||f(()=>{Xe.value=j.value?.getScrollTarget()??null,tt()})}),l(Ne,(e,t)=>{!e&&t&&z&&U.value&&Mt()}),p(()=>{window.addEventListener(`kobo:focus-history-event`,Ye),f(()=>{Xe.value=j.value?.getScrollTarget()??null,tt()}),U.value&&Mt(),b.value&&It();let e=new URLSearchParams(window.location.hash.split(`?`)[1]??``).get(`eventId`);e&&(Ye(new CustomEvent(`kobo:focus-history-event`,{detail:{workspaceId:r.workspaceId,sessionId:b.value,eventId:e}})),Je())}),l([Nt,()=>ie.value.length,()=>A.value.length],async([e,t,n])=>{N.value||z&&e+t+n>0&&await Mt()}),l([Qe,()=>k.value.length],()=>{f(tt)});let Pt=x(()=>i.liveAppendCountFor(r.workspaceId,E)),$=()=>`${r.workspaceId}\u0000${d.selectedSessionId??``}`;l([Pt,$],([e,t],[n,r])=>{t===r&&e>n&&M.value&&!N.value&&Ke()}),c(()=>{Z++,z=!1,Ue(),window.removeEventListener(`kobo:focus-history-event`,Ye),J!=null&&(cancelAnimationFrame(J),J=null),$e!==null&&cancelAnimationFrame($e)}),l([()=>r.workspaceId,()=>d.selectedSessionId],()=>{Z++,z=!0,B=null,M.value=!0,R=!1,It(),U.value&&Mt()});let Ft=new Set;async function It(){let e=r.workspaceId,t=b.value;if(!t||Nt.value>0)return;let n=W(e,t);if(Ft.has(n))return;Ft.add(n),V.value.add(n);let a=we.begin();H.set(n,a),P.value=``;try{let n=await O(`/api/workspaces/${e}/events?session=${encodeURIComponent(t)}&limit=500`,{signal:a});if(!n.ok)throw await ce(n);let r=await n.json();if(!we.isCurrent(a))return;let o=r.events??[];if(o.length===0)return;let s=o.filter(t=>t.type===`agent:event`&&t.workspaceId===e),c=o.filter(t=>t.type===`user:message`&&t.workspaceId===e),l=s.map(e=>e.payload),u=s.map(e=>e.createdAt),f=s.map(e=>e.sessionId??null),p=s.map(e=>e.id);Be(e,t,r.hasMore),l.length>0&&i.prepend(e,l,u,{oldestId:o[0].id,hasMoreOlder:i.hasMoreOlderFor(e),sessionIds:f,eventIds:p});for(let t of c){let n=t.payload;typeof n.content==`string`&&d.addActivityItem(e,{id:t.id,type:`text`,content:n.content,timestamp:t.createdAt,sessionId:t.sessionId??void 0,meta:{sender:n.sender??`user`,source:ye(n.source)}})}}catch(e){if(ge(e)||!we.isCurrent(a)){(!H.has(n)||H.get(n)===a)&&Ft.delete(n);return}P.value=e instanceof Error?e.message:String(e),console.error(`[ActivityFeed] fetchSessionIfMissing failed:`,e),Ft.delete(n)}finally{H.get(n)===a&&(H.delete(n),V.value.delete(n))}}let Lt=x(()=>ie.value.filter(e=>e.sender===`user`).length),Rt=x(()=>(d.activityFeeds[r.workspaceId]??[]).filter(e=>e.meta?.sender===`user`&&e.meta.pending&&E(e.sessionId)).length);l([Lt,Rt,$],async([e,t,n],[r,i,a])=>{let o=t>i;n===a&&(o||e>r&&M.value&&!N.value&&!Ne.value)&&(M.value=!0,await q(o?180:0))});async function zt(){M.value=!0,await q(250)}return(t,n)=>Ae.value?(u(),S(`div`,at,[g(be,{size:`40px`,color:`primary`})])):(u(),S(`div`,ot,[e(d).sessionsErrors[r.workspaceId]?(u(),S(`div`,st,[y(a(t.$t(`activity.sessionsError`,{message:e(d).sessionsErrors[r.workspaceId]}))+` `,1),g(D,{flat:``,dense:``,label:t.$t(`common.retry`),onClick:n[0]||=t=>e(d).fetchSessions(r.workspaceId)},null,8,[`label`])])):v(``,!0),P.value?(u(),S(`div`,ct,[y(a(t.$t(`activity.historyError`,{message:P.value}))+` `,1),g(D,{flat:``,dense:``,label:t.$t(`common.retry`),onClick:We},null,8,[`label`])])):v(``,!0),w(`div`,{"data-testid":`activity-live-region`,class:`sr-only`,role:`log`,"aria-live":`polite`,"aria-atomic":`true`,"aria-label":t.$t(`activity.a11y.region`)},a(Se.value),9,lt),g(re,{name:`fade`},{default:h(()=>[ee.value?(u(),S(`div`,ut,[g(be,{size:`18px`,color:`primary`}),w(`span`,dt,a(t.$t(`activity.compacting`)),1)])):v(``,!0)]),_:1}),g(Te,{ref_key:`scrollRef`,ref:j,class:`activity-feed-scroll`,onScroll:Pe,onWheelPassive:Q,onTouchstartPassive:Q,onKeydown:Q},{default:h(()=>[N.value?(u(),S(`div`,ft,[g(se,{size:`sm`}),y(` `+a(t.$t(`activity.loading_older`)),1)])):v(``,!0),g(Me,{ref_key:`virtualScrollRef`,ref:Y,class:`q-pa-md`,items:k.value,"scroll-target":Xe.value??void 0,"virtual-scroll-item-size":160,"virtual-scroll-slice-size":20,onVirtualScroll:Dt},{default:h(({item:t,index:n})=>[(u(),_(it,{key:e(Ie)(t),turn:t,"workspace-id":r.workspaceId,"data-turn-index":n,highlighted:t.items.some(e=>e.eventIds?.includes(L.value??``)??!1),onScrollTo:qe},null,8,[`turn`,`workspace-id`,`data-turn-index`,`highlighted`]))]),_:1},8,[`items`,`scroll-target`]),k.value.length===0&&A.value.length===0&&!N.value?(u(),S(`div`,pt,[g(oe,{name:`forum`,size:`28px`}),w(`div`,mt,a(t.$t(`activity.empty`)),1),w(`div`,ht,a(t.$t(`activity.emptyHint`)),1)])):v(``,!0),A.value.length?(u(),S(`div`,gt,[g(Ce,{label:t.$t(`activity.raw_lines`,{n:A.value.length}),dense:``},{default:h(()=>[(u(!0),S(C,null,te(A.value,(e,t)=>(u(),S(`div`,{key:t,class:`text-caption text-kobo-3 q-pa-xs`},a(e),1))),128))]),_:1},8,[`label`])])):v(``,!0)]),_:1},512),rt.value?(u(),S(`button`,{key:2,type:`button`,class:`activity-feed-last-user`,"data-testid":`latest-user-message`,title:rt.value.content,onClick:Ot},[g(oe,{name:`person`,size:`16px`}),w(`span`,vt,a(rt.value.content),1)],8,_t)):v(``,!0),w(`div`,yt,[M.value?v(``,!0):(u(),_(D,{key:0,round:``,dense:``,unelevated:``,color:`kobo-surface-2`,"text-color":`kobo-1`,icon:`arrow_downward`,size:`sm`,class:`activity-feed-nav-btn`,title:t.$t(`activity.scroll_to_bottom`),"aria-label":t.$t(`activity.scroll_to_bottom`),onClick:zt},null,8,[`title`,`aria-label`])),g(D,{round:``,dense:``,unelevated:``,color:`kobo-surface-2`,"text-color":`kobo-1`,icon:`arrow_upward`,size:`sm`,class:`activity-feed-nav-btn`,title:t.$t(`activity.prev_user_message`),"aria-label":t.$t(`activity.prev_user_message`),loading:kt.value,disable:kt.value,onClick:At},null,8,[`title`,`aria-label`,`loading`,`disable`])])]))}}),[[`__scopeId`,`data-v-58324159`]]);export{Dt as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{M as e,pt as t,v as n}from"./reactivity.esm-bundler-DY1JkAEA.js";import{J as r,L as i,Y as a,_ as o,d as s,f as c,l,p as u,r as d,u as f,y as p}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{t as m}from"./QBtn-BUSdPaf4.js";import{Mt as h,Qt as g,f as _,gn as v,j as y,jt as b,l as x,tn as S,vn as C}from"./index-
|
|
1
|
+
import{M as e,pt as t,v as n}from"./reactivity.esm-bundler-DY1JkAEA.js";import{J as r,L as i,Y as a,_ as o,d as s,f as c,l,p as u,r as d,u as f,y as p}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{t as m}from"./QBtn-BUSdPaf4.js";import{Mt as h,Qt as g,f as _,gn as v,j as y,jt as b,l as x,tn as S,vn as C}from"./index-CNcXBpzz.js";import{t as w}from"./QSelect-DrLpbvcr.js";import{a as T}from"./use-tours-B0KtCS9w.js";import{i as E,t as D}from"./permissionModes-DLWiBfdb.js";import{t as O}from"./efforts-B3I7w5bs.js";function k(e,t){return e.engine!==t.engine||e.model!==t.model||e.reasoningEffort!==t.reasoningEffort||e.agentPermissionMode!==t.agentPermissionMode}var A={class:`text-h6`},j={class:`text-body2 text-kobo-2 q-mt-xs`},ee={class:`row q-col-gutter-sm q-mb-md`},te={class:`col-12 col-sm-6`},ne={class:`col-12 col-sm-6`},M={class:`col-12 col-sm-6`},N={class:`col-12 col-sm-6`},P={key:0,class:`text-caption text-kobo-3 q-mt-xs`},F={class:`text-caption text-kobo-3 q-mt-xs`},I={class:`text-caption text-kobo-3 q-mt-xs`},L=T(p({__name:`StartReviewDialog`,props:{modelValue:{type:Boolean},loading:{type:Boolean},workspace:{},canReturnToSession:{type:Boolean},currentSession:{},mode:{},scheduledConfiguration:{}},emits:[`update:modelValue`,`submit`],setup(e,{emit:p}){let T=e,L=p,{t:R}=g(),z=y(),B=l(()=>T.mode===`auto-loop`),V=n(``),H=n(!1),U=n(!1),W=n(`claude-code`),G=n(`auto`),K=n(`auto`),q=n(`bypass`),J=l(()=>B.value||U.value?`plan`:q.value),Y=l(()=>({engine:W.value,model:G.value,reasoningEffort:K.value,agentPermissionMode:J.value})),X=l(()=>{let e=T.currentSession;return B.value||U.value||!!T.workspace&&k(Y.value,T.workspace)||!!e?.engine&&e.engine!==W.value||G.value!==`auto`&&!!e?.model&&e.model!==G.value}),Z=l({get:()=>H.value||X.value,set:e=>{H.value=e}}),re=l(()=>[{value:`claude-code`,label:R(`workspacePage.engineClaude`)},{value:`codex`,label:R(`workspacePage.engineCodex`)}]),Q=l(()=>{let e=(E[W.value]??[]).map(e=>({value:e.value,label:R(e.i18nLabelKey)}));T.workspace?.engine===W.value&&!e.some(e=>e.value===T.workspace?.model)&&e.push({value:T.workspace.model,label:T.workspace.model});let t=T.scheduledConfiguration;return t?.engine===W.value&&!e.some(e=>e.value===t.model)&&e.push({value:t.model,label:t.model}),e}),ie=l(()=>(O[W.value]??[]).map(e=>({value:e.value,label:R(e.i18nLabelKey)}))),$=l(()=>(D[W.value]??[]).map(e=>({value:e,label:R(`agentPermissionMode.${e}`)})));r(W,()=>{let e=T.workspace,t=z.global.defaultModelByEngine[W.value];G.value=e?.engine===W.value?e.model:Q.value.some(e=>e.value===t)?t:`auto`,K.value=e?.engine===W.value?e.reasoningEffort:`auto`,$.value.some(e=>e.value===q.value)||(q.value=`plan`)},{flush:`sync`}),r([()=>T.modelValue,()=>T.workspace?.id],([e])=>{if(!e)return;let t=B.value?T.scheduledConfiguration:null;V.value=t?.additionalInstructions??``,H.value=!1,U.value=B.value,T.workspace&&(W.value=T.workspace.engine,G.value=T.workspace.model,K.value=T.workspace.reasoningEffort,q.value=T.workspace.agentPermissionMode),t&&(W.value=t.engine,G.value=t.model,K.value=t.reasoningEffort)},{immediate:!0}),r(()=>T.canReturnToSession,e=>{!e&&!B.value&&(U.value=!1)});function ae(){T.loading||L(`update:modelValue`,!1)}function oe(){!T.loading&&T.workspace&&L(`submit`,{...Y.value,additionalInstructions:V.value,newSession:Z.value,returnToSession:B.value||U.value&&T.canReturnToSession})}return(n,r)=>(i(),s(S,{"model-value":e.modelValue,persistent:e.loading,"onUpdate:modelValue":r[7]||=e=>L(`update:modelValue`,e)},{default:a(()=>[o(v,{class:`review-card text-kobo-1`},{default:a(()=>[o(C,null,{default:a(()=>[f(`div`,A,t(n.$t(B.value?`autoLoop.finalReview.title`:`review.title`)),1),f(`div`,j,t(n.$t(B.value?`autoLoop.finalReview.description`:`review.subtitle`)),1)]),_:1}),o(_,{dark:``}),o(C,{class:`q-pt-md`},{default:a(()=>[f(`div`,ee,[f(`div`,te,[o(w,{modelValue:W.value,"onUpdate:modelValue":r[0]||=e=>W.value=e,options:re.value,label:n.$t(`engine.select`),disable:e.loading,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``},null,8,[`modelValue`,`options`,`label`,`disable`])]),f(`div`,ne,[o(w,{modelValue:G.value,"onUpdate:modelValue":r[1]||=e=>G.value=e,options:Q.value,label:n.$t(`engine.model`),disable:e.loading,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``},null,8,[`modelValue`,`options`,`label`,`disable`])]),f(`div`,M,[o(w,{modelValue:K.value,"onUpdate:modelValue":r[2]||=e=>K.value=e,options:ie.value,label:n.$t(`engine.effort`),disable:e.loading,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``},null,8,[`modelValue`,`options`,`label`,`disable`])]),f(`div`,N,[o(w,{"model-value":J.value,options:$.value,label:n.$t(`agentPermissionMode.label`),disable:e.loading||U.value,"emit-value":``,"map-options":``,outlined:``,dark:``,dense:``,"onUpdate:modelValue":r[3]||=e=>q.value=e},null,8,[`model-value`,`options`,`label`,`disable`]),U.value?(i(),u(`div`,P,t(n.$t(`review.readOnlyForced`)),1)):c(``,!0)])]),o(h,{modelValue:V.value,"onUpdate:modelValue":r[4]||=e=>V.value=e,type:`textarea`,disable:e.loading,label:n.$t(`review.additionalInstructions`),placeholder:n.$t(`review.additionalInstructionsPlaceholder`),rows:4,outlined:``,dark:``,color:`primary`},null,8,[`modelValue`,`disable`,`label`,`placeholder`])]),_:1}),B.value?c(``,!0):(i(),s(C,{key:0,class:`q-pt-none`},{default:a(()=>[o(x,{modelValue:Z.value,"onUpdate:modelValue":r[5]||=e=>Z.value=e,disable:e.loading||X.value,label:n.$t(`review.newSession`),color:`primary`,dark:``},null,8,[`modelValue`,`disable`,`label`]),f(`div`,F,t(n.$t(X.value?`review.newSessionRequired`:`review.newSessionHint`)),1),Z.value?(i(),u(d,{key:0},[o(x,{modelValue:U.value,"onUpdate:modelValue":r[6]||=e=>U.value=e,disable:e.loading||!e.canReturnToSession,label:n.$t(`review.returnToSession`),color:`primary`,dark:``,class:`q-mt-md`},null,8,[`modelValue`,`disable`,`label`]),f(`div`,I,t(n.$t(e.canReturnToSession?`review.returnToSessionHint`:`review.returnUnavailable`)),1)],64)):c(``,!0)]),_:1})),o(b,{align:`right`,class:`q-pa-md`},{default:a(()=>[o(m,{flat:``,"no-caps":``,label:n.$t(`review.cancel`),color:`kobo-2`,disable:e.loading,onClick:ae},null,8,[`label`,`disable`]),o(m,{"no-caps":``,color:`primary`,label:n.$t(B.value?`autoLoop.finalReview.save`:`review.start`),loading:e.loading,disable:!e.workspace||e.loading,onClick:oe},null,8,[`label`,`loading`,`disable`])]),_:1})]),_:1})]),_:1},8,[`model-value`,`persistent`]))}}),[[`__scopeId`,`data-v-a4419350`]]),R={class:`final-review-settings`},z={class:`text-caption text-kobo-3`},B=T(p({__name:`AutoLoopFinalReviewSettings`,props:{modelValue:{},workspace:{},disabled:{type:Boolean},loading:{type:Boolean}},emits:[`update:modelValue`],setup(a,{emit:l}){let d=a,p=l,{t:h}=g(),_=n(!1),v=n(null);r(()=>d.modelValue,e=>{JSON.stringify(e)===JSON.stringify(v.value)&&(v.value=null)}),r(()=>d.workspace.id,()=>{_.value=!1,v.value=null});function y(e){d.disabled||d.loading||(e?_.value=!0:p(`update:modelValue`,null))}function b(e){!d.disabled&&!d.loading&&e.engine&&e.model&&e.reasoningEffort&&(v.value={engine:e.engine,model:e.model,reasoningEffort:e.reasoningEffort,additionalInstructions:e.additionalInstructions??``},p(`update:modelValue`,v.value),_.value=!1)}return(n,r)=>(i(),u(`div`,R,[o(x,{"model-value":!!a.modelValue,disable:a.disabled||a.loading,color:`primary`,label:e(h)(`autoLoop.finalReview.enabled`),"onUpdate:modelValue":y},null,8,[`model-value`,`disable`,`label`]),f(`p`,z,t(e(h)(`autoLoop.finalReview.hint`)),1),a.modelValue?(i(),s(m,{key:0,flat:``,dense:``,"no-caps":``,disable:a.disabled||a.loading,label:e(h)(`autoLoop.finalReview.configure`),onClick:r[0]||=e=>_.value=!0},null,8,[`disable`,`label`])):c(``,!0),o(L,{modelValue:_.value,"onUpdate:modelValue":r[1]||=e=>_.value=e,mode:`auto-loop`,loading:a.loading??!1,workspace:a.workspace,"scheduled-configuration":v.value??a.modelValue,"can-return-to-session":!0,onSubmit:b},null,8,[`modelValue`,`loading`,`workspace`,`scheduled-configuration`])]))}}),[[`__scopeId`,`data-v-b7f36f83`]]);export{L as n,B as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{M as e,pt as t,v as n}from"./reactivity.esm-bundler-DY1JkAEA.js";import{L as r,P as i,Y as a,_ as o,d as s,f as c,p as l,r as u,u as d,y as f,z as p}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{t as m}from"./QBtn-BUSdPaf4.js";import{Kt as h,Ut as g,a as _,gn as v,vn as y}from"./index-
|
|
1
|
+
import{M as e,pt as t,v as n}from"./reactivity.esm-bundler-DY1JkAEA.js";import{L as r,P as i,Y as a,_ as o,d as s,f as c,p as l,r as u,u as d,y as f,z as p}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{t as m}from"./QBtn-BUSdPaf4.js";import{Kt as h,Ut as g,a as _,gn as v,vn as y}from"./index-CNcXBpzz.js";import{a as b,i as x,n as S}from"./use-tours-B0KtCS9w.js";import{n as C}from"./render-chat-markdown-CafzCcmu.js";import{t as w}from"./QChip-Be16M4Ig.js";import{t as T}from"./QPage-CqkGHokx.js";import{t as E}from"./DrawerToggleButton-BLWaFgh0.js";import{t as D}from"./TourReplayButton-Dw4sGf9B.js";var O={class:`row items-center q-mb-md`},k={class:`text-h6 q-ml-sm`},A={key:0,class:`text-kobo-3 text-center q-pa-lg`},j={key:1,class:`text-negative text-center q-pa-lg`},M={key:2,class:`text-kobo-3 text-center q-pa-lg`},N={key:3,class:`column q-gutter-md`,"data-tour":`changelog-list`},P={key:0,class:`text-caption text-kobo-3`},F={class:`row items-center q-mb-sm`},I={class:`text-subtitle1 text-kobo-2`,style:{"font-family":`var(--kobo-font-mono, monospace)`}},L=[`innerHTML`],R=b(f({__name:`ChangelogPage`,setup(f){let b=_(),{scheduleAutoRun:R}=S(),z=n([]),B=n(``),V=n(!1),H=n(null);function U(e){return C(e)}async function W(){V.value=!0,H.value=null;try{let e=await g(`/api/changelog`);if(!e.ok)throw await h(e);let t=await e.json();B.value=t.currentVersion??``,z.value=t.versions??[]}catch(e){H.value=e instanceof Error?e.message:String(e)}finally{V.value=!1}}return i(()=>{W(),R(`changelog`)}),(n,i)=>(r(),s(T,{class:`q-pa-md`,style:{"max-width":`900px`,margin:`0 auto`}},{default:a(()=>[d(`div`,O,[o(E,{class:`q-mr-xs`}),o(m,{flat:``,dense:``,round:``,icon:`arrow_back`,onClick:i[0]||=t=>e(b).back()}),d(`div`,k,t(n.$t(`changelog.title`)),1),o(x),o(m,{flat:``,dense:``,icon:`refresh`,loading:V.value,label:n.$t(`common.refresh`),onClick:W},null,8,[`loading`,`label`]),o(D,{"tour-id":`changelog`,class:`q-ml-xs`})]),V.value&&z.value.length===0?(r(),l(`div`,A,t(n.$t(`common.loading`)),1)):H.value?(r(),l(`div`,j,t(H.value),1)):z.value.length===0?(r(),l(`div`,M,t(n.$t(`changelog.empty`)),1)):(r(),l(`div`,N,[B.value?(r(),l(`div`,P,t(n.$t(`changelog.currentVersion`,{version:B.value})),1)):c(``,!0),(r(!0),l(u,null,p(z.value,e=>(r(),s(v,{key:e.version,dark:``,flat:``,bordered:``},{default:a(()=>[o(y,null,{default:a(()=>[d(`div`,F,[d(`div`,I,` v`+t(e.version),1),e.version===B.value?(r(),s(w,{key:0,dense:``,size:`sm`,color:`primary`,"text-color":`kobo-1`,label:n.$t(`changelog.current`),class:`q-ml-sm`},null,8,[`label`])):c(``,!0)]),d(`div`,{class:`changelog-notes`,innerHTML:U(e.notes)},null,8,L)]),_:2},1024)]),_:2},1024))),128))]))]),_:1}))}}),[[`__scopeId`,`data-v-4032778f`]]);export{R as default};
|
package/src/client/dist/pwa/assets/{ComparisonPanel-Cw5Dkan0.js → ComparisonPanel-b5nTBjK6.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{lt as e,pt as t,v as n}from"./reactivity.esm-bundler-DY1JkAEA.js";import{J as r,L as i,P as ee,Y as a,_ as o,d as te,f as s,g as ne,l as c,p as l,r as re,u,y as d,z as ie}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{t as f}from"./QBtn-BUSdPaf4.js";import{Qt as p,Ut as m,a as h,at as ae}from"./index-
|
|
1
|
+
import{lt as e,pt as t,v as n}from"./reactivity.esm-bundler-DY1JkAEA.js";import{J as r,L as i,P as ee,Y as a,_ as o,d as te,f as s,g as ne,l as c,p as l,r as re,u,y as d,z as ie}from"./runtime-core.esm-bundler-Bqg71Vll.js";import{t as f}from"./QBtn-BUSdPaf4.js";import{Qt as p,Ut as m,a as h,at as ae}from"./index-CNcXBpzz.js";import{t as oe}from"./QMarkupTable-UhP7fVUp.js";import{a as g,i as _}from"./use-tours-B0KtCS9w.js";var v=[`workspace`,`engine`,`model`,`status`,`branch`,`tasks_done`,`tasks_total`,`commits`,`files_changed`,`insertions`,`deletions`,`agent_messages`,`user_messages`,`injected_prompts`,`questions`,`tool_calls`,`errors`,`input_tokens`,`output_tokens`,`sessions`,`duration_seconds`];function y(e){if(e==null)return``;let t=String(e);return/[",\r\n]/.test(t)?`"${t.replace(/"/g,`""`)}"`:t}function b(e){let t=e.map(e=>{let t=e.gitStats,n=e.activity;return[e.workspace.name,e.workspace.engine,e.workspace.model,e.workspace.status,e.workspace.workingBranch,e.tasks.done,e.tasks.total,t?.commitCount??null,t?.filesChanged??null,t?.insertions??null,t?.deletions??null,n.agentMessages,n.userMessages,n.injectedPrompts,n.questions,n.toolCalls,n.errors,n.inputTokens,n.outputTokens,n.sessions,Math.round(n.durationMs/1e3)].map(y).join(`,`)});return`${[v.join(`,`),...t].join(`\r
|
|
2
2
|
`)}`}var x={key:0,class:`comparison-panel q-pa-md`},S={class:`row items-center q-mb-sm`},C={class:`text-subtitle2`},w={class:`text-caption text-kobo-3 q-mb-sm`},T={class:`text-left`},E={class:`text-left`},D={class:`text-right`},O={class:`text-right`},k={class:`text-right`},A={class:`text-right`},j={class:`text-right`},M={class:`text-right`},N={class:`text-right`},P={class:`text-right`},F={class:`text-right`},I={class:`text-right`},L={class:`text-right`},R={class:`text-caption text-kobo-3 comparison-mono`},z={key:0,class:`text-caption text-kobo-3`},B={class:`text-right comparison-mono`},V={class:`text-right`},H={class:`text-right`},U={class:`text-right`},se={key:0,class:`comparison-mono`},W={class:`text-kobo-success`},G={class:`text-kobo-danger q-ml-xs`},K={key:1,class:`text-kobo-3`},ce={class:`text-right comparison-mono`},le=[`title`],ue={class:`text-right`},de={class:`text-right`},fe={class:`text-right comparison-mono`},pe=[`title`],me={class:`text-right`},he={class:`text-right comparison-mono`},ge={class:`text-right`},_e={key:1,class:`text-caption text-kobo-3`},ve={key:0,class:`text-caption text-kobo-warning q-mt-sm`},q=g(d({__name:`ComparisonPanel`,props:{workspaceId:{}},setup(d){let g=d;function v(e){return e<1e3?String(e):e<1e6?`${(e/1e3).toFixed(+(e<1e4))}k`:`${(e/1e6).toFixed(1)}M`}function y(e){if(e<=0)return`-`;let t=Math.round(e/1e3);if(t<60)return J(`reliability.durationSeconds`,{s:t});let n=Math.floor(t/60);return n<60?J(`reliability.durationMinutes`,{m:n,s:t%60}):J(`reliability.durationHours`,{h:Math.floor(n/60),m:n%60})}let q=h(),ye=ae(),{t:J}=p(),Y=n([]),X=n(!1),be={created:`workspaceStatus.created`,extracting:`workspaceStatus.extracting`,brainstorming:`workspaceStatus.brainstorming`,executing:`workspaceStatus.executing`,compacting:`workspaceStatus.compacting`,"awaiting-user":`workspaceStatus.awaitingUser`,completed:`workspaceStatus.completed`,idle:`workspaceStatus.idle`,error:`workspaceStatus.error`,quota:`workspaceStatus.quota`,retrying:`workspaceStatus.retrying`},Z=n({});function xe(e){return Z.value[e]??e}async function Se(){try{let e=await m(`/api/engines`);if(!e.ok)return;let t=await e.json();Z.value=Object.fromEntries(t.map(e=>[e.id,e.displayName]))}catch{}}function Ce(e){let t=be[e];return t?J(t):e}let we=c(()=>g.workspaceId);function Q(e){return e.workspace.id===we.value}function Te(e){ye.selectWorkspace(e),q.push({name:`workspace`,params:{id:e}})}function Ee(){let e=b(Y.value),t=new Blob([e],{type:`text/csv;charset=utf-8`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`kobo-comparison-${Y.value[0]?.workspace.comparisonId??`comparison`}.csv`,r.click(),URL.revokeObjectURL(n)}async function $(){X.value=!0;try{let e=await m(`/api/workspaces/${g.workspaceId}/comparison`);if(!e.ok){Y.value=[];return}let t=await e.json();Y.value=t.members??[]}catch{Y.value=[]}finally{X.value=!1}}return ee(()=>{Se(),$()}),r(()=>g.workspaceId,$),(n,r)=>Y.value.length>0?(i(),l(`div`,x,[u(`div`,S,[u(`div`,C,t(n.$t(`comparison.title`)),1),o(_),o(f,{flat:``,dense:``,round:``,size:`sm`,icon:`download`,title:n.$t(`comparison.exportCsv`),onClick:Ee},null,8,[`title`]),o(f,{flat:``,dense:``,round:``,size:`sm`,icon:`refresh`,loading:X.value,onClick:$},null,8,[`loading`])]),u(`div`,w,t(n.$t(`comparison.hint`)),1),o(oe,{flat:``,dense:``,dark:``,class:`comparison-table`},{default:a(()=>[u(`thead`,null,[u(`tr`,null,[u(`th`,T,t(n.$t(`comparison.engine`)),1),u(`th`,E,t(n.$t(`comparison.status`)),1),u(`th`,D,t(n.$t(`comparison.tasks`)),1),u(`th`,O,t(n.$t(`comparison.commits`)),1),u(`th`,k,t(n.$t(`comparison.files`)),1),u(`th`,A,t(n.$t(`comparison.diff`)),1),u(`th`,j,t(n.$t(`comparison.messages`)),1),u(`th`,M,t(n.$t(`comparison.questions`)),1),u(`th`,N,t(n.$t(`comparison.tools`)),1),u(`th`,P,t(n.$t(`comparison.errors`)),1),u(`th`,F,t(n.$t(`comparison.tokens`)),1),u(`th`,I,t(n.$t(`comparison.sessions`)),1),u(`th`,L,t(n.$t(`comparison.duration`)),1),r[0]||=u(`th`,null,null,-1)])]),u(`tbody`,null,[(i(!0),l(re,null,ie(Y.value,r=>(i(),l(`tr`,{key:r.workspace.id,class:e({"comparison-current":Q(r)})},[u(`td`,null,[u(`div`,null,t(xe(r.workspace.engine)),1),u(`div`,R,t(r.workspace.model),1)]),u(`td`,null,[ne(t(Ce(r.workspace.status))+` `,1),r.workspace.archivedAt?(i(),l(`span`,z,` · `+t(n.$t(`comparison.archived`)),1)):s(``,!0)]),u(`td`,B,t(r.tasks.done)+`/`+t(r.tasks.total),1),u(`td`,V,t(r.gitStats?.commitCount??`-`),1),u(`td`,H,t(r.gitStats?.filesChanged??`-`),1),u(`td`,U,[r.gitStats?(i(),l(`span`,se,[u(`span`,W,`+`+t(r.gitStats.insertions),1),u(`span`,G,`-`+t(r.gitStats.deletions),1)])):(i(),l(`span`,K,`-`))]),u(`td`,ce,[u(`span`,{title:n.$t(`comparison.messagesTitle`)},t(r.activity.agentMessages)+` / `+t(r.activity.userMessages),9,le)]),u(`td`,ue,t(r.activity.questions),1),u(`td`,de,t(r.activity.toolCalls),1),u(`td`,{class:e([`text-right`,r.activity.errors>0?`text-kobo-danger`:``])},t(r.activity.errors),3),u(`td`,fe,[u(`span`,{title:n.$t(`comparison.tokensTitle`)},t(v(r.activity.inputTokens))+` / `+t(v(r.activity.outputTokens)),9,pe)]),u(`td`,me,t(r.activity.sessions),1),u(`td`,he,t(y(r.activity.durationMs)),1),u(`td`,ge,[Q(r)?(i(),l(`span`,_e,t(n.$t(`comparison.current`)),1)):(i(),te(f,{key:0,flat:``,dense:``,"no-caps":``,size:`sm`,label:n.$t(`comparison.open`),onClick:e=>Te(r.workspace.id)},null,8,[`label`,`onClick`]))])],2))),128))])]),_:1}),Y.value.length<2?(i(),l(`div`,ve,t(n.$t(`comparison.incomplete`)),1)):s(``,!0)])):s(``,!0)}}),[[`__scopeId`,`data-v-bda71e6d`]]);export{q as default};
|