opencode-muse 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,235 @@
1
+ import { MspProtocolError, MuseTurnFailedError, MuseTurnUnqueuedError, } from "../errors.js";
2
+ function isNumber(value) {
3
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
4
+ }
5
+ function terminalFinishReason(terminal) {
6
+ if (terminal === "completed")
7
+ return "stop";
8
+ if (terminal === "failed")
9
+ return "error";
10
+ return "other";
11
+ }
12
+ /** Maps typed Muse view facts to text/reasoning-only V3 events and safe usage. */
13
+ export class MuseStreamMapper {
14
+ turnId;
15
+ itemKinds = new Map();
16
+ itemStarted = new Set();
17
+ reasoningStarted = new Set();
18
+ itemDeltaCounts = new Map();
19
+ itemText = new Map();
20
+ seenUsageCursors = new Set();
21
+ textParts = [];
22
+ terminalUsage;
23
+ callUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0, reasoningTokens: 0 };
24
+ hasCallUsage = false;
25
+ finishWasSent = false;
26
+ currentFinishReason;
27
+ terminal;
28
+ failure;
29
+ constructor(turnId) {
30
+ this.turnId = turnId;
31
+ }
32
+ get generatedText() {
33
+ return this.textParts.map((part) => part.text).join("");
34
+ }
35
+ get content() {
36
+ const text = this.generatedText;
37
+ return text.length > 0 ? [{ type: "text", text }] : [];
38
+ }
39
+ get usage() {
40
+ if (this.terminalUsage)
41
+ return { ...this.terminalUsage };
42
+ if (!this.hasCallUsage)
43
+ return undefined;
44
+ return { ...this.callUsage };
45
+ }
46
+ get finishWasSentToOpenCode() {
47
+ return this.finishWasSent;
48
+ }
49
+ get finishReason() {
50
+ return this.currentFinishReason;
51
+ }
52
+ accept(notification) {
53
+ const params = notification.params ?? {};
54
+ switch (notification.method) {
55
+ case "item/started":
56
+ return this.itemStartedEvent(params);
57
+ case "item/delta":
58
+ return this.itemDeltaEvent(params);
59
+ case "item/completed":
60
+ return this.itemCompletedEvent(params);
61
+ case "session/tokenUsage":
62
+ this.tokenUsageEvent(params);
63
+ return [];
64
+ case "turn/foregroundCompleted":
65
+ if (params.turnId !== this.turnId || this.finishWasSent)
66
+ return [];
67
+ this.terminal = "foregroundCompleted";
68
+ return [this.finishPart("stop", "foregroundCompleted")];
69
+ case "turn/unqueued":
70
+ if (params.turnId !== this.turnId)
71
+ return [];
72
+ this.terminal = "unqueued";
73
+ this.failure = new MuseTurnUnqueuedError();
74
+ return this.finishWasSent ? [] : this.failAndFinish(this.failure, "unqueued");
75
+ case "turn/retracted":
76
+ if (params.turnId !== this.turnId)
77
+ return [];
78
+ this.terminal = "retracted";
79
+ return this.finishWasSent ? [] : [this.finishPart("other", "retracted")];
80
+ case "turn/completed":
81
+ return this.turnCompleted(params);
82
+ default:
83
+ return [];
84
+ }
85
+ }
86
+ itemStartedEvent(params) {
87
+ const item = params.item;
88
+ if (!item || item.turnId !== this.turnId || typeof item.itemId !== "string")
89
+ return [];
90
+ this.itemKinds.set(item.itemId, item.kind ?? "unknown");
91
+ this.itemStarted.add(item.itemId);
92
+ if (item.kind === "agentMessage")
93
+ return [{ type: "text-start", id: item.itemId }];
94
+ return [];
95
+ }
96
+ itemDeltaEvent(params) {
97
+ if (typeof params.itemId !== "string" || typeof params.delta !== "string")
98
+ return [];
99
+ const kind = this.itemKinds.get(params.itemId);
100
+ if (kind === "agentMessage" && (params.field === undefined || params.field === "text")) {
101
+ this.itemDeltaCounts.set(params.itemId, (this.itemDeltaCounts.get(params.itemId) ?? 0) + 1);
102
+ this.itemText.set(params.itemId, (this.itemText.get(params.itemId) ?? "") + params.delta);
103
+ this.textParts.push({ type: "text", text: params.delta });
104
+ return [{ type: "text-delta", id: params.itemId, delta: params.delta }];
105
+ }
106
+ if (kind === "reasoning" && typeof params.field === "string" && params.field.startsWith("summary.")) {
107
+ this.itemDeltaCounts.set(params.itemId, (this.itemDeltaCounts.get(params.itemId) ?? 0) + 1);
108
+ const parts = [];
109
+ if (!this.reasoningStarted.has(params.itemId)) {
110
+ this.reasoningStarted.add(params.itemId);
111
+ parts.push({ type: "reasoning-start", id: params.itemId });
112
+ }
113
+ parts.push({ type: "reasoning-delta", id: params.itemId, delta: params.delta });
114
+ return parts;
115
+ }
116
+ return [];
117
+ }
118
+ itemCompletedEvent(params) {
119
+ const item = params.item;
120
+ if (!item || item.turnId !== this.turnId || typeof item.itemId !== "string")
121
+ return [];
122
+ this.itemKinds.set(item.itemId, item.kind ?? "unknown");
123
+ if (item.kind === "reasoning") {
124
+ const summaries = Array.isArray(item.summary) ? item.summary.filter((value) => typeof value === "string") : [];
125
+ const hasSummaryDeltas = (this.itemDeltaCounts.get(item.itemId) ?? 0) > 0;
126
+ if (hasSummaryDeltas)
127
+ return this.reasoningStarted.has(item.itemId)
128
+ ? [{ type: "reasoning-end", id: item.itemId }]
129
+ : [];
130
+ if (summaries.length === 0)
131
+ return [];
132
+ return [
133
+ { type: "reasoning-start", id: item.itemId },
134
+ ...summaries.map((delta) => ({ type: "reasoning-delta", id: item.itemId, delta })),
135
+ { type: "reasoning-end", id: item.itemId },
136
+ ];
137
+ }
138
+ if (item.kind !== "agentMessage")
139
+ return [];
140
+ const parts = [];
141
+ if (!this.itemStarted.has(item.itemId)) {
142
+ this.itemStarted.add(item.itemId);
143
+ parts.push({ type: "text-start", id: item.itemId });
144
+ }
145
+ if (typeof item.text === "string") {
146
+ const observed = this.itemText.get(item.itemId) ?? "";
147
+ if (observed.length === 0 && item.text.length > 0) {
148
+ this.itemText.set(item.itemId, item.text);
149
+ this.textParts.push({ type: "text", text: item.text });
150
+ parts.push({ type: "text-delta", id: item.itemId, delta: item.text });
151
+ }
152
+ else if (observed.length > 0 && item.text.startsWith(observed)) {
153
+ const suffix = item.text.slice(observed.length);
154
+ if (suffix.length > 0) {
155
+ this.itemText.set(item.itemId, item.text);
156
+ this.textParts.push({ type: "text", text: suffix });
157
+ parts.push({ type: "text-delta", id: item.itemId, delta: suffix });
158
+ }
159
+ }
160
+ else if (observed !== item.text) {
161
+ this.failure = new MspProtocolError("item/completed");
162
+ return [{ type: "error", error: this.failure }];
163
+ }
164
+ }
165
+ parts.push({ type: "text-end", id: item.itemId });
166
+ return parts;
167
+ }
168
+ tokenUsageEvent(params) {
169
+ if (params.turnId !== this.turnId || typeof params.viewCursor !== "string")
170
+ return;
171
+ if (this.seenUsageCursors.has(params.viewCursor))
172
+ return;
173
+ this.seenUsageCursors.add(params.viewCursor);
174
+ const raw = params.usage;
175
+ if (!raw)
176
+ return;
177
+ const inputTokens = isNumber(params.promptTokens)
178
+ ? params.promptTokens
179
+ : isNumber(raw.inputTokens) ? raw.inputTokens : 0;
180
+ const outputTokens = isNumber(raw.outputTokens) ? raw.outputTokens : 0;
181
+ const reasoningTokens = isNumber(raw.reasoningTokens) ? raw.reasoningTokens : 0;
182
+ const totalTokens = isNumber(params.totalTokens) ? params.totalTokens : inputTokens + outputTokens;
183
+ this.callUsage.inputTokens += inputTokens;
184
+ this.callUsage.outputTokens += outputTokens;
185
+ this.callUsage.totalTokens += totalTokens;
186
+ this.callUsage.reasoningTokens += reasoningTokens;
187
+ this.hasCallUsage = true;
188
+ }
189
+ turnCompleted(params) {
190
+ if (params.turnId !== this.turnId || typeof params.terminal !== "string")
191
+ return [];
192
+ this.terminal = params.terminal;
193
+ const unified = terminalFinishReason(params.terminal);
194
+ this.currentFinishReason = { unified, raw: params.terminal };
195
+ const terminalUsage = params.usage;
196
+ if (terminalUsage) {
197
+ const inputTokens = isNumber(terminalUsage.inputTokens) ? terminalUsage.inputTokens : undefined;
198
+ const outputTokens = isNumber(terminalUsage.outputTokens) ? terminalUsage.outputTokens : undefined;
199
+ const reasoningTokens = isNumber(terminalUsage.reasoningTokens) ? terminalUsage.reasoningTokens : undefined;
200
+ this.terminalUsage = {
201
+ inputTokens,
202
+ outputTokens,
203
+ totalTokens: inputTokens === undefined || outputTokens === undefined ? undefined : inputTokens + outputTokens,
204
+ reasoningTokens,
205
+ };
206
+ }
207
+ if (this.failure)
208
+ return this.finishWasSent ? [] : this.failAndFinish(this.failure, params.terminal);
209
+ if (params.terminal === "failed") {
210
+ const error = params.error;
211
+ this.failure = new MuseTurnFailedError(typeof error?.kind === "string" ? error.kind : "unknown", typeof error?.retryable === "boolean" ? error.retryable : undefined);
212
+ return this.finishWasSent ? [] : this.failAndFinish(this.failure, params.terminal);
213
+ }
214
+ return this.finishWasSent ? [] : [this.finishPart(terminalFinishReason(params.terminal), params.terminal)];
215
+ }
216
+ failAndFinish(error, terminal) {
217
+ this.finishWasSent = true;
218
+ const unified = error instanceof MspProtocolError ? "error" : terminalFinishReason(terminal);
219
+ return [{ type: "error", error }, this.finishPart(unified, terminal)];
220
+ }
221
+ finishPart(unified, raw) {
222
+ this.finishWasSent = true;
223
+ this.currentFinishReason = { unified, raw };
224
+ return {
225
+ type: "finish",
226
+ finishReason: this.currentFinishReason,
227
+ usage: this.usage ?? {
228
+ inputTokens: undefined,
229
+ outputTokens: undefined,
230
+ totalTokens: undefined,
231
+ reasoningTokens: undefined,
232
+ },
233
+ };
234
+ }
235
+ }
@@ -0,0 +1,49 @@
1
+ import { type CommandOptions } from "@muse-code/sdk";
2
+ import { MspProtocolError } from "../errors.js";
3
+ export interface MspNotification {
4
+ jsonrpc: "2.0";
5
+ method: string;
6
+ params?: Record<string, unknown>;
7
+ emittedAtMs?: number;
8
+ }
9
+ export interface MspConnectionLike {
10
+ readonly closed?: Promise<void>;
11
+ command(method: string, params: Record<string, unknown>, options?: CommandOptions): Promise<Record<string, unknown>>;
12
+ request(method: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;
13
+ mintCommandId(): string;
14
+ onNotification(handler: (notification: MspNotification) => void): void;
15
+ onProtocolError?(handler: (error: unknown) => void): void;
16
+ close(): Promise<void>;
17
+ }
18
+ export interface MspClientOptions {
19
+ commandTimeoutMs?: number;
20
+ requestTimeoutMs?: number;
21
+ closeConnection?: boolean;
22
+ onFatal?: () => void;
23
+ }
24
+ /** Thin typed facade over the SDK connection; it never logs or retains wire payloads. */
25
+ export declare class MspClient {
26
+ private readonly connection;
27
+ private readonly subscribers;
28
+ private closePromise;
29
+ private closed;
30
+ private observedProtocolFailure;
31
+ private readonly commandTimeoutMs;
32
+ private readonly requestTimeoutMs;
33
+ private readonly closeConnection;
34
+ constructor(connection: MspConnectionLike, options?: MspClientOptions);
35
+ get isClosed(): boolean;
36
+ get protocolFailure(): MspProtocolError | undefined;
37
+ mintCommandId(): string;
38
+ command<TResult extends object = Record<string, unknown>>(method: string, paramsWithCommandId: Record<string, unknown> & {
39
+ commandId: string;
40
+ }, options?: Omit<CommandOptions, "commandId">): Promise<TResult>;
41
+ request<TResult extends object = Record<string, unknown>>(method: string, params?: Record<string, unknown>): Promise<TResult>;
42
+ /** Start/resume already attach at their returned head; `after` explicitly requests replay. */
43
+ subscribe(sessionId: string, after?: string, signal?: AbortSignal): AsyncIterable<MspNotification>;
44
+ /** Mark subscriptions ended after the owning process wrapper has shut down. */
45
+ dispose(): void;
46
+ close(): Promise<void>;
47
+ private assertOpen;
48
+ private publish;
49
+ }
@@ -0,0 +1,229 @@
1
+ import { MspError, ProtocolError as SdkProtocolError, } from "@muse-code/sdk";
2
+ import { MspCommandRejectedError, MspCommandTimeoutError, MspHostClosedError, MspProtocolError, MspRequestTimeoutError, MspTransportError, } from "../errors.js";
3
+ class AsyncQueue {
4
+ values = [];
5
+ readers = new Set();
6
+ ended = false;
7
+ failure;
8
+ push(value) {
9
+ if (this.ended)
10
+ return;
11
+ const reader = this.readers.values().next().value;
12
+ if (reader) {
13
+ this.readers.delete(reader);
14
+ if (reader.onAbort && reader.signal)
15
+ reader.signal.removeEventListener("abort", reader.onAbort);
16
+ reader.resolve({ value, done: false });
17
+ return;
18
+ }
19
+ this.values.push(value);
20
+ }
21
+ next(signal) {
22
+ if (this.failure !== undefined)
23
+ return Promise.reject(this.failure);
24
+ const value = this.values.shift();
25
+ if (value !== undefined)
26
+ return Promise.resolve({ value, done: false });
27
+ if (this.ended)
28
+ return Promise.resolve({ value: undefined, done: true });
29
+ if (signal?.aborted)
30
+ return Promise.reject(abortError());
31
+ return new Promise((resolve, reject) => {
32
+ const reader = { resolve, reject, signal };
33
+ if (signal) {
34
+ reader.onAbort = () => {
35
+ this.readers.delete(reader);
36
+ reject(abortError());
37
+ };
38
+ signal.addEventListener("abort", reader.onAbort, { once: true });
39
+ }
40
+ this.readers.add(reader);
41
+ });
42
+ }
43
+ end() {
44
+ if (this.ended)
45
+ return;
46
+ this.ended = true;
47
+ for (const reader of this.readers) {
48
+ if (reader.onAbort && reader.signal)
49
+ reader.signal.removeEventListener("abort", reader.onAbort);
50
+ reader.resolve({ value: undefined, done: true });
51
+ }
52
+ this.readers.clear();
53
+ }
54
+ fail(error) {
55
+ if (this.ended)
56
+ return;
57
+ this.failure = error;
58
+ this.ended = true;
59
+ for (const reader of this.readers) {
60
+ if (reader.onAbort && reader.signal)
61
+ reader.signal.removeEventListener("abort", reader.onAbort);
62
+ reader.reject(error);
63
+ }
64
+ this.readers.clear();
65
+ }
66
+ }
67
+ function abortError() {
68
+ return new DOMException("MSP subscription aborted", "AbortError");
69
+ }
70
+ function withTimeout(promise, timeoutMs, timeout) {
71
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
72
+ return promise;
73
+ let timer;
74
+ return Promise.race([
75
+ promise,
76
+ new Promise((_resolve, reject) => {
77
+ timer = setTimeout(() => reject(timeout()), timeoutMs);
78
+ }),
79
+ ]).finally(() => {
80
+ if (timer !== undefined)
81
+ clearTimeout(timer);
82
+ });
83
+ }
84
+ function safeRequestFailure(method, error) {
85
+ if (error instanceof MspError) {
86
+ return new MspCommandRejectedError(method, error.code, error.kind, error.retryable);
87
+ }
88
+ if (error instanceof SdkProtocolError)
89
+ return new MspProtocolError(method);
90
+ if (error instanceof Error && error.name === "MspRequestTimeoutError")
91
+ return error;
92
+ return new MspTransportError(method);
93
+ }
94
+ /** Thin typed facade over the SDK connection; it never logs or retains wire payloads. */
95
+ export class MspClient {
96
+ connection;
97
+ subscribers = new Set();
98
+ closePromise;
99
+ closed = false;
100
+ observedProtocolFailure;
101
+ commandTimeoutMs;
102
+ requestTimeoutMs;
103
+ closeConnection;
104
+ constructor(connection, options = {}) {
105
+ this.connection = connection;
106
+ this.commandTimeoutMs = options.commandTimeoutMs ?? 30_000;
107
+ this.requestTimeoutMs = options.requestTimeoutMs ?? this.commandTimeoutMs;
108
+ this.closeConnection = options.closeConnection ?? true;
109
+ connection.onNotification((notification) => this.publish(notification));
110
+ connection.onProtocolError?.(() => {
111
+ if (this.observedProtocolFailure)
112
+ return;
113
+ this.observedProtocolFailure = new MspProtocolError();
114
+ this.closed = true;
115
+ for (const subscription of this.subscribers)
116
+ subscription.queue.fail(this.observedProtocolFailure);
117
+ this.subscribers.clear();
118
+ options.onFatal?.();
119
+ });
120
+ void connection.closed?.then(() => {
121
+ const unexpected = !this.closed;
122
+ this.dispose();
123
+ if (unexpected)
124
+ options.onFatal?.();
125
+ }, () => {
126
+ const unexpected = !this.closed;
127
+ this.dispose();
128
+ if (unexpected)
129
+ options.onFatal?.();
130
+ });
131
+ }
132
+ get isClosed() {
133
+ return this.closed;
134
+ }
135
+ get protocolFailure() {
136
+ return this.observedProtocolFailure;
137
+ }
138
+ mintCommandId() {
139
+ this.assertOpen();
140
+ return this.connection.mintCommandId();
141
+ }
142
+ command(method, paramsWithCommandId, options = {}) {
143
+ this.assertOpen();
144
+ if (typeof paramsWithCommandId.commandId !== "string" || paramsWithCommandId.commandId.length === 0) {
145
+ return Promise.reject(new MspProtocolError(method));
146
+ }
147
+ const request = this.connection.command(method, paramsWithCommandId, {
148
+ ...options,
149
+ commandId: paramsWithCommandId.commandId,
150
+ });
151
+ return withTimeout(request, this.commandTimeoutMs, () => new MspCommandTimeoutError(method, this.commandTimeoutMs)).catch((error) => {
152
+ if (error instanceof MspCommandTimeoutError)
153
+ throw error;
154
+ throw safeRequestFailure(method, error);
155
+ });
156
+ }
157
+ request(method, params) {
158
+ this.assertOpen();
159
+ const request = this.connection.request(method, params);
160
+ return withTimeout(request, this.requestTimeoutMs, () => new MspRequestTimeoutError(method, this.requestTimeoutMs)).catch((error) => {
161
+ if (error instanceof MspRequestTimeoutError)
162
+ throw error;
163
+ throw safeRequestFailure(method, error);
164
+ });
165
+ }
166
+ /** Start/resume already attach at their returned head; `after` explicitly requests replay. */
167
+ async *subscribe(sessionId, after, signal) {
168
+ this.assertOpen();
169
+ if (!sessionId)
170
+ throw new MspProtocolError("view/subscribe");
171
+ if (signal?.aborted)
172
+ throw abortError();
173
+ const subscription = { sessionId, queue: new AsyncQueue() };
174
+ this.subscribers.add(subscription);
175
+ try {
176
+ if (after !== undefined)
177
+ await this.request("view/subscribe", { sessionId, after });
178
+ while (!signal?.aborted) {
179
+ const next = await subscription.queue.next(signal);
180
+ if (next.done)
181
+ return;
182
+ yield next.value;
183
+ }
184
+ }
185
+ finally {
186
+ this.subscribers.delete(subscription);
187
+ subscription.queue.end();
188
+ }
189
+ }
190
+ /** Mark subscriptions ended after the owning process wrapper has shut down. */
191
+ dispose() {
192
+ if (this.closed)
193
+ return;
194
+ this.closed = true;
195
+ for (const subscription of this.subscribers)
196
+ subscription.queue.end();
197
+ this.subscribers.clear();
198
+ }
199
+ close() {
200
+ if (this.closePromise)
201
+ return this.closePromise;
202
+ this.dispose();
203
+ this.closePromise = this.closeConnection
204
+ ? this.connection.close().catch(() => { throw new MspTransportError(); })
205
+ : Promise.resolve();
206
+ return this.closePromise;
207
+ }
208
+ assertOpen() {
209
+ if (this.observedProtocolFailure)
210
+ throw this.observedProtocolFailure;
211
+ if (this.closed)
212
+ throw new MspHostClosedError();
213
+ }
214
+ publish(notification) {
215
+ if (this.closed)
216
+ return;
217
+ const params = notification.params ?? {};
218
+ const item = params.item;
219
+ const sessionId = typeof params.sessionId === "string"
220
+ ? params.sessionId
221
+ : typeof item?.sessionId === "string" ? item.sessionId : undefined;
222
+ if (sessionId === undefined)
223
+ return;
224
+ for (const subscription of this.subscribers) {
225
+ if (subscription.sessionId === sessionId)
226
+ subscription.queue.push(notification);
227
+ }
228
+ }
229
+ }
@@ -0,0 +1,55 @@
1
+ import { type MspHandshake, type SpawnMspConnectionOptions } from "@muse-code/sdk";
2
+ import { MspClient, type MspConnectionLike, type MspNotification } from "./client.js";
3
+ export interface MspHostRuntime {
4
+ connection: MspConnectionLike;
5
+ initializeResult: Record<string, unknown>;
6
+ close(): Promise<unknown>;
7
+ exited?: Promise<unknown>;
8
+ }
9
+ export interface MspHandshakeLike {
10
+ initialize(params: Parameters<MspHandshake["initialize"]>[0]): Promise<MspHostRuntime>;
11
+ close(): Promise<unknown>;
12
+ }
13
+ export interface MspHostOptions {
14
+ museBin?: string;
15
+ args?: readonly string[];
16
+ cwd?: string;
17
+ env?: NodeJS.ProcessEnv;
18
+ startupTimeoutMs?: number;
19
+ commandTimeoutMs?: number;
20
+ requestTimeoutMs?: number;
21
+ shutdownTimeoutMs?: number;
22
+ clientInfo?: {
23
+ name: string;
24
+ version: string;
25
+ };
26
+ capabilities?: Parameters<MspHandshake["initialize"]>[0]["capabilities"];
27
+ }
28
+ export interface MspHostDependencies {
29
+ createHandshake?: (options: SpawnMspConnectionOptions) => MspHandshakeLike;
30
+ }
31
+ export interface MspHostExit {
32
+ kind: string;
33
+ exitCode?: number | null;
34
+ exitSignal?: string | null;
35
+ retry?: string;
36
+ }
37
+ /** Owns one muse serve child and one MSP connection for one OpenCode session. */
38
+ export declare class MspHost {
39
+ private readonly runtime;
40
+ readonly client: MspClient;
41
+ readonly initializeResult: Record<string, unknown>;
42
+ readonly exited: Promise<MspHostExit>;
43
+ private state;
44
+ private closePromise;
45
+ private constructor();
46
+ static start(options?: MspHostOptions, dependencies?: MspHostDependencies): Promise<MspHost>;
47
+ get isClosed(): boolean;
48
+ mintCommandId(): string;
49
+ command<TResult extends object = Record<string, unknown>>(method: string, paramsWithCommandId: Record<string, unknown> & {
50
+ commandId: string;
51
+ }): Promise<TResult>;
52
+ request<TResult extends object = Record<string, unknown>>(method: string, params?: Record<string, unknown>): Promise<TResult>;
53
+ subscribe(sessionId: string, after?: string, signal?: AbortSignal): AsyncIterable<MspNotification>;
54
+ close(): Promise<void>;
55
+ }