@valon-technologies/gestalt 0.0.1-alpha.18 → 0.0.1-alpha.20

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/src/invoker.ts CHANGED
@@ -1,9 +1,9 @@
1
- import type { JsonObject, JsonValue } from "@bufbuild/protobuf";
2
1
  import { createClient, type Client, type Interceptor } from "@connectrpc/connect";
3
2
  import { createGrpcTransport } from "@connectrpc/connect-node";
4
3
 
5
4
  import { PluginInvoker as PluginInvokerService } from "./internal/gen/v1/plugin_pb.ts";
6
5
  import type { OperationResult, Request } from "./api.ts";
6
+ import { structFromObject, type JsonObjectInput } from "./protocol.ts";
7
7
 
8
8
  /** Environment variable containing the plugin-invoker host-service target. */
9
9
  export const ENV_PLUGIN_INVOKER_SOCKET = "GESTALT_PLUGIN_INVOKER_SOCKET";
@@ -37,7 +37,7 @@ export interface PluginInvocationGrant {
37
37
  /** Options for invoking a plugin GraphQL surface. */
38
38
  export interface PluginGraphQLInvokeOptions extends PluginInvokeOptions {
39
39
  /** GraphQL variables encoded as a JSON object. */
40
- variables?: Record<string, unknown>;
40
+ variables?: JsonObjectInput;
41
41
  }
42
42
 
43
43
  /**
@@ -72,14 +72,14 @@ export class PluginInvoker {
72
72
  async invoke(
73
73
  plugin: string,
74
74
  operation: string,
75
- params: Record<string, unknown> = {},
75
+ params: JsonObjectInput = {},
76
76
  options?: PluginInvokeOptions,
77
77
  ): Promise<OperationResult> {
78
78
  const response = await this.client.invoke({
79
79
  invocationToken: this.invocationToken,
80
80
  plugin,
81
81
  operation,
82
- params: toJsonObject(params),
82
+ params: structFromObject(params),
83
83
  connection: options?.connection ?? "",
84
84
  instance: options?.instance ?? "",
85
85
  idempotencyKey: options?.idempotencyKey?.trim() ?? "",
@@ -105,8 +105,8 @@ export class PluginInvoker {
105
105
  invocationToken: this.invocationToken,
106
106
  plugin,
107
107
  document: trimmedDocument,
108
- ...(options?.variables
109
- ? { variables: toJsonObject(options.variables) }
108
+ ...(options?.variables !== undefined
109
+ ? { variables: structFromObject(options.variables) }
110
110
  : {}),
111
111
  connection: options?.connection ?? "",
112
112
  instance: options?.instance ?? "",
@@ -199,32 +199,3 @@ function normalizeInvocationToken(requestOrToken: Request | string): string {
199
199
  }
200
200
  return trimmed;
201
201
  }
202
-
203
- function toJsonObject(params: Record<string, unknown>): JsonObject {
204
- const output: JsonObject = {};
205
- for (const [key, value] of Object.entries(params ?? {})) {
206
- if (value === undefined) {
207
- continue;
208
- }
209
- output[key] = toJsonValue(value);
210
- }
211
- return output;
212
- }
213
-
214
- function toJsonValue(value: unknown): JsonValue {
215
- if (
216
- value === null ||
217
- typeof value === "string" ||
218
- typeof value === "number" ||
219
- typeof value === "boolean"
220
- ) {
221
- return value as JsonValue;
222
- }
223
- if (Array.isArray(value)) {
224
- return value.map((entry) => toJsonValue(entry));
225
- }
226
- if (typeof value === "object") {
227
- return toJsonObject(value as Record<string, unknown>);
228
- }
229
- throw new Error("plugin invoker: params must be JSON-serializable");
230
- }
package/src/plugin.ts CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  type Request,
15
15
  responseBrand,
16
16
  type Response,
17
- type Subject,
17
+ type SubjectInput,
18
18
  } from "./api.ts";
19
19
  import {
20
20
  cloneHTTPSubjectRequest,
@@ -24,9 +24,9 @@ import {
24
24
  type HTTPSubjectResolver,
25
25
  } from "./http-subject.ts";
26
26
  import {
27
- isRuntimeProvider,
28
- RuntimeProvider,
29
- type RuntimeProviderOptions,
27
+ isProviderBase,
28
+ ProviderBase,
29
+ type ProviderBaseOptions,
30
30
  } from "./provider.ts";
31
31
  import type { Schema } from "./schema.ts";
32
32
 
@@ -36,8 +36,8 @@ import type { Schema } from "./schema.ts";
36
36
  export type ConnectionMode =
37
37
  | "unspecified"
38
38
  | "none"
39
- | "user"
40
- | "platform";
39
+ | "subject"
40
+ | "user";
41
41
 
42
42
  /**
43
43
  * Metadata for a single connection parameter exposed by a provider.
@@ -118,7 +118,7 @@ export type PostConnectHandler = (
118
118
  /**
119
119
  * Runtime hooks required to implement a plugin provider.
120
120
  */
121
- export interface PluginDefinitionOptions extends RuntimeProviderOptions {
121
+ export interface PluginDefinitionOptions extends ProviderBaseOptions {
122
122
  connectionMode?: ConnectionMode;
123
123
  authTypes?: string[];
124
124
  connectionParams?: Record<string, ConnectionParamDefinition>;
@@ -170,7 +170,7 @@ export function operation<In, Out>(
170
170
  * });
171
171
  * ```
172
172
  */
173
- export class PluginProvider extends RuntimeProvider {
173
+ export class PluginProvider extends ProviderBase {
174
174
  readonly kind = "integration" as const;
175
175
  readonly iconSvg: string;
176
176
  readonly connectionMode: ConnectionMode;
@@ -243,7 +243,7 @@ export class PluginProvider extends RuntimeProvider {
243
243
  async resolveHTTPSubject(
244
244
  request: HTTPSubjectRequest,
245
245
  context: HTTPSubjectResolutionContext,
246
- ): Promise<Subject | null | undefined> {
246
+ ): Promise<SubjectInput | null | undefined> {
247
247
  return await this.httpSubjectResolver?.(
248
248
  cloneHTTPSubjectRequest(request),
249
249
  cloneHTTPSubjectResolutionContext(context),
@@ -390,7 +390,7 @@ export function isPluginProvider(
390
390
  ): value is PluginProvider {
391
391
  return (
392
392
  value instanceof PluginProvider ||
393
- (isRuntimeProvider(value) &&
393
+ (isProviderBase(value) &&
394
394
  "kind" in value &&
395
395
  (value as { kind?: unknown }).kind === "integration" &&
396
396
  "staticCatalog" in value &&
@@ -513,10 +513,10 @@ export function connectionModeToProtoValue(mode: ConnectionMode): number {
513
513
  switch (mode) {
514
514
  case "none":
515
515
  return 1;
516
+ case "subject":
517
+ return 2;
516
518
  case "user":
517
519
  return 2;
518
- case "platform":
519
- return 5;
520
520
  case "unspecified":
521
521
  default:
522
522
  return 0;
@@ -1,4 +1,4 @@
1
- import { create, type MessageInitShape } from "@bufbuild/protobuf";
1
+ import { create } from "@bufbuild/protobuf";
2
2
  import { EmptySchema } from "@bufbuild/protobuf/wkt";
3
3
  import {
4
4
  Code,
@@ -9,52 +9,155 @@ import {
9
9
  import {
10
10
  HostedPluginSchema,
11
11
  ListPluginRuntimeSessionsResponseSchema,
12
- PluginRuntimeEgressMode,
12
+ PreparePluginRuntimeWorkspaceResponseSchema,
13
+ PluginRuntimeEgressMode as ProtoPluginRuntimeEgressMode,
13
14
  PluginRuntimeProvider as PluginRuntimeProviderService,
14
15
  PluginRuntimeSessionSchema,
15
16
  PluginRuntimeSupportSchema,
16
- type GetPluginRuntimeSessionRequest,
17
- type HostedPlugin,
18
- type ListPluginRuntimeSessionsRequest,
19
- type PluginRuntimeSession,
20
- type PluginRuntimeSupport,
21
- type StartHostedPluginRequest,
22
- type StartPluginRuntimeSessionRequest,
23
- type StopPluginRuntimeSessionRequest,
17
+ type GetPluginRuntimeSessionRequest as ProtoGetPluginRuntimeSessionRequest,
18
+ type ListPluginRuntimeSessionsRequest as ProtoListPluginRuntimeSessionsRequest,
19
+ type PreparePluginRuntimeWorkspaceRequest as ProtoPreparePluginRuntimeWorkspaceRequest,
20
+ type RemovePluginRuntimeWorkspaceRequest as ProtoRemovePluginRuntimeWorkspaceRequest,
21
+ type StartHostedPluginRequest as ProtoStartHostedPluginRequest,
22
+ type StartPluginRuntimeSessionRequest as ProtoStartPluginRuntimeSessionRequest,
23
+ type StopPluginRuntimeSessionRequest as ProtoStopPluginRuntimeSessionRequest,
24
24
  } from "./internal/gen/v1/pluginruntime_pb.ts";
25
+ import {
26
+ timestampFromDate,
27
+ } from "./protocol.ts";
25
28
  import { errorMessage, type MaybePromise } from "./api.ts";
26
- import { RuntimeProvider, type RuntimeProviderOptions } from "./provider.ts";
27
-
28
- export type {
29
- GetPluginRuntimeSessionRequest,
30
- HostedPlugin,
31
- ListPluginRuntimeSessionsRequest,
32
- PluginRuntimeSession,
33
- PluginRuntimeSupport,
34
- StartHostedPluginRequest,
35
- StartPluginRuntimeSessionRequest,
36
- StopPluginRuntimeSessionRequest,
37
- };
38
- export { PluginRuntimeEgressMode };
39
-
40
- export interface PluginRuntimeProviderOptions extends RuntimeProviderOptions {
41
- getSupport: () => MaybePromise<MessageInitShape<typeof PluginRuntimeSupportSchema>>;
29
+ import { ProviderBase, type ProviderBaseOptions } from "./provider.ts";
30
+
31
+ type PluginRuntimeProviderServiceImpl = Partial<
32
+ ServiceImpl<typeof PluginRuntimeProviderService>
33
+ >;
34
+
35
+ /** Native egress-mode constants for authored plugin runtime providers. */
36
+ export const PluginRuntimeEgressMode = {
37
+ UNSPECIFIED: ProtoPluginRuntimeEgressMode.UNSPECIFIED,
38
+ NONE: ProtoPluginRuntimeEgressMode.NONE,
39
+ CIDR: ProtoPluginRuntimeEgressMode.CIDR,
40
+ HOSTNAME: ProtoPluginRuntimeEgressMode.HOSTNAME,
41
+ } as const;
42
+ export type PluginRuntimeEgressMode =
43
+ (typeof PluginRuntimeEgressMode)[keyof typeof PluginRuntimeEgressMode];
44
+
45
+ export interface PluginRuntimeSupport {
46
+ canHostPlugins?: boolean | undefined;
47
+ egressMode?: PluginRuntimeEgressMode | undefined;
48
+ supportsPrepareWorkspace?: boolean | undefined;
49
+ }
50
+
51
+ export interface PluginRuntimeSessionLifecycle {
52
+ startedAt?: Date | undefined;
53
+ recommendedDrainAt?: Date | undefined;
54
+ expiresAt?: Date | undefined;
55
+ }
56
+
57
+ export interface PluginRuntimeSession {
58
+ id?: string | undefined;
59
+ state?: string | undefined;
60
+ metadata?: Record<string, string> | undefined;
61
+ lifecycle?: PluginRuntimeSessionLifecycle | undefined;
62
+ stateReason?: string | undefined;
63
+ stateMessage?: string | undefined;
64
+ }
65
+
66
+ export interface PluginRuntimeImagePullAuth {
67
+ dockerConfigJson?: string | undefined;
68
+ }
69
+
70
+ export interface StartPluginRuntimeSessionRequest {
71
+ pluginName: string;
72
+ template?: string | undefined;
73
+ image?: string | undefined;
74
+ metadata?: Record<string, string> | undefined;
75
+ imagePullAuth?: PluginRuntimeImagePullAuth | undefined;
76
+ }
77
+
78
+ export interface GetPluginRuntimeSessionRequest {
79
+ sessionId: string;
80
+ }
81
+
82
+ export interface ListPluginRuntimeSessionsRequest {}
83
+
84
+ export interface StopPluginRuntimeSessionRequest {
85
+ sessionId: string;
86
+ }
87
+
88
+ export interface PluginRuntimeAgentWorkspaceGitCheckout {
89
+ url?: string | undefined;
90
+ ref?: string | undefined;
91
+ path?: string | undefined;
92
+ }
93
+
94
+ export interface PluginRuntimeAgentWorkspace {
95
+ checkouts?: readonly PluginRuntimeAgentWorkspaceGitCheckout[] | undefined;
96
+ cwd?: string | undefined;
97
+ }
98
+
99
+ export interface PluginRuntimePreparedAgentWorkspace {
100
+ root?: string | undefined;
101
+ cwd?: string | undefined;
102
+ }
103
+
104
+ export interface PreparePluginRuntimeWorkspaceRequest {
105
+ sessionId: string;
106
+ agentSessionId: string;
107
+ workspace?: PluginRuntimeAgentWorkspace | undefined;
108
+ }
109
+
110
+ export interface PreparePluginRuntimeWorkspaceResponse {
111
+ workspace?: PluginRuntimePreparedAgentWorkspace | undefined;
112
+ }
113
+
114
+ export interface RemovePluginRuntimeWorkspaceRequest {
115
+ sessionId: string;
116
+ agentSessionId: string;
117
+ }
118
+
119
+ export interface StartHostedPluginRequest {
120
+ sessionId: string;
121
+ pluginName: string;
122
+ command?: string | undefined;
123
+ args?: readonly string[] | undefined;
124
+ env?: Record<string, string> | undefined;
125
+ allowedHosts?: readonly string[] | undefined;
126
+ defaultAction?: string | undefined;
127
+ hostBinary?: string | undefined;
128
+ }
129
+
130
+ export interface HostedPlugin {
131
+ id?: string | undefined;
132
+ sessionId?: string | undefined;
133
+ pluginName?: string | undefined;
134
+ dialTarget?: string | undefined;
135
+ }
136
+
137
+ export interface PluginRuntimeProviderOptions extends ProviderBaseOptions {
138
+ getSupport: () => MaybePromise<PluginRuntimeSupport>;
42
139
  startSession: (
43
140
  request: StartPluginRuntimeSessionRequest,
44
- ) => MaybePromise<MessageInitShape<typeof PluginRuntimeSessionSchema>>;
141
+ ) => MaybePromise<PluginRuntimeSession>;
45
142
  getSession: (
46
143
  request: GetPluginRuntimeSessionRequest,
47
- ) => MaybePromise<MessageInitShape<typeof PluginRuntimeSessionSchema>>;
144
+ ) => MaybePromise<PluginRuntimeSession>;
48
145
  listSessions: (
49
146
  request: ListPluginRuntimeSessionsRequest,
50
- ) => MaybePromise<MessageInitShape<typeof PluginRuntimeSessionSchema>[]>;
147
+ ) => MaybePromise<readonly PluginRuntimeSession[]>;
51
148
  stopSession: (request: StopPluginRuntimeSessionRequest) => MaybePromise<void>;
149
+ prepareWorkspace?: (
150
+ request: PreparePluginRuntimeWorkspaceRequest,
151
+ ) => MaybePromise<PreparePluginRuntimeWorkspaceResponse>;
152
+ removeWorkspace?: (
153
+ request: RemovePluginRuntimeWorkspaceRequest,
154
+ ) => MaybePromise<void>;
52
155
  startPlugin: (
53
156
  request: StartHostedPluginRequest,
54
- ) => MaybePromise<MessageInitShape<typeof HostedPluginSchema>>;
157
+ ) => MaybePromise<HostedPlugin>;
55
158
  }
56
159
 
57
- export class PluginRuntimeProvider extends RuntimeProvider {
160
+ export class PluginRuntimeProvider extends ProviderBase {
58
161
  readonly kind = "runtime" as const;
59
162
 
60
163
  private readonly getSupportHandler: PluginRuntimeProviderOptions["getSupport"];
@@ -62,6 +165,8 @@ export class PluginRuntimeProvider extends RuntimeProvider {
62
165
  private readonly getSessionHandler: PluginRuntimeProviderOptions["getSession"];
63
166
  private readonly listSessionsHandler: PluginRuntimeProviderOptions["listSessions"];
64
167
  private readonly stopSessionHandler: PluginRuntimeProviderOptions["stopSession"];
168
+ private readonly prepareWorkspaceHandler: PluginRuntimeProviderOptions["prepareWorkspace"];
169
+ private readonly removeWorkspaceHandler: PluginRuntimeProviderOptions["removeWorkspace"];
65
170
  private readonly startPluginHandler: PluginRuntimeProviderOptions["startPlugin"];
66
171
 
67
172
  constructor(options: PluginRuntimeProviderOptions) {
@@ -71,28 +176,30 @@ export class PluginRuntimeProvider extends RuntimeProvider {
71
176
  this.getSessionHandler = options.getSession;
72
177
  this.listSessionsHandler = options.listSessions;
73
178
  this.stopSessionHandler = options.stopSession;
179
+ this.prepareWorkspaceHandler = options.prepareWorkspace;
180
+ this.removeWorkspaceHandler = options.removeWorkspace;
74
181
  this.startPluginHandler = options.startPlugin;
75
182
  }
76
183
 
77
- async getSupport(): Promise<MessageInitShape<typeof PluginRuntimeSupportSchema>> {
184
+ async getSupport(): Promise<PluginRuntimeSupport> {
78
185
  return await this.getSupportHandler();
79
186
  }
80
187
 
81
188
  async startSession(
82
189
  request: StartPluginRuntimeSessionRequest,
83
- ): Promise<MessageInitShape<typeof PluginRuntimeSessionSchema>> {
190
+ ): Promise<PluginRuntimeSession> {
84
191
  return await this.startSessionHandler(request);
85
192
  }
86
193
 
87
194
  async getSession(
88
195
  request: GetPluginRuntimeSessionRequest,
89
- ): Promise<MessageInitShape<typeof PluginRuntimeSessionSchema>> {
196
+ ): Promise<PluginRuntimeSession> {
90
197
  return await this.getSessionHandler(request);
91
198
  }
92
199
 
93
200
  async listSessions(
94
201
  request: ListPluginRuntimeSessionsRequest,
95
- ): Promise<MessageInitShape<typeof PluginRuntimeSessionSchema>[]> {
202
+ ): Promise<readonly PluginRuntimeSession[]> {
96
203
  return await this.listSessionsHandler(request);
97
204
  }
98
205
 
@@ -100,9 +207,33 @@ export class PluginRuntimeProvider extends RuntimeProvider {
100
207
  await this.stopSessionHandler(request);
101
208
  }
102
209
 
210
+ async prepareWorkspace(
211
+ request: PreparePluginRuntimeWorkspaceRequest,
212
+ ): Promise<PreparePluginRuntimeWorkspaceResponse> {
213
+ if (!this.prepareWorkspaceHandler) {
214
+ throw new ConnectError(
215
+ "plugin runtime provider prepare workspace is not implemented",
216
+ Code.Unimplemented,
217
+ );
218
+ }
219
+ return await this.prepareWorkspaceHandler(request);
220
+ }
221
+
222
+ async removeWorkspace(
223
+ request: RemovePluginRuntimeWorkspaceRequest,
224
+ ): Promise<void> {
225
+ if (!this.removeWorkspaceHandler) {
226
+ throw new ConnectError(
227
+ "plugin runtime provider remove workspace is not implemented",
228
+ Code.Unimplemented,
229
+ );
230
+ }
231
+ await this.removeWorkspaceHandler(request);
232
+ }
233
+
103
234
  async startPlugin(
104
235
  request: StartHostedPluginRequest,
105
- ): Promise<MessageInitShape<typeof HostedPluginSchema>> {
236
+ ): Promise<HostedPlugin> {
106
237
  return await this.startPluginHandler(request);
107
238
  }
108
239
  }
@@ -130,56 +261,210 @@ export function isPluginRuntimeProvider(
130
261
 
131
262
  export function createPluginRuntimeProviderService(
132
263
  provider: PluginRuntimeProvider,
133
- ): Partial<ServiceImpl<typeof PluginRuntimeProviderService>> {
264
+ ): PluginRuntimeProviderServiceImpl {
134
265
  return {
135
266
  async getSupport() {
136
267
  return create(
137
268
  PluginRuntimeSupportSchema,
138
- await invokePluginRuntimeProvider("get support", () =>
139
- provider.getSupport(),
269
+ pluginRuntimeSupportToProto(
270
+ await invokePluginRuntimeProvider("get support", () =>
271
+ provider.getSupport(),
272
+ ),
140
273
  ),
141
274
  );
142
275
  },
143
276
  async startSession(request) {
144
277
  return create(
145
278
  PluginRuntimeSessionSchema,
146
- await invokePluginRuntimeProvider("start session", () =>
147
- provider.startSession(request),
279
+ pluginRuntimeSessionToProto(
280
+ await invokePluginRuntimeProvider("start session", () =>
281
+ provider.startSession(startSessionRequestFromProto(request)),
282
+ ),
148
283
  ),
149
284
  );
150
285
  },
151
286
  async getSession(request) {
152
287
  return create(
153
288
  PluginRuntimeSessionSchema,
154
- await invokePluginRuntimeProvider("get session", () =>
155
- provider.getSession(request),
289
+ pluginRuntimeSessionToProto(
290
+ await invokePluginRuntimeProvider("get session", () =>
291
+ provider.getSession(getSessionRequestFromProto(request)),
292
+ ),
156
293
  ),
157
294
  );
158
295
  },
159
296
  async listSessions(request) {
160
297
  return create(ListPluginRuntimeSessionsResponseSchema, {
161
- sessions: await invokePluginRuntimeProvider("list sessions", () =>
162
- provider.listSessions(request),
163
- ),
298
+ sessions: (
299
+ await invokePluginRuntimeProvider("list sessions", () =>
300
+ provider.listSessions(listSessionsRequestFromProto(request)),
301
+ )
302
+ ).map(pluginRuntimeSessionToProto),
164
303
  });
165
304
  },
166
305
  async stopSession(request) {
167
306
  await invokePluginRuntimeProvider("stop session", () =>
168
- provider.stopSession(request),
307
+ provider.stopSession(stopSessionRequestFromProto(request)),
308
+ );
309
+ return create(EmptySchema);
310
+ },
311
+ async prepareWorkspace(request) {
312
+ return create(
313
+ PreparePluginRuntimeWorkspaceResponseSchema,
314
+ prepareWorkspaceResponseToProto(
315
+ await invokePluginRuntimeProvider("prepare workspace", () =>
316
+ provider.prepareWorkspace(prepareWorkspaceRequestFromProto(request)),
317
+ ),
318
+ ),
319
+ );
320
+ },
321
+ async removeWorkspace(request) {
322
+ await invokePluginRuntimeProvider("remove workspace", () =>
323
+ provider.removeWorkspace(removeWorkspaceRequestFromProto(request)),
169
324
  );
170
325
  return create(EmptySchema);
171
326
  },
172
327
  async startPlugin(request) {
173
328
  return create(
174
329
  HostedPluginSchema,
175
- await invokePluginRuntimeProvider("start plugin", () =>
176
- provider.startPlugin(request),
330
+ hostedPluginToProto(
331
+ await invokePluginRuntimeProvider("start plugin", () =>
332
+ provider.startPlugin(startHostedPluginRequestFromProto(request)),
333
+ ),
177
334
  ),
178
335
  );
179
336
  },
180
337
  };
181
338
  }
182
339
 
340
+ function startSessionRequestFromProto(
341
+ request: ProtoStartPluginRuntimeSessionRequest,
342
+ ): StartPluginRuntimeSessionRequest {
343
+ return {
344
+ pluginName: request.pluginName,
345
+ template: request.template,
346
+ image: request.image,
347
+ metadata: { ...request.metadata },
348
+ imagePullAuth: request.imagePullAuth === undefined
349
+ ? undefined
350
+ : { dockerConfigJson: request.imagePullAuth.dockerConfigJson },
351
+ };
352
+ }
353
+
354
+ function getSessionRequestFromProto(
355
+ request: ProtoGetPluginRuntimeSessionRequest,
356
+ ): GetPluginRuntimeSessionRequest {
357
+ return { sessionId: request.sessionId };
358
+ }
359
+
360
+ function listSessionsRequestFromProto(
361
+ _request: ProtoListPluginRuntimeSessionsRequest,
362
+ ): ListPluginRuntimeSessionsRequest {
363
+ return {};
364
+ }
365
+
366
+ function stopSessionRequestFromProto(
367
+ request: ProtoStopPluginRuntimeSessionRequest,
368
+ ): StopPluginRuntimeSessionRequest {
369
+ return { sessionId: request.sessionId };
370
+ }
371
+
372
+ function prepareWorkspaceRequestFromProto(
373
+ request: ProtoPreparePluginRuntimeWorkspaceRequest,
374
+ ): PreparePluginRuntimeWorkspaceRequest {
375
+ return {
376
+ sessionId: request.sessionId,
377
+ agentSessionId: request.agentSessionId,
378
+ workspace: request.workspace === undefined
379
+ ? undefined
380
+ : {
381
+ checkouts: request.workspace.checkouts.map((checkout) => ({
382
+ url: checkout.url,
383
+ ref: checkout.ref,
384
+ path: checkout.path,
385
+ })),
386
+ cwd: request.workspace.cwd,
387
+ },
388
+ };
389
+ }
390
+
391
+ function removeWorkspaceRequestFromProto(
392
+ request: ProtoRemovePluginRuntimeWorkspaceRequest,
393
+ ): RemovePluginRuntimeWorkspaceRequest {
394
+ return {
395
+ sessionId: request.sessionId,
396
+ agentSessionId: request.agentSessionId,
397
+ };
398
+ }
399
+
400
+ function startHostedPluginRequestFromProto(
401
+ request: ProtoStartHostedPluginRequest,
402
+ ): StartHostedPluginRequest {
403
+ return {
404
+ sessionId: request.sessionId,
405
+ pluginName: request.pluginName,
406
+ command: request.command,
407
+ args: [...request.args],
408
+ env: { ...request.env },
409
+ allowedHosts: [...request.allowedHosts],
410
+ defaultAction: request.defaultAction,
411
+ hostBinary: request.hostBinary,
412
+ };
413
+ }
414
+
415
+ function pluginRuntimeSupportToProto(support: PluginRuntimeSupport) {
416
+ return {
417
+ canHostPlugins: support.canHostPlugins ?? false,
418
+ egressMode: support.egressMode ?? PluginRuntimeEgressMode.UNSPECIFIED,
419
+ supportsPrepareWorkspace: support.supportsPrepareWorkspace ?? false,
420
+ };
421
+ }
422
+
423
+ function pluginRuntimeSessionToProto(session: PluginRuntimeSession) {
424
+ return {
425
+ id: session.id ?? "",
426
+ state: session.state ?? "",
427
+ metadata: { ...(session.metadata ?? {}) },
428
+ lifecycle: session.lifecycle === undefined
429
+ ? undefined
430
+ : {
431
+ startedAt: session.lifecycle.startedAt === undefined
432
+ ? undefined
433
+ : timestampFromDate(session.lifecycle.startedAt),
434
+ recommendedDrainAt: session.lifecycle.recommendedDrainAt === undefined
435
+ ? undefined
436
+ : timestampFromDate(session.lifecycle.recommendedDrainAt),
437
+ expiresAt: session.lifecycle.expiresAt === undefined
438
+ ? undefined
439
+ : timestampFromDate(session.lifecycle.expiresAt),
440
+ },
441
+ stateReason: session.stateReason ?? "",
442
+ stateMessage: session.stateMessage ?? "",
443
+ };
444
+ }
445
+
446
+ function prepareWorkspaceResponseToProto(
447
+ response: PreparePluginRuntimeWorkspaceResponse,
448
+ ) {
449
+ return {
450
+ workspace: response.workspace === undefined
451
+ ? undefined
452
+ : {
453
+ root: response.workspace.root ?? "",
454
+ cwd: response.workspace.cwd ?? "",
455
+ },
456
+ };
457
+ }
458
+
459
+ function hostedPluginToProto(plugin: HostedPlugin) {
460
+ return {
461
+ id: plugin.id ?? "",
462
+ sessionId: plugin.sessionId ?? "",
463
+ pluginName: plugin.pluginName ?? "",
464
+ dialTarget: plugin.dialTarget ?? "",
465
+ };
466
+ }
467
+
183
468
  async function invokePluginRuntimeProvider<T>(
184
469
  label: string,
185
470
  fn: () => MaybePromise<T>,
@@ -187,6 +472,9 @@ async function invokePluginRuntimeProvider<T>(
187
472
  try {
188
473
  return await fn();
189
474
  } catch (error) {
475
+ if (error instanceof ConnectError) {
476
+ throw error;
477
+ }
190
478
  throw new ConnectError(
191
479
  `plugin runtime provider ${label}: ${errorMessage(error)}`,
192
480
  Code.Unknown,
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Low-level Gestalt v1 protocol bindings for advanced integration tests.
3
+ *
4
+ * Provider authoring code should prefer the root SDK exports. This module
5
+ * deliberately re-exports generated schemas, services, and message types for
6
+ * test harnesses and protocol fixtures.
7
+ */
8
+ export * from "../internal/gen/v1/agent_pb.ts";
9
+ export * from "../internal/gen/v1/authentication_pb.ts";
10
+ export * from "../internal/gen/v1/authorization_pb.ts";
11
+ export * from "../internal/gen/v1/cache_pb.ts";
12
+ export * from "../internal/gen/v1/datastore_pb.ts";
13
+ export * from "../internal/gen/v1/external_credential_pb.ts";
14
+ export * from "../internal/gen/v1/plugin_pb.ts";
15
+ export * from "../internal/gen/v1/pluginruntime_pb.ts";
16
+ export * from "../internal/gen/v1/runtime_pb.ts";
17
+ export * from "../internal/gen/v1/s3_pb.ts";
18
+ export * from "../internal/gen/v1/secrets_pb.ts";
19
+ export * from "../internal/gen/v1/workflow_pb.ts";