@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,37 @@
1
+ import { MAX_TURN_INPUT_BYTES, } from "@maiaos/protocol";
2
+ export const MAX_SESSION_CREATION_TASKS = 32;
3
+ export const orderExecutionWorkspaces = (workspaces) => workspaces
4
+ .filter((workspace) => workspace.state === "ready")
5
+ .toSorted((left, right) => Number(right.kind === "local-main") -
6
+ Number(left.kind === "local-main") ||
7
+ left.name.localeCompare(right.name));
8
+ const utf8 = new TextEncoder();
9
+ const taskLines = (input) => {
10
+ if (input.split === "whole") {
11
+ const task = input.text.trim();
12
+ return [{ line: 1, ...(task === "" ? {} : { task }) }];
13
+ }
14
+ return input.text
15
+ .split(/\r?\n/u)
16
+ .map((text, index) => ({ line: index + 1, task: text.trim() }))
17
+ .filter((entry) => entry.task !== "");
18
+ };
19
+ const fits = (entry) => entry.task === undefined ||
20
+ utf8.encode(entry.task).byteLength <= MAX_TURN_INPUT_BYTES;
21
+ export const splitTasks = (input) => {
22
+ const lines = taskLines(input);
23
+ const fitting = lines.filter((entry) => fits(entry));
24
+ const refusals = [
25
+ ...lines
26
+ .filter((entry) => !fits(entry))
27
+ .map((entry) => ({ line: entry.line, reason: "too_long" })),
28
+ ...fitting.slice(MAX_SESSION_CREATION_TASKS).map((entry) => ({
29
+ line: entry.line,
30
+ reason: "over_batch_limit",
31
+ })),
32
+ ].toSorted((left, right) => left.line - right.line);
33
+ return { accepted: fitting.slice(0, MAX_SESSION_CREATION_TASKS), refusals };
34
+ };
35
+ export const sessionCreationSettled = (outcome, item) => outcome.stage === "sent" ||
36
+ (outcome.stage === "started" && item.task === undefined);
37
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1,2 @@
1
+ export { initialSessionAttachView, isNewSessionRecord, MAX_SESSION_VIEW_TURN_ITEMS, MAX_SESSION_VIEW_TURNS, reduceSessionAttach, sessionAttachCursor, type SessionAttachView, sessionItemText, type SessionViewEnd, type SessionViewItem, type SessionViewTurn, } from "./view.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { initialSessionAttachView, isNewSessionRecord, MAX_SESSION_VIEW_TURN_ITEMS, MAX_SESSION_VIEW_TURNS, reduceSessionAttach, sessionAttachCursor, sessionItemText, } from "./view.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,42 @@
1
+ import type { FailureDetail, SessionAttachFrame, SessionItem, SessionItemStatus, SessionStreamRecord, SessionTurnStatus } from "@maiaos/protocol";
2
+ export declare const MAX_SESSION_VIEW_TURNS = 64;
3
+ export declare const MAX_SESSION_VIEW_TURN_ITEMS = 256;
4
+ export type SessionViewItem = {
5
+ readonly item: SessionItem;
6
+ readonly itemId: string;
7
+ readonly sequence: number;
8
+ readonly status: "open" | SessionItemStatus;
9
+ readonly text: string;
10
+ readonly truncated: boolean;
11
+ };
12
+ export type SessionViewTurn = {
13
+ readonly failure?: FailureDetail;
14
+ readonly items: readonly SessionViewItem[];
15
+ readonly status: "running" | SessionTurnStatus;
16
+ readonly turnId: string;
17
+ };
18
+ export type SessionViewEnd = {
19
+ readonly code: string;
20
+ readonly kind: "error";
21
+ readonly message: string;
22
+ } | {
23
+ readonly kind: "resync";
24
+ readonly reason: string;
25
+ };
26
+ export type SessionAttachView = {
27
+ readonly end?: SessionViewEnd;
28
+ readonly epoch?: string;
29
+ readonly sequence: number;
30
+ readonly sessionId?: string;
31
+ readonly synchronized: boolean;
32
+ readonly turns: readonly SessionViewTurn[];
33
+ };
34
+ export declare const initialSessionAttachView: SessionAttachView;
35
+ export declare const sessionItemText: (item: SessionItem) => string;
36
+ export declare const isNewSessionRecord: (view: SessionAttachView, record: SessionStreamRecord) => boolean;
37
+ export declare const sessionAttachCursor: (view: SessionAttachView) => undefined | {
38
+ readonly epoch: string;
39
+ readonly sequence: number;
40
+ };
41
+ export declare const reduceSessionAttach: (view: SessionAttachView, frame: SessionAttachFrame) => SessionAttachView;
42
+ //# sourceMappingURL=view.d.ts.map
@@ -0,0 +1,137 @@
1
+ export const MAX_SESSION_VIEW_TURNS = 64;
2
+ export const MAX_SESSION_VIEW_TURN_ITEMS = 256;
3
+ export const initialSessionAttachView = {
4
+ sequence: 0,
5
+ synchronized: false,
6
+ turns: [],
7
+ };
8
+ export const sessionItemText = (item) => {
9
+ switch (item.kind) {
10
+ case "message":
11
+ case "reasoning":
12
+ return item.text;
13
+ case "command":
14
+ case "tool_call":
15
+ return item.output ?? "";
16
+ case "approval_request":
17
+ return item.summary;
18
+ case "error":
19
+ return item.message;
20
+ case "file_change":
21
+ case "usage":
22
+ return "";
23
+ }
24
+ };
25
+ const isTruncated = (item) => "truncated" in item && item.truncated === true;
26
+ export const isNewSessionRecord = (view, record) => record.sequence > view.sequence;
27
+ export const sessionAttachCursor = (view) => view.epoch === undefined
28
+ ? undefined
29
+ : { epoch: view.epoch, sequence: view.sequence };
30
+ const withTurn = (turns, turnId, update) => {
31
+ const index = turns.findIndex((turn) => turn.turnId === turnId);
32
+ if (index !== -1)
33
+ return turns.map((turn, position) => position === index ? update(turn) : turn);
34
+ const added = update({ items: [], status: "running", turnId });
35
+ return [...turns, added].slice(-MAX_SESSION_VIEW_TURNS);
36
+ };
37
+ const withItem = (turn, itemId, update) => {
38
+ const index = turn.items.findIndex((item) => item.itemId === itemId);
39
+ const next = update(index === -1 ? undefined : turn.items[index]);
40
+ if (next === undefined)
41
+ return turn;
42
+ return {
43
+ ...turn,
44
+ items: index === -1
45
+ ? [...turn.items, next].slice(-MAX_SESSION_VIEW_TURN_ITEMS)
46
+ : turn.items.map((item, position) => position === index ? next : item),
47
+ };
48
+ };
49
+ const applyItemRecord = (turn, record) => withItem(turn, record.itemId, (current) => {
50
+ if (record.type === "item.delta")
51
+ return current === undefined
52
+ ? undefined
53
+ : {
54
+ ...current,
55
+ sequence: record.sequence,
56
+ text: current.text + record.delta,
57
+ };
58
+ const completed = record.type === "item.completed";
59
+ if (current !== undefined && current.status !== "open" && !completed)
60
+ return current;
61
+ return {
62
+ item: record.item,
63
+ itemId: record.itemId,
64
+ sequence: record.sequence,
65
+ status: completed ? record.status : "open",
66
+ text: sessionItemText(record.item),
67
+ truncated: isTruncated(record.item),
68
+ };
69
+ });
70
+ const applyRecord = (turns, record) => withTurn(turns, record.turnId, (turn) => {
71
+ if (record.type === "turn.started")
72
+ return turn;
73
+ if (record.type === "turn.completed")
74
+ return {
75
+ ...turn,
76
+ ...(record.failure === undefined ? {} : { failure: record.failure }),
77
+ status: record.status,
78
+ };
79
+ return applyItemRecord(turn, record);
80
+ });
81
+ const applyRecords = (view, records) => records.reduce((current, record) => isNewSessionRecord(current, record)
82
+ ? {
83
+ ...current,
84
+ sequence: record.sequence,
85
+ turns: applyRecord(current.turns, record),
86
+ }
87
+ : current, view);
88
+ const applySynchronized = (view, frame) => ({
89
+ ...view,
90
+ sequence: Math.max(view.sequence, frame.data.sequence),
91
+ synchronized: true,
92
+ turns: frame.data.openItems.reduce((turns, open) => withTurn(turns, open.turnId, (turn) => withItem(turn, open.itemId, (current) => current === undefined
93
+ ? undefined
94
+ : {
95
+ ...current,
96
+ sequence: Math.max(current.sequence, open.sequence),
97
+ text: open.text,
98
+ truncated: current.truncated || open.truncated === true,
99
+ })), view.turns),
100
+ });
101
+ const applyAttached = (view, frame) => {
102
+ const restart = frame.data.mode === "snapshot" ||
103
+ frame.data.epoch !== view.epoch ||
104
+ frame.data.sessionId !== view.sessionId;
105
+ const base = restart ? initialSessionAttachView : view;
106
+ return {
107
+ epoch: frame.data.epoch,
108
+ sequence: base.sequence,
109
+ sessionId: frame.data.sessionId,
110
+ synchronized: false,
111
+ turns: base.turns,
112
+ };
113
+ };
114
+ export const reduceSessionAttach = (view, frame) => {
115
+ switch (frame.kind) {
116
+ case "attached":
117
+ return applyAttached(view, frame);
118
+ case "records":
119
+ return applyRecords(view, frame.data.records);
120
+ case "synchronized":
121
+ return applySynchronized(view, frame);
122
+ case "heartbeat":
123
+ return view;
124
+ case "resync":
125
+ return { ...view, end: { kind: "resync", reason: frame.data.reason } };
126
+ case "error":
127
+ return {
128
+ ...view,
129
+ end: {
130
+ code: frame.data.error.code,
131
+ kind: "error",
132
+ message: frame.data.error.message,
133
+ },
134
+ };
135
+ }
136
+ };
137
+ //# sourceMappingURL=view.js.map
@@ -0,0 +1,29 @@
1
+ import type { ProtocolError } from "@maiaos/protocol";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Option from "effect/Option";
4
+ import * as Stream from "effect/Stream";
5
+ import { MaiaClientError } from "../request/index.js";
6
+ import type { StreamRelay } from "./stream.js";
7
+ export type ResumeStep = {
8
+ readonly cursor?: string;
9
+ readonly kind: "frame";
10
+ } | {
11
+ readonly error: ProtocolError;
12
+ readonly kind: "error";
13
+ } | {
14
+ readonly kind: "resnapshot";
15
+ };
16
+ export declare const RESNAPSHOT: {
17
+ readonly kind: "resnapshot";
18
+ };
19
+ export type Resumable<TSubscribe, TFrame> = {
20
+ readonly decode: (text: string, messageId: string) => Option.Option<TFrame>;
21
+ readonly nextId: (prefix: "request") => Effect.Effect<string>;
22
+ readonly relay: StreamRelay<TSubscribe>;
23
+ readonly step: (frame: TFrame) => ResumeStep;
24
+ readonly subscribe: (messageId: string, cursor?: string) => TSubscribe;
25
+ readonly terminal: (frame: TFrame) => boolean;
26
+ };
27
+ export declare const MAX_BUFFERED_FRAMES = 256;
28
+ export declare const resumeStream: <TSubscribe, TFrame>(input: Resumable<TSubscribe, TFrame>) => Stream.Stream<TFrame | typeof RESNAPSHOT, MaiaClientError>;
29
+ //# sourceMappingURL=effect.d.ts.map
@@ -0,0 +1,77 @@
1
+ import * as Cause from "effect/Cause";
2
+ import * as Duration from "effect/Duration";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Option from "effect/Option";
5
+ import * as Queue from "effect/Queue";
6
+ import * as Ref from "effect/Ref";
7
+ import * as Stream from "effect/Stream";
8
+ import { MaiaClientError } from "../request/index.js";
9
+ export const RESNAPSHOT = { kind: "resnapshot" };
10
+ export const MAX_BUFFERED_FRAMES = 256;
11
+ const MAX_RESNAPSHOTS = 3;
12
+ const RECONNECT_AFTER = Duration.seconds(2);
13
+ const RESUBSCRIBE_AFTER = Duration.millis(250);
14
+ const RELAY_CLOSED = Symbol("relay closed");
15
+ const OVERFLOWED = Symbol("buffer overflowed");
16
+ const ended = (reason) => new MaiaClientError("transport_failure", reason === RELAY_CLOSED
17
+ ? "The Maia Node stream relay closed."
18
+ : "The Maia Node stream outran its consumer.", { cause: reason });
19
+ const invalidFrame = () => new MaiaClientError("invalid_response", "The Maia Node stream frame is invalid.");
20
+ const tooManyResnapshots = () => new MaiaClientError("saturated", "The Maia Node stream keeps asking for a fresh snapshot.");
21
+ const fail = (queue, error) => {
22
+ Queue.failCauseUnsafe(queue, Cause.fail(error));
23
+ };
24
+ const offer = (queue, decode, terminal) => (event) => {
25
+ if (event.kind === "closed") {
26
+ fail(queue, ended(RELAY_CLOSED));
27
+ return;
28
+ }
29
+ const frame = decode(event.text);
30
+ if (Option.isNone(frame)) {
31
+ fail(queue, invalidFrame());
32
+ return;
33
+ }
34
+ if (!Queue.offerUnsafe(queue, frame.value)) {
35
+ fail(queue, ended(OVERFLOWED));
36
+ return;
37
+ }
38
+ if (terminal(frame.value))
39
+ Queue.endUnsafe(queue);
40
+ };
41
+ const subscribeFailed = (cause) => new MaiaClientError("transport_failure", "The Maia Node stream relay could not subscribe.", { cause });
42
+ const relayInto = (input, queue, subscribe) => Effect.acquireRelease(Effect.tryPromise({
43
+ catch: subscribeFailed,
44
+ try: () => input.relay(input.subscribe(subscribe.messageId, subscribe.cursor), offer(queue, (text) => input.decode(text, subscribe.messageId), input.terminal)),
45
+ }), (cancel) => Effect.ignore(Effect.tryPromise(() => Promise.resolve(cancel())))).pipe(Effect.catch((error) => Effect.sync(() => {
46
+ fail(queue, error);
47
+ })));
48
+ const subscription = (input, cursor) => Stream.unwrap(Effect.map(input.nextId("request"), (messageId) => Stream.callback((queue) => relayInto(input, queue, {
49
+ messageId,
50
+ ...(cursor === undefined ? {} : { cursor }),
51
+ }), { bufferSize: MAX_BUFFERED_FRAMES, strategy: "suspend" })));
52
+ const advance = (position, frame, step) => {
53
+ if (step.kind === "error")
54
+ return Effect.fail(new MaiaClientError("remote_error", step.error.message, {
55
+ remoteError: step.error,
56
+ }));
57
+ if (step.kind === "resnapshot")
58
+ return resnapshot(position);
59
+ return Effect.as(Ref.update(position, (current) => ({
60
+ cursor: step.cursor === undefined ? current.cursor : Option.some(step.cursor),
61
+ resnapshots: 0,
62
+ })), frame);
63
+ };
64
+ const resnapshot = (position) => Effect.flatMap(Ref.updateAndGet(position, (current) => ({
65
+ cursor: Option.none(),
66
+ resnapshots: current.resnapshots + 1,
67
+ })), (current) => current.resnapshots > MAX_RESNAPSHOTS
68
+ ? Effect.fail(tooManyResnapshots())
69
+ : Effect.succeed(RESNAPSHOT));
70
+ const endedBy = (reason) => (error) => error.cause === reason;
71
+ const pause = (duration) => Stream.drain(Stream.fromEffect(Effect.sleep(duration)));
72
+ const once = (input, position) => Stream.unwrap(Effect.map(Ref.get(position), ({ cursor }) => subscription(input, Option.getOrUndefined(cursor)))).pipe(Stream.mapEffect((frame) => advance(position, frame, input.step(frame))));
73
+ export const resumeStream = (input) => Stream.unwrap(Effect.map(Ref.make({ cursor: Option.none(), resnapshots: 0 }), (position) => {
74
+ const resumed = once(input, position).pipe(Stream.catchIf(endedBy(RELAY_CLOSED), () => pause(RECONNECT_AFTER)), Stream.catchIf(endedBy(OVERFLOWED), () => Stream.fromEffect(resnapshot(position))), Stream.concat(pause(RESUBSCRIBE_AFTER)), Stream.concat(Stream.suspend(() => resumed)));
75
+ return resumed;
76
+ }));
77
+ //# sourceMappingURL=effect.js.map
@@ -0,0 +1,2 @@
1
+ export type { StreamRelay, StreamRelayEvent } from "./stream.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ export type StreamRelayEvent = {
2
+ readonly kind: "closed";
3
+ readonly reason: string;
4
+ } | {
5
+ readonly kind: "frame";
6
+ readonly text: string;
7
+ };
8
+ export type StreamRelay<TSubscribe> = (subscribe: TSubscribe, onEvent: (event: StreamRelayEvent) => void) => Promise<() => Promise<void> | void>;
9
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1,7 @@
1
+ import { type EffectClient, type LocalNodeEffectRequester } from "../request/effect.js";
2
+ import { MaiaClientError } from "../request/index.js";
3
+ import type { VoiceManagedTurnClient } from "./managed-turn.js";
4
+ import type { InvalidVoicePiRelayResponse, VoicePiRelayClient } from "./pi-relay.js";
5
+ export declare const makeVoiceManagedTurnOperations: (request: LocalNodeEffectRequester<unknown>) => EffectClient<VoiceManagedTurnClient>;
6
+ export declare const makeVoicePiRelayOperations: <TError>(request: LocalNodeEffectRequester<TError>, invalidResponse: InvalidVoicePiRelayResponse) => EffectClient<VoicePiRelayClient, MaiaClientError | TError>;
7
+ //# sourceMappingURL=effect.d.ts.map
@@ -0,0 +1,71 @@
1
+ import { turnSendResultSchema } from "@maiaos/protocol";
2
+ import { voiceManagedTurnConfirmParametersSchema, voiceManagedTurnPreviewParametersSchema, voiceManagedTurnPreviewResultSchema, } from "@maiaos/protocol/voice-orchestrator";
3
+ import { Effect } from "effect";
4
+ import { failInvalidResponse, } from "../request/effect.js";
5
+ import { MaiaClientError } from "../request/index.js";
6
+ import { voiceWire } from "./wire-schema.js";
7
+ const invalidManagedTurnResponse = () => new MaiaClientError("invalid_response", "The managed voice response did not match the request.");
8
+ const validate = (schema, value) => Effect.try({
9
+ catch: () => new MaiaClientError("invalid_request", "The managed voice request is invalid."),
10
+ try: () => schema.parse(value),
11
+ });
12
+ const managedTurnFailure = (error) => error instanceof MaiaClientError ? error : invalidManagedTurnResponse();
13
+ const matchesConfirmation = (result, parameters) => result.turn.sessionId === parameters.sessionId &&
14
+ result.receipt.commandId === parameters.confirmation.commandId &&
15
+ result.receipt.method === "turn.send" &&
16
+ result.receipt.target.id === result.turn.id &&
17
+ result.receipt.target.type === "turn";
18
+ const matchesPreview = (result, parameters) => result.sessionId === parameters.sessionId &&
19
+ result.projectId === parameters.projectId &&
20
+ result.voiceSessionId === parameters.scopeId &&
21
+ result.expectedSessionRevision === parameters.expectedSessionRevision &&
22
+ result.turnInput === parameters.utterance.trim();
23
+ const confirmVoiceManagedTurn = (request, parameters, options) => Effect.gen(function* () {
24
+ const validated = yield* validate(voiceManagedTurnConfirmParametersSchema, parameters);
25
+ const result = yield* request({ method: "voice.managed-turn.confirm", parameters: validated }, turnSendResultSchema, options).pipe(Effect.mapError(managedTurnFailure));
26
+ if (!matchesConfirmation(result, validated))
27
+ return yield* Effect.fail(invalidManagedTurnResponse());
28
+ return result;
29
+ });
30
+ const previewVoiceManagedTurn = (request, parameters, options) => Effect.gen(function* () {
31
+ const validated = yield* validate(voiceManagedTurnPreviewParametersSchema, parameters);
32
+ const result = yield* request({ method: "voice.managed-turn.preview", parameters: validated }, voiceManagedTurnPreviewResultSchema, options).pipe(Effect.mapError(managedTurnFailure));
33
+ if (!matchesPreview(result, validated))
34
+ return yield* Effect.fail(invalidManagedTurnResponse());
35
+ return result;
36
+ });
37
+ export const makeVoiceManagedTurnOperations = (request) => ({
38
+ confirmVoiceManagedTurn: (parameters, options) => confirmVoiceManagedTurn(request, parameters, options),
39
+ previewVoiceManagedTurn: (parameters, options) => previewVoiceManagedTurn(request, parameters, options),
40
+ });
41
+ const matchedRelayResult = (context, result, matches) => matches
42
+ ? Effect.succeed(result)
43
+ : failInvalidResponse(context.invalidResponse);
44
+ const requestVoicePiRelayPreview = (context, parameters, options) => Effect.suspend(() => context.request({
45
+ method: "voice.pi.relay.preview",
46
+ parameters: voiceWire.previewParameters(parameters),
47
+ }, { parse: (value) => voiceWire.previewResult(value) }, options)).pipe(Effect.flatMap((result) => matchedRelayResult(context, result, result.commandId === parameters.commandId &&
48
+ result.workspaceId === parameters.workspaceId &&
49
+ result.workspaceRevision === parameters.expectedWorkspaceRevision &&
50
+ result.contextRevision === parameters.expectedContextRevision)));
51
+ const requestVoicePiRelayReconcile = (context, parameters, options) => Effect.suspend(() => context.request({
52
+ method: "voice.pi.relay.reconcile",
53
+ parameters: voiceWire.reconcileParameters(parameters),
54
+ }, { parse: (value) => voiceWire.reconcileResult(value) }, options)).pipe(Effect.flatMap((result) => matchedRelayResult(context, result, result.commandId === parameters.commandId)));
55
+ const requestConfirmedVoicePiRelay = (context, parameters, options) => Effect.suspend(() => context.request({
56
+ method: "voice.pi.relay",
57
+ parameters: voiceWire.relayParameters(parameters),
58
+ }, { parse: (value) => voiceWire.relayResult(value) }, options)).pipe(Effect.flatMap((result) => matchedRelayResult(context, result, result.commandId === parameters.commandId &&
59
+ result.workspaceId === parameters.workspaceId &&
60
+ result.sessionId === parameters.sessionId &&
61
+ result.workspaceRevision === parameters.expectedWorkspaceRevision &&
62
+ result.contextRevision === parameters.expectedContextRevision)));
63
+ export const makeVoicePiRelayOperations = (request, invalidResponse) => {
64
+ const context = { invalidResponse, request };
65
+ return {
66
+ previewVoiceToPi: (parameters, options) => requestVoicePiRelayPreview(context, parameters, options),
67
+ reconcileVoiceToPi: (parameters, options) => requestVoicePiRelayReconcile(context, parameters, options),
68
+ relayVoiceToPi: (parameters, options) => requestConfirmedVoicePiRelay(context, parameters, options),
69
+ };
70
+ };
71
+ //# sourceMappingURL=effect.js.map
@@ -0,0 +1,4 @@
1
+ export { makeVoiceManagedTurnClient, type VoiceManagedTurnClient, } from "./managed-turn.js";
2
+ export type { VoiceOrchestratorClient } from "./orchestrator.js";
3
+ export { type InvalidVoicePiRelayResponse, makeVoicePiRelayClient, type VoicePiRelayClient, } from "./pi-relay.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { makeVoiceManagedTurnClient, } from "./managed-turn.js";
2
+ export { makeVoicePiRelayClient, } from "./pi-relay.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ import type { TurnSendResult } from "@maiaos/protocol";
2
+ import type { VoiceManagedTurnConfirmParameters, VoiceManagedTurnPreviewParameters, VoiceManagedTurnPreviewResult } from "@maiaos/protocol/voice-orchestrator";
3
+ import type { LocalNodeRequester, LocalNodeRequestOptions } from "../request/index.js";
4
+ export type VoiceManagedTurnClient = {
5
+ readonly confirmVoiceManagedTurn: (parameters: VoiceManagedTurnConfirmParameters, options: LocalNodeRequestOptions) => Promise<TurnSendResult>;
6
+ readonly previewVoiceManagedTurn: (parameters: VoiceManagedTurnPreviewParameters, options: LocalNodeRequestOptions) => Promise<VoiceManagedTurnPreviewResult>;
7
+ };
8
+ export declare const makeVoiceManagedTurnClient: (request: LocalNodeRequester) => VoiceManagedTurnClient;
9
+ //# sourceMappingURL=managed-turn.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { fromPromiseRequester, toPromiseClient } from "../request/effect.js";
2
+ import { makeVoiceManagedTurnOperations } from "./effect.js";
3
+ export const makeVoiceManagedTurnClient = (request) => toPromiseClient(makeVoiceManagedTurnOperations(fromPromiseRequester(request)));
4
+ //# sourceMappingURL=managed-turn.js.map
@@ -0,0 +1,5 @@
1
+ export { createVoiceOrchestratorClient, type VoiceOrchestratorClient, VoiceOrchestratorClientError, type VoiceOrchestratorClientErrorCode, type VoiceOrchestratorRequestOptions, type VoiceOrchestratorTransport, } from "./orchestrator.js";
2
+ export type { VoiceOrchestratorContextShowParameters, VoiceOrchestratorContextShowResult, VoiceOrchestratorToolCall, VoiceOrchestratorToolCallParameters, VoiceOrchestratorToolCallResult, VoiceOrchestratorToolDefinition, VoiceOrchestratorToolParameters, VoiceOrchestratorToolResult, } from "@maiaos/protocol/voice-orchestrator";
3
+ export { VOICE_MANAGED_TURN_SCHEMA_VERSION, type VoiceManagedTurnConfirmParameters, voiceManagedTurnConfirmParametersSchema, type VoiceManagedTurnPreviewParameters, voiceManagedTurnPreviewParametersSchema, type VoiceManagedTurnPreviewResult, voiceManagedTurnPreviewResultSchema, } from "@maiaos/protocol/voice-orchestrator";
4
+ export { MAX_VOICE_ORCHESTRATOR_CONTEXT_BYTES, MAX_VOICE_ORCHESTRATOR_SAFE_MESSAGE_BYTES, MAX_VOICE_ORCHESTRATOR_TOOL_CALLS, MAX_VOICE_ORCHESTRATOR_TOOL_OUTPUT_BYTES, MAX_VOICE_ORCHESTRATOR_TOOL_REQUEST_BYTES, VOICE_ORCHESTRATOR_ASK_AUTHORITY, VOICE_ORCHESTRATOR_CONTEXT_SCHEMA_VERSION, VOICE_ORCHESTRATOR_OPERATION_BINDINGS, VOICE_ORCHESTRATOR_REVIEWED_SKILL, VOICE_ORCHESTRATOR_REVIEWED_SKILL_PROJECTION, VOICE_ORCHESTRATOR_SYSTEM_PROMPT, VOICE_ORCHESTRATOR_SYSTEM_PROMPT_SCHEMA, VOICE_ORCHESTRATOR_SYSTEM_PROMPT_SHA256, VOICE_ORCHESTRATOR_SYSTEM_PROMPT_VERSION, VOICE_ORCHESTRATOR_TOOL_CALL_RESULT_SCHEMA_VERSION, VOICE_ORCHESTRATOR_TOOL_DEFINITION, VOICE_ORCHESTRATOR_TOOL_DEFINITIONS, VOICE_ORCHESTRATOR_TOOL_DESCRIPTION, VOICE_ORCHESTRATOR_TOOL_NAME, VOICE_ORCHESTRATOR_TOOL_RESULT_SCHEMA_VERSION, VOICE_ORCHESTRATOR_TOOL_SCHEMA_VERSION, voiceOrchestratorContextShowParametersSchema, voiceOrchestratorContextShowResultSchema, voiceOrchestratorToolCallParametersSchema, voiceOrchestratorToolCallResultSchema, voiceOrchestratorToolCallSchema, voiceOrchestratorToolDefinitionSchema, voiceOrchestratorToolParametersSchema, voiceOrchestratorToolResultSchema, } from "@maiaos/protocol/voice-orchestrator";
5
+ //# sourceMappingURL=orchestrator-contract.d.ts.map
@@ -0,0 +1,4 @@
1
+ export { createVoiceOrchestratorClient, VoiceOrchestratorClientError, } from "./orchestrator.js";
2
+ export { VOICE_MANAGED_TURN_SCHEMA_VERSION, voiceManagedTurnConfirmParametersSchema, voiceManagedTurnPreviewParametersSchema, voiceManagedTurnPreviewResultSchema, } from "@maiaos/protocol/voice-orchestrator";
3
+ export { MAX_VOICE_ORCHESTRATOR_CONTEXT_BYTES, MAX_VOICE_ORCHESTRATOR_SAFE_MESSAGE_BYTES, MAX_VOICE_ORCHESTRATOR_TOOL_CALLS, MAX_VOICE_ORCHESTRATOR_TOOL_OUTPUT_BYTES, MAX_VOICE_ORCHESTRATOR_TOOL_REQUEST_BYTES, VOICE_ORCHESTRATOR_ASK_AUTHORITY, VOICE_ORCHESTRATOR_CONTEXT_SCHEMA_VERSION, VOICE_ORCHESTRATOR_OPERATION_BINDINGS, VOICE_ORCHESTRATOR_REVIEWED_SKILL, VOICE_ORCHESTRATOR_REVIEWED_SKILL_PROJECTION, VOICE_ORCHESTRATOR_SYSTEM_PROMPT, VOICE_ORCHESTRATOR_SYSTEM_PROMPT_SCHEMA, VOICE_ORCHESTRATOR_SYSTEM_PROMPT_SHA256, VOICE_ORCHESTRATOR_SYSTEM_PROMPT_VERSION, VOICE_ORCHESTRATOR_TOOL_CALL_RESULT_SCHEMA_VERSION, VOICE_ORCHESTRATOR_TOOL_DEFINITION, VOICE_ORCHESTRATOR_TOOL_DEFINITIONS, VOICE_ORCHESTRATOR_TOOL_DESCRIPTION, VOICE_ORCHESTRATOR_TOOL_NAME, VOICE_ORCHESTRATOR_TOOL_RESULT_SCHEMA_VERSION, VOICE_ORCHESTRATOR_TOOL_SCHEMA_VERSION, voiceOrchestratorContextShowParametersSchema, voiceOrchestratorContextShowResultSchema, voiceOrchestratorToolCallParametersSchema, voiceOrchestratorToolCallResultSchema, voiceOrchestratorToolCallSchema, voiceOrchestratorToolDefinitionSchema, voiceOrchestratorToolParametersSchema, voiceOrchestratorToolResultSchema, } from "@maiaos/protocol/voice-orchestrator";
4
+ //# sourceMappingURL=orchestrator-contract.js.map
@@ -0,0 +1,25 @@
1
+ import { type ProtocolError, type ProtocolRequestEnvelope } from "@maiaos/protocol";
2
+ import type { VoiceOrchestratorContextShowParameters, VoiceOrchestratorContextShowResult, VoiceOrchestratorToolCallParameters, VoiceOrchestratorToolCallResult } from "@maiaos/protocol/voice-orchestrator";
3
+ export type VoiceOrchestratorRequestOptions = {
4
+ readonly messageId: string;
5
+ readonly signal?: AbortSignal;
6
+ };
7
+ export type VoiceOrchestratorTransport = {
8
+ readonly request: (envelope: ProtocolRequestEnvelope<unknown>, options?: {
9
+ readonly signal?: AbortSignal;
10
+ }) => Promise<unknown>;
11
+ };
12
+ export type VoiceOrchestratorClient = {
13
+ readonly callVoiceOrchestratorTool: (parameters: VoiceOrchestratorToolCallParameters, options: VoiceOrchestratorRequestOptions) => Promise<VoiceOrchestratorToolCallResult>;
14
+ readonly showVoiceOrchestratorContext: (parameters: VoiceOrchestratorContextShowParameters, options: VoiceOrchestratorRequestOptions) => Promise<VoiceOrchestratorContextShowResult>;
15
+ };
16
+ export type VoiceOrchestratorClientErrorCode = "cancelled" | "correlation_mismatch" | "deadline_exceeded" | "invalid_request" | "invalid_response" | "outcome_unknown" | "remote_error" | "saturated" | "transport_failure";
17
+ export declare class VoiceOrchestratorClientError extends Error {
18
+ readonly code: VoiceOrchestratorClientErrorCode;
19
+ readonly remoteError?: ProtocolError;
20
+ constructor(code: VoiceOrchestratorClientErrorCode, message: string, options?: ErrorOptions & {
21
+ readonly remoteError?: ProtocolError;
22
+ });
23
+ }
24
+ export declare const createVoiceOrchestratorClient: (transport: VoiceOrchestratorTransport) => VoiceOrchestratorClient;
25
+ //# sourceMappingURL=orchestrator.d.ts.map