@valon-technologies/gestalt 0.0.1-alpha.11 → 0.0.1-alpha.13
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/README.md +1 -1
- package/gen/v1/agent_pb.ts +1916 -0
- package/gen/v1/authentication_pb.ts +1 -1
- package/gen/v1/authorization_pb.ts +28 -28
- package/gen/v1/cache_pb.ts +4 -4
- package/gen/v1/datastore_pb.ts +10 -10
- package/gen/v1/external_credential_pb.ts +274 -0
- package/gen/v1/plugin_pb.ts +196 -36
- package/gen/v1/pluginruntime_pb.ts +593 -0
- package/gen/v1/runtime_pb.ts +18 -3
- package/gen/v1/s3_pb.ts +19 -19
- package/gen/v1/secrets_pb.ts +1 -1
- package/gen/v1/workflow_pb.ts +501 -68
- package/package.json +1 -1
- package/src/agent-manager.ts +247 -0
- package/src/agent.ts +492 -0
- package/src/authorization.ts +208 -0
- package/src/cache.ts +69 -9
- package/src/http-subject.ts +113 -0
- package/src/index.ts +104 -0
- package/src/indexeddb.ts +59 -6
- package/src/invoker.ts +49 -7
- package/src/manifest-metadata.ts +7 -1
- package/src/plugin.ts +125 -4
- package/src/provider-kind.ts +6 -0
- package/src/provider.ts +12 -1
- package/src/runtime.ts +233 -44
- package/src/s3.ts +90 -32
- package/src/workflow-manager.ts +162 -9
package/src/agent.ts
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
import { connect } from "node:net";
|
|
2
|
+
|
|
3
|
+
import { create, type MessageInitShape } from "@bufbuild/protobuf";
|
|
4
|
+
import {
|
|
5
|
+
Code,
|
|
6
|
+
ConnectError,
|
|
7
|
+
createClient,
|
|
8
|
+
type Client,
|
|
9
|
+
type ServiceImpl,
|
|
10
|
+
} from "@connectrpc/connect";
|
|
11
|
+
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
AgentExecutionStatus,
|
|
15
|
+
AgentHost as AgentHostService,
|
|
16
|
+
AgentInteractionSchema,
|
|
17
|
+
AgentInteractionState,
|
|
18
|
+
AgentInteractionType,
|
|
19
|
+
AgentMessagePartType,
|
|
20
|
+
AgentProvider as AgentProviderService,
|
|
21
|
+
AgentProviderCapabilitiesSchema,
|
|
22
|
+
AgentSessionSchema,
|
|
23
|
+
AgentSessionState,
|
|
24
|
+
AgentToolSourceMode,
|
|
25
|
+
AgentTurnEventSchema,
|
|
26
|
+
AgentTurnSchema,
|
|
27
|
+
GetAgentProviderCapabilitiesRequestSchema,
|
|
28
|
+
ListAgentProviderInteractionsResponseSchema,
|
|
29
|
+
ListAgentProviderSessionsResponseSchema,
|
|
30
|
+
ListAgentProviderTurnEventsResponseSchema,
|
|
31
|
+
ListAgentProviderTurnsResponseSchema,
|
|
32
|
+
type AgentActor,
|
|
33
|
+
type AgentInteraction,
|
|
34
|
+
type AgentMessage,
|
|
35
|
+
type AgentMessagePart,
|
|
36
|
+
type AgentMessagePartImageRef,
|
|
37
|
+
type AgentMessagePartToolCall,
|
|
38
|
+
type AgentMessagePartToolResult,
|
|
39
|
+
type AgentProviderCapabilities,
|
|
40
|
+
type AgentSession,
|
|
41
|
+
type AgentToolRef,
|
|
42
|
+
type AgentTurn,
|
|
43
|
+
type AgentTurnEvent,
|
|
44
|
+
type BoundAgentToolTarget,
|
|
45
|
+
type CancelAgentProviderTurnRequest,
|
|
46
|
+
type CreateAgentProviderSessionRequest,
|
|
47
|
+
type CreateAgentProviderTurnRequest,
|
|
48
|
+
type ExecuteAgentToolRequest,
|
|
49
|
+
type ExecuteAgentToolResponse,
|
|
50
|
+
type GetAgentProviderCapabilitiesRequest,
|
|
51
|
+
type GetAgentProviderInteractionRequest,
|
|
52
|
+
type GetAgentProviderSessionRequest,
|
|
53
|
+
type GetAgentProviderTurnRequest,
|
|
54
|
+
type ListAgentProviderInteractionsRequest,
|
|
55
|
+
type ListAgentProviderSessionsRequest,
|
|
56
|
+
type ListAgentProviderTurnEventsRequest,
|
|
57
|
+
type ListAgentProviderTurnsRequest,
|
|
58
|
+
type ResolveAgentProviderInteractionRequest,
|
|
59
|
+
type ResolvedAgentTool,
|
|
60
|
+
type UpdateAgentProviderSessionRequest,
|
|
61
|
+
} from "../gen/v1/agent_pb.ts";
|
|
62
|
+
import { errorMessage, type MaybePromise } from "./api.ts";
|
|
63
|
+
import { RuntimeProvider, type RuntimeProviderOptions } from "./provider.ts";
|
|
64
|
+
|
|
65
|
+
export const ENV_AGENT_HOST_SOCKET = "GESTALT_AGENT_HOST_SOCKET";
|
|
66
|
+
|
|
67
|
+
export type {
|
|
68
|
+
AgentActor,
|
|
69
|
+
AgentInteraction,
|
|
70
|
+
AgentMessage,
|
|
71
|
+
AgentMessagePart,
|
|
72
|
+
AgentMessagePartImageRef,
|
|
73
|
+
AgentMessagePartToolCall,
|
|
74
|
+
AgentMessagePartToolResult,
|
|
75
|
+
AgentProviderCapabilities,
|
|
76
|
+
AgentSession,
|
|
77
|
+
AgentToolRef,
|
|
78
|
+
AgentTurn,
|
|
79
|
+
AgentTurnEvent,
|
|
80
|
+
BoundAgentToolTarget,
|
|
81
|
+
CancelAgentProviderTurnRequest,
|
|
82
|
+
CreateAgentProviderSessionRequest,
|
|
83
|
+
CreateAgentProviderTurnRequest,
|
|
84
|
+
ExecuteAgentToolRequest,
|
|
85
|
+
ExecuteAgentToolResponse,
|
|
86
|
+
GetAgentProviderCapabilitiesRequest,
|
|
87
|
+
GetAgentProviderInteractionRequest,
|
|
88
|
+
GetAgentProviderSessionRequest,
|
|
89
|
+
GetAgentProviderTurnRequest,
|
|
90
|
+
ListAgentProviderInteractionsRequest,
|
|
91
|
+
ListAgentProviderSessionsRequest,
|
|
92
|
+
ListAgentProviderTurnEventsRequest,
|
|
93
|
+
ListAgentProviderTurnsRequest,
|
|
94
|
+
ResolveAgentProviderInteractionRequest,
|
|
95
|
+
ResolvedAgentTool,
|
|
96
|
+
UpdateAgentProviderSessionRequest,
|
|
97
|
+
};
|
|
98
|
+
export {
|
|
99
|
+
AgentExecutionStatus,
|
|
100
|
+
AgentInteractionState,
|
|
101
|
+
AgentInteractionType,
|
|
102
|
+
AgentMessagePartType,
|
|
103
|
+
AgentSessionState,
|
|
104
|
+
AgentToolSourceMode,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export interface AgentProviderOptions extends RuntimeProviderOptions {
|
|
108
|
+
createSession?: (
|
|
109
|
+
request: CreateAgentProviderSessionRequest,
|
|
110
|
+
) => MaybePromise<MessageInitShape<typeof AgentSessionSchema>>;
|
|
111
|
+
getSession?: (
|
|
112
|
+
request: GetAgentProviderSessionRequest,
|
|
113
|
+
) => MaybePromise<MessageInitShape<typeof AgentSessionSchema>>;
|
|
114
|
+
listSessions?: (
|
|
115
|
+
request: ListAgentProviderSessionsRequest,
|
|
116
|
+
) => MaybePromise<MessageInitShape<typeof AgentSessionSchema>[]>;
|
|
117
|
+
updateSession?: (
|
|
118
|
+
request: UpdateAgentProviderSessionRequest,
|
|
119
|
+
) => MaybePromise<MessageInitShape<typeof AgentSessionSchema>>;
|
|
120
|
+
createTurn?: (
|
|
121
|
+
request: CreateAgentProviderTurnRequest,
|
|
122
|
+
) => MaybePromise<MessageInitShape<typeof AgentTurnSchema>>;
|
|
123
|
+
getTurn?: (
|
|
124
|
+
request: GetAgentProviderTurnRequest,
|
|
125
|
+
) => MaybePromise<MessageInitShape<typeof AgentTurnSchema>>;
|
|
126
|
+
listTurns?: (
|
|
127
|
+
request: ListAgentProviderTurnsRequest,
|
|
128
|
+
) => MaybePromise<MessageInitShape<typeof AgentTurnSchema>[]>;
|
|
129
|
+
cancelTurn?: (
|
|
130
|
+
request: CancelAgentProviderTurnRequest,
|
|
131
|
+
) => MaybePromise<MessageInitShape<typeof AgentTurnSchema>>;
|
|
132
|
+
listTurnEvents?: (
|
|
133
|
+
request: ListAgentProviderTurnEventsRequest,
|
|
134
|
+
) => MaybePromise<MessageInitShape<typeof AgentTurnEventSchema>[]>;
|
|
135
|
+
getInteraction?: (
|
|
136
|
+
request: GetAgentProviderInteractionRequest,
|
|
137
|
+
) => MaybePromise<MessageInitShape<typeof AgentInteractionSchema>>;
|
|
138
|
+
listInteractions?: (
|
|
139
|
+
request: ListAgentProviderInteractionsRequest,
|
|
140
|
+
) => MaybePromise<MessageInitShape<typeof AgentInteractionSchema>[]>;
|
|
141
|
+
resolveInteraction?: (
|
|
142
|
+
request: ResolveAgentProviderInteractionRequest,
|
|
143
|
+
) => MaybePromise<MessageInitShape<typeof AgentInteractionSchema>>;
|
|
144
|
+
getCapabilities?: (
|
|
145
|
+
request: GetAgentProviderCapabilitiesRequest,
|
|
146
|
+
) => MaybePromise<MessageInitShape<typeof AgentProviderCapabilitiesSchema>>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export class AgentProvider extends RuntimeProvider {
|
|
150
|
+
readonly kind = "agent" as const;
|
|
151
|
+
|
|
152
|
+
private readonly createSessionHandler: AgentProviderOptions["createSession"];
|
|
153
|
+
private readonly getSessionHandler: AgentProviderOptions["getSession"];
|
|
154
|
+
private readonly listSessionsHandler: AgentProviderOptions["listSessions"];
|
|
155
|
+
private readonly updateSessionHandler: AgentProviderOptions["updateSession"];
|
|
156
|
+
private readonly createTurnHandler: AgentProviderOptions["createTurn"];
|
|
157
|
+
private readonly getTurnHandler: AgentProviderOptions["getTurn"];
|
|
158
|
+
private readonly listTurnsHandler: AgentProviderOptions["listTurns"];
|
|
159
|
+
private readonly cancelTurnHandler: AgentProviderOptions["cancelTurn"];
|
|
160
|
+
private readonly listTurnEventsHandler: AgentProviderOptions["listTurnEvents"];
|
|
161
|
+
private readonly getInteractionHandler: AgentProviderOptions["getInteraction"];
|
|
162
|
+
private readonly listInteractionsHandler: AgentProviderOptions["listInteractions"];
|
|
163
|
+
private readonly resolveInteractionHandler: AgentProviderOptions["resolveInteraction"];
|
|
164
|
+
private readonly getCapabilitiesHandler: AgentProviderOptions["getCapabilities"];
|
|
165
|
+
|
|
166
|
+
constructor(options: AgentProviderOptions) {
|
|
167
|
+
super(options);
|
|
168
|
+
this.createSessionHandler = options.createSession;
|
|
169
|
+
this.getSessionHandler = options.getSession;
|
|
170
|
+
this.listSessionsHandler = options.listSessions;
|
|
171
|
+
this.updateSessionHandler = options.updateSession;
|
|
172
|
+
this.createTurnHandler = options.createTurn;
|
|
173
|
+
this.getTurnHandler = options.getTurn;
|
|
174
|
+
this.listTurnsHandler = options.listTurns;
|
|
175
|
+
this.cancelTurnHandler = options.cancelTurn;
|
|
176
|
+
this.listTurnEventsHandler = options.listTurnEvents;
|
|
177
|
+
this.getInteractionHandler = options.getInteraction;
|
|
178
|
+
this.listInteractionsHandler = options.listInteractions;
|
|
179
|
+
this.resolveInteractionHandler = options.resolveInteraction;
|
|
180
|
+
this.getCapabilitiesHandler = options.getCapabilities;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async createSession(
|
|
184
|
+
request: CreateAgentProviderSessionRequest,
|
|
185
|
+
): Promise<MessageInitShape<typeof AgentSessionSchema>> {
|
|
186
|
+
return await requireAgentProviderHandler(
|
|
187
|
+
"create session",
|
|
188
|
+
this.createSessionHandler,
|
|
189
|
+
request,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async getSession(
|
|
194
|
+
request: GetAgentProviderSessionRequest,
|
|
195
|
+
): Promise<MessageInitShape<typeof AgentSessionSchema>> {
|
|
196
|
+
return await requireAgentProviderHandler(
|
|
197
|
+
"get session",
|
|
198
|
+
this.getSessionHandler,
|
|
199
|
+
request,
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async listSessions(
|
|
204
|
+
request: ListAgentProviderSessionsRequest,
|
|
205
|
+
): Promise<MessageInitShape<typeof AgentSessionSchema>[]> {
|
|
206
|
+
return await requireAgentProviderHandler(
|
|
207
|
+
"list sessions",
|
|
208
|
+
this.listSessionsHandler,
|
|
209
|
+
request,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async updateSession(
|
|
214
|
+
request: UpdateAgentProviderSessionRequest,
|
|
215
|
+
): Promise<MessageInitShape<typeof AgentSessionSchema>> {
|
|
216
|
+
return await requireAgentProviderHandler(
|
|
217
|
+
"update session",
|
|
218
|
+
this.updateSessionHandler,
|
|
219
|
+
request,
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async createTurn(
|
|
224
|
+
request: CreateAgentProviderTurnRequest,
|
|
225
|
+
): Promise<MessageInitShape<typeof AgentTurnSchema>> {
|
|
226
|
+
return await requireAgentProviderHandler(
|
|
227
|
+
"create turn",
|
|
228
|
+
this.createTurnHandler,
|
|
229
|
+
request,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async getTurn(
|
|
234
|
+
request: GetAgentProviderTurnRequest,
|
|
235
|
+
): Promise<MessageInitShape<typeof AgentTurnSchema>> {
|
|
236
|
+
return await requireAgentProviderHandler(
|
|
237
|
+
"get turn",
|
|
238
|
+
this.getTurnHandler,
|
|
239
|
+
request,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async listTurns(
|
|
244
|
+
request: ListAgentProviderTurnsRequest,
|
|
245
|
+
): Promise<MessageInitShape<typeof AgentTurnSchema>[]> {
|
|
246
|
+
return await requireAgentProviderHandler(
|
|
247
|
+
"list turns",
|
|
248
|
+
this.listTurnsHandler,
|
|
249
|
+
request,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async cancelTurn(
|
|
254
|
+
request: CancelAgentProviderTurnRequest,
|
|
255
|
+
): Promise<MessageInitShape<typeof AgentTurnSchema>> {
|
|
256
|
+
return await requireAgentProviderHandler(
|
|
257
|
+
"cancel turn",
|
|
258
|
+
this.cancelTurnHandler,
|
|
259
|
+
request,
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async listTurnEvents(
|
|
264
|
+
request: ListAgentProviderTurnEventsRequest,
|
|
265
|
+
): Promise<MessageInitShape<typeof AgentTurnEventSchema>[]> {
|
|
266
|
+
return await requireAgentProviderHandler(
|
|
267
|
+
"list turn events",
|
|
268
|
+
this.listTurnEventsHandler,
|
|
269
|
+
request,
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async getInteraction(
|
|
274
|
+
request: GetAgentProviderInteractionRequest,
|
|
275
|
+
): Promise<MessageInitShape<typeof AgentInteractionSchema>> {
|
|
276
|
+
return await requireAgentProviderHandler(
|
|
277
|
+
"get interaction",
|
|
278
|
+
this.getInteractionHandler,
|
|
279
|
+
request,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async listInteractions(
|
|
284
|
+
request: ListAgentProviderInteractionsRequest,
|
|
285
|
+
): Promise<MessageInitShape<typeof AgentInteractionSchema>[]> {
|
|
286
|
+
return await requireAgentProviderHandler(
|
|
287
|
+
"list interactions",
|
|
288
|
+
this.listInteractionsHandler,
|
|
289
|
+
request,
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async resolveInteraction(
|
|
294
|
+
request: ResolveAgentProviderInteractionRequest,
|
|
295
|
+
): Promise<MessageInitShape<typeof AgentInteractionSchema>> {
|
|
296
|
+
return await requireAgentProviderHandler(
|
|
297
|
+
"resolve interaction",
|
|
298
|
+
this.resolveInteractionHandler,
|
|
299
|
+
request,
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async getCapabilities(
|
|
304
|
+
request: GetAgentProviderCapabilitiesRequest = create(
|
|
305
|
+
GetAgentProviderCapabilitiesRequestSchema,
|
|
306
|
+
{},
|
|
307
|
+
),
|
|
308
|
+
): Promise<MessageInitShape<typeof AgentProviderCapabilitiesSchema>> {
|
|
309
|
+
return await requireAgentProviderHandler(
|
|
310
|
+
"get capabilities",
|
|
311
|
+
this.getCapabilitiesHandler,
|
|
312
|
+
request,
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export function defineAgentProvider(options: AgentProviderOptions): AgentProvider {
|
|
318
|
+
return new AgentProvider(options);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function isAgentProvider(value: unknown): value is AgentProvider {
|
|
322
|
+
return (
|
|
323
|
+
value instanceof AgentProvider ||
|
|
324
|
+
(typeof value === "object" &&
|
|
325
|
+
value !== null &&
|
|
326
|
+
"kind" in value &&
|
|
327
|
+
(value as { kind?: unknown }).kind === "agent" &&
|
|
328
|
+
"createSession" in value &&
|
|
329
|
+
"createTurn" in value)
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export class AgentHost {
|
|
334
|
+
private readonly client: Client<typeof AgentHostService>;
|
|
335
|
+
|
|
336
|
+
constructor() {
|
|
337
|
+
const socketPath = process.env[ENV_AGENT_HOST_SOCKET];
|
|
338
|
+
if (!socketPath) {
|
|
339
|
+
throw new Error(`agent host: ${ENV_AGENT_HOST_SOCKET} is not set`);
|
|
340
|
+
}
|
|
341
|
+
const transport = createGrpcTransport({
|
|
342
|
+
baseUrl: "http://localhost",
|
|
343
|
+
nodeOptions: {
|
|
344
|
+
createConnection: () => connect(socketPath),
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
this.client = createClient(AgentHostService, transport);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
async executeTool(
|
|
351
|
+
request: ExecuteAgentToolRequest,
|
|
352
|
+
): Promise<ExecuteAgentToolResponse> {
|
|
353
|
+
return await this.client.executeTool(request);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export function createAgentProviderService(
|
|
359
|
+
provider: AgentProvider,
|
|
360
|
+
): Partial<ServiceImpl<typeof AgentProviderService>> {
|
|
361
|
+
return {
|
|
362
|
+
async createSession(request) {
|
|
363
|
+
return create(
|
|
364
|
+
AgentSessionSchema,
|
|
365
|
+
await invokeAgentProvider("create session", () =>
|
|
366
|
+
provider.createSession(request),
|
|
367
|
+
),
|
|
368
|
+
);
|
|
369
|
+
},
|
|
370
|
+
async getSession(request) {
|
|
371
|
+
return create(
|
|
372
|
+
AgentSessionSchema,
|
|
373
|
+
await invokeAgentProvider("get session", () =>
|
|
374
|
+
provider.getSession(request),
|
|
375
|
+
),
|
|
376
|
+
);
|
|
377
|
+
},
|
|
378
|
+
async listSessions(request) {
|
|
379
|
+
return create(ListAgentProviderSessionsResponseSchema, {
|
|
380
|
+
sessions: await invokeAgentProvider("list sessions", () =>
|
|
381
|
+
provider.listSessions(request),
|
|
382
|
+
),
|
|
383
|
+
});
|
|
384
|
+
},
|
|
385
|
+
async updateSession(request) {
|
|
386
|
+
return create(
|
|
387
|
+
AgentSessionSchema,
|
|
388
|
+
await invokeAgentProvider("update session", () =>
|
|
389
|
+
provider.updateSession(request),
|
|
390
|
+
),
|
|
391
|
+
);
|
|
392
|
+
},
|
|
393
|
+
async createTurn(request) {
|
|
394
|
+
return create(
|
|
395
|
+
AgentTurnSchema,
|
|
396
|
+
await invokeAgentProvider("create turn", () =>
|
|
397
|
+
provider.createTurn(request),
|
|
398
|
+
),
|
|
399
|
+
);
|
|
400
|
+
},
|
|
401
|
+
async getTurn(request) {
|
|
402
|
+
return create(
|
|
403
|
+
AgentTurnSchema,
|
|
404
|
+
await invokeAgentProvider("get turn", () => provider.getTurn(request)),
|
|
405
|
+
);
|
|
406
|
+
},
|
|
407
|
+
async listTurns(request) {
|
|
408
|
+
return create(ListAgentProviderTurnsResponseSchema, {
|
|
409
|
+
turns: await invokeAgentProvider("list turns", () =>
|
|
410
|
+
provider.listTurns(request),
|
|
411
|
+
),
|
|
412
|
+
});
|
|
413
|
+
},
|
|
414
|
+
async cancelTurn(request) {
|
|
415
|
+
return create(
|
|
416
|
+
AgentTurnSchema,
|
|
417
|
+
await invokeAgentProvider("cancel turn", () =>
|
|
418
|
+
provider.cancelTurn(request),
|
|
419
|
+
),
|
|
420
|
+
);
|
|
421
|
+
},
|
|
422
|
+
async listTurnEvents(request) {
|
|
423
|
+
return create(ListAgentProviderTurnEventsResponseSchema, {
|
|
424
|
+
events: await invokeAgentProvider("list turn events", () =>
|
|
425
|
+
provider.listTurnEvents(request),
|
|
426
|
+
),
|
|
427
|
+
});
|
|
428
|
+
},
|
|
429
|
+
async getInteraction(request) {
|
|
430
|
+
return create(
|
|
431
|
+
AgentInteractionSchema,
|
|
432
|
+
await invokeAgentProvider("get interaction", () =>
|
|
433
|
+
provider.getInteraction(request),
|
|
434
|
+
),
|
|
435
|
+
);
|
|
436
|
+
},
|
|
437
|
+
async listInteractions(request) {
|
|
438
|
+
return create(ListAgentProviderInteractionsResponseSchema, {
|
|
439
|
+
interactions: await invokeAgentProvider("list interactions", () =>
|
|
440
|
+
provider.listInteractions(request),
|
|
441
|
+
),
|
|
442
|
+
});
|
|
443
|
+
},
|
|
444
|
+
async resolveInteraction(request) {
|
|
445
|
+
return create(
|
|
446
|
+
AgentInteractionSchema,
|
|
447
|
+
await invokeAgentProvider("resolve interaction", () =>
|
|
448
|
+
provider.resolveInteraction(request),
|
|
449
|
+
),
|
|
450
|
+
);
|
|
451
|
+
},
|
|
452
|
+
async getCapabilities(request) {
|
|
453
|
+
return create(
|
|
454
|
+
AgentProviderCapabilitiesSchema,
|
|
455
|
+
await invokeAgentProvider("get capabilities", () =>
|
|
456
|
+
provider.getCapabilities(request),
|
|
457
|
+
),
|
|
458
|
+
);
|
|
459
|
+
},
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
async function requireAgentProviderHandler<Request, Response>(
|
|
464
|
+
action: string,
|
|
465
|
+
fn: ((request: Request) => MaybePromise<Response>) | undefined,
|
|
466
|
+
request: Request,
|
|
467
|
+
): Promise<Response> {
|
|
468
|
+
if (!fn) {
|
|
469
|
+
throw new ConnectError(
|
|
470
|
+
`agent provider ${action} is not implemented`,
|
|
471
|
+
Code.Unimplemented,
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
return await fn(request);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
async function invokeAgentProvider<T>(
|
|
478
|
+
action: string,
|
|
479
|
+
fn: () => Promise<T>,
|
|
480
|
+
): Promise<T> {
|
|
481
|
+
try {
|
|
482
|
+
return await fn();
|
|
483
|
+
} catch (error) {
|
|
484
|
+
if (error instanceof ConnectError) {
|
|
485
|
+
throw error;
|
|
486
|
+
}
|
|
487
|
+
throw new ConnectError(
|
|
488
|
+
`agent provider ${action}: ${errorMessage(error)}`,
|
|
489
|
+
Code.Unknown,
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { connect } from "node:net";
|
|
2
|
+
|
|
3
|
+
import type { MessageInitShape } from "@bufbuild/protobuf";
|
|
4
|
+
import {
|
|
5
|
+
createClient,
|
|
6
|
+
type Client,
|
|
7
|
+
type Interceptor,
|
|
8
|
+
} from "@connectrpc/connect";
|
|
9
|
+
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
type AccessDecision,
|
|
13
|
+
type ActionSearchResponse,
|
|
14
|
+
type AuthorizationMetadata,
|
|
15
|
+
AuthorizationProvider as AuthorizationProviderService,
|
|
16
|
+
type ReadRelationshipsResponse,
|
|
17
|
+
type ResourceSearchResponse,
|
|
18
|
+
type SubjectSearchResponse,
|
|
19
|
+
AccessEvaluationRequestSchema,
|
|
20
|
+
ActionSearchRequestSchema,
|
|
21
|
+
ReadRelationshipsRequestSchema,
|
|
22
|
+
ResourceSearchRequestSchema,
|
|
23
|
+
SubjectSearchRequestSchema,
|
|
24
|
+
} from "../gen/v1/authorization_pb.ts";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Environment variable containing the Unix socket path or relay target for the
|
|
28
|
+
* read-only host authorization client exposed to plugins.
|
|
29
|
+
*/
|
|
30
|
+
export const ENV_AUTHORIZATION_SOCKET = "GESTALT_AUTHORIZATION_SOCKET";
|
|
31
|
+
export const ENV_AUTHORIZATION_SOCKET_TOKEN =
|
|
32
|
+
`${ENV_AUTHORIZATION_SOCKET}_TOKEN`;
|
|
33
|
+
const AUTHORIZATION_RELAY_TOKEN_HEADER =
|
|
34
|
+
"x-gestalt-host-service-relay-token";
|
|
35
|
+
|
|
36
|
+
export type AuthorizationEvaluateInput = MessageInitShape<
|
|
37
|
+
typeof AccessEvaluationRequestSchema
|
|
38
|
+
>;
|
|
39
|
+
export type AuthorizationSearchResourcesInput = MessageInitShape<
|
|
40
|
+
typeof ResourceSearchRequestSchema
|
|
41
|
+
>;
|
|
42
|
+
export type AuthorizationSearchSubjectsInput = MessageInitShape<
|
|
43
|
+
typeof SubjectSearchRequestSchema
|
|
44
|
+
>;
|
|
45
|
+
export type AuthorizationSearchActionsInput = MessageInitShape<
|
|
46
|
+
typeof ActionSearchRequestSchema
|
|
47
|
+
>;
|
|
48
|
+
export type AuthorizationReadRelationshipsInput = MessageInitShape<
|
|
49
|
+
typeof ReadRelationshipsRequestSchema
|
|
50
|
+
>;
|
|
51
|
+
|
|
52
|
+
export type AuthorizationDecisionMessage = AccessDecision;
|
|
53
|
+
export type AuthorizationMetadataMessage = AuthorizationMetadata;
|
|
54
|
+
export type AuthorizationResourceSearchMessage = ResourceSearchResponse;
|
|
55
|
+
export type AuthorizationSubjectSearchMessage = SubjectSearchResponse;
|
|
56
|
+
export type AuthorizationActionSearchMessage = ActionSearchResponse;
|
|
57
|
+
export type AuthorizationReadRelationshipsMessage = ReadRelationshipsResponse;
|
|
58
|
+
|
|
59
|
+
const sharedAuthorizationTransport: {
|
|
60
|
+
target: string;
|
|
61
|
+
token: string;
|
|
62
|
+
client: AuthorizationClient | undefined;
|
|
63
|
+
} = {
|
|
64
|
+
target: "",
|
|
65
|
+
token: "",
|
|
66
|
+
client: undefined,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Read-only client for the host-configured authorization provider.
|
|
71
|
+
*/
|
|
72
|
+
export class AuthorizationClient {
|
|
73
|
+
private readonly client: Client<typeof AuthorizationProviderService>;
|
|
74
|
+
|
|
75
|
+
constructor(socketTarget?: string, relayToken = process.env[ENV_AUTHORIZATION_SOCKET_TOKEN]?.trim() ?? "") {
|
|
76
|
+
const resolvedTarget = resolveAuthorizationSocketTarget(socketTarget);
|
|
77
|
+
const transportOptions = authorizationTransportOptions(resolvedTarget);
|
|
78
|
+
const transport = createGrpcTransport({
|
|
79
|
+
...transportOptions,
|
|
80
|
+
...(transportOptions.nodeOptions
|
|
81
|
+
? {
|
|
82
|
+
nodeOptions: {
|
|
83
|
+
createConnection: () => connect(transportOptions.nodeOptions!.path),
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
: {}),
|
|
87
|
+
interceptors: relayToken
|
|
88
|
+
? [authorizationRelayTokenInterceptor(relayToken)]
|
|
89
|
+
: [],
|
|
90
|
+
});
|
|
91
|
+
this.client = createClient(AuthorizationProviderService, transport);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async evaluate(
|
|
95
|
+
request: AuthorizationEvaluateInput,
|
|
96
|
+
): Promise<AuthorizationDecisionMessage> {
|
|
97
|
+
return await this.client.evaluate(request);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async searchResources(
|
|
101
|
+
request: AuthorizationSearchResourcesInput,
|
|
102
|
+
): Promise<AuthorizationResourceSearchMessage> {
|
|
103
|
+
return await this.client.searchResources(request);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async searchSubjects(
|
|
107
|
+
request: AuthorizationSearchSubjectsInput,
|
|
108
|
+
): Promise<AuthorizationSubjectSearchMessage> {
|
|
109
|
+
return await this.client.searchSubjects(request);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async searchActions(
|
|
113
|
+
request: AuthorizationSearchActionsInput,
|
|
114
|
+
): Promise<AuthorizationActionSearchMessage> {
|
|
115
|
+
return await this.client.searchActions(request);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async readRelationships(
|
|
119
|
+
request: AuthorizationReadRelationshipsInput,
|
|
120
|
+
): Promise<AuthorizationReadRelationshipsMessage> {
|
|
121
|
+
return await this.client.readRelationships(request);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async getMetadata(): Promise<AuthorizationMetadataMessage> {
|
|
125
|
+
return await this.client.getMetadata({});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Mirrors the Go SDK helper for obtaining the read-only host authorization
|
|
131
|
+
* client inside authored providers.
|
|
132
|
+
*/
|
|
133
|
+
export function Authorization(): AuthorizationClient {
|
|
134
|
+
const target = resolveAuthorizationSocketTarget();
|
|
135
|
+
const token = process.env[ENV_AUTHORIZATION_SOCKET_TOKEN]?.trim() ?? "";
|
|
136
|
+
if (
|
|
137
|
+
sharedAuthorizationTransport.client &&
|
|
138
|
+
sharedAuthorizationTransport.target === target &&
|
|
139
|
+
sharedAuthorizationTransport.token === token
|
|
140
|
+
) {
|
|
141
|
+
return sharedAuthorizationTransport.client;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const client = new AuthorizationClient(target, token);
|
|
145
|
+
sharedAuthorizationTransport.target = target;
|
|
146
|
+
sharedAuthorizationTransport.token = token;
|
|
147
|
+
sharedAuthorizationTransport.client = client;
|
|
148
|
+
return client;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function resolveAuthorizationSocketTarget(socketPath = process.env[ENV_AUTHORIZATION_SOCKET]): string {
|
|
152
|
+
const trimmed = socketPath?.trim() ?? "";
|
|
153
|
+
if (!trimmed) {
|
|
154
|
+
throw new Error(`authorization: ${ENV_AUTHORIZATION_SOCKET} is not set`);
|
|
155
|
+
}
|
|
156
|
+
return trimmed;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function authorizationTransportOptions(rawTarget: string): {
|
|
160
|
+
baseUrl: string;
|
|
161
|
+
nodeOptions?: { path: string };
|
|
162
|
+
} {
|
|
163
|
+
const target = rawTarget.trim();
|
|
164
|
+
if (!target) {
|
|
165
|
+
throw new Error("authorization: transport target is required");
|
|
166
|
+
}
|
|
167
|
+
if (target.startsWith("tcp://")) {
|
|
168
|
+
const address = target.slice("tcp://".length).trim();
|
|
169
|
+
if (!address) {
|
|
170
|
+
throw new Error(
|
|
171
|
+
`authorization: tcp target ${JSON.stringify(rawTarget)} is missing host:port`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
return { baseUrl: `http://${address}` };
|
|
175
|
+
}
|
|
176
|
+
if (target.startsWith("tls://")) {
|
|
177
|
+
const address = target.slice("tls://".length).trim();
|
|
178
|
+
if (!address) {
|
|
179
|
+
throw new Error(
|
|
180
|
+
`authorization: tls target ${JSON.stringify(rawTarget)} is missing host:port`,
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
return { baseUrl: `https://${address}` };
|
|
184
|
+
}
|
|
185
|
+
if (target.startsWith("unix://")) {
|
|
186
|
+
const socketPath = target.slice("unix://".length).trim();
|
|
187
|
+
if (!socketPath) {
|
|
188
|
+
throw new Error(
|
|
189
|
+
`authorization: unix target ${JSON.stringify(rawTarget)} is missing a socket path`,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
return { baseUrl: "http://localhost", nodeOptions: { path: socketPath } };
|
|
193
|
+
}
|
|
194
|
+
if (target.includes("://")) {
|
|
195
|
+
const parsed = new URL(target);
|
|
196
|
+
throw new Error(
|
|
197
|
+
`authorization: unsupported target scheme ${JSON.stringify(parsed.protocol.replace(/:$/, ""))}`,
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
return { baseUrl: "http://localhost", nodeOptions: { path: target } };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function authorizationRelayTokenInterceptor(token: string): Interceptor {
|
|
204
|
+
return (next) => async (req) => {
|
|
205
|
+
req.header.set(AUTHORIZATION_RELAY_TOKEN_HEADER, token);
|
|
206
|
+
return next(req);
|
|
207
|
+
};
|
|
208
|
+
}
|