@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.
Files changed (198) hide show
  1. package/README.md +177 -0
  2. package/dist/agent-permission/agent-permission.d.ts +9 -0
  3. package/dist/agent-permission/agent-permission.js +5 -0
  4. package/dist/agent-permission/effect.d.ts +4 -0
  5. package/dist/agent-permission/effect.js +34 -0
  6. package/dist/agent-permission/index.d.ts +2 -0
  7. package/dist/agent-permission/index.js +2 -0
  8. package/dist/approval/approval.d.ts +10 -0
  9. package/dist/approval/approval.js +5 -0
  10. package/dist/approval/effect.d.ts +5 -0
  11. package/dist/approval/effect.js +43 -0
  12. package/dist/approval/index.d.ts +2 -0
  13. package/dist/approval/index.js +2 -0
  14. package/dist/call/call.d.ts +26 -0
  15. package/dist/call/call.js +6 -0
  16. package/dist/call/effect.d.ts +5 -0
  17. package/dist/call/effect.js +46 -0
  18. package/dist/call/index.d.ts +2 -0
  19. package/dist/call/index.js +2 -0
  20. package/dist/client/effect.d.ts +8 -0
  21. package/dist/client/effect.js +283 -0
  22. package/dist/client/index.d.ts +2 -0
  23. package/dist/client/index.js +2 -0
  24. package/dist/client/local-node-client.d.ts +100 -0
  25. package/dist/client/local-node-client.js +4 -0
  26. package/dist/connection/connection.d.ts +19 -0
  27. package/dist/connection/connection.js +5 -0
  28. package/dist/connection/effect.d.ts +5 -0
  29. package/dist/connection/effect.js +119 -0
  30. package/dist/connection/index.d.ts +2 -0
  31. package/dist/connection/index.js +2 -0
  32. package/dist/container/container.d.ts +14 -0
  33. package/dist/container/container.js +5 -0
  34. package/dist/container/effect.d.ts +4 -0
  35. package/dist/container/effect.js +90 -0
  36. package/dist/container/index.d.ts +2 -0
  37. package/dist/container/index.js +2 -0
  38. package/dist/discovery/discovery.d.ts +11 -0
  39. package/dist/discovery/discovery.js +5 -0
  40. package/dist/discovery/effect.d.ts +5 -0
  41. package/dist/discovery/effect.js +44 -0
  42. package/dist/discovery/index.d.ts +2 -0
  43. package/dist/discovery/index.js +2 -0
  44. package/dist/execution/effect.d.ts +4 -0
  45. package/dist/execution/effect.js +8 -0
  46. package/dist/execution/index.d.ts +2 -0
  47. package/dist/execution/index.js +2 -0
  48. package/dist/execution/relocation.d.ts +10 -0
  49. package/dist/execution/relocation.js +4 -0
  50. package/dist/feature-bindings/feature-bindings.d.ts +10 -0
  51. package/dist/feature-bindings/feature-bindings.js +2 -0
  52. package/dist/feature-bindings/index.d.ts +2 -0
  53. package/dist/feature-bindings/index.js +2 -0
  54. package/dist/hold/effect.d.ts +5 -0
  55. package/dist/hold/effect.js +61 -0
  56. package/dist/hold/hold.d.ts +12 -0
  57. package/dist/hold/hold.js +5 -0
  58. package/dist/hold/index.d.ts +2 -0
  59. package/dist/hold/index.js +2 -0
  60. package/dist/index.d.ts +26 -0
  61. package/dist/index.js +21 -0
  62. package/dist/interaction/effect.d.ts +5 -0
  63. package/dist/interaction/effect.js +79 -0
  64. package/dist/interaction/index.d.ts +2 -0
  65. package/dist/interaction/index.js +2 -0
  66. package/dist/interaction/interaction.d.ts +12 -0
  67. package/dist/interaction/interaction.js +5 -0
  68. package/dist/node/attach.d.ts +11 -0
  69. package/dist/node/attach.js +33 -0
  70. package/dist/node/bridge-frame.d.ts +18 -0
  71. package/dist/node/bridge-frame.js +67 -0
  72. package/dist/node/bridge.d.ts +31 -0
  73. package/dist/node/bridge.js +148 -0
  74. package/dist/node/discovery.d.ts +187 -0
  75. package/dist/node/discovery.js +408 -0
  76. package/dist/node/effect.d.ts +9 -0
  77. package/dist/node/effect.js +9 -0
  78. package/dist/node/fetch.d.ts +2 -0
  79. package/dist/node/fetch.js +2 -0
  80. package/dist/node/http.d.ts +27 -0
  81. package/dist/node/http.js +258 -0
  82. package/dist/node/index.d.ts +3 -0
  83. package/dist/node/index.js +3 -0
  84. package/dist/node/local-node.d.ts +26 -0
  85. package/dist/node/local-node.js +67 -0
  86. package/dist/node/session.d.ts +15 -0
  87. package/dist/node/session.js +27 -0
  88. package/dist/node/ssh.d.ts +16 -0
  89. package/dist/node/ssh.js +74 -0
  90. package/dist/node/transport.d.ts +52 -0
  91. package/dist/node/transport.js +211 -0
  92. package/dist/node-changes/effect.d.ts +11 -0
  93. package/dist/node-changes/effect.js +61 -0
  94. package/dist/node-changes/index.d.ts +2 -0
  95. package/dist/node-changes/index.js +2 -0
  96. package/dist/node-changes/node-changes.d.ts +21 -0
  97. package/dist/node-changes/node-changes.js +23 -0
  98. package/dist/port-lease/effect.d.ts +5 -0
  99. package/dist/port-lease/effect.js +53 -0
  100. package/dist/port-lease/index.d.ts +2 -0
  101. package/dist/port-lease/index.js +2 -0
  102. package/dist/port-lease/port-lease.d.ts +11 -0
  103. package/dist/port-lease/port-lease.js +5 -0
  104. package/dist/presentation/client.d.ts +10 -0
  105. package/dist/presentation/client.js +4 -0
  106. package/dist/presentation/effect.d.ts +5 -0
  107. package/dist/presentation/effect.js +30 -0
  108. package/dist/presentation/index.d.ts +5 -0
  109. package/dist/presentation/index.js +3 -0
  110. package/dist/presentation/project-list.d.ts +7 -0
  111. package/dist/presentation/project-list.js +24 -0
  112. package/dist/presentation/session-list.d.ts +7 -0
  113. package/dist/presentation/session-list.js +32 -0
  114. package/dist/project-guard/effect.d.ts +5 -0
  115. package/dist/project-guard/effect.js +39 -0
  116. package/dist/project-guard/index.d.ts +2 -0
  117. package/dist/project-guard/index.js +2 -0
  118. package/dist/project-guard/project-guard.d.ts +10 -0
  119. package/dist/project-guard/project-guard.js +5 -0
  120. package/dist/project-workspace/effect.d.ts +5 -0
  121. package/dist/project-workspace/effect.js +124 -0
  122. package/dist/project-workspace/index.d.ts +2 -0
  123. package/dist/project-workspace/index.js +2 -0
  124. package/dist/project-workspace/project-workspace.d.ts +23 -0
  125. package/dist/project-workspace/project-workspace.js +4 -0
  126. package/dist/provider-pool/effect.d.ts +4 -0
  127. package/dist/provider-pool/effect.js +5 -0
  128. package/dist/provider-pool/index.d.ts +2 -0
  129. package/dist/provider-pool/index.js +2 -0
  130. package/dist/provider-pool/provider-pool.d.ts +7 -0
  131. package/dist/provider-pool/provider-pool.js +4 -0
  132. package/dist/remote-node/effect.d.ts +4 -0
  133. package/dist/remote-node/effect.js +57 -0
  134. package/dist/remote-node/index.d.ts +2 -0
  135. package/dist/remote-node/index.js +2 -0
  136. package/dist/remote-node/remote-node.d.ts +12 -0
  137. package/dist/remote-node/remote-node.js +5 -0
  138. package/dist/request/classify.d.ts +15 -0
  139. package/dist/request/classify.js +96 -0
  140. package/dist/request/client-error.d.ts +10 -0
  141. package/dist/request/client-error.js +11 -0
  142. package/dist/request/effect.d.ts +22 -0
  143. package/dist/request/effect.js +104 -0
  144. package/dist/request/envelope-schema.d.ts +2 -0
  145. package/dist/request/envelope-schema.js +2 -0
  146. package/dist/request/index.d.ts +5 -0
  147. package/dist/request/index.js +4 -0
  148. package/dist/request/maia-client.d.ts +21 -0
  149. package/dist/request/maia-client.js +9 -0
  150. package/dist/request/options.d.ts +9 -0
  151. package/dist/request/options.js +2 -0
  152. package/dist/run-ledger/effect.d.ts +5 -0
  153. package/dist/run-ledger/effect.js +72 -0
  154. package/dist/run-ledger/index.d.ts +2 -0
  155. package/dist/run-ledger/index.js +2 -0
  156. package/dist/run-ledger/run-ledger.d.ts +12 -0
  157. package/dist/run-ledger/run-ledger.js +2 -0
  158. package/dist/session/effect.d.ts +4 -0
  159. package/dist/session/effect.js +7 -0
  160. package/dist/session/index.d.ts +2 -0
  161. package/dist/session/index.js +2 -0
  162. package/dist/session/mailbox.d.ts +9 -0
  163. package/dist/session/mailbox.js +4 -0
  164. package/dist/session-creation/effect.d.ts +25 -0
  165. package/dist/session-creation/effect.js +269 -0
  166. package/dist/session-creation/index.d.ts +3 -0
  167. package/dist/session-creation/index.js +3 -0
  168. package/dist/session-creation/session-creation.d.ts +18 -0
  169. package/dist/session-creation/session-creation.js +24 -0
  170. package/dist/session-creation/tasks.d.ts +69 -0
  171. package/dist/session-creation/tasks.js +37 -0
  172. package/dist/session-view/index.d.ts +2 -0
  173. package/dist/session-view/index.js +2 -0
  174. package/dist/session-view/view.d.ts +42 -0
  175. package/dist/session-view/view.js +137 -0
  176. package/dist/stream/effect.d.ts +29 -0
  177. package/dist/stream/effect.js +77 -0
  178. package/dist/stream/index.d.ts +2 -0
  179. package/dist/stream/index.js +2 -0
  180. package/dist/stream/stream.d.ts +9 -0
  181. package/dist/stream/stream.js +2 -0
  182. package/dist/voice/effect.d.ts +7 -0
  183. package/dist/voice/effect.js +71 -0
  184. package/dist/voice/index.d.ts +4 -0
  185. package/dist/voice/index.js +3 -0
  186. package/dist/voice/managed-turn.d.ts +9 -0
  187. package/dist/voice/managed-turn.js +4 -0
  188. package/dist/voice/orchestrator-contract.d.ts +5 -0
  189. package/dist/voice/orchestrator-contract.js +4 -0
  190. package/dist/voice/orchestrator.d.ts +25 -0
  191. package/dist/voice/orchestrator.js +169 -0
  192. package/dist/voice/pi-relay-contract.d.ts +4 -0
  193. package/dist/voice/pi-relay-contract.js +2 -0
  194. package/dist/voice/pi-relay.d.ts +12 -0
  195. package/dist/voice/pi-relay.js +9 -0
  196. package/dist/voice/wire-schema.d.ts +215 -0
  197. package/dist/voice/wire-schema.js +16 -0
  198. package/package.json +84 -0
