dsh-remote-window 0.0.0-stage → 0.1.0-alpha.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/LICENSE +24 -0
- package/README-zh.md +288 -0
- package/README.md +331 -2
- package/assets/official-ui/NOTICE.md +25 -0
- package/assets/official-ui/approval-client.js +367 -0
- package/assets/official-ui/chat-client.js +13343 -0
- package/assets/official-ui/conversation-client.js +20263 -0
- package/assets/official-ui/model-client.js +1931 -0
- package/assets/official-ui/tool-client.js +4633 -0
- package/assets/official-ui/trajectory-client.js +8257 -0
- package/assets/server-plugin/checksums.json +3 -0
- package/assets/server-plugin/dsh-remote-window-server-0.1.0-alpha.3.tgz +0 -0
- package/cordis.patch.yml +28 -0
- package/lib/client.js +13003 -0
- package/lib/client.js.map +1 -0
- package/lib/connection.js +242 -0
- package/lib/index.js +10974 -0
- package/lib/protocol.js +132 -0
- package/lib/routing-CQbG6gEF.js +473 -0
- package/lib/routing-qoFLGH4r.js +473 -0
- package/lib/rsession.js +250 -0
- package/lib/session-persistence.js +1 -0
- package/package.json +176 -3
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Vendored official DSH Conversation/Chat client bundles
|
|
2
|
+
|
|
3
|
+
Source: `@deepseek-ai/dsh-client-ui-conversation@0.2.1-rc.3` and
|
|
4
|
+
`@deepseek-ai/dsh-client-ui-chat@0.2.1-rc.3` (DSH tag `dsh-v0.2.1-rc.3`,
|
|
5
|
+
commit `1f81c047fc`).
|
|
6
|
+
|
|
7
|
+
The files are the official package `lib/client.js` builds with only the outer
|
|
8
|
+
module wrapper changed:
|
|
9
|
+
|
|
10
|
+
- the wrapper assigns the CJS factory to `window.__DSH_OFFICIAL_UI_LOAD__`
|
|
11
|
+
(`conversation-client.js`) or `window.__DSH_OFFICIAL_CHAT_LOAD__`
|
|
12
|
+
(`chat-client.js`) instead of calling `window.__ModuleLoader__.load`;
|
|
13
|
+
- the returned exports additionally expose the components the remote adapter
|
|
14
|
+
mounts: `InputBar`, `SessionInputShell`, `ConversationSessionHeader`,
|
|
15
|
+
`conversationCss`; `UserContent`, `AssistantMarkdown`,
|
|
16
|
+
`UserMessageNodeView`, `MessageIconActions`, `ReasoningRow`.
|
|
17
|
+
|
|
18
|
+
No component code, CSS or behavior was rewritten. The browser adapter in
|
|
19
|
+
`src/client/official-ui-runtime.ts` evaluates these factories with the page's
|
|
20
|
+
platform `require` table. The readable CSS copy used by the adapter is generated
|
|
21
|
+
by `scripts/vendor-official-ui.mjs` from the same tag.
|
|
22
|
+
|
|
23
|
+
The approval panel is the official `@deepseek-ai/dsh-client-ui-approval@0.2.1-rc.3`
|
|
24
|
+
`lib/client.js`, with the same outer-wrapper patch (`approval-client.js`)
|
|
25
|
+
exporting `ApprovalPanel`. The bundle injects its own official CSS.
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
window.__DSH_OFFICIAL_APPROVAL_LOAD__ = ({
|
|
2
|
+
id: "@deepseek-ai/dsh-client-ui-approval",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
|
+
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-approval/src/client/ApprovalPanel.module.css.mjs
|
|
11
|
+
const css = ".mna1RW_root{padding:8px calc(var(--dsh-composer-side-clearance) + 16px) 12px;flex-direction:column;align-items:center;display:flex}.mna1RW_card{width:100%;max-width:var(--dsh-chat-content-width);border:1px solid var(--dsw-alias-state-warn-secondary);border-radius:var(--dsw-radius-xl);background:var(--dsw-specific-input-major);box-shadow:var(--dsw-shadow-lv2);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);overflow:hidden}.mna1RW_strip{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-primary);align-items:center;gap:8px;padding:10px 16px;font-size:13px;line-height:18px;display:flex}.mna1RW_body{box-sizing:border-box;max-height:var(--dsh-composer-text-max-height);flex-direction:column;gap:6px;padding:12px 16px 0;display:flex;overflow-y:auto}.mna1RW_headline{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:500;line-height:24px}.mna1RW_command{color:var(--dsw-alias-label-tertiary);font-family:var(--ds-font-family-code);word-break:break-all;font-size:13px;line-height:20px}.mna1RW_actionRow{justify-content:flex-end;gap:8px;padding:14px 16px;display:flex}.mna1RW_reject:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);border-color:#0000}";
|
|
12
|
+
const tagId = "@deepseek-ai/dsh-client-ui-approval/ApprovalPanel.module.css";
|
|
13
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
14
|
+
const tag = document.createElement("style");
|
|
15
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-approval";
|
|
16
|
+
tag.dataset.pluginCss = tagId;
|
|
17
|
+
tag.textContent = css;
|
|
18
|
+
document.head.appendChild(tag);
|
|
19
|
+
}
|
|
20
|
+
var ApprovalPanel_module_css_default = {
|
|
21
|
+
"actionRow": "mna1RW_actionRow",
|
|
22
|
+
"body": "mna1RW_body",
|
|
23
|
+
"card": "mna1RW_card",
|
|
24
|
+
"command": "mna1RW_command",
|
|
25
|
+
"headline": "mna1RW_headline",
|
|
26
|
+
"reject": "mna1RW_reject",
|
|
27
|
+
"root": "mna1RW_root",
|
|
28
|
+
"strip": "mna1RW_strip"
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region lib/types/client/ApprovalPanel.js
|
|
32
|
+
/** Composer takeover for one pending approval waterfall. */
|
|
33
|
+
/**
|
|
34
|
+
* Render one pending approval and its optional Tool-owned detail.
|
|
35
|
+
* @param props - selector-matched request and standard Slot props.
|
|
36
|
+
* @returns The approval composer takeover.
|
|
37
|
+
*/
|
|
38
|
+
function ApprovalPanel(props) {
|
|
39
|
+
const approval = props.matched;
|
|
40
|
+
const detail = approval.callId === void 0 ? null : props.renderSlot("conversation.approval.detail", { callId: approval.callId });
|
|
41
|
+
return (0, react_jsx_runtime.jsx)(ApprovalFlow, {
|
|
42
|
+
pending: approval,
|
|
43
|
+
reason: approval.displayReason === void 0 ? approval.reason : props.resolveReason(approval.displayReason),
|
|
44
|
+
detail,
|
|
45
|
+
t: props.t
|
|
46
|
+
}, approval.key);
|
|
47
|
+
}
|
|
48
|
+
function ApprovalFlow({ pending, reason, detail, t }) {
|
|
49
|
+
const [answered, setAnswered] = (0, react.useState)(false);
|
|
50
|
+
const waiting = (0, react.useRef)(false);
|
|
51
|
+
const active = (0, react.useRef)(true);
|
|
52
|
+
const composing = (0, react.useRef)(false);
|
|
53
|
+
const compositionEnded = (0, react.useRef)(false);
|
|
54
|
+
(0, react.useEffect)(() => {
|
|
55
|
+
active.current = true;
|
|
56
|
+
return () => {
|
|
57
|
+
active.current = false;
|
|
58
|
+
};
|
|
59
|
+
}, []);
|
|
60
|
+
const answer = (outcome) => {
|
|
61
|
+
if (waiting.current || !pending.answerable) return;
|
|
62
|
+
waiting.current = true;
|
|
63
|
+
setAnswered(true);
|
|
64
|
+
pending.answer(outcome).catch(() => {
|
|
65
|
+
if (!active.current || !pending.answerable) return;
|
|
66
|
+
waiting.current = false;
|
|
67
|
+
setAnswered(false);
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const keydown = (event) => {
|
|
71
|
+
const element = event.target;
|
|
72
|
+
if (event.defaultPrevented || !event.currentTarget.contains(document.activeElement) || element.closest("input, textarea, select, [contenteditable=\"true\"], [contenteditable=\"\"]") !== null) return;
|
|
73
|
+
if (event.key !== "Enter" && event.key !== "Escape") return;
|
|
74
|
+
if (event.key === "Enter" && element.closest("button, a[href], [role=\"button\"]") !== null) return;
|
|
75
|
+
if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) return;
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
event.stopPropagation();
|
|
78
|
+
if (event.repeat || composing.current || compositionEnded.current || event.nativeEvent.isComposing || event.keyCode === 229) return;
|
|
79
|
+
answer(event.key === "Enter" ? "allowed-once" : "rejected");
|
|
80
|
+
};
|
|
81
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
82
|
+
className: ApprovalPanel_module_css_default.root,
|
|
83
|
+
"data-approval-key": pending.key,
|
|
84
|
+
"aria-busy": answered,
|
|
85
|
+
onKeyDown: keydown,
|
|
86
|
+
onKeyUpCapture: () => {
|
|
87
|
+
compositionEnded.current = false;
|
|
88
|
+
},
|
|
89
|
+
onCompositionStartCapture: () => {
|
|
90
|
+
composing.current = true;
|
|
91
|
+
},
|
|
92
|
+
onCompositionEndCapture: () => {
|
|
93
|
+
composing.current = false;
|
|
94
|
+
compositionEnded.current = true;
|
|
95
|
+
},
|
|
96
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
97
|
+
className: ApprovalPanel_module_css_default.card,
|
|
98
|
+
children: [
|
|
99
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
100
|
+
className: ApprovalPanel_module_css_default.strip,
|
|
101
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: answered ? "ongoing" : "warning" }), t("waiting")]
|
|
102
|
+
}),
|
|
103
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
104
|
+
className: ApprovalPanel_module_css_default.body,
|
|
105
|
+
"data-approval-scroll": "",
|
|
106
|
+
tabIndex: 0,
|
|
107
|
+
role: "group",
|
|
108
|
+
"aria-label": t("detail.aria"),
|
|
109
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
110
|
+
className: ApprovalPanel_module_css_default.headline,
|
|
111
|
+
children: reason ?? t("escalation", { toolName: pending.toolName })
|
|
112
|
+
}), detail !== null && (0, react_jsx_runtime.jsx)("div", {
|
|
113
|
+
className: ApprovalPanel_module_css_default.command,
|
|
114
|
+
children: detail
|
|
115
|
+
})]
|
|
116
|
+
}),
|
|
117
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
118
|
+
className: ApprovalPanel_module_css_default.actionRow,
|
|
119
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
120
|
+
variant: "outline",
|
|
121
|
+
className: ApprovalPanel_module_css_default.reject,
|
|
122
|
+
disabled: answered,
|
|
123
|
+
onClick: () => {
|
|
124
|
+
answer("rejected");
|
|
125
|
+
},
|
|
126
|
+
children: t("reject")
|
|
127
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
128
|
+
variant: "primary",
|
|
129
|
+
disabled: answered,
|
|
130
|
+
onClick: () => {
|
|
131
|
+
answer("allowed-once");
|
|
132
|
+
},
|
|
133
|
+
children: t("allowOnce")
|
|
134
|
+
})]
|
|
135
|
+
})
|
|
136
|
+
]
|
|
137
|
+
})
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region lib/types/client/contract/slots.js
|
|
142
|
+
function settlePendingComposer(settle, failureMessage) {
|
|
143
|
+
try {
|
|
144
|
+
settle();
|
|
145
|
+
return Promise.resolve();
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return Promise.reject(error instanceof Error ? error : new Error(failureMessage, { cause: error }));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
let nextApprovalKey = 0;
|
|
151
|
+
/** One answerable Client presentation of a pending Host waterfall. */
|
|
152
|
+
var PendingApproval = class {
|
|
153
|
+
sessionId;
|
|
154
|
+
/** Domain discriminator used by Session pending-interaction consumers. */
|
|
155
|
+
kind;
|
|
156
|
+
/** Opaque render identity and one-shot remount axis. */
|
|
157
|
+
key;
|
|
158
|
+
/** Tool requesting the decision. */
|
|
159
|
+
toolName;
|
|
160
|
+
/** Correlated Tool call, when supplied by the asker. */
|
|
161
|
+
callId;
|
|
162
|
+
/** Human-readable reason supplied by the asker. */
|
|
163
|
+
reason;
|
|
164
|
+
/** Localized presentation copy, when supplied by the asker. */
|
|
165
|
+
displayReason;
|
|
166
|
+
/** Result returned by the Remote Event listener to the Host waterfall. */
|
|
167
|
+
result;
|
|
168
|
+
#resolve;
|
|
169
|
+
#reject;
|
|
170
|
+
#signal;
|
|
171
|
+
#onAbort;
|
|
172
|
+
#delegated = Symbol("pending approval delegated");
|
|
173
|
+
#settled = false;
|
|
174
|
+
/**
|
|
175
|
+
* @param sessionId - Agent/Session identity owning the scoped request.
|
|
176
|
+
* @param request - Host approval request projected through the Remote Event.
|
|
177
|
+
*/
|
|
178
|
+
constructor(sessionId, request) {
|
|
179
|
+
this.sessionId = sessionId;
|
|
180
|
+
this.kind = "approval";
|
|
181
|
+
nextApprovalKey += 1;
|
|
182
|
+
this.key = `approval:${String(nextApprovalKey)}`;
|
|
183
|
+
this.toolName = request.toolName;
|
|
184
|
+
this.callId = request.callId;
|
|
185
|
+
this.reason = request.reason;
|
|
186
|
+
this.displayReason = request.displayReason;
|
|
187
|
+
const completion = Promise.withResolvers();
|
|
188
|
+
this.result = completion.promise;
|
|
189
|
+
this.#resolve = completion.resolve;
|
|
190
|
+
this.#reject = completion.reject;
|
|
191
|
+
this.#signal = request.signal;
|
|
192
|
+
if (request.signal === void 0) {
|
|
193
|
+
this.#onAbort = void 0;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const onAbort = () => {
|
|
197
|
+
this.abort(request.signal?.reason ?? /* @__PURE__ */ new Error("approval request was aborted"));
|
|
198
|
+
};
|
|
199
|
+
this.#onAbort = onAbort;
|
|
200
|
+
request.signal.addEventListener("abort", onAbort, { once: true });
|
|
201
|
+
if (request.signal.aborted) onAbort();
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Availability of this pending request after answer or withdrawal.
|
|
205
|
+
* @returns whether this request can still accept a decision.
|
|
206
|
+
*/
|
|
207
|
+
get answerable() {
|
|
208
|
+
return !this.#settled;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Resolve the Host waterfall with the user's decision.
|
|
212
|
+
* @param outcome - supported interactive decision.
|
|
213
|
+
*/
|
|
214
|
+
answer(outcome) {
|
|
215
|
+
return settlePendingComposer(() => {
|
|
216
|
+
this.finish(() => {
|
|
217
|
+
this.#resolve(outcome);
|
|
218
|
+
});
|
|
219
|
+
}, "pending approval settlement failed");
|
|
220
|
+
}
|
|
221
|
+
/** Delegate an unanswered request to the next waterfall listener. */
|
|
222
|
+
delegate() {
|
|
223
|
+
if (this.#settled) return;
|
|
224
|
+
this.finish(() => {
|
|
225
|
+
this.#reject(this.#delegated);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Test whether a rejection requests waterfall delegation.
|
|
230
|
+
* @param reason - rejection received from {@link PendingApproval.result}.
|
|
231
|
+
* @returns whether {@link PendingApproval.delegate} produced it.
|
|
232
|
+
*/
|
|
233
|
+
isDelegation(reason) {
|
|
234
|
+
return reason === this.#delegated;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* End an unanswered presentation when its transport, scope, or plugin lifetime ends.
|
|
238
|
+
* @param reason - rejection exposed to the waiting Remote Event listener.
|
|
239
|
+
*/
|
|
240
|
+
abort(reason) {
|
|
241
|
+
if (this.#settled) return;
|
|
242
|
+
this.finish(() => {
|
|
243
|
+
this.#reject(reason);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
finish(settle) {
|
|
247
|
+
if (this.#settled) throw new Error(`pending approval ${this.key} is already settled`);
|
|
248
|
+
this.#settled = true;
|
|
249
|
+
if (this.#signal !== void 0 && this.#onAbort !== void 0) this.#signal.removeEventListener("abort", this.#onAbort);
|
|
250
|
+
settle();
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
//#endregion
|
|
254
|
+
//#region lib/types/client/locales.js
|
|
255
|
+
/** `approval` namespace dictionaries. */
|
|
256
|
+
/** Simplified Chinese dictionary and key-set source of truth. */
|
|
257
|
+
const zh = {
|
|
258
|
+
waiting: "等待审批",
|
|
259
|
+
"detail.aria": "审批详情",
|
|
260
|
+
escalation: "工具 {toolName} 请求越权执行",
|
|
261
|
+
reject: "拒绝",
|
|
262
|
+
allowOnce: "允许一次"
|
|
263
|
+
};
|
|
264
|
+
/** English dictionary, checked against the Chinese key set. */
|
|
265
|
+
const en = {
|
|
266
|
+
waiting: "Waiting for approval",
|
|
267
|
+
"detail.aria": "Approval details",
|
|
268
|
+
escalation: "Tool {toolName} requests privileged execution",
|
|
269
|
+
reject: "Reject",
|
|
270
|
+
allowOnce: "Allow once"
|
|
271
|
+
};
|
|
272
|
+
//#endregion
|
|
273
|
+
//#region lib/types/client/index.js
|
|
274
|
+
/** Required services: Agent scopes, Remote Events, Session UI, Slot registry, and copy. */
|
|
275
|
+
const inject = [
|
|
276
|
+
"sessions",
|
|
277
|
+
"remote",
|
|
278
|
+
"uiSession",
|
|
279
|
+
"slots",
|
|
280
|
+
"locale"
|
|
281
|
+
];
|
|
282
|
+
const NS = "approval";
|
|
283
|
+
/** Present one request until the user answers or its lifetime ends. */
|
|
284
|
+
async function answerApproval(ctx, owner, request, next, registerPendingInteraction) {
|
|
285
|
+
const sessionId = ctx.sessions.scopeOf(owner);
|
|
286
|
+
if (sessionId === void 0) return next();
|
|
287
|
+
const pending = new PendingApproval(sessionId, {
|
|
288
|
+
toolName: request.toolName,
|
|
289
|
+
...request.callId === void 0 ? {} : { callId: request.callId },
|
|
290
|
+
...request.reason === void 0 ? {} : { reason: request.reason },
|
|
291
|
+
...request.displayReason === void 0 ? {} : { displayReason: request.displayReason },
|
|
292
|
+
...request.signal === void 0 ? {} : { signal: request.signal }
|
|
293
|
+
});
|
|
294
|
+
const completed = Promise.withResolvers();
|
|
295
|
+
const remove = registerPendingInteraction(pending, async () => {
|
|
296
|
+
pending.delegate();
|
|
297
|
+
await completed.promise;
|
|
298
|
+
});
|
|
299
|
+
try {
|
|
300
|
+
try {
|
|
301
|
+
return await pending.result;
|
|
302
|
+
} catch (error) {
|
|
303
|
+
if (pending.isDelegation(error)) return await next();
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
} finally {
|
|
307
|
+
remove();
|
|
308
|
+
completed.resolve();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Install approval copy and the scoped waterfall consumer.
|
|
313
|
+
* @param ctx - Client root context.
|
|
314
|
+
*/
|
|
315
|
+
function apply(ctx) {
|
|
316
|
+
ctx.effect(() => ctx.locale.register(NS, {
|
|
317
|
+
zh,
|
|
318
|
+
en
|
|
319
|
+
}), "ui-approval: dictionaries");
|
|
320
|
+
ctx.inject(["shortcuts"], (scope) => {
|
|
321
|
+
const t = ctx.locale.bind(NS);
|
|
322
|
+
scope.effect(() => scope.shortcuts.registerFixed({
|
|
323
|
+
id: "approval.allow",
|
|
324
|
+
label: () => t("allowOnce"),
|
|
325
|
+
keys: ["Enter"],
|
|
326
|
+
bindings: [{
|
|
327
|
+
code: "Enter",
|
|
328
|
+
modifiers: []
|
|
329
|
+
}],
|
|
330
|
+
group: "approval"
|
|
331
|
+
}), "ui-approval: fixed allow reference");
|
|
332
|
+
scope.effect(() => scope.shortcuts.registerFixed({
|
|
333
|
+
id: "approval.reject",
|
|
334
|
+
label: () => t("reject"),
|
|
335
|
+
keys: ["Esc"],
|
|
336
|
+
bindings: [{
|
|
337
|
+
code: "Escape",
|
|
338
|
+
modifiers: []
|
|
339
|
+
}],
|
|
340
|
+
group: "approval"
|
|
341
|
+
}), "ui-approval: fixed reject reference");
|
|
342
|
+
});
|
|
343
|
+
const registerPendingInteraction = ctx.uiSession.registerPendingInteraction(() => 0);
|
|
344
|
+
ctx.slots.inject("conversation.composer", () => ctx.slots.register({
|
|
345
|
+
name: "conversation.composer",
|
|
346
|
+
priority: 1,
|
|
347
|
+
select: ({ pendingInteraction }) => pendingInteraction instanceof PendingApproval ? pendingInteraction : null,
|
|
348
|
+
locale: NS,
|
|
349
|
+
inject: () => ({ resolveReason: (reason) => ctx.locale.resolveText(reason) }),
|
|
350
|
+
children: { "conversation.approval.detail": {
|
|
351
|
+
kind: "single",
|
|
352
|
+
scope: "session"
|
|
353
|
+
} }
|
|
354
|
+
}, ApprovalPanel));
|
|
355
|
+
ctx.remote.$on("approval/request", function(request, next) {
|
|
356
|
+
return answerApproval(ctx, this, request, next, registerPendingInteraction);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
//#endregion
|
|
360
|
+
exports.apply = apply;
|
|
361
|
+
exports.inject = inject;
|
|
362
|
+
exports.ApprovalPanel = ApprovalPanel;
|
|
363
|
+
return module.exports;
|
|
364
|
+
}
|
|
365
|
+
}).factory;
|
|
366
|
+
|
|
367
|
+
//# sourceMappingURL=client.js.map
|