opencode-oncall 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.
Files changed (105) hide show
  1. package/LICENSE +151 -0
  2. package/README.md +50 -0
  3. package/dist/common-settings-actions.d.ts +15 -0
  4. package/dist/common-settings-actions.js +48 -0
  5. package/dist/common-settings-store.d.ts +1 -0
  6. package/dist/common-settings-store.js +1 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +1 -0
  9. package/dist/plugin-hooks.d.ts +51 -0
  10. package/dist/plugin-hooks.js +288 -0
  11. package/dist/plugin.d.ts +10 -0
  12. package/dist/plugin.js +115 -0
  13. package/dist/settings-store.d.ts +50 -0
  14. package/dist/settings-store.js +214 -0
  15. package/dist/store-paths.d.ts +16 -0
  16. package/dist/store-paths.js +61 -0
  17. package/dist/ui/wechat-menu.d.ts +26 -0
  18. package/dist/ui/wechat-menu.js +90 -0
  19. package/dist/wechat/bind-flow.d.ts +29 -0
  20. package/dist/wechat/bind-flow.js +207 -0
  21. package/dist/wechat/bridge.d.ts +136 -0
  22. package/dist/wechat/bridge.js +1059 -0
  23. package/dist/wechat/broker-client.d.ts +23 -0
  24. package/dist/wechat/broker-client.js +274 -0
  25. package/dist/wechat/broker-endpoint.d.ts +21 -0
  26. package/dist/wechat/broker-endpoint.js +78 -0
  27. package/dist/wechat/broker-entry.d.ts +123 -0
  28. package/dist/wechat/broker-entry.js +1321 -0
  29. package/dist/wechat/broker-launcher.d.ts +37 -0
  30. package/dist/wechat/broker-launcher.js +418 -0
  31. package/dist/wechat/broker-mutation-queue.d.ts +93 -0
  32. package/dist/wechat/broker-mutation-queue.js +126 -0
  33. package/dist/wechat/broker-server.d.ts +86 -0
  34. package/dist/wechat/broker-server.js +1340 -0
  35. package/dist/wechat/broker-state-store.d.ts +335 -0
  36. package/dist/wechat/broker-state-store.js +1964 -0
  37. package/dist/wechat/command-parser.d.ts +18 -0
  38. package/dist/wechat/command-parser.js +58 -0
  39. package/dist/wechat/compat/jiti-loader.d.ts +27 -0
  40. package/dist/wechat/compat/jiti-loader.js +118 -0
  41. package/dist/wechat/compat/openclaw-account-helpers.d.ts +29 -0
  42. package/dist/wechat/compat/openclaw-account-helpers.js +60 -0
  43. package/dist/wechat/compat/openclaw-bind-helpers.d.ts +29 -0
  44. package/dist/wechat/compat/openclaw-bind-helpers.js +169 -0
  45. package/dist/wechat/compat/openclaw-guided-smoke.d.ts +180 -0
  46. package/dist/wechat/compat/openclaw-guided-smoke.js +1134 -0
  47. package/dist/wechat/compat/openclaw-public-entry.d.ts +33 -0
  48. package/dist/wechat/compat/openclaw-public-entry.js +62 -0
  49. package/dist/wechat/compat/openclaw-public-helpers.d.ts +70 -0
  50. package/dist/wechat/compat/openclaw-public-helpers.js +68 -0
  51. package/dist/wechat/compat/openclaw-qr-gateway.d.ts +15 -0
  52. package/dist/wechat/compat/openclaw-qr-gateway.js +39 -0
  53. package/dist/wechat/compat/openclaw-smoke.d.ts +48 -0
  54. package/dist/wechat/compat/openclaw-smoke.js +100 -0
  55. package/dist/wechat/compat/openclaw-sync-buf.d.ts +24 -0
  56. package/dist/wechat/compat/openclaw-sync-buf.js +80 -0
  57. package/dist/wechat/compat/openclaw-updates-send.d.ts +47 -0
  58. package/dist/wechat/compat/openclaw-updates-send.js +38 -0
  59. package/dist/wechat/compat/qrcode-terminal-loader.d.ts +12 -0
  60. package/dist/wechat/compat/qrcode-terminal-loader.js +16 -0
  61. package/dist/wechat/compat/slash-guard.d.ts +11 -0
  62. package/dist/wechat/compat/slash-guard.js +24 -0
  63. package/dist/wechat/dead-letter-store.d.ts +48 -0
  64. package/dist/wechat/dead-letter-store.js +224 -0
  65. package/dist/wechat/debug-bundle-collector.d.ts +49 -0
  66. package/dist/wechat/debug-bundle-collector.js +580 -0
  67. package/dist/wechat/debug-bundle-flow.d.ts +37 -0
  68. package/dist/wechat/debug-bundle-flow.js +180 -0
  69. package/dist/wechat/debug-bundle-redaction.d.ts +14 -0
  70. package/dist/wechat/debug-bundle-redaction.js +339 -0
  71. package/dist/wechat/handle.d.ts +10 -0
  72. package/dist/wechat/handle.js +57 -0
  73. package/dist/wechat/ipc-auth.d.ts +6 -0
  74. package/dist/wechat/ipc-auth.js +39 -0
  75. package/dist/wechat/latest-account-state-store.d.ts +8 -0
  76. package/dist/wechat/latest-account-state-store.js +38 -0
  77. package/dist/wechat/notification-dispatcher.d.ts +34 -0
  78. package/dist/wechat/notification-dispatcher.js +266 -0
  79. package/dist/wechat/notification-format.d.ts +15 -0
  80. package/dist/wechat/notification-format.js +196 -0
  81. package/dist/wechat/notification-store.d.ts +72 -0
  82. package/dist/wechat/notification-store.js +807 -0
  83. package/dist/wechat/notification-types.d.ts +37 -0
  84. package/dist/wechat/notification-types.js +1 -0
  85. package/dist/wechat/openclaw-account-adapter.d.ts +30 -0
  86. package/dist/wechat/openclaw-account-adapter.js +60 -0
  87. package/dist/wechat/operator-store.d.ts +9 -0
  88. package/dist/wechat/operator-store.js +69 -0
  89. package/dist/wechat/protocol.d.ts +150 -0
  90. package/dist/wechat/protocol.js +197 -0
  91. package/dist/wechat/question-interaction.d.ts +24 -0
  92. package/dist/wechat/question-interaction.js +180 -0
  93. package/dist/wechat/request-store.d.ts +108 -0
  94. package/dist/wechat/request-store.js +669 -0
  95. package/dist/wechat/session-digest.d.ts +50 -0
  96. package/dist/wechat/session-digest.js +167 -0
  97. package/dist/wechat/state-paths.d.ts +26 -0
  98. package/dist/wechat/state-paths.js +92 -0
  99. package/dist/wechat/status-format.d.ts +26 -0
  100. package/dist/wechat/status-format.js +616 -0
  101. package/dist/wechat/token-store.d.ts +20 -0
  102. package/dist/wechat/token-store.js +193 -0
  103. package/dist/wechat/wechat-status-runtime.d.ts +89 -0
  104. package/dist/wechat/wechat-status-runtime.js +518 -0
  105. package/package.json +74 -0