@@ -0,0 +1,12 @@
1
+ import type { InteractionCancelParameters, InteractionCancelResult, InteractionCreateParameters, InteractionCreateResult, InteractionListParameters, InteractionListResult, InteractionRespondParameters, InteractionRespondResult, InteractionShowParameters, InteractionShowResult } from "@maiaos/protocol";
2
+ import type { LocalNodeRequester, LocalNodeRequestOptions } from "../request/index.js";
3
+ export type InteractionClient = {
4
+ readonly cancelInteraction: (parameters: InteractionCancelParameters, options: LocalNodeRequestOptions) => Promise<InteractionCancelResult>;
5
+ readonly createInteraction: (parameters: InteractionCreateParameters, options: LocalNodeRequestOptions) => Promise<InteractionCreateResult>;
6
+ readonly listInteractions: (parameters: InteractionListParameters, options: LocalNodeRequestOptions) => Promise<InteractionListResult>;
7
+ readonly respondToInteraction: (parameters: InteractionRespondParameters, options: LocalNodeRequestOptions) => Promise<InteractionRespondResult>;
8
+ readonly showInteraction: (parameters: InteractionShowParameters, options: LocalNodeRequestOptions) => Promise<InteractionShowResult>;
9
+ };
10
+ export declare const makeInteractionClient: (request: LocalNodeRequester) => InteractionClient;
11
+ export { type Interaction, INTERACTION_EXPIRED_ERROR_CODE, type InteractionAnswer, interactionAnswerSchema, type InteractionCancelParameters, interactionCancelParametersSchema, type InteractionCancelResult, interactionCancelResultSchema, type InteractionCreateParameters, interactionCreateParametersSchema, type InteractionCreateResult, interactionCreateResultSchema, type InteractionDetail, interactionDetailSchema, type InteractionListParameters, interactionListParametersSchema, type InteractionListResult, interactionListResultSchema, type InteractionRespondParameters, interactionRespondParametersSchema, type InteractionRespondResult, interactionRespondResultSchema, interactionSchema, type InteractionShowParameters, interactionShowParametersSchema, type InteractionShowResult, interactionShowResultSchema, MAX_INTERACTION_RESULT_BYTES, } from "@maiaos/protocol";
12
+ //# sourceMappingURL=interaction.d.ts.map
@@ -0,0 +1,5 @@
1
+ import { fromPromiseRequester, toPromiseClient } from "../request/effect.js";
2
+ import { makeInteractionOperations } from "./effect.js";
3
+ export const makeInteractionClient = (request) => toPromiseClient(makeInteractionOperations(fromPromiseRequester(request)));
4
+ export { INTERACTION_EXPIRED_ERROR_CODE, interactionAnswerSchema, interactionCancelParametersSchema, interactionCancelResultSchema, interactionCreateParametersSchema, interactionCreateResultSchema, interactionDetailSchema, interactionListParametersSchema, interactionListResultSchema, interactionRespondParametersSchema, interactionRespondResultSchema, interactionSchema, interactionShowParametersSchema, interactionShowResultSchema, MAX_INTERACTION_RESULT_BYTES, } from "@maiaos/protocol";
5
+ //# sourceMappingURL=interaction.js.map
@@ -0,0 +1,11 @@
1
+ import { type SessionAttachFrame } from "@maiaos/protocol";
2
+ import type * as Crypto from "effect/Crypto";
3
+ import * as Stream from "effect/Stream";
4
+ import type { MaiaClientError } from "../request/index.js";
5
+ import { type NodeApiEffectDiscoveryOptions } from "./discovery.js";
6
+ import { type SessionAttachRequest } from "./transport.js";
7
+ export type SessionAttachEffectOptions = NodeApiEffectDiscoveryOptions & {
8
+ readonly messageId?: string;
9
+ };
10
+ export declare const attachSessionEffect: (parameters: SessionAttachRequest["parameters"], options?: SessionAttachEffectOptions) => Stream.Stream<SessionAttachFrame, MaiaClientError, Crypto.Crypto>;
11
+ //# sourceMappingURL=attach.d.ts.map
@@ -0,0 +1,33 @@
1
+ import { MAIA_PROTOCOL_VERSION, NODE_API_SCHEMA_VERSION, } from "@maiaos/protocol";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Stream from "effect/Stream";
4
+ import { connectDiscoveredNodeApi, discoveryFailure, newMessageId, } from "./discovery.js";
5
+ import { createNodeApiEffectClient } from "./http.js";
6
+ import { makeSessionAttachStream, } from "./transport.js";
7
+ const discoverAttachment = (options) => connectDiscoveredNodeApi(options, (descriptor, token) => {
8
+ const client = createNodeApiEffectClient({
9
+ credential: token,
10
+ endpoint: descriptor.endpoint,
11
+ });
12
+ return {
13
+ client: { token },
14
+ status: (messageId) => client.status({ messageId }),
15
+ };
16
+ }).pipe(Effect.mapError(discoveryFailure));
17
+ export const attachSessionEffect = (parameters, options = {}) => Stream.unwrap(Effect.gen(function* () {
18
+ const connection = yield* discoverAttachment(options);
19
+ const messageId = options.messageId ?? (yield* newMessageId("attach"));
20
+ return makeSessionAttachStream({
21
+ credential: connection.client.token,
22
+ endpoint: connection.descriptor.endpoint,
23
+ request: {
24
+ kind: "subscribe",
25
+ messageId,
26
+ operationId: "session.attach",
27
+ parameters,
28
+ protocolVersion: MAIA_PROTOCOL_VERSION,
29
+ schemaVersion: NODE_API_SCHEMA_VERSION,
30
+ },
31
+ });
32
+ }));
33
+ //# sourceMappingURL=attach.js.map
@@ -0,0 +1,18 @@
1
+ import { type BridgeRequestFrame, type BridgeServerFrame, type ProtocolError } from "@maiaos/protocol";
2
+ import * as Stream from "effect/Stream";
3
+ export declare const decodeRequestFrame: (line: string) => BridgeRequestFrame | undefined;
4
+ export declare const decodeServerFrame: (line: string) => BridgeServerFrame | undefined;
5
+ export declare const failureRemoteError: (frame: Extract<BridgeServerFrame, {
6
+ readonly type: "failure";
7
+ }>) => ProtocolError | undefined;
8
+ export declare const encodeFrame: (frame: BridgeRequestFrame | BridgeServerFrame) => string;
9
+ export type FrameLine = {
10
+ readonly _tag: "Invalid";
11
+ } | {
12
+ readonly _tag: "Line";
13
+ readonly text: string;
14
+ } | {
15
+ readonly _tag: "Overflow";
16
+ };
17
+ export declare const splitFrameLines: (maximumBytes: number) => <TError, TContext>(stream: Stream.Stream<Uint8Array, TError, TContext>) => Stream.Stream<readonly FrameLine[], TError, TContext>;
18
+ //# sourceMappingURL=bridge-frame.d.ts.map
@@ -0,0 +1,67 @@
1
+ import { Buffer } from "node:buffer";
2
+ import { bridgeRequestFrameSchema, bridgeServerFrameSchema, protocolErrorSchema, } from "@maiaos/protocol";
3
+ import * as Option from "effect/Option";
4
+ import * as Schema from "effect/Schema";
5
+ import * as Stream from "effect/Stream";
6
+ const decodeJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown));
7
+ const parseJson = (line) => Option.getOrUndefined(decodeJson(line));
8
+ export const decodeRequestFrame = (line) => {
9
+ const parsed = bridgeRequestFrameSchema.safeParse(parseJson(line));
10
+ return parsed.success ? parsed.data : undefined;
11
+ };
12
+ export const decodeServerFrame = (line) => {
13
+ const parsed = bridgeServerFrameSchema.safeParse(parseJson(line));
14
+ return parsed.success ? parsed.data : undefined;
15
+ };
16
+ export const failureRemoteError = (frame) => {
17
+ const parsed = protocolErrorSchema.safeParse(frame.remoteError);
18
+ return parsed.success ? parsed.data : undefined;
19
+ };
20
+ export const encodeFrame = (frame) => `${JSON.stringify(frame)}\n`;
21
+ const NEWLINE = 10;
22
+ const STOPPED = { bytes: 0, chunks: [], stopped: true };
23
+ const EMPTY = { bytes: 0, chunks: [], stopped: false };
24
+ const utf8 = new TextDecoder("utf-8", { fatal: true });
25
+ const decodeLine = (chunks) => {
26
+ try {
27
+ return { _tag: "Line", text: utf8.decode(Buffer.concat(chunks)) };
28
+ }
29
+ catch {
30
+ return { _tag: "Invalid" };
31
+ }
32
+ };
33
+ const piecesOf = (chunk, state) => Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength)
34
+ .toString("latin1")
35
+ .split(String.fromCodePoint(NEWLINE))
36
+ .map((segment, index) => ({
37
+ bytes: Buffer.from(segment, "latin1"),
38
+ prefix: index === 0 ? state : EMPTY,
39
+ }));
40
+ const tooLong = (piece, maximumBytes) => piece.prefix.bytes + piece.bytes.byteLength > maximumBytes;
41
+ const pending = (piece) => ({
42
+ bytes: piece.prefix.bytes + piece.bytes.byteLength,
43
+ chunks: piece.bytes.byteLength === 0
44
+ ? piece.prefix.chunks
45
+ : [...piece.prefix.chunks, piece.bytes],
46
+ stopped: false,
47
+ });
48
+ const splitChunk = (state, chunk, maximumBytes) => {
49
+ const pieces = piecesOf(chunk, state);
50
+ const overflow = pieces.findIndex((piece) => tooLong(piece, maximumBytes));
51
+ const complete = pieces.slice(0, -1);
52
+ const lines = complete
53
+ .slice(0, overflow < 0 ? complete.length : overflow)
54
+ .map((piece) => decodeLine([...piece.prefix.chunks, piece.bytes]));
55
+ if (overflow >= 0)
56
+ return [STOPPED, [...lines, { _tag: "Overflow" }]];
57
+ const remainder = pieces.at(-1) ?? { bytes: new Uint8Array(), prefix: state };
58
+ return [pending(remainder), lines];
59
+ };
60
+ const batch = (state, chunk, maximumBytes) => {
61
+ if (state.stopped)
62
+ return [state, []];
63
+ const [next, lines] = splitChunk(state, chunk, maximumBytes);
64
+ return [next, lines.length === 0 ? [] : [lines]];
65
+ };
66
+ export const splitFrameLines = (maximumBytes) => (stream) => stream.pipe(Stream.mapAccum(() => EMPTY, (state, chunk) => batch(state, chunk, maximumBytes)));
67
+ //# sourceMappingURL=bridge-frame.js.map
@@ -0,0 +1,31 @@
1
+ import { type LocalNodeStatusResult } from "@maiaos/protocol";
2
+ import type * as Cause from "effect/Cause";
3
+ import * as Duration from "effect/Duration";
4
+ import * as Effect from "effect/Effect";
5
+ import type { ChildProcessHandle } from "effect/process/ChildProcessSpawner";
6
+ import type * as Scope from "effect/Scope";
7
+ import { type LocalNodeEffectClient } from "../client/effect.js";
8
+ import { type MaiaTransport } from "../request/index.js";
9
+ declare const BridgeError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
10
+ readonly _tag: "BridgeError";
11
+ } & Readonly<A>;
12
+ export declare class BridgeError extends BridgeError_base<{
13
+ readonly message: string;
14
+ readonly reason: "closed" | "deadline_exceeded" | "node_unavailable" | "protocol_invalid";
15
+ }> {
16
+ }
17
+ export type BridgeHello = {
18
+ readonly status: LocalNodeStatusResult;
19
+ readonly version: string;
20
+ };
21
+ export type NodeBridge = {
22
+ readonly client: LocalNodeEffectClient;
23
+ readonly closed: Effect.Effect<boolean>;
24
+ readonly hello: BridgeHello;
25
+ readonly transport: MaiaTransport;
26
+ };
27
+ export declare const openNodeBridge: (handle: ChildProcessHandle, options?: {
28
+ readonly helloDeadline?: Duration.Input;
29
+ }) => Effect.Effect<NodeBridge, BridgeError, Scope.Scope>;
30
+ export {};
31
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1,148 @@
1
+ import { localNodeOperationErrorCodeSchema, localNodeStatusResultSchema, MAX_BRIDGE_FRAME_BYTES, MAX_BRIDGE_IN_FLIGHT, } from "@maiaos/protocol";
2
+ import * as Data from "effect/Data";
3
+ import * as Deferred from "effect/Deferred";
4
+ import * as Duration from "effect/Duration";
5
+ import * as Effect from "effect/Effect";
6
+ import * as Queue from "effect/Queue";
7
+ import * as Stream from "effect/Stream";
8
+ import { makeLocalNodeEffectClient, } from "../client/effect.js";
9
+ import { makeLocalNodeEffectRequester, } from "../request/effect.js";
10
+ import { MaiaClientError, } from "../request/index.js";
11
+ import { decodeServerFrame, encodeFrame, failureRemoteError, splitFrameLines, } from "./bridge-frame.js";
12
+ const DEFAULT_HELLO_DEADLINE = Duration.seconds(20);
13
+ const REQUEST_DEADLINE = Duration.seconds(15);
14
+ export class BridgeError extends Data.TaggedError("BridgeError") {
15
+ }
16
+ const BASE_CLIENT_CODES = new Set([
17
+ "cancelled",
18
+ "correlation_mismatch",
19
+ "invalid_request",
20
+ "invalid_response",
21
+ "remote_error",
22
+ "transport_failure",
23
+ ]);
24
+ const isClientCode = (code) => BASE_CLIENT_CODES.has(code) ||
25
+ localNodeOperationErrorCodeSchema.safeParse(code).success;
26
+ const clientError = (frame) => {
27
+ const remote = failureRemoteError(frame);
28
+ return new MaiaClientError(isClientCode(frame.code) ? frame.code : "transport_failure", frame.message, remote === undefined ? undefined : { remoteError: remote });
29
+ };
30
+ const outcomeUnknown = () => new MaiaClientError("outcome_unknown", "The bridged request outcome is unknown.");
31
+ const protocolInvalid = (message) => new BridgeError({ message, reason: "protocol_invalid" });
32
+ const acceptHello = (state, frame) => {
33
+ if (frame.type === "unavailable") {
34
+ return Deferred.fail(state.hello, new BridgeError({ message: frame.message, reason: "node_unavailable" }));
35
+ }
36
+ const status = frame.type === "ready"
37
+ ? localNodeStatusResultSchema.safeParse(frame.status)
38
+ : undefined;
39
+ return status?.success === true && frame.type === "ready"
40
+ ? Deferred.succeed(state.hello, {
41
+ status: status.data,
42
+ version: frame.version,
43
+ })
44
+ : Deferred.fail(state.hello, protocolInvalid("The bridge greeted without a valid node.status."));
45
+ };
46
+ const settle = (state, frame) => {
47
+ if (frame.type === "response") {
48
+ const deferred = state.pending.get(String(frame.envelope.correlationId));
49
+ return deferred === undefined
50
+ ? Effect.void
51
+ : Deferred.succeed(deferred, frame.envelope);
52
+ }
53
+ if (frame.type === "failure") {
54
+ const deferred = state.pending.get(frame.messageId);
55
+ return deferred === undefined
56
+ ? Effect.void
57
+ : Deferred.fail(deferred, clientError(frame));
58
+ }
59
+ return Effect.fail(protocolInvalid("The bridge greeted twice."));
60
+ };
61
+ const onLine = (state) => (line) => {
62
+ const frame = line._tag === "Line" ? decodeServerFrame(line.text) : undefined;
63
+ if (frame === undefined) {
64
+ return Effect.fail(protocolInvalid("The bridge sent an invalid frame."));
65
+ }
66
+ return Deferred.isDone(state.hello).pipe(Effect.flatMap((greeted) => greeted ? settle(state, frame) : acceptHello(state, frame)));
67
+ };
68
+ const close = (state) => Effect.suspend(() => {
69
+ state.closed = true;
70
+ const waiting = [...state.pending.values()];
71
+ state.pending.clear();
72
+ return Effect.all([
73
+ Deferred.fail(state.hello, new BridgeError({
74
+ message: "The bridge closed before it greeted.",
75
+ reason: "closed",
76
+ })),
77
+ ...waiting.map((deferred) => Deferred.fail(deferred, outcomeUnknown())),
78
+ ], { discard: true });
79
+ });
80
+ const readFrames = (state, handle) => handle.stdout.pipe(splitFrameLines(MAX_BRIDGE_FRAME_BYTES), Stream.runForEach((lines) => Effect.forEach(lines, onLine(state), { discard: true })), Effect.ignore, Effect.ensuring(close(state)));
81
+ const admissionFailure = (state, messageId) => {
82
+ if (state.closed) {
83
+ return new MaiaClientError("transport_failure", "The Maia Node bridge is closed.");
84
+ }
85
+ if (state.pending.has(messageId)) {
86
+ return new MaiaClientError("invalid_request", "A bridged request with this message ID is already in flight.");
87
+ }
88
+ return state.pending.size >= MAX_BRIDGE_IN_FLIGHT
89
+ ? new MaiaClientError("saturated", "The Maia Node bridge reached its concurrency limit.")
90
+ : undefined;
91
+ };
92
+ const notSent = () => new MaiaClientError("transport_failure", "The Maia Node bridge closed before the request was sent.");
93
+ const dispatch = (state, envelope) => Effect.gen(function* () {
94
+ const deferred = yield* Deferred.make();
95
+ state.pending.set(envelope.messageId, deferred);
96
+ const sent = yield* Queue.offer(state.outgoing, encodeFrame({ envelope: { ...envelope }, type: "request" }));
97
+ return sent
98
+ ? yield* Deferred.await(deferred)
99
+ : yield* Effect.fail(notSent());
100
+ }).pipe(Effect.timeoutOrElse({
101
+ duration: REQUEST_DEADLINE,
102
+ orElse: () => Effect.fail(outcomeUnknown()),
103
+ }), Effect.ensuring(Effect.sync(() => state.pending.delete(envelope.messageId))));
104
+ const request = (state, envelope) => Effect.suspend(() => {
105
+ const refused = admissionFailure(state, envelope.messageId);
106
+ return refused === undefined
107
+ ? dispatch(state, envelope)
108
+ : Effect.fail(refused);
109
+ });
110
+ const startStreams = (state, handle) => Effect.all([
111
+ Effect.addFinalizer(() => Queue.end(state.outgoing)),
112
+ Stream.fromQueue(state.outgoing).pipe(Stream.encodeText, Stream.run(handle.stdin), Effect.ignore, Effect.ensuring(Queue.shutdown(state.outgoing)), Effect.forkScoped),
113
+ Effect.forkScoped(readFrames(state, handle)),
114
+ ], { discard: true });
115
+ const awaitHello = (state, deadline) => Deferred.await(state.hello).pipe(Effect.timeoutOrElse({
116
+ duration: deadline,
117
+ orElse: () => Effect.fail(new BridgeError({
118
+ message: "The bridge did not greet in time.",
119
+ reason: "deadline_exceeded",
120
+ })),
121
+ }));
122
+ const transportFor = (state) => ({
123
+ request: (envelope, requestOptions) => Effect.runPromise(request(state, envelope), {
124
+ ...(requestOptions?.signal === undefined
125
+ ? {}
126
+ : { signal: requestOptions.signal }),
127
+ }),
128
+ });
129
+ export const openNodeBridge = (handle, options = {}) => Effect.gen(function* () {
130
+ const state = {
131
+ closed: false,
132
+ hello: yield* Deferred.make(),
133
+ outgoing: yield* Queue.bounded(MAX_BRIDGE_IN_FLIGHT * 2),
134
+ pending: new Map(),
135
+ };
136
+ yield* startStreams(state, handle);
137
+ const hello = yield* awaitHello(state, options.helloDeadline ?? DEFAULT_HELLO_DEADLINE);
138
+ const effectTransport = {
139
+ request: (envelope) => request(state, envelope),
140
+ };
141
+ return {
142
+ client: makeLocalNodeEffectClient(makeLocalNodeEffectRequester(effectTransport)),
143
+ closed: Effect.sync(() => state.closed),
144
+ hello,
145
+ transport: transportFor(state),
146
+ };
147
+ });
148
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1,187 @@
1
+ import { type InvocationContextShowResult, type LocalNodeStatusResult, type NodeApiConnectionDescriptor, type SessionInboxAckParameters, type SessionInboxAckResult, type SessionInboxCheckParameters, type SessionInboxCheckResult, type SessionMessageSendParameters, type SessionMessageSendResult } from "@maiaos/protocol";
2
+ import * 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
+ import type { NodeApiDiscoveryOptions } from "./local-node.js";
7
+ type LocalNodeTransportErrorReason = "credential_invalid" | "deadline_exceeded" | "discovery_invalid" | "endpoint_invalid" | "outcome_unknown" | "saturated" | "transport_failed";
8
+ declare const LocalNodeTransportError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
9
+ readonly _tag: "LocalNodeTransportError";
10
+ } & Readonly<A>;
11
+ declare class LocalNodeTransportError extends LocalNodeTransportError_base<{
12
+ readonly message: string;
13
+ readonly reason: LocalNodeTransportErrorReason;
14
+ }> {
15
+ }
16
+ export type DiscoveredNodeApiClient<TClient> = {
17
+ readonly client: TClient;
18
+ readonly status: (messageId: string) => Effect.Effect<LocalNodeStatusResult, unknown>;
19
+ };
20
+ export declare const newMessageId: (prefix: string) => Effect.Effect<string, never, Crypto.Crypto>;
21
+ export declare const connectDiscoveredNodeApi: <TClient>(options: NodeApiDiscoveryOptions, open: (descriptor: NodeApiConnectionDescriptor, token: string) => DiscoveredNodeApiClient<TClient>) => Effect.Effect<{
22
+ client: TClient;
23
+ descriptor: {
24
+ readonly instanceId: string;
25
+ readonly pid: number;
26
+ readonly profile: string;
27
+ readonly startedAt: string;
28
+ readonly credentialPath: string;
29
+ readonly descriptorVersion: 1;
30
+ readonly endpoint: {
31
+ readonly observationPath: "/api/v1/observations";
32
+ readonly operationPath: "/api/v1/operations";
33
+ readonly origin: string;
34
+ readonly transport: "http-websocket";
35
+ };
36
+ readonly kind: "maia.node-api.connection";
37
+ readonly lifecycle: "ready";
38
+ readonly lifecycleOwner: "desktop";
39
+ readonly protocolVersion: "maia.protocol/v1alpha1";
40
+ readonly schemaVersion: "maia.node-api/v1";
41
+ };
42
+ status: {
43
+ readonly instanceId: string;
44
+ readonly lifecycle: "draining" | "failed" | "ready" | "starting" | "stopped";
45
+ readonly pid: number;
46
+ readonly profile: string;
47
+ readonly startedAt: string;
48
+ readonly method: "node.status";
49
+ readonly processResources: {
50
+ readonly activeTrees: number;
51
+ readonly admission: {
52
+ readonly availableTrees: number;
53
+ readonly capacity: number;
54
+ readonly queuedSpawns: 0;
55
+ readonly state: "available" | "degraded" | "pressured" | "saturated" | "unavailable";
56
+ readonly usedTrees: number;
57
+ };
58
+ readonly capability: {
59
+ readonly hardLimitEnforcement: "enforced";
60
+ readonly metricSampling: "host_sampled";
61
+ readonly mode: "hard_containment";
62
+ readonly observedPressureTermination: "disabled";
63
+ readonly releaseQualified: false;
64
+ readonly sourceCandidate: true;
65
+ } | {
66
+ readonly hardLimitEnforcement: "unavailable";
67
+ readonly metricSampling: "host_sampled";
68
+ readonly mode: "macos_cooperative";
69
+ readonly observedPressureTermination: "disabled";
70
+ readonly releaseQualified: false;
71
+ readonly sourceCandidate: true;
72
+ } | {
73
+ readonly hardLimitEnforcement: "unavailable";
74
+ readonly metricSampling: "unavailable";
75
+ readonly mode: "unavailable";
76
+ readonly observedPressureTermination: "disabled";
77
+ readonly releaseQualified: false;
78
+ readonly sourceCandidate: false;
79
+ };
80
+ readonly cleanupUnknownTrees: number;
81
+ readonly fencedTrees: number;
82
+ readonly nextStep: "close_idle_terminal" | "inspect_cleanup_unknown" | "inspect_observed_pressure" | "none" | "verify_native_host";
83
+ readonly observations: {
84
+ readonly cpuTimeMilliseconds: {
85
+ readonly availableTrees: number;
86
+ readonly budget: "declared_per_tree_limit" | "unavailable_not_declared";
87
+ readonly maximumValue?: number | undefined;
88
+ readonly state: "available" | "partial" | "unavailable";
89
+ readonly unavailableTrees: number;
90
+ readonly warningTrees: number;
91
+ };
92
+ readonly fileDescriptorCount: {
93
+ readonly availableTrees: number;
94
+ readonly budget: "declared_per_tree_limit" | "unavailable_not_declared";
95
+ readonly maximumValue?: number | undefined;
96
+ readonly state: "available" | "partial" | "unavailable";
97
+ readonly unavailableTrees: number;
98
+ readonly warningTrees: number;
99
+ };
100
+ readonly ioReadBytes: {
101
+ readonly availableTrees: number;
102
+ readonly budget: "declared_per_tree_limit" | "unavailable_not_declared";
103
+ readonly maximumValue?: number | undefined;
104
+ readonly state: "available" | "partial" | "unavailable";
105
+ readonly unavailableTrees: number;
106
+ readonly warningTrees: number;
107
+ };
108
+ readonly ioWriteBytes: {
109
+ readonly availableTrees: number;
110
+ readonly budget: "declared_per_tree_limit" | "unavailable_not_declared";
111
+ readonly maximumValue?: number | undefined;
112
+ readonly state: "available" | "partial" | "unavailable";
113
+ readonly unavailableTrees: number;
114
+ readonly warningTrees: number;
115
+ };
116
+ readonly observedPeakRssBytes: {
117
+ readonly availableTrees: number;
118
+ readonly budget: "declared_per_tree_limit" | "unavailable_not_declared";
119
+ readonly maximumValue?: number | undefined;
120
+ readonly state: "available" | "partial" | "unavailable";
121
+ readonly unavailableTrees: number;
122
+ readonly warningTrees: number;
123
+ };
124
+ readonly processCount: {
125
+ readonly availableTrees: number;
126
+ readonly budget: "declared_per_tree_limit" | "unavailable_not_declared";
127
+ readonly maximumValue?: number | undefined;
128
+ readonly state: "available" | "partial" | "unavailable";
129
+ readonly unavailableTrees: number;
130
+ readonly warningTrees: number;
131
+ };
132
+ readonly rssBytes: {
133
+ readonly availableTrees: number;
134
+ readonly budget: "declared_per_tree_limit" | "unavailable_not_declared";
135
+ readonly maximumValue?: number | undefined;
136
+ readonly state: "available" | "partial" | "unavailable";
137
+ readonly unavailableTrees: number;
138
+ readonly warningTrees: number;
139
+ };
140
+ readonly treeCount: number;
141
+ };
142
+ readonly pressure: "admission_degraded" | "cleanup_unknown" | "healthy" | "observed_pressure" | "warning";
143
+ readonly supervision: {
144
+ readonly trackedTrees: number;
145
+ readonly watcherFibers: number;
146
+ };
147
+ };
148
+ readonly storage: {
149
+ readonly integrity: "ok";
150
+ readonly journalMode: "wal";
151
+ readonly schemaTag: string;
152
+ readonly schemaVersion: number;
153
+ };
154
+ };
155
+ }, LocalNodeTransportError, Crypto.Crypto>;
156
+ export declare const discoveryFailure: (error: unknown) => MaiaClientError;
157
+ export type DiscoveredNodeApiEffectConnection = {
158
+ readonly client: LocalNodeEffectClient;
159
+ readonly descriptor: NodeApiConnectionDescriptor;
160
+ readonly status: LocalNodeStatusResult;
161
+ };
162
+ export type NodeApiEffectDiscoveryOptions = Omit<NodeApiDiscoveryOptions, "signal">;
163
+ export declare const connectNodeApiEffect: (options?: NodeApiEffectDiscoveryOptions) => Effect.Effect<DiscoveredNodeApiEffectConnection, MaiaClientError, Crypto.Crypto>;
164
+ export declare const acquireAttachedCredential: () => Effect.Effect<Uint8Array, unknown>;
165
+ export declare const attachedTransportOptions: <TCredential>(descriptor: NodeApiConnectionDescriptor, credential: Uint8Array, readToken: (read: Effect.Effect<string, unknown>) => TCredential) => {
166
+ credential: TCredential;
167
+ endpoint: {
168
+ readonly observationPath: "/api/v1/observations";
169
+ readonly operationPath: "/api/v1/operations";
170
+ readonly origin: string;
171
+ readonly transport: "http-websocket";
172
+ };
173
+ invocationAuthentication: {
174
+ credential: string;
175
+ scheme: "maia.invocation-attachment/v1";
176
+ };
177
+ };
178
+ export declare const requireAttachmentPlatform: () => Effect.Effect<void, MaiaClientError>;
179
+ export type AttachedLocalNodeEffectOptions = NodeApiEffectDiscoveryOptions & {
180
+ readonly messageId?: string;
181
+ };
182
+ export declare const showAttachedCurrentContextEffect: (options?: AttachedLocalNodeEffectOptions) => Effect.Effect<InvocationContextShowResult, MaiaClientError, Crypto.Crypto>;
183
+ export declare const sendAttachedSessionMessageEffect: (parameters: SessionMessageSendParameters, options?: AttachedLocalNodeEffectOptions) => Effect.Effect<SessionMessageSendResult, MaiaClientError, Crypto.Crypto>;
184
+ export declare const checkAttachedSessionInboxEffect: (parameters: SessionInboxCheckParameters, options?: AttachedLocalNodeEffectOptions) => Effect.Effect<SessionInboxCheckResult, MaiaClientError, Crypto.Crypto>;
185
+ export declare const acknowledgeAttachedSessionDeliveryEffect: (parameters: SessionInboxAckParameters, options?: AttachedLocalNodeEffectOptions) => Effect.Effect<SessionInboxAckResult, MaiaClientError, Crypto.Crypto>;
186
+ export {};
187
+ //# sourceMappingURL=discovery.d.ts.map