@maiaos/sdk 0.1.0-canary.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 +177 -0
- package/dist/agent-permission/agent-permission.d.ts +9 -0
- package/dist/agent-permission/agent-permission.js +5 -0
- package/dist/agent-permission/effect.d.ts +4 -0
- package/dist/agent-permission/effect.js +34 -0
- package/dist/agent-permission/index.d.ts +2 -0
- package/dist/agent-permission/index.js +2 -0
- package/dist/approval/approval.d.ts +10 -0
- package/dist/approval/approval.js +5 -0
- package/dist/approval/effect.d.ts +5 -0
- package/dist/approval/effect.js +43 -0
- package/dist/approval/index.d.ts +2 -0
- package/dist/approval/index.js +2 -0
- package/dist/call/call.d.ts +26 -0
- package/dist/call/call.js +6 -0
- package/dist/call/effect.d.ts +5 -0
- package/dist/call/effect.js +46 -0
- package/dist/call/index.d.ts +2 -0
- package/dist/call/index.js +2 -0
- package/dist/client/effect.d.ts +8 -0
- package/dist/client/effect.js +283 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +2 -0
- package/dist/client/local-node-client.d.ts +100 -0
- package/dist/client/local-node-client.js +4 -0
- package/dist/connection/connection.d.ts +19 -0
- package/dist/connection/connection.js +5 -0
- package/dist/connection/effect.d.ts +5 -0
- package/dist/connection/effect.js +119 -0
- package/dist/connection/index.d.ts +2 -0
- package/dist/connection/index.js +2 -0
- package/dist/container/container.d.ts +14 -0
- package/dist/container/container.js +5 -0
- package/dist/container/effect.d.ts +4 -0
- package/dist/container/effect.js +90 -0
- package/dist/container/index.d.ts +2 -0
- package/dist/container/index.js +2 -0
- package/dist/discovery/discovery.d.ts +11 -0
- package/dist/discovery/discovery.js +5 -0
- package/dist/discovery/effect.d.ts +5 -0
- package/dist/discovery/effect.js +44 -0
- package/dist/discovery/index.d.ts +2 -0
- package/dist/discovery/index.js +2 -0
- package/dist/execution/effect.d.ts +4 -0
- package/dist/execution/effect.js +8 -0
- package/dist/execution/index.d.ts +2 -0
- package/dist/execution/index.js +2 -0
- package/dist/execution/relocation.d.ts +10 -0
- package/dist/execution/relocation.js +4 -0
- package/dist/feature-bindings/feature-bindings.d.ts +10 -0
- package/dist/feature-bindings/feature-bindings.js +2 -0
- package/dist/feature-bindings/index.d.ts +2 -0
- package/dist/feature-bindings/index.js +2 -0
- package/dist/hold/effect.d.ts +5 -0
- package/dist/hold/effect.js +61 -0
- package/dist/hold/hold.d.ts +12 -0
- package/dist/hold/hold.js +5 -0
- package/dist/hold/index.d.ts +2 -0
- package/dist/hold/index.js +2 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +21 -0
- package/dist/interaction/effect.d.ts +5 -0
- package/dist/interaction/effect.js +79 -0
- package/dist/interaction/index.d.ts +2 -0
- package/dist/interaction/index.js +2 -0
- package/dist/interaction/interaction.d.ts +12 -0
- package/dist/interaction/interaction.js +5 -0
- package/dist/node/attach.d.ts +11 -0
- package/dist/node/attach.js +33 -0
- package/dist/node/bridge-frame.d.ts +18 -0
- package/dist/node/bridge-frame.js +67 -0
- package/dist/node/bridge.d.ts +31 -0
- package/dist/node/bridge.js +148 -0
- package/dist/node/discovery.d.ts +187 -0
- package/dist/node/discovery.js +408 -0
- package/dist/node/effect.d.ts +9 -0
- package/dist/node/effect.js +9 -0
- package/dist/node/fetch.d.ts +2 -0
- package/dist/node/fetch.js +2 -0
- package/dist/node/http.d.ts +27 -0
- package/dist/node/http.js +258 -0
- package/dist/node/index.d.ts +3 -0
- package/dist/node/index.js +3 -0
- package/dist/node/local-node.d.ts +26 -0
- package/dist/node/local-node.js +67 -0
- package/dist/node/session.d.ts +15 -0
- package/dist/node/session.js +27 -0
- package/dist/node/ssh.d.ts +16 -0
- package/dist/node/ssh.js +74 -0
- package/dist/node/transport.d.ts +52 -0
- package/dist/node/transport.js +211 -0
- package/dist/node-changes/effect.d.ts +11 -0
- package/dist/node-changes/effect.js +61 -0
- package/dist/node-changes/index.d.ts +2 -0
- package/dist/node-changes/index.js +2 -0
- package/dist/node-changes/node-changes.d.ts +21 -0
- package/dist/node-changes/node-changes.js +23 -0
- package/dist/port-lease/effect.d.ts +5 -0
- package/dist/port-lease/effect.js +53 -0
- package/dist/port-lease/index.d.ts +2 -0
- package/dist/port-lease/index.js +2 -0
- package/dist/port-lease/port-lease.d.ts +11 -0
- package/dist/port-lease/port-lease.js +5 -0
- package/dist/presentation/client.d.ts +10 -0
- package/dist/presentation/client.js +4 -0
- package/dist/presentation/effect.d.ts +5 -0
- package/dist/presentation/effect.js +30 -0
- package/dist/presentation/index.d.ts +5 -0
- package/dist/presentation/index.js +3 -0
- package/dist/presentation/project-list.d.ts +7 -0
- package/dist/presentation/project-list.js +24 -0
- package/dist/presentation/session-list.d.ts +7 -0
- package/dist/presentation/session-list.js +32 -0
- package/dist/project-guard/effect.d.ts +5 -0
- package/dist/project-guard/effect.js +39 -0
- package/dist/project-guard/index.d.ts +2 -0
- package/dist/project-guard/index.js +2 -0
- package/dist/project-guard/project-guard.d.ts +10 -0
- package/dist/project-guard/project-guard.js +5 -0
- package/dist/project-workspace/effect.d.ts +5 -0
- package/dist/project-workspace/effect.js +124 -0
- package/dist/project-workspace/index.d.ts +2 -0
- package/dist/project-workspace/index.js +2 -0
- package/dist/project-workspace/project-workspace.d.ts +23 -0
- package/dist/project-workspace/project-workspace.js +4 -0
- package/dist/provider-pool/effect.d.ts +4 -0
- package/dist/provider-pool/effect.js +5 -0
- package/dist/provider-pool/index.d.ts +2 -0
- package/dist/provider-pool/index.js +2 -0
- package/dist/provider-pool/provider-pool.d.ts +7 -0
- package/dist/provider-pool/provider-pool.js +4 -0
- package/dist/remote-node/effect.d.ts +4 -0
- package/dist/remote-node/effect.js +57 -0
- package/dist/remote-node/index.d.ts +2 -0
- package/dist/remote-node/index.js +2 -0
- package/dist/remote-node/remote-node.d.ts +12 -0
- package/dist/remote-node/remote-node.js +5 -0
- package/dist/request/classify.d.ts +15 -0
- package/dist/request/classify.js +96 -0
- package/dist/request/client-error.d.ts +10 -0
- package/dist/request/client-error.js +11 -0
- package/dist/request/effect.d.ts +22 -0
- package/dist/request/effect.js +104 -0
- package/dist/request/envelope-schema.d.ts +2 -0
- package/dist/request/envelope-schema.js +2 -0
- package/dist/request/index.d.ts +5 -0
- package/dist/request/index.js +4 -0
- package/dist/request/maia-client.d.ts +21 -0
- package/dist/request/maia-client.js +9 -0
- package/dist/request/options.d.ts +9 -0
- package/dist/request/options.js +2 -0
- package/dist/run-ledger/effect.d.ts +5 -0
- package/dist/run-ledger/effect.js +72 -0
- package/dist/run-ledger/index.d.ts +2 -0
- package/dist/run-ledger/index.js +2 -0
- package/dist/run-ledger/run-ledger.d.ts +12 -0
- package/dist/run-ledger/run-ledger.js +2 -0
- package/dist/session/effect.d.ts +4 -0
- package/dist/session/effect.js +7 -0
- package/dist/session/index.d.ts +2 -0
- package/dist/session/index.js +2 -0
- package/dist/session/mailbox.d.ts +9 -0
- package/dist/session/mailbox.js +4 -0
- package/dist/session-creation/effect.d.ts +25 -0
- package/dist/session-creation/effect.js +269 -0
- package/dist/session-creation/index.d.ts +3 -0
- package/dist/session-creation/index.js +3 -0
- package/dist/session-creation/session-creation.d.ts +18 -0
- package/dist/session-creation/session-creation.js +24 -0
- package/dist/session-creation/tasks.d.ts +69 -0
- package/dist/session-creation/tasks.js +37 -0
- package/dist/session-view/index.d.ts +2 -0
- package/dist/session-view/index.js +2 -0
- package/dist/session-view/view.d.ts +42 -0
- package/dist/session-view/view.js +137 -0
- package/dist/stream/effect.d.ts +29 -0
- package/dist/stream/effect.js +77 -0
- package/dist/stream/index.d.ts +2 -0
- package/dist/stream/index.js +2 -0
- package/dist/stream/stream.d.ts +9 -0
- package/dist/stream/stream.js +2 -0
- package/dist/voice/effect.d.ts +7 -0
- package/dist/voice/effect.js +71 -0
- package/dist/voice/index.d.ts +4 -0
- package/dist/voice/index.js +3 -0
- package/dist/voice/managed-turn.d.ts +9 -0
- package/dist/voice/managed-turn.js +4 -0
- package/dist/voice/orchestrator-contract.d.ts +5 -0
- package/dist/voice/orchestrator-contract.js +4 -0
- package/dist/voice/orchestrator.d.ts +25 -0
- package/dist/voice/orchestrator.js +169 -0
- package/dist/voice/pi-relay-contract.d.ts +4 -0
- package/dist/voice/pi-relay-contract.js +2 -0
- package/dist/voice/pi-relay.d.ts +12 -0
- package/dist/voice/pi-relay.js +9 -0
- package/dist/voice/wire-schema.d.ts +215 -0
- package/dist/voice/wire-schema.js +16 -0
- package/package.json +84 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { MAX_NODE_API_BODY_BYTES, NODE_API_AUTHORIZATION_HEADER, NODE_API_COORDINATOR_PRINCIPAL, NODE_API_HTTP_METHOD, NODE_API_INVOCATION_CREDENTIAL_HEADER, NODE_API_JSON_CONTENT_TYPE, NODE_API_OPERATION_PATH, NODE_API_PRINCIPAL_HEADER, NODE_API_SESSION_CREDENTIAL_SCHEME, nodeApiAuthenticationSchema, nodeApiEndpointSchema, nodeApiHttpRequestSchema, nodeApiHttpResponseSchema, nodeApiInvocationAuthenticationSchema, } from "@maiaos/protocol";
|
|
2
|
+
import * as Data from "effect/Data";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Option from "effect/Option";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import * as Semaphore from "effect/Semaphore";
|
|
7
|
+
import { makeLocalNodeEffectClient, } from "../client/effect.js";
|
|
8
|
+
import { makeLocalNodeEffectRequester, } from "../request/effect.js";
|
|
9
|
+
import { MaiaClientError, } from "../request/index.js";
|
|
10
|
+
import { platformFetch } from "./fetch.js";
|
|
11
|
+
const MAX_HTTP_IN_FLIGHT_REQUESTS = 8;
|
|
12
|
+
const REQUEST_DEADLINE_MS = 5000;
|
|
13
|
+
class NodeApiTransportError extends Data.TaggedError("NodeApiTransportError") {
|
|
14
|
+
}
|
|
15
|
+
const transportError = (reason, message) => new NodeApiTransportError({ message, reason });
|
|
16
|
+
const CLIENT_ERROR_CODES = new Map([
|
|
17
|
+
["cancelled", "cancelled"],
|
|
18
|
+
["deadline_exceeded", "deadline_exceeded"],
|
|
19
|
+
["invalid_response", "invalid_response"],
|
|
20
|
+
["outcome_unknown", "outcome_unknown"],
|
|
21
|
+
["saturated", "saturated"],
|
|
22
|
+
["transport_failure", "transport_failure"],
|
|
23
|
+
]);
|
|
24
|
+
export const toClientError = (error, signal) => {
|
|
25
|
+
if (error instanceof MaiaClientError)
|
|
26
|
+
return error;
|
|
27
|
+
if (signal?.aborted === true) {
|
|
28
|
+
return new MaiaClientError("cancelled", "The Maia Node API request was cancelled.", { cause: error });
|
|
29
|
+
}
|
|
30
|
+
if (error instanceof NodeApiTransportError) {
|
|
31
|
+
const code = CLIENT_ERROR_CODES.get(error.reason) ?? "transport_failure";
|
|
32
|
+
return new MaiaClientError(code, error.message, { cause: error });
|
|
33
|
+
}
|
|
34
|
+
return new MaiaClientError("transport_failure", "The Maia Node API transport failed.", { cause: error });
|
|
35
|
+
};
|
|
36
|
+
const invalidOptions = () => transportError("transport_failure", "The Maia Node API transport options are invalid.");
|
|
37
|
+
const requireSingleAuthority = (options) => (options.authorizationScheme === "session" &&
|
|
38
|
+
(options.invocationAuthentication !== undefined ||
|
|
39
|
+
options.principal !== undefined)) ||
|
|
40
|
+
(options.principal !== undefined &&
|
|
41
|
+
options.invocationAuthentication !== undefined)
|
|
42
|
+
? Effect.fail(invalidOptions())
|
|
43
|
+
: Effect.succeed(options);
|
|
44
|
+
const parseOptions = (options) => Effect.try({
|
|
45
|
+
catch: invalidOptions,
|
|
46
|
+
try: () => ({
|
|
47
|
+
authorizationScheme: options.authorizationScheme ?? "bearer",
|
|
48
|
+
credential: options.credential,
|
|
49
|
+
endpoint: nodeApiEndpointSchema.parse(options.endpoint),
|
|
50
|
+
fetch: options.fetch ?? platformFetch(),
|
|
51
|
+
...(options.principal === undefined
|
|
52
|
+
? {}
|
|
53
|
+
: { principal: options.principal }),
|
|
54
|
+
...(options.invocationAuthentication === undefined
|
|
55
|
+
? {}
|
|
56
|
+
: {
|
|
57
|
+
invocationAuthentication: nodeApiInvocationAuthenticationSchema.parse(options.invocationAuthentication),
|
|
58
|
+
}),
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
const validateCredential = (token) => Effect.try({
|
|
62
|
+
catch: () => transportError("transport_failure", "The Maia Node API credential is invalid."),
|
|
63
|
+
try: () => nodeApiAuthenticationSchema.parse({
|
|
64
|
+
scheme: "maia.node.bearer/v1",
|
|
65
|
+
token,
|
|
66
|
+
}).token,
|
|
67
|
+
});
|
|
68
|
+
const credentialUnavailable = () => transportError("transport_failure", "The Maia Node API credential is unavailable.");
|
|
69
|
+
const readCredentialSource = (credential) => {
|
|
70
|
+
if (typeof credential === "string")
|
|
71
|
+
return Effect.succeed(credential);
|
|
72
|
+
return Effect.isEffect(credential)
|
|
73
|
+
? Effect.mapError(credential, credentialUnavailable)
|
|
74
|
+
: Effect.tryPromise({ catch: credentialUnavailable, try: credential });
|
|
75
|
+
};
|
|
76
|
+
export const resolveCredential = (credential) => readCredentialSource(credential).pipe(Effect.flatMap(validateCredential));
|
|
77
|
+
const responseTooLarge = () => new TypeError("Response body exceeds its resource limit.");
|
|
78
|
+
const decodeBody = (bytes, state) => Effect.try({
|
|
79
|
+
catch: (error) => error,
|
|
80
|
+
try: () => {
|
|
81
|
+
if (state.offset === 0)
|
|
82
|
+
throw new TypeError("Response body is empty.");
|
|
83
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, state.offset));
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
const readBodyChunks = (reader, bytes, state) => Effect.tryPromise({ catch: (error) => error, try: () => reader.read() }).pipe(Effect.flatMap((next) => {
|
|
87
|
+
if (next.done)
|
|
88
|
+
return decodeBody(bytes, state);
|
|
89
|
+
if (state.offset + next.value.byteLength > bytes.byteLength) {
|
|
90
|
+
return Effect.tryPromise({
|
|
91
|
+
catch: (error) => error,
|
|
92
|
+
try: () => reader.cancel("response_too_large"),
|
|
93
|
+
}).pipe(Effect.andThen(Effect.fail(responseTooLarge())));
|
|
94
|
+
}
|
|
95
|
+
bytes.set(next.value, state.offset);
|
|
96
|
+
state.offset += next.value.byteLength;
|
|
97
|
+
return readBodyChunks(reader, bytes, state);
|
|
98
|
+
}));
|
|
99
|
+
const readBoundedBody = (body) => Effect.acquireUseRelease(Effect.try({ catch: (error) => error, try: () => body.getReader() }), (reader) => readBodyChunks(reader, new Uint8Array(MAX_NODE_API_BODY_BYTES), {
|
|
100
|
+
offset: 0,
|
|
101
|
+
}).pipe(Effect.onInterrupt(() => Effect.sync(() => {
|
|
102
|
+
void reader.cancel().catch(() => false);
|
|
103
|
+
}))), (reader) => Effect.sync(() => {
|
|
104
|
+
reader.releaseLock();
|
|
105
|
+
}));
|
|
106
|
+
const hasOversizedContentLength = (response) => {
|
|
107
|
+
const raw = response.headers.get("content-length");
|
|
108
|
+
if (raw === null || !/^\d+$/u.test(raw))
|
|
109
|
+
return false;
|
|
110
|
+
return Number(raw) > MAX_NODE_API_BODY_BYTES;
|
|
111
|
+
};
|
|
112
|
+
const readBoundedResponse = (response) => (hasOversizedContentLength(response) || response.body === null
|
|
113
|
+
? Effect.fail(responseTooLarge())
|
|
114
|
+
: readBoundedBody(response.body)).pipe(Effect.mapError(() => transportError("invalid_response", "The Maia Node API response could not be read within its limits.")));
|
|
115
|
+
const validateResponseMetadata = (response) => {
|
|
116
|
+
if (response.redirected || response.url === "") {
|
|
117
|
+
return Effect.fail(transportError("invalid_response", "The Maia Node API returned an invalid HTTP response."));
|
|
118
|
+
}
|
|
119
|
+
const contentType = response.headers
|
|
120
|
+
.get("content-type")
|
|
121
|
+
?.split(";", 1)[0]
|
|
122
|
+
?.trim();
|
|
123
|
+
return contentType === NODE_API_JSON_CONTENT_TYPE
|
|
124
|
+
? Effect.void
|
|
125
|
+
: Effect.fail(transportError("invalid_response", "The Maia Node API returned an unsupported response type."));
|
|
126
|
+
};
|
|
127
|
+
const decodeJson = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Unknown));
|
|
128
|
+
const decodeResponseBody = (body) => decodeJson(body).pipe(Effect.flatMap((value) => Effect.try({
|
|
129
|
+
catch: (error) => error,
|
|
130
|
+
try: () => nodeApiHttpResponseSchema.parse(value),
|
|
131
|
+
})), Effect.mapError(() => transportError("invalid_response", "The Maia Node API response failed runtime validation.")));
|
|
132
|
+
const decodeHttpResponse = Effect.fn("NodeApiTransport.decodeResponse")(function* (response, requestUrl) {
|
|
133
|
+
const decoded = yield* validateResponseMetadata(response).pipe(Effect.andThen(readBoundedResponse(response)), Effect.flatMap(decodeResponseBody), Effect.mapError(() => dispatchFailure(true)));
|
|
134
|
+
if (response.status === 401 &&
|
|
135
|
+
response.url === requestUrl &&
|
|
136
|
+
decoded.correlationId === undefined &&
|
|
137
|
+
!decoded.payload.ok &&
|
|
138
|
+
decoded.payload.error.code === "authentication_failed") {
|
|
139
|
+
return yield* Effect.fail(new MaiaClientError("remote_error", "The Maia Node API rejected authentication.", { remoteError: decoded.payload.error }));
|
|
140
|
+
}
|
|
141
|
+
return decoded;
|
|
142
|
+
});
|
|
143
|
+
const encodeHttpBody = (envelope) => Effect.try({
|
|
144
|
+
catch: () => transportError("transport_failure", "The Maia Node API request failed runtime validation."),
|
|
145
|
+
try: () => JSON.stringify(nodeApiHttpRequestSchema.parse(envelope)),
|
|
146
|
+
}).pipe(Effect.filterOrFail((body) => new TextEncoder().encode(body).byteLength <= MAX_NODE_API_BODY_BYTES, () => transportError("transport_failure", "The Maia Node API request exceeded its resource limit.")));
|
|
147
|
+
const authorizationValue = (options, token) => options.authorizationScheme === "session"
|
|
148
|
+
? `${NODE_API_SESSION_CREDENTIAL_SCHEME} ${token}`
|
|
149
|
+
: `Bearer ${token}`;
|
|
150
|
+
const requestHeaders = (options, token) => {
|
|
151
|
+
const headers = new Headers([
|
|
152
|
+
["content-type", NODE_API_JSON_CONTENT_TYPE],
|
|
153
|
+
[NODE_API_AUTHORIZATION_HEADER, authorizationValue(options, token)],
|
|
154
|
+
]);
|
|
155
|
+
if (options.invocationAuthentication !== undefined) {
|
|
156
|
+
headers.set(NODE_API_INVOCATION_CREDENTIAL_HEADER, options.invocationAuthentication.credential);
|
|
157
|
+
}
|
|
158
|
+
if (options.principal !== undefined)
|
|
159
|
+
headers.set(NODE_API_PRINCIPAL_HEADER, NODE_API_COORDINATOR_PRINCIPAL);
|
|
160
|
+
return headers;
|
|
161
|
+
};
|
|
162
|
+
const dispatchFailure = (dispatched) => dispatched
|
|
163
|
+
? transportError("outcome_unknown", "The Maia Node API request outcome is unknown.")
|
|
164
|
+
: transportError("transport_failure", "The Maia Node API request could not be dispatched.");
|
|
165
|
+
const forwardAbort = (source, target) => {
|
|
166
|
+
const abort = () => {
|
|
167
|
+
target.abort(source.reason);
|
|
168
|
+
};
|
|
169
|
+
if (source.aborted)
|
|
170
|
+
abort();
|
|
171
|
+
else
|
|
172
|
+
source.addEventListener("abort", abort, { once: true });
|
|
173
|
+
return () => {
|
|
174
|
+
source.removeEventListener("abort", abort);
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
const combinedRequestSignal = (effectSignal, callerSignal) => {
|
|
178
|
+
const controller = new AbortController();
|
|
179
|
+
const releases = [forwardAbort(effectSignal, controller)];
|
|
180
|
+
if (callerSignal !== undefined) {
|
|
181
|
+
releases.push(forwardAbort(callerSignal, controller));
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
release: () => {
|
|
185
|
+
releases.forEach((release) => {
|
|
186
|
+
release();
|
|
187
|
+
});
|
|
188
|
+
},
|
|
189
|
+
signal: controller.signal,
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
const dispatchHttpRequest = (input) => Effect.tryPromise({
|
|
193
|
+
catch: () => dispatchFailure(input.context.dispatchState.dispatched),
|
|
194
|
+
try: (effectSignal) => {
|
|
195
|
+
const combined = combinedRequestSignal(effectSignal, input.context.signal);
|
|
196
|
+
input.context.dispatchState.dispatched = true;
|
|
197
|
+
return input.options
|
|
198
|
+
.fetch(`${input.options.endpoint.origin}${NODE_API_OPERATION_PATH}`, {
|
|
199
|
+
body: input.body,
|
|
200
|
+
cache: "no-store",
|
|
201
|
+
credentials: "omit",
|
|
202
|
+
headers: requestHeaders(input.options, input.token),
|
|
203
|
+
method: NODE_API_HTTP_METHOD,
|
|
204
|
+
redirect: "error",
|
|
205
|
+
referrerPolicy: "no-referrer",
|
|
206
|
+
signal: combined.signal,
|
|
207
|
+
})
|
|
208
|
+
.finally(combined.release);
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
const executeHttpRequest = Effect.fn("NodeApiTransport.request")(function* (context) {
|
|
212
|
+
const options = yield* requireSingleAuthority(context.options).pipe(Effect.flatMap(parseOptions));
|
|
213
|
+
if (typeof options.fetch !== "function") {
|
|
214
|
+
return yield* Effect.fail(transportError("transport_failure", "No Maia Node API HTTP implementation is available."));
|
|
215
|
+
}
|
|
216
|
+
const [body, token] = yield* Effect.all([
|
|
217
|
+
encodeHttpBody(context.envelope),
|
|
218
|
+
resolveCredential(options.credential),
|
|
219
|
+
]);
|
|
220
|
+
const response = yield* dispatchHttpRequest({
|
|
221
|
+
body,
|
|
222
|
+
context,
|
|
223
|
+
options: { ...options, fetch: options.fetch },
|
|
224
|
+
token,
|
|
225
|
+
});
|
|
226
|
+
return yield* decodeHttpResponse(response, `${options.endpoint.origin}${NODE_API_OPERATION_PATH}`);
|
|
227
|
+
});
|
|
228
|
+
const deadlineFailure = (state) => state.dispatched
|
|
229
|
+
? transportError("outcome_unknown", "The Maia Node API request outcome is unknown.")
|
|
230
|
+
: transportError("deadline_exceeded", "The Maia Node API request deadline expired before dispatch.");
|
|
231
|
+
const admitHttpRequest = (concurrency, context) => concurrency
|
|
232
|
+
.withPermitsIfAvailable(1)(executeHttpRequest(context).pipe(Effect.timeoutOrElse({
|
|
233
|
+
duration: REQUEST_DEADLINE_MS,
|
|
234
|
+
orElse: () => Effect.fail(deadlineFailure(context.dispatchState)),
|
|
235
|
+
})))
|
|
236
|
+
.pipe(Effect.flatMap((admitted) => Option.isSome(admitted)
|
|
237
|
+
? Effect.succeed(admitted.value)
|
|
238
|
+
: Effect.fail(transportError("saturated", "The Maia Node API transport reached its concurrency limit."))));
|
|
239
|
+
export const makeNodeApiHttpRequest = (options) => {
|
|
240
|
+
const concurrency = Semaphore.makeUnsafe(MAX_HTTP_IN_FLIGHT_REQUESTS);
|
|
241
|
+
return (envelope, requestOptions) => {
|
|
242
|
+
const signal = requestOptions?.signal;
|
|
243
|
+
return admitHttpRequest(concurrency, {
|
|
244
|
+
dispatchState: { dispatched: false },
|
|
245
|
+
envelope,
|
|
246
|
+
options,
|
|
247
|
+
...(signal === undefined ? {} : { signal }),
|
|
248
|
+
});
|
|
249
|
+
};
|
|
250
|
+
};
|
|
251
|
+
export const makeNodeApiEffectTransport = (options) => {
|
|
252
|
+
const request = makeNodeApiHttpRequest(options);
|
|
253
|
+
return {
|
|
254
|
+
request: (envelope, requestOptions) => request(envelope, requestOptions).pipe(Effect.mapError((error) => toClientError(error, requestOptions?.signal))),
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
export const createNodeApiEffectClient = (options) => makeLocalNodeEffectClient(makeLocalNodeEffectRequester(makeNodeApiEffectTransport(options)));
|
|
258
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { acknowledgeAttachedSessionDelivery, type AttachedCurrentContextOptions, type AttachedLocalNodeOptions, checkAttachedSessionInbox, connectNodeApi, type DiscoveredNodeApiConnection, type LocalNodeConnection, type LocalNodeDiscoveryOptions, type NodeApiDiscoveryOptions, sendAttachedSessionMessage, showAttachedCurrentContext, } from "./local-node.js";
|
|
2
|
+
export { attachSession, createNodeApiClient, createNodeApiTransport, type NodeApiConnection, type NodeApiCredential, type NodeApiObservationOptions, type NodeApiObservationRequest, type NodeApiTransportOptions, type SessionAttachOptions, type SessionAttachRequest, subscribeNodeApiObservations, } from "./transport.js";
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { acknowledgeAttachedSessionDelivery, checkAttachedSessionInbox, connectNodeApi, sendAttachedSessionMessage, showAttachedCurrentContext, } from "./local-node.js";
|
|
2
|
+
export { attachSession, createNodeApiClient, createNodeApiTransport, subscribeNodeApiObservations, } from "./transport.js";
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { InvocationContextShowResult, LocalNodeStatusResult, SessionInboxAckParameters, SessionInboxAckResult, SessionInboxCheckParameters, SessionInboxCheckResult, SessionMessageSendParameters, SessionMessageSendResult } from "@maiaos/protocol";
|
|
2
|
+
import { type NodeApiConnection } from "./transport.js";
|
|
3
|
+
export type LocalNodeDiscoveryOptions = {
|
|
4
|
+
readonly principal?: "coordinator";
|
|
5
|
+
readonly profile?: string;
|
|
6
|
+
readonly runtimeRootOverride?: string;
|
|
7
|
+
readonly signal?: AbortSignal;
|
|
8
|
+
};
|
|
9
|
+
export type NodeApiDiscoveryOptions = LocalNodeDiscoveryOptions;
|
|
10
|
+
export type DiscoveredNodeApiConnection = NodeApiConnection & {
|
|
11
|
+
readonly status: LocalNodeStatusResult;
|
|
12
|
+
};
|
|
13
|
+
export type LocalNodeConnection = DiscoveredNodeApiConnection;
|
|
14
|
+
export declare const principalOf: (options: Pick<NodeApiDiscoveryOptions, "principal">) => {
|
|
15
|
+
readonly principal?: "coordinator";
|
|
16
|
+
};
|
|
17
|
+
export declare const connectNodeApi: (options?: NodeApiDiscoveryOptions) => Promise<DiscoveredNodeApiConnection>;
|
|
18
|
+
export type AttachedLocalNodeOptions = LocalNodeDiscoveryOptions & {
|
|
19
|
+
readonly messageId?: string;
|
|
20
|
+
};
|
|
21
|
+
export type AttachedCurrentContextOptions = AttachedLocalNodeOptions;
|
|
22
|
+
export declare const showAttachedCurrentContext: (options?: AttachedCurrentContextOptions) => Promise<InvocationContextShowResult>;
|
|
23
|
+
export declare const sendAttachedSessionMessage: (parameters: SessionMessageSendParameters, options?: AttachedLocalNodeOptions) => Promise<SessionMessageSendResult>;
|
|
24
|
+
export declare const checkAttachedSessionInbox: (parameters: SessionInboxCheckParameters, options?: AttachedLocalNodeOptions) => Promise<SessionInboxCheckResult>;
|
|
25
|
+
export declare const acknowledgeAttachedSessionDelivery: (parameters: SessionInboxAckParameters, options?: AttachedLocalNodeOptions) => Promise<SessionInboxAckResult>;
|
|
26
|
+
//# sourceMappingURL=local-node.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import * as Crypto from "effect/Crypto";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as PlatformError from "effect/PlatformError";
|
|
5
|
+
import { MaiaClientError } from "../request/index.js";
|
|
6
|
+
import { acquireAttachedCredential, attachedTransportOptions, connectDiscoveredNodeApi, discoveryFailure, newMessageId, requireAttachmentPlatform, } from "./discovery.js";
|
|
7
|
+
import { createNodeApiClient } from "./transport.js";
|
|
8
|
+
const digestAlgorithms = {
|
|
9
|
+
["SHA-1"]: "sha1",
|
|
10
|
+
["SHA-256"]: "sha256",
|
|
11
|
+
["SHA-384"]: "sha384",
|
|
12
|
+
["SHA-512"]: "sha512",
|
|
13
|
+
};
|
|
14
|
+
const facadeCrypto = Crypto.make({
|
|
15
|
+
digest: (algorithm, data) => Effect.try({
|
|
16
|
+
catch: (cause) => PlatformError.systemError({
|
|
17
|
+
_tag: "Unknown",
|
|
18
|
+
cause,
|
|
19
|
+
description: "Could not compute digest",
|
|
20
|
+
method: "digest",
|
|
21
|
+
module: "Crypto",
|
|
22
|
+
}),
|
|
23
|
+
try: () => Uint8Array.from(createHash(digestAlgorithms[algorithm]).update(data).digest()),
|
|
24
|
+
}),
|
|
25
|
+
randomBytes: (size) => randomBytes(size),
|
|
26
|
+
});
|
|
27
|
+
const runFacade = (program, signal) => Effect.runPromise(Effect.provideService(program, Crypto.Crypto, facadeCrypto), signal === undefined ? undefined : { signal });
|
|
28
|
+
export const principalOf = (options) => options.principal === undefined ? {} : { principal: options.principal };
|
|
29
|
+
export const connectNodeApi = (options = {}) => runFacade(connectDiscoveredNodeApi(options, (descriptor, token) => {
|
|
30
|
+
const client = createNodeApiClient({
|
|
31
|
+
credential: token,
|
|
32
|
+
endpoint: descriptor.endpoint,
|
|
33
|
+
...principalOf(options),
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
client,
|
|
37
|
+
status: (messageId) => Effect.tryPromise({
|
|
38
|
+
catch: (error) => error,
|
|
39
|
+
try: (signal) => client.status({ messageId, signal }),
|
|
40
|
+
}),
|
|
41
|
+
};
|
|
42
|
+
}), options.signal).catch((error) => {
|
|
43
|
+
if (options.signal?.aborted === true) {
|
|
44
|
+
throw new MaiaClientError("cancelled", "The Maia Node API discovery was cancelled.", { cause: error });
|
|
45
|
+
}
|
|
46
|
+
throw discoveryFailure(error);
|
|
47
|
+
});
|
|
48
|
+
const readAttachedCredential = (options) => runFacade(acquireAttachedCredential(), options.signal).catch((error) => {
|
|
49
|
+
throw new MaiaClientError(options.signal?.aborted === true ? "cancelled" : "transport_failure", "The inherited Invocation attachment is invalid or unavailable.", { cause: error });
|
|
50
|
+
});
|
|
51
|
+
const attachedLocalNodeClient = (descriptor, credential) => createNodeApiClient(attachedTransportOptions(descriptor, credential, (read) => () => Effect.runPromise(read)));
|
|
52
|
+
const attachedRequestOptions = (prefix, options) => runFacade(options.messageId === undefined
|
|
53
|
+
? newMessageId(prefix)
|
|
54
|
+
: Effect.succeed(options.messageId)).then((messageId) => ({
|
|
55
|
+
messageId,
|
|
56
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
57
|
+
}));
|
|
58
|
+
const withAttachedLocalNode = (options, operation) => runFacade(requireAttachmentPlatform())
|
|
59
|
+
.then(() => connectNodeApi(options))
|
|
60
|
+
.then((connection) => readAttachedCredential(options).then((credential) => operation(attachedLocalNodeClient(connection.descriptor, credential)).finally(() => {
|
|
61
|
+
credential.fill(0);
|
|
62
|
+
})));
|
|
63
|
+
export const showAttachedCurrentContext = (options = {}) => withAttachedLocalNode(options, (client) => attachedRequestOptions("context_attached", options).then((requestOptions) => client.showCurrentContext({}, requestOptions)));
|
|
64
|
+
export const sendAttachedSessionMessage = (parameters, options = {}) => withAttachedLocalNode(options, (client) => attachedRequestOptions("session_message", options).then((requestOptions) => client.sendSessionMessage(parameters, requestOptions)));
|
|
65
|
+
export const checkAttachedSessionInbox = (parameters, options = {}) => withAttachedLocalNode(options, (client) => attachedRequestOptions("session_inbox_check", options).then((requestOptions) => client.checkSessionInbox(parameters, requestOptions)));
|
|
66
|
+
export const acknowledgeAttachedSessionDelivery = (parameters, options = {}) => withAttachedLocalNode(options, (client) => attachedRequestOptions("session_inbox_ack", options).then((requestOptions) => client.acknowledgeSessionDelivery(parameters, requestOptions)));
|
|
67
|
+
//# sourceMappingURL=local-node.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type LocalNodeStatusResult } from "@maiaos/protocol";
|
|
2
|
+
import type * as Crypto from "effect/Crypto";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import type { LocalNodeEffectClient } from "../client/effect.js";
|
|
5
|
+
import { MaiaClientError } from "../request/index.js";
|
|
6
|
+
export type SessionNodeApiEffectOptions = {
|
|
7
|
+
readonly credential: string;
|
|
8
|
+
readonly origin: string;
|
|
9
|
+
};
|
|
10
|
+
export type SessionNodeApiEffectConnection = {
|
|
11
|
+
readonly client: LocalNodeEffectClient;
|
|
12
|
+
readonly status: LocalNodeStatusResult;
|
|
13
|
+
};
|
|
14
|
+
export declare const connectSessionNodeApiEffect: (options: SessionNodeApiEffectOptions) => Effect.Effect<SessionNodeApiEffectConnection, MaiaClientError, Crypto.Crypto>;
|
|
15
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { NODE_API_OBSERVATION_PATH, NODE_API_OPERATION_PATH, nodeApiEndpointSchema, } from "@maiaos/protocol";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import { MaiaClientError } from "../request/index.js";
|
|
4
|
+
import { newMessageId } from "./discovery.js";
|
|
5
|
+
import { createNodeApiEffectClient } from "./http.js";
|
|
6
|
+
const invalidOrigin = () => new MaiaClientError("transport_failure", "The Maia Node origin of this Session is invalid.");
|
|
7
|
+
const sessionEndpoint = (origin) => Effect.try({
|
|
8
|
+
catch: invalidOrigin,
|
|
9
|
+
try: () => nodeApiEndpointSchema.parse({
|
|
10
|
+
observationPath: NODE_API_OBSERVATION_PATH,
|
|
11
|
+
operationPath: NODE_API_OPERATION_PATH,
|
|
12
|
+
origin,
|
|
13
|
+
transport: "http-websocket",
|
|
14
|
+
}),
|
|
15
|
+
});
|
|
16
|
+
export const connectSessionNodeApiEffect = (options) => Effect.gen(function* () {
|
|
17
|
+
const endpoint = yield* sessionEndpoint(options.origin);
|
|
18
|
+
const client = createNodeApiEffectClient({
|
|
19
|
+
authorizationScheme: "session",
|
|
20
|
+
credential: options.credential,
|
|
21
|
+
endpoint,
|
|
22
|
+
});
|
|
23
|
+
const messageId = yield* newMessageId("discovery");
|
|
24
|
+
const status = yield* client.status({ messageId });
|
|
25
|
+
return { client, status };
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const SSH_OPTIONS: readonly ["-o", "BatchMode=yes", "-o", "ConnectTimeout=15", "-o", "ServerAliveInterval=15", "-o", "ServerAliveCountMax=4", "-o", "ForwardAgent=no", "-o", "ForwardX11=no", "-o", "ClearAllForwardings=yes", "-o", "GSSAPIDelegateCredentials=no", "-o", "PermitLocalCommand=no", "-o", "Tunnel=no", "-o", "ControlMaster=no", "-o", "ControlPath=none", "-o", "SendEnv=-*"];
|
|
2
|
+
export declare const PATH_SEGMENT_PATTERN: RegExp;
|
|
3
|
+
export declare const isPlainAbsolutePath: (path: string) => boolean;
|
|
4
|
+
export declare const shellQuote: (value: string) => string;
|
|
5
|
+
export declare const REMOTE_BOOTSTRAP = "eval \"$(printf %s \"$1\" | base64 -d)\"";
|
|
6
|
+
export declare const encodedScriptBytes: (script: string) => number;
|
|
7
|
+
export declare const bootstrapArguments: (script: string) => readonly string[];
|
|
8
|
+
export declare const remoteCommandWords: (script: string) => readonly string[];
|
|
9
|
+
export declare const sshCommandArguments: (input: {
|
|
10
|
+
readonly compress?: boolean;
|
|
11
|
+
readonly host: string;
|
|
12
|
+
readonly script: string;
|
|
13
|
+
readonly terminal?: boolean;
|
|
14
|
+
}) => readonly string[];
|
|
15
|
+
export declare const bridgeScript: (launcherPath: string) => string;
|
|
16
|
+
//# sourceMappingURL=ssh.d.ts.map
|
package/dist/node/ssh.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { REMOTE_NODE_SSH_HOST_PATTERN } from "@maiaos/protocol";
|
|
3
|
+
export const SSH_OPTIONS = [
|
|
4
|
+
"-o",
|
|
5
|
+
"BatchMode=yes",
|
|
6
|
+
"-o",
|
|
7
|
+
"ConnectTimeout=15",
|
|
8
|
+
"-o",
|
|
9
|
+
"ServerAliveInterval=15",
|
|
10
|
+
"-o",
|
|
11
|
+
"ServerAliveCountMax=4",
|
|
12
|
+
"-o",
|
|
13
|
+
"ForwardAgent=no",
|
|
14
|
+
"-o",
|
|
15
|
+
"ForwardX11=no",
|
|
16
|
+
"-o",
|
|
17
|
+
"ClearAllForwardings=yes",
|
|
18
|
+
"-o",
|
|
19
|
+
"GSSAPIDelegateCredentials=no",
|
|
20
|
+
"-o",
|
|
21
|
+
"PermitLocalCommand=no",
|
|
22
|
+
"-o",
|
|
23
|
+
"Tunnel=no",
|
|
24
|
+
"-o",
|
|
25
|
+
"ControlMaster=no",
|
|
26
|
+
"-o",
|
|
27
|
+
"ControlPath=none",
|
|
28
|
+
"-o",
|
|
29
|
+
"SendEnv=-*",
|
|
30
|
+
];
|
|
31
|
+
export const PATH_SEGMENT_PATTERN = /^(?!\.{1,2}$)[A-Za-z0-9._-]{1,128}$/u;
|
|
32
|
+
const ABSOLUTE_PATH_PATTERN = /^\/[A-Za-z0-9._/-]{1,512}$/u;
|
|
33
|
+
export const isPlainAbsolutePath = (path) => ABSOLUTE_PATH_PATTERN.test(path) &&
|
|
34
|
+
path
|
|
35
|
+
.slice(1)
|
|
36
|
+
.split("/")
|
|
37
|
+
.every((segment) => PATH_SEGMENT_PATTERN.test(segment));
|
|
38
|
+
export const shellQuote = (value) => `'${value.replaceAll("'", String.raw `'\''`)}'`;
|
|
39
|
+
export const REMOTE_BOOTSTRAP = 'eval "$(printf %s "$1" | base64 -d)"';
|
|
40
|
+
const encodeScript = (script) => Buffer.from(script, "utf8").toString("base64");
|
|
41
|
+
export const encodedScriptBytes = (script) => Math.ceil(Buffer.byteLength(script, "utf8") / 3) * 4;
|
|
42
|
+
export const bootstrapArguments = (script) => [
|
|
43
|
+
"-c",
|
|
44
|
+
REMOTE_BOOTSTRAP,
|
|
45
|
+
"maia-remote",
|
|
46
|
+
encodeScript(script),
|
|
47
|
+
];
|
|
48
|
+
export const remoteCommandWords = (script) => [
|
|
49
|
+
"sh",
|
|
50
|
+
"-c",
|
|
51
|
+
shellQuote(REMOTE_BOOTSTRAP),
|
|
52
|
+
"maia-remote",
|
|
53
|
+
encodeScript(script),
|
|
54
|
+
];
|
|
55
|
+
export const sshCommandArguments = (input) => {
|
|
56
|
+
if (!REMOTE_NODE_SSH_HOST_PATTERN.test(input.host)) {
|
|
57
|
+
throw new TypeError("The SSH host is invalid.");
|
|
58
|
+
}
|
|
59
|
+
return [
|
|
60
|
+
...SSH_OPTIONS,
|
|
61
|
+
input.terminal === true ? "-t" : "-T",
|
|
62
|
+
...(input.compress === true ? ["-o", "Compression=yes"] : []),
|
|
63
|
+
"--",
|
|
64
|
+
input.host,
|
|
65
|
+
...remoteCommandWords(input.script),
|
|
66
|
+
];
|
|
67
|
+
};
|
|
68
|
+
export const bridgeScript = (launcherPath) => {
|
|
69
|
+
if (!isPlainAbsolutePath(launcherPath)) {
|
|
70
|
+
throw new TypeError("The launcher path is not a plain absolute path.");
|
|
71
|
+
}
|
|
72
|
+
return `exec ${shellQuote(launcherPath)}`;
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=ssh.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type NodeApiConnectionDescriptor, type NodeApiEndpoint, type NodeApiInvocationAuthentication, type NodeApiObservationFrame, type NodeApiObservationSubscribe, type SessionAttachFrame, type SessionAttachSubscribe } from "@maiaos/protocol";
|
|
2
|
+
import * as Stream from "effect/Stream";
|
|
3
|
+
import { type LocalNodeClient } from "../client/index.js";
|
|
4
|
+
import { MaiaClientError, type MaiaTransport } from "../request/index.js";
|
|
5
|
+
type Fetch = typeof globalThis.fetch;
|
|
6
|
+
type WebSocketEvent = {
|
|
7
|
+
readonly data?: unknown;
|
|
8
|
+
};
|
|
9
|
+
type WebSocketCloseEvent = {
|
|
10
|
+
readonly code?: number;
|
|
11
|
+
readonly reason?: string;
|
|
12
|
+
};
|
|
13
|
+
type WebSocketLike = {
|
|
14
|
+
readonly addEventListener: (type: "close" | "error" | "message" | "open", listener: (event: WebSocketCloseEvent | WebSocketEvent) => void) => void;
|
|
15
|
+
readonly close: (code?: number, reason?: string) => void;
|
|
16
|
+
readonly readyState?: number;
|
|
17
|
+
readonly removeEventListener: (type: "close" | "error" | "message" | "open", listener: (event: WebSocketCloseEvent | WebSocketEvent) => void) => void;
|
|
18
|
+
readonly send: (data: string) => void;
|
|
19
|
+
};
|
|
20
|
+
type WebSocketFactory = (url: string, protocols: readonly string[]) => WebSocketLike;
|
|
21
|
+
export type NodeApiCredential = (() => Promise<string>) | string;
|
|
22
|
+
export type NodeApiTransportOptions = {
|
|
23
|
+
readonly authorizationScheme?: "bearer" | "session";
|
|
24
|
+
readonly credential: NodeApiCredential;
|
|
25
|
+
readonly endpoint: NodeApiEndpoint;
|
|
26
|
+
readonly fetch?: Fetch;
|
|
27
|
+
readonly invocationAuthentication?: NodeApiInvocationAuthentication;
|
|
28
|
+
readonly principal?: "coordinator";
|
|
29
|
+
};
|
|
30
|
+
export type NodeApiConnection = {
|
|
31
|
+
readonly client: LocalNodeClient;
|
|
32
|
+
readonly descriptor: NodeApiConnectionDescriptor;
|
|
33
|
+
};
|
|
34
|
+
export type NodeApiObservationRequest = Omit<NodeApiObservationSubscribe, "authentication">;
|
|
35
|
+
export type NodeApiObservationOptions = {
|
|
36
|
+
readonly credential: NodeApiCredential;
|
|
37
|
+
readonly endpoint: NodeApiEndpoint;
|
|
38
|
+
readonly signal?: AbortSignal;
|
|
39
|
+
readonly subscribe: NodeApiObservationRequest;
|
|
40
|
+
readonly webSocketFactory?: WebSocketFactory;
|
|
41
|
+
};
|
|
42
|
+
export type SessionAttachRequest = Omit<SessionAttachSubscribe, "authentication">;
|
|
43
|
+
export type SessionAttachOptions = Omit<NodeApiObservationOptions, "subscribe"> & {
|
|
44
|
+
readonly request: SessionAttachRequest;
|
|
45
|
+
};
|
|
46
|
+
export declare const createNodeApiTransport: (options: NodeApiTransportOptions) => MaiaTransport;
|
|
47
|
+
export declare const createNodeApiClient: (options: NodeApiTransportOptions) => LocalNodeClient;
|
|
48
|
+
export declare const subscribeNodeApiObservations: (options: NodeApiObservationOptions) => AsyncIterable<NodeApiObservationFrame>;
|
|
49
|
+
export declare const makeSessionAttachStream: (options: SessionAttachOptions) => Stream.Stream<SessionAttachFrame, MaiaClientError>;
|
|
50
|
+
export declare const attachSession: (options: SessionAttachOptions) => AsyncIterable<SessionAttachFrame>;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=transport.d.ts.map
|