dsh-connect 0.5.0 → 0.5.3
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 +184 -8
- package/lib/binding.d.ts +53 -0
- package/lib/binding.d.ts.map +1 -1
- package/lib/binding.js +72 -3
- package/lib/binding.js.map +1 -1
- package/lib/commands.d.ts +14 -0
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +40 -0
- package/lib/commands.js.map +1 -1
- package/lib/i18n.d.ts +90 -0
- package/lib/i18n.d.ts.map +1 -1
- package/lib/i18n.js +210 -4
- package/lib/i18n.js.map +1 -1
- package/lib/index.d.ts +16 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +8 -1
- package/lib/index.js.map +1 -1
- package/lib/interaction.d.ts +96 -0
- package/lib/interaction.d.ts.map +1 -0
- package/lib/interaction.js +389 -0
- package/lib/interaction.js.map +1 -0
- package/lib/runner.d.ts +181 -2
- package/lib/runner.d.ts.map +1 -1
- package/lib/runner.js +1169 -62
- package/lib/runner.js.map +1 -1
- package/lib/service.d.ts +19 -0
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +128 -2
- package/lib/service.js.map +1 -1
- package/lib/types.d.ts +26 -0
- package/lib/types.d.ts.map +1 -1
- package/package.json +58 -58
- package/LICENSE +0 -21
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { messages } from "./i18n.js";
|
|
2
|
+
function delay(ms) {
|
|
3
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Decode a free-text chat reply into the answer for one question. Exact label
|
|
7
|
+
* match wins; otherwise space/comma separated numbers are mapped onto the
|
|
8
|
+
* options (multi-select accumulates them); anything else becomes free text.
|
|
9
|
+
*/
|
|
10
|
+
export function decodeTextAnswer(q, text) {
|
|
11
|
+
const opts = q.options ?? [];
|
|
12
|
+
const trimmed = text.trim();
|
|
13
|
+
if (opts.length === 0)
|
|
14
|
+
return { selected: [], custom: trimmed };
|
|
15
|
+
const exact = opts.findIndex((o) => o.label === trimmed);
|
|
16
|
+
if (exact !== -1)
|
|
17
|
+
return { selected: [opts[exact].label] };
|
|
18
|
+
const parts = trimmed
|
|
19
|
+
.split(/[,,、;;\s]+/)
|
|
20
|
+
.map((s) => s.trim())
|
|
21
|
+
.filter((s) => s !== "");
|
|
22
|
+
const labels = [...new Set(parts.filter((p) => opts.some((o) => o.label === p)))];
|
|
23
|
+
const nums = parts.map((p) => Number(p)).filter((n) => Number.isInteger(n) && n >= 1 && n <= opts.length);
|
|
24
|
+
const picked = q.multiSelect
|
|
25
|
+
? [...new Set([...labels, ...nums.map((n) => opts[n - 1].label)])]
|
|
26
|
+
: [...new Set([...labels, ...(nums.length > 0 ? [opts[nums[0] - 1].label] : [])])].slice(0, 1);
|
|
27
|
+
if (picked.length > 0)
|
|
28
|
+
return { selected: picked };
|
|
29
|
+
return { selected: [], custom: trimmed };
|
|
30
|
+
}
|
|
31
|
+
/** Decode a button choice (`q:<questionId>:<optionIndex>`) back into an answer. */
|
|
32
|
+
function decodeChoice(q, choice) {
|
|
33
|
+
const prefix = `q:${q.id}:`;
|
|
34
|
+
if (!choice.startsWith(prefix))
|
|
35
|
+
return undefined;
|
|
36
|
+
const idx = Number(choice.slice(prefix.length));
|
|
37
|
+
const opt = q.options?.[idx];
|
|
38
|
+
if (opt === undefined)
|
|
39
|
+
return undefined;
|
|
40
|
+
return { selected: [opt.label] };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Bridge user choices and permission approvals from DSH into the chat channel.
|
|
44
|
+
* Subscribes once to the host mux stream; frames for connect-bound sessions are
|
|
45
|
+
* rendered as interactive cards and answered via `apiProxy.respond`.
|
|
46
|
+
*/
|
|
47
|
+
export class InteractionBridge {
|
|
48
|
+
ctx;
|
|
49
|
+
adapters;
|
|
50
|
+
bindings;
|
|
51
|
+
config;
|
|
52
|
+
pending = new Map();
|
|
53
|
+
started = false;
|
|
54
|
+
apiProxy;
|
|
55
|
+
controller;
|
|
56
|
+
constructor(ctx, adapters, bindings, config) {
|
|
57
|
+
this.ctx = ctx;
|
|
58
|
+
this.adapters = adapters;
|
|
59
|
+
this.bindings = bindings;
|
|
60
|
+
this.config = config;
|
|
61
|
+
this.ctx.effect(() => () => this.controller?.abort(), "connect: interaction bridge");
|
|
62
|
+
}
|
|
63
|
+
/** Open the mux subscription (idempotent). No-op when the host api-proxy is absent. */
|
|
64
|
+
start() {
|
|
65
|
+
if (this.started)
|
|
66
|
+
return;
|
|
67
|
+
const apiProxy = this.ctx.get("apiProxy");
|
|
68
|
+
if (apiProxy?.events?.mux === undefined || apiProxy.respond === undefined)
|
|
69
|
+
return;
|
|
70
|
+
this.started = true;
|
|
71
|
+
this.apiProxy = apiProxy;
|
|
72
|
+
this.controller = new AbortController();
|
|
73
|
+
void this.run(this.controller.signal);
|
|
74
|
+
}
|
|
75
|
+
/** Whether a question/approval is waiting on an answer in this chat. */
|
|
76
|
+
pendingFor(chatKey) {
|
|
77
|
+
return this.pending.has(chatKey);
|
|
78
|
+
}
|
|
79
|
+
/** Deliver a plain-text chat reply as the answer to the pending question. */
|
|
80
|
+
answerText(chatKey, text) {
|
|
81
|
+
const p = this.pending.get(chatKey);
|
|
82
|
+
if (p === undefined || p.kind !== "question")
|
|
83
|
+
return false;
|
|
84
|
+
const q = p.questions[p.current];
|
|
85
|
+
if (q === undefined)
|
|
86
|
+
return false;
|
|
87
|
+
const answer = decodeTextAnswer(q, text);
|
|
88
|
+
if (answer.selected.length === 0 && (answer.custom === undefined || answer.custom.trim() === ""))
|
|
89
|
+
return false;
|
|
90
|
+
this.recordAnswer(p, q.id, answer);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
async run(signal) {
|
|
94
|
+
const stream = this.apiProxy.events.mux({ rpcId: "connect-interaction", payload: {} }, signal);
|
|
95
|
+
try {
|
|
96
|
+
for await (const { rpcId, payload } of stream) {
|
|
97
|
+
try {
|
|
98
|
+
this.onFrame(rpcId, payload);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
this.log(`connect: interaction frame handler error: ${String(error)}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
this.log(`connect: interaction mux stream closed: ${String(error)}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
onFrame(rpcId, payload) {
|
|
110
|
+
switch (payload.type) {
|
|
111
|
+
case "question/requested": {
|
|
112
|
+
const sessionId = String(payload.sessionId ?? "");
|
|
113
|
+
const questions = Array.isArray(payload.questions) ? payload.questions : [];
|
|
114
|
+
if (sessionId === "" || questions.length === 0)
|
|
115
|
+
return;
|
|
116
|
+
for (const target of this.targetsFor(sessionId)) {
|
|
117
|
+
this.presentQuestion(target, rpcId, sessionId, questions);
|
|
118
|
+
}
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
case "approval/requested": {
|
|
122
|
+
const sessionId = String(payload.sessionId ?? "");
|
|
123
|
+
const approvalId = String(payload.approvalId ?? "");
|
|
124
|
+
if (sessionId === "" || approvalId === "")
|
|
125
|
+
return;
|
|
126
|
+
const toolName = String(payload.toolName ?? "?");
|
|
127
|
+
const reason = typeof payload.reason === "string" ? payload.reason : undefined;
|
|
128
|
+
for (const target of this.targetsFor(sessionId)) {
|
|
129
|
+
this.presentApproval(target, rpcId, sessionId, approvalId, toolName, reason);
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case "question/resolved": {
|
|
134
|
+
// Someone (Web GUI or this bridge) answered/cancelled the ask.
|
|
135
|
+
const questionRpcId = String(payload.questionRpcId ?? "");
|
|
136
|
+
for (const p of [...this.pending.values()]) {
|
|
137
|
+
if (p.kind === "question" && p.rpcId === questionRpcId)
|
|
138
|
+
this.settle(p);
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
case "session/event": {
|
|
143
|
+
const event = payload.event;
|
|
144
|
+
if (event?.type !== "turn/end")
|
|
145
|
+
return;
|
|
146
|
+
const sessionId = String(payload.sessionId ?? "");
|
|
147
|
+
for (const p of [...this.pending.values()]) {
|
|
148
|
+
if (p.sessionId === sessionId)
|
|
149
|
+
this.settle(p);
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
default:
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Every connect-bound chat that currently uses this session (active or mirrored). */
|
|
158
|
+
targetsFor(sessionId) {
|
|
159
|
+
const out = [];
|
|
160
|
+
for (const binding of this.bindings.list()) {
|
|
161
|
+
if (binding.sessionId !== sessionId && binding.webMirrorSessionId !== sessionId)
|
|
162
|
+
continue;
|
|
163
|
+
const adapter = this.adapters.get(binding.channel);
|
|
164
|
+
if (adapter === undefined)
|
|
165
|
+
continue;
|
|
166
|
+
out.push({ binding, adapter });
|
|
167
|
+
}
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
presentQuestion(target, rpcId, sessionId, questions) {
|
|
171
|
+
// One pending ask per session — a replayed frame after the mux reopens
|
|
172
|
+
// must not stack duplicate cards.
|
|
173
|
+
for (const p of this.pending.values()) {
|
|
174
|
+
if (p.sessionId === sessionId)
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const interaction = {
|
|
178
|
+
kind: "question",
|
|
179
|
+
chatKey: target.binding.chatKey,
|
|
180
|
+
chatType: target.binding.chatType,
|
|
181
|
+
adapter: target.adapter,
|
|
182
|
+
sessionId,
|
|
183
|
+
rpcId,
|
|
184
|
+
language: target.binding.language ?? this.config.language,
|
|
185
|
+
questions,
|
|
186
|
+
answers: new Map(),
|
|
187
|
+
current: 0,
|
|
188
|
+
controller: new AbortController(),
|
|
189
|
+
settled: false,
|
|
190
|
+
};
|
|
191
|
+
this.pending.set(interaction.chatKey, interaction);
|
|
192
|
+
this.stepQuestion(interaction);
|
|
193
|
+
}
|
|
194
|
+
presentApproval(target, rpcId, sessionId, approvalId, toolName, reason) {
|
|
195
|
+
for (const p of this.pending.values()) {
|
|
196
|
+
if (p.sessionId === sessionId)
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const interaction = {
|
|
200
|
+
kind: "approval",
|
|
201
|
+
chatKey: target.binding.chatKey,
|
|
202
|
+
chatType: target.binding.chatType,
|
|
203
|
+
adapter: target.adapter,
|
|
204
|
+
sessionId,
|
|
205
|
+
rpcId,
|
|
206
|
+
approvalId,
|
|
207
|
+
toolName,
|
|
208
|
+
...(reason === undefined ? {} : { reason }),
|
|
209
|
+
language: target.binding.language ?? this.config.language,
|
|
210
|
+
controller: new AbortController(),
|
|
211
|
+
settled: false,
|
|
212
|
+
};
|
|
213
|
+
this.pending.set(interaction.chatKey, interaction);
|
|
214
|
+
void this.presentApprovalLoop(interaction);
|
|
215
|
+
}
|
|
216
|
+
/** Advance to the next unanswered question, or settle once all are answered. */
|
|
217
|
+
stepQuestion(interaction) {
|
|
218
|
+
while (interaction.current < interaction.questions.length &&
|
|
219
|
+
interaction.answers.has(interaction.questions[interaction.current].id)) {
|
|
220
|
+
interaction.current += 1;
|
|
221
|
+
}
|
|
222
|
+
if (interaction.current >= interaction.questions.length) {
|
|
223
|
+
void this.settleQuestion(interaction);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const q = interaction.questions[interaction.current];
|
|
227
|
+
const hasOptions = Array.isArray(q.options) && q.options.length > 0;
|
|
228
|
+
if (hasOptions) {
|
|
229
|
+
void this.presentQuestionButtons(interaction, q);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
void this.presentQuestionText(interaction, q);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async presentQuestionButtons(interaction, q) {
|
|
236
|
+
const t = messages(interaction.language);
|
|
237
|
+
const options = (q.options ?? []).map((o, i) => ({
|
|
238
|
+
id: `q:${q.id}:${i}`,
|
|
239
|
+
label: o.label,
|
|
240
|
+
}));
|
|
241
|
+
const prompt = {
|
|
242
|
+
title: t.questionCardTitle,
|
|
243
|
+
description: this.questionPromptText(interaction, q),
|
|
244
|
+
options,
|
|
245
|
+
footer: q.multiSelect === true ? `${t.questionCardHint}\n${t.questionMultiHint}` : t.questionCardHint,
|
|
246
|
+
};
|
|
247
|
+
// One answered question steps the interaction to the next one; settling is
|
|
248
|
+
// the flow's job (stepQuestion → settleQuestion), not this loop's.
|
|
249
|
+
await this.presentLoop(interaction, prompt, (choice) => {
|
|
250
|
+
if (choice === undefined)
|
|
251
|
+
return undefined;
|
|
252
|
+
const answer = decodeChoice(q, choice);
|
|
253
|
+
if (answer === undefined)
|
|
254
|
+
return undefined;
|
|
255
|
+
this.recordAnswer(interaction, q.id, answer);
|
|
256
|
+
return "answered";
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
async presentQuestionText(interaction, q) {
|
|
260
|
+
const t = messages(interaction.language);
|
|
261
|
+
const target = this.outbound(interaction);
|
|
262
|
+
await interaction.adapter.sendText(target, t.questionTextHint(q.question)).catch(() => undefined);
|
|
263
|
+
while (!interaction.controller.signal.aborted && !interaction.settled) {
|
|
264
|
+
if (interaction.answers.has(q.id))
|
|
265
|
+
return;
|
|
266
|
+
await delay(60_000);
|
|
267
|
+
if (interaction.controller.signal.aborted || interaction.settled || interaction.answers.has(q.id))
|
|
268
|
+
return;
|
|
269
|
+
await interaction.adapter.sendText(target, t.questionWaiting(q.question)).catch(() => undefined);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async presentApprovalLoop(interaction) {
|
|
273
|
+
const t = messages(interaction.language);
|
|
274
|
+
const prompt = {
|
|
275
|
+
title: t.approvalCardTitle,
|
|
276
|
+
description: t.approvalAsk(interaction.toolName, interaction.reason),
|
|
277
|
+
options: [
|
|
278
|
+
{ id: "approval:allow", label: t.approveLabel },
|
|
279
|
+
{ id: "approval:reject", label: t.rejectLabel },
|
|
280
|
+
],
|
|
281
|
+
};
|
|
282
|
+
const result = await this.presentLoop(interaction, prompt, (choice) => {
|
|
283
|
+
if (choice !== "approval:allow" && choice !== "approval:reject")
|
|
284
|
+
return undefined;
|
|
285
|
+
const outcome = choice === "approval:allow" ? "allowed-once" : "rejected";
|
|
286
|
+
void this.respondThen(interaction, {
|
|
287
|
+
sessionId: interaction.sessionId,
|
|
288
|
+
approvalId: interaction.approvalId,
|
|
289
|
+
outcome,
|
|
290
|
+
});
|
|
291
|
+
return "answered";
|
|
292
|
+
});
|
|
293
|
+
if (result === "answered")
|
|
294
|
+
this.settle(interaction);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Keep one interactive card alive until the user answers (or the ask is
|
|
298
|
+
* cancelled). The channel's choice prompt expires after its own idle
|
|
299
|
+
* timeout; on expiry the same card is re-presented in place so the choice
|
|
300
|
+
* stays clickable for as long as the agent waits. Resolves `"answered"`
|
|
301
|
+
* when `onChoice` accepted a choice, `"stopped"` otherwise.
|
|
302
|
+
*/
|
|
303
|
+
async presentLoop(interaction, prompt, onChoice) {
|
|
304
|
+
while (!interaction.controller.signal.aborted && !interaction.settled) {
|
|
305
|
+
try {
|
|
306
|
+
const { choice, messageId } = await interaction.adapter.promptChoice(this.outbound(interaction), prompt, interaction.messageId);
|
|
307
|
+
interaction.messageId = messageId;
|
|
308
|
+
if (onChoice(choice) === "answered")
|
|
309
|
+
return "answered";
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return "stopped";
|
|
313
|
+
}
|
|
314
|
+
await delay(1200);
|
|
315
|
+
}
|
|
316
|
+
return "stopped";
|
|
317
|
+
}
|
|
318
|
+
questionPromptText(interaction, q) {
|
|
319
|
+
const t = messages(interaction.language);
|
|
320
|
+
const total = interaction.questions.length;
|
|
321
|
+
const prefix = total > 1 ? `${t.questionStep(interaction.current + 1, total)}\n` : "";
|
|
322
|
+
const header = q.header === undefined || q.header === "" ? "" : `**${q.header}**\n`;
|
|
323
|
+
const detail = q.detail === undefined || q.detail === "" ? "" : `\n${q.detail}`;
|
|
324
|
+
const multi = q.multiSelect === true ? `\n${t.questionMultiHint}` : "";
|
|
325
|
+
return `${prefix}${header}${q.question}${detail}${multi}`;
|
|
326
|
+
}
|
|
327
|
+
recordAnswer(interaction, qid, answer) {
|
|
328
|
+
if (interaction.answers.has(qid))
|
|
329
|
+
return;
|
|
330
|
+
interaction.answers.set(qid, answer);
|
|
331
|
+
this.stepQuestion(interaction);
|
|
332
|
+
}
|
|
333
|
+
/** All questions answered — deliver the answers through the host respond path. */
|
|
334
|
+
async settleQuestion(interaction) {
|
|
335
|
+
if (interaction.settled)
|
|
336
|
+
return;
|
|
337
|
+
interaction.settled = true;
|
|
338
|
+
const answers = interaction.questions.map((q) => {
|
|
339
|
+
const a = interaction.answers.get(q.id);
|
|
340
|
+
return {
|
|
341
|
+
id: q.id,
|
|
342
|
+
selected: a?.selected ?? [],
|
|
343
|
+
...(a?.custom !== undefined && a.custom.trim() !== "" ? { custom: a.custom.trim() } : {}),
|
|
344
|
+
};
|
|
345
|
+
});
|
|
346
|
+
const accepted = await this.respond(interaction.rpcId, {
|
|
347
|
+
sessionId: interaction.sessionId,
|
|
348
|
+
answer: { answers },
|
|
349
|
+
});
|
|
350
|
+
if (accepted) {
|
|
351
|
+
const t = messages(interaction.language);
|
|
352
|
+
await interaction.adapter.sendText(this.outbound(interaction), t.answerReceived).catch(() => undefined);
|
|
353
|
+
}
|
|
354
|
+
this.settle(interaction);
|
|
355
|
+
}
|
|
356
|
+
async respondThen(interaction, value) {
|
|
357
|
+
await this.respond(interaction.rpcId, value);
|
|
358
|
+
}
|
|
359
|
+
async respond(rpcId, value) {
|
|
360
|
+
if (this.apiProxy?.respond === undefined)
|
|
361
|
+
return false;
|
|
362
|
+
try {
|
|
363
|
+
const res = await this.apiProxy.respond({
|
|
364
|
+
type: "client-response",
|
|
365
|
+
rpcId,
|
|
366
|
+
result: { ok: true, value },
|
|
367
|
+
});
|
|
368
|
+
return res?.accepted === true;
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
this.log(`connect: interaction respond failed: ${String(error)}`);
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
/** Stop presenting and drop the interaction (answered, cancelled, or the turn ended). */
|
|
376
|
+
settle(interaction) {
|
|
377
|
+
if (this.pending.get(interaction.chatKey) === interaction)
|
|
378
|
+
this.pending.delete(interaction.chatKey);
|
|
379
|
+
interaction.settled = true;
|
|
380
|
+
interaction.controller.abort();
|
|
381
|
+
}
|
|
382
|
+
outbound(p) {
|
|
383
|
+
return { chatKey: p.chatKey, chatType: p.chatType };
|
|
384
|
+
}
|
|
385
|
+
log(message) {
|
|
386
|
+
this.ctx.get("logger")?.info?.(message);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
//# sourceMappingURL=interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interaction.js","sourceRoot":"","sources":["../src/interaction.ts"],"names":[],"mappings":"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"}
|
package/lib/runner.d.ts
CHANGED
|
@@ -20,6 +20,14 @@ export interface ConnectConfig {
|
|
|
20
20
|
allowUsers?: string[];
|
|
21
21
|
allowChats?: string[];
|
|
22
22
|
stateDir?: string;
|
|
23
|
+
/** Automatically create Web mirror for new sessions (default: true). */
|
|
24
|
+
autoMirror?: boolean;
|
|
25
|
+
/** Liveness heartbeat interval ms for the streaming card; 0 disables it (default: 60000). */
|
|
26
|
+
streamHeartbeatMs?: number;
|
|
27
|
+
/** Default notification level for streaming replies (default: `important`). */
|
|
28
|
+
notifyLevel?: NotifyLevel;
|
|
29
|
+
/** Proactive progress-notice interval ms: when a turn goes silent for this long, a standalone status card is sent (default: 300000 = 5 min; 0 disables). */
|
|
30
|
+
progressTimeoutMs?: number;
|
|
23
31
|
}
|
|
24
32
|
export interface ResolvedConnectConfig {
|
|
25
33
|
agentPreset?: string;
|
|
@@ -33,9 +41,61 @@ export interface ResolvedConnectConfig {
|
|
|
33
41
|
allowUsers: string[];
|
|
34
42
|
allowChats: string[];
|
|
35
43
|
stateDir?: string;
|
|
44
|
+
autoMirror: boolean;
|
|
45
|
+
streamHeartbeatMs: number;
|
|
46
|
+
notifyLevel: NotifyLevel;
|
|
47
|
+
progressTimeoutMs: number;
|
|
36
48
|
}
|
|
37
49
|
export declare function resolveConnectConfig(config: ConnectConfig): ResolvedConnectConfig;
|
|
50
|
+
/** Per-turn streaming assembly state mutated by {@link applyStreamChunk}. */
|
|
51
|
+
export interface StreamState {
|
|
52
|
+
chunks: {
|
|
53
|
+
push(text: string): void;
|
|
54
|
+
};
|
|
55
|
+
lastText: string;
|
|
56
|
+
reasoning: boolean;
|
|
57
|
+
hintPushed: boolean;
|
|
58
|
+
lastIndex: number | undefined;
|
|
59
|
+
pushedAny: boolean;
|
|
60
|
+
lastPushAt: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* How much of the agent's live progress the streaming card shows.
|
|
64
|
+
* - `full` — everything: reasoning text, tool calls, heartbeats, answer.
|
|
65
|
+
* - `important` — key milestones only: thinking hint, tool calls, heartbeats, answer (no reasoning text).
|
|
66
|
+
* - `result` — only the final answer.
|
|
67
|
+
*/
|
|
68
|
+
export type NotifyLevel = "full" | "important" | "result";
|
|
69
|
+
/** One assistant chunk event of interest to the streaming bridge. */
|
|
70
|
+
export interface StreamChunkLike {
|
|
71
|
+
type: string;
|
|
72
|
+
index?: number;
|
|
73
|
+
text?: string;
|
|
74
|
+
block?: {
|
|
75
|
+
type?: string;
|
|
76
|
+
text?: string;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export declare function applyStreamChunk(state: StreamState, thinkingHint: string, chunk: StreamChunkLike, level?: NotifyLevel): void;
|
|
80
|
+
/**
|
|
81
|
+
* Push a localized tool-call status line into the streaming queue so long
|
|
82
|
+
* tool-execution stretches stay visibly alive (the Web GUI shows tool calls;
|
|
83
|
+
* the chat card should too). Ends the reasoning phase and drops the block
|
|
84
|
+
* index so the next content block gets its own separator instead of stacking
|
|
85
|
+
* one on top of the tool line's own blank lines.
|
|
86
|
+
* @param state - the turn's mutable assembly state.
|
|
87
|
+
* @param label - the localized status line, e.g. "🔧 调用工具 `pwsh` — …".
|
|
88
|
+
*/
|
|
89
|
+
export declare function applyToolCall(state: StreamState, label: string): void;
|
|
90
|
+
/** Pull a short human summary out of a tool call's `arguments` JSON (whitespace folded to one line). */
|
|
91
|
+
export declare function toolCallSummary(argumentsJson: unknown): string | undefined;
|
|
92
|
+
/** Pull the first question's text out of an `ask_user_question` arguments JSON (whitespace folded to one line). */
|
|
93
|
+
export declare function questionTextOf(argumentsJson: unknown): string;
|
|
38
94
|
export declare function summarizeTurn(events: readonly SessionEvent[], firstSeq: number): TurnOutcome;
|
|
95
|
+
/** Error category used to pick actionable advice for the user. */
|
|
96
|
+
export type ErrorCategory = "permission" | "network" | "model" | "generic";
|
|
97
|
+
/** Classify an error message into an advice bucket (keyword-based, best-effort). */
|
|
98
|
+
export declare function classifyError(detail: string): ErrorCategory;
|
|
39
99
|
export declare class AgentRunner {
|
|
40
100
|
private readonly ctx;
|
|
41
101
|
private readonly config;
|
|
@@ -44,6 +104,7 @@ export declare class AgentRunner {
|
|
|
44
104
|
private readonly chatType;
|
|
45
105
|
private readonly adapter;
|
|
46
106
|
private readonly bindings;
|
|
107
|
+
private readonly adapters?;
|
|
47
108
|
private readonly queue;
|
|
48
109
|
private running;
|
|
49
110
|
private agent?;
|
|
@@ -52,8 +113,11 @@ export declare class AgentRunner {
|
|
|
52
113
|
private workDir;
|
|
53
114
|
private streamEnabled;
|
|
54
115
|
private summaryEnabled;
|
|
55
|
-
private
|
|
56
|
-
|
|
116
|
+
private language;
|
|
117
|
+
private notifyLevel;
|
|
118
|
+
private progressTimeoutMs;
|
|
119
|
+
private t;
|
|
120
|
+
constructor(ctx: Context, config: ResolvedConnectConfig, channel: string, chatKey: string, chatType: "p2p" | "group", adapter: ChannelAdapter, bindings: BindingStore, adapters?: Map<string, ChannelAdapter> | undefined);
|
|
57
121
|
private menuTitle;
|
|
58
122
|
private rootMenuSections;
|
|
59
123
|
private reasonLabel;
|
|
@@ -63,13 +127,44 @@ export declare class AgentRunner {
|
|
|
63
127
|
/** Route one live session event to the active turn's chunk queue. */
|
|
64
128
|
onSessionEvent(session: Session, event: SessionEvent): void;
|
|
65
129
|
private target;
|
|
130
|
+
/** Completion-card target: in groups, @ the requester so they notice the result. */
|
|
131
|
+
private taskTarget;
|
|
132
|
+
/** Send the one-time welcome card on a chat's first message (persisted marker). */
|
|
133
|
+
private maybeSendWelcome;
|
|
134
|
+
/** Pick the localized advice text for a failed turn. */
|
|
135
|
+
private errorAdvice;
|
|
136
|
+
/** Present a destructive-action confirmation; true only when the user confirms. */
|
|
137
|
+
private confirmAction;
|
|
66
138
|
private drain;
|
|
67
139
|
private runTurn;
|
|
68
140
|
private ensureAgent;
|
|
141
|
+
/**
|
|
142
|
+
* Attach a session to the DSH workspace matching its work directory so the
|
|
143
|
+
* Web GUI groups it under the same workspace the Feishu side uses.
|
|
144
|
+
* Best-effort: without a workspace registry this is a no-op.
|
|
145
|
+
*/
|
|
146
|
+
private attachToWorkspace;
|
|
69
147
|
private get agents();
|
|
70
148
|
private get sessions();
|
|
71
149
|
private defaultSelection;
|
|
150
|
+
/**
|
|
151
|
+
* Compose the preset-only agent setup.
|
|
152
|
+
*
|
|
153
|
+
* Deliberately does NOT install a static model selection on the agent. The
|
|
154
|
+
* DSH Web GUI switches models through the host api-proxy's session-scoped
|
|
155
|
+
* selection (`selectionFor` + `installModelSelection`), which is installed
|
|
156
|
+
* lazily when a session's model directory is loaded and wins the
|
|
157
|
+
* `agent/request` waterfall. A static selection captured here at create /
|
|
158
|
+
* resume time would take precedence over that and silently pin every request
|
|
159
|
+
* to the default model captured at composition — so a model the user picks
|
|
160
|
+
* in the Web GUI would appear to succeed (the seat and `session.models`
|
|
161
|
+
* report it) while the actual LLM requests keep using the old default.
|
|
162
|
+
* The default model still seeds the agent through `agentOptions` in
|
|
163
|
+
* `ensureAgent`, which `buildRequest` uses as its fallback route.
|
|
164
|
+
*/
|
|
72
165
|
private composeSetup;
|
|
166
|
+
/** Agents this runner has already attached a `session/event` listener to. */
|
|
167
|
+
private readonly watchedAgents;
|
|
73
168
|
private watchAgent;
|
|
74
169
|
private driveAgent;
|
|
75
170
|
/**
|
|
@@ -81,6 +176,8 @@ export declare class AgentRunner {
|
|
|
81
176
|
private buildUserContent;
|
|
82
177
|
/** Copy images into `<workDir>/.dsh-connect-images` so the agent's tools can reach them. */
|
|
83
178
|
private stageImages;
|
|
179
|
+
/** Copy non-image attachments into `<workDir>/.dsh-connect-files` so the agent's tools can reach them. */
|
|
180
|
+
private stageFiles;
|
|
84
181
|
private imageBlocks;
|
|
85
182
|
private describeImages;
|
|
86
183
|
private modelSupportsVision;
|
|
@@ -89,9 +186,22 @@ export declare class AgentRunner {
|
|
|
89
186
|
private readTodos;
|
|
90
187
|
private touchBinding;
|
|
91
188
|
private sendSummary;
|
|
189
|
+
/** Context-window usage at or above this percentage suggests compaction. */
|
|
190
|
+
private static readonly COMPACT_THRESHOLD_PCT;
|
|
191
|
+
/**
|
|
192
|
+
* Send a compact task-end card: the model used, input/output tokens, elapsed
|
|
193
|
+
* time, and whether compaction is advisable given context-window usage.
|
|
194
|
+
*/
|
|
195
|
+
private sendTurnStats;
|
|
92
196
|
private handleCommand;
|
|
93
197
|
private disposeAgent;
|
|
94
198
|
private recordSession;
|
|
199
|
+
/**
|
|
200
|
+
* Automatically create a Web mirror for the session.
|
|
201
|
+
* This enables DSH Web GUI to view and interact with the conversation
|
|
202
|
+
* without requiring manual `/mirror` command.
|
|
203
|
+
*/
|
|
204
|
+
private autoCreateWebMirror;
|
|
95
205
|
private newChat;
|
|
96
206
|
private clearChat;
|
|
97
207
|
private switchTo;
|
|
@@ -99,6 +209,8 @@ export declare class AgentRunner {
|
|
|
99
209
|
private openMenu;
|
|
100
210
|
private menuItems;
|
|
101
211
|
private showStatus;
|
|
212
|
+
/** Extract the most recent turn's completion info from session events. */
|
|
213
|
+
private getLastTurnInfo;
|
|
102
214
|
private showTasks;
|
|
103
215
|
private showSettings;
|
|
104
216
|
private modelMenuItems;
|
|
@@ -106,6 +218,22 @@ export declare class AgentRunner {
|
|
|
106
218
|
private setModel;
|
|
107
219
|
private reasoningMenuItems;
|
|
108
220
|
private setReasoning;
|
|
221
|
+
/** Switch the user-facing language for this chat, persisted in its binding. */
|
|
222
|
+
private setLanguage;
|
|
223
|
+
/**
|
|
224
|
+
* Switch the notification level for this chat (persisted in its binding and
|
|
225
|
+
* effective immediately for the next streaming reply).
|
|
226
|
+
*/
|
|
227
|
+
private setNotifyLevel;
|
|
228
|
+
/** Show the three-level notification picker (used by the `/notify` command). */
|
|
229
|
+
private openNotifyPicker;
|
|
230
|
+
/**
|
|
231
|
+
* Switch the proactive progress-notice interval for this chat (persisted in
|
|
232
|
+
* its binding and effective for the next turn; 0 disables the watchdog).
|
|
233
|
+
*/
|
|
234
|
+
private setProgressTimeout;
|
|
235
|
+
/** Show the progress-interval picker (used by the `/progress` command). */
|
|
236
|
+
private openProgressPicker;
|
|
109
237
|
private showPlugins;
|
|
110
238
|
private createWorkspace;
|
|
111
239
|
private compact;
|
|
@@ -114,5 +242,56 @@ export declare class AgentRunner {
|
|
|
114
242
|
private goalPhaseLabel;
|
|
115
243
|
private showSchedule;
|
|
116
244
|
private showAllWorkspaces;
|
|
245
|
+
/**
|
|
246
|
+
* Create or show Web mirror session for this chat.
|
|
247
|
+
* The mirror shares the same DSH session but enforces mutual exclusion:
|
|
248
|
+
* when Feishu is executing a task, Web is read-only, and vice versa.
|
|
249
|
+
*/
|
|
250
|
+
private handleMirror;
|
|
251
|
+
/**
|
|
252
|
+
* Manually release session lock.
|
|
253
|
+
*/
|
|
254
|
+
private handleUnlock;
|
|
255
|
+
/**
|
|
256
|
+
* Renew the current session lock timeout.
|
|
257
|
+
* Extends the lock by another full timeout period from now.
|
|
258
|
+
*/
|
|
259
|
+
private handleRenewLock;
|
|
260
|
+
/**
|
|
261
|
+
* Export conversation history to Markdown or PDF.
|
|
262
|
+
*/
|
|
263
|
+
private handleExport;
|
|
264
|
+
/**
|
|
265
|
+
* Generate Markdown representation of the conversation history.
|
|
266
|
+
*/
|
|
267
|
+
private generateMarkdown;
|
|
268
|
+
/**
|
|
269
|
+
* Check if the current channel has write access to the session.
|
|
270
|
+
* Returns true if allowed to send messages, false if read-only.
|
|
271
|
+
*/
|
|
272
|
+
private canWrite;
|
|
273
|
+
/**
|
|
274
|
+
* Acquire session lock for the given channel.
|
|
275
|
+
* Returns true if lock acquired, false if already locked by another channel.
|
|
276
|
+
*/
|
|
277
|
+
private acquireLock;
|
|
278
|
+
/**
|
|
279
|
+
* Queue a message for later execution when lock is released.
|
|
280
|
+
* Returns the position in queue.
|
|
281
|
+
*/
|
|
282
|
+
private queueMessage;
|
|
283
|
+
/**
|
|
284
|
+
* Process all queued messages after lock release.
|
|
285
|
+
* Re-enqueues them into the runner's message queue for actual execution.
|
|
286
|
+
*/
|
|
287
|
+
private processQueuedMessages;
|
|
288
|
+
/** Release session lock. */
|
|
289
|
+
private releaseLock;
|
|
290
|
+
/** Check if lock has timed out. */
|
|
291
|
+
private isLockTimedOut;
|
|
292
|
+
/** Check and release timed-out locks. */
|
|
293
|
+
private checkAndReleaseTimeoutLock;
|
|
294
|
+
/** Release a timed-out lock and notify. */
|
|
295
|
+
private releaseTimeoutLock;
|
|
117
296
|
}
|
|
118
297
|
//# sourceMappingURL=runner.d.ts.map
|