@@ -0,0 +1,23 @@
1
+ import { type BrokerAckPayload, type BrokerEnvelope, type BrokerToBridgeCommand, type BrokerToBridgeControl, type BridgeToBrokerEvent, type HelloRegisterPayload, type RegisterAckPayload } from "./protocol.js";
2
+ export type LiveRegisterResult = {
3
+ ack: RegisterAckPayload;
4
+ control?: BrokerToBridgeControl;
5
+ pendingCommands: BrokerToBridgeCommand[];
6
+ };
7
+ export type SendBridgeEventOptions = {
8
+ instanceID: string;
9
+ controlId?: string;
10
+ };
11
+ export type BrokerClientLiveHandlers = {
12
+ onBrokerControl?: (control: BrokerToBridgeControl) => Promise<void> | void;
13
+ onBrokerCommand?: (command: BrokerToBridgeCommand) => Promise<void> | void;
14
+ };
15
+ export type BrokerClientOptions = BrokerClientLiveHandlers;
16
+ export type BrokerClient = {
17
+ ping: () => Promise<BrokerEnvelope>;
18
+ registerHello: (payload: HelloRegisterPayload) => Promise<LiveRegisterResult>;
19
+ sendBridgeEvent: (event: BridgeToBrokerEvent, options: SendBridgeEventOptions) => Promise<BrokerAckPayload>;
20
+ setLiveHandlers: (handlers: BrokerClientLiveHandlers) => void;
21
+ close: () => Promise<void>;
22
+ };
23
+ export declare function connect(endpoint: string, options?: BrokerClientOptions): Promise<BrokerClient>;
@@ -0,0 +1,274 @@
1
+ import { createBrokerSocket } from "./broker-endpoint.js";
2
+ import { createBridgeEventEnvelope, createHelloRegisterEnvelope, parseEnvelopeLine, serializeEnvelope, } from "./protocol.js";
3
+ function isNonEmptyString(value) {
4
+ return typeof value === "string" && value.trim().length > 0;
5
+ }
6
+ function isFiniteNumber(value) {
7
+ return typeof value === "number" && Number.isFinite(value);
8
+ }
9
+ function isObject(value) {
10
+ return typeof value === "object" && value !== null;
11
+ }
12
+ function isLiveBrokerCommandPayload(value) {
13
+ if (!isObject(value)) {
14
+ return false;
15
+ }
16
+ return isNonEmptyString(value.commandId)
17
+ && isFiniteNumber(value.brokerSeq)
18
+ && isNonEmptyString(value.type)
19
+ && "payload" in value;
20
+ }
21
+ function isLiveBrokerControlPayload(value) {
22
+ if (!isObject(value)) {
23
+ return false;
24
+ }
25
+ return isNonEmptyString(value.controlId)
26
+ && isFiniteNumber(value.brokerSeq)
27
+ && isNonEmptyString(value.type)
28
+ && "payload" in value;
29
+ }
30
+ function isResponseForRequest(response, requestId) {
31
+ if (response.id === requestId) {
32
+ return true;
33
+ }
34
+ if (response.id.endsWith(`-${requestId}`)) {
35
+ return true;
36
+ }
37
+ if (response.type === "error") {
38
+ const payload = response.payload;
39
+ return payload.requestId === requestId;
40
+ }
41
+ return false;
42
+ }
43
+ export async function connect(endpoint, options = {}) {
44
+ const socket = createBrokerSocket(endpoint);
45
+ let sequence = 0;
46
+ const pendingRequests = new Map();
47
+ let buffer = "";
48
+ let connected = false;
49
+ let closed = false;
50
+ let serverPushChain = Promise.resolve();
51
+ let liveHandlers = {
52
+ onBrokerControl: options.onBrokerControl,
53
+ onBrokerCommand: options.onBrokerCommand,
54
+ };
55
+ function enqueueServerPush(task) {
56
+ serverPushChain = serverPushChain
57
+ .then(() => task())
58
+ .catch(() => {
59
+ // swallow push handler failures to keep connection alive
60
+ });
61
+ }
62
+ function deletePendingRequest(requestId) {
63
+ const pending = pendingRequests.get(requestId);
64
+ if (!pending) {
65
+ return undefined;
66
+ }
67
+ pendingRequests.delete(requestId);
68
+ return pending;
69
+ }
70
+ function rejectPendingRequest(requestId, reason) {
71
+ deletePendingRequest(requestId)?.reject(reason);
72
+ }
73
+ function findPendingRequest(response) {
74
+ if (response.type === "error") {
75
+ const requestId = response.payload.requestId;
76
+ if (isNonEmptyString(requestId)) {
77
+ const pending = pendingRequests.get(requestId);
78
+ if (pending) {
79
+ return [requestId, pending];
80
+ }
81
+ }
82
+ }
83
+ const direct = pendingRequests.get(response.id);
84
+ if (direct) {
85
+ return [response.id, direct];
86
+ }
87
+ for (const [requestId, pending] of pendingRequests.entries()) {
88
+ if (isResponseForRequest(response, requestId)) {
89
+ return [requestId, pending];
90
+ }
91
+ }
92
+ return null;
93
+ }
94
+ const connectedReady = new Promise((resolve, reject) => {
95
+ socket.once("connect", () => {
96
+ connected = true;
97
+ resolve();
98
+ });
99
+ socket.once("error", reject);
100
+ });
101
+ socket.on("data", (chunk) => {
102
+ buffer += chunk.toString("utf8");
103
+ const parsedFrames = [];
104
+ while (true) {
105
+ const newlineIndex = buffer.indexOf("\n");
106
+ if (newlineIndex === -1) {
107
+ break;
108
+ }
109
+ const frame = buffer.slice(0, newlineIndex + 1);
110
+ buffer = buffer.slice(newlineIndex + 1);
111
+ try {
112
+ parsedFrames.push(parseEnvelopeLine(frame));
113
+ }
114
+ catch (error) {
115
+ for (const requestId of [...pendingRequests.keys()]) {
116
+ rejectPendingRequest(requestId, error);
117
+ }
118
+ }
119
+ }
120
+ if (parsedFrames.length === 0) {
121
+ return;
122
+ }
123
+ for (const parsed of parsedFrames) {
124
+ if (handleServerPush(parsed)) {
125
+ continue;
126
+ }
127
+ const matched = findPendingRequest(parsed);
128
+ if (!matched) {
129
+ continue;
130
+ }
131
+ const [requestId] = matched;
132
+ deletePendingRequest(requestId)?.resolve(parsed);
133
+ }
134
+ });
135
+ socket.on("error", (error) => {
136
+ for (const requestId of [...pendingRequests.keys()]) {
137
+ rejectPendingRequest(requestId, error);
138
+ }
139
+ });
140
+ socket.on("close", () => {
141
+ connected = false;
142
+ closed = true;
143
+ for (const requestId of [...pendingRequests.keys()]) {
144
+ rejectPendingRequest(requestId, new Error("broker connection closed"));
145
+ }
146
+ });
147
+ await connectedReady;
148
+ function nextRequestId(prefix) {
149
+ sequence += 1;
150
+ return `${prefix}-${Date.now()}-${sequence}`;
151
+ }
152
+ function handleBrokerControlPush(envelope) {
153
+ if (envelope.type !== "requestReplay" && envelope.type !== "requestFullSync") {
154
+ return false;
155
+ }
156
+ if (!liveHandlers.onBrokerControl || !isLiveBrokerControlPayload(envelope.payload)) {
157
+ return false;
158
+ }
159
+ const control = envelope.payload;
160
+ enqueueServerPush(() => liveHandlers.onBrokerControl?.(control));
161
+ return true;
162
+ }
163
+ function handleBrokerCommandPush(envelope) {
164
+ if (envelope.type !== "replyQuestion"
165
+ && envelope.type !== "replyPermission"
166
+ && envelope.type !== "replyNaturalStop") {
167
+ return false;
168
+ }
169
+ if (!liveHandlers.onBrokerCommand || !isLiveBrokerCommandPayload(envelope.payload)) {
170
+ return false;
171
+ }
172
+ const command = envelope.payload;
173
+ enqueueServerPush(() => liveHandlers.onBrokerCommand?.(command));
174
+ return true;
175
+ }
176
+ function handleServerPush(envelope) {
177
+ if (handleBrokerControlPush(envelope)) {
178
+ return true;
179
+ }
180
+ if (handleBrokerCommandPush(envelope)) {
181
+ return true;
182
+ }
183
+ return false;
184
+ }
185
+ async function send(envelope) {
186
+ if (!connected || closed) {
187
+ throw new Error("broker connection closed");
188
+ }
189
+ return new Promise((resolve, reject) => {
190
+ pendingRequests.set(envelope.id, { resolve, reject });
191
+ socket.write(serializeEnvelope(envelope));
192
+ });
193
+ }
194
+ return {
195
+ async ping() {
196
+ return send({
197
+ id: nextRequestId("ping"),
198
+ type: "ping",
199
+ payload: {},
200
+ });
201
+ },
202
+ async registerHello(payload) {
203
+ const hello = createHelloRegisterEnvelope(payload);
204
+ const response = await send({
205
+ id: nextRequestId("hello-register"),
206
+ type: "hello/register",
207
+ instanceID: hello.payload.instanceID,
208
+ payload: hello.payload,
209
+ });
210
+ if (response.type !== "registerAck" || !isObject(response.payload)) {
211
+ throw new Error("hello/register failed");
212
+ }
213
+ const ackPayload = response.payload;
214
+ return {
215
+ ack: {
216
+ protocolVersion: ackPayload.protocolVersion,
217
+ stateGeneration: ackPayload.stateGeneration,
218
+ instanceIncarnation: ackPayload.instanceIncarnation,
219
+ brokerSeq: ackPayload.brokerSeq,
220
+ needReplay: ackPayload.needReplay,
221
+ needFullSync: ackPayload.needFullSync,
222
+ },
223
+ ...(isLiveBrokerControlPayload(ackPayload.control) ? { control: ackPayload.control } : {}),
224
+ pendingCommands: Array.isArray(ackPayload.pendingCommands)
225
+ ? ackPayload.pendingCommands.filter((command) => isLiveBrokerCommandPayload(command))
226
+ : [],
227
+ };
228
+ },
229
+ async sendBridgeEvent(event, options) {
230
+ const bridgeEvent = createBridgeEventEnvelope(options.controlId ? { ...event, controlId: options.controlId } : event);
231
+ const response = await send({
232
+ id: nextRequestId(bridgeEvent.type),
233
+ type: bridgeEvent.type,
234
+ instanceID: options.instanceID,
235
+ payload: bridgeEvent,
236
+ });
237
+ if (response.type !== "ack" || !isObject(response.payload)) {
238
+ throw new Error(`bridge event ack failed: ${bridgeEvent.type}`);
239
+ }
240
+ return response.payload;
241
+ },
242
+ setLiveHandlers(handlers) {
243
+ liveHandlers = {
244
+ ...liveHandlers,
245
+ ...handlers,
246
+ };
247
+ },
248
+ async close() {
249
+ if (closed) {
250
+ return;
251
+ }
252
+ if (socket.destroyed) {
253
+ closed = true;
254
+ connected = false;
255
+ return;
256
+ }
257
+ const closePromise = new Promise((resolve) => {
258
+ socket.once("close", () => resolve());
259
+ });
260
+ socket.end();
261
+ await Promise.race([
262
+ closePromise,
263
+ new Promise((resolve) => {
264
+ setTimeout(() => {
265
+ if (!socket.destroyed) {
266
+ socket.destroy();
267
+ }
268
+ resolve();
269
+ }, 200);
270
+ }),
271
+ ]);
272
+ },
273
+ };
274
+ }
@@ -0,0 +1,21 @@
1
+ import net from "node:net";
2
+ type BrokerEndpointOptions = {
3
+ platform?: NodeJS.Platform;
4
+ stateRoot?: string;
5
+ now?: () => number;
6
+ random?: () => number;
7
+ };
8
+ type ParsedBrokerEndpoint = {
9
+ kind: "tcp";
10
+ host: string;
11
+ port: number;
12
+ } | {
13
+ kind: "path";
14
+ path: string;
15
+ };
16
+ export declare function isTcpBrokerEndpoint(endpoint: string): boolean;
17
+ export declare function createDefaultBrokerEndpoint(options?: BrokerEndpointOptions): string;
18
+ export declare function parseBrokerEndpoint(endpoint: string): ParsedBrokerEndpoint;
19
+ export declare function createBrokerSocket(endpoint: string): net.Socket;
20
+ export declare function listenOnBrokerEndpoint(server: net.Server, endpoint: string): Promise<string>;
21
+ export {};
@@ -0,0 +1,78 @@
1
+ import net from "node:net";
2
+ import path from "node:path";
3
+ function isNonEmptyString(value) {
4
+ return typeof value === "string" && value.trim().length > 0;
5
+ }
6
+ export function isTcpBrokerEndpoint(endpoint) {
7
+ return endpoint.startsWith("tcp://");
8
+ }
9
+ export function createDefaultBrokerEndpoint(options = {}) {
10
+ const platform = options.platform ?? process.platform;
11
+ const stateRoot = options.stateRoot ?? ".";
12
+ const now = options.now ?? Date.now;
13
+ const random = options.random ?? Math.random;
14
+ const suffix = `${now()}-${random().toString(16).slice(2)}`;
15
+ if (platform === "win32") {
16
+ return "tcp://127.0.0.1:0";
17
+ }
18
+ return path.join(stateRoot, `broker-${suffix}.sock`);
19
+ }
20
+ export function parseBrokerEndpoint(endpoint) {
21
+ if (!isTcpBrokerEndpoint(endpoint)) {
22
+ return {
23
+ kind: "path",
24
+ path: endpoint,
25
+ };
26
+ }
27
+ const parsed = new URL(endpoint);
28
+ if (parsed.protocol !== "tcp:") {
29
+ throw new Error(`unsupported broker endpoint protocol: ${parsed.protocol}`);
30
+ }
31
+ if (!isNonEmptyString(parsed.hostname)) {
32
+ throw new Error("tcp broker endpoint host is required");
33
+ }
34
+ const port = Number(parsed.port);
35
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
36
+ throw new Error("tcp broker endpoint port is invalid");
37
+ }
38
+ return {
39
+ kind: "tcp",
40
+ host: parsed.hostname,
41
+ port,
42
+ };
43
+ }
44
+ export function createBrokerSocket(endpoint) {
45
+ const parsed = parseBrokerEndpoint(endpoint);
46
+ if (parsed.kind === "tcp") {
47
+ return net.createConnection({
48
+ host: parsed.host,
49
+ port: parsed.port,
50
+ });
51
+ }
52
+ return net.createConnection(parsed.path);
53
+ }
54
+ export async function listenOnBrokerEndpoint(server, endpoint) {
55
+ const parsed = parseBrokerEndpoint(endpoint);
56
+ await new Promise((resolve, reject) => {
57
+ server.once("error", reject);
58
+ if (parsed.kind === "tcp") {
59
+ server.listen({ host: parsed.host, port: parsed.port }, () => {
60
+ server.off("error", reject);
61
+ resolve();
62
+ });
63
+ return;
64
+ }
65
+ server.listen(parsed.path, () => {
66
+ server.off("error", reject);
67
+ resolve();
68
+ });
69
+ });
70
+ if (parsed.kind === "path") {
71
+ return parsed.path;
72
+ }
73
+ const address = server.address();
74
+ if (!address || typeof address === "string") {
75
+ throw new Error("tcp broker endpoint failed to resolve bound address");
76
+ }
77
+ return `tcp://${address.address}:${address.port}`;
78
+ }
@@ -0,0 +1,123 @@
1
+ import type { QuestionAnswer } from "@opencode-ai/sdk/v2";
2
+ import { type BrokerMutationQueue, type RecoveryMutation } from "./broker-mutation-queue.js";
3
+ import { type BrokerAuthoritativeView, type BrokerCommandActionInput, type BrokerCommandRecord } from "./broker-state-store.js";
4
+ import type { WechatSlashCommand } from "./command-parser.js";
5
+ import { markDeadLetterRecoveryFailed } from "./dead-letter-store.js";
6
+ import { type WechatNotificationDeliveryFailureInput, type WechatNotificationSendInput } from "./notification-dispatcher.js";
7
+ import { type WechatStatusRuntime, type WechatStatusRuntimeDiagnosticEvent } from "./wechat-status-runtime.js";
8
+ type ReplyMutationResult = {
9
+ mutationId: string;
10
+ ok: boolean;
11
+ errorMessage?: string;
12
+ };
13
+ type Awaitable<T> = T | Promise<T>;
14
+ type BrokerWechatStatusRuntimeLifecycle = {
15
+ start: () => Promise<void>;
16
+ close: () => Promise<void>;
17
+ };
18
+ type BrokerWechatStatusRuntimeLifecycleDeps = {
19
+ createStatusRuntime?: (deps: {
20
+ onSlashCommand: (input: {
21
+ command: import("./command-parser.js").WechatSlashCommand;
22
+ }) => Promise<string>;
23
+ onDiagnosticEvent: (event: WechatStatusRuntimeDiagnosticEvent) => void | Promise<void>;
24
+ drainOutboundMessages: (input?: {
25
+ sendMessage: (input: WechatNotificationSendInput) => Promise<void>;
26
+ }) => Promise<void>;
27
+ }) => WechatStatusRuntime;
28
+ createNotificationDispatcher?: (input: {
29
+ sendMessage: (input: WechatNotificationSendInput) => Promise<void>;
30
+ onDeliveryFailed?: (input: WechatNotificationDeliveryFailureInput) => Promise<void>;
31
+ }) => {
32
+ drainOutboundMessages: () => Promise<void>;
33
+ };
34
+ handleWechatSlashCommand?: (command: import("./command-parser.js").WechatSlashCommand) => Promise<string>;
35
+ sendReplyQuestionRpc?: (input: {
36
+ instanceID: string;
37
+ mutationId: string;
38
+ requestID: string;
39
+ answers: QuestionAnswer[];
40
+ }) => Promise<ReplyMutationResult>;
41
+ sendReplyPermissionRpc?: (input: {
42
+ instanceID: string;
43
+ mutationId: string;
44
+ requestID: string;
45
+ reply: "once" | "always" | "reject";
46
+ message?: string;
47
+ }) => Promise<ReplyMutationResult>;
48
+ sendReplyNaturalStopRpc?: (input: {
49
+ instanceID: string;
50
+ mutationId: string;
51
+ sessionID: string;
52
+ handle: string;
53
+ text: string;
54
+ }) => Promise<ReplyMutationResult>;
55
+ handleNotificationDeliveryFailure?: (input: {
56
+ instanceID: string;
57
+ wechatAccountId: string;
58
+ userId: string;
59
+ registrationEpoch?: string;
60
+ }) => Promise<void>;
61
+ onRuntimeError?: (error: unknown) => void;
62
+ onDiagnosticEvent?: (event: WechatStatusRuntimeDiagnosticEvent) => void | Promise<void>;
63
+ stateRoot?: string;
64
+ };
65
+ export declare function shouldEnableBrokerWechatStatusRuntime(env?: NodeJS.ProcessEnv): boolean;
66
+ type BrokerWechatSlashHandlerClient = {
67
+ question?: {
68
+ reply?: (input: {
69
+ requestID: string;
70
+ directory?: string;
71
+ answers?: Array<QuestionAnswer>;
72
+ }) => Promise<unknown>;
73
+ };
74
+ permission?: {
75
+ reply?: (input: {
76
+ requestID: string;
77
+ directory?: string;
78
+ reply?: "once" | "always" | "reject";
79
+ message?: string;
80
+ }) => Promise<unknown>;
81
+ };
82
+ };
83
+ type PermissionMutationTestHooks = {
84
+ beforeFinalizePermission?: (request: {
85
+ readonly routeKey: string;
86
+ readonly handle: string;
87
+ }) => Promise<void> | void;
88
+ };
89
+ export declare function createBrokerWechatSlashCommandHandler(input: {
90
+ handleStatusCommand?: () => Promise<string>;
91
+ client?: BrokerWechatSlashHandlerClient;
92
+ readBrokerAuthoritativeView?: () => Awaitable<BrokerAuthoritativeView | undefined>;
93
+ readBrokerCommandStateByAction?: (input: BrokerCommandActionInput) => Awaitable<BrokerCommandRecord | undefined>;
94
+ sendReplyQuestionRpc?: (input: {
95
+ instanceID: string;
96
+ mutationId: string;
97
+ requestID: string;
98
+ answers: QuestionAnswer[];
99
+ }) => Promise<ReplyMutationResult>;
100
+ sendReplyPermissionRpc?: (input: {
101
+ instanceID: string;
102
+ mutationId: string;
103
+ requestID: string;
104
+ reply: "once" | "always" | "reject";
105
+ message?: string;
106
+ }) => Promise<ReplyMutationResult>;
107
+ sendReplyNaturalStopRpc?: (input: {
108
+ instanceID: string;
109
+ mutationId: string;
110
+ sessionID: string;
111
+ handle: string;
112
+ text: string;
113
+ }) => Promise<ReplyMutationResult>;
114
+ directory?: string;
115
+ mutationQueue?: BrokerMutationQueue;
116
+ markDeadLetterRecoveryFailedImpl?: typeof markDeadLetterRecoveryFailed;
117
+ permissionMutationTestHooks?: PermissionMutationTestHooks;
118
+ recoveryTestHooks?: {
119
+ afterReopenRequest?: (mutation: RecoveryMutation) => Promise<void> | void;
120
+ };
121
+ }): (command: WechatSlashCommand) => Promise<string>;
122
+ export declare function createBrokerWechatStatusRuntimeLifecycle(deps?: BrokerWechatStatusRuntimeLifecycleDeps): BrokerWechatStatusRuntimeLifecycle;
123
+ export {};