@mastra/code-sdk 1.15.0-alpha.1 → 1.15.0-alpha.3

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 (54) hide show
  1. package/dist/agent-connections/tools.d.ts.map +1 -1
  2. package/dist/agent-connections/tools.js +1 -1
  3. package/dist/agent-connections/tools.js.map +1 -1
  4. package/dist/agents/workspace.d.ts.map +1 -1
  5. package/dist/agents/workspace.js +1 -0
  6. package/dist/agents/workspace.js.map +1 -1
  7. package/dist/factory/client.d.ts +41 -0
  8. package/dist/factory/client.d.ts.map +1 -0
  9. package/dist/factory/client.js +98 -0
  10. package/dist/factory/client.js.map +1 -0
  11. package/dist/factory/remote-controller.d.ts +34 -0
  12. package/dist/factory/remote-controller.d.ts.map +1 -0
  13. package/dist/factory/remote-controller.js +43 -0
  14. package/dist/factory/remote-controller.js.map +1 -0
  15. package/dist/factory/remote-session.d.ts +210 -0
  16. package/dist/factory/remote-session.d.ts.map +1 -0
  17. package/dist/factory/remote-session.js +416 -0
  18. package/dist/factory/remote-session.js.map +1 -0
  19. package/dist/headless/cli.d.ts +7 -0
  20. package/dist/headless/cli.d.ts.map +1 -1
  21. package/dist/headless/cli.js +19 -3
  22. package/dist/headless/cli.js.map +1 -1
  23. package/dist/headless/flags.d.ts.map +1 -1
  24. package/dist/headless/flags.js +2 -1
  25. package/dist/headless/flags.js.map +1 -1
  26. package/dist/headless/format.d.ts +2 -0
  27. package/dist/headless/format.d.ts.map +1 -1
  28. package/dist/headless/format.js +13 -1
  29. package/dist/headless/format.js.map +1 -1
  30. package/dist/headless/run-mc.d.ts.map +1 -1
  31. package/dist/headless/run-mc.js +48 -20
  32. package/dist/headless/run-mc.js.map +1 -1
  33. package/dist/index.d.ts +9 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +11 -5
  36. package/dist/index.js.map +1 -1
  37. package/dist/onboarding/settings.d.ts +18 -0
  38. package/dist/onboarding/settings.d.ts.map +1 -1
  39. package/dist/onboarding/settings.js +28 -3
  40. package/dist/onboarding/settings.js.map +1 -1
  41. package/dist/platform/index.d.ts +74 -0
  42. package/dist/platform/index.d.ts.map +1 -0
  43. package/dist/platform/index.js +200 -0
  44. package/dist/platform/index.js.map +1 -0
  45. package/dist/providers/model-ids.d.ts +1 -0
  46. package/dist/providers/model-ids.d.ts.map +1 -1
  47. package/dist/providers/model-ids.js +6 -4
  48. package/dist/providers/model-ids.js.map +1 -1
  49. package/dist/tools/workflows/create-workflow.d.ts.map +1 -1
  50. package/dist/tools/workflows/create-workflow.js +5 -1
  51. package/dist/tools/workflows/create-workflow.js.map +1 -1
  52. package/dist/workflows/register-primitives.js +4 -1
  53. package/dist/workflows/register-primitives.js.map +1 -1
  54. package/package.json +12 -11
