@npv12/opencode-mini-session 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -0
- package/dist/agent.js +103 -0
- package/dist/components/ActionButton.js +39 -0
- package/dist/components/AnswerDialog.js +841 -0
- package/dist/components/HintBar.js +34 -0
- package/dist/config.js +27 -0
- package/dist/constants.js +24 -0
- package/dist/context.js +72 -0
- package/dist/counter.js +55 -0
- package/dist/diagnostics.js +59 -0
- package/dist/index.js +157 -0
- package/dist/keybinds.js +152 -0
- package/dist/model.js +75 -0
- package/dist/routing.js +20 -0
- package/dist/session.js +617 -0
- package/dist/theme.js +34 -0
- package/dist/types.js +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,841 @@
|
|
|
1
|
+
import { createTextNode as _$createTextNode } from "@opentui/solid";
|
|
2
|
+
import { effect as _$effect } from "@opentui/solid";
|
|
3
|
+
import { createComponent as _$createComponent } from "@opentui/solid";
|
|
4
|
+
import { memo as _$memo } from "@opentui/solid";
|
|
5
|
+
import { use as _$use } from "@opentui/solid";
|
|
6
|
+
import { insertNode as _$insertNode } from "@opentui/solid";
|
|
7
|
+
import { insert as _$insert } from "@opentui/solid";
|
|
8
|
+
import { setProp as _$setProp } from "@opentui/solid";
|
|
9
|
+
import { createElement as _$createElement } from "@opentui/solid";
|
|
10
|
+
/** @jsxImportSource @opentui/solid */
|
|
11
|
+
import { SyntaxStyle } from "@opentui/core";
|
|
12
|
+
import { createMemo, Show } from "solid-js";
|
|
13
|
+
import { THINKING_TEXT } from "../constants.js";
|
|
14
|
+
import { extractAssistantText } from "../session.js";
|
|
15
|
+
import { ActionButton } from "./ActionButton.js";
|
|
16
|
+
import { buildMiniTheme } from "../theme.js";
|
|
17
|
+
function buildSyntaxStyle(theme) {
|
|
18
|
+
return SyntaxStyle.fromStyles({
|
|
19
|
+
"markup.heading": {
|
|
20
|
+
fg: theme.markdownHeading,
|
|
21
|
+
bold: true
|
|
22
|
+
},
|
|
23
|
+
"markup.strong": {
|
|
24
|
+
fg: theme.markdownStrong,
|
|
25
|
+
bold: true
|
|
26
|
+
},
|
|
27
|
+
"markup.italic": {
|
|
28
|
+
fg: theme.markdownEmph,
|
|
29
|
+
italic: true
|
|
30
|
+
},
|
|
31
|
+
"markup.link": {
|
|
32
|
+
fg: theme.markdownLink
|
|
33
|
+
},
|
|
34
|
+
"markup.link.label": {
|
|
35
|
+
fg: theme.markdownLinkText
|
|
36
|
+
},
|
|
37
|
+
"markup.link.url": {
|
|
38
|
+
fg: theme.markdownLink
|
|
39
|
+
},
|
|
40
|
+
"markup.raw": {
|
|
41
|
+
fg: theme.markdownCode
|
|
42
|
+
},
|
|
43
|
+
"markup.raw.block": {
|
|
44
|
+
fg: theme.markdownCodeBlock
|
|
45
|
+
},
|
|
46
|
+
"markup.strikethrough": {
|
|
47
|
+
fg: theme.markdownText
|
|
48
|
+
},
|
|
49
|
+
blockquote: {
|
|
50
|
+
fg: theme.markdownBlockQuote
|
|
51
|
+
},
|
|
52
|
+
conceal: {
|
|
53
|
+
fg: theme.border,
|
|
54
|
+
dim: true
|
|
55
|
+
},
|
|
56
|
+
comment: {
|
|
57
|
+
fg: theme.syntaxComment
|
|
58
|
+
},
|
|
59
|
+
keyword: {
|
|
60
|
+
fg: theme.syntaxKeyword
|
|
61
|
+
},
|
|
62
|
+
function: {
|
|
63
|
+
fg: theme.syntaxFunction
|
|
64
|
+
},
|
|
65
|
+
variable: {
|
|
66
|
+
fg: theme.syntaxVariable
|
|
67
|
+
},
|
|
68
|
+
string: {
|
|
69
|
+
fg: theme.syntaxString
|
|
70
|
+
},
|
|
71
|
+
number: {
|
|
72
|
+
fg: theme.syntaxNumber
|
|
73
|
+
},
|
|
74
|
+
type: {
|
|
75
|
+
fg: theme.syntaxType
|
|
76
|
+
},
|
|
77
|
+
operator: {
|
|
78
|
+
fg: theme.syntaxOperator
|
|
79
|
+
},
|
|
80
|
+
punctuation: {
|
|
81
|
+
fg: theme.syntaxPunctuation
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const THINKING_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
86
|
+
function resolveAssistantModelName(models, agent, model) {
|
|
87
|
+
if (!model) return undefined;
|
|
88
|
+
const found = models?.find(m => m.providerID === model.providerID && m.id === model.id);
|
|
89
|
+
return found?.name || `${model.providerID}/${model.id}`;
|
|
90
|
+
}
|
|
91
|
+
export function AnswerDialog(props) {
|
|
92
|
+
const theme = () => buildMiniTheme(props.context.theme);
|
|
93
|
+
const mdSyntaxStyle = buildSyntaxStyle(theme());
|
|
94
|
+
let scroller;
|
|
95
|
+
let input;
|
|
96
|
+
let inputValue = "";
|
|
97
|
+
const screenWidth = props.context.renderer.width;
|
|
98
|
+
const screenHeight = props.context.renderer.height;
|
|
99
|
+
const panelWidth = Math.min(100, Math.floor(screenWidth * 0.85));
|
|
100
|
+
const panelHeight = Math.max(14, Math.min(screenHeight - 6, Math.floor(screenHeight * 0.68)));
|
|
101
|
+
const transcriptWidth = Math.max(20, panelWidth - 6);
|
|
102
|
+
const promptContentWidth = Math.max(10, transcriptWidth - 6);
|
|
103
|
+
const transcriptHeight = Math.max(1, panelHeight - 13);
|
|
104
|
+
const transcriptContentWidth = Math.max(20, transcriptWidth - 5);
|
|
105
|
+
const shiftLeft = Math.floor(screenWidth * 0.3);
|
|
106
|
+
const messages = createMemo(() => buildMiniMessages(props.state, props.context));
|
|
107
|
+
const estimatedContentHeight = createMemo(() => estimateMiniMessagesHeight(messages(), props.state, transcriptContentWidth) + 4);
|
|
108
|
+
const contentOverflows = createMemo(() => estimatedContentHeight() > transcriptHeight - 2);
|
|
109
|
+
const showScrollbar = createMemo(() => props.state.scrollbarVisible || contentOverflows());
|
|
110
|
+
const canContinue = createMemo(() => !props.state.loading && !props.state.error && Boolean(extractAssistantText(props.state.entries) || props.state.streamingAnswer.trim()));
|
|
111
|
+
const createUserMessageHint = createMemo(() => getCreateUserMessageHint(props.state));
|
|
112
|
+
const footerCounter = createMemo(() => props.state.footerCounter);
|
|
113
|
+
const hasFooterCounter = createMemo(() => Boolean(footerCounter().miniSession || footerCounter().copiedContext));
|
|
114
|
+
const footerModelName = createMemo(() => truncateWithEllipsis(props.modelName, Math.max(0, promptContentWidth - getFooterCounterWidth(footerCounter()) - (hasFooterCounter() ? 3 : 0))));
|
|
115
|
+
return (() => {
|
|
116
|
+
var _el$ = _$createElement("box"),
|
|
117
|
+
_el$2 = _$createElement("box"),
|
|
118
|
+
_el$3 = _$createElement("box"),
|
|
119
|
+
_el$4 = _$createElement("box"),
|
|
120
|
+
_el$5 = _$createElement("text"),
|
|
121
|
+
_el$6 = _$createElement("b"),
|
|
122
|
+
_el$7 = _$createElement("box"),
|
|
123
|
+
_el$8 = _$createElement("scrollbox"),
|
|
124
|
+
_el$9 = _$createElement("box"),
|
|
125
|
+
_el$0 = _$createElement("box"),
|
|
126
|
+
_el$1 = _$createElement("box"),
|
|
127
|
+
_el$10 = _$createElement("input"),
|
|
128
|
+
_el$11 = _$createElement("box"),
|
|
129
|
+
_el$12 = _$createElement("text"),
|
|
130
|
+
_el$13 = _$createElement("box");
|
|
131
|
+
_$insertNode(_el$, _el$2);
|
|
132
|
+
_$insertNode(_el$, _el$3);
|
|
133
|
+
_$setProp(_el$, "position", "absolute");
|
|
134
|
+
_$setProp(_el$, "top", 0);
|
|
135
|
+
_$setProp(_el$, "left", 0);
|
|
136
|
+
_$setProp(_el$, "width", screenWidth);
|
|
137
|
+
_$setProp(_el$, "height", screenHeight);
|
|
138
|
+
_$setProp(_el$, "justifyContent", "center");
|
|
139
|
+
_$setProp(_el$, "alignItems", "center");
|
|
140
|
+
_$setProp(_el$2, "position", "absolute");
|
|
141
|
+
_$setProp(_el$2, "top", 0);
|
|
142
|
+
_$setProp(_el$2, "left", 0);
|
|
143
|
+
_$setProp(_el$2, "width", screenWidth);
|
|
144
|
+
_$setProp(_el$2, "height", screenHeight);
|
|
145
|
+
_$setProp(_el$2, "backgroundColor", "#000000");
|
|
146
|
+
_$setProp(_el$2, "opacity", 0.65);
|
|
147
|
+
_$insertNode(_el$3, _el$4);
|
|
148
|
+
_$insertNode(_el$3, _el$7);
|
|
149
|
+
_$insertNode(_el$3, _el$0);
|
|
150
|
+
_$setProp(_el$3, "marginLeft", -shiftLeft);
|
|
151
|
+
_$setProp(_el$3, "width", panelWidth);
|
|
152
|
+
_$setProp(_el$3, "height", panelHeight);
|
|
153
|
+
_$setProp(_el$3, "flexDirection", "column");
|
|
154
|
+
_$insertNode(_el$4, _el$5);
|
|
155
|
+
_$setProp(_el$4, "paddingTop", 1);
|
|
156
|
+
_$setProp(_el$4, "paddingLeft", 3);
|
|
157
|
+
_$setProp(_el$4, "paddingRight", 3);
|
|
158
|
+
_$setProp(_el$4, "flexDirection", "row");
|
|
159
|
+
_$setProp(_el$4, "justifyContent", "flex-start");
|
|
160
|
+
_$setProp(_el$4, "alignItems", "center");
|
|
161
|
+
_$setProp(_el$4, "marginBottom", 1);
|
|
162
|
+
_$insertNode(_el$5, _el$6);
|
|
163
|
+
_$insert(_el$6, () => props.title);
|
|
164
|
+
_$insertNode(_el$7, _el$8);
|
|
165
|
+
_$setProp(_el$7, "paddingLeft", 3);
|
|
166
|
+
_$setProp(_el$7, "paddingRight", 3);
|
|
167
|
+
_$insertNode(_el$8, _el$9);
|
|
168
|
+
_$use(node => {
|
|
169
|
+
scroller = node;
|
|
170
|
+
props.onScroller?.(node);
|
|
171
|
+
}, _el$8);
|
|
172
|
+
_$setProp(_el$8, "height", transcriptHeight);
|
|
173
|
+
_$setProp(_el$8, "width", transcriptWidth);
|
|
174
|
+
_$setProp(_el$8, "scrollY", true);
|
|
175
|
+
_$setProp(_el$8, "stickyScroll", true);
|
|
176
|
+
_$setProp(_el$8, "stickyStart", "bottom");
|
|
177
|
+
_$setProp(_el$9, "flexDirection", "column");
|
|
178
|
+
_$setProp(_el$9, "gap", 1);
|
|
179
|
+
_$setProp(_el$9, "width", transcriptContentWidth);
|
|
180
|
+
_$insert(_el$9, (() => {
|
|
181
|
+
var _c$ = _$memo(() => !!props.state.notice);
|
|
182
|
+
return () => _c$() ? (() => {
|
|
183
|
+
var _el$14 = _$createElement("text"),
|
|
184
|
+
_el$15 = _$createTextNode(`Warning: `);
|
|
185
|
+
_$insertNode(_el$14, _el$15);
|
|
186
|
+
_$insert(_el$14, () => props.state.notice, null);
|
|
187
|
+
_$effect(_$p => _$setProp(_el$14, "fg", theme().warning, _$p));
|
|
188
|
+
return _el$14;
|
|
189
|
+
})() : null;
|
|
190
|
+
})(), null);
|
|
191
|
+
_$insert(_el$9, (() => {
|
|
192
|
+
var _c$2 = _$memo(() => messages().length > 0);
|
|
193
|
+
return () => _c$2() ? messages().map(message => (() => {
|
|
194
|
+
var _el$16 = _$createElement("box"),
|
|
195
|
+
_el$17 = _$createElement("text"),
|
|
196
|
+
_el$18 = _$createElement("b");
|
|
197
|
+
_$insertNode(_el$16, _el$17);
|
|
198
|
+
_$setProp(_el$16, "flexDirection", "column");
|
|
199
|
+
_$setProp(_el$16, "gap", 0);
|
|
200
|
+
_$insertNode(_el$17, _el$18);
|
|
201
|
+
_$insert(_el$18, (() => {
|
|
202
|
+
var _c$7 = _$memo(() => message.role === "assistant");
|
|
203
|
+
return () => _c$7() ? `assistant [${message.modelName ?? props.modelName}]` : message.role;
|
|
204
|
+
})());
|
|
205
|
+
_$insert(_el$16, () => message.parts.map((part, index) => (() => {
|
|
206
|
+
var _el$19 = _$createElement("box");
|
|
207
|
+
_$insert(_el$19, (() => {
|
|
208
|
+
var _c$8 = _$memo(() => part.type === "reasoning");
|
|
209
|
+
return () => _c$8() ? _$createComponent(ThinkingPart, {
|
|
210
|
+
get theme() {
|
|
211
|
+
return theme();
|
|
212
|
+
},
|
|
213
|
+
part: part,
|
|
214
|
+
get expanded() {
|
|
215
|
+
return isThinkingPartExpanded(props.state, part);
|
|
216
|
+
},
|
|
217
|
+
get spinnerFrame() {
|
|
218
|
+
return props.state.spinnerFrame;
|
|
219
|
+
},
|
|
220
|
+
onToggle: () => props.onToggleThinkingPart(part.id)
|
|
221
|
+
}) : _$memo(() => !!(message.role === "assistant" && part.type === "text" && !props.state.loading))() ? (() => {
|
|
222
|
+
var _el$20 = _$createElement("markdown");
|
|
223
|
+
_$setProp(_el$20, "syntaxStyle", mdSyntaxStyle);
|
|
224
|
+
_$setProp(_el$20, "width", transcriptContentWidth);
|
|
225
|
+
_$effect(_p$ => {
|
|
226
|
+
var _v$11 = part.text,
|
|
227
|
+
_v$12 = theme().markdownText,
|
|
228
|
+
_v$13 = props.state.loading;
|
|
229
|
+
_v$11 !== _p$.e && (_p$.e = _$setProp(_el$20, "content", _v$11, _p$.e));
|
|
230
|
+
_v$12 !== _p$.t && (_p$.t = _$setProp(_el$20, "fg", _v$12, _p$.t));
|
|
231
|
+
_v$13 !== _p$.a && (_p$.a = _$setProp(_el$20, "streaming", _v$13, _p$.a));
|
|
232
|
+
return _p$;
|
|
233
|
+
}, {
|
|
234
|
+
e: undefined,
|
|
235
|
+
t: undefined,
|
|
236
|
+
a: undefined
|
|
237
|
+
});
|
|
238
|
+
return _el$20;
|
|
239
|
+
})() : (() => {
|
|
240
|
+
var _el$21 = _$createElement("text");
|
|
241
|
+
_$insert(_el$21, () => formatMiniPart(part));
|
|
242
|
+
_$effect(_$p => _$setProp(_el$21, "fg", getMiniPartColor(theme(), part), _$p));
|
|
243
|
+
return _el$21;
|
|
244
|
+
})();
|
|
245
|
+
})());
|
|
246
|
+
_$effect(_$p => _$setProp(_el$19, "marginTop", getMiniPartTopMargin(message.parts, index, message.role), _$p));
|
|
247
|
+
return _el$19;
|
|
248
|
+
})()), null);
|
|
249
|
+
_$effect(_$p => _$setProp(_el$17, "fg", message.role === "assistant" ? theme().primary : theme().secondary, _$p));
|
|
250
|
+
return _el$16;
|
|
251
|
+
})()) : _$memo(() => !!props.state.loading)() ? (() => {
|
|
252
|
+
var _el$22 = _$createElement("text");
|
|
253
|
+
_$insert(_el$22, THINKING_TEXT);
|
|
254
|
+
_$effect(_$p => _$setProp(_el$22, "fg", theme().textMuted, _$p));
|
|
255
|
+
return _el$22;
|
|
256
|
+
})() : (() => {
|
|
257
|
+
var _el$23 = _$createElement("text");
|
|
258
|
+
_$insertNode(_el$23, _$createTextNode(`Ask a side question below.`));
|
|
259
|
+
_$effect(_$p => _$setProp(_el$23, "fg", theme().textMuted, _$p));
|
|
260
|
+
return _el$23;
|
|
261
|
+
})();
|
|
262
|
+
})(), null);
|
|
263
|
+
_$insert(_el$9, (() => {
|
|
264
|
+
var _c$3 = _$memo(() => !!props.state.error);
|
|
265
|
+
return () => _c$3() ? (() => {
|
|
266
|
+
var _el$25 = _$createElement("text"),
|
|
267
|
+
_el$26 = _$createTextNode(`Error: `);
|
|
268
|
+
_$insertNode(_el$25, _el$26);
|
|
269
|
+
_$insert(_el$25, () => props.state.error, null);
|
|
270
|
+
_$effect(_$p => _$setProp(_el$25, "fg", theme().error, _$p));
|
|
271
|
+
return _el$25;
|
|
272
|
+
})() : null;
|
|
273
|
+
})(), null);
|
|
274
|
+
_$insert(_el$9, (() => {
|
|
275
|
+
var _c$4 = _$memo(() => !!props.state.errorDetail);
|
|
276
|
+
return () => _c$4() ? (() => {
|
|
277
|
+
var _el$27 = _$createElement("text");
|
|
278
|
+
_$insert(_el$27, () => props.state.errorDetail);
|
|
279
|
+
_$effect(_$p => _$setProp(_el$27, "fg", theme().textMuted, _$p));
|
|
280
|
+
return _el$27;
|
|
281
|
+
})() : null;
|
|
282
|
+
})(), null);
|
|
283
|
+
_$insert(_el$9, (() => {
|
|
284
|
+
var _c$5 = _$memo(() => !!createUserMessageHint());
|
|
285
|
+
return () => _c$5() ? (() => {
|
|
286
|
+
var _el$28 = _$createElement("text");
|
|
287
|
+
_$insert(_el$28, createUserMessageHint);
|
|
288
|
+
_$effect(_$p => _$setProp(_el$28, "fg", theme().warning, _$p));
|
|
289
|
+
return _el$28;
|
|
290
|
+
})() : null;
|
|
291
|
+
})(), null);
|
|
292
|
+
_$insert(_el$9, (() => {
|
|
293
|
+
var _c$6 = _$memo(() => !!(props.state.loading && messages().length > 0));
|
|
294
|
+
return () => _c$6() ? (() => {
|
|
295
|
+
var _el$29 = _$createElement("text");
|
|
296
|
+
_$insert(_el$29, THINKING_TEXT);
|
|
297
|
+
_$effect(_$p => _$setProp(_el$29, "fg", theme().textMuted, _$p));
|
|
298
|
+
return _el$29;
|
|
299
|
+
})() : null;
|
|
300
|
+
})(), null);
|
|
301
|
+
_$insertNode(_el$0, _el$1);
|
|
302
|
+
_$insertNode(_el$0, _el$13);
|
|
303
|
+
_$setProp(_el$0, "paddingLeft", 3);
|
|
304
|
+
_$setProp(_el$0, "paddingRight", 3);
|
|
305
|
+
_$setProp(_el$0, "paddingBottom", 1);
|
|
306
|
+
_$setProp(_el$0, "flexDirection", "column");
|
|
307
|
+
_$setProp(_el$0, "gap", 1);
|
|
308
|
+
_$setProp(_el$0, "marginTop", 1);
|
|
309
|
+
_$insertNode(_el$1, _el$10);
|
|
310
|
+
_$insertNode(_el$1, _el$11);
|
|
311
|
+
_$setProp(_el$1, "width", transcriptWidth);
|
|
312
|
+
_$setProp(_el$1, "height", 6);
|
|
313
|
+
_$setProp(_el$1, "flexDirection", "column");
|
|
314
|
+
_$setProp(_el$1, "paddingTop", 1);
|
|
315
|
+
_$setProp(_el$1, "paddingLeft", 2);
|
|
316
|
+
_$setProp(_el$1, "paddingRight", 2);
|
|
317
|
+
_$setProp(_el$1, "paddingBottom", 1);
|
|
318
|
+
_$setProp(_el$1, "justifyContent", "space-between");
|
|
319
|
+
_$use(node => {
|
|
320
|
+
input = node;
|
|
321
|
+
props.onInput?.(node);
|
|
322
|
+
}, _el$10);
|
|
323
|
+
_$setProp(_el$10, "width", promptContentWidth);
|
|
324
|
+
_$setProp(_el$10, "onInput", value => {
|
|
325
|
+
inputValue = value;
|
|
326
|
+
});
|
|
327
|
+
_$setProp(_el$10, "onSubmit", () => {
|
|
328
|
+
const submitted = (input?.value || inputValue).trim();
|
|
329
|
+
if (!submitted || props.state.loading) return;
|
|
330
|
+
if (!props.onSubmit(submitted)) return;
|
|
331
|
+
inputValue = "";
|
|
332
|
+
if (input) input.value = "";
|
|
333
|
+
});
|
|
334
|
+
_$insertNode(_el$11, _el$12);
|
|
335
|
+
_$setProp(_el$11, "flexDirection", "row");
|
|
336
|
+
_$setProp(_el$11, "justifyContent", "space-between");
|
|
337
|
+
_$setProp(_el$11, "alignItems", "center");
|
|
338
|
+
_$setProp(_el$11, "width", promptContentWidth);
|
|
339
|
+
_$setProp(_el$11, "gap", 3);
|
|
340
|
+
_$insert(_el$12, footerModelName);
|
|
341
|
+
_$insert(_el$11, _$createComponent(Show, {
|
|
342
|
+
get when() {
|
|
343
|
+
return hasFooterCounter();
|
|
344
|
+
},
|
|
345
|
+
get children() {
|
|
346
|
+
return _$createComponent(FooterCounter, {
|
|
347
|
+
get theme() {
|
|
348
|
+
return theme();
|
|
349
|
+
},
|
|
350
|
+
get state() {
|
|
351
|
+
return footerCounter();
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}), null);
|
|
356
|
+
_$setProp(_el$13, "flexDirection", "row");
|
|
357
|
+
_$setProp(_el$13, "justifyContent", "flex-end");
|
|
358
|
+
_$setProp(_el$13, "alignItems", "center");
|
|
359
|
+
_$setProp(_el$13, "width", transcriptWidth);
|
|
360
|
+
_$setProp(_el$13, "gap", 2);
|
|
361
|
+
_$insert(_el$13, _$createComponent(Show, {
|
|
362
|
+
get when() {
|
|
363
|
+
return canContinue();
|
|
364
|
+
},
|
|
365
|
+
get children() {
|
|
366
|
+
return _$createComponent(ActionButton, {
|
|
367
|
+
get context() {
|
|
368
|
+
return props.context;
|
|
369
|
+
},
|
|
370
|
+
label: "Continue",
|
|
371
|
+
keybind: "shift+enter",
|
|
372
|
+
get onPress() {
|
|
373
|
+
return props.onContinue;
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}), null);
|
|
378
|
+
_$insert(_el$13, _$createComponent(ActionButton, {
|
|
379
|
+
get context() {
|
|
380
|
+
return props.context;
|
|
381
|
+
},
|
|
382
|
+
label: "Toggle",
|
|
383
|
+
get keybind() {
|
|
384
|
+
return props.hideKey || undefined;
|
|
385
|
+
},
|
|
386
|
+
get onPress() {
|
|
387
|
+
return props.onHide;
|
|
388
|
+
}
|
|
389
|
+
}), null);
|
|
390
|
+
_$insert(_el$13, _$createComponent(ActionButton, {
|
|
391
|
+
get context() {
|
|
392
|
+
return props.context;
|
|
393
|
+
},
|
|
394
|
+
label: "Thinking",
|
|
395
|
+
get keybind() {
|
|
396
|
+
return props.toggleThinkingKeybind || undefined;
|
|
397
|
+
},
|
|
398
|
+
get onPress() {
|
|
399
|
+
return props.onToggleThinking;
|
|
400
|
+
}
|
|
401
|
+
}), null);
|
|
402
|
+
_$insert(_el$13, _$createComponent(ActionButton, {
|
|
403
|
+
get context() {
|
|
404
|
+
return props.context;
|
|
405
|
+
},
|
|
406
|
+
label: "Model",
|
|
407
|
+
keybind: "tab",
|
|
408
|
+
get onPress() {
|
|
409
|
+
return props.onChangeModel;
|
|
410
|
+
}
|
|
411
|
+
}), null);
|
|
412
|
+
_$effect(_p$ => {
|
|
413
|
+
var _v$ = theme().backgroundPanel,
|
|
414
|
+
_v$2 = theme().text,
|
|
415
|
+
_v$3 = {
|
|
416
|
+
visible: showScrollbar()
|
|
417
|
+
},
|
|
418
|
+
_v$4 = theme().borderSubtle,
|
|
419
|
+
_v$5 = props.state.inputPlaceholder ?? (props.state.loading ? "Waiting for response..." : "Ask a question..."),
|
|
420
|
+
_v$6 = theme().text,
|
|
421
|
+
_v$7 = theme().textMuted,
|
|
422
|
+
_v$8 = theme().borderSubtle,
|
|
423
|
+
_v$9 = theme().text,
|
|
424
|
+
_v$0 = theme().primary,
|
|
425
|
+
_v$1 = theme().borderSubtle,
|
|
426
|
+
_v$10 = theme().text;
|
|
427
|
+
_v$ !== _p$.e && (_p$.e = _$setProp(_el$3, "backgroundColor", _v$, _p$.e));
|
|
428
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$5, "fg", _v$2, _p$.t));
|
|
429
|
+
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$8, "verticalScrollbarOptions", _v$3, _p$.a));
|
|
430
|
+
_v$4 !== _p$.o && (_p$.o = _$setProp(_el$1, "backgroundColor", _v$4, _p$.o));
|
|
431
|
+
_v$5 !== _p$.i && (_p$.i = _$setProp(_el$10, "placeholder", _v$5, _p$.i));
|
|
432
|
+
_v$6 !== _p$.n && (_p$.n = _$setProp(_el$10, "textColor", _v$6, _p$.n));
|
|
433
|
+
_v$7 !== _p$.s && (_p$.s = _$setProp(_el$10, "placeholderColor", _v$7, _p$.s));
|
|
434
|
+
_v$8 !== _p$.h && (_p$.h = _$setProp(_el$10, "backgroundColor", _v$8, _p$.h));
|
|
435
|
+
_v$9 !== _p$.r && (_p$.r = _$setProp(_el$10, "focusedTextColor", _v$9, _p$.r));
|
|
436
|
+
_v$0 !== _p$.d && (_p$.d = _$setProp(_el$10, "cursorColor", _v$0, _p$.d));
|
|
437
|
+
_v$1 !== _p$.l && (_p$.l = _$setProp(_el$10, "focusedBackgroundColor", _v$1, _p$.l));
|
|
438
|
+
_v$10 !== _p$.u && (_p$.u = _$setProp(_el$12, "fg", _v$10, _p$.u));
|
|
439
|
+
return _p$;
|
|
440
|
+
}, {
|
|
441
|
+
e: undefined,
|
|
442
|
+
t: undefined,
|
|
443
|
+
a: undefined,
|
|
444
|
+
o: undefined,
|
|
445
|
+
i: undefined,
|
|
446
|
+
n: undefined,
|
|
447
|
+
s: undefined,
|
|
448
|
+
h: undefined,
|
|
449
|
+
r: undefined,
|
|
450
|
+
d: undefined,
|
|
451
|
+
l: undefined,
|
|
452
|
+
u: undefined
|
|
453
|
+
});
|
|
454
|
+
return _el$;
|
|
455
|
+
})();
|
|
456
|
+
}
|
|
457
|
+
function buildMiniMessages(state, context) {
|
|
458
|
+
const models = context.data.location.model.list();
|
|
459
|
+
const messages = [];
|
|
460
|
+
for (const entry of state.entries) {
|
|
461
|
+
const miniParts = [];
|
|
462
|
+
if (entry.type === "user" && entry.text.trim()) miniParts.push({
|
|
463
|
+
type: "text",
|
|
464
|
+
text: entry.text.trim()
|
|
465
|
+
});
|
|
466
|
+
if (entry.type === "assistant") {
|
|
467
|
+
for (const part of entry.content) {
|
|
468
|
+
miniParts.push(...toMiniParts(part));
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (miniParts.length === 0) continue;
|
|
472
|
+
const modelName = entry.type === "assistant" ? resolveAssistantModelName(models, entry.agent, entry.model) : undefined;
|
|
473
|
+
const message = {
|
|
474
|
+
id: entry.id,
|
|
475
|
+
role: entry.type === "assistant" ? "assistant" : "user",
|
|
476
|
+
parts: miniParts,
|
|
477
|
+
modelName
|
|
478
|
+
};
|
|
479
|
+
const previous = messages[messages.length - 1];
|
|
480
|
+
if (shouldMergeMiniMessages(previous, message)) {
|
|
481
|
+
previous.parts.push(...message.parts);
|
|
482
|
+
previous.modelName ??= message.modelName;
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
messages.push(message);
|
|
486
|
+
}
|
|
487
|
+
if (!state.streamingAnswer) return messages;
|
|
488
|
+
const lastAssistant = [...messages].reverse().find(m => m.role === "assistant");
|
|
489
|
+
if (!lastAssistant) {
|
|
490
|
+
messages.push({
|
|
491
|
+
id: "streaming-assistant",
|
|
492
|
+
role: "assistant",
|
|
493
|
+
parts: [{
|
|
494
|
+
type: "text",
|
|
495
|
+
text: state.streamingAnswer
|
|
496
|
+
}],
|
|
497
|
+
modelName: undefined
|
|
498
|
+
});
|
|
499
|
+
return messages;
|
|
500
|
+
}
|
|
501
|
+
const lastText = [...lastAssistant.parts].reverse().find(p => p.type === "text");
|
|
502
|
+
if (lastText) {
|
|
503
|
+
const s = state.streamingAnswer.trim();
|
|
504
|
+
const t = lastText.text.trim();
|
|
505
|
+
if (s === t) {/* identical */} else if (s.startsWith(t) && s.length > t.length) lastText.text = state.streamingAnswer;else if (!t.endsWith(s)) lastText.text += state.streamingAnswer;
|
|
506
|
+
} else {
|
|
507
|
+
const lastReasoning = [...lastAssistant.parts].reverse().find(p => p.type === "reasoning");
|
|
508
|
+
if (!lastReasoning || lastReasoning.text.trim() !== state.streamingAnswer.trim()) {
|
|
509
|
+
lastAssistant.parts.push({
|
|
510
|
+
type: "text",
|
|
511
|
+
text: state.streamingAnswer
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return messages;
|
|
516
|
+
}
|
|
517
|
+
function shouldMergeMiniMessages(previous, current) {
|
|
518
|
+
return Boolean(previous && previous.role === "assistant" && current.role === "assistant");
|
|
519
|
+
}
|
|
520
|
+
function ThinkingPart(props) {
|
|
521
|
+
const header = () => formatThinkingHeader(props.part, props.expanded, props);
|
|
522
|
+
const body = () => getThinkingBodyText(props.part);
|
|
523
|
+
return (() => {
|
|
524
|
+
var _el$30 = _$createElement("box"),
|
|
525
|
+
_el$31 = _$createElement("box"),
|
|
526
|
+
_el$32 = _$createElement("text");
|
|
527
|
+
_$insertNode(_el$30, _el$31);
|
|
528
|
+
_$setProp(_el$30, "flexDirection", "column");
|
|
529
|
+
_$setProp(_el$30, "gap", 0);
|
|
530
|
+
_$insertNode(_el$31, _el$32);
|
|
531
|
+
_$insert(_el$32, _$createComponent(Show, {
|
|
532
|
+
get when() {
|
|
533
|
+
return !props.expanded;
|
|
534
|
+
},
|
|
535
|
+
get fallback() {
|
|
536
|
+
return header();
|
|
537
|
+
},
|
|
538
|
+
get children() {
|
|
539
|
+
var _el$33 = _$createElement("b");
|
|
540
|
+
_$insert(_el$33, header);
|
|
541
|
+
return _el$33;
|
|
542
|
+
}
|
|
543
|
+
}));
|
|
544
|
+
_$insert(_el$30, _$createComponent(Show, {
|
|
545
|
+
get when() {
|
|
546
|
+
return _$memo(() => !!props.expanded)() && body();
|
|
547
|
+
},
|
|
548
|
+
get children() {
|
|
549
|
+
var _el$34 = _$createElement("box"),
|
|
550
|
+
_el$35 = _$createElement("text");
|
|
551
|
+
_$insertNode(_el$34, _el$35);
|
|
552
|
+
_$setProp(_el$34, "marginLeft", 2);
|
|
553
|
+
_$setProp(_el$34, "marginTop", 1);
|
|
554
|
+
_$insert(_el$35, body);
|
|
555
|
+
_$effect(_$p => _$setProp(_el$35, "fg", props.theme.markdownBlockQuote, _$p));
|
|
556
|
+
return _el$34;
|
|
557
|
+
}
|
|
558
|
+
}), null);
|
|
559
|
+
_$effect(_p$ => {
|
|
560
|
+
var _v$14 = props.expanded ? 0.65 : 1,
|
|
561
|
+
_v$15 = props.onToggle,
|
|
562
|
+
_v$16 = props.theme.warning;
|
|
563
|
+
_v$14 !== _p$.e && (_p$.e = _$setProp(_el$30, "opacity", _v$14, _p$.e));
|
|
564
|
+
_v$15 !== _p$.t && (_p$.t = _$setProp(_el$31, "onMouseUp", _v$15, _p$.t));
|
|
565
|
+
_v$16 !== _p$.a && (_p$.a = _$setProp(_el$32, "fg", _v$16, _p$.a));
|
|
566
|
+
return _p$;
|
|
567
|
+
}, {
|
|
568
|
+
e: undefined,
|
|
569
|
+
t: undefined,
|
|
570
|
+
a: undefined
|
|
571
|
+
});
|
|
572
|
+
return _el$30;
|
|
573
|
+
})();
|
|
574
|
+
}
|
|
575
|
+
function estimateMiniMessagesHeight(messages, state, width) {
|
|
576
|
+
let lines = 0;
|
|
577
|
+
for (const message of messages) {
|
|
578
|
+
lines += 1;
|
|
579
|
+
for (let i = 0; i < message.parts.length; i++) {
|
|
580
|
+
lines += getMiniPartTopMargin(message.parts, i, message.role);
|
|
581
|
+
const part = message.parts[i];
|
|
582
|
+
if (part.type === "reasoning") {
|
|
583
|
+
lines += estimateWrappedLines(formatThinkingHeader(part, isThinkingPartExpanded(state, part), state), width);
|
|
584
|
+
if (isThinkingPartExpanded(state, part)) {
|
|
585
|
+
const body = getThinkingBodyText(part);
|
|
586
|
+
if (body) lines += 1 + estimateWrappedLines(body, Math.max(1, width - 2));
|
|
587
|
+
}
|
|
588
|
+
} else lines += estimateWrappedLines(formatMiniPart(part), width);
|
|
589
|
+
}
|
|
590
|
+
lines += 1;
|
|
591
|
+
}
|
|
592
|
+
if (state.error) lines += estimateWrappedLines(`Error: ${state.error}`, width);
|
|
593
|
+
if (state.errorDetail) lines += estimateWrappedLines(state.errorDetail, width);
|
|
594
|
+
const hint = getCreateUserMessageHint(state);
|
|
595
|
+
if (hint) lines += estimateWrappedLines(hint, width);
|
|
596
|
+
if (state.notice) lines += estimateWrappedLines(`Warning: ${state.notice}`, width);
|
|
597
|
+
if (state.loading && messages.length > 0) lines += 1;
|
|
598
|
+
if (messages.length === 0) lines += 1;
|
|
599
|
+
return lines;
|
|
600
|
+
}
|
|
601
|
+
function estimateWrappedLines(text, width) {
|
|
602
|
+
return text.split("\n").reduce((count, line) => count + Math.max(1, Math.ceil(line.length / Math.max(1, width))), 0);
|
|
603
|
+
}
|
|
604
|
+
function getMiniPartTopMargin(parts, index, role) {
|
|
605
|
+
if (index === 0) return parts[0]?.type === "reasoning" && role === "assistant" ? 1 : 0;
|
|
606
|
+
const previous = parts[index - 1];
|
|
607
|
+
const current = parts[index];
|
|
608
|
+
if (current.type === "reasoning") return previous.type === "tool" || previous.type === "reasoning" ? 1 : 0;
|
|
609
|
+
if (current.type === "tool") return previous.type === "tool" || previous.type === "reasoning" ? 1 : 0;
|
|
610
|
+
return current.type === "text" && previous.type !== "text" ? 1 : 0;
|
|
611
|
+
}
|
|
612
|
+
function toMiniParts(part) {
|
|
613
|
+
if (part.type === "reasoning" && part.text.trim()) return toReasoningMiniParts(part);
|
|
614
|
+
if (part.type === "text" && part.text.trim()) return [{
|
|
615
|
+
type: "text",
|
|
616
|
+
text: part.text.trim()
|
|
617
|
+
}];
|
|
618
|
+
if (part.type === "tool") {
|
|
619
|
+
const inputSummary = typeof part.state.input === "string" ? part.state.input : summarizeToolInput(part.state.input);
|
|
620
|
+
return [{
|
|
621
|
+
type: "tool",
|
|
622
|
+
status: part.state.status,
|
|
623
|
+
text: inputSummary ? `→ ${part.name} ${inputSummary}` : `→ ${part.name}`
|
|
624
|
+
}];
|
|
625
|
+
}
|
|
626
|
+
return [];
|
|
627
|
+
}
|
|
628
|
+
function toReasoningMiniParts(part) {
|
|
629
|
+
const baseID = part.text;
|
|
630
|
+
const time = part.time;
|
|
631
|
+
const segments = splitReasoningText(part.text.trim());
|
|
632
|
+
return segments.map((text, i) => ({
|
|
633
|
+
type: "reasoning",
|
|
634
|
+
id: segments.length === 1 ? baseID : `${baseID}:${i}`,
|
|
635
|
+
text,
|
|
636
|
+
time: i === 0 ? time ? {
|
|
637
|
+
start: time.created,
|
|
638
|
+
end: time.completed
|
|
639
|
+
} : undefined : undefined
|
|
640
|
+
}));
|
|
641
|
+
}
|
|
642
|
+
function splitReasoningText(text) {
|
|
643
|
+
const titlePattern = /\*\*([^*\n]+)\*\*/g;
|
|
644
|
+
const matches = [...text.matchAll(titlePattern)].filter(m => isReasoningTitleMatch(text, m.index ?? -1));
|
|
645
|
+
if (matches.length <= 1) return [text];
|
|
646
|
+
const segments = [];
|
|
647
|
+
if ((matches[0].index ?? 0) > 0) {
|
|
648
|
+
const intro = text.slice(0, matches[0].index).trim();
|
|
649
|
+
if (intro) segments.push(intro);
|
|
650
|
+
}
|
|
651
|
+
for (let i = 0; i < matches.length; i++) {
|
|
652
|
+
const start = matches[i].index ?? 0;
|
|
653
|
+
const end = matches[i + 1]?.index ?? text.length;
|
|
654
|
+
const seg = text.slice(start, end).trim();
|
|
655
|
+
if (seg) segments.push(seg);
|
|
656
|
+
}
|
|
657
|
+
return segments.length > 0 ? segments : [text];
|
|
658
|
+
}
|
|
659
|
+
function isReasoningTitleMatch(text, index) {
|
|
660
|
+
if (index < 0) return false;
|
|
661
|
+
if (index === 0) return true;
|
|
662
|
+
const before = text.slice(0, index).trimEnd();
|
|
663
|
+
if (!before) return true;
|
|
664
|
+
return /[.!?)]$/.test(before) || before.endsWith("...");
|
|
665
|
+
}
|
|
666
|
+
function summarizeToolInput(input) {
|
|
667
|
+
if (!input) return "";
|
|
668
|
+
const entries = Object.entries(input).slice(0, 2);
|
|
669
|
+
if (entries.length === 0) return "";
|
|
670
|
+
return entries.map(([, v]) => {
|
|
671
|
+
const s = typeof v === "string" ? v : String(v);
|
|
672
|
+
return s.length > 60 ? `${s.slice(0, 57)}...` : s;
|
|
673
|
+
}).join(" ");
|
|
674
|
+
}
|
|
675
|
+
function formatMiniPart(part) {
|
|
676
|
+
return part.text;
|
|
677
|
+
}
|
|
678
|
+
function FooterCounter(props) {
|
|
679
|
+
if (!props.state.miniSession && !props.state.copiedContext) return _$createElement("text");
|
|
680
|
+
return (() => {
|
|
681
|
+
var _el$37 = _$createElement("box");
|
|
682
|
+
_$setProp(_el$37, "flexDirection", "row");
|
|
683
|
+
_$setProp(_el$37, "gap", 1);
|
|
684
|
+
_$insert(_el$37, _$createComponent(Show, {
|
|
685
|
+
get when() {
|
|
686
|
+
return props.state.miniSession;
|
|
687
|
+
},
|
|
688
|
+
children: miniSession => (() => {
|
|
689
|
+
var _el$40 = _$createElement("text");
|
|
690
|
+
_$insert(_el$40, () => miniSession().text);
|
|
691
|
+
_$effect(_$p => _$setProp(_el$40, "fg", miniSession().warning ? props.theme.warning : props.theme.textMuted, _$p));
|
|
692
|
+
return _el$40;
|
|
693
|
+
})()
|
|
694
|
+
}), null);
|
|
695
|
+
_$insert(_el$37, _$createComponent(Show, {
|
|
696
|
+
get when() {
|
|
697
|
+
return _$memo(() => !!props.state.miniSession)() && props.state.copiedContext;
|
|
698
|
+
},
|
|
699
|
+
get children() {
|
|
700
|
+
var _el$38 = _$createElement("text");
|
|
701
|
+
_$insertNode(_el$38, _$createTextNode(`·`));
|
|
702
|
+
_$effect(_$p => _$setProp(_el$38, "fg", props.theme.textMuted, _$p));
|
|
703
|
+
return _el$38;
|
|
704
|
+
}
|
|
705
|
+
}), null);
|
|
706
|
+
_$insert(_el$37, _$createComponent(Show, {
|
|
707
|
+
get when() {
|
|
708
|
+
return props.state.copiedContext;
|
|
709
|
+
},
|
|
710
|
+
children: copiedContext => (() => {
|
|
711
|
+
var _el$41 = _$createElement("text");
|
|
712
|
+
_$insert(_el$41, () => copiedContext().text);
|
|
713
|
+
_$effect(_$p => _$setProp(_el$41, "fg", copiedContext().truncated ? props.theme.warning : props.theme.textMuted, _$p));
|
|
714
|
+
return _el$41;
|
|
715
|
+
})()
|
|
716
|
+
}), null);
|
|
717
|
+
return _el$37;
|
|
718
|
+
})();
|
|
719
|
+
}
|
|
720
|
+
function truncateWithEllipsis(text, maxWidth) {
|
|
721
|
+
if (maxWidth <= 0) return "";
|
|
722
|
+
if (text.length <= maxWidth) return text;
|
|
723
|
+
if (maxWidth <= 3) return ".".repeat(maxWidth);
|
|
724
|
+
return `${text.slice(0, maxWidth - 3)}...`;
|
|
725
|
+
}
|
|
726
|
+
function getFooterCounterWidth(state) {
|
|
727
|
+
return (state.miniSession?.text.length ?? 0) + (state.copiedContext?.text.length ?? 0);
|
|
728
|
+
}
|
|
729
|
+
function isThinkingPartExpanded(state, part) {
|
|
730
|
+
const toggled = Boolean(state.expandedThinkingPartIDs[part.id]);
|
|
731
|
+
return state.thinkingEnabled ? !toggled : toggled;
|
|
732
|
+
}
|
|
733
|
+
function formatThinkingHeader(part, expanded, spinnerSource) {
|
|
734
|
+
const title = getThinkingTitle(part);
|
|
735
|
+
const duration = formatThinkingDuration(part.time);
|
|
736
|
+
const prefix = isThinkingPartLoading(part) ? `${THINKING_SPINNER_FRAMES[spinnerSource.spinnerFrame]} ` : expanded ? "- " : "+ ";
|
|
737
|
+
if (title) return `${prefix}Thought: ${title}${duration ? ` · ${duration}` : ""}`;
|
|
738
|
+
return `${prefix}Thought${duration ? `: ${duration}` : ""}`;
|
|
739
|
+
}
|
|
740
|
+
function isThinkingPartLoading(part) {
|
|
741
|
+
if (!part.time) return false;
|
|
742
|
+
return Number.isFinite(part.time.start ?? NaN) && !Number.isFinite(part.time.end ?? NaN);
|
|
743
|
+
}
|
|
744
|
+
function getThinkingTitle(part) {
|
|
745
|
+
const line = part.text.split("\n").find(l => l.trim().length > 0)?.trim();
|
|
746
|
+
const match = line?.match(/^\*\*(.+?)\*\*/);
|
|
747
|
+
const title = match?.[1]?.trim();
|
|
748
|
+
return title ? truncateThinkingTitle(title) : "";
|
|
749
|
+
}
|
|
750
|
+
function truncateThinkingTitle(title) {
|
|
751
|
+
return title.length > 80 ? `${title.slice(0, 77).trim()}...` : title;
|
|
752
|
+
}
|
|
753
|
+
function getThinkingBodyText(part) {
|
|
754
|
+
const lines = part.text.split("\n");
|
|
755
|
+
const titleIndex = lines.findIndex(l => l.trim().length > 0);
|
|
756
|
+
if (titleIndex === -1) return "";
|
|
757
|
+
const title = getThinkingTitle(part);
|
|
758
|
+
if (!title) return part.text;
|
|
759
|
+
lines[titleIndex] = lines[titleIndex].replace(/^\s*\*\*(.+?)\*\*/, "");
|
|
760
|
+
return lines.slice(titleIndex).join("\n").replace(/^\s+/, "").trimEnd();
|
|
761
|
+
}
|
|
762
|
+
function formatThinkingDuration(time) {
|
|
763
|
+
if (!time) return "";
|
|
764
|
+
const start = Number(time.start);
|
|
765
|
+
const end = Number(time.end);
|
|
766
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) return "";
|
|
767
|
+
const diff = end - start;
|
|
768
|
+
const milliseconds = start > 10_000_000_000 || end > 10_000_000_000 ? diff : diff * 1000;
|
|
769
|
+
if (milliseconds < 1000) return `${Math.round(milliseconds)}ms`;
|
|
770
|
+
const seconds = milliseconds / 1000;
|
|
771
|
+
return seconds < 10 ? `${seconds.toFixed(1)}s` : `${Math.round(seconds)}s`;
|
|
772
|
+
}
|
|
773
|
+
function getMiniPartColor(theme, part) {
|
|
774
|
+
if (part.type === "reasoning") return theme.textMuted;
|
|
775
|
+
if (part.type === "meta") return theme.textMuted;
|
|
776
|
+
if (part.type === "tool" && part.status === "error") return theme.error;
|
|
777
|
+
if (part.type === "tool" && part.status === "running") return theme.info;
|
|
778
|
+
if (part.type === "tool") return theme.textMuted;
|
|
779
|
+
return theme.text;
|
|
780
|
+
}
|
|
781
|
+
function getCreateUserMessageHint(state) {
|
|
782
|
+
const text = [state.error, state.errorDetail].filter(Boolean).join("\n");
|
|
783
|
+
if (!/SessionPrompt\.createUserMessage|createUserMessage|chat\.message/i.test(text)) return undefined;
|
|
784
|
+
return "Hint: OpenCode failed while creating the user message. A server plugin chat.message hook may be throwing.";
|
|
785
|
+
}
|
|
786
|
+
export function createOverlaySlot(getOverlay) {
|
|
787
|
+
return () => {
|
|
788
|
+
return _$createComponent(Show, {
|
|
789
|
+
get when() {
|
|
790
|
+
return getOverlay();
|
|
791
|
+
},
|
|
792
|
+
children: current => _$createComponent(AnswerDialog, {
|
|
793
|
+
get context() {
|
|
794
|
+
return current().context;
|
|
795
|
+
},
|
|
796
|
+
get title() {
|
|
797
|
+
return current().title;
|
|
798
|
+
},
|
|
799
|
+
get modelName() {
|
|
800
|
+
return current().modelName;
|
|
801
|
+
},
|
|
802
|
+
get hideKey() {
|
|
803
|
+
return current().hideKey;
|
|
804
|
+
},
|
|
805
|
+
get toggleThinkingKeybind() {
|
|
806
|
+
return current().toggleThinkingKeybind;
|
|
807
|
+
},
|
|
808
|
+
get state() {
|
|
809
|
+
return current().state;
|
|
810
|
+
},
|
|
811
|
+
get onScroller() {
|
|
812
|
+
return current().onScroller;
|
|
813
|
+
},
|
|
814
|
+
get onInput() {
|
|
815
|
+
return current().onInput;
|
|
816
|
+
},
|
|
817
|
+
get onHide() {
|
|
818
|
+
return current().onHide;
|
|
819
|
+
},
|
|
820
|
+
get onClose() {
|
|
821
|
+
return current().onClose;
|
|
822
|
+
},
|
|
823
|
+
get onContinue() {
|
|
824
|
+
return current().onContinue;
|
|
825
|
+
},
|
|
826
|
+
get onChangeModel() {
|
|
827
|
+
return current().onChangeModel;
|
|
828
|
+
},
|
|
829
|
+
get onToggleThinking() {
|
|
830
|
+
return current().onToggleThinking;
|
|
831
|
+
},
|
|
832
|
+
get onToggleThinkingPart() {
|
|
833
|
+
return current().onToggleThinkingPart;
|
|
834
|
+
},
|
|
835
|
+
get onSubmit() {
|
|
836
|
+
return current().onSubmit;
|
|
837
|
+
}
|
|
838
|
+
})
|
|
839
|
+
});
|
|
840
|
+
};
|
|
841
|
+
}
|