wepscli 0.1.0 → 0.1.5
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 +9 -8
- package/dist/WEPSCLI-shell/agent-runtime-events.js +194 -0
- package/dist/WEPSCLI-shell/agent-runtime-events.js.map +1 -0
- package/dist/WEPSCLI-shell/agent-runtime-helpers.js +117 -0
- package/dist/WEPSCLI-shell/agent-runtime-helpers.js.map +1 -0
- package/dist/WEPSCLI-shell/agent-runtime-types.js +1 -0
- package/dist/WEPSCLI-shell/agent-runtime-types.js.map +1 -0
- package/dist/WEPSCLI-shell/agent-runtime.js +42 -294
- package/dist/WEPSCLI-shell/agent-runtime.js.map +1 -1
- package/dist/WEPSCLI-shell/approval-overlay.js.map +1 -1
- package/dist/WEPSCLI-shell/chat-components.js +13 -6
- package/dist/WEPSCLI-shell/chat-components.js.map +1 -1
- package/dist/WEPSCLI-shell/file-change-preview.js.map +1 -1
- package/dist/WEPSCLI-shell/runtime-recovery.js.map +1 -1
- package/dist/WEPSCLI-shell/session-consistency.js +9 -0
- package/dist/WEPSCLI-shell/session-consistency.js.map +1 -0
- package/dist/WEPSCLI-shell/shell-app.js +169 -259
- package/dist/WEPSCLI-shell/shell-app.js.map +1 -1
- package/dist/WEPSCLI-shell/shell-keyboard.js +135 -0
- package/dist/WEPSCLI-shell/shell-keyboard.js.map +1 -0
- package/dist/WEPSCLI-shell/shell-modes.js.map +1 -1
- package/dist/WEPSCLI-shell/shell-prompt-controller.js +93 -0
- package/dist/WEPSCLI-shell/shell-prompt-controller.js.map +1 -0
- package/dist/WEPSCLI-shell/shell-status.js +16 -0
- package/dist/WEPSCLI-shell/shell-status.js.map +1 -0
- package/dist/WEPSCLI-shell/skill-commands.js +7 -0
- package/dist/WEPSCLI-shell/skill-commands.js.map +1 -0
- package/dist/WEPSCLI-shell/slash-commands.js +68 -7
- package/dist/WEPSCLI-shell/slash-commands.js.map +1 -1
- package/dist/WEPSCLI-shell/tool-approval.js.map +1 -1
- package/dist/WEPSCLI-shell/tool-diff.js.map +1 -1
- package/dist/WEPSCLI-shell/tool-file-changes.js.map +1 -1
- package/dist/WEPSCLI-shell/tool-message-detail.js.map +1 -1
- package/dist/WEPSCLI-shell/tool-messages.js.map +1 -1
- package/dist/WEPSCLI-shell/transcript-panel.js.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/main.js.map +1 -1
- package/dist/skills/skill-add-flow.js +88 -0
- package/dist/skills/skill-add-flow.js.map +1 -0
- package/dist/skills/skill-service.js +123 -0
- package/dist/skills/skill-service.js.map +1 -0
- package/package.json +28 -24
|
@@ -6,18 +6,24 @@ import { createTextNode as _$createTextNode } from "@opentui/solid";
|
|
|
6
6
|
import { insertNode as _$insertNode } from "@opentui/solid";
|
|
7
7
|
import { setProp as _$setProp } from "@opentui/solid";
|
|
8
8
|
import { createElement as _$createElement } from "@opentui/solid";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { useRenderer, useTerminalDimensions } from "@opentui/solid";
|
|
10
|
+
import { createEffect, createMemo, createSignal, onMount } from "solid-js";
|
|
11
11
|
import { SessionHistoryService } from "../session-history/session-history-service.js";
|
|
12
12
|
import { getAgentDir } from "../config.js";
|
|
13
13
|
import { ApprovalOverlay } from "./approval-overlay.js";
|
|
14
14
|
import { WepsAgentRuntime } from "./agent-runtime.js";
|
|
15
15
|
import { writeShellDebugLog } from "./debug-log.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
16
|
+
import { useShellKeyboard } from "./shell-keyboard.js";
|
|
17
|
+
import { getSessionApprovalRequest, nextFocusRegionForSession } from "./session-consistency.js";
|
|
18
|
+
import { createSkillAddFlow } from "../skills/skill-add-flow.js";
|
|
19
|
+
import { formatInstalledSkillsSummary, listInstalledSkills } from "../skills/skill-service.js";
|
|
20
|
+
import { createShellPromptController } from "./shell-prompt-controller.js";
|
|
21
|
+
import { buildSkillSlashCommands } from "./skill-commands.js";
|
|
22
|
+
import { createIdleRuntimeState } from "./runtime-status.js";
|
|
23
|
+
import { runtimeStatusColor } from "./shell-status.js";
|
|
24
|
+
import { getShellMode, nextShellMode, shellModeSwitchMessage } from "./shell-modes.js";
|
|
19
25
|
import { wepscliShellTheme as theme } from "./theme.js";
|
|
20
|
-
import { formatTimestamp, INITIAL_SESSIONS, overlayDescription, overlayTitle, truncate
|
|
26
|
+
import { formatTimestamp, INITIAL_SESSIONS, overlayDescription, overlayTitle, truncate } from "./helpers.js";
|
|
21
27
|
import { createProviderAddFlow } from "./provider-add-flow.js";
|
|
22
28
|
import { appendSessionMessage, insertSessionMessageBefore, patchSessionMessage, toggleSessionMessage as toggleSessionMessageState } from "./transcript-state.js";
|
|
23
29
|
import { TranscriptPanel } from "./transcript-panel.js";
|
|
@@ -27,7 +33,6 @@ export function WEPSCLIShellApp(props) {
|
|
|
27
33
|
const renderer = useRenderer();
|
|
28
34
|
const dimensions = useTerminalDimensions();
|
|
29
35
|
const sessionHistory = new SessionHistoryService();
|
|
30
|
-
const [view, setView] = createSignal("home");
|
|
31
36
|
const [focusRegion, setFocusRegionState] = createSignal("composer");
|
|
32
37
|
const [overlay, setOverlay] = createSignal(undefined);
|
|
33
38
|
const [profiles, setProfiles] = createSignal(props.profileService.listProfiles());
|
|
@@ -42,6 +47,7 @@ export function WEPSCLIShellApp(props) {
|
|
|
42
47
|
const [runtimeStateBySession, setRuntimeStateBySession] = createSignal({});
|
|
43
48
|
const [approvalRequests, setApprovalRequests] = createSignal([]);
|
|
44
49
|
const [approvalDecisionIndex, setApprovalDecisionIndex] = createSignal(0);
|
|
50
|
+
const [skillSlashCommands, setSkillSlashCommands] = createSignal([]);
|
|
45
51
|
const runtime = new WepsAgentRuntime(props.profileService, {
|
|
46
52
|
appendMessage: (sessionId, message) => appendTranscriptMessage(sessionId, message),
|
|
47
53
|
insertMessageBefore: (sessionId, beforeMessageId, message) => insertTranscriptMessageBefore(sessionId, beforeMessageId, message),
|
|
@@ -87,34 +93,47 @@ export function WEPSCLIShellApp(props) {
|
|
|
87
93
|
},
|
|
88
94
|
onClose: () => setFocusRegion("composer")
|
|
89
95
|
});
|
|
96
|
+
const skillAddFlow = createSkillAddFlow({
|
|
97
|
+
onInstalled: async ({
|
|
98
|
+
skill,
|
|
99
|
+
targetDir,
|
|
100
|
+
diagnostics
|
|
101
|
+
}) => {
|
|
102
|
+
const session = currentSession();
|
|
103
|
+
const sessionId = session?.id ?? createdTransientSessionId();
|
|
104
|
+
const warnings = diagnostics.filter(diagnostic => diagnostic.type === "warning").length;
|
|
105
|
+
const reloaded = session ? await runtime.reload(session.id, selectionForSession(session), {
|
|
106
|
+
runtimeSessionFile: session.runtimeSessionFile
|
|
107
|
+
}) : false;
|
|
108
|
+
await reloadSkillSlashCommands();
|
|
109
|
+
pushChatMessage(sessionId, {
|
|
110
|
+
id: `skill-add:${skill.name}:${Date.now()}`,
|
|
111
|
+
role: "system",
|
|
112
|
+
content: reloaded ? `Installed skill ${skill.name} and reloaded the current session.\nPath: ${targetDir}${warnings > 0 ? `\nWarnings: ${warnings}` : ""}` : `Installed skill ${skill.name}.\nPath: ${targetDir}${warnings > 0 ? `\nWarnings: ${warnings}` : ""}`,
|
|
113
|
+
time: new Date().toLocaleTimeString("en-US", {
|
|
114
|
+
hour: "2-digit",
|
|
115
|
+
minute: "2-digit"
|
|
116
|
+
}),
|
|
117
|
+
kind: "status"
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
onClose: () => setFocusRegion("composer")
|
|
121
|
+
});
|
|
90
122
|
const viewport = createMemo(() => ({
|
|
91
123
|
width: dimensions().width || 120,
|
|
92
124
|
height: dimensions().height || 32
|
|
93
125
|
}));
|
|
94
|
-
const showSidebar = createMemo(() => false);
|
|
95
|
-
const shellReady = createMemo(() => profiles().length > 0);
|
|
96
126
|
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
|
-
});
|
|
127
|
+
const activeProfile = createMemo(() => selection().profileId ? profiles().find(profile => profile.id === selection().profileId) : profiles()[0]);
|
|
101
128
|
const activeModel = createMemo(() => selection().modelId ?? activeProfile()?.models[0]?.id);
|
|
102
129
|
const currentSession = createMemo(() => {
|
|
103
|
-
const currentId = activeSessionId()
|
|
104
|
-
|
|
130
|
+
const currentId = activeSessionId(),
|
|
131
|
+
list = sessions();
|
|
105
132
|
return currentId ? list.find(item => item.id === currentId) : list.find(item => item.state === "active") ?? list[0];
|
|
106
133
|
});
|
|
107
|
-
const currentMessages = createMemo(() =>
|
|
108
|
-
|
|
109
|
-
|
|
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.");
|
|
134
|
+
const currentMessages = createMemo(() => currentSession() ? messagesBySession()[currentSession().id] ?? [] : []);
|
|
135
|
+
const currentRuntimeState = createMemo(() => currentSession() ? runtimeStateBySession()[currentSession().id] ?? createIdleRuntimeState() : createIdleRuntimeState());
|
|
136
|
+
const activeApproval = createMemo(() => getSessionApprovalRequest(approvalRequests(), currentSession()?.id));
|
|
118
137
|
const overlayOptions = createMemo(() => {
|
|
119
138
|
switch (overlay()) {
|
|
120
139
|
case "provider":
|
|
@@ -156,6 +175,7 @@ export function WEPSCLIShellApp(props) {
|
|
|
156
175
|
});
|
|
157
176
|
onMount(() => {
|
|
158
177
|
writeShellDebugLog(`mounted chat shell profiles=${profiles().length} sessions=${sessionHistory.listSessions().length}`);
|
|
178
|
+
void reloadSkillSlashCommands();
|
|
159
179
|
setTimeout(() => composerRef?.focus(), 10);
|
|
160
180
|
});
|
|
161
181
|
createEffect(() => {
|
|
@@ -179,132 +199,38 @@ export function WEPSCLIShellApp(props) {
|
|
|
179
199
|
}
|
|
180
200
|
writeShellDebugLog(`effect session=${session.id} messages=${currentMessages().length}`);
|
|
181
201
|
});
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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;
|
|
202
|
+
useShellKeyboard({
|
|
203
|
+
focusRegion,
|
|
204
|
+
overlay,
|
|
205
|
+
overlayIndex,
|
|
206
|
+
overlayOptionsLength: () => overlayOptions().length,
|
|
207
|
+
hasActiveApproval: () => Boolean(activeApproval()),
|
|
208
|
+
approvalDecisionIndex,
|
|
209
|
+
providerAddFlowActive: () => providerAddFlow.isActive(),
|
|
210
|
+
providerAddFlowPickerStep: () => providerAddFlow.isPickerStep(),
|
|
211
|
+
skillAddFlowActive: () => skillAddFlow.isActive(),
|
|
212
|
+
composerValue: () => composerRef?.value ?? composerValue()
|
|
213
|
+
}, {
|
|
214
|
+
exitShell,
|
|
215
|
+
abortActiveRequest,
|
|
216
|
+
resolveActiveApproval,
|
|
217
|
+
setApprovalDecisionIndex: updater => setApprovalDecisionIndex(updater),
|
|
218
|
+
providerAddBack: () => providerAddFlow.back(),
|
|
219
|
+
providerAddMoveSelection: delta => providerAddFlow.moveSelection(delta),
|
|
220
|
+
providerAddConfirmSelection: () => providerAddFlow.confirmSelection(),
|
|
221
|
+
closeSkillAddFlow: () => skillAddFlow.close(),
|
|
222
|
+
closeOverlay,
|
|
223
|
+
setOverlayIndex: updater => setOverlayIndex(updater),
|
|
224
|
+
activateOverlaySelection: () => {
|
|
225
|
+
const target = overlayOptions()[overlayIndex()];
|
|
226
|
+
if (target) {
|
|
227
|
+
activateAction(target.id);
|
|
302
228
|
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
229
|
+
},
|
|
230
|
+
applyNextShellMode: () => applyShellMode(nextShellMode(shellMode())),
|
|
231
|
+
applyMode: modeId => applyShellMode(modeId),
|
|
232
|
+
cycleFocus,
|
|
233
|
+
setFocusRegion
|
|
308
234
|
});
|
|
309
235
|
function exitShell() {
|
|
310
236
|
if (closed) return;
|
|
@@ -343,6 +269,10 @@ export function WEPSCLIShellApp(props) {
|
|
|
343
269
|
setProfiles(props.profileService.listProfiles());
|
|
344
270
|
setSelection(props.profileService.getActiveSelection());
|
|
345
271
|
}
|
|
272
|
+
async function reloadSkillSlashCommands() {
|
|
273
|
+
const result = await listInstalledSkills();
|
|
274
|
+
setSkillSlashCommands(buildSkillSlashCommands(result.skills));
|
|
275
|
+
}
|
|
346
276
|
function updateRuntimeState(sessionId, state) {
|
|
347
277
|
setRuntimeStateBySession(current => ({
|
|
348
278
|
...current,
|
|
@@ -422,10 +352,12 @@ export function WEPSCLIShellApp(props) {
|
|
|
422
352
|
}
|
|
423
353
|
function openApprovalRequest(request) {
|
|
424
354
|
writeShellDebugLog(`approval open tool=${request.toolName} id=${request.id}`);
|
|
425
|
-
setOverlay(undefined);
|
|
426
355
|
setApprovalRequests(current => [...current, request]);
|
|
427
|
-
|
|
428
|
-
|
|
356
|
+
if (currentSession()?.id === request.sessionId) {
|
|
357
|
+
setOverlay(undefined);
|
|
358
|
+
setApprovalDecisionIndex(0);
|
|
359
|
+
setFocusRegion("overlay");
|
|
360
|
+
}
|
|
429
361
|
requestRender();
|
|
430
362
|
}
|
|
431
363
|
function closeApprovalRequest(requestId) {
|
|
@@ -462,12 +394,6 @@ export function WEPSCLIShellApp(props) {
|
|
|
462
394
|
const index = order.indexOf(focusRegion());
|
|
463
395
|
setFocusRegion(order[(index + 1) % order.length] ?? "composer");
|
|
464
396
|
}
|
|
465
|
-
function setShellView(next) {
|
|
466
|
-
batch(() => {
|
|
467
|
-
setView(next);
|
|
468
|
-
});
|
|
469
|
-
setFocusRegion("composer");
|
|
470
|
-
}
|
|
471
397
|
function openOverlay(kind) {
|
|
472
398
|
if (kind === "model" && profiles().length === 0) {
|
|
473
399
|
return;
|
|
@@ -495,9 +421,18 @@ export function WEPSCLIShellApp(props) {
|
|
|
495
421
|
}
|
|
496
422
|
function openProviderAdd() {
|
|
497
423
|
setOverlay(undefined);
|
|
424
|
+
skillAddFlow.close();
|
|
498
425
|
providerAddFlow.open();
|
|
499
426
|
setFocusRegion("overlay");
|
|
500
427
|
}
|
|
428
|
+
function openSkillAdd() {
|
|
429
|
+
setOverlay(undefined);
|
|
430
|
+
if (providerAddFlow.isActive()) {
|
|
431
|
+
providerAddFlow.close();
|
|
432
|
+
}
|
|
433
|
+
skillAddFlow.open();
|
|
434
|
+
setFocusRegion("overlay");
|
|
435
|
+
}
|
|
501
436
|
function ensureSessionTranscript(sessionId) {
|
|
502
437
|
setMessagesBySession(current => {
|
|
503
438
|
if (current[sessionId]) return current;
|
|
@@ -586,6 +521,16 @@ export function WEPSCLIShellApp(props) {
|
|
|
586
521
|
reloadProviderState();
|
|
587
522
|
}
|
|
588
523
|
function activateSession(sessionId) {
|
|
524
|
+
cancelTranscriptAutoScroll();
|
|
525
|
+
if (providerAddFlow.isActive()) {
|
|
526
|
+
providerAddFlow.close();
|
|
527
|
+
}
|
|
528
|
+
if (skillAddFlow.isActive()) {
|
|
529
|
+
skillAddFlow.close();
|
|
530
|
+
}
|
|
531
|
+
setOverlay(undefined);
|
|
532
|
+
setOverlayIndex(0);
|
|
533
|
+
setApprovalDecisionIndex(0);
|
|
589
534
|
setActiveSessionId(sessionId);
|
|
590
535
|
ensureSessionTranscript(sessionId);
|
|
591
536
|
syncActiveSelectionFromSession(sessionId);
|
|
@@ -593,7 +538,6 @@ export function WEPSCLIShellApp(props) {
|
|
|
593
538
|
if (session) {
|
|
594
539
|
sessionHistory.markActive(sessionId);
|
|
595
540
|
setSessions(sessionHistory.listSessions());
|
|
596
|
-
setShellView("home");
|
|
597
541
|
void runtime.syncSelection(sessionId, selectionForSession(session));
|
|
598
542
|
if (session.runtimeSessionFile) {
|
|
599
543
|
void runtime.loadSession(sessionId, selectionForSession(session), {
|
|
@@ -601,7 +545,8 @@ export function WEPSCLIShellApp(props) {
|
|
|
601
545
|
});
|
|
602
546
|
}
|
|
603
547
|
}
|
|
604
|
-
|
|
548
|
+
setFocusRegion(nextFocusRegionForSession(sessionId, approvalRequests()));
|
|
549
|
+
scheduleTranscriptScrollToBottom();
|
|
605
550
|
}
|
|
606
551
|
function startNewSession() {
|
|
607
552
|
const provider = activeProfile();
|
|
@@ -644,87 +589,67 @@ export function WEPSCLIShellApp(props) {
|
|
|
644
589
|
});
|
|
645
590
|
requestRender();
|
|
646
591
|
}
|
|
647
|
-
function
|
|
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);
|
|
592
|
+
function updatePromptSession(session, trimmed, sessionSelection) {
|
|
663
593
|
sessionHistory.updateSession(session.id, {
|
|
664
594
|
title: `Chat: ${truncate(trimmed, 24)}`,
|
|
665
595
|
summary: `Last prompt: ${truncate(trimmed, 60)}`,
|
|
666
|
-
providerProfileId:
|
|
596
|
+
providerProfileId: sessionSelection.profileId,
|
|
667
597
|
providerLabel: activeProfile()?.label,
|
|
668
|
-
modelId:
|
|
598
|
+
modelId: sessionSelection.modelId,
|
|
669
599
|
lastPrompt: trimmed,
|
|
670
600
|
state: "active"
|
|
671
601
|
});
|
|
672
602
|
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
603
|
}
|
|
682
|
-
function
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
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
|
-
}
|
|
604
|
+
async function reloadCurrentSessionResources() {
|
|
605
|
+
const session = currentSession();
|
|
606
|
+
if (!session) {
|
|
607
|
+
promptController.pushSystemMessage(createdTransientSessionId(), "No active session is ready to reload yet.");
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
const reloaded = await runtime.reload(session.id, selectionForSession(session), {
|
|
611
|
+
runtimeSessionFile: session.runtimeSessionFile
|
|
726
612
|
});
|
|
727
|
-
|
|
613
|
+
await reloadSkillSlashCommands();
|
|
614
|
+
promptController.pushSystemMessage(session.id, reloaded ? "Reloaded skills, prompts, and extensions for the current session." : "Resource reload did not complete successfully.");
|
|
615
|
+
}
|
|
616
|
+
const promptController = createShellPromptController({
|
|
617
|
+
currentSession,
|
|
618
|
+
startNewSession,
|
|
619
|
+
createdTransientSessionId,
|
|
620
|
+
selectionForSession,
|
|
621
|
+
ensureSessionTranscript,
|
|
622
|
+
updatePromptSession,
|
|
623
|
+
pushChatMessage,
|
|
624
|
+
setComposerValue,
|
|
625
|
+
setComposerText: value => composerRef?.setText?.(value),
|
|
626
|
+
focusComposer: () => composerRef?.focus(),
|
|
627
|
+
setFocusRegionComposer: () => setFocusRegion("composer"),
|
|
628
|
+
requestRender,
|
|
629
|
+
runtimePrompt: (sessionId, text, sessionSelection, runtimeSessionFile) => {
|
|
630
|
+
void runtime.prompt(sessionId, text, sessionSelection, {
|
|
631
|
+
runtimeSessionFile
|
|
632
|
+
});
|
|
633
|
+
},
|
|
634
|
+
reloadCurrentSessionResources,
|
|
635
|
+
openSkillAdd,
|
|
636
|
+
openOverlay,
|
|
637
|
+
openProviderAdd,
|
|
638
|
+
compactCurrentSession,
|
|
639
|
+
abortActiveRequest: () => {
|
|
640
|
+
void abortActiveRequest();
|
|
641
|
+
},
|
|
642
|
+
applyShellMode,
|
|
643
|
+
getCurrentMode: () => shellMode(),
|
|
644
|
+
getStatusSummary: () => {
|
|
645
|
+
const session = currentSession();
|
|
646
|
+
return ["Current shell status:", `Session: ${session?.title ?? "none"}`, `Mode: ${activeShellMode().label}`, `Provider: ${activeProfile()?.label ?? "none"}`, `Model: ${activeModel() ?? "none"}`, `Runtime: ${currentRuntimeState().label}`, `Agent dir: ${getAgentDir()}`].join("\n");
|
|
647
|
+
},
|
|
648
|
+
showSkillsSummary: async () => {
|
|
649
|
+
promptController.pushSystemMessage(currentSession()?.id ?? createdTransientSessionId(), await formatInstalledSkillsSummary());
|
|
650
|
+
},
|
|
651
|
+
getAdditionalSlashCommands: skillSlashCommands
|
|
652
|
+
});
|
|
728
653
|
function activateAction(actionId) {
|
|
729
654
|
if (actionId === "session:new") {
|
|
730
655
|
startNewSession();
|
|
@@ -839,30 +764,7 @@ export function WEPSCLIShellApp(props) {
|
|
|
839
764
|
ensureSessionTranscript(created.id);
|
|
840
765
|
return created.id;
|
|
841
766
|
}
|
|
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
|
-
}
|
|
767
|
+
const topStatus = createMemo(() => `${activeProfile()?.label ?? "none"} · ${activeModel() ?? "no model"} · ${currentRuntimeState().label}`);
|
|
866
768
|
return (() => {
|
|
867
769
|
var _el$ = _$createElement("box"),
|
|
868
770
|
_el$2 = _$createElement("box"),
|
|
@@ -973,8 +875,15 @@ export function WEPSCLIShellApp(props) {
|
|
|
973
875
|
onFocus: () => setFocusRegion("composer"),
|
|
974
876
|
onInput: value => setComposerValue(value),
|
|
975
877
|
onModeClick: () => applyShellMode(nextShellMode(shellMode())),
|
|
976
|
-
onSubmit
|
|
977
|
-
|
|
878
|
+
get onSubmit() {
|
|
879
|
+
return promptController.handleComposerSubmit;
|
|
880
|
+
},
|
|
881
|
+
get onSelectSlashCommand() {
|
|
882
|
+
return promptController.runSlashCommand;
|
|
883
|
+
},
|
|
884
|
+
get slashCommands() {
|
|
885
|
+
return skillSlashCommands();
|
|
886
|
+
}
|
|
978
887
|
}), _el$0);
|
|
979
888
|
_$insert(_el$, (() => {
|
|
980
889
|
var _c$2 = _$memo(() => !!overlay());
|
|
@@ -1012,6 +921,7 @@ export function WEPSCLIShellApp(props) {
|
|
|
1012
921
|
}) : null;
|
|
1013
922
|
})(), _el$0);
|
|
1014
923
|
_$insert(_el$, () => providerAddFlow.render(), _el$0);
|
|
924
|
+
_$insert(_el$, () => skillAddFlow.render(), _el$0);
|
|
1015
925
|
_$insertNode(_el$0, _el$1);
|
|
1016
926
|
_$setProp(_el$0, "flexShrink", 0);
|
|
1017
927
|
_$setProp(_el$0, "paddingLeft", 1);
|