pikiloom 0.4.58 → 0.4.60
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/dashboard/dist/assets/{AgentTab-CLlOp3lJ.js → AgentTab-KSanVg_l.js} +1 -1
- package/dashboard/dist/assets/{ConnectionModal-BJhiouLS.js → ConnectionModal-BSoA2mZL.js} +1 -1
- package/dashboard/dist/assets/{DirBrowser-H0N2gMRB.js → DirBrowser-zKX7wmty.js} +1 -1
- package/dashboard/dist/assets/{ExtensionsTab-5uaiMRcm.js → ExtensionsTab-DKLjCr4u.js} +1 -1
- package/dashboard/dist/assets/{IMAccessTab-ClNbxnzS.js → IMAccessTab-BhvB7Hes.js} +1 -1
- package/dashboard/dist/assets/{Modal-Cy1zHcC7.js → Modal-Qwlap_Fl.js} +1 -1
- package/dashboard/dist/assets/{Modals-BrLADO-I.js → Modals-2Zw2FSLo.js} +1 -1
- package/dashboard/dist/assets/{Select-D4DbOixc.js → Select-dIxoi_TN.js} +1 -1
- package/dashboard/dist/assets/SessionPanel--D5NGYgd.js +1 -0
- package/dashboard/dist/assets/{SystemTab-CDrID55_.js → SystemTab-CtjiZa5s.js} +1 -1
- package/dashboard/dist/assets/index-BDSh0L9U.js +3 -0
- package/dashboard/dist/assets/index-DN0a6ZnO.js +23 -0
- package/dashboard/dist/assets/{shared-DQyw9U1Z.js → shared-D2sGZJ9f.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dist/agent/drivers/claude.js +34 -3
- package/dist/agent/drivers/codex.js +24 -4
- package/dist/agent/turn-snapshot.js +141 -0
- package/dist/bot/bot.js +11 -0
- package/dist/dashboard/routes/sessions.js +30 -9
- package/package.json +1 -1
- package/dashboard/dist/assets/SessionPanel-1hemRLg_.js +0 -1
- package/dashboard/dist/assets/index-Iot9Vn3K.js +0 -3
- package/dashboard/dist/assets/index-QFqtuRrZ.js +0 -23
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getUserConfigPath } from '../core/config/user-config.js';
|
|
4
|
+
// Durable per-turn snapshot of the content pikiloom actually delivered.
|
|
5
|
+
//
|
|
6
|
+
// The agent CLIs are the source of truth for transcript history, but their session jsonl is
|
|
7
|
+
// lossy under two upstream conditions we cannot prevent: (1) a turn's closing reply dies before
|
|
8
|
+
// the CLI flushes it to disk (kill/flush race), and (2) the CLI's resume rewrites the jsonl in
|
|
9
|
+
// place and drops a turn that never got a synthetic-free conclusion. In both cases pikiloom has
|
|
10
|
+
// already streamed the complete reply to the user (turn-audit confirms ok/end_turn), yet a later
|
|
11
|
+
// history render reads only a "No response requested." tombstone — the swallow.
|
|
12
|
+
//
|
|
13
|
+
// This sidecar is the missing durable copy: one JSON line per delivered turn, keyed by the user
|
|
14
|
+
// prompt, so the claude history renderer can restore the real reply at a tombstone instead of
|
|
15
|
+
// showing a bare "ended before a closing message" notice. It complements turn-audit.jsonl (which
|
|
16
|
+
// records how a turn ended, not what it said). See [[posttool-empty-result-no-response-requested]].
|
|
17
|
+
const MAX_SNAPSHOT_BYTES = 512 * 1024; // per-session cap, single-slot rotation
|
|
18
|
+
const MAX_TEXT_CHARS = 40_000; // don't archive megabyte replies verbatim
|
|
19
|
+
const STALE_MS = 30 * 24 * 60 * 60 * 1000;
|
|
20
|
+
// Match the raw prompt pikiloom ran against the user text reconstructed from the jsonl. Both
|
|
21
|
+
// sides normalize identically: collapse whitespace, trim, cap length. Case is preserved (matching
|
|
22
|
+
// is mostly CJK / mixed-script prose).
|
|
23
|
+
export function normalizeSnapshotPrompt(s) {
|
|
24
|
+
return (s || '').replace(/\s+/g, ' ').trim().slice(0, 240);
|
|
25
|
+
}
|
|
26
|
+
function snapshotDir() {
|
|
27
|
+
return path.join(path.dirname(getUserConfigPath()), 'turn-snapshots');
|
|
28
|
+
}
|
|
29
|
+
function sessionSnapshotPath(sessionId) {
|
|
30
|
+
// sessionId is a uuid / codex rollout id — safe as a filename, but strip separators defensively.
|
|
31
|
+
const safe = sessionId.replace(/[^A-Za-z0-9_-]/g, '_');
|
|
32
|
+
return path.join(snapshotDir(), `${safe}.jsonl`);
|
|
33
|
+
}
|
|
34
|
+
// A finished turn whose delivered message is only a placeholder or an appended incomplete-notice
|
|
35
|
+
// carries nothing worth restoring. Strip a trailing "⚠️ …" note (composeKernelFinalPresentation
|
|
36
|
+
// and the legacy driver append one to real prose) and drop the empty/placeholder shapes.
|
|
37
|
+
function bodyWorthSaving(message) {
|
|
38
|
+
let text = (message || '').replace(/\n\n⚠️[^\n]*$/u, '').trim();
|
|
39
|
+
if (!text)
|
|
40
|
+
return null;
|
|
41
|
+
if (text === '(no textual response)' || text === '(no output)')
|
|
42
|
+
return null;
|
|
43
|
+
if (text.length > MAX_TEXT_CHARS)
|
|
44
|
+
text = text.slice(0, MAX_TEXT_CHARS);
|
|
45
|
+
return text;
|
|
46
|
+
}
|
|
47
|
+
let cleanedThisProcess = false;
|
|
48
|
+
function cleanupStaleSnapshots() {
|
|
49
|
+
if (cleanedThisProcess)
|
|
50
|
+
return;
|
|
51
|
+
cleanedThisProcess = true;
|
|
52
|
+
try {
|
|
53
|
+
const dir = snapshotDir();
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
for (const name of fs.readdirSync(dir)) {
|
|
56
|
+
const p = path.join(dir, name);
|
|
57
|
+
try {
|
|
58
|
+
if (now - fs.statSync(p).mtimeMs > STALE_MS)
|
|
59
|
+
fs.unlinkSync(p);
|
|
60
|
+
}
|
|
61
|
+
catch { /* skip */ }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch { /* no dir yet */ }
|
|
65
|
+
}
|
|
66
|
+
export function recordDeliveredTurn(entry) {
|
|
67
|
+
try {
|
|
68
|
+
if (!entry.sessionId)
|
|
69
|
+
return;
|
|
70
|
+
const text = bodyWorthSaving(entry.message);
|
|
71
|
+
if (!text)
|
|
72
|
+
return;
|
|
73
|
+
const prompt = (entry.prompt || '').slice(0, 500);
|
|
74
|
+
const dir = snapshotDir();
|
|
75
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
76
|
+
cleanupStaleSnapshots();
|
|
77
|
+
const file = sessionSnapshotPath(entry.sessionId);
|
|
78
|
+
try {
|
|
79
|
+
if (fs.statSync(file).size > MAX_SNAPSHOT_BYTES)
|
|
80
|
+
fs.renameSync(file, `${file}.1`);
|
|
81
|
+
}
|
|
82
|
+
catch { /* no file yet */ }
|
|
83
|
+
const line = JSON.stringify({
|
|
84
|
+
ts: new Date().toISOString(),
|
|
85
|
+
prompt,
|
|
86
|
+
promptNorm: normalizeSnapshotPrompt(prompt),
|
|
87
|
+
text,
|
|
88
|
+
model: entry.model ?? null,
|
|
89
|
+
ok: entry.ok,
|
|
90
|
+
stopReason: entry.stopReason ?? null,
|
|
91
|
+
});
|
|
92
|
+
fs.appendFileSync(file, line + '\n');
|
|
93
|
+
}
|
|
94
|
+
catch { /* snapshotting is best-effort by design */ }
|
|
95
|
+
}
|
|
96
|
+
// Ordered list (append order == turn order) of delivered turns for a session, for render merge.
|
|
97
|
+
export function loadDeliveredTurns(sessionId) {
|
|
98
|
+
if (!sessionId)
|
|
99
|
+
return [];
|
|
100
|
+
try {
|
|
101
|
+
const content = fs.readFileSync(sessionSnapshotPath(sessionId), 'utf-8');
|
|
102
|
+
const out = [];
|
|
103
|
+
for (const raw of content.split('\n')) {
|
|
104
|
+
if (!raw.trim() || raw[0] !== '{')
|
|
105
|
+
continue;
|
|
106
|
+
try {
|
|
107
|
+
const ev = JSON.parse(raw);
|
|
108
|
+
if (typeof ev.text !== 'string' || !ev.text)
|
|
109
|
+
continue;
|
|
110
|
+
out.push({
|
|
111
|
+
prompt: typeof ev.prompt === 'string' ? ev.prompt : '',
|
|
112
|
+
promptNorm: typeof ev.promptNorm === 'string' ? ev.promptNorm : normalizeSnapshotPrompt(ev.prompt || ''),
|
|
113
|
+
text: ev.text,
|
|
114
|
+
model: typeof ev.model === 'string' ? ev.model : null,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
catch { /* skip bad line */ }
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// A per-prompt FIFO of delivered replies. A tombstone consumes the next reply recorded for its
|
|
126
|
+
// preceding prompt. Front-pop is exact for the common case (a unique recent prompt was swallowed);
|
|
127
|
+
// for a prompt repeated across turns with mixed outcomes the match is by order and may attach a
|
|
128
|
+
// sibling occurrence's reply — still strictly better than a bare tombstone.
|
|
129
|
+
export function buildRecoveryQueue(turns) {
|
|
130
|
+
const q = new Map();
|
|
131
|
+
for (const t of turns) {
|
|
132
|
+
if (!t.promptNorm)
|
|
133
|
+
continue;
|
|
134
|
+
const list = q.get(t.promptNorm);
|
|
135
|
+
if (list)
|
|
136
|
+
list.push(t.text);
|
|
137
|
+
else
|
|
138
|
+
q.set(t.promptNorm, [t.text]);
|
|
139
|
+
}
|
|
140
|
+
return q;
|
|
141
|
+
}
|
package/dist/bot/bot.js
CHANGED
|
@@ -11,6 +11,7 @@ import { resolveGuiIntegrationConfig } from '../agent/mcp/bridge.js';
|
|
|
11
11
|
import { composeSessionToolPrompt } from '../agent/mcp/capabilities.js';
|
|
12
12
|
import { terminateProcessTree } from '../core/process-control.js';
|
|
13
13
|
import { appendTurnAudit } from '../core/turn-audit.js';
|
|
14
|
+
import { recordDeliveredTurn } from '../agent/turn-snapshot.js';
|
|
14
15
|
import { expandTilde } from '../core/platform.js';
|
|
15
16
|
import { VERSION } from '../core/version.js';
|
|
16
17
|
import { buildHumanLoopResponse, createEmptyHumanLoopAnswer, currentHumanLoopQuestion, isHumanLoopAwaitingText, setHumanLoopOption, setHumanLoopText, skipHumanLoopQuestion, summarizeResolvedHumanLoopAnswers, } from './human-loop.js';
|
|
@@ -2132,6 +2133,16 @@ export class Bot {
|
|
|
2132
2133
|
error: result.error ? String(result.error).slice(0, 500) : null,
|
|
2133
2134
|
elapsedS: result.elapsedS, model: result.model ?? resolvedModel, promptPreview: prompt.slice(0, 120),
|
|
2134
2135
|
});
|
|
2136
|
+
// Durable copy of what we just delivered, so the history render can restore it if the CLI's
|
|
2137
|
+
// jsonl later loses this turn to a flush race or an in-place resume rewrite (the swallow).
|
|
2138
|
+
// claude-only: it is the driver whose renderer knows how to merge these at a tombstone.
|
|
2139
|
+
if (cs.agent === 'claude') {
|
|
2140
|
+
recordDeliveredTurn({
|
|
2141
|
+
sessionId: result.sessionId || cs.sessionId || null,
|
|
2142
|
+
prompt, message: result.message, model: result.model ?? resolvedModel ?? null,
|
|
2143
|
+
ok: result.ok, stopReason: result.stopReason ?? null,
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2135
2146
|
if (cs.agent === 'claude' && workflowEnabled && result.thinkingEffort) {
|
|
2136
2147
|
result.thinkingEffort = 'ultra';
|
|
2137
2148
|
}
|
|
@@ -26,6 +26,31 @@ function parsePageSize(value, fallback = DEFAULT_SESSION_PAGE_SIZE) {
|
|
|
26
26
|
return fallback;
|
|
27
27
|
return Math.min(parsed, MAX_SESSION_PAGE_SIZE);
|
|
28
28
|
}
|
|
29
|
+
function sameWorkspacePath(a, b) {
|
|
30
|
+
if (!a || !b)
|
|
31
|
+
return false;
|
|
32
|
+
return path.resolve(a) === path.resolve(b);
|
|
33
|
+
}
|
|
34
|
+
export function isRemovableWorkspacePath(workspacePath, runtimeWorkdir) {
|
|
35
|
+
return !!workspacePath && !sameWorkspacePath(workspacePath, runtimeWorkdir);
|
|
36
|
+
}
|
|
37
|
+
export function projectWorkspacesForDashboard(workspaces, runtimeWorkdir, nowIso = new Date().toISOString()) {
|
|
38
|
+
const runtimePath = runtimeWorkdir ? path.resolve(runtimeWorkdir) : '';
|
|
39
|
+
const projected = workspaces.map(workspace => sameWorkspacePath(workspace.path, runtimePath)
|
|
40
|
+
? { ...workspace, isDefault: true, removable: false }
|
|
41
|
+
: { ...workspace, removable: true });
|
|
42
|
+
if (runtimePath && !projected.some(workspace => sameWorkspacePath(workspace.path, runtimePath))) {
|
|
43
|
+
projected.unshift({
|
|
44
|
+
path: runtimePath,
|
|
45
|
+
name: path.basename(runtimePath),
|
|
46
|
+
order: -1,
|
|
47
|
+
addedAt: nowIso,
|
|
48
|
+
isDefault: true,
|
|
49
|
+
removable: false,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return projected;
|
|
53
|
+
}
|
|
29
54
|
function paginateSessionResult(items, page, limit) {
|
|
30
55
|
const total = items.length;
|
|
31
56
|
const totalPages = Math.max(1, Math.ceil(total / limit));
|
|
@@ -242,15 +267,7 @@ app.get('/api/workspaces', (c) => {
|
|
|
242
267
|
const workspaces = loadWorkspaces();
|
|
243
268
|
const config = loadUserConfig();
|
|
244
269
|
const rwd = runtime.getRuntimeWorkdir(config);
|
|
245
|
-
|
|
246
|
-
workspaces.unshift({
|
|
247
|
-
path: rwd,
|
|
248
|
-
name: path.basename(rwd),
|
|
249
|
-
order: -1,
|
|
250
|
-
addedAt: new Date().toISOString(),
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
return c.json({ ok: true, workspaces });
|
|
270
|
+
return c.json({ ok: true, workspaces: projectWorkspacesForDashboard(workspaces, rwd) });
|
|
254
271
|
});
|
|
255
272
|
app.post('/api/workspaces', async (c) => {
|
|
256
273
|
try {
|
|
@@ -271,6 +288,10 @@ app.delete('/api/workspaces', async (c) => {
|
|
|
271
288
|
const wsPath = typeof body?.path === 'string' ? body.path.trim() : '';
|
|
272
289
|
if (!wsPath)
|
|
273
290
|
return c.json({ ok: false, error: 'path is required' }, 400);
|
|
291
|
+
const runtimeWorkdir = runtime.getRuntimeWorkdir(loadUserConfig());
|
|
292
|
+
if (!isRemovableWorkspacePath(wsPath, runtimeWorkdir)) {
|
|
293
|
+
return c.json({ ok: false, error: 'default workspace cannot be removed' }, 400);
|
|
294
|
+
}
|
|
274
295
|
const removed = removeWorkspace(wsPath);
|
|
275
296
|
return c.json({ ok: true, removed });
|
|
276
297
|
}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,j as s}from"./react-vendor-C7Sl8SE7.js";import{c as on,I as an,S as ze,m as We,a as T,u as pt,d as un,g as cn,l as dn,e as fn,j as mn,f as gn,s as pn,Y as hn}from"./index-Iot9Vn3K.js";import{s as xn,l as kn,n as Et,m as Sn,a as bn,o as vn,d as In,b as Tn,p as yn,h as Mt,c as Qe,e as Rn,f as Pt,g as $e,i as Ke,j as jn,k as wn,T as Nn,R as An,U as Ct,q as Ln,r as Ut,L as qt,t as On,I as En}from"./index-QFqtuRrZ.js";import{M as Ht,a as Ft}from"./Modal-Cy1zHcC7.js";import"./router-DHISdpPk.js";import"./Select-D4DbOixc.js";import"./DirBrowser-H0N2gMRB.js";import"./markdown-DxQYQFeH.js";import"./ExtensionsTab-5uaiMRcm.js";function Mn({snapshot:o}){const[t,f]=n.useState(o.currentIndex??0),[N,y]=n.useState(""),[x,p]=n.useState(!1),[C,S]=n.useState(null);n.useEffect(()=>{f(o.currentIndex??0),y(""),S(null)},[o.promptId,o.currentIndex]);const O=o.questions||[],R=O[t]||null,Z=O.length,U=!!(R?.options&&R.options.length),E=U?!!R?.allowFreeform:!0,de=c=>{c&&(f(i=>i+1),y(""))},fe=async c=>{if(!x){p(!0),S(null);try{const i=await T.interactionSelectOption(o.promptId,c);if(!i.ok){S(i.error||"Failed to submit selection.");return}de(i.advanced)}catch(i){S(i?.message||"Network error.")}finally{p(!1)}}},me=async()=>{if(x)return;const c=N.trim();if(!c&&!R?.allowEmpty){S("Please enter a response.");return}p(!0),S(null);try{const i=await T.interactionSubmitText(o.promptId,c);if(!i.ok){S(i.error||"Failed to submit answer.");return}de(i.advanced)}catch(i){S(i?.message||"Network error.")}finally{p(!1)}},m=async()=>{if(!x){p(!0),S(null);try{const c=await T.interactionSkip(o.promptId);if(!c.ok){S(c.error||"Failed to skip.");return}de(c.advanced)}catch(c){S(c?.message||"Network error.")}finally{p(!1)}}},ee=async()=>{if(!x){p(!0);try{await T.interactionCancel(o.promptId)}catch{}}},te=n.useMemo(()=>{const c=[];return o.hint&&c.push(o.hint),Z>1&&c.push(`Question ${t+1} of ${Z}`),c.join(" · ")||void 0},[o.hint,t,Z]);return s.jsxs(Ht,{open:!0,onClose:ee,wide:U&&(R?.options?.length||0)>3,children:[s.jsx(Ft,{title:o.title||"Pikiloom needs your input",description:te,onClose:ee}),R?s.jsxs("div",{className:"space-y-4",children:[s.jsxs("div",{children:[s.jsx("div",{className:"text-xs font-medium uppercase tracking-wide text-fg-5",children:R.header||"Question"}),s.jsx("div",{className:"mt-1 whitespace-pre-wrap text-sm leading-relaxed text-fg",children:R.prompt})]}),U&&s.jsx("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:(R.options||[]).map(c=>s.jsxs("button",{type:"button",disabled:x,onClick:()=>fe(c.value||c.label),className:on("group rounded-lg border border-edge bg-panel-alt px-3 py-2 text-left text-sm transition","hover:border-control-border-h hover:bg-control-h hover:shadow-sm","focus:outline-none focus:ring-2 focus:ring-[var(--th-glow-a)]","disabled:cursor-not-allowed disabled:opacity-50"),children:[s.jsx("div",{className:"font-medium text-fg group-hover:text-fg",children:c.label}),c.description&&s.jsx("div",{className:"mt-0.5 text-xs leading-snug text-fg-4",children:c.description})]},c.value||c.label))}),E&&s.jsx("div",{children:s.jsx(an,{value:N,onChange:c=>y(c.target.value),onKeyDown:c=>{c.key==="Enter"&&!c.shiftKey&&!x&&(c.preventDefault(),me())},placeholder:U?"Or type a custom answer…":"Type your answer…",disabled:x,autoFocus:!U})}),C&&s.jsx("div",{className:"rounded-md border border-red-300/40 bg-red-500/10 px-3 py-2 text-xs text-red-600",children:C}),s.jsxs("div",{className:"flex items-center justify-between gap-3",children:[s.jsx("div",{className:"text-xs text-fg-5",children:x?s.jsxs("span",{className:"inline-flex items-center gap-2",children:[s.jsx(ze,{})," Submitting…"]}):s.jsxs("span",{children:["Press ",s.jsx("kbd",{className:"rounded border border-edge bg-panel-alt px-1.5 py-0.5 text-[10px] uppercase",children:"Enter"})," to send"]})}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(We,{variant:"ghost",size:"sm",onClick:m,disabled:x,children:"Skip"}),E&&s.jsx(We,{variant:"primary",size:"sm",onClick:me,disabled:x||!N.trim()&&!R.allowEmpty,children:"Submit"})]})]})]}):s.jsxs("div",{className:"py-6 text-center text-sm text-fg-5",children:[s.jsx(ze,{className:"mr-2 inline-block"})," Waiting for the agent…"]})]})}function Pn(o){return o.isNull?(o.localStreamPending||o.holdsActiveState)&&!o.holdExpired?"reject-null":"apply":(typeof o.updatedAt=="number"?o.updatedAt:0)<o.lastAppliedUpdatedAt?"reject-stale":"apply"}function Cn(o,t){return typeof t!="number"?o:t>o?t:o}function Un(o,t){return!o||!o.length?[]:t.size?o.filter(f=>!t.has(f)):o.slice()}function qn(o,t,f,N){if(!o.size)return o;const y=new Set(t);let x=!1;const p=new Map;for(const[C,S]of o){if(f-S>N||!y.has(C)){x=!0;continue}p.set(C,S)}return x?p:o}const ht=12,Dt=160,Dn=96,Hn=[],Fn=[],Bn=[],_n={phase:"streaming",text:"",thinking:""},Qn=20,$n=6e4,Kn=15e3,zn=7e3,ie=new Map;function Wn(o,t){return`${o}:${t}`}function Yn(o,t){for(ie.delete(o),ie.set(o,t);ie.size>Qn;)ie.delete(ie.keys().next().value)}const lr=n.memo(function({session:t,workdir:f,active:N=!0,onSessionChange:y,initialPendingPrompt:x,initialPendingImageUrls:p,onPendingPromptConsumed:C}){const S=pt(e=>e.locale),O=pt(e=>e.agentStatus?.agents?.find(r=>r.agent===t.agent)??null),R=O?.selectedEffort??null,Z=O?.selectedModel??null,U=pt(e=>e.modelLayer),E=t.profileId?U?.profiles.find(e=>e.id===t.profileId)??null:null,de=E?U?.providers.find(e=>e.id===E.providerId)??null:null,fe=t.profileId===void 0?O?.byokProviderName??null:de?.name??null,me=t.profileId===void 0?O?.byokProfileName??null:E&&E.name.trim().toLowerCase()!==E.modelId.trim().toLowerCase()?E.name:null,m=n.useMemo(()=>un(S),[S]),ee=cn(t.agent||""),te=dn(t),c=!!x||!!(p&&p.length),[i,Ye]=n.useState(null),[Ge,ge]=n.useState(!c),[pe,xt]=n.useState(!1),[u,B]=n.useState(null),[_,he]=n.useState(!1),[q,Ve]=n.useState(null),[Bt,kt]=n.useState(0),[_t,Xe]=n.useState(null),[D,Re]=n.useState([]),[Qt,je]=n.useState([]),[xe,Je]=n.useState([]),[h,ne]=n.useState(x||null),[M,re]=n.useState(p||[]),[$t,se]=n.useState(null),Q=n.useRef(null);Q.current=$t;const St=n.useRef(h);St.current=h;const[we,H]=n.useState([]),Ne=n.useRef([]);Ne.current=we;const ke=n.useRef(null),[Kt,bt]=n.useState(null),[Ae,Se]=n.useState(null),[be,Ze]=n.useState(""),[$,et]=n.useState(!1),zt=!!O?.capabilities?.fork,tt=n.useRef(null),L=n.useRef(p||[]),K=n.useRef(u),nt=n.useRef(_);K.current=u,nt.current=_;const rt=n.useRef(D);rt.current=D;const vt=n.useRef(q);vt.current=q;const z=n.useRef(null),Le=n.useRef(null),W=n.useRef(!0),le=n.useRef(!1),Oe=n.useRef(null),st=n.useRef(!1),P=n.useRef(c),oe=n.useRef(!1),Y=n.useRef(!1),lt=n.useRef(!1),ot=n.useRef(!1),G=n.useRef(null),Ee=n.useRef(0),ve=n.useRef(Date.now()),Ie=n.useRef(new Map),It=n.useRef({model:null,effort:null}),Wt=n.useCallback(e=>{It.current=e},[]);n.useEffect(()=>{lt.current||!c||(lt.current=!0,x&&!h&&ne(x),p&&p.length&&!M.length&&(re(p),L.current=p),ge(!1),kt(e=>e+1),C?.())},[c,C]);const A=n.useCallback(()=>{ne(null),re(e=>{for(const r of e)URL.revokeObjectURL(r);return[]}),L.current=[],se(null)},[]),V=n.useCallback(()=>{H(e=>{if(!e.length)return e;for(const r of e)for(const l of r.imageUrls)URL.revokeObjectURL(l);return[]}),ke.current=null},[]),Tt=n.useCallback((e,r)=>{ve.current=Date.now();const l=xn({streaming:nt.current,liveStreamPhase:K.current?.phase??null,streamPhase:vt.current,queuedTaskCount:rt.current.length,pendingQueuedCount:Ne.current.length}),a=r||[];if(l){const d=`local-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;ke.current=d,H(k=>[...k,{localId:d,taskId:null,prompt:e||"",imageUrls:a}]);return}K.current?.phase==="done"&&B(null);for(const d of L.current)URL.revokeObjectURL(d);ke.current=null,ne(e||null),re(a),L.current=a,se(null)},[]),Yt=n.useCallback(e=>{const r=ke.current;if(r){ke.current=null,H(l=>{const a=l.findIndex(k=>k.localId===r);if(a<0)return l;const d=l.slice();return d[a]={...d[a],taskId:e},d});return}se(e)},[]),Gt=n.useCallback(async()=>{if(!Ae)return;const e=be.trim();if(e){et(!0);try{const r=await T.forkSession(f,t.agent||"",t.sessionId,Ae.atTurn,e,{});if(!r.ok||!r.sessionKey){et(!1);return}const[l,a]=r.sessionKey.split(":");Se(null),Ze(""),y?.({agent:l,sessionId:a,workdir:f})}finally{et(!1)}}},[Ae,be,f,t.agent,t.sessionId,y]);tt.current=Gt;const Me=n.useCallback(async(e,r={})=>{try{const l=await kn({workdir:f,agent:t.agent||"",sessionId:t.sessionId,rich:!0,turnOffset:e.turnOffset,turnLimit:e.turnLimit,lastNTurns:e.lastNTurns},{force:r.force});return l.ok?Et(l):null}catch{return null}},[f,t.agent,t.sessionId]),j=n.useCallback(async({keepOlder:e,force:r=!1,scrollToBottom:l=!1})=>{const a=t.sessionId;if(Oe.current===a)return!1;Oe.current=a;try{const d=await Me({turnOffset:0,turnLimit:ht},{force:r});if(!d||t.sessionId!==a)return!1;if(l&&(le.current=!0),Ye(k=>!k||!e?d:Sn(k,d)),ge(!1),oe.current&&(oe.current=!1,A()),Y.current){const k=Y.current;Y.current=!1;const X=k!==!0?k.taskId:null;K.current&&(k===!0||K.current.taskId===X)&&B(null)}return!0}finally{Oe.current===a&&(Oe.current=null)}},[Me,A,t.sessionId]),Pe=n.useCallback(async()=>{if(!i?.hasOlder||st.current)return;const e=z.current;e&&(Le.current={scrollHeight:e.scrollHeight,scrollTop:e.scrollTop}),st.current=!0,xt(!0);try{const r=await Me({turnOffset:Math.max(0,i.totalTurns-i.startTurn),turnLimit:ht});r?Ye(l=>l?bn(l,r):r):Le.current=null}finally{st.current=!1,xt(!1)}},[Me,i]),Ce=n.useRef(null),ae=n.useCallback((e,r="ws")=>{const l=nt.current||rt.current.length>0,a=Date.now()-ve.current>Kn;if(Pn({updatedAt:e?.updatedAt,isNull:!e,lastAppliedUpdatedAt:Ee.current,localStreamPending:P.current,holdsActiveState:l,holdExpired:a})!=="apply")return;const k=!e&&a&&(P.current||l);if(e&&(ve.current=Date.now(),Ee.current=Cn(Ee.current,e.updatedAt)),e?.sessionId&&e.sessionId!==t.sessionId&&(ot.current=!0,Te.current=`${t.agent}:${e.sessionId}`,y?.({agent:t.agent||"",sessionId:e.sessionId,workdir:f})),!e){const g=Ce.current;he(!1),k?(P.current=!1,oe.current=!0,Y.current=!0,V(),j({keepOlder:!0,force:!0,scrollToBottom:W.current})):g==="streaming"?(oe.current=!0,Y.current=!0,j({keepOlder:!0,force:!0,scrollToBottom:W.current})):B(null),k||(P.current&&g!=="streaming"?j({keepOlder:!0,force:!0}):(g==="done"&&(A(),V()),g!==null&&(P.current=!1))),Xe(null),Ve(null),Re([]),je([]),Je([]),Ce.current=null;return}Ve(e.phase),Xe(e.taskId||null);const X=[];e.taskId&&X.push(e.taskId),Array.isArray(e.queuedTaskIds)&&X.push(...e.queuedTaskIds),Ie.current=qn(Ie.current,X,Date.now(),$n);const ue=Ie.current,mt=Un(e.queuedTaskIds,ue),Ot=(Array.isArray(e.queuedTasks)?e.queuedTasks:[]).filter(g=>!ue.has(g.taskId));if(Re(mt.length?mt:Hn),je(Ot.length?Ot:Fn),Je(Array.isArray(e.interactions)&&e.interactions.length?e.interactions:Bn),vn({pendingTaskId:Q.current,streamTaskId:e.taskId||null,queuedTaskIds:e.queuedTaskIds})){const g=Q.current,w=St.current||"",I=L.current;H(v=>v.some(ce=>ce.taskId===g)?v:[...v,{localId:`demote-${g}`,taskId:g,prompt:w,imageUrls:I}]),ne(null),re([]),L.current=[],se(null),Q.current=null}if(e.phase==="streaming"){if(B({taskId:e.taskId||null,phase:"streaming",text:e.text||"",thinking:e.thinking||"",activity:e.activity,plan:e.plan??null,model:e.model??null,effort:e.effort??null,previewMeta:e.previewMeta??null,subAgents:e.previewMeta?.subAgents??null,generatingImages:e.previewMeta?.generatingImages??0,artifacts:e.artifacts??null,startedAt:typeof e.startedAt=="number"?e.startedAt:null,error:null,question:e.question??null,questionBlocks:e.questionBlocks??null}),he(!0),e.taskId&&e.taskId!==Q.current){const g=Ne.current,w=g.findIndex(I=>I.taskId===e.taskId);if(w>=0){const I=g[w];for(const v of L.current)URL.revokeObjectURL(v);ne(I.prompt||null),re(I.imageUrls),L.current=I.imageUrls,se(e.taskId),H(v=>v.filter((ce,J)=>J!==w))}}W.current&&(le.current=!0)}else if(e.phase==="queued")B(null),he(!1);else if(e.phase==="done"){const g=In(K.current?.taskId??null,e.taskId||null),w=mt.length>0;if(g){he(!1),B(J=>J?{...J,phase:"done",error:e.error??null}:e.error?{taskId:e.taskId||null,phase:"done",text:"",thinking:"",activity:"",plan:null,model:e.model??null,effort:e.effort??null,previewMeta:e.previewMeta??null,subAgents:e.previewMeta?.subAgents??null,generatingImages:e.previewMeta?.generatingImages??0,artifacts:e.artifacts??null,error:e.error,question:e.question??null,questionBlocks:e.questionBlocks??null}:J);const I=K.current,v=!!I&&Tn(I),ce=!!e.incomplete&&v&&!w;if(Ce.current!=="done"){w||(oe.current=!0),Y.current=ce?!1:{taskId:e.taskId||null},j({keepOlder:!0,force:!0,scrollToBottom:W.current});const J=t.agent||"",rn=t.sessionId,sn=Te.current;G.current&&clearTimeout(G.current),G.current=setTimeout(()=>{G.current=null,T.getSessionStreamState(J,rn).then(ln=>{Te.current===sn&&Ue.current(ln.state,"seed")}).catch(()=>{})},900)}}w||(P.current=!1)}const gt=new Set;if(e.taskId&>.add(e.taskId),Array.isArray(e.queuedTaskIds))for(const g of e.queuedTaskIds)gt.add(g);H(g=>{let w=!1;const I=[];for(const v of g)if(!v.taskId||gt.has(v.taskId))I.push(v);else{for(const ce of v.imageUrls)URL.revokeObjectURL(ce);w=!0}return w?I:g}),Ce.current=e.phase},[A,V,j,t.sessionId,t.agent,y,f]),Ue=n.useRef(ae);Ue.current=ae;const yt=n.useCallback(()=>{P.current=!0,ve.current=Date.now(),kt(e=>e+1)},[]);n.useEffect(()=>()=>{G.current&&(clearTimeout(G.current),G.current=null)},[]);const Vt=n.useCallback(async e=>{try{Ie.current.set(e,Date.now()),await T.recallSessionMessage(e),Q.current===e&&A(),H(r=>{let l=!1;const a=[];for(const d of r)if(d.taskId===e){for(const k of d.imageUrls)URL.revokeObjectURL(k);l=!0}else a.push(d);return l?a:r}),Re(r=>r.filter(l=>l!==e)),je(r=>r.filter(l=>l.taskId!==e)),Xe(r=>r===e?null:r)}catch{}},[A]),Xt=n.useCallback(async e=>{const r=Ne.current.find(l=>l.taskId===e)||null;if(r&&r.imageUrls.length>0){for(const l of L.current)URL.revokeObjectURL(l);ne(r.prompt||null),re(r.imageUrls),L.current=r.imageUrls,se(e),Q.current=e,H(l=>l.filter(a=>a.taskId!==e))}try{await T.steerSession(e)}catch{}},[]),Jt=n.useCallback(async()=>{try{await T.stopSession(t.agent||"",t.sessionId)}catch{}},[t.agent,t.sessionId]),qe=Wn(t.agent||"",t.sessionId);n.useEffect(()=>{if(ot.current){ot.current=!1;let d=!1;return j({keepOlder:!0,force:!0}).finally(()=>{d||ge(!1)}),()=>{d=!0}}let e=!1;const r=yn({workdir:f,agent:t.agent||"",sessionId:t.sessionId,rich:!0,turnOffset:0,turnLimit:ht},{allowStale:!0}),l=c&&!lt.current,a=r?.ok?Et(r):ie.get(qe)||null;return ge(l?!1:!a),Ye(a),B(null),he(!1),Ve(null),Re([]),je([]),Je([]),Ee.current=0,ve.current=Date.now(),Ie.current=new Map,l||(A(),V(),P.current=!1,oe.current=!1,Y.current=!1),W.current=!0,le.current=!0,l||j({keepOlder:!1,force:!0}).finally(()=>{e||ge(!1)}),()=>{e=!0}},[j,t.agent,t.sessionId,f,qe,A,V]),n.useEffect(()=>{i&&i.turns.length>0&&Yn(qe,i)},[qe,i]),n.useEffect(()=>{N&&j({keepOlder:!0,force:!0})},[N,j]);const Te=n.useRef(`${t.agent}:${t.sessionId}`);Te.current=`${t.agent}:${t.sessionId}`,fn("stream-update",n.useCallback(e=>{e.key===Te.current&&ae(e.snapshot??null)},[ae])),n.useEffect(()=>{let e=!0;return T.getSessionStreamState(t.agent||"",t.sessionId).then(r=>{e&&Ue.current(r.state,"seed")}).catch(()=>{}),()=>{e=!1}},[t.agent,t.sessionId,Bt]),mn(n.useCallback(()=>{T.getSessionStreamState(t.agent||"",t.sessionId).then(e=>{ae(e.state,"seed")}).catch(()=>{}),j({keepOlder:!0,force:!0})},[ae,t.agent,t.sessionId,j]));const Rt=_||!!q||D.length>0||!!h||we.length>0;n.useEffect(()=>{if(!N||!Rt)return;const e=setInterval(()=>{typeof document<"u"&&document.visibilityState!=="visible"||T.getSessionStreamState(t.agent||"",t.sessionId).then(r=>Ue.current(r.state,"seed")).catch(()=>{})},zn);return()=>clearInterval(e)},[N,Rt,t.agent,t.sessionId]),n.useEffect(()=>{!P.current&&te!=="running"&&!_&&!u&&!q&&D.length===0&&(A(),V())},[te,_,u,q,D.length,A,V]),n.useLayoutEffect(()=>{const e=Le.current,r=z.current;!e||!r||(Le.current=null,r.scrollTop=e.scrollTop+(r.scrollHeight-e.scrollHeight))},[i?.turns.length]),n.useLayoutEffect(()=>{if(!le.current)return;const e=z.current;e&&(le.current=!1,e.scrollTop=e.scrollHeight,requestAnimationFrame(()=>{W.current&&(e.scrollTop=e.scrollHeight)}))},[i,u]),n.useLayoutEffect(()=>{if(!h)return;const e=z.current;e&&(e.scrollTop=e.scrollHeight)},[h]),n.useEffect(()=>{if(!i?.hasOlder||Ge||pe)return;const e=z.current;e&&e.scrollHeight<=e.clientHeight+Dt&&Pe()},[i?.hasOlder,i?.turns.length,Pe,Ge,pe]);const Zt=n.useCallback(()=>{const e=z.current;if(!e)return;const r=e.scrollHeight-e.scrollTop-e.clientHeight;W.current=r<=Dn,e.scrollTop<=Dt&&Pe()},[Pe]),ye=u?.model||t.model||Z||null,De=gn(t.agent||"",u?.effort||t.thinkingEffort||R||null,t.workflowEnabled??O?.workflowEnabled)||null,at=me&&(!ye||ye===Z)?me:ye?pn(ye):null,ut=hn(t,{streaming:_,hasLiveStream:!!u,streamPhase:q,queuedTaskCount:D.length}),b=i?.turns||[],jt=n.useMemo(()=>{for(let e=b.length-1;e>=0;e--){const r=b[e].assistant?.blocks;if(r)for(let l=r.length-1;l>=0;l--){const a=r[l];if(a.type==="plan"&&Mt(a.plan))return a.plan}}return null},[b]),He=n.useMemo(()=>{if(!M.length||!b.length)return!1;const e=b[b.length-1];return!e.user||!Qe(e.user.text,h)?!1:e.user.blocks.filter(l=>l.type==="image").length<M.length},[b,h,M.length]),ct=n.useMemo(()=>M.length?M.map(e=>({type:"image",content:e})):!h||!u?.questionBlocks?.length?[]:Qe(h,u.question)?u.questionBlocks:[],[M,h,u]),wt=u?.question||null,Fe=Rn(h,wt),it=Pt(wt,h),Nt=b.length>0?b[b.length-1]?.user?.text:null,At=!!Fe&&b.length>0&&$e(Nt,Fe),F=n.useMemo(()=>{let e=b;if(He){const ue=e[e.length-1];e=[...e.slice(0,-1),{...ue,user:null}]}if(!u||!e.length)return e;const r=e[e.length-1],l=Fe;if(!r.assistant)return!!r.user&&!!l&&!Qe(r.user.text,l)&&($e(r.user.text,l)||Pt(l,r.user.text))?[...e.slice(0,-1),{...r,user:{...r.user,text:l}}]:e;const a=(u.text||"").trim(),d=r.assistant.text?.trim()||"";if(!(l!=null?$e(r.user?.text,l):!!d&&!!a&&(a.startsWith(d)||d.startsWith(a))))return e;const X=r.user&&l&&!Qe(r.user.text,l)?{...r.user,text:l}:r.user;return[...e.slice(0,-1),{...r,user:X,assistant:null}]},[b,u,Fe,He]),en=(!!h||ct.length>0)&&!it&&(He||!At)&&!u,tn=!!u&&Ke(u)&&u.phase==="streaming",dt=jn({sessionRunning:te==="running",streaming:_,streamPhase:q,queuedTaskCount:D.length,pendingQueuedCount:we.length,liveTurnStreaming:tn,pendingBubbleDots:en}),Be=dt&&F.length>0?F[F.length-1]:null,_e=!!Be?.assistant&&wn(Be.assistant),ft=_e?Be.assistant.usage??null:null,nn=_e?Be.assistant.blocks.filter(e=>e.type==="tool_use").length:0,Lt=(()=>{if(!dt||te!=="running")return null;const e=t.runUpdatedAt?Date.parse(t.runUpdatedAt):NaN;return Number.isFinite(e)?e:null})();return s.jsxs("div",{className:"flex flex-col h-full overflow-hidden",children:[s.jsx("div",{ref:z,onScroll:Zt,className:"flex-1 overflow-y-auto overscroll-contain",children:Ge&&!h&&!M.length&&!u?s.jsx("div",{className:"flex items-center justify-center py-20",children:s.jsx(ze,{className:"h-5 w-5 text-fg-4"})}):F.length===0&&!h&&!M.length&&!u&&!ut?s.jsx("div",{className:"py-20 text-center text-[13px] text-fg-5",children:m("hub.noMessages")}):s.jsxs("div",{className:"max-w-[900px] mx-auto px-6 py-6 space-y-0",children:[(i?.hasOlder||pe)&&s.jsxs("div",{className:"mb-4 flex items-center justify-center gap-2 text-[11px] text-fg-5",children:[pe?s.jsx(ze,{className:"h-3 w-3 text-fg-5"}):s.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-fg-5/35"}),s.jsx("span",{children:m(pe?"hub.loadingOlderTurns":"hub.loadOlderTurnsHint")})]}),t.migratedFrom?.kind==="fork"&&t.migratedFrom.sessionId&&s.jsxs("button",{type:"button",onClick:()=>y?.({agent:t.migratedFrom.agent||t.agent||"",sessionId:t.migratedFrom.sessionId,workdir:f}),className:"mb-4 inline-flex items-center gap-1.5 rounded-md border border-edge bg-panel-alt px-2.5 py-1 text-[11px] text-fg-5 transition hover:border-edge-h hover:text-fg-2",title:`#${t.migratedFrom.sessionId.slice(0,8)}`,children:[s.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[s.jsx("circle",{cx:"6",cy:"6",r:"2"}),s.jsx("circle",{cx:"18",cy:"6",r:"2"}),s.jsx("circle",{cx:"12",cy:"20",r:"2"}),s.jsx("path",{d:"M6 8v3a3 3 0 0 0 3 3h6a3 3 0 0 0 3-3V8"}),s.jsx("path",{d:"M12 14v4"})]}),s.jsx("span",{children:m("hub.forkBadge")}),s.jsxs("span",{className:"font-mono",children:["#",t.migratedFrom.sessionId.slice(0,8)]}),typeof t.migratedFrom.forkedAtTurn=="number"&&s.jsxs("span",{className:"text-fg-5/70",children:["· ",m("hub.forkBadgeAt").replace("{turn}",String(t.migratedFrom.forkedAtTurn+1))]})]}),F.map((e,r)=>{const l=(i?.startTurn||0)+r;return s.jsx(Nn,{turn:e,turnIndex:l,hideHeaderUsage:_e&&r===F.length-1,isTail:r===F.length-1,fallbackPlan:r===F.length-1&&!(u&&Ke(u))?jt:void 0,agent:t.agent||"",meta:ee,model:at,effort:De,providerName:fe,t:m,workdir:f,onResend:a=>{le.current=!0,Tt(a);const d=It.current;T.sendSessionMessage(f,t.agent||"",t.sessionId,a,{model:d.model||ye||void 0,effort:d.effort||De||void 0}).then(k=>{k.ok&&yt()}).catch(()=>{A()})},onEdit:a=>bt(a),onFork:zt?a=>{Ze(""),Se({atTurn:a})}:void 0},`${i?.startTurn||0}:${r}`)}),ut&&s.jsx("div",{className:"mb-5 animate-in",children:s.jsx(An,{detail:ut,t:m})}),(h||ct.length>0)&&!it&&(He||!At)&&s.jsxs("div",{className:"session-turn session-turn--live",children:[s.jsx(Ct,{text:h||"",blocks:ct,t:m}),!u&&s.jsx("div",{className:"mt-3 mb-5 animate-in",children:s.jsx(Ln,{className:"text-fg-5"})})]}),u&&Ke(u)&&u.question&&(!h||it)&&!(b.length>0&&$e(Nt,u.question))&&s.jsx("div",{className:"session-turn session-turn--live",children:s.jsx(Ct,{text:u.question,blocks:u.questionBlocks||void 0,t:m})}),u&&Ke(u)&&s.jsxs("div",{className:"mb-6",children:[s.jsx(Ut,{agent:t.agent||"",meta:ee,model:at,effort:De,providerName:fe,previewMeta:u.previewMeta,hideContextUsage:!0}),s.jsx(qt,{stream:Mt(u.plan)?u:{...u,plan:jt},t:m,workdir:f})]}),dt&&(_e?s.jsx("div",{className:"-mt-3 mb-6 animate-in",children:s.jsx(On,{toolCount:nn,ctxPct:ft?.contextPercent??null,ctxTokens:ft?.contextUsedTokens??0,turnOutTokens:ft?.turnOutputTokens??0,startedAt:Lt})}):s.jsxs("div",{className:"mb-6",children:[s.jsx(Ut,{agent:t.agent||"",meta:ee,model:at,effort:De,providerName:fe,hideContextUsage:!0}),s.jsx(qt,{stream:{..._n,startedAt:Lt},t:m,workdir:f})]})),s.jsx("div",{className:"h-4"})]})}),s.jsx(En,{session:t,workdir:f,onStreamQueued:yt,onSendStart:Tt,onSendTaskAssigned:Yt,onSessionChange:y,t:m,streamPhase:q,streamTaskId:_t,queuedTaskIds:D,queuedTasks:Qt,pendingQueuedSends:we,onRecall:Vt,onSteer:Xt,onStopAll:Jt,editDraft:Kt,onEditDraftConsumed:()=>bt(null),onSelectionChange:Wt}),Ae&&s.jsxs(Ht,{open:!0,onClose:()=>{$||Se(null)},children:[s.jsx(Ft,{title:m("hub.forkPromptTitle"),description:m("hub.forkPromptHint"),onClose:()=>{$||Se(null)}}),s.jsx("textarea",{autoFocus:!0,value:be,disabled:$,onChange:e=>Ze(e.target.value),onKeyDown:e=>{e.key==="Enter"&&(e.metaKey||e.ctrlKey)&&be.trim()&&!$&&(e.preventDefault(),tt.current?.())},placeholder:m("hub.forkPromptPlaceholder"),className:"w-full min-h-[120px] resize-y rounded-md border border-edge bg-panel-alt px-3 py-2 text-[13px] leading-relaxed text-fg outline-none focus:border-edge-h"}),s.jsxs("div",{className:"mt-4 flex items-center justify-end gap-2",children:[s.jsx(We,{variant:"ghost",disabled:$,onClick:()=>Se(null),children:m("modal.cancel")}),s.jsx(We,{variant:"primary",disabled:$||!be.trim(),onClick:()=>{tt.current?.()},children:m($?"hub.forkSubmitting":"hub.forkSubmit")})]})]}),N&&xe.length>0&&s.jsx(Mn,{snapshot:xe[xe.length-1]},xe[xe.length-1].promptId)]})});export{lr as SessionPanel};
|