@pipeline-moe/client-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.d.ts ADDED
@@ -0,0 +1,238 @@
1
+ import type { ConversationMeta, Message, ModelInfo, PersonaDetail, PersonaTemplate, PresetFile, ProviderInfo, ResumableRoom, RoomSettings, RoomSummary, RouteDecision, RoutingMode, RosterItem, WorkspaceFile } from "./types.js";
2
+ /**
3
+ * Build the API surface bound to a given server base URL.
4
+ *
5
+ * This is the single place the client talks HTTP to a pipeline-moe server.
6
+ * It is framework- and host-agnostic: the base URL is injected rather than
7
+ * read from `import.meta.env`, so the same module serves the web frontend
8
+ * (passing `import.meta.env.VITE_API_BASE`) and a terminal client (passing
9
+ * `process.env`). `fetch`/`Response` are assumed to exist in the host (browser,
10
+ * or Node ≥18).
11
+ *
12
+ * @param API_BASE Server origin, e.g. "http://localhost:5300".
13
+ * @returns `{ API_BASE, makeRoomApi, api }` — the same shape the web app
14
+ * previously imported from its local `api.ts`.
15
+ */
16
+ export declare function createApi(API_BASE: string): {
17
+ API_BASE: string;
18
+ makeRoomApi: (prefix: string) => {
19
+ roster: () => Promise<RosterItem[]>;
20
+ savePreset: (name: string) => Promise<PresetFile>;
21
+ loadPreset: (name: string) => Promise<{
22
+ ok: boolean;
23
+ conversation: ConversationMeta;
24
+ downgraded?: Array<{
25
+ agent: string;
26
+ model: string;
27
+ }>;
28
+ }>;
29
+ applyPreset: (name: string) => Promise<{
30
+ ok: boolean;
31
+ conversation: ConversationMeta;
32
+ downgraded?: Array<{
33
+ agent: string;
34
+ model: string;
35
+ }>;
36
+ }>;
37
+ transcript: () => Promise<Message[]>;
38
+ workspace: () => Promise<WorkspaceFile[]>;
39
+ sendMessage: (text: string, images?: string[]) => Promise<{
40
+ accepted: boolean;
41
+ }>;
42
+ setActive: (id: string, active: boolean) => Promise<RosterItem>;
43
+ setParallel: (id: string, parallel: boolean) => Promise<RosterItem>;
44
+ kick: (id: string) => Promise<void>;
45
+ participant: (id: string) => Promise<PersonaDetail>;
46
+ updateAgent: (id: string, patch: {
47
+ name?: string;
48
+ systemPrompt?: string;
49
+ tools?: string[];
50
+ color?: string;
51
+ icon?: string;
52
+ model?: string | null;
53
+ thinkingLevel?: string | null;
54
+ compactionInstructions?: string | null;
55
+ }) => Promise<RosterItem>;
56
+ reorder: (order: string[]) => Promise<RosterItem[]>;
57
+ create: (body: {
58
+ name: string;
59
+ systemPrompt: string;
60
+ tools?: string[];
61
+ color?: string;
62
+ icon?: string;
63
+ id?: string;
64
+ }) => Promise<RosterItem>;
65
+ addFromTemplate: (templateId: string) => Promise<RosterItem>;
66
+ abort: () => Promise<unknown>;
67
+ steerMessage: (text: string, target: string) => Promise<{
68
+ ok: boolean;
69
+ target: string;
70
+ text: string;
71
+ }>;
72
+ compact: (id: string) => Promise<{
73
+ summary: string;
74
+ tokensBefore: number;
75
+ }>;
76
+ exportAgent: (id: string) => Promise<Blob>;
77
+ exportAgentJsonl: (id: string) => Promise<Blob>;
78
+ settings: () => Promise<RoomSettings>;
79
+ setChaining: (chaining: boolean) => Promise<RoomSettings>;
80
+ setDefaultAgent: (defaultAgent: string | null) => Promise<RoomSettings>;
81
+ setFallbackAgent: (fallbackAgent: string | null) => Promise<RoomSettings>;
82
+ setMaxChainHops: (maxChainHops: number) => Promise<RoomSettings>;
83
+ setRoutingMode: (routingMode: RoutingMode) => Promise<RoomSettings>;
84
+ setCircuitBreaker: (circuitBreaker: boolean) => Promise<RoomSettings>;
85
+ setDefaultThinkingLevel: (defaultThinkingLevel: "off" | "minimal" | "low" | "medium" | "high" | "xhigh") => Promise<RoomSettings>;
86
+ setAllowCloud: (allowCloud: boolean) => Promise<RoomSettings>;
87
+ setCompactionReserveTokens: (compactionReserveTokens: number) => Promise<RoomSettings>;
88
+ resolveRoute: (decision: RouteDecision) => Promise<unknown>;
89
+ conversations: () => Promise<{
90
+ currentId: string;
91
+ list: ConversationMeta[];
92
+ }>;
93
+ newConversation: (title?: string) => Promise<ConversationMeta>;
94
+ loadConversation: (id: string) => Promise<{
95
+ ok: boolean;
96
+ }>;
97
+ renameConversation: (id: string, title: string) => Promise<{
98
+ ok: boolean;
99
+ }>;
100
+ deleteConversation: (id: string) => Promise<void>;
101
+ };
102
+ api: {
103
+ models: () => Promise<{
104
+ models: ModelInfo[];
105
+ allowCloud: boolean;
106
+ }>;
107
+ presets: () => Promise<PresetFile[]>;
108
+ deletePreset: (name: string) => Promise<void>;
109
+ providers: () => Promise<{
110
+ providers: ProviderInfo[];
111
+ explicitlyEnabled: string[];
112
+ }>;
113
+ addProvider: (name: string, key: string) => Promise<{
114
+ name: string;
115
+ configured: boolean;
116
+ source?: string;
117
+ label?: string;
118
+ }>;
119
+ removeProvider: (name: string) => Promise<{
120
+ name: string;
121
+ configured: boolean;
122
+ agentsUsing?: string[];
123
+ }>;
124
+ loginProvider: (name: string) => Promise<{
125
+ accepted: boolean;
126
+ provider: string;
127
+ }>;
128
+ personaTemplates: () => Promise<PersonaTemplate[]>;
129
+ listRooms: () => Promise<RoomSummary[]>;
130
+ resumableRooms: () => Promise<ResumableRoom[]>;
131
+ resumeRoom: (roomId: string) => Promise<RoomSummary>;
132
+ /** Stop a specific room's in-flight pipeline (cancels a running goal). */
133
+ abortRoom: (roomId: string) => Promise<{
134
+ aborted: boolean;
135
+ }>;
136
+ createRoom: (body: {
137
+ name: string;
138
+ roomId?: string;
139
+ preset?: string;
140
+ goal?: string;
141
+ workspaceDir?: string;
142
+ }) => Promise<RoomSummary>;
143
+ getRoomDetails: (roomId: string) => Promise<RoomSummary>;
144
+ destroyRoom: (roomId: string) => Promise<void>;
145
+ renameRoom: (roomId: string, name: string) => Promise<{
146
+ roomId: string;
147
+ name: string;
148
+ }>;
149
+ roster: () => Promise<RosterItem[]>;
150
+ savePreset: (name: string) => Promise<PresetFile>;
151
+ loadPreset: (name: string) => Promise<{
152
+ ok: boolean;
153
+ conversation: ConversationMeta;
154
+ downgraded?: Array<{
155
+ agent: string;
156
+ model: string;
157
+ }>;
158
+ }>;
159
+ applyPreset: (name: string) => Promise<{
160
+ ok: boolean;
161
+ conversation: ConversationMeta;
162
+ downgraded?: Array<{
163
+ agent: string;
164
+ model: string;
165
+ }>;
166
+ }>;
167
+ transcript: () => Promise<Message[]>;
168
+ workspace: () => Promise<WorkspaceFile[]>;
169
+ sendMessage: (text: string, images?: string[]) => Promise<{
170
+ accepted: boolean;
171
+ }>;
172
+ setActive: (id: string, active: boolean) => Promise<RosterItem>;
173
+ setParallel: (id: string, parallel: boolean) => Promise<RosterItem>;
174
+ kick: (id: string) => Promise<void>;
175
+ participant: (id: string) => Promise<PersonaDetail>;
176
+ updateAgent: (id: string, patch: {
177
+ name?: string;
178
+ systemPrompt?: string;
179
+ tools?: string[];
180
+ color?: string;
181
+ icon?: string;
182
+ model?: string | null;
183
+ thinkingLevel?: string | null;
184
+ compactionInstructions?: string | null;
185
+ }) => Promise<RosterItem>;
186
+ reorder: (order: string[]) => Promise<RosterItem[]>;
187
+ create: (body: {
188
+ name: string;
189
+ systemPrompt: string;
190
+ tools?: string[];
191
+ color?: string;
192
+ icon?: string;
193
+ id?: string;
194
+ }) => Promise<RosterItem>;
195
+ addFromTemplate: (templateId: string) => Promise<RosterItem>;
196
+ abort: () => Promise<unknown>;
197
+ steerMessage: (text: string, target: string) => Promise<{
198
+ ok: boolean;
199
+ target: string;
200
+ text: string;
201
+ }>;
202
+ compact: (id: string) => Promise<{
203
+ summary: string;
204
+ tokensBefore: number;
205
+ }>;
206
+ exportAgent: (id: string) => Promise<Blob>;
207
+ exportAgentJsonl: (id: string) => Promise<Blob>;
208
+ settings: () => Promise<RoomSettings>;
209
+ setChaining: (chaining: boolean) => Promise<RoomSettings>;
210
+ setDefaultAgent: (defaultAgent: string | null) => Promise<RoomSettings>;
211
+ setFallbackAgent: (fallbackAgent: string | null) => Promise<RoomSettings>;
212
+ setMaxChainHops: (maxChainHops: number) => Promise<RoomSettings>;
213
+ setRoutingMode: (routingMode: RoutingMode) => Promise<RoomSettings>;
214
+ setCircuitBreaker: (circuitBreaker: boolean) => Promise<RoomSettings>;
215
+ setDefaultThinkingLevel: (defaultThinkingLevel: "off" | "minimal" | "low" | "medium" | "high" | "xhigh") => Promise<RoomSettings>;
216
+ setAllowCloud: (allowCloud: boolean) => Promise<RoomSettings>;
217
+ setCompactionReserveTokens: (compactionReserveTokens: number) => Promise<RoomSettings>;
218
+ resolveRoute: (decision: RouteDecision) => Promise<unknown>;
219
+ conversations: () => Promise<{
220
+ currentId: string;
221
+ list: ConversationMeta[];
222
+ }>;
223
+ newConversation: (title?: string) => Promise<ConversationMeta>;
224
+ loadConversation: (id: string) => Promise<{
225
+ ok: boolean;
226
+ }>;
227
+ renameConversation: (id: string, title: string) => Promise<{
228
+ ok: boolean;
229
+ }>;
230
+ deleteConversation: (id: string) => Promise<void>;
231
+ };
232
+ };
233
+ /** The shape returned by {@link createApi} — useful for typing consumers. */
234
+ export type ClientApi = ReturnType<typeof createApi>;
235
+ /** The room-scoped API object (per-room operations). */
236
+ export type RoomApi = ReturnType<ClientApi["makeRoomApi"]>;
237
+ /** The full API object (room-scoped default + process-global operations). */
238
+ export type Api = ClientApi["api"];
package/dist/api.js ADDED
@@ -0,0 +1,216 @@
1
+ async function json(res) {
2
+ if (!res.ok) {
3
+ let detail = "";
4
+ try {
5
+ const body = (await res.json());
6
+ detail = body.error ?? "";
7
+ }
8
+ catch {
9
+ /* ignore */
10
+ }
11
+ throw new Error(detail || `${res.status} ${res.statusText}`);
12
+ }
13
+ return res.json();
14
+ }
15
+ /**
16
+ * Build the API surface bound to a given server base URL.
17
+ *
18
+ * This is the single place the client talks HTTP to a pipeline-moe server.
19
+ * It is framework- and host-agnostic: the base URL is injected rather than
20
+ * read from `import.meta.env`, so the same module serves the web frontend
21
+ * (passing `import.meta.env.VITE_API_BASE`) and a terminal client (passing
22
+ * `process.env`). `fetch`/`Response` are assumed to exist in the host (browser,
23
+ * or Node ≥18).
24
+ *
25
+ * @param API_BASE Server origin, e.g. "http://localhost:5300".
26
+ * @returns `{ API_BASE, makeRoomApi, api }` — the same shape the web app
27
+ * previously imported from its local `api.ts`.
28
+ */
29
+ export function createApi(API_BASE) {
30
+ /**
31
+ * Create a room-scoped API object for the given route prefix.
32
+ * Use prefix "/api" for the default room (backward compat).
33
+ * Use "/api/rooms/:roomId" for non-default rooms.
34
+ */
35
+ function makeRoomApi(prefix) {
36
+ const base = `${API_BASE}${prefix}`;
37
+ return {
38
+ roster: () => fetch(`${base}/participants`).then((r) => json(r)),
39
+ // Preset save/load/apply target THIS room (the prefix), so loading from the
40
+ // second room's view doesn't clobber the default room.
41
+ savePreset: (name) => fetch(`${base}/presets`, {
42
+ method: "POST",
43
+ headers: { "Content-Type": "application/json" },
44
+ body: JSON.stringify({ name }),
45
+ }).then((r) => json(r)),
46
+ loadPreset: (name) => fetch(`${base}/presets/${name}/load`, { method: "POST" }).then((r) => json(r)),
47
+ applyPreset: (name) => fetch(`${base}/presets/${name}/apply`, { method: "POST" }).then((r) => json(r)),
48
+ transcript: () => fetch(`${base}/transcript`).then((r) => json(r)),
49
+ workspace: () => fetch(`${base}/workspace`).then((r) => json(r)),
50
+ sendMessage: (text, images) => fetch(`${base}/messages`, {
51
+ method: "POST",
52
+ headers: { "Content-Type": "application/json" },
53
+ body: JSON.stringify({ text, ...(images && images.length > 0 ? { images } : {}) }),
54
+ }).then((r) => json(r)),
55
+ setActive: (id, active) => fetch(`${base}/participants/${id}`, {
56
+ method: "PATCH",
57
+ headers: { "Content-Type": "application/json" },
58
+ body: JSON.stringify({ active }),
59
+ }).then((r) => json(r)),
60
+ setParallel: (id, parallel) => fetch(`${base}/participants/${id}`, {
61
+ method: "PATCH",
62
+ headers: { "Content-Type": "application/json" },
63
+ body: JSON.stringify({ parallel }),
64
+ }).then((r) => json(r)),
65
+ kick: (id) => fetch(`${base}/participants/${id}`, { method: "DELETE" }).then((r) => {
66
+ if (!r.ok && r.status !== 204)
67
+ throw new Error(`${r.status}`);
68
+ }),
69
+ participant: (id) => fetch(`${base}/participants/${id}`).then((r) => json(r)),
70
+ updateAgent: (id, patch) => fetch(`${base}/participants/${id}`, {
71
+ method: "PATCH",
72
+ headers: { "Content-Type": "application/json" },
73
+ body: JSON.stringify(patch),
74
+ }).then((r) => json(r)),
75
+ reorder: (order) => fetch(`${base}/participants/reorder`, {
76
+ method: "POST",
77
+ headers: { "Content-Type": "application/json" },
78
+ body: JSON.stringify({ order }),
79
+ }).then((r) => json(r)),
80
+ create: (body) => fetch(`${base}/participants`, {
81
+ method: "POST",
82
+ headers: { "Content-Type": "application/json" },
83
+ body: JSON.stringify(body),
84
+ }).then((r) => json(r)),
85
+ addFromTemplate: (templateId) => fetch(`${base}/participants/from-template`, {
86
+ method: "POST",
87
+ headers: { "Content-Type": "application/json" },
88
+ body: JSON.stringify({ templateId }),
89
+ }).then((r) => json(r)),
90
+ abort: () => fetch(`${base}/abort`, { method: "POST" }).then((r) => json(r)),
91
+ steerMessage: (text, target) => fetch(`${base}/messages/steer`, {
92
+ method: "POST",
93
+ headers: { "Content-Type": "application/json" },
94
+ body: JSON.stringify({ text, target }),
95
+ }).then((r) => json(r)),
96
+ compact: (id) => fetch(`${base}/participants/${id}/compact`, { method: "POST" }).then((r) => json(r)),
97
+ exportAgent: (id) => fetch(`${base}/participants/${id}/export`).then((r) => r.blob()),
98
+ exportAgentJsonl: (id) => fetch(`${base}/participants/${id}/export-jsonl`).then((r) => r.blob()),
99
+ settings: () => fetch(`${base}/settings`).then((r) => json(r)),
100
+ setChaining: (chaining) => fetch(`${base}/settings`, {
101
+ method: "PATCH",
102
+ headers: { "Content-Type": "application/json" },
103
+ body: JSON.stringify({ chaining }),
104
+ }).then((r) => json(r)),
105
+ setDefaultAgent: (defaultAgent) => fetch(`${base}/settings`, {
106
+ method: "PATCH",
107
+ headers: { "Content-Type": "application/json" },
108
+ body: JSON.stringify({ defaultAgent }),
109
+ }).then((r) => json(r)),
110
+ setFallbackAgent: (fallbackAgent) => fetch(`${base}/settings`, {
111
+ method: "PATCH",
112
+ headers: { "Content-Type": "application/json" },
113
+ body: JSON.stringify({ fallbackAgent }),
114
+ }).then((r) => json(r)),
115
+ setMaxChainHops: (maxChainHops) => fetch(`${base}/settings`, {
116
+ method: "PATCH",
117
+ headers: { "Content-Type": "application/json" },
118
+ body: JSON.stringify({ maxChainHops }),
119
+ }).then((r) => json(r)),
120
+ setRoutingMode: (routingMode) => fetch(`${base}/settings`, {
121
+ method: "PATCH",
122
+ headers: { "Content-Type": "application/json" },
123
+ body: JSON.stringify({ routingMode }),
124
+ }).then((r) => json(r)),
125
+ setCircuitBreaker: (circuitBreaker) => fetch(`${base}/settings`, {
126
+ method: "PATCH",
127
+ headers: { "Content-Type": "application/json" },
128
+ body: JSON.stringify({ circuitBreaker }),
129
+ }).then((r) => json(r)),
130
+ setDefaultThinkingLevel: (defaultThinkingLevel) => fetch(`${base}/settings`, {
131
+ method: "PATCH",
132
+ headers: { "Content-Type": "application/json" },
133
+ body: JSON.stringify({ defaultThinkingLevel }),
134
+ }).then((r) => json(r)),
135
+ setAllowCloud: (allowCloud) => fetch(`${base}/settings`, {
136
+ method: "PATCH",
137
+ headers: { "Content-Type": "application/json" },
138
+ body: JSON.stringify({ allowCloud }),
139
+ }).then((r) => json(r)),
140
+ setCompactionReserveTokens: (compactionReserveTokens) => fetch(`${base}/settings`, {
141
+ method: "PATCH",
142
+ headers: { "Content-Type": "application/json" },
143
+ body: JSON.stringify({ compactionReserveTokens }),
144
+ }).then((r) => json(r)),
145
+ resolveRoute: (decision) => fetch(`${base}/route`, {
146
+ method: "POST",
147
+ headers: { "Content-Type": "application/json" },
148
+ body: JSON.stringify(decision),
149
+ }).then((r) => json(r)),
150
+ conversations: () => fetch(`${base}/conversations`).then((r) => json(r)),
151
+ newConversation: (title) => fetch(`${base}/conversations`, {
152
+ method: "POST",
153
+ headers: { "Content-Type": "application/json" },
154
+ body: JSON.stringify(title ? { title } : {}),
155
+ }).then((r) => json(r)),
156
+ loadConversation: (id) => fetch(`${base}/conversations/${id}/load`, { method: "POST" }).then((r) => json(r)),
157
+ renameConversation: (id, title) => fetch(`${base}/conversations/${id}`, {
158
+ method: "PATCH",
159
+ headers: { "Content-Type": "application/json" },
160
+ body: JSON.stringify({ title }),
161
+ }).then((r) => json(r)),
162
+ deleteConversation: (id) => fetch(`${base}/conversations/${id}`, { method: "DELETE" }).then((r) => {
163
+ if (!r.ok && r.status !== 204)
164
+ throw new Error(`${r.status}`);
165
+ }),
166
+ };
167
+ }
168
+ const api = {
169
+ // Room-scoped operations via the default /api prefix (backward compat).
170
+ ...makeRoomApi("/api"),
171
+ // ── Models (process-global) ─────────────────────────────────────────────
172
+ models: () => fetch(`${API_BASE}/api/models`).then((r) => json(r)),
173
+ // ── Presets (process-global) ────────────────────────────────────────────
174
+ presets: () => fetch(`${API_BASE}/api/presets`).then((r) => json(r)),
175
+ deletePreset: (name) => fetch(`${API_BASE}/api/presets/${name}`, { method: "DELETE" }).then((r) => {
176
+ if (!r.ok && r.status !== 204)
177
+ throw new Error(`${r.status}`);
178
+ }),
179
+ // ── Providers (process-global) ──────────────────────────────────────────
180
+ providers: () => fetch(`${API_BASE}/api/providers`).then((r) => json(r)),
181
+ addProvider: (name, key) => fetch(`${API_BASE}/api/providers/${name}`, {
182
+ method: "POST",
183
+ headers: { "Content-Type": "application/json" },
184
+ body: JSON.stringify({ key }),
185
+ }).then((r) => json(r)),
186
+ removeProvider: (name) => fetch(`${API_BASE}/api/providers/${name}`, { method: "DELETE" }).then((r) => json(r)),
187
+ loginProvider: (name) => fetch(`${API_BASE}/api/providers/${name}/login`, { method: "POST" }).then((r) => json(r)),
188
+ // ── Room CRUD (process-global) ──────────────────────────────────────────
189
+ personaTemplates: () => fetch(`${API_BASE}/api/persona-templates`).then((r) => json(r)),
190
+ listRooms: () => fetch(`${API_BASE}/api/rooms`).then((r) => json(r)),
191
+ resumableRooms: () => fetch(`${API_BASE}/api/rooms/resumable`).then((r) => json(r)),
192
+ resumeRoom: (roomId) => fetch(`${API_BASE}/api/rooms/${roomId}/resume`, { method: "POST" }).then((r) => json(r)),
193
+ /** Stop a specific room's in-flight pipeline (cancels a running goal). */
194
+ abortRoom: (roomId) => fetch(`${API_BASE}/api/rooms/${roomId}/abort`, { method: "POST" }).then((r) => json(r)),
195
+ createRoom: (body) => fetch(`${API_BASE}/api/rooms`, {
196
+ method: "POST",
197
+ headers: { "Content-Type": "application/json" },
198
+ body: JSON.stringify(body),
199
+ }).then((r) => json(r)),
200
+ getRoomDetails: (roomId) => fetch(`${API_BASE}/api/rooms/${roomId}`).then((r) => json(r)),
201
+ destroyRoom: (roomId) => fetch(`${API_BASE}/api/rooms/${roomId}`, { method: "DELETE" }).then((r) => {
202
+ if (!r.ok && r.status !== 204)
203
+ throw new Error(`${r.status}`);
204
+ }),
205
+ renameRoom: (roomId, name) => fetch(`${API_BASE}/api/rooms/${roomId}`, {
206
+ method: "PATCH",
207
+ headers: { "Content-Type": "application/json" },
208
+ body: JSON.stringify({ name }),
209
+ }).then((r) => {
210
+ if (!r.ok)
211
+ throw new Error(`${r.status}`);
212
+ return json(r);
213
+ }),
214
+ };
215
+ return { API_BASE, makeRoomApi, api };
216
+ }
@@ -0,0 +1,7 @@
1
+ export * from "./types.js";
2
+ export { createApi } from "./api.js";
3
+ export type { ClientApi, RoomApi, Api } from "./api.js";
4
+ export { initialRoomState, resetTransient, reduce, SSE_EVENT_NAMES, } from "./state.js";
5
+ export type { RoomState, Notice, ThinkingLevel, SseEvent, SseEventName, Effect, ReduceResult, } from "./state.js";
6
+ export { createRoomStore, browserEventSourceFactory } from "./store.js";
7
+ export type { RoomStore, RoomStoreOptions, EventSourceFactory, SseConnection, SseHandlers, } from "./store.js";
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // @pipeline-moe/client-core — framework-agnostic client for a pipeline-moe
2
+ // server: the typed REST surface, the shared domain types, the pure SSE
3
+ // reducer, and the effectful room store. Both the web frontend and a terminal
4
+ // client consume this one protocol implementation.
5
+ export * from "./types.js";
6
+ export { createApi } from "./api.js";
7
+ export { initialRoomState, resetTransient, reduce, SSE_EVENT_NAMES, } from "./state.js";
8
+ export { createRoomStore, browserEventSourceFactory } from "./store.js";
@@ -0,0 +1,78 @@
1
+ import type { ConversationMeta, Message, OAuthProgress, ProviderInfo, Receipt, RosterItem, RouteProposal, RoutingMode, ToolActivity, WorkspaceFile } from "./types.js";
2
+ export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
3
+ /** A transient toast. `id` is assigned by the store, not the reducer. */
4
+ export interface Notice {
5
+ id: number;
6
+ msg: string;
7
+ level: "info" | "error";
8
+ }
9
+ /** The complete observable state of one room. */
10
+ export interface RoomState {
11
+ roster: RosterItem[];
12
+ messages: Message[];
13
+ /** In-flight text deltas, keyed by agent id (cleared when the message lands). */
14
+ streaming: Record<string, string>;
15
+ /** In-flight tool calls of running agents, keyed by agent id. */
16
+ liveActivity: Record<string, ToolActivity[]>;
17
+ /** In-flight reasoning deltas, keyed by agent id. */
18
+ liveReasoning: Record<string, string>;
19
+ /** Filesystem receipts, keyed by the transcript index of the owning message. */
20
+ receipts: Record<number, Receipt>;
21
+ workspace: WorkspaceFile[];
22
+ notices: Notice[];
23
+ connected: boolean;
24
+ turnActive: boolean;
25
+ runningAgentId: string | null;
26
+ paused: boolean;
27
+ pausedQuestion: string | null;
28
+ pausedAskerId: string | null;
29
+ chaining: boolean;
30
+ routingMode: RoutingMode;
31
+ defaultAgent: string | null;
32
+ fallbackAgent: string | null;
33
+ maxChainHops: number;
34
+ circuitBreaker: boolean;
35
+ defaultThinkingLevel: ThinkingLevel;
36
+ allowCloud: boolean;
37
+ compactionReserveTokens: number;
38
+ pendingRoute: RouteProposal[] | null;
39
+ maxRooms: number;
40
+ conversations: ConversationMeta[];
41
+ currentConversationId: string;
42
+ providers: ProviderInfo[];
43
+ explicitlyEnabled: string[];
44
+ /** In-flight OAuth login flow, or null. Persists until success/error/dismiss. */
45
+ oauthProgress: OAuthProgress | null;
46
+ }
47
+ /** The initial state of a freshly-opened room, before any snapshot or SSE. */
48
+ export declare const initialRoomState: RoomState;
49
+ /**
50
+ * Reset the per-turn transient fields. These are driven only by
51
+ * `turn`/`token`/`activity` SSE events; on a room/conversation switch they must
52
+ * be cleared, otherwise a turn the new context never started would leave them
53
+ * pinned (e.g. a stuck "agents running…" or a stale ask_user prompt).
54
+ */
55
+ export declare function resetTransient(state: RoomState): RoomState;
56
+ /** The named SSE events a room client subscribes to. */
57
+ export declare const SSE_EVENT_NAMES: readonly ["roster", "status", "token", "activity", "reasoning", "message", "receipt", "workspace", "notice", "turn", "settings", "routing", "transcript", "conversations", "providers", "oauth_progress"];
58
+ export type SseEventName = (typeof SSE_EVENT_NAMES)[number];
59
+ /** A parsed SSE event: its name plus the JSON-decoded payload. */
60
+ export interface SseEvent {
61
+ name: SseEventName;
62
+ data: unknown;
63
+ }
64
+ /** A side effect the store must apply (currently only transient notices). */
65
+ export type Effect = {
66
+ type: "notice";
67
+ msg: string;
68
+ level: "info" | "error";
69
+ };
70
+ export interface ReduceResult {
71
+ state: RoomState;
72
+ effects: Effect[];
73
+ }
74
+ /**
75
+ * The pure SSE reducer. Given the current state and one parsed event, returns
76
+ * the next state plus any notices to surface. Never mutates its inputs.
77
+ */
78
+ export declare function reduce(state: RoomState, event: SseEvent): ReduceResult;