dsh-connect 0.2.0 → 0.5.2
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 +197 -0
- package/lib/binding.d.ts +51 -0
- package/lib/binding.d.ts.map +1 -1
- package/lib/binding.js +71 -3
- package/lib/binding.js.map +1 -1
- package/lib/commands.d.ts +18 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +66 -25
- package/lib/commands.js.map +1 -1
- package/lib/i18n.d.ts +233 -0
- package/lib/i18n.d.ts.map +1 -0
- package/lib/i18n.js +469 -0
- package/lib/i18n.js.map +1 -0
- package/lib/index.d.ts +39 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +14 -2
- 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 +201 -1
- package/lib/runner.d.ts.map +1 -1
- package/lib/runner.js +1506 -170
- 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 +38 -0
- package/lib/types.d.ts.map +1 -1
- package/package.json +58 -49
- package/LICENSE +0 -21
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,CAAC,MAAM,0BAA0B,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,CAAC,MAAM,0BAA0B,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,oBAAoB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEjJ,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAgBrC,qDAAqD;AACrD,MAAM,CAAC,MAAM,IAAI,GAAG,SAAS,CAAC;AAE9B,6EAA6E;AAC7E,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,mBAAmB,CAAC,CAAC;AAElE,wEAAwE;AACxE,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,qFAAqF;IACrF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,yEAAyE;IACzE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,oEAAoE;IACpE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC/B,uFAAuF;IACvF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAClE,4DAA4D;IAC5D,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,qDAAqD;IACrD,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC/B,iDAAiD;IACjD,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC/B,qDAAqD;IACrD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,6FAA6F;IAC7F,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC7B,+EAA+E;IAC/E,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChF,4GAA4G;IAC5G,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;CAC9B,CAAC,CAAC;AAQH,qFAAqF;AACrF,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,SAAwB,EAAE;IAC5D,KAAK,IAAI,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive user-choices and permission approvals bridged into the chat
|
|
3
|
+
* channel (Feishu first).
|
|
4
|
+
*
|
|
5
|
+
* DSH's host api-proxy owns the single `userQuestions` provider and the
|
|
6
|
+
* `approval/request` waterfall, so a channel plugin cannot register a second
|
|
7
|
+
* answerer. Instead this bridge acts as an in-process client of the host's
|
|
8
|
+
* `ctx.apiProxy`: it subscribes to the same mux stream the Web GUI uses,
|
|
9
|
+
* watches for `question/requested` and `approval/requested` frames on
|
|
10
|
+
* connect-bound sessions, renders them as chat cards with buttons, and feeds
|
|
11
|
+
* the user's answer back through `apiProxy.respond` — the exact same path a
|
|
12
|
+
* Web client uses. The Web GUI stays fully functional; whoever answers first
|
|
13
|
+
* wins.
|
|
14
|
+
*
|
|
15
|
+
* Everything is best-effort: when the host api-proxy is absent (e.g. a
|
|
16
|
+
* headless host), the bridge is a no-op and the current behavior (question
|
|
17
|
+
* pending until a Web client answers) is unchanged.
|
|
18
|
+
* @module dsh-connect/interaction
|
|
19
|
+
*/
|
|
20
|
+
import type { Context } from "@deepseek-ai/cordis";
|
|
21
|
+
import type { ChannelAdapter } from "./types.js";
|
|
22
|
+
import type { BindingStore } from "./binding.js";
|
|
23
|
+
import type { ResolvedConnectConfig } from "./runner.js";
|
|
24
|
+
/** One question from a `question/requested` mux frame (loosely typed). */
|
|
25
|
+
export interface AskQuestionLike {
|
|
26
|
+
id: string;
|
|
27
|
+
question: string;
|
|
28
|
+
header?: string;
|
|
29
|
+
detail?: string;
|
|
30
|
+
options?: {
|
|
31
|
+
label: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
}[];
|
|
34
|
+
multiSelect?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Decode a free-text chat reply into the answer for one question. Exact label
|
|
38
|
+
* match wins; otherwise space/comma separated numbers are mapped onto the
|
|
39
|
+
* options (multi-select accumulates them); anything else becomes free text.
|
|
40
|
+
*/
|
|
41
|
+
export declare function decodeTextAnswer(q: AskQuestionLike, text: string): {
|
|
42
|
+
selected: string[];
|
|
43
|
+
custom?: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Bridge user choices and permission approvals from DSH into the chat channel.
|
|
47
|
+
* Subscribes once to the host mux stream; frames for connect-bound sessions are
|
|
48
|
+
* rendered as interactive cards and answered via `apiProxy.respond`.
|
|
49
|
+
*/
|
|
50
|
+
export declare class InteractionBridge {
|
|
51
|
+
private readonly ctx;
|
|
52
|
+
private readonly adapters;
|
|
53
|
+
private readonly bindings;
|
|
54
|
+
private readonly config;
|
|
55
|
+
private readonly pending;
|
|
56
|
+
private started;
|
|
57
|
+
private apiProxy?;
|
|
58
|
+
private controller?;
|
|
59
|
+
constructor(ctx: Context, adapters: ReadonlyMap<string, ChannelAdapter>, bindings: BindingStore, config: ResolvedConnectConfig);
|
|
60
|
+
/** Open the mux subscription (idempotent). No-op when the host api-proxy is absent. */
|
|
61
|
+
start(): void;
|
|
62
|
+
/** Whether a question/approval is waiting on an answer in this chat. */
|
|
63
|
+
pendingFor(chatKey: string): boolean;
|
|
64
|
+
/** Deliver a plain-text chat reply as the answer to the pending question. */
|
|
65
|
+
answerText(chatKey: string, text: string): boolean;
|
|
66
|
+
private run;
|
|
67
|
+
private onFrame;
|
|
68
|
+
/** Every connect-bound chat that currently uses this session (active or mirrored). */
|
|
69
|
+
private targetsFor;
|
|
70
|
+
private presentQuestion;
|
|
71
|
+
private presentApproval;
|
|
72
|
+
/** Advance to the next unanswered question, or settle once all are answered. */
|
|
73
|
+
private stepQuestion;
|
|
74
|
+
private presentQuestionButtons;
|
|
75
|
+
private presentQuestionText;
|
|
76
|
+
private presentApprovalLoop;
|
|
77
|
+
/**
|
|
78
|
+
* Keep one interactive card alive until the user answers (or the ask is
|
|
79
|
+
* cancelled). The channel's choice prompt expires after its own idle
|
|
80
|
+
* timeout; on expiry the same card is re-presented in place so the choice
|
|
81
|
+
* stays clickable for as long as the agent waits. Resolves `"answered"`
|
|
82
|
+
* when `onChoice` accepted a choice, `"stopped"` otherwise.
|
|
83
|
+
*/
|
|
84
|
+
private presentLoop;
|
|
85
|
+
private questionPromptText;
|
|
86
|
+
private recordAnswer;
|
|
87
|
+
/** All questions answered — deliver the answers through the host respond path. */
|
|
88
|
+
private settleQuestion;
|
|
89
|
+
private respondThen;
|
|
90
|
+
private respond;
|
|
91
|
+
/** Stop presenting and drop the interaction (answered, cancelled, or the turn ended). */
|
|
92
|
+
private settle;
|
|
93
|
+
private outbound;
|
|
94
|
+
private log;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=interaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interaction.d.ts","sourceRoot":"","sources":["../src/interaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAA8C,MAAM,YAAY,CAAC;AAC7F,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,cAAc,CAAC;AAE9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA2CD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAiB1G;AAYD;;;;GAIG;AACH,qBAAa,iBAAiB;IAO1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IATzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IACjE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,CAAe;IAChC,OAAO,CAAC,UAAU,CAAC,CAAkB;gBAGlB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,EAC7C,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,qBAAqB;IAKhD,uFAAuF;IACvF,KAAK,IAAI,IAAI;IAUb,wEAAwE;IACxE,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIpC,6EAA6E;IAC7E,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;YAWpC,GAAG;IAejB,OAAO,CAAC,OAAO;IA4Cf,sFAAsF;IACtF,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,eAAe;IA6BvB,OAAO,CAAC,eAAe;IA6BvB,gFAAgF;IAChF,OAAO,CAAC,YAAY;YAoBN,sBAAsB;YAuBtB,mBAAmB;YAYnB,mBAAmB;IAuBjC;;;;;;OAMG;YACW,WAAW;IAsBzB,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,YAAY;IAMpB,kFAAkF;YACpE,cAAc;YAsBd,WAAW;YAIX,OAAO;IAerB,yFAAyF;IACzF,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,GAAG;CAGZ"}
|
|
@@ -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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"}
|