@@ -0,0 +1,210 @@
1
+ import type { AgentControllerModeInfo } from '@mastra/client-js';
2
+ import type { AgentControllerDisplayState, AgentControllerEventListener, AgentControllerRequestStateUpdater, AgentControllerThread, PermissionRules, Session } from '@mastra/core/agent-controller';
3
+ import type { FactoryAddress } from './client.js';
4
+ import { createFactoryClient } from './client.js';
5
+ type RemoteHandle = ReturnType<ReturnType<ReturnType<typeof createFactoryClient>['getAgentController']>['session']>;
6
+ type RemoteMode = AgentControllerModeInfo;
7
+ type Files = Array<{
8
+ data: string;
9
+ mediaType: string;
10
+ filename?: string;
11
+ }>;
12
+ /**
13
+ * Stands in for an in-process `Session` while the agent, tools, and storage
14
+ * run inside a Factory. Reads are served from state mirrored off the session's
15
+ * event stream; every action is forwarded to the Factory over HTTP.
16
+ *
17
+ * Only the surface the TUI drives is implemented. Anything else resolves to a
18
+ * no-op so local-only features (thread locks, grants) degrade instead of crash.
19
+ */
20
+ export declare class RemoteSession {
21
+ #private;
22
+ constructor(address: FactoryAddress, resourceId: string, remote?: RemoteHandle);
23
+ /** Create/resume the remote session, hydrate the mirror, and open the event stream. */
24
+ connect(): Promise<void>;
25
+ /** Modes come from the controller; used to resolve the current mode's name and color. */
26
+ setModes(modes: RemoteMode[]): void;
27
+ disconnect(): void;
28
+ subscribe(listener: AgentControllerEventListener): () => void;
29
+ onBeforeAgentEnd(): () => void;
30
+ readonly identity: {
31
+ getResourceId: () => string;
32
+ getDefaultResourceId: () => string;
33
+ getId: () => string;
34
+ getOwnerId: () => string;
35
+ setResourceId: () => void;
36
+ };
37
+ readonly thread: {
38
+ getId: () => string | null;
39
+ isSet: () => boolean;
40
+ requireId: () => string;
41
+ ensureId: () => Promise<string>;
42
+ list: () => Promise<AgentControllerThread[]>;
43
+ getById: ({ threadId }: {
44
+ threadId: string;
45
+ }) => Promise<AgentControllerThread | null>;
46
+ create: ({ title }?: {
47
+ title?: string;
48
+ }) => Promise<AgentControllerThread>;
49
+ switch: ({ threadId }: {
50
+ threadId: string;
51
+ }) => Promise<void>;
52
+ clone: ({ sourceThreadId, title }?: {
53
+ sourceThreadId?: string;
54
+ title?: string;
55
+ }) => Promise<AgentControllerThread>;
56
+ rename: ({ title }: {
57
+ title: string;
58
+ }) => Promise<void>;
59
+ delete: ({ threadId }: {
60
+ threadId: string;
61
+ }) => Promise<void>;
62
+ listMessages: ({ threadId, limit }: {
63
+ threadId: string;
64
+ limit?: number;
65
+ }) => Promise<import("@mastra/client-js").MastraDBMessage[]>;
66
+ listActiveMessages: ({ limit }?: {
67
+ limit?: number;
68
+ }) => Promise<never[] | import("@mastra/client-js").MastraDBMessage[]>;
69
+ firstUserMessage: () => Promise<null>;
70
+ firstUserMessages: () => Promise<Map<any, any>>;
71
+ getSetting: () => Promise<undefined>;
72
+ getSettingOn: () => Promise<undefined>;
73
+ setSetting: () => Promise<void>;
74
+ setSettingOn: () => Promise<void>;
75
+ deleteSetting: () => Promise<void>;
76
+ cleanupSubscription: () => void;
77
+ detachFromCurrent: () => void;
78
+ clear: () => void;
79
+ clearAndReleaseLock: () => Promise<void>;
80
+ cloneToCurrentResource: ({ sourceThreadId }: {
81
+ sourceThreadId: string;
82
+ }) => Promise<AgentControllerThread>;
83
+ loadMetadata: () => Promise<void>;
84
+ };
85
+ readonly mode: {
86
+ get: () => string;
87
+ hasSelection: () => boolean;
88
+ resolve: () => {
89
+ id: string;
90
+ name?: string | undefined | undefined;
91
+ };
92
+ set: ({ modeId }: {
93
+ modeId: string;
94
+ }) => void;
95
+ switch: ({ modeId }: {
96
+ modeId: string;
97
+ }) => Promise<void>;
98
+ };
99
+ readonly model: {
100
+ get: () => string;
101
+ hasSelection: () => boolean;
102
+ displayName: () => string;
103
+ set: ({ modelId }: {
104
+ modelId: string;
105
+ }) => void;
106
+ switch: (modelId: string, options?: {
107
+ thinkingLevel?: any;
108
+ }) => Promise<void>;
109
+ syncFromPersisted: () => Promise<void>;
110
+ };
111
+ readonly state: {
112
+ get: () => Record<string, unknown>;
113
+ set: (updates: Record<string, unknown>) => Promise<void>;
114
+ setIf: (updates: Record<string, unknown>, shouldApply: () => boolean) => Promise<boolean>;
115
+ update: <TResult>(updater: AgentControllerRequestStateUpdater<any, TResult>) => Promise<TResult>;
116
+ };
117
+ readonly displayState: {
118
+ get: () => AgentControllerDisplayState;
119
+ clearModifiedFiles: () => void;
120
+ restoreTasks: () => void;
121
+ clearPendingSuspensions: () => void;
122
+ deletePendingSuspension: () => void;
123
+ clearPendingApprovals: () => void;
124
+ resetThread: () => void;
125
+ apply: () => void;
126
+ };
127
+ readonly run: {
128
+ isRunning: () => boolean;
129
+ getRunId: () => null;
130
+ getTraceId: () => null;
131
+ };
132
+ readonly stream: {
133
+ isActive: () => boolean;
134
+ isOpen: () => boolean;
135
+ };
136
+ readonly suspensions: {
137
+ hasPending: () => boolean;
138
+ get: ({ toolCallId }: {
139
+ toolCallId: string;
140
+ }) => {
141
+ toolCallId: string;
142
+ toolName: string;
143
+ args: unknown;
144
+ suspendPayload: unknown;
145
+ resumeSchema?: string;
146
+ resourceId?: string;
147
+ threadId?: string;
148
+ runId?: string;
149
+ } | undefined;
150
+ has: ({ toolCallId }: {
151
+ toolCallId: string;
152
+ }) => boolean;
153
+ delete: () => void;
154
+ };
155
+ readonly permissions: {
156
+ getRules: () => PermissionRules;
157
+ setForCategory: ({ category, policy }: {
158
+ category: any;
159
+ policy: any;
160
+ }) => Promise<void>;
161
+ setForTool: ({ toolName, policy }: {
162
+ toolName: string;
163
+ policy: any;
164
+ }) => Promise<void>;
165
+ };
166
+ getCurrentRunId(): string | null;
167
+ getTags(): Record<string, string>;
168
+ getTokenUsage(): import("@mastra/core/harness").TokenUsage;
169
+ getGrants(): {
170
+ categories: never[];
171
+ tools: never[];
172
+ };
173
+ sendMessage({ content, files }: {
174
+ content: string;
175
+ files?: Files;
176
+ }): Promise<void>;
177
+ queueMessage({ content }: {
178
+ content: string;
179
+ }): Promise<void>;
180
+ sendSignal(input: Parameters<Session['sendSignal']>[0]): {
181
+ id: `${string}-${string}-${string}-${string}-${string}`;
182
+ type: "user";
183
+ accepted: Promise<{
184
+ accepted: true;
185
+ }>;
186
+ persisted: Promise<void>;
187
+ };
188
+ steer({ content }: {
189
+ content: string;
190
+ }): Promise<void>;
191
+ followUp({ content }: {
192
+ content: string;
193
+ }): Promise<void>;
194
+ respondToToolApproval({ decision, toolCallId, }: {
195
+ decision: 'approve' | 'decline' | 'always_allow_category';
196
+ toolCallId: string;
197
+ }): {
198
+ accepted: true;
199
+ };
200
+ respondToToolSuspension({ resumeData, toolCallId }: {
201
+ resumeData: unknown;
202
+ toolCallId?: string;
203
+ }): Promise<void>;
204
+ claimToolResponse(): boolean;
205
+ releaseToolResponse(): void;
206
+ abort(): void;
207
+ abortRun(): void;
208
+ }
209
+ export {};
210
+ //# sourceMappingURL=remote-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-session.d.ts","sourceRoot":"","sources":["../../src/factory/remote-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,416 @@
1
+ import { createFactoryClient } from "./client.js";
2
+ import { randomUUID } from "crypto";
3
+ import { defaultDisplayState } from "@mastra/core/agent-controller";
4
+ //#region src/factory/remote-session.ts
5
+ const MAP_FIELDS = [
6
+ "activeTools",
7
+ "toolInputBuffers",
8
+ "pendingSuspensions",
9
+ "pendingApprovals",
10
+ "activeSubagents",
11
+ "modifiedFiles"
12
+ ];
13
+ /** The wire flattens the display state's Maps to objects; restore them. */
14
+ function hydrateDisplayState(wire) {
15
+ const state = {
16
+ ...defaultDisplayState(),
17
+ ...wire
18
+ };
19
+ for (const field of MAP_FIELDS) {
20
+ const value = wire[field];
21
+ state[field] = value instanceof Map ? value : new Map(Object.entries(value ?? {}));
22
+ }
23
+ return state;
24
+ }
25
+ /** The wire flattens errors to `{ name, message }`; restore them. */
26
+ function hydrateEvent(event) {
27
+ const out = { ...event };
28
+ if (out.displayState && typeof out.displayState === "object") out.displayState = hydrateDisplayState(out.displayState);
29
+ const error = out.error;
30
+ if (error && typeof error === "object" && !(error instanceof Error)) out.error = Object.assign(new Error(error.message ?? "Remote error"), { name: error.name ?? "Error" });
31
+ return out;
32
+ }
33
+ function toThread(thread, resourceId) {
34
+ const date = (value) => value ? new Date(value) : /* @__PURE__ */ new Date();
35
+ return {
36
+ id: thread.id,
37
+ resourceId: thread.resourceId ?? resourceId,
38
+ title: thread.title ?? "",
39
+ createdAt: date(thread.createdAt),
40
+ updatedAt: date(thread.updatedAt)
41
+ };
42
+ }
43
+ /**
44
+ * Stands in for an in-process `Session` while the agent, tools, and storage
45
+ * run inside a Factory. Reads are served from state mirrored off the session's
46
+ * event stream; every action is forwarded to the Factory over HTTP.
47
+ *
48
+ * Only the surface the TUI drives is implemented. Anything else resolves to a
49
+ * no-op so local-only features (thread locks, grants) degrade instead of crash.
50
+ */
51
+ var RemoteSession = class {
52
+ #remote;
53
+ #resourceId;
54
+ #listeners = /* @__PURE__ */ new Set();
55
+ #unsubscribe;
56
+ #threadId = null;
57
+ #modeId = "";
58
+ #modelId = "";
59
+ #running = false;
60
+ #state = {};
61
+ #displayState = defaultDisplayState();
62
+ #modes = [];
63
+ #permissionRules = {
64
+ categories: {},
65
+ tools: {}
66
+ };
67
+ #pendingUserIds = [];
68
+ #userIdMap = /* @__PURE__ */ new Map();
69
+ constructor(address, resourceId, remote) {
70
+ this.#resourceId = resourceId;
71
+ this.#remote = remote ?? createFactoryClient(address).getAgentController("code").session(resourceId);
72
+ }
73
+ /** Create/resume the remote session, hydrate the mirror, and open the event stream. */
74
+ async connect() {
75
+ await this.#remote.create();
76
+ await Promise.all([this.#hydrate(), this.#refreshPermissions()]);
77
+ const subscription = await this.#remote.subscribe({
78
+ reconnect: true,
79
+ onEvent: (event) => this.#receive(hydrateEvent(event)),
80
+ onReconnect: () => void this.#hydrate().catch(() => {})
81
+ });
82
+ this.#unsubscribe = subscription.unsubscribe;
83
+ }
84
+ /** Modes come from the controller; used to resolve the current mode's name and color. */
85
+ setModes(modes) {
86
+ this.#modes = modes;
87
+ }
88
+ disconnect() {
89
+ this.#unsubscribe?.();
90
+ this.#unsubscribe = void 0;
91
+ }
92
+ async #hydrate() {
93
+ const snapshot = await this.#remote.state();
94
+ this.#threadId = snapshot.threadId ?? null;
95
+ this.#modeId = snapshot.modeId;
96
+ this.#modelId = snapshot.modelId;
97
+ this.#running = Boolean(snapshot.running);
98
+ if (snapshot.settings) this.#state = {
99
+ ...this.#state,
100
+ ...snapshot.settings
101
+ };
102
+ this.#displayState = {
103
+ ...this.#displayState,
104
+ ...snapshot.tasks ? { tasks: snapshot.tasks } : {},
105
+ ...snapshot.tokenUsage ? { tokenUsage: snapshot.tokenUsage } : {}
106
+ };
107
+ }
108
+ async #refreshPermissions() {
109
+ const rules = await this.#remote.getPermissions();
110
+ this.#permissionRules = {
111
+ categories: rules.categories ?? {},
112
+ tools: rules.tools ?? {}
113
+ };
114
+ }
115
+ /** Surface a failed remote command in the transcript instead of dropping it. */
116
+ #emitError(message) {
117
+ this.#receive({
118
+ type: "error",
119
+ error: new Error(message)
120
+ });
121
+ }
122
+ /**
123
+ * The TUI renders a user message as soon as it is sent, keyed by the id
124
+ * `sendSignal` returned. The Factory echoes it back under its own id, so map
125
+ * that echo onto the local id to keep it from rendering twice.
126
+ */
127
+ #adoptLocalUserId(e) {
128
+ const message = e.message;
129
+ const isUser = message?.role === "user" || message?.role === "signal" && message.content?.metadata?.signal?.type === "user";
130
+ if (!message?.id || !isUser) return;
131
+ let localId = this.#userIdMap.get(message.id);
132
+ if (!localId && e.type === "message_start") {
133
+ localId = this.#pendingUserIds.shift();
134
+ if (localId) this.#userIdMap.set(message.id, localId);
135
+ }
136
+ if (localId) e.message = {
137
+ ...message,
138
+ id: localId
139
+ };
140
+ }
141
+ #receive(event) {
142
+ const e = event;
143
+ if (e.type === "message_start" || e.type === "message_update" || e.type === "message_end") this.#adoptLocalUserId(e);
144
+ switch (e.type) {
145
+ case "mode_changed":
146
+ this.#modeId = e.modeId;
147
+ break;
148
+ case "model_changed":
149
+ this.#modelId = e.modelId;
150
+ break;
151
+ case "thread_changed":
152
+ this.#threadId = e.threadId;
153
+ break;
154
+ case "thread_created":
155
+ this.#threadId = e.thread.id;
156
+ break;
157
+ case "state_changed":
158
+ this.#state = {
159
+ ...this.#state,
160
+ ...e.state
161
+ };
162
+ break;
163
+ case "display_state_changed":
164
+ this.#displayState = e.displayState;
165
+ break;
166
+ case "agent_start":
167
+ this.#running = true;
168
+ break;
169
+ case "agent_end":
170
+ this.#running = false;
171
+ break;
172
+ }
173
+ for (const listener of this.#listeners) Promise.resolve(listener(event)).catch(() => {});
174
+ }
175
+ subscribe(listener) {
176
+ this.#listeners.add(listener);
177
+ return () => this.#listeners.delete(listener);
178
+ }
179
+ onBeforeAgentEnd() {
180
+ return () => {};
181
+ }
182
+ identity = {
183
+ getResourceId: () => this.#resourceId,
184
+ getDefaultResourceId: () => this.#resourceId,
185
+ getId: () => this.#resourceId,
186
+ getOwnerId: () => this.#resourceId,
187
+ setResourceId: () => {}
188
+ };
189
+ thread = (() => {
190
+ const remote = () => this.#remote;
191
+ const resourceId = this.#resourceId;
192
+ return {
193
+ getId: () => this.#threadId,
194
+ isSet: () => this.#threadId !== null,
195
+ requireId: () => {
196
+ if (!this.#threadId) throw new Error("No active thread");
197
+ return this.#threadId;
198
+ },
199
+ ensureId: async () => {
200
+ if (!this.#threadId) await this.thread.create();
201
+ return this.#threadId;
202
+ },
203
+ list: async () => (await remote().listThreads()).map((t) => toThread(t, resourceId)),
204
+ getById: async ({ threadId }) => (await this.thread.list()).find((t) => t.id === threadId) ?? null,
205
+ create: async ({ title } = {}) => {
206
+ const thread = toThread(await remote().createThread(title), resourceId);
207
+ this.#threadId = thread.id;
208
+ return thread;
209
+ },
210
+ switch: async ({ threadId }) => {
211
+ await remote().switchThread(threadId);
212
+ this.#threadId = threadId;
213
+ },
214
+ clone: async ({ sourceThreadId, title } = {}) => {
215
+ const thread = toThread(await remote().cloneThread({
216
+ sourceThreadId,
217
+ title
218
+ }), resourceId);
219
+ this.#threadId = thread.id;
220
+ return thread;
221
+ },
222
+ rename: async ({ title }) => {
223
+ if (this.#threadId) await remote().renameThread(this.#threadId, title);
224
+ },
225
+ delete: async ({ threadId }) => {
226
+ await remote().deleteThread(threadId);
227
+ if (this.#threadId === threadId) this.#threadId = null;
228
+ },
229
+ listMessages: ({ threadId, limit }) => remote().listMessages(threadId, limit),
230
+ listActiveMessages: async ({ limit } = {}) => this.#threadId ? remote().listMessages(this.#threadId, limit) : [],
231
+ firstUserMessage: async () => null,
232
+ firstUserMessages: async () => /* @__PURE__ */ new Map(),
233
+ getSetting: async () => void 0,
234
+ getSettingOn: async () => void 0,
235
+ setSetting: async () => {},
236
+ setSettingOn: async () => {},
237
+ deleteSetting: async () => {},
238
+ cleanupSubscription: () => {},
239
+ detachFromCurrent: () => {},
240
+ clear: () => {
241
+ this.#threadId = null;
242
+ },
243
+ clearAndReleaseLock: async () => {},
244
+ cloneToCurrentResource: async ({ sourceThreadId }) => this.thread.clone({ sourceThreadId }),
245
+ loadMetadata: async () => {}
246
+ };
247
+ })();
248
+ mode = {
249
+ get: () => this.#modeId,
250
+ hasSelection: () => Boolean(this.#modeId),
251
+ resolve: () => this.#modes.find((mode) => mode.id === this.#modeId) ?? {
252
+ id: this.#modeId,
253
+ name: this.#modeId
254
+ },
255
+ set: ({ modeId }) => {
256
+ this.#modeId = modeId;
257
+ },
258
+ switch: async ({ modeId }) => {
259
+ await this.#remote.switchMode(modeId);
260
+ this.#modeId = modeId;
261
+ }
262
+ };
263
+ model = {
264
+ get: () => this.#modelId,
265
+ hasSelection: () => Boolean(this.#modelId),
266
+ displayName: () => this.#modelId,
267
+ set: ({ modelId }) => {
268
+ this.#modelId = modelId;
269
+ },
270
+ switch: async (modelId, options = {}) => {
271
+ await this.#remote.switchModel(modelId, options);
272
+ this.#modelId = modelId;
273
+ },
274
+ syncFromPersisted: async () => {}
275
+ };
276
+ state = {
277
+ get: () => this.#state,
278
+ set: async (updates) => {
279
+ this.#state = {
280
+ ...this.#state,
281
+ ...updates
282
+ };
283
+ await this.#remote.setState(updates);
284
+ },
285
+ setIf: async (updates, shouldApply) => {
286
+ if (!shouldApply()) return false;
287
+ await this.state.set(updates);
288
+ return true;
289
+ },
290
+ update: async (updater) => {
291
+ const { updates, result } = await updater(this.#state);
292
+ if (updates) await this.state.set(updates);
293
+ return result;
294
+ }
295
+ };
296
+ displayState = {
297
+ get: () => this.#displayState,
298
+ clearModifiedFiles: () => {
299
+ this.#displayState = {
300
+ ...this.#displayState,
301
+ modifiedFiles: /* @__PURE__ */ new Map()
302
+ };
303
+ },
304
+ restoreTasks: () => {},
305
+ clearPendingSuspensions: () => {},
306
+ deletePendingSuspension: () => {},
307
+ clearPendingApprovals: () => {},
308
+ resetThread: () => {},
309
+ apply: () => {}
310
+ };
311
+ run = {
312
+ isRunning: () => this.#running,
313
+ getRunId: () => null,
314
+ getTraceId: () => null
315
+ };
316
+ stream = {
317
+ isActive: () => this.#running,
318
+ isOpen: () => this.#running
319
+ };
320
+ suspensions = {
321
+ hasPending: () => this.#displayState.pendingSuspensions.size > 0,
322
+ get: ({ toolCallId }) => this.#displayState.pendingSuspensions.get(toolCallId),
323
+ has: ({ toolCallId }) => this.#displayState.pendingSuspensions.has(toolCallId),
324
+ delete: () => {}
325
+ };
326
+ permissions = {
327
+ getRules: () => this.#permissionRules,
328
+ setForCategory: async ({ category, policy }) => {
329
+ await this.#remote.setPermissionForCategory(category, policy);
330
+ await this.#refreshPermissions();
331
+ },
332
+ setForTool: async ({ toolName, policy }) => {
333
+ await this.#remote.setPermissionForTool(toolName, policy);
334
+ await this.#refreshPermissions();
335
+ }
336
+ };
337
+ getCurrentRunId() {
338
+ return null;
339
+ }
340
+ getTags() {
341
+ return {};
342
+ }
343
+ getTokenUsage() {
344
+ return this.#displayState.tokenUsage;
345
+ }
346
+ getGrants() {
347
+ return {
348
+ categories: [],
349
+ tools: []
350
+ };
351
+ }
352
+ async sendMessage({ content, files }) {
353
+ await this.#remote.sendMessage({
354
+ content,
355
+ files
356
+ });
357
+ }
358
+ async queueMessage({ content }) {
359
+ await this.#remote.followUp(content);
360
+ }
361
+ sendSignal(input) {
362
+ const content = "content" in input ? input.content : void 0;
363
+ const text = typeof content === "string" ? content : Array.isArray(content) ? content.map((part) => typeof part === "string" ? part : part?.text ?? "").join("") : JSON.stringify(content);
364
+ const files = "files" in input ? input.files : void 0;
365
+ const message = files?.length ? {
366
+ content: text,
367
+ files
368
+ } : text;
369
+ const id = randomUUID();
370
+ this.#pendingUserIds.push(id);
371
+ const sent = this.#running ? this.#remote.followUp(message) : this.#remote.sendMessage(message);
372
+ sent.catch(() => {
373
+ this.#pendingUserIds = this.#pendingUserIds.filter((pending) => pending !== id);
374
+ });
375
+ const accepted = sent.then(() => ({ accepted: true }));
376
+ accepted.catch(() => {});
377
+ return {
378
+ id,
379
+ type: "user",
380
+ accepted,
381
+ persisted: sent
382
+ };
383
+ }
384
+ async steer({ content }) {
385
+ await this.#remote.steer(content);
386
+ }
387
+ async followUp({ content }) {
388
+ await this.#remote.followUp(content);
389
+ }
390
+ respondToToolApproval({ decision, toolCallId }) {
391
+ (async () => {
392
+ const ack = await this.#remote.approveTool(toolCallId, decision !== "decline", { alwaysAllowCategory: decision === "always_allow_category" });
393
+ if (ack && "accepted" in ack && ack.accepted === false) this.#emitError(`Tool approval was not applied: ${ack.reason ?? "rejected"}`);
394
+ })().catch((error) => this.#emitError(`Tool approval failed: ${error instanceof Error ? error.message : String(error)}`));
395
+ return { accepted: true };
396
+ }
397
+ async respondToToolSuspension({ resumeData, toolCallId }) {
398
+ const id = toolCallId ?? this.#displayState.pendingSuspensions.keys().next().value;
399
+ if (!id) throw new Error("No pending tool suspension to respond to");
400
+ await this.#remote.respondToToolSuspension(id, resumeData);
401
+ }
402
+ claimToolResponse() {
403
+ return true;
404
+ }
405
+ releaseToolResponse() {}
406
+ abort() {
407
+ this.#remote.abort().catch((error) => this.#emitError(`Abort failed: ${error instanceof Error ? error.message : String(error)}`));
408
+ }
409
+ abortRun() {
410
+ this.abort();
411
+ }
412
+ };
413
+ //#endregion
414
+ export { RemoteSession };
415
+
416
+ //# sourceMappingURL=remote-session.js.map