wepscli 0.1.0

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.
Files changed (130) hide show
  1. package/README.md +293 -0
  2. package/dist/WEPSCLI-shell/agent-runtime.js +824 -0
  3. package/dist/WEPSCLI-shell/agent-runtime.js.map +1 -0
  4. package/dist/WEPSCLI-shell/approval-overlay.js +275 -0
  5. package/dist/WEPSCLI-shell/approval-overlay.js.map +1 -0
  6. package/dist/WEPSCLI-shell/chat-components.js +760 -0
  7. package/dist/WEPSCLI-shell/chat-components.js.map +1 -0
  8. package/dist/WEPSCLI-shell/components.js +850 -0
  9. package/dist/WEPSCLI-shell/components.js.map +1 -0
  10. package/dist/WEPSCLI-shell/config-overlays.js +205 -0
  11. package/dist/WEPSCLI-shell/config-overlays.js.map +1 -0
  12. package/dist/WEPSCLI-shell/debug-log.js +16 -0
  13. package/dist/WEPSCLI-shell/debug-log.js.map +1 -0
  14. package/dist/WEPSCLI-shell/file-change-preview.js +261 -0
  15. package/dist/WEPSCLI-shell/file-change-preview.js.map +1 -0
  16. package/dist/WEPSCLI-shell/helpers.js +112 -0
  17. package/dist/WEPSCLI-shell/helpers.js.map +1 -0
  18. package/dist/WEPSCLI-shell/index.js +3 -0
  19. package/dist/WEPSCLI-shell/index.js.map +1 -0
  20. package/dist/WEPSCLI-shell/provider-add-flow.js +406 -0
  21. package/dist/WEPSCLI-shell/provider-add-flow.js.map +1 -0
  22. package/dist/WEPSCLI-shell/run-wepscli-shell.js +21 -0
  23. package/dist/WEPSCLI-shell/run-wepscli-shell.js.map +1 -0
  24. package/dist/WEPSCLI-shell/runtime-recovery.js +37 -0
  25. package/dist/WEPSCLI-shell/runtime-recovery.js.map +1 -0
  26. package/dist/WEPSCLI-shell/runtime-status.js +66 -0
  27. package/dist/WEPSCLI-shell/runtime-status.js.map +1 -0
  28. package/dist/WEPSCLI-shell/shell-app.js +1047 -0
  29. package/dist/WEPSCLI-shell/shell-app.js.map +1 -0
  30. package/dist/WEPSCLI-shell/shell-modes.js +77 -0
  31. package/dist/WEPSCLI-shell/shell-modes.js.map +1 -0
  32. package/dist/WEPSCLI-shell/slash-commands.js +135 -0
  33. package/dist/WEPSCLI-shell/slash-commands.js.map +1 -0
  34. package/dist/WEPSCLI-shell/theme.js +19 -0
  35. package/dist/WEPSCLI-shell/theme.js.map +1 -0
  36. package/dist/WEPSCLI-shell/tool-approval.js +85 -0
  37. package/dist/WEPSCLI-shell/tool-approval.js.map +1 -0
  38. package/dist/WEPSCLI-shell/tool-diff.js +76 -0
  39. package/dist/WEPSCLI-shell/tool-diff.js.map +1 -0
  40. package/dist/WEPSCLI-shell/tool-file-changes.js +268 -0
  41. package/dist/WEPSCLI-shell/tool-file-changes.js.map +1 -0
  42. package/dist/WEPSCLI-shell/tool-message-detail.js +138 -0
  43. package/dist/WEPSCLI-shell/tool-message-detail.js.map +1 -0
  44. package/dist/WEPSCLI-shell/tool-messages.js +145 -0
  45. package/dist/WEPSCLI-shell/tool-messages.js.map +1 -0
  46. package/dist/WEPSCLI-shell/transcript-panel.js +372 -0
  47. package/dist/WEPSCLI-shell/transcript-panel.js.map +1 -0
  48. package/dist/WEPSCLI-shell/transcript-state.js +62 -0
  49. package/dist/WEPSCLI-shell/transcript-state.js.map +1 -0
  50. package/dist/WEPSCLI-shell/types.js +1 -0
  51. package/dist/WEPSCLI-shell/types.js.map +1 -0
  52. package/dist/cli.js +11 -0
  53. package/dist/cli.js.map +1 -0
  54. package/dist/config.js +40 -0
  55. package/dist/config.js.map +1 -0
  56. package/dist/index.js +4 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/main.js +140 -0
  59. package/dist/main.js.map +1 -0
  60. package/dist/onboarding/action-screen.js +90 -0
  61. package/dist/onboarding/action-screen.js.map +1 -0
  62. package/dist/onboarding/framed-screen.js +35 -0
  63. package/dist/onboarding/framed-screen.js.map +1 -0
  64. package/dist/onboarding/onboarding-app.js +312 -0
  65. package/dist/onboarding/onboarding-app.js.map +1 -0
  66. package/dist/onboarding/run-onboarding.js +23 -0
  67. package/dist/onboarding/run-onboarding.js.map +1 -0
  68. package/dist/onboarding/select-screen.js +21 -0
  69. package/dist/onboarding/select-screen.js.map +1 -0
  70. package/dist/onboarding/summary-screen.js +23 -0
  71. package/dist/onboarding/summary-screen.js.map +1 -0
  72. package/dist/onboarding/text-input-screen.js +55 -0
  73. package/dist/onboarding/text-input-screen.js.map +1 -0
  74. package/dist/onboarding/theme.js +26 -0
  75. package/dist/onboarding/theme.js.map +1 -0
  76. package/dist/provider-profiles/api-key-store.js +51 -0
  77. package/dist/provider-profiles/api-key-store.js.map +1 -0
  78. package/dist/provider-profiles/defaults.js +18 -0
  79. package/dist/provider-profiles/defaults.js.map +1 -0
  80. package/dist/provider-profiles/fetch-models.js +53 -0
  81. package/dist/provider-profiles/fetch-models.js.map +1 -0
  82. package/dist/provider-profiles/index.js +6 -0
  83. package/dist/provider-profiles/index.js.map +1 -0
  84. package/dist/provider-profiles/provider-profile-service.js +223 -0
  85. package/dist/provider-profiles/provider-profile-service.js.map +1 -0
  86. package/dist/provider-profiles/providers-config-store.js +17 -0
  87. package/dist/provider-profiles/providers-config-store.js.map +1 -0
  88. package/dist/provider-profiles/types.js +1 -0
  89. package/dist/provider-profiles/types.js.map +1 -0
  90. package/dist/session-history/session-history-service.js +142 -0
  91. package/dist/session-history/session-history-service.js.map +1 -0
  92. package/dist/shell/animator.js +30 -0
  93. package/dist/shell/animator.js.map +1 -0
  94. package/dist/shell/clickables.js +101 -0
  95. package/dist/shell/clickables.js.map +1 -0
  96. package/dist/shell/dashboard-shell.js +292 -0
  97. package/dist/shell/dashboard-shell.js.map +1 -0
  98. package/dist/shell/index.js +5 -0
  99. package/dist/shell/index.js.map +1 -0
  100. package/dist/shell/keymap.js +14 -0
  101. package/dist/shell/keymap.js.map +1 -0
  102. package/dist/shell/mouse.js +39 -0
  103. package/dist/shell/mouse.js.map +1 -0
  104. package/dist/shell/render.js +122 -0
  105. package/dist/shell/render.js.map +1 -0
  106. package/dist/shell/run-shell.js +36 -0
  107. package/dist/shell/run-shell.js.map +1 -0
  108. package/dist/shell/theme.js +56 -0
  109. package/dist/shell/theme.js.map +1 -0
  110. package/dist/storage/locked-json-file.js +88 -0
  111. package/dist/storage/locked-json-file.js.map +1 -0
  112. package/dist/workbench/animator.js +30 -0
  113. package/dist/workbench/animator.js.map +1 -0
  114. package/dist/workbench/index.js +6 -0
  115. package/dist/workbench/index.js.map +1 -0
  116. package/dist/workbench/mouse.js +39 -0
  117. package/dist/workbench/mouse.js.map +1 -0
  118. package/dist/workbench/render.js +82 -0
  119. package/dist/workbench/render.js.map +1 -0
  120. package/dist/workbench/renderer.js +364 -0
  121. package/dist/workbench/renderer.js.map +1 -0
  122. package/dist/workbench/run-workbench.js +36 -0
  123. package/dist/workbench/run-workbench.js.map +1 -0
  124. package/dist/workbench/theme.js +63 -0
  125. package/dist/workbench/theme.js.map +1 -0
  126. package/dist/workbench/types.js +1 -0
  127. package/dist/workbench/types.js.map +1 -0
  128. package/dist/workbench/workbench-shell.js +649 -0
  129. package/dist/workbench/workbench-shell.js.map +1 -0
  130. package/package.json +65 -0
@@ -0,0 +1,1047 @@
1
+ import { effect as _$effect } from "@opentui/solid";
2
+ import { createComponent as _$createComponent } from "@opentui/solid";
3
+ import { memo as _$memo } from "@opentui/solid";
4
+ import { insert as _$insert } from "@opentui/solid";
5
+ import { createTextNode as _$createTextNode } from "@opentui/solid";
6
+ import { insertNode as _$insertNode } from "@opentui/solid";
7
+ import { setProp as _$setProp } from "@opentui/solid";
8
+ import { createElement as _$createElement } from "@opentui/solid";
9
+ import { useKeyboard, useRenderer, useTerminalDimensions } from "@opentui/solid";
10
+ import { batch, createEffect, createMemo, createSignal, onMount } from "solid-js";
11
+ import { SessionHistoryService } from "../session-history/session-history-service.js";
12
+ import { getAgentDir } from "../config.js";
13
+ import { ApprovalOverlay } from "./approval-overlay.js";
14
+ import { WepsAgentRuntime } from "./agent-runtime.js";
15
+ import { writeShellDebugLog } from "./debug-log.js";
16
+ import { executeSlashCommand } from "./slash-commands.js";
17
+ import { createIdleRuntimeState, runtimeStateTone } from "./runtime-status.js";
18
+ import { applyShellModePrompt, getShellMode, nextShellMode, shellModeSwitchMessage } from "./shell-modes.js";
19
+ import { wepscliShellTheme as theme } from "./theme.js";
20
+ import { formatTimestamp, INITIAL_SESSIONS, overlayDescription, overlayTitle, truncate, wrapIndex } from "./helpers.js";
21
+ import { createProviderAddFlow } from "./provider-add-flow.js";
22
+ import { appendSessionMessage, insertSessionMessageBefore, patchSessionMessage, toggleSessionMessage as toggleSessionMessageState } from "./transcript-state.js";
23
+ import { TranscriptPanel } from "./transcript-panel.js";
24
+ import { ChatComposer, OverlayPicker } from "./chat-components.js";
25
+ const LOGO = "WEPsCLI";
26
+ export function WEPSCLIShellApp(props) {
27
+ const renderer = useRenderer();
28
+ const dimensions = useTerminalDimensions();
29
+ const sessionHistory = new SessionHistoryService();
30
+ const [view, setView] = createSignal("home");
31
+ const [focusRegion, setFocusRegionState] = createSignal("composer");
32
+ const [overlay, setOverlay] = createSignal(undefined);
33
+ const [profiles, setProfiles] = createSignal(props.profileService.listProfiles());
34
+ const [selection, setSelection] = createSignal(props.profileService.getActiveSelection());
35
+ const [overlayIndex, setOverlayIndex] = createSignal(0);
36
+ const [modelPickerProfileId, setModelPickerProfileId] = createSignal(selection().profileId);
37
+ const [sessions, setSessions] = createSignal(sessionHistory.ensureSeed(INITIAL_SESSIONS));
38
+ const [composerValue, setComposerValue] = createSignal("");
39
+ const [shellMode, setShellMode] = createSignal("agent");
40
+ const [activeSessionId, setActiveSessionId] = createSignal(undefined);
41
+ const [messagesBySession, setMessagesBySession] = createSignal({});
42
+ const [runtimeStateBySession, setRuntimeStateBySession] = createSignal({});
43
+ const [approvalRequests, setApprovalRequests] = createSignal([]);
44
+ const [approvalDecisionIndex, setApprovalDecisionIndex] = createSignal(0);
45
+ const runtime = new WepsAgentRuntime(props.profileService, {
46
+ appendMessage: (sessionId, message) => appendTranscriptMessage(sessionId, message),
47
+ insertMessageBefore: (sessionId, beforeMessageId, message) => insertTranscriptMessageBefore(sessionId, beforeMessageId, message),
48
+ replaceMessages: (sessionId, messages) => replaceTranscriptMessages(sessionId, messages),
49
+ patchMessage: (sessionId, messageId, patch) => patchTranscriptMessage(sessionId, messageId, patch),
50
+ openApproval: (_sessionId, request) => openApprovalRequest(request),
51
+ closeApproval: (_sessionId, requestId) => closeApprovalRequest(requestId),
52
+ updateRuntimeState: (sessionId, state) => updateRuntimeState(sessionId, state),
53
+ updateSessionBinding: (sessionId, binding) => persistRuntimeSessionBinding(sessionId, binding)
54
+ });
55
+ let composerRef;
56
+ let transcriptScroll;
57
+ let closed = false;
58
+ let transcriptScrollTimer;
59
+ const providerAddFlow = createProviderAddFlow({
60
+ profileService: props.profileService,
61
+ onCreated: ({
62
+ profile,
63
+ modelId
64
+ }) => {
65
+ reloadProviderState();
66
+ if (currentSession()) {
67
+ sessionHistory.updateSession(currentSession().id, {
68
+ providerProfileId: profile.id,
69
+ providerLabel: profile.label,
70
+ modelId
71
+ });
72
+ setSessions(sessionHistory.listSessions());
73
+ void runtime.syncSelection(currentSession().id, {
74
+ profileId: profile.id,
75
+ modelId
76
+ });
77
+ }
78
+ pushChatMessage(currentSession()?.id ?? createdTransientSessionId(), {
79
+ id: `provider-add:${profile.id}:${Date.now()}`,
80
+ role: "system",
81
+ content: `Added provider ${profile.label} / ${modelId}`,
82
+ time: new Date().toLocaleTimeString("en-US", {
83
+ hour: "2-digit",
84
+ minute: "2-digit"
85
+ })
86
+ });
87
+ },
88
+ onClose: () => setFocusRegion("composer")
89
+ });
90
+ const viewport = createMemo(() => ({
91
+ width: dimensions().width || 120,
92
+ height: dimensions().height || 32
93
+ }));
94
+ const showSidebar = createMemo(() => false);
95
+ const shellReady = createMemo(() => profiles().length > 0);
96
+ const activeShellMode = createMemo(() => getShellMode(shellMode()));
97
+ const activeProfile = createMemo(() => {
98
+ const current = selection().profileId;
99
+ return current ? profiles().find(profile => profile.id === current) : profiles()[0];
100
+ });
101
+ const activeModel = createMemo(() => selection().modelId ?? activeProfile()?.models[0]?.id);
102
+ const currentSession = createMemo(() => {
103
+ const currentId = activeSessionId();
104
+ const list = sessions();
105
+ return currentId ? list.find(item => item.id === currentId) : list.find(item => item.state === "active") ?? list[0];
106
+ });
107
+ const currentMessages = createMemo(() => {
108
+ const session = currentSession();
109
+ return session ? messagesBySession()[session.id] ?? [] : [];
110
+ });
111
+ const currentRuntimeState = createMemo(() => {
112
+ const session = currentSession();
113
+ return session ? runtimeStateBySession()[session.id] ?? createIdleRuntimeState() : createIdleRuntimeState();
114
+ });
115
+ const activeApproval = createMemo(() => approvalRequests()[0]);
116
+ const recentSessions = createMemo(() => sessions().slice(0, 5));
117
+ const sessionSummary = createMemo(() => currentSession()?.summary ?? "No session selected yet.");
118
+ const overlayOptions = createMemo(() => {
119
+ switch (overlay()) {
120
+ case "provider":
121
+ return [...profiles().map(profile => ({
122
+ id: `provider:${profile.id}`,
123
+ label: profile.label,
124
+ description: `${profile.family} | ${profile.models.length} model${profile.models.length === 1 ? "" : "s"} | ${profile.lastValidationStatus}`,
125
+ badge: selection().profileId === profile.id ? "ACTIVE" : undefined
126
+ })), {
127
+ id: "provider:add",
128
+ label: "Add provider",
129
+ description: "Create a new provider profile with a guided setup flow.",
130
+ badge: "NEW"
131
+ }];
132
+ case "model-provider":
133
+ return profiles().map(profile => ({
134
+ id: `model-provider:${profile.id}`,
135
+ label: profile.label,
136
+ description: `${profile.family} | ${profile.models.length} model${profile.models.length === 1 ? "" : "s"} available`,
137
+ badge: modelPickerProfileId() === profile.id ? "OPEN" : selection().profileId === profile.id ? "ACTIVE" : undefined
138
+ }));
139
+ case "model":
140
+ return (profiles().find(profile => profile.id === modelPickerProfileId())?.models ?? []).map(model => ({
141
+ id: `model:${modelPickerProfileId()}:${model.id}`,
142
+ label: model.id,
143
+ description: `${model.family} | ${model.name}`,
144
+ badge: selection().profileId === modelPickerProfileId() && activeModel() === model.id ? "CURRENT" : undefined
145
+ }));
146
+ case "session":
147
+ return sessions().map(session => ({
148
+ id: `session:${session.id}`,
149
+ label: session.title,
150
+ description: `${session.state} | ${formatTimestamp(session.updatedAt)} | ${session.summary}`,
151
+ badge: session.id === currentSession()?.id ? "OPEN" : undefined
152
+ }));
153
+ case undefined:
154
+ return [];
155
+ }
156
+ });
157
+ onMount(() => {
158
+ writeShellDebugLog(`mounted chat shell profiles=${profiles().length} sessions=${sessionHistory.listSessions().length}`);
159
+ setTimeout(() => composerRef?.focus(), 10);
160
+ });
161
+ createEffect(() => {
162
+ runtime.setMode(shellMode());
163
+ });
164
+ createEffect(() => {
165
+ const session = currentSession();
166
+ if (!session) {
167
+ writeShellDebugLog("effect session=none messages=0");
168
+ return;
169
+ }
170
+ if (!activeSessionId()) {
171
+ setActiveSessionId(session.id);
172
+ syncActiveSelectionFromSession(session.id);
173
+ }
174
+ ensureSessionTranscript(session.id);
175
+ if (session.runtimeSessionFile) {
176
+ void runtime.loadSession(session.id, selectionForSession(session), {
177
+ runtimeSessionFile: session.runtimeSessionFile
178
+ });
179
+ }
180
+ writeShellDebugLog(`effect session=${session.id} messages=${currentMessages().length}`);
181
+ });
182
+ useKeyboard(evt => {
183
+ writeShellDebugLog(`key name=${evt.name} focus=${focusRegion()} overlay=${overlay() ?? "none"}`);
184
+ if (evt.ctrl && evt.name === "c") {
185
+ evt.preventDefault();
186
+ exitShell();
187
+ return;
188
+ }
189
+ if (evt.ctrl && evt.name === ".") {
190
+ evt.preventDefault();
191
+ void abortActiveRequest();
192
+ return;
193
+ }
194
+ if (activeApproval()) {
195
+ if (evt.name === "escape") {
196
+ evt.preventDefault();
197
+ resolveActiveApproval("cancel");
198
+ return;
199
+ }
200
+ if (evt.name === "left" || evt.name === "up") {
201
+ evt.preventDefault();
202
+ setApprovalDecisionIndex(current => wrapIndex(current, -1, 3));
203
+ return;
204
+ }
205
+ if (evt.name === "right" || evt.name === "down") {
206
+ evt.preventDefault();
207
+ setApprovalDecisionIndex(current => wrapIndex(current, 1, 3));
208
+ return;
209
+ }
210
+ if (evt.name === "return") {
211
+ evt.preventDefault();
212
+ resolveActiveApproval(["allow", "reject", "cancel"][approvalDecisionIndex()] ?? "cancel");
213
+ return;
214
+ }
215
+ return;
216
+ }
217
+ if (providerAddFlow.isActive()) {
218
+ if (evt.name === "escape") {
219
+ evt.preventDefault();
220
+ providerAddFlow.back();
221
+ return;
222
+ }
223
+ if (providerAddFlow.isPickerStep()) {
224
+ if (evt.name === "up") {
225
+ evt.preventDefault();
226
+ providerAddFlow.moveSelection(-1);
227
+ return;
228
+ }
229
+ if (evt.name === "down") {
230
+ evt.preventDefault();
231
+ providerAddFlow.moveSelection(1);
232
+ return;
233
+ }
234
+ if (evt.name === "return") {
235
+ evt.preventDefault();
236
+ providerAddFlow.confirmSelection();
237
+ return;
238
+ }
239
+ }
240
+ return;
241
+ }
242
+ if (overlay()) {
243
+ if (evt.name === "escape") {
244
+ evt.preventDefault();
245
+ closeOverlay();
246
+ return;
247
+ }
248
+ if (evt.name === "up") {
249
+ evt.preventDefault();
250
+ setOverlayIndex(wrapIndex(overlayIndex(), -1, overlayOptions().length));
251
+ return;
252
+ }
253
+ if (evt.name === "down") {
254
+ evt.preventDefault();
255
+ setOverlayIndex(wrapIndex(overlayIndex(), 1, overlayOptions().length));
256
+ return;
257
+ }
258
+ if (evt.name === "return") {
259
+ evt.preventDefault();
260
+ const target = overlayOptions()[overlayIndex()];
261
+ if (target) activateAction(target.id);
262
+ return;
263
+ }
264
+ return;
265
+ }
266
+ if (evt.option && evt.name === "m") {
267
+ evt.preventDefault();
268
+ applyShellMode(nextShellMode(shellMode()));
269
+ return;
270
+ }
271
+ if (evt.option && ["1", "2", "3", "4"].includes(evt.name)) {
272
+ evt.preventDefault();
273
+ const nextMode = {
274
+ "1": "agent",
275
+ "2": "plan",
276
+ "3": "read-only",
277
+ "4": "auto-approve"
278
+ }[evt.name];
279
+ if (nextMode) {
280
+ applyShellMode(nextMode);
281
+ }
282
+ return;
283
+ }
284
+ if (evt.name === "tab") {
285
+ evt.preventDefault();
286
+ cycleFocus();
287
+ return;
288
+ }
289
+ if (focusRegion() === "main") {
290
+ if (evt.name === "up") {
291
+ evt.preventDefault();
292
+ return;
293
+ }
294
+ if (evt.name === "down") {
295
+ evt.preventDefault();
296
+ return;
297
+ }
298
+ if (evt.name === "escape") {
299
+ evt.preventDefault();
300
+ setFocusRegion("composer");
301
+ return;
302
+ }
303
+ }
304
+ if (focusRegion() === "composer" && evt.name === "escape" && !(composerRef?.value ?? "").trim()) {
305
+ evt.preventDefault();
306
+ exitShell();
307
+ }
308
+ });
309
+ function exitShell() {
310
+ if (closed) return;
311
+ closed = true;
312
+ writeShellDebugLog("exit shell");
313
+ if (transcriptScrollTimer) {
314
+ clearTimeout(transcriptScrollTimer);
315
+ transcriptScrollTimer = undefined;
316
+ }
317
+ runtime.dispose();
318
+ renderer.setTerminalTitle("");
319
+ renderer.destroy();
320
+ props.onExit();
321
+ }
322
+ function requestRender() {
323
+ renderer.requestRender?.();
324
+ }
325
+ function cancelTranscriptAutoScroll() {
326
+ if (!transcriptScrollTimer) {
327
+ return;
328
+ }
329
+ clearTimeout(transcriptScrollTimer);
330
+ transcriptScrollTimer = undefined;
331
+ }
332
+ function scheduleTranscriptScrollToBottom() {
333
+ cancelTranscriptAutoScroll();
334
+ transcriptScrollTimer = setTimeout(() => {
335
+ transcriptScrollTimer = undefined;
336
+ if (!transcriptScroll || transcriptScroll.isDestroyed) {
337
+ return;
338
+ }
339
+ transcriptScroll.scrollTo(transcriptScroll.scrollHeight);
340
+ }, 50);
341
+ }
342
+ function reloadProviderState() {
343
+ setProfiles(props.profileService.listProfiles());
344
+ setSelection(props.profileService.getActiveSelection());
345
+ }
346
+ function updateRuntimeState(sessionId, state) {
347
+ setRuntimeStateBySession(current => ({
348
+ ...current,
349
+ [sessionId]: state
350
+ }));
351
+ requestRender();
352
+ }
353
+ async function abortActiveRequest() {
354
+ const session = currentSession();
355
+ if (!session) {
356
+ return;
357
+ }
358
+ const aborted = await runtime.abort(session.id);
359
+ if (!aborted) {
360
+ pushChatMessage(session.id, {
361
+ id: `${session.id}:system:${Date.now()}`,
362
+ role: "system",
363
+ content: "No active request to interrupt.",
364
+ time: new Date().toLocaleTimeString("en-US", {
365
+ hour: "2-digit",
366
+ minute: "2-digit"
367
+ }),
368
+ kind: "status"
369
+ });
370
+ }
371
+ }
372
+ async function compactCurrentSession() {
373
+ const session = currentSession();
374
+ if (!session) {
375
+ const sessionId = createdTransientSessionId();
376
+ pushChatMessage(sessionId, {
377
+ id: `${sessionId}:system:${Date.now()}`,
378
+ role: "system",
379
+ content: "No active session is ready to compact yet.",
380
+ time: new Date().toLocaleTimeString("en-US", {
381
+ hour: "2-digit",
382
+ minute: "2-digit"
383
+ }),
384
+ kind: "status"
385
+ });
386
+ return;
387
+ }
388
+ await runtime.compact(session.id, selectionForSession(session), {
389
+ runtimeSessionFile: session.runtimeSessionFile
390
+ });
391
+ }
392
+ function applyShellMode(nextMode) {
393
+ if (shellMode() === nextMode) {
394
+ const sessionId = currentSession()?.id ?? createdTransientSessionId();
395
+ pushChatMessage(sessionId, {
396
+ id: `${sessionId}:system:${Date.now()}`,
397
+ role: "system",
398
+ content: `Already in ${getShellMode(nextMode).label} mode.`,
399
+ time: new Date().toLocaleTimeString("en-US", {
400
+ hour: "2-digit",
401
+ minute: "2-digit"
402
+ }),
403
+ kind: "status"
404
+ });
405
+ return;
406
+ }
407
+ setShellMode(nextMode);
408
+ const sessionId = currentSession()?.id ?? createdTransientSessionId();
409
+ pushChatMessage(sessionId, {
410
+ id: `${sessionId}:system:${Date.now()}`,
411
+ role: "system",
412
+ content: shellModeSwitchMessage(nextMode),
413
+ time: new Date().toLocaleTimeString("en-US", {
414
+ hour: "2-digit",
415
+ minute: "2-digit"
416
+ }),
417
+ kind: "status"
418
+ });
419
+ composerRef?.focus();
420
+ setFocusRegion("composer");
421
+ requestRender();
422
+ }
423
+ function openApprovalRequest(request) {
424
+ writeShellDebugLog(`approval open tool=${request.toolName} id=${request.id}`);
425
+ setOverlay(undefined);
426
+ setApprovalRequests(current => [...current, request]);
427
+ setApprovalDecisionIndex(0);
428
+ setFocusRegion("overlay");
429
+ requestRender();
430
+ }
431
+ function closeApprovalRequest(requestId) {
432
+ writeShellDebugLog(`approval close id=${requestId}`);
433
+ setApprovalRequests(current => current.filter(request => request.id !== requestId));
434
+ setApprovalDecisionIndex(0);
435
+ if (!providerAddFlow.isActive() && !overlay() && approvalRequests().filter(request => request.id !== requestId).length === 0) {
436
+ setFocusRegion("composer");
437
+ }
438
+ requestRender();
439
+ }
440
+ function resolveActiveApproval(decision) {
441
+ const request = activeApproval();
442
+ if (!request) {
443
+ return;
444
+ }
445
+ writeShellDebugLog(`approval decision tool=${request.toolName} decision=${decision}`);
446
+ runtime.resolveApproval(request.id, decision);
447
+ }
448
+ function setFocusRegion(region) {
449
+ setFocusRegionState(region);
450
+ if (region === "composer") {
451
+ setTimeout(() => composerRef?.focus(), 0);
452
+ return;
453
+ }
454
+ composerRef?.blur();
455
+ }
456
+ function cycleFocus() {
457
+ if (activeApproval() || overlay()) {
458
+ setFocusRegion("overlay");
459
+ return;
460
+ }
461
+ const order = ["main", "composer"];
462
+ const index = order.indexOf(focusRegion());
463
+ setFocusRegion(order[(index + 1) % order.length] ?? "composer");
464
+ }
465
+ function setShellView(next) {
466
+ batch(() => {
467
+ setView(next);
468
+ });
469
+ setFocusRegion("composer");
470
+ }
471
+ function openOverlay(kind) {
472
+ if (kind === "model" && profiles().length === 0) {
473
+ return;
474
+ }
475
+ if (kind === "model") {
476
+ const activeProviderId = selection().profileId ?? profiles()[0]?.id;
477
+ if (!activeProviderId) {
478
+ return;
479
+ }
480
+ setModelPickerProfileId(activeProviderId);
481
+ if (profiles().length > 1) {
482
+ setOverlay("model-provider");
483
+ setOverlayIndex(Math.max(0, profiles().findIndex(profile => profile.id === activeProviderId)));
484
+ setFocusRegion("overlay");
485
+ return;
486
+ }
487
+ }
488
+ setOverlay(kind);
489
+ setOverlayIndex(0);
490
+ setFocusRegion("overlay");
491
+ }
492
+ function closeOverlay() {
493
+ setOverlay(undefined);
494
+ setFocusRegion("composer");
495
+ }
496
+ function openProviderAdd() {
497
+ setOverlay(undefined);
498
+ providerAddFlow.open();
499
+ setFocusRegion("overlay");
500
+ }
501
+ function ensureSessionTranscript(sessionId) {
502
+ setMessagesBySession(current => {
503
+ if (current[sessionId]) return current;
504
+ const session = sessions().find(item => item.id === sessionId);
505
+ const initial = [{
506
+ id: `${sessionId}:system:0`,
507
+ role: "system",
508
+ content: session ? `Opened ${session.title}` : "Opened session",
509
+ time: new Date().toLocaleTimeString("en-US", {
510
+ hour: "2-digit",
511
+ minute: "2-digit"
512
+ })
513
+ }];
514
+ return {
515
+ ...current,
516
+ [sessionId]: initial
517
+ };
518
+ });
519
+ setRuntimeStateBySession(current => current[sessionId] ? current : {
520
+ ...current,
521
+ [sessionId]: createIdleRuntimeState()
522
+ });
523
+ requestRender();
524
+ scheduleTranscriptScrollToBottom();
525
+ }
526
+ function appendTranscriptMessage(sessionId, message) {
527
+ setMessagesBySession(current => appendSessionMessage(current, sessionId, message));
528
+ requestRender();
529
+ scheduleTranscriptScrollToBottom();
530
+ }
531
+ function replaceTranscriptMessages(sessionId, messages) {
532
+ setMessagesBySession(current => ({
533
+ ...current,
534
+ [sessionId]: messages.slice(-200)
535
+ }));
536
+ requestRender();
537
+ scheduleTranscriptScrollToBottom();
538
+ }
539
+ function insertTranscriptMessageBefore(sessionId, beforeMessageId, message) {
540
+ setMessagesBySession(current => insertSessionMessageBefore(current, sessionId, beforeMessageId, message));
541
+ requestRender();
542
+ scheduleTranscriptScrollToBottom();
543
+ }
544
+ function patchTranscriptMessage(sessionId, messageId, patch) {
545
+ setMessagesBySession(current => {
546
+ const next = patchSessionMessage(current, sessionId, messageId, patch);
547
+ return next.messagesBySession;
548
+ });
549
+ requestRender();
550
+ scheduleTranscriptScrollToBottom();
551
+ }
552
+ function toggleTranscriptMessage(sessionId, messageId) {
553
+ cancelTranscriptAutoScroll();
554
+ setMessagesBySession(current => toggleSessionMessageState(current, sessionId, messageId));
555
+ requestRender();
556
+ }
557
+ function selectionForSession(session = currentSession()) {
558
+ return {
559
+ profileId: session?.providerProfileId ?? selection().profileId,
560
+ modelId: session?.modelId ?? selection().modelId
561
+ };
562
+ }
563
+ function persistRuntimeSessionBinding(sessionId, binding) {
564
+ if (!binding.runtimeSessionFile) {
565
+ return;
566
+ }
567
+ const existing = sessions().find(session => session.id === sessionId);
568
+ if (existing?.runtimeSessionFile === binding.runtimeSessionFile) {
569
+ return;
570
+ }
571
+ sessionHistory.updateSession(sessionId, {
572
+ runtimeSessionFile: binding.runtimeSessionFile
573
+ });
574
+ setSessions(sessionHistory.listSessions());
575
+ }
576
+ function syncActiveSelectionFromSession(sessionId) {
577
+ const session = sessions().find(item => item.id === sessionId);
578
+ if (!session?.providerProfileId) {
579
+ return;
580
+ }
581
+ const profile = profiles().find(item => item.id === session.providerProfileId);
582
+ if (!profile) {
583
+ return;
584
+ }
585
+ props.profileService.setActiveSelection(profile.id, session.modelId ?? profile.models[0]?.id);
586
+ reloadProviderState();
587
+ }
588
+ function activateSession(sessionId) {
589
+ setActiveSessionId(sessionId);
590
+ ensureSessionTranscript(sessionId);
591
+ syncActiveSelectionFromSession(sessionId);
592
+ const session = sessions().find(item => item.id === sessionId);
593
+ if (session) {
594
+ sessionHistory.markActive(sessionId);
595
+ setSessions(sessionHistory.listSessions());
596
+ setShellView("home");
597
+ void runtime.syncSelection(sessionId, selectionForSession(session));
598
+ if (session.runtimeSessionFile) {
599
+ void runtime.loadSession(sessionId, selectionForSession(session), {
600
+ runtimeSessionFile: session.runtimeSessionFile
601
+ });
602
+ }
603
+ }
604
+ closeOverlay();
605
+ }
606
+ function startNewSession() {
607
+ const provider = activeProfile();
608
+ const created = sessionHistory.createSession({
609
+ title: "New WEPsCLI chat",
610
+ summary: provider ? `Chat ready with ${provider.label}.` : "Chat ready before provider selection.",
611
+ state: "active",
612
+ providerProfileId: provider?.id,
613
+ providerLabel: provider?.label,
614
+ modelId: activeModel()
615
+ });
616
+ setSessions(sessionHistory.listSessions());
617
+ setActiveSessionId(created.id);
618
+ ensureSessionTranscript(created.id);
619
+ setMessagesBySession(current => ({
620
+ ...current,
621
+ [created.id]: [{
622
+ id: `${created.id}:system:0`,
623
+ role: "system",
624
+ content: provider ? `Ready with ${provider.label}${activeModel() ? ` / ${activeModel()}` : ""}` : "Connect a provider to start sending prompts.",
625
+ time: new Date().toLocaleTimeString("en-US", {
626
+ hour: "2-digit",
627
+ minute: "2-digit"
628
+ })
629
+ }]
630
+ }));
631
+ setComposerValue("");
632
+ composerRef?.focus();
633
+ setFocusRegion("composer");
634
+ requestRender();
635
+ scheduleTranscriptScrollToBottom();
636
+ return created;
637
+ }
638
+ function pushChatMessage(sessionId, message) {
639
+ writeShellDebugLog(`pushChatMessage session=${sessionId} role=${message.role} content=${JSON.stringify(message.content)}`);
640
+ setMessagesBySession(current => {
641
+ const next = appendSessionMessage(current, sessionId, message);
642
+ writeShellDebugLog(`pushChatMessage nextCount=${next[sessionId]?.length ?? 0}`);
643
+ return next;
644
+ });
645
+ requestRender();
646
+ }
647
+ function handleComposerSubmit(value) {
648
+ const trimmed = value.trim();
649
+ writeShellDebugLog(`handleComposerSubmit raw=${JSON.stringify(value)} trimmed=${JSON.stringify(trimmed)}`);
650
+ if (!trimmed) return;
651
+ const session = currentSession() ?? startNewSession();
652
+ writeShellDebugLog(`handleComposerSubmit currentSession=${session?.id ?? "none"}`);
653
+ if (!session) {
654
+ writeShellDebugLog("handleComposerSubmit no current session available");
655
+ return;
656
+ }
657
+ if (trimmed.startsWith("/")) {
658
+ writeShellDebugLog(`handleComposerSubmit slash=${trimmed}`);
659
+ runSlashCommand(trimmed);
660
+ return;
661
+ }
662
+ ensureSessionTranscript(session.id);
663
+ sessionHistory.updateSession(session.id, {
664
+ title: `Chat: ${truncate(trimmed, 24)}`,
665
+ summary: `Last prompt: ${truncate(trimmed, 60)}`,
666
+ providerProfileId: selectionForSession(session).profileId,
667
+ providerLabel: activeProfile()?.label,
668
+ modelId: selectionForSession(session).modelId,
669
+ lastPrompt: trimmed,
670
+ state: "active"
671
+ });
672
+ setSessions(sessionHistory.listSessions());
673
+ writeShellDebugLog(`handleComposerSubmit sessionUpdated=${session.id}`);
674
+ setComposerValue("");
675
+ composerRef?.setText?.("");
676
+ composerRef?.focus();
677
+ void runtime.prompt(session.id, applyShellModePrompt(shellMode(), trimmed), selectionForSession(session), {
678
+ runtimeSessionFile: session.runtimeSessionFile
679
+ });
680
+ requestRender();
681
+ }
682
+ function runSlashCommand(commandId) {
683
+ executeSlashCommand(commandId, {
684
+ startNewSession,
685
+ openOverlay,
686
+ openProviderAdd,
687
+ compactCurrentSession,
688
+ abortActiveRequest: () => {
689
+ void abortActiveRequest();
690
+ },
691
+ setMode: modeId => applyShellMode(modeId),
692
+ getCurrentMode: () => shellMode(),
693
+ getStatusSummary: () => {
694
+ const session = currentSession();
695
+ const runtimeState = currentRuntimeState();
696
+ return ["Current shell status:", `Session: ${session?.title ?? "none"}`, `Mode: ${activeShellMode().label}`, `Provider: ${activeProfile()?.label ?? "none"}`, `Model: ${activeModel() ?? "none"}`, `Runtime: ${runtimeState.label}`, `Agent dir: ${getAgentDir()}`].join("\n");
697
+ },
698
+ queuePromptTemplate: (title, prompt, summary) => {
699
+ const session = currentSession() ?? startNewSession();
700
+ pushChatMessage(session.id, {
701
+ id: `${session.id}:system:${Date.now()}`,
702
+ role: "system",
703
+ content: `${title}: ${summary}`,
704
+ time: new Date().toLocaleTimeString("en-US", {
705
+ hour: "2-digit",
706
+ minute: "2-digit"
707
+ })
708
+ });
709
+ setComposerValue(prompt);
710
+ composerRef?.setText?.(prompt);
711
+ composerRef?.focus();
712
+ setFocusRegion("composer");
713
+ },
714
+ pushTimeline: message => {
715
+ const session = currentSession() ?? startNewSession();
716
+ pushChatMessage(session.id, {
717
+ id: `${session.id}:system:${Date.now()}`,
718
+ role: "system",
719
+ content: message,
720
+ time: new Date().toLocaleTimeString("en-US", {
721
+ hour: "2-digit",
722
+ minute: "2-digit"
723
+ })
724
+ });
725
+ }
726
+ });
727
+ }
728
+ function activateAction(actionId) {
729
+ if (actionId === "session:new") {
730
+ startNewSession();
731
+ return;
732
+ }
733
+ if (actionId === "overlay:provider") {
734
+ openOverlay("provider");
735
+ return;
736
+ }
737
+ if (actionId === "overlay:model") {
738
+ openOverlay("model");
739
+ return;
740
+ }
741
+ if (actionId === "overlay:session") {
742
+ openOverlay("session");
743
+ return;
744
+ }
745
+ if (actionId === "command-menu") {
746
+ setComposerValue("/");
747
+ composerRef?.setText?.("/");
748
+ composerRef?.focus();
749
+ setFocusRegion("composer");
750
+ return;
751
+ }
752
+ if (actionId === "provider:add") {
753
+ openProviderAdd();
754
+ return;
755
+ }
756
+ if (actionId.startsWith("provider:")) {
757
+ const profile = profiles().find(item => item.id === actionId.slice(9));
758
+ if (!profile) return;
759
+ const nextModel = selection().profileId === profile.id ? selection().modelId ?? profile.models[0]?.id : profile.models[0]?.id;
760
+ props.profileService.setActiveSelection(profile.id, nextModel);
761
+ reloadProviderState();
762
+ if (currentSession()) {
763
+ sessionHistory.updateSession(currentSession().id, {
764
+ providerProfileId: profile.id,
765
+ providerLabel: profile.label,
766
+ modelId: nextModel
767
+ });
768
+ setSessions(sessionHistory.listSessions());
769
+ void runtime.syncSelection(currentSession().id, selectionForSession(currentSession()));
770
+ }
771
+ pushChatMessage(currentSession()?.id ?? createdTransientSessionId(), {
772
+ id: `provider:${profile.id}:${Date.now()}`,
773
+ role: "system",
774
+ content: `Provider switched to ${profile.label}${nextModel ? ` / ${nextModel}` : ""}`,
775
+ time: new Date().toLocaleTimeString("en-US", {
776
+ hour: "2-digit",
777
+ minute: "2-digit"
778
+ })
779
+ });
780
+ closeOverlay();
781
+ return;
782
+ }
783
+ if (actionId.startsWith("model-provider:")) {
784
+ const profileId = actionId.slice("model-provider:".length);
785
+ setModelPickerProfileId(profileId);
786
+ setOverlay("model");
787
+ setOverlayIndex(0);
788
+ setFocusRegion("overlay");
789
+ return;
790
+ }
791
+ if (actionId.startsWith("model:")) {
792
+ const payload = actionId.slice(6);
793
+ const separator = payload.indexOf(":");
794
+ const profileId = separator === -1 ? selection().profileId ?? activeProfile()?.id : payload.slice(0, separator);
795
+ const modelId = separator === -1 ? payload : payload.slice(separator + 1);
796
+ const profile = profiles().find(item => item.id === profileId);
797
+ if (!profile) return;
798
+ props.profileService.setActiveSelection(profile.id, modelId);
799
+ reloadProviderState();
800
+ if (currentSession()) {
801
+ sessionHistory.updateSession(currentSession().id, {
802
+ providerProfileId: profile.id,
803
+ providerLabel: profile.label,
804
+ modelId
805
+ });
806
+ setSessions(sessionHistory.listSessions());
807
+ void runtime.syncSelection(currentSession().id, selectionForSession(currentSession()));
808
+ }
809
+ pushChatMessage(currentSession()?.id ?? createdTransientSessionId(), {
810
+ id: `model:${modelId}:${Date.now()}`,
811
+ role: "system",
812
+ content: `Model switched to ${profile.label} / ${modelId}`,
813
+ time: new Date().toLocaleTimeString("en-US", {
814
+ hour: "2-digit",
815
+ minute: "2-digit"
816
+ })
817
+ });
818
+ closeOverlay();
819
+ return;
820
+ }
821
+ if (actionId.startsWith("session:")) {
822
+ activateSession(actionId.slice(8));
823
+ return;
824
+ }
825
+ }
826
+ function createdTransientSessionId() {
827
+ const current = currentSession();
828
+ if (current) return current.id;
829
+ const created = sessionHistory.createSession({
830
+ title: "Transient chat",
831
+ summary: "Temporary chat session created while initializing.",
832
+ state: "active",
833
+ providerProfileId: activeProfile()?.id,
834
+ providerLabel: activeProfile()?.label,
835
+ modelId: activeModel()
836
+ });
837
+ setSessions(sessionHistory.listSessions());
838
+ setActiveSessionId(created.id);
839
+ ensureSessionTranscript(created.id);
840
+ return created.id;
841
+ }
842
+ const topStatus = createMemo(() => {
843
+ const profile = activeProfile();
844
+ const runtimeState = currentRuntimeState();
845
+ if (!profile) return runtimeState.label;
846
+ return `${profile.label} · ${activeModel() ?? "no model"} · ${runtimeState.label}`;
847
+ });
848
+ const sidebarSummary = createMemo(() => {
849
+ if (!shellReady()) return "Complete onboarding to connect a provider.";
850
+ return activeProfile()?.baseUrl ?? "Provider ready.";
851
+ });
852
+ function runtimeStatusColor(state) {
853
+ switch (runtimeStateTone(state)) {
854
+ case "accent":
855
+ return theme.accent;
856
+ case "warning":
857
+ return theme.warning;
858
+ case "danger":
859
+ return theme.danger;
860
+ case "success":
861
+ return theme.success;
862
+ case "muted":
863
+ return theme.muted;
864
+ }
865
+ }
866
+ return (() => {
867
+ var _el$ = _$createElement("box"),
868
+ _el$2 = _$createElement("box"),
869
+ _el$3 = _$createElement("box"),
870
+ _el$4 = _$createElement("text"),
871
+ _el$6 = _$createElement("text"),
872
+ _el$7 = _$createElement("box"),
873
+ _el$8 = _$createElement("text"),
874
+ _el$9 = _$createElement("box"),
875
+ _el$0 = _$createElement("box"),
876
+ _el$1 = _$createElement("text");
877
+ _$insertNode(_el$, _el$2);
878
+ _$insertNode(_el$, _el$9);
879
+ _$insertNode(_el$, _el$0);
880
+ _$setProp(_el$, "flexGrow", 1);
881
+ _$setProp(_el$, "flexDirection", "column");
882
+ _$insertNode(_el$2, _el$3);
883
+ _$insertNode(_el$2, _el$7);
884
+ _$setProp(_el$2, "flexShrink", 0);
885
+ _$setProp(_el$2, "paddingLeft", 1);
886
+ _$setProp(_el$2, "paddingRight", 1);
887
+ _$setProp(_el$2, "paddingTop", 1);
888
+ _$setProp(_el$2, "paddingBottom", 1);
889
+ _$setProp(_el$2, "flexDirection", "row");
890
+ _$setProp(_el$2, "justifyContent", "space-between");
891
+ _$setProp(_el$2, "gap", 1);
892
+ _$insertNode(_el$3, _el$4);
893
+ _$insertNode(_el$3, _el$6);
894
+ _$setProp(_el$3, "flexDirection", "row");
895
+ _$setProp(_el$3, "gap", 1);
896
+ _$setProp(_el$3, "minWidth", 0);
897
+ _$setProp(_el$3, "flexGrow", 1);
898
+ _$insertNode(_el$4, _$createTextNode(`WEPsCLI`));
899
+ _$insert(_el$6, () => truncate(currentSession()?.title ?? "WEPsCLI", 28));
900
+ _$insertNode(_el$7, _el$8);
901
+ _$setProp(_el$7, "flexDirection", "row");
902
+ _$setProp(_el$7, "gap", 1);
903
+ _$setProp(_el$7, "alignItems", "center");
904
+ _$insert(_el$7, (() => {
905
+ var _c$ = _$memo(() => !!currentRuntimeState().interruptible);
906
+ return () => _c$() ? (() => {
907
+ var _el$10 = _$createElement("box"),
908
+ _el$11 = _$createElement("text");
909
+ _$insertNode(_el$10, _el$11);
910
+ _$setProp(_el$10, "paddingLeft", 1);
911
+ _$setProp(_el$10, "paddingRight", 1);
912
+ _$setProp(_el$10, "onMouseUp", () => void abortActiveRequest());
913
+ _$insertNode(_el$11, _$createTextNode(`Stop`));
914
+ _$effect(_p$ => {
915
+ var _v$7 = theme.danger,
916
+ _v$8 = theme.background;
917
+ _v$7 !== _p$.e && (_p$.e = _$setProp(_el$10, "backgroundColor", _v$7, _p$.e));
918
+ _v$8 !== _p$.t && (_p$.t = _$setProp(_el$11, "fg", _v$8, _p$.t));
919
+ return _p$;
920
+ }, {
921
+ e: undefined,
922
+ t: undefined
923
+ });
924
+ return _el$10;
925
+ })() : null;
926
+ })(), _el$8);
927
+ _$insert(_el$8, () => truncate(topStatus(), 36));
928
+ _$setProp(_el$9, "flexGrow", 1);
929
+ _$setProp(_el$9, "minHeight", 0);
930
+ _$setProp(_el$9, "flexDirection", "row");
931
+ _$setProp(_el$9, "gap", 1);
932
+ _$setProp(_el$9, "paddingLeft", 1);
933
+ _$setProp(_el$9, "paddingRight", 1);
934
+ _$setProp(_el$9, "paddingTop", 1);
935
+ _$insert(_el$9, _$createComponent(TranscriptPanel, {
936
+ get messages() {
937
+ return currentMessages();
938
+ },
939
+ get activeModelLabel() {
940
+ return `${activeProfile()?.label ?? "none"} / ${activeModel() ?? "none"}`;
941
+ },
942
+ get width() {
943
+ return viewport().width;
944
+ },
945
+ scrollRef: ref => {
946
+ transcriptScroll = ref;
947
+ },
948
+ onToggleMessage: messageId => toggleTranscriptMessage(currentSession().id, messageId)
949
+ }));
950
+ _$insert(_el$, _$createComponent(ChatComposer, {
951
+ get focused() {
952
+ return focusRegion() === "composer";
953
+ },
954
+ get value() {
955
+ return composerValue();
956
+ },
957
+ get providerLabel() {
958
+ return activeProfile()?.label ?? "No provider";
959
+ },
960
+ get modelLabel() {
961
+ return activeModel() ?? "No model";
962
+ },
963
+ get modeLabel() {
964
+ return activeShellMode().composerLabel;
965
+ },
966
+ get modeTone() {
967
+ return activeShellMode().tone;
968
+ },
969
+ inputRef: ref => {
970
+ composerRef = ref;
971
+ },
972
+ onAction: activateAction,
973
+ onFocus: () => setFocusRegion("composer"),
974
+ onInput: value => setComposerValue(value),
975
+ onModeClick: () => applyShellMode(nextShellMode(shellMode())),
976
+ onSubmit: handleComposerSubmit,
977
+ onSelectSlashCommand: runSlashCommand
978
+ }), _el$0);
979
+ _$insert(_el$, (() => {
980
+ var _c$2 = _$memo(() => !!overlay());
981
+ return () => _c$2() ? _$createComponent(OverlayPicker, {
982
+ get title() {
983
+ return overlayTitle(overlay());
984
+ },
985
+ get description() {
986
+ return overlayDescription(overlay());
987
+ },
988
+ get options() {
989
+ return overlayOptions();
990
+ },
991
+ get selectedIndex() {
992
+ return overlayIndex();
993
+ },
994
+ onClose: closeOverlay,
995
+ onSelect: (id, index) => {
996
+ setOverlayIndex(index);
997
+ activateAction(id);
998
+ }
999
+ }) : null;
1000
+ })(), _el$0);
1001
+ _$insert(_el$, (() => {
1002
+ var _c$3 = _$memo(() => !!activeApproval());
1003
+ return () => _c$3() ? _$createComponent(ApprovalOverlay, {
1004
+ get request() {
1005
+ return activeApproval();
1006
+ },
1007
+ get selectedIndex() {
1008
+ return approvalDecisionIndex();
1009
+ },
1010
+ onSelectIndex: setApprovalDecisionIndex,
1011
+ onResolve: resolveActiveApproval
1012
+ }) : null;
1013
+ })(), _el$0);
1014
+ _$insert(_el$, () => providerAddFlow.render(), _el$0);
1015
+ _$insertNode(_el$0, _el$1);
1016
+ _$setProp(_el$0, "flexShrink", 0);
1017
+ _$setProp(_el$0, "paddingLeft", 1);
1018
+ _$setProp(_el$0, "paddingRight", 1);
1019
+ _$setProp(_el$0, "paddingBottom", 0);
1020
+ _$setProp(_el$0, "paddingTop", 0);
1021
+ _$setProp(_el$0, "flexDirection", "row");
1022
+ _$insert(_el$1, () => truncate(getAgentDir(), 36));
1023
+ _$effect(_p$ => {
1024
+ var _v$ = theme.background,
1025
+ _v$2 = theme.header,
1026
+ _v$3 = theme.accentStrong,
1027
+ _v$4 = theme.text,
1028
+ _v$5 = runtimeStatusColor(currentRuntimeState()),
1029
+ _v$6 = theme.muted;
1030
+ _v$ !== _p$.e && (_p$.e = _$setProp(_el$, "backgroundColor", _v$, _p$.e));
1031
+ _v$2 !== _p$.t && (_p$.t = _$setProp(_el$2, "backgroundColor", _v$2, _p$.t));
1032
+ _v$3 !== _p$.a && (_p$.a = _$setProp(_el$4, "fg", _v$3, _p$.a));
1033
+ _v$4 !== _p$.o && (_p$.o = _$setProp(_el$6, "fg", _v$4, _p$.o));
1034
+ _v$5 !== _p$.i && (_p$.i = _$setProp(_el$8, "fg", _v$5, _p$.i));
1035
+ _v$6 !== _p$.n && (_p$.n = _$setProp(_el$1, "fg", _v$6, _p$.n));
1036
+ return _p$;
1037
+ }, {
1038
+ e: undefined,
1039
+ t: undefined,
1040
+ a: undefined,
1041
+ o: undefined,
1042
+ i: undefined,
1043
+ n: undefined
1044
+ });
1045
+ return _el$;
1046
+ })();
1047
+ }