@aiwayds/dsh-tui-pi 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.
- package/LICENSE +21 -0
- package/README.md +324 -0
- package/bin/dsh-tui-pi +5 -0
- package/cordis.patch.yml +9 -0
- package/lib/append-system.d.ts +66 -0
- package/lib/append-system.js +161 -0
- package/lib/append-system.js.map +1 -0
- package/lib/commands.d.ts +53 -0
- package/lib/commands.js +167 -0
- package/lib/commands.js.map +1 -0
- package/lib/dsh-events.d.ts +106 -0
- package/lib/dsh-events.js +30 -0
- package/lib/dsh-events.js.map +1 -0
- package/lib/editor.d.ts +28 -0
- package/lib/editor.js +70 -0
- package/lib/editor.js.map +1 -0
- package/lib/footer.d.ts +36 -0
- package/lib/footer.js +112 -0
- package/lib/footer.js.map +1 -0
- package/lib/frame.d.ts +35 -0
- package/lib/frame.js +75 -0
- package/lib/frame.js.map +1 -0
- package/lib/git.d.ts +17 -0
- package/lib/git.js +51 -0
- package/lib/git.js.map +1 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.js +781 -0
- package/lib/index.js.map +1 -0
- package/lib/instructions.d.ts +29 -0
- package/lib/instructions.js +67 -0
- package/lib/instructions.js.map +1 -0
- package/lib/live-widgets.d.ts +85 -0
- package/lib/live-widgets.js +218 -0
- package/lib/live-widgets.js.map +1 -0
- package/lib/messages.d.ts +277 -0
- package/lib/messages.js +734 -0
- package/lib/messages.js.map +1 -0
- package/lib/permission.d.ts +27 -0
- package/lib/permission.js +48 -0
- package/lib/permission.js.map +1 -0
- package/lib/provider-catalog.d.ts +114 -0
- package/lib/provider-catalog.js +124 -0
- package/lib/provider-catalog.js.map +1 -0
- package/lib/quotes.d.ts +28 -0
- package/lib/quotes.js +144 -0
- package/lib/quotes.js.map +1 -0
- package/lib/reload.d.ts +23 -0
- package/lib/reload.js +171 -0
- package/lib/reload.js.map +1 -0
- package/lib/selectors.d.ts +48 -0
- package/lib/selectors.js +261 -0
- package/lib/selectors.js.map +1 -0
- package/lib/session.d.ts +157 -0
- package/lib/session.js +555 -0
- package/lib/session.js.map +1 -0
- package/lib/sessions.d.ts +73 -0
- package/lib/sessions.js +253 -0
- package/lib/sessions.js.map +1 -0
- package/lib/settings.d.ts +180 -0
- package/lib/settings.js +1328 -0
- package/lib/settings.js.map +1 -0
- package/lib/text.d.ts +22 -0
- package/lib/text.js +45 -0
- package/lib/text.js.map +1 -0
- package/lib/theme/index.d.ts +79 -0
- package/lib/theme/index.js +121 -0
- package/lib/theme/index.js.map +1 -0
- package/lib/theme/palette.d.ts +56 -0
- package/lib/theme/palette.js +154 -0
- package/lib/theme/palette.js.map +1 -0
- package/lib/theme-settings.d.ts +68 -0
- package/lib/theme-settings.js +223 -0
- package/lib/theme-settings.js.map +1 -0
- package/lib/tui.d.ts +70 -0
- package/lib/tui.js +206 -0
- package/lib/tui.js.map +1 -0
- package/lib/welcome.d.ts +91 -0
- package/lib/welcome.js +281 -0
- package/lib/welcome.js.map +1 -0
- package/package.json +50 -0
- package/patches/@earendil-works__pi-tui.patch +72 -0
- package/pnpm-workspace.yaml +2 -0
- package/templates/APPEND_SYSTEM.md +34 -0
package/lib/session.js
ADDED
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session bridge between the dsh tree and the TUI.
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* - lazy agent creation on first prompt (openma runner pattern)
|
|
6
|
+
* - prompt delivery via agent.followup()
|
|
7
|
+
* - session-event subscription filtered to the bridge's session
|
|
8
|
+
* - O(1) incremental stats maintained as events arrive (footer reads these —
|
|
9
|
+
* never re-scans the session log, per the pi-turbo findings)
|
|
10
|
+
* - resume of persisted sessions (log replay into stats + transcript)
|
|
11
|
+
*/
|
|
12
|
+
import { installModelSelection } from '@deepseek-ai/dsh-agent';
|
|
13
|
+
import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
14
|
+
import { settingsNamespace, SettingsConflictError } from '@deepseek-ai/dsh-settings';
|
|
15
|
+
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
16
|
+
import { isAgentEnd, isAgentStart, isLlmRetry, isSubagentDescriptor } from "./dsh-events.js";
|
|
17
|
+
export class DshSessionBridge {
|
|
18
|
+
ctx;
|
|
19
|
+
callbacks;
|
|
20
|
+
handle;
|
|
21
|
+
creating;
|
|
22
|
+
resuming;
|
|
23
|
+
disposers = [];
|
|
24
|
+
sessionId;
|
|
25
|
+
selection;
|
|
26
|
+
/** Mutable live selection installed into the agent; `/model` mutates `current`. */
|
|
27
|
+
selectionRef = { current: undefined, assembled: undefined };
|
|
28
|
+
/** Mirror of the agent's `agent/status`; `isRunning()` reads this. */
|
|
29
|
+
running = false;
|
|
30
|
+
stats = {
|
|
31
|
+
inputTokens: 0,
|
|
32
|
+
outputTokens: 0,
|
|
33
|
+
cacheReadTokens: 0,
|
|
34
|
+
cacheWriteTokens: 0,
|
|
35
|
+
msgCount: 0,
|
|
36
|
+
toolCallCount: 0,
|
|
37
|
+
};
|
|
38
|
+
/** Live subagent rows keyed by child session id. */
|
|
39
|
+
agentViews = new Map();
|
|
40
|
+
/** Child session ids whose own events we fold into the agent views. */
|
|
41
|
+
childSessions = new Set();
|
|
42
|
+
/**
|
|
43
|
+
* Session ids that can own tracked children (this session first, then every
|
|
44
|
+
* tracked child — delegation nests). Used to match `parentSession` headers
|
|
45
|
+
* and to fold workflow events of the parent log.
|
|
46
|
+
*/
|
|
47
|
+
trackedSessions = new Set();
|
|
48
|
+
/** `${runId}:${seq}` → childId, for `tool-workflow/agent-end` pairing. */
|
|
49
|
+
runSeqToChild = new Map();
|
|
50
|
+
constructor(ctx, callbacks) {
|
|
51
|
+
this.ctx = ctx;
|
|
52
|
+
this.callbacks = callbacks;
|
|
53
|
+
// Footer shows provider/model from the very first frame — read the
|
|
54
|
+
// composed default selection eagerly; a session created later refreshes it.
|
|
55
|
+
const defaultModel = ctx.get('agentDefaultModel');
|
|
56
|
+
const sel = defaultModel?.currentSelection();
|
|
57
|
+
this.selection = sel === undefined
|
|
58
|
+
? undefined
|
|
59
|
+
: {
|
|
60
|
+
provider: sel.provider,
|
|
61
|
+
model: sel.model,
|
|
62
|
+
...sel.reasoningEffort === undefined ? {} : { reasoningEffort: sel.reasoningEffort },
|
|
63
|
+
};
|
|
64
|
+
this.disposers.push(ctx.on('session/event', (session, event) => {
|
|
65
|
+
const sessionKey = String(session.id);
|
|
66
|
+
// Discover subagent children by session header — the deployment may
|
|
67
|
+
// never emit tool-workflow events (the firehose is not scope-filtered,
|
|
68
|
+
// so child sessions arrive here too). Any session whose parent is a
|
|
69
|
+
// tracked session is a child; the descriptor event later refines the
|
|
70
|
+
// label/provider.
|
|
71
|
+
const header = session.header;
|
|
72
|
+
if (header?.origin === 'subagent' && header.parentSession !== undefined
|
|
73
|
+
&& this.trackedSessions.has(String(header.parentSession))
|
|
74
|
+
&& !this.agentViews.has(sessionKey)) {
|
|
75
|
+
this.agentViews.set(sessionKey, {
|
|
76
|
+
childId: sessionKey,
|
|
77
|
+
label: `subagent ${sessionKey.slice(0, 8)}`,
|
|
78
|
+
startedAt: event.time,
|
|
79
|
+
tokens: 0,
|
|
80
|
+
retries: 0,
|
|
81
|
+
});
|
|
82
|
+
this.childSessions.add(sessionKey);
|
|
83
|
+
this.trackedSessions.add(sessionKey);
|
|
84
|
+
this.emitLive();
|
|
85
|
+
}
|
|
86
|
+
// Fold workflow + child events for every tracked session.
|
|
87
|
+
if (this.trackedSessions.has(sessionKey)) {
|
|
88
|
+
this.foldTracked(sessionKey, event);
|
|
89
|
+
}
|
|
90
|
+
if (this.sessionId !== undefined && session.id === this.sessionId) {
|
|
91
|
+
this.applyEvent(event);
|
|
92
|
+
this.callbacks.onEvent(event);
|
|
93
|
+
}
|
|
94
|
+
}));
|
|
95
|
+
this.disposers.push(ctx.on('agent/status', ({ agent, status }) => {
|
|
96
|
+
if (this.handle === undefined || agent.id !== this.handle.agent.id)
|
|
97
|
+
return;
|
|
98
|
+
this.running = status === 'running';
|
|
99
|
+
this.callbacks.onStatus(status);
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
/** Snapshot of the incremental stats (footer reads this O(1)). */
|
|
103
|
+
getStats() {
|
|
104
|
+
return { ...this.stats };
|
|
105
|
+
}
|
|
106
|
+
/** Current session id, when one exists. */
|
|
107
|
+
getSessionId() {
|
|
108
|
+
return this.sessionId;
|
|
109
|
+
}
|
|
110
|
+
/** Queue one user prompt, creating the session lazily on first use. */
|
|
111
|
+
async prompt(text) {
|
|
112
|
+
const handle = await this.ensureSession();
|
|
113
|
+
const message = createUserMessage({
|
|
114
|
+
content: [{ type: 'text', text }],
|
|
115
|
+
source: { kind: 'user' },
|
|
116
|
+
});
|
|
117
|
+
handle.agent.followup(message);
|
|
118
|
+
}
|
|
119
|
+
/** The live agent, creating the session lazily when needed. */
|
|
120
|
+
async ensureAgent() {
|
|
121
|
+
const handle = await this.ensureSession();
|
|
122
|
+
return handle.agent;
|
|
123
|
+
}
|
|
124
|
+
/** The live agent when a session already exists (no creation side effect). */
|
|
125
|
+
getAgent() {
|
|
126
|
+
return this.handle?.agent;
|
|
127
|
+
}
|
|
128
|
+
/** Whether the bridge's agent is mid-turn (mirror of `agent/status`). */
|
|
129
|
+
isRunning() {
|
|
130
|
+
return this.running;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Abort the bridge's agent mid-turn, mirroring the web client's stop
|
|
134
|
+
* button: the host-side `session.cancel` handler calls
|
|
135
|
+
* `agent.cancel({ kind: 'user' }, { keepInbox: true })`
|
|
136
|
+
* (dsh-host-apiproxy), and that is exactly what the agent's public
|
|
137
|
+
* synchronous `cancel(cause, options)` API takes. `keepInbox` preserves
|
|
138
|
+
* queued prompts for a later turn; the active driver's AbortSignal fires
|
|
139
|
+
* and status converges to `idle` via the existing subscription. The API
|
|
140
|
+
* is fire-and-forget — the returned promise resolves once the call is
|
|
141
|
+
* made, not when the turn settles.
|
|
142
|
+
* @returns false when there is no agent or it is not running; true once
|
|
143
|
+
* the cancellation was issued.
|
|
144
|
+
*/
|
|
145
|
+
async cancelActiveTurn() {
|
|
146
|
+
const agent = this.handle?.agent;
|
|
147
|
+
if (agent === undefined || !this.running)
|
|
148
|
+
return false;
|
|
149
|
+
try {
|
|
150
|
+
agent.cancel({ kind: 'user' }, { keepInbox: true });
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// Cancellation must never take the input path down with it.
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** Dispose the live agent (if any) and stop event subscriptions. */
|
|
159
|
+
async dispose() {
|
|
160
|
+
for (const dispose of this.disposers.splice(0)) {
|
|
161
|
+
try {
|
|
162
|
+
dispose();
|
|
163
|
+
}
|
|
164
|
+
catch { /* contained */ }
|
|
165
|
+
}
|
|
166
|
+
const handle = this.handle;
|
|
167
|
+
this.handle = undefined;
|
|
168
|
+
this.sessionId = undefined;
|
|
169
|
+
this.running = false;
|
|
170
|
+
this.agentViews.clear();
|
|
171
|
+
this.childSessions.clear();
|
|
172
|
+
this.trackedSessions.clear();
|
|
173
|
+
this.runSeqToChild.clear();
|
|
174
|
+
if (handle !== undefined)
|
|
175
|
+
await handle.dispose();
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Detach the live agent WITHOUT tearing down the event subscriptions —
|
|
179
|
+
* `/new` wants a fresh session while the renderer keeps receiving events.
|
|
180
|
+
* The agent handle is disposed, the session id cleared, and the
|
|
181
|
+
* incremental stats zeroed (the footer must not carry the old session's
|
|
182
|
+
* numbers); the disposers stay installed, and the session-id filter
|
|
183
|
+
* re-binds on the next lazy creation. The subagent tracker is cleared and
|
|
184
|
+
* an empty `onLive` is emitted so the renderer drops the agents block.
|
|
185
|
+
*/
|
|
186
|
+
async detachCurrent() {
|
|
187
|
+
const handle = this.handle;
|
|
188
|
+
this.handle = undefined;
|
|
189
|
+
this.sessionId = undefined;
|
|
190
|
+
this.running = false;
|
|
191
|
+
this.stats.inputTokens = 0;
|
|
192
|
+
this.stats.outputTokens = 0;
|
|
193
|
+
this.stats.cacheReadTokens = 0;
|
|
194
|
+
this.stats.cacheWriteTokens = 0;
|
|
195
|
+
this.stats.msgCount = 0;
|
|
196
|
+
this.stats.toolCallCount = 0;
|
|
197
|
+
this.stats.cacheHitRate = undefined;
|
|
198
|
+
this.agentViews.clear();
|
|
199
|
+
this.childSessions.clear();
|
|
200
|
+
this.trackedSessions.clear();
|
|
201
|
+
this.runSeqToChild.clear();
|
|
202
|
+
this.emitLive();
|
|
203
|
+
if (handle !== undefined)
|
|
204
|
+
await handle.dispose();
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Resume a persisted session: tear down the live agent (disposers are kept —
|
|
208
|
+
* the session-id filter re-binds to the resumed id) and load the persisted
|
|
209
|
+
* session in its place. The caller replays `handle.agent.session.events`
|
|
210
|
+
* through `replay()` to rebuild stats/transcript — clear the transcript
|
|
211
|
+
* BEFORE replaying (the renderer's echo dedupe must not see replayed user
|
|
212
|
+
* messages next to a stale local echo). Serialized: concurrent calls share
|
|
213
|
+
* the single in-flight resume.
|
|
214
|
+
*/
|
|
215
|
+
async resume(sessionId) {
|
|
216
|
+
if (this.resuming !== undefined)
|
|
217
|
+
return this.resuming;
|
|
218
|
+
const task = (async () => {
|
|
219
|
+
const handle = this.handle;
|
|
220
|
+
this.handle = undefined;
|
|
221
|
+
this.sessionId = undefined;
|
|
222
|
+
this.running = false;
|
|
223
|
+
this.agentViews.clear();
|
|
224
|
+
this.childSessions.clear();
|
|
225
|
+
this.trackedSessions.clear();
|
|
226
|
+
this.runSeqToChild.clear();
|
|
227
|
+
// The renderer keeps its live snapshot across the resume teardown (it
|
|
228
|
+
// must survive theme-switch rebuilds), so an empty emit is required to
|
|
229
|
+
// drop the previous session's agents block before the resumed log's
|
|
230
|
+
// workflow events rebuild it.
|
|
231
|
+
this.emitLive();
|
|
232
|
+
if (handle !== undefined)
|
|
233
|
+
await handle.dispose();
|
|
234
|
+
// Same seeding rule as createSession: a live /model or /think choice
|
|
235
|
+
// survives the resume; otherwise the composed default applies.
|
|
236
|
+
this.seedSelectionFromDefault();
|
|
237
|
+
const resumed = await this.ctx.agents.resume({
|
|
238
|
+
resumeSessionId: sessionId,
|
|
239
|
+
agentOptions: this.selection ?? {},
|
|
240
|
+
// Install the mutable selection so `/model` can live-switch the route.
|
|
241
|
+
setup: async (agentCtx) => {
|
|
242
|
+
installModelSelection(agentCtx, this.selectionRef);
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
this.handle = resumed;
|
|
246
|
+
this.sessionId = sessionId;
|
|
247
|
+
this.trackedSessions.add(String(sessionId));
|
|
248
|
+
return resumed;
|
|
249
|
+
})();
|
|
250
|
+
this.resuming = task;
|
|
251
|
+
try {
|
|
252
|
+
return await task;
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
this.resuming = undefined;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Replay a persisted session log into the transcript and stats — the second
|
|
260
|
+
* half of a resume (call after `resume()`). Stats are rebuilt from zero so
|
|
261
|
+
* the footer reflects the resumed session only; replaying the same log
|
|
262
|
+
* twice is idempotent. `assistant/chunk` events are skipped: the finalized
|
|
263
|
+
* `assistant/message` carries the full text, and replaying chunks would
|
|
264
|
+
* re-run the quadratic streaming assembly for every historical step.
|
|
265
|
+
*/
|
|
266
|
+
replay(events) {
|
|
267
|
+
this.stats.inputTokens = 0;
|
|
268
|
+
this.stats.outputTokens = 0;
|
|
269
|
+
this.stats.cacheReadTokens = 0;
|
|
270
|
+
this.stats.cacheWriteTokens = 0;
|
|
271
|
+
this.stats.msgCount = 0;
|
|
272
|
+
this.stats.toolCallCount = 0;
|
|
273
|
+
this.stats.cacheHitRate = undefined;
|
|
274
|
+
const sessionId = this.sessionId;
|
|
275
|
+
for (const event of events) {
|
|
276
|
+
if (event.type === 'assistant/chunk')
|
|
277
|
+
continue;
|
|
278
|
+
// Replay feeds the parent log only — fold its persisted workflow events
|
|
279
|
+
// through the same tracking logic so the agents view is rebuilt; child
|
|
280
|
+
// live events arrive via the subscription after resume.
|
|
281
|
+
if (sessionId !== undefined && this.trackedSessions.has(String(sessionId))) {
|
|
282
|
+
this.foldTracked(String(sessionId), event);
|
|
283
|
+
}
|
|
284
|
+
this.applyEvent(event);
|
|
285
|
+
this.callbacks.onEvent(event);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/** Update incremental stats from one event — one pass over the event only. */
|
|
289
|
+
applyEvent(event) {
|
|
290
|
+
switch (event.type) {
|
|
291
|
+
case 'user/message':
|
|
292
|
+
this.stats.msgCount += 1;
|
|
293
|
+
break;
|
|
294
|
+
case 'assistant/message': {
|
|
295
|
+
this.stats.msgCount += 1;
|
|
296
|
+
for (const block of event.data.message.content) {
|
|
297
|
+
if (block.type === 'tool-call')
|
|
298
|
+
this.stats.toolCallCount += 1;
|
|
299
|
+
}
|
|
300
|
+
const usage = event.data.usage;
|
|
301
|
+
if (usage === undefined)
|
|
302
|
+
break;
|
|
303
|
+
this.stats.inputTokens += usage.inputTokens;
|
|
304
|
+
this.stats.outputTokens += usage.outputTokens;
|
|
305
|
+
this.stats.cacheReadTokens += usage.cacheReadTokens ?? 0;
|
|
306
|
+
this.stats.cacheWriteTokens += usage.cacheWriteTokens ?? 0;
|
|
307
|
+
const billedInput = this.stats.inputTokens + this.stats.cacheReadTokens + this.stats.cacheWriteTokens;
|
|
308
|
+
this.stats.cacheHitRate = billedInput > 0
|
|
309
|
+
? (this.stats.cacheReadTokens / billedInput) * 100
|
|
310
|
+
: undefined;
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
default:
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Fold one event of a tracked session into the agent views (workflow events
|
|
319
|
+
* of the parent log + the child's own log). O(1) per event — Maps/Sets only,
|
|
320
|
+
* never a session-log scan. Emits `onLive` when a view actually changed.
|
|
321
|
+
* @returns whether a view changed (and `onLive` was emitted).
|
|
322
|
+
*/
|
|
323
|
+
foldTracked(sessionId, event) {
|
|
324
|
+
let changed = false;
|
|
325
|
+
if (isAgentStart(event)) {
|
|
326
|
+
// Workflow member: register with the workflow label + start time.
|
|
327
|
+
if (!this.agentViews.has(event.data.childId)) {
|
|
328
|
+
this.agentViews.set(event.data.childId, {
|
|
329
|
+
childId: event.data.childId,
|
|
330
|
+
label: event.data.label,
|
|
331
|
+
startedAt: event.time,
|
|
332
|
+
tokens: 0,
|
|
333
|
+
retries: 0,
|
|
334
|
+
});
|
|
335
|
+
this.runSeqToChild.set(`${event.data.runId}:${event.data.seq}`, event.data.childId);
|
|
336
|
+
this.childSessions.add(event.data.childId);
|
|
337
|
+
this.trackedSessions.add(event.data.childId);
|
|
338
|
+
changed = true;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else if (isAgentEnd(event)) {
|
|
342
|
+
const childId = this.runSeqToChild.get(`${event.data.runId}:${event.data.seq}`);
|
|
343
|
+
const existing = childId === undefined ? undefined : this.agentViews.get(childId);
|
|
344
|
+
if (childId !== undefined && existing !== undefined && existing.outcome === undefined) {
|
|
345
|
+
this.agentViews.set(childId, {
|
|
346
|
+
...existing,
|
|
347
|
+
outcome: event.data.outcome,
|
|
348
|
+
endedAt: event.time,
|
|
349
|
+
});
|
|
350
|
+
changed = true;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (this.childSessions.has(sessionId)) {
|
|
354
|
+
const view = this.agentViews.get(sessionId);
|
|
355
|
+
if (view !== undefined) {
|
|
356
|
+
if (isSubagentDescriptor(event)) {
|
|
357
|
+
if (view.provider !== event.data.provider
|
|
358
|
+
|| (event.data.label !== undefined && view.label !== event.data.label)) {
|
|
359
|
+
this.agentViews.set(sessionId, {
|
|
360
|
+
...view,
|
|
361
|
+
provider: event.data.provider,
|
|
362
|
+
...(event.data.label === undefined ? {} : { label: event.data.label }),
|
|
363
|
+
});
|
|
364
|
+
changed = true;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else if (event.type === 'assistant/message') {
|
|
368
|
+
const usage = event.data.usage;
|
|
369
|
+
if (usage !== undefined) {
|
|
370
|
+
const delta = usage.inputTokens + usage.outputTokens
|
|
371
|
+
+ (usage.cacheReadTokens ?? 0) + (usage.cacheWriteTokens ?? 0);
|
|
372
|
+
if (delta > 0) {
|
|
373
|
+
this.agentViews.set(sessionId, { ...view, tokens: view.tokens + delta });
|
|
374
|
+
changed = true;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
else if (isLlmRetry(event)) {
|
|
379
|
+
if (view.retries !== event.data.retry || view.maxRetries !== event.data.maxRetries) {
|
|
380
|
+
this.agentViews.set(sessionId, {
|
|
381
|
+
...view,
|
|
382
|
+
retries: event.data.retry,
|
|
383
|
+
maxRetries: event.data.maxRetries,
|
|
384
|
+
});
|
|
385
|
+
changed = true;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
else if (event.type === 'tool/call') {
|
|
389
|
+
if (view.lastTool !== event.data.name) {
|
|
390
|
+
this.agentViews.set(sessionId, { ...view, lastTool: event.data.name });
|
|
391
|
+
changed = true;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
else if (event.type === 'request/context') {
|
|
395
|
+
const contextWindow = event.data.contextWindow;
|
|
396
|
+
if (typeof contextWindow === 'number' && view.contextWindow !== contextWindow) {
|
|
397
|
+
this.agentViews.set(sessionId, { ...view, contextWindow });
|
|
398
|
+
changed = true;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
else if (event.type === 'turn/end' && view.outcome === undefined) {
|
|
402
|
+
// Best-effort settle for header-discovered children (no workflow
|
|
403
|
+
// outcome event): the child's turn closed — the widget drops it.
|
|
404
|
+
this.agentViews.set(sessionId, { ...view, outcome: 'completed', endedAt: event.time });
|
|
405
|
+
changed = true;
|
|
406
|
+
}
|
|
407
|
+
else if (event.type === 'turn/start' && view.outcome !== undefined) {
|
|
408
|
+
// A continuable child resumed: mark it running again.
|
|
409
|
+
this.agentViews.set(sessionId, { ...view, outcome: undefined, endedAt: undefined });
|
|
410
|
+
changed = true;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (changed)
|
|
415
|
+
this.emitLive();
|
|
416
|
+
return changed;
|
|
417
|
+
}
|
|
418
|
+
/** Push the current agent views (stable order) to the renderer. */
|
|
419
|
+
emitLive() {
|
|
420
|
+
this.callbacks.onLive([...this.agentViews.values()].sort((a, b) => a.startedAt - b.startedAt || a.childId.localeCompare(b.childId)));
|
|
421
|
+
}
|
|
422
|
+
async ensureSession() {
|
|
423
|
+
// A resume in flight would otherwise race this check: the handle is only
|
|
424
|
+
// set when resume completes, so a prompt fired mid-resume must not start
|
|
425
|
+
// a second agent creation. Await it — on success the handle is ready for
|
|
426
|
+
// reuse; on failure fall through to the normal creation path.
|
|
427
|
+
if (this.resuming !== undefined) {
|
|
428
|
+
try {
|
|
429
|
+
await this.resuming;
|
|
430
|
+
}
|
|
431
|
+
catch {
|
|
432
|
+
// Resume failed — fall through to create a fresh session.
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (this.handle !== undefined)
|
|
436
|
+
return this.handle;
|
|
437
|
+
if (this.creating !== undefined)
|
|
438
|
+
return this.creating;
|
|
439
|
+
const creation = this.createSession();
|
|
440
|
+
this.creating = creation;
|
|
441
|
+
try {
|
|
442
|
+
this.handle = await creation;
|
|
443
|
+
this.sessionId = this.handle.agent.session.id;
|
|
444
|
+
this.trackedSessions.add(String(this.sessionId));
|
|
445
|
+
return this.handle;
|
|
446
|
+
}
|
|
447
|
+
finally {
|
|
448
|
+
this.creating = undefined;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Seed `selection`/`selectionRef` from the composed default — without
|
|
453
|
+
* clobbering a live user choice: `/model`/`/think` before the first prompt
|
|
454
|
+
* write the ref, and that choice must survive session creation.
|
|
455
|
+
*/
|
|
456
|
+
seedSelectionFromDefault() {
|
|
457
|
+
if (this.selectionRef.current !== undefined) {
|
|
458
|
+
this.selection = { ...this.selectionRef.current };
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
const defaultModel = this.ctx.get('agentDefaultModel');
|
|
462
|
+
const selection = defaultModel?.currentSelection();
|
|
463
|
+
this.selection = selection === undefined
|
|
464
|
+
? undefined
|
|
465
|
+
: {
|
|
466
|
+
provider: selection.provider,
|
|
467
|
+
model: selection.model,
|
|
468
|
+
...selection.reasoningEffort === undefined ? {} : { reasoningEffort: selection.reasoningEffort },
|
|
469
|
+
};
|
|
470
|
+
this.selectionRef.current = this.selection === undefined ? undefined : { ...this.selection };
|
|
471
|
+
}
|
|
472
|
+
/** Create the agent with the composed default model selection. */
|
|
473
|
+
createSession() {
|
|
474
|
+
this.seedSelectionFromDefault();
|
|
475
|
+
return this.ctx.agents.create({
|
|
476
|
+
sessionId: SessionId(crypto.randomUUID()),
|
|
477
|
+
meta: { cwd: process.cwd() },
|
|
478
|
+
agentOptions: this.selection ?? {},
|
|
479
|
+
// Install the mutable selection so `/model` can live-switch the route.
|
|
480
|
+
setup: async (agentCtx) => {
|
|
481
|
+
installModelSelection(agentCtx, this.selectionRef);
|
|
482
|
+
},
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
/** The model selection shown in the footer (live value after `/model`). */
|
|
486
|
+
getSelection() {
|
|
487
|
+
return this.selectionRef.current ?? this.selection;
|
|
488
|
+
}
|
|
489
|
+
/** Apply a live model switch (`/model` selector outcome). */
|
|
490
|
+
setSelection(next) {
|
|
491
|
+
this.selectionRef.current = { ...next };
|
|
492
|
+
this.selection = { ...next };
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Persist the default model selection. Preferred path: the
|
|
497
|
+
* `agent-default-model` service's `saveSelection`, the official API (a
|
|
498
|
+
* settings.replace, last-write-wins). The namespace is read live by that
|
|
499
|
+
* service — the change takes effect on the next lazy session creation
|
|
500
|
+
* (`/new` or the next prompt) and survives restarts. Without the service,
|
|
501
|
+
* fall back to a direct settings mutate (with one optimistic-concurrency
|
|
502
|
+
* retry). Best-effort: a deployment without a settings provider is skipped
|
|
503
|
+
* silently; a failed write returns its error message for the caller to
|
|
504
|
+
* surface.
|
|
505
|
+
* @returns undefined on success, the failure message otherwise.
|
|
506
|
+
*/
|
|
507
|
+
export async function persistDefaultModel(ctx, selection) {
|
|
508
|
+
const service = ctx.get('agentDefaultModel');
|
|
509
|
+
if (service?.saveSelection !== undefined) {
|
|
510
|
+
try {
|
|
511
|
+
// The service API takes the whole selection and writes through
|
|
512
|
+
// settings.replace (last-write-wins, no revision check). It may be
|
|
513
|
+
// sync or async — awaiting covers both.
|
|
514
|
+
await service.saveSelection(selection);
|
|
515
|
+
return undefined;
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
return error instanceof Error ? error.message : String(error);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
const settings = ctx.get('settings');
|
|
522
|
+
if (settings === undefined)
|
|
523
|
+
return undefined;
|
|
524
|
+
const ns = settingsNamespace('agent-default-model');
|
|
525
|
+
// The descriptor carries the namespace's revision (optimistic-concurrency
|
|
526
|
+
// token for mutate) and proves the schema registration that validates the
|
|
527
|
+
// field names below; the write itself rejects when the namespace is
|
|
528
|
+
// unregistered (no descriptor either).
|
|
529
|
+
const ops = [
|
|
530
|
+
{ op: 'set', path: ['provider'], value: selection.provider },
|
|
531
|
+
{ op: 'set', path: ['model'], value: selection.model },
|
|
532
|
+
];
|
|
533
|
+
if (selection.reasoningEffort === undefined) {
|
|
534
|
+
// Unset so a stale override is dropped from the stored yaml document too.
|
|
535
|
+
ops.push({ op: 'unset', path: ['reasoningEffort'] });
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
ops.push({ op: 'set', path: ['reasoningEffort'], value: selection.reasoningEffort });
|
|
539
|
+
}
|
|
540
|
+
// One retry after a concurrent writer moved the namespace (fresh revision);
|
|
541
|
+
// a second conflict surfaces the raw error for the caller.
|
|
542
|
+
for (let attempt = 0;; attempt++) {
|
|
543
|
+
const descriptor = settings.describe().find(d => d.ns === ns);
|
|
544
|
+
try {
|
|
545
|
+
await settings.mutate(ns, ops, descriptor?.revision);
|
|
546
|
+
return undefined;
|
|
547
|
+
}
|
|
548
|
+
catch (error) {
|
|
549
|
+
if (attempt === 0 && error instanceof SettingsConflictError)
|
|
550
|
+
continue;
|
|
551
|
+
return error instanceof Error ? error.message : String(error);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session TUI overlays: the `/session` info panel and the `/resume`
|
|
3
|
+
* persisted-session picker — terminal counterparts of the web surface's
|
|
4
|
+
* session management. Both follow the pi SelectList overlay pattern
|
|
5
|
+
* (`showOverlay` + `restoreFocus` on close); the info panel is a one-shot
|
|
6
|
+
* read-only component in the style of settings' ReadOnlyViewer.
|
|
7
|
+
*/
|
|
8
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
9
|
+
import type { SessionEvent, SessionHeader, SessionId } from '@deepseek-ai/dsh-session';
|
|
10
|
+
import { type TUI } from '@earendil-works/pi-tui';
|
|
11
|
+
import { type TuiTheme } from './theme/index.ts';
|
|
12
|
+
/** Everything the `/session` info panel renders (snapshot, built by the caller). */
|
|
13
|
+
export interface SessionPanelData {
|
|
14
|
+
id: string | undefined;
|
|
15
|
+
cwd: string | undefined;
|
|
16
|
+
createdAt: number | undefined;
|
|
17
|
+
/** "provider/model", or already including the reasoning effort. */
|
|
18
|
+
model: string | undefined;
|
|
19
|
+
effort: string | undefined;
|
|
20
|
+
msgCount: number;
|
|
21
|
+
toolCallCount: number;
|
|
22
|
+
inputTokens: number;
|
|
23
|
+
outputTokens: number;
|
|
24
|
+
cacheReadTokens: number;
|
|
25
|
+
cacheWriteTokens: number;
|
|
26
|
+
status: 'idle' | 'running' | 'none';
|
|
27
|
+
eventCount: number | undefined;
|
|
28
|
+
parentSession: string | undefined;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Open the `/session` info panel; resolves when the user closes it. Focus
|
|
32
|
+
* returns to `restoreFocus` on close — it must re-focus the CURRENT editor
|
|
33
|
+
* instance, which may have been rebuilt under a theme hot-swap while the
|
|
34
|
+
* panel was open (pi-tui's hide would otherwise restore focus to the stale
|
|
35
|
+
* pre-overlay editor and swallow subsequent input).
|
|
36
|
+
*/
|
|
37
|
+
export declare function showSessionInfo(tui: TUI, theme: TuiTheme, data: SessionPanelData, restoreFocus: () => void): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* The session's "first sentence": the first direct human prompt, falling
|
|
40
|
+
* back to the first non-injected user-role text (goal/cron/recall prompts),
|
|
41
|
+
* then the first assistant message. Synthetic context injects (workspace
|
|
42
|
+
* instructions, runtime reminders) are skipped entirely — they precede the
|
|
43
|
+
* first real prompt and read as noise.
|
|
44
|
+
*/
|
|
45
|
+
export declare function previewOfEvents(events: readonly SessionEvent[]): string | undefined;
|
|
46
|
+
/** Collapse control chars/whitespace and clip a raw message into a one-line preview. */
|
|
47
|
+
export declare function normalizePreview(text: string, maxChars?: number): string;
|
|
48
|
+
/**
|
|
49
|
+
* Validate one persisted session's log without publishing it — the /resume
|
|
50
|
+
* pre-check: a corrupt target must be rejected BEFORE the current live agent
|
|
51
|
+
* is torn down. Throws when persistence is missing or the log fails to load.
|
|
52
|
+
*/
|
|
53
|
+
export declare function inspectPersistedSession(ctx: Context, id: SessionId): Promise<{
|
|
54
|
+
meta: SessionHeader;
|
|
55
|
+
events: readonly SessionEvent[];
|
|
56
|
+
}>;
|
|
57
|
+
/** Outcome of the `/resume` picker, so the caller can phrase its reply. */
|
|
58
|
+
export type PickSessionResult = {
|
|
59
|
+
kind: 'empty';
|
|
60
|
+
} | {
|
|
61
|
+
kind: 'cancelled';
|
|
62
|
+
} | {
|
|
63
|
+
kind: 'picked';
|
|
64
|
+
id: SessionId;
|
|
65
|
+
header: SessionHeader;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Open the persisted-session picker. Resolves with the picked session,
|
|
69
|
+
* `cancelled` when dismissed, or `empty` when no other session exists.
|
|
70
|
+
* Throws when the profile has no persistence backend. Focus returns to
|
|
71
|
+
* `restoreFocus` on close.
|
|
72
|
+
*/
|
|
73
|
+
export declare function pickPersistedSession(ctx: Context, tui: TUI, theme: TuiTheme, excludeSessionId: string | undefined, restoreFocus: () => void): Promise<PickSessionResult>;
|