@valon-technologies/gestalt 0.0.1-alpha.32 → 0.0.1-alpha.34

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 CHANGED
@@ -19,9 +19,9 @@ explicitly names a submodule.
19
19
  | --- | --- | --- |
20
20
  | Provider authoring | `defineApp`, `operation`, `ok` | Executable app providers, typed request handlers, and operation results. |
21
21
  | Runtime schemas | `s`, `object`, `string` | Runtime validation and generated catalog metadata for operation inputs and outputs. |
22
- | Provider runtimes | `defineAuthenticationProvider`, `defineAuthorizationProvider`, `defineCacheProvider`, `defineS3Provider`, `defineWorkflowProvider`, `defineAgentProvider` | Host-service backends implemented as TypeScript providers. |
22
+ | Provider runtimes | `defineAuthenticationProvider`, `defineCacheProvider`, `defineS3Provider`, `defineWorkflowProvider`, `defineAgentProvider` | Host-service backends implemented as TypeScript providers. |
23
23
  | Workflow and agent models | `WorkflowProvider`, `Workflow`, `AgentProvider`, `Agent` | Native workflow values, agent sessions, turns, messages, tools, and host-service access. |
24
- | Host-service clients | `Cache`, `IndexedDB`, `S3`, `App`, `Authorization` | Calling sibling services exposed to a provider process by `gestaltd`. |
24
+ | Host-service clients | `Cache`, `IndexedDB`, `S3`, `App` | Calling sibling services exposed to a provider process by `gestaltd`. |
25
25
  | Telemetry | `withModelOperation`, `withToolExecution`, `withAgentInvocation` | Provider-authored GenAI spans and metrics inside a running provider process. |
26
26
 
27
27
  ```ts
@@ -77,8 +77,8 @@ is omitted, the runtime looks for `provider`, then `app`, then the default
77
77
  export.
78
78
 
79
79
  Use `"app"` as the kind token for executable app providers. Use an object
80
- target with an explicit kind for authentication, authorization, cache,
81
- IndexedDB, S3, secrets, workflow, agent, and hosted-runtime providers.
80
+ target with an explicit kind for authentication, cache, IndexedDB, S3,
81
+ secrets, workflow, agent, and hosted-runtime providers.
82
82
 
83
83
  ## Public surface
84
84
 
@@ -86,7 +86,6 @@ The root package exports provider definition helpers:
86
86
 
87
87
  - `defineApp` for integration operations and session catalogs.
88
88
  - `defineAuthenticationProvider` for authentication surfaces.
89
- - `defineAuthorizationProvider` for custom authorization providers.
90
89
  - `defineCacheProvider`, `defineIndexedDBProvider`, `defineS3Provider`, and
91
90
  `defineSecretsProvider` for host-service backends.
92
91
  - `defineWorkflowProvider`, `defineAgentProvider`, and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valon-technologies/gestalt",
3
- "version": "0.0.1-alpha.32",
3
+ "version": "0.0.1-alpha.34",
4
4
  "description": "TypeScript SDK for Gestalt executable providers",
5
5
  "type": "module",
6
6
  "repository": {
@@ -12,7 +12,6 @@ import {
12
12
  } from "./internal/gen/v1/agent_pb.ts";
13
13
  import type { Request } from "./api.ts";
14
14
  import {
15
- agentActorFromProto,
16
15
  agentOutputToProto,
17
16
  agentMessageFromProto,
18
17
  agentMessageToProto,
@@ -38,6 +37,7 @@ import {
38
37
  dateFromTimestamp,
39
38
  type JsonObjectInput,
40
39
  } from "./protocol.ts";
40
+ import { hostInvocationContext } from "./invocation-context.ts";
41
41
  import {
42
42
  optionalObjectFromStruct,
43
43
  optionalStruct,
@@ -171,12 +171,12 @@ export interface Agent {
171
171
  */
172
172
  class AgentImpl implements Agent {
173
173
  private readonly client: Client<typeof AgentProviderService>;
174
- private readonly invocationToken: string;
174
+ private readonly invocationContext: ReturnType<typeof hostInvocationContext>;
175
175
 
176
176
  constructor(request: Request);
177
177
  constructor(invocationToken: string);
178
178
  constructor(requestOrToken: Request | string) {
179
- this.invocationToken = normalizeInvocationToken(requestOrToken);
179
+ this.invocationContext = hostInvocationContext(requestOrToken);
180
180
 
181
181
  const target = process.env[ENV_HOST_SERVICE_SOCKET]?.trim();
182
182
  if (!target) {
@@ -203,7 +203,7 @@ class AgentImpl implements Agent {
203
203
  clientRef: request.clientRef ?? "",
204
204
  metadata: optionalStruct(request.metadata),
205
205
  idempotencyKey: request.idempotencyKey ?? "",
206
- invocationToken: this.invocationToken,
206
+ ...this.invocationContext,
207
207
  workspace: workspaceToProto(request.workspace),
208
208
  }),
209
209
  );
@@ -214,7 +214,7 @@ class AgentImpl implements Agent {
214
214
  return agentSessionFromProto(
215
215
  await this.client.getSession({
216
216
  sessionId: request.sessionId,
217
- invocationToken: this.invocationToken,
217
+ ...this.invocationContext,
218
218
  }),
219
219
  );
220
220
  }
@@ -225,7 +225,7 @@ class AgentImpl implements Agent {
225
225
  ): Promise<AgentSession[]> {
226
226
  const response = await this.client.listSessions({
227
227
  providerName: request.providerName ?? "",
228
- invocationToken: this.invocationToken,
228
+ ...this.invocationContext,
229
229
  state: request.state ?? AgentSessionState.UNSPECIFIED,
230
230
  limit: request.limit ?? 0,
231
231
  summaryOnly: request.summaryOnly ?? false,
@@ -243,13 +243,17 @@ class AgentImpl implements Agent {
243
243
  clientRef: request.clientRef ?? "",
244
244
  state: request.state ?? AgentSessionState.UNSPECIFIED,
245
245
  metadata: optionalStruct(request.metadata),
246
- invocationToken: this.invocationToken,
246
+ ...this.invocationContext,
247
247
  }),
248
248
  );
249
249
  }
250
250
 
251
251
  /** Creates an agent turn. */
252
252
  async createTurn(request: AgentCreateTurn): Promise<AgentTurn> {
253
+ const timeoutSeconds = request.timeoutSeconds ?? 0;
254
+ if (!Number.isInteger(timeoutSeconds) || timeoutSeconds < 0) {
255
+ throw new Error("agent create turn timeoutSeconds must not be negative");
256
+ }
253
257
  return agentTurnFromProto(
254
258
  await this.client.createTurn({
255
259
  sessionId: request.sessionId,
@@ -260,9 +264,9 @@ class AgentImpl implements Agent {
260
264
  output: agentOutputToProto(request.output),
261
265
  metadata: optionalStruct(request.metadata),
262
266
  idempotencyKey: request.idempotencyKey ?? "",
263
- invocationToken: this.invocationToken,
267
+ ...this.invocationContext,
264
268
  modelOptions: optionalStruct(request.modelOptions),
265
- timeoutSeconds: request.timeoutSeconds ?? 0,
269
+ timeoutSeconds,
266
270
  }),
267
271
  );
268
272
  }
@@ -272,7 +276,7 @@ class AgentImpl implements Agent {
272
276
  return agentTurnFromProto(
273
277
  await this.client.getTurn({
274
278
  turnId: request.turnId,
275
- invocationToken: this.invocationToken,
279
+ ...this.invocationContext,
276
280
  }),
277
281
  );
278
282
  }
@@ -281,7 +285,7 @@ class AgentImpl implements Agent {
281
285
  async listTurns(request: AgentListTurns): Promise<AgentTurn[]> {
282
286
  const response = await this.client.listTurns({
283
287
  sessionId: request.sessionId,
284
- invocationToken: this.invocationToken,
288
+ ...this.invocationContext,
285
289
  status: request.status ?? AgentExecutionStatus.UNSPECIFIED,
286
290
  limit: request.limit ?? 0,
287
291
  summaryOnly: request.summaryOnly ?? false,
@@ -295,7 +299,7 @@ class AgentImpl implements Agent {
295
299
  await this.client.cancelTurn({
296
300
  turnId: request.turnId,
297
301
  reason: request.reason ?? "",
298
- invocationToken: this.invocationToken,
302
+ ...this.invocationContext,
299
303
  }),
300
304
  );
301
305
  }
@@ -308,7 +312,7 @@ class AgentImpl implements Agent {
308
312
  turnId: request.turnId,
309
313
  afterSeq: BigInt(request.afterSeq ?? 0),
310
314
  limit: request.limit ?? 0,
311
- invocationToken: this.invocationToken,
315
+ ...this.invocationContext,
312
316
  });
313
317
  return response.events.map(agentTurnEventFromProto);
314
318
  }
@@ -319,7 +323,7 @@ class AgentImpl implements Agent {
319
323
  ): Promise<AgentInteraction[]> {
320
324
  const response = await this.client.listInteractions({
321
325
  turnId: request.turnId,
322
- invocationToken: this.invocationToken,
326
+ ...this.invocationContext,
323
327
  });
324
328
  return response.interactions.map(agentInteractionFromProto);
325
329
  }
@@ -333,24 +337,12 @@ class AgentImpl implements Agent {
333
337
  turnId: request.turnId,
334
338
  interactionId: request.interactionId,
335
339
  resolution: optionalStruct(request.resolution),
336
- invocationToken: this.invocationToken,
340
+ ...this.invocationContext,
337
341
  }),
338
342
  );
339
343
  }
340
344
  }
341
345
 
342
- function normalizeInvocationToken(requestOrToken: Request | string): string {
343
- const invocationToken =
344
- typeof requestOrToken === "string"
345
- ? requestOrToken
346
- : requestOrToken.invocationToken;
347
- const trimmed = invocationToken.trim();
348
- if (!trimmed) {
349
- throw new Error("agent: invocation token is not available");
350
- }
351
- return trimmed;
352
- }
353
-
354
346
  function workspaceToProto(workspace?: AgentWorkspace | undefined) {
355
347
  if (workspace === undefined) {
356
348
  return undefined;
@@ -375,7 +367,7 @@ function agentSessionFromProto(session: ProtoAgentSession): AgentSession {
375
367
  clientRef: session.clientRef,
376
368
  state: session.state as AgentSessionState,
377
369
  metadata: optionalObjectFromStruct(session.metadata),
378
- createdBy: agentActorFromProto(session.createdBy),
370
+ createdBySubjectId: session.createdBySubjectId ?? "",
379
371
  createdAt: optionalDate(session.createdAt),
380
372
  updatedAt: optionalDate(session.updatedAt),
381
373
  lastTurnAt: optionalDate(session.lastTurnAt),
@@ -392,7 +384,7 @@ function agentTurnFromProto(turn: ProtoAgentTurn): AgentTurn {
392
384
  messages: turn.messages.map(agentMessageFromProto),
393
385
  output: agentTurnOutputFromProto(turn.output),
394
386
  statusMessage: turn.statusMessage,
395
- createdBy: agentActorFromProto(turn.createdBy),
387
+ createdBySubjectId: turn.createdBySubjectId ?? "",
396
388
  createdAt: optionalDate(turn.createdAt),
397
389
  startedAt: optionalDate(turn.startedAt),
398
390
  completedAt: optionalDate(turn.completedAt),
@@ -4,7 +4,6 @@ import {
4
4
  } from "@bufbuild/protobuf";
5
5
 
6
6
  import {
7
- AgentActorSchema,
8
7
  AgentOutputSchema,
9
8
  AgentStructuredOutputSchema,
10
9
  AgentTextOutputSchema,
@@ -14,7 +13,6 @@ import {
14
13
  AgentTurnDisplaySchema,
15
14
  AgentTurnStructuredOutputSchema,
16
15
  AgentTurnTextOutputSchema,
17
- type AgentActor as ProtoAgentActor,
18
16
  type AgentMessage as ProtoAgentMessage,
19
17
  type AgentMessagePart as ProtoAgentMessagePart,
20
18
  type AgentOutput as ProtoAgentOutput,
@@ -37,7 +35,6 @@ import {
37
35
  optionalStruct,
38
36
  } from "./protocol-internal.ts";
39
37
  import type {
40
- AgentActor,
41
38
  AgentOutput,
42
39
  AgentMessage,
43
40
  AgentMessagePart,
@@ -266,34 +263,6 @@ export function agentMessagePartToProto(
266
263
  };
267
264
  }
268
265
 
269
- export function agentActorFromProto(
270
- actor?: ProtoAgentActor | undefined,
271
- ): AgentActor | undefined {
272
- if (actor === undefined) {
273
- return undefined;
274
- }
275
- return {
276
- subjectId: actor.subjectId,
277
- subjectKind: actor.subjectKind,
278
- displayName: actor.displayName,
279
- authSource: actor.authSource,
280
- };
281
- }
282
-
283
- export function agentActorToProto(
284
- actor?: AgentActor | undefined,
285
- ): ProtoAgentActor | undefined {
286
- if (actor === undefined) {
287
- return undefined;
288
- }
289
- return create(AgentActorSchema, {
290
- subjectId: actor.subjectId ?? "",
291
- subjectKind: actor.subjectKind ?? "",
292
- displayName: actor.displayName ?? "",
293
- authSource: actor.authSource ?? "",
294
- });
295
- }
296
-
297
266
  export function agentToolRefFromProto(ref: ProtoAgentToolRef): AgentToolRef {
298
267
  return {
299
268
  app: ref.app,
@@ -328,10 +297,7 @@ function agentRunAsSubjectFromProto(
328
297
  }
329
298
  return {
330
299
  id: subject.id,
331
- kind: subject.kind,
332
300
  credentialSubjectId: subject.credentialSubjectId,
333
- displayName: subject.displayName,
334
- authSource: subject.authSource,
335
301
  email: subject.email,
336
302
  };
337
303
  }
@@ -344,10 +310,7 @@ function agentRunAsSubjectToProto(
344
310
  }
345
311
  return create(SubjectContextSchema, {
346
312
  id: subject.id ?? "",
347
- kind: subject.kind ?? "",
348
313
  credentialSubjectId: subject.credentialSubjectId ?? "",
349
- displayName: subject.displayName ?? "",
350
- authSource: subject.authSource ?? "",
351
314
  email: subject.email ?? "",
352
315
  });
353
316
  }
package/src/agent.ts CHANGED
@@ -39,7 +39,6 @@ import {
39
39
  ListAgentProviderTurnEventsResponseSchema,
40
40
  ListAgentProviderTurnsResponseSchema,
41
41
  ResolveAgentConnectionRequestSchema,
42
- type AgentActor as ProtoAgentActor,
43
42
  type AgentInteraction as ProtoAgentInteraction,
44
43
  type AgentMessagePartImageRef as ProtoAgentMessagePartImageRef,
45
44
  type AgentMessagePartToolCall as ProtoAgentMessagePartToolCall,
@@ -80,8 +79,6 @@ import {
80
79
  type SubjectInput,
81
80
  } from "./api.ts";
82
81
  import {
83
- agentActorFromProto,
84
- agentActorToProto,
85
82
  agentOutputFromProto,
86
83
  agentOutputToProto,
87
84
  agentMessageFromProto,
@@ -200,12 +197,6 @@ export interface AgentMessage {
200
197
  metadata?: JsonObjectInput | undefined;
201
198
  }
202
199
 
203
- export interface AgentActor {
204
- subjectId?: string | undefined;
205
- subjectKind?: string | undefined;
206
- displayName?: string | undefined;
207
- authSource?: string | undefined;
208
- }
209
200
 
210
201
  export interface AgentToolRef {
211
202
  app?: string | undefined;
@@ -245,7 +236,7 @@ export interface AgentSession {
245
236
  clientRef?: string | undefined;
246
237
  state?: AgentSessionState | undefined;
247
238
  metadata?: JsonObjectInput | undefined;
248
- createdBy?: AgentActor | undefined;
239
+ createdBySubjectId?: string | undefined;
249
240
  createdAt?: Date | undefined;
250
241
  updatedAt?: Date | undefined;
251
242
  lastTurnAt?: Date | undefined;
@@ -281,7 +272,7 @@ export interface CreateAgentProviderSessionRequest {
281
272
  model: string;
282
273
  clientRef: string;
283
274
  metadata?: JsonObjectInput | undefined;
284
- createdBy?: AgentActor | undefined;
275
+ createdBySubjectId?: string | undefined;
285
276
  subject?: Subject | undefined;
286
277
  sessionStart?: AgentSessionStartConfig | undefined;
287
278
  preparedWorkspace?: AgentPreparedWorkspace | undefined;
@@ -325,7 +316,7 @@ export interface AgentTurn {
325
316
  messages?: readonly AgentMessage[] | undefined;
326
317
  output?: AgentTurnOutput | undefined;
327
318
  statusMessage?: string | undefined;
328
- createdBy?: AgentActor | undefined;
319
+ createdBySubjectId?: string | undefined;
329
320
  createdAt?: Date | undefined;
330
321
  startedAt?: Date | undefined;
331
322
  completedAt?: Date | undefined;
@@ -365,7 +356,7 @@ export interface CreateAgentProviderTurnRequest {
365
356
  tools: readonly ResolvedAgentTool[];
366
357
  output: AgentOutput;
367
358
  metadata?: JsonObjectInput | undefined;
368
- createdBy?: AgentActor | undefined;
359
+ createdBySubjectId?: string | undefined;
369
360
  executionRef: string;
370
361
  toolRefs: readonly AgentToolRef[];
371
362
  toolSource: AgentToolSourceMode;
@@ -816,7 +807,7 @@ function createAgentProviderSessionRequestFromProto(
816
807
  model: request.model,
817
808
  clientRef: request.clientRef,
818
809
  metadata: optionalObjectFromStruct(request.metadata),
819
- createdBy: agentActorFromProto(request.createdBy),
810
+ createdBySubjectId: request.createdBySubjectId ?? "",
820
811
  subject: agentSubjectFromProto(request.subject),
821
812
  sessionStart: request.sessionStart === undefined ? undefined : {
822
813
  hooks: request.sessionStart.hooks.map((hook) => ({
@@ -888,6 +879,12 @@ function createAgentProviderTurnRequestFromProto(
888
879
  if (output === undefined) {
889
880
  throw new ConnectError("create turn output is required", Code.InvalidArgument);
890
881
  }
882
+ if (!Number.isInteger(request.timeoutSeconds) || request.timeoutSeconds < 0) {
883
+ throw new ConnectError(
884
+ "agent create turn timeoutSeconds must not be negative",
885
+ Code.InvalidArgument,
886
+ );
887
+ }
891
888
  return {
892
889
  turnId: request.turnId,
893
890
  sessionId: request.sessionId,
@@ -897,7 +894,7 @@ function createAgentProviderTurnRequestFromProto(
897
894
  tools: request.tools.map(resolvedAgentToolFromProto),
898
895
  output,
899
896
  metadata: optionalObjectFromStruct(request.metadata),
900
- createdBy: agentActorFromProto(request.createdBy),
897
+ createdBySubjectId: request.createdBySubjectId ?? "",
901
898
  executionRef: request.executionRef,
902
899
  toolRefs: request.toolRefs.map(agentToolRefFromProto),
903
900
  toolSource: request.toolSource as AgentToolSourceMode,
@@ -997,7 +994,7 @@ function agentSessionToProto(
997
994
  clientRef: session.clientRef ?? "",
998
995
  state: session.state ?? AgentSessionState.UNSPECIFIED,
999
996
  metadata: optionalStruct(session.metadata),
1000
- createdBy: agentActorToProto(session.createdBy),
997
+ createdBySubjectId: session.createdBySubjectId ?? "",
1001
998
  createdAt: optionalTimestamp(session.createdAt),
1002
999
  updatedAt: optionalTimestamp(session.updatedAt),
1003
1000
  lastTurnAt: optionalTimestamp(session.lastTurnAt),
@@ -1014,7 +1011,7 @@ function agentTurnToProto(turn: AgentTurn): MessageInitShape<typeof AgentTurnSch
1014
1011
  messages: turn.messages?.map(agentMessageToProto) ?? [],
1015
1012
  output: agentTurnOutputToProto(turn.output),
1016
1013
  statusMessage: turn.statusMessage ?? "",
1017
- createdBy: agentActorToProto(turn.createdBy),
1014
+ createdBySubjectId: turn.createdBySubjectId ?? "",
1018
1015
  createdAt: optionalTimestamp(turn.createdAt),
1019
1016
  startedAt: optionalTimestamp(turn.startedAt),
1020
1017
  completedAt: optionalTimestamp(turn.completedAt),
@@ -1090,10 +1087,7 @@ function agentSubjectFromProto(
1090
1087
  }
1091
1088
  return {
1092
1089
  id: subject.id,
1093
- kind: subject.kind,
1094
1090
  credentialSubjectId: subject.credentialSubjectId,
1095
- displayName: subject.displayName,
1096
- authSource: subject.authSource,
1097
1091
  email: subject.email,
1098
1092
  };
1099
1093
  }
package/src/api.ts CHANGED
@@ -5,10 +5,7 @@ import type { AgentToolRef } from "./agent.ts";
5
5
 
6
6
  export interface Subject {
7
7
  id: string;
8
- kind: string;
9
8
  credentialSubjectId: string;
10
- displayName: string;
11
- authSource: string;
12
9
  email: string;
13
10
  }
14
11
 
@@ -17,10 +14,7 @@ export interface Subject {
17
14
  */
18
15
  export interface SubjectInput {
19
16
  id: string;
20
- kind: string;
21
17
  credentialSubjectId?: string | undefined;
22
- displayName: string;
23
- authSource: string;
24
18
  email?: string | undefined;
25
19
  }
26
20
 
@@ -62,7 +56,7 @@ export interface Request {
62
56
  host: Host;
63
57
  idempotencyKey: string;
64
58
  // Workflow callback metadata uses a JSON-style lowerCamelCase object such as
65
- // runId, target.steps, trigger.scheduleId, and trigger.event.specVersion.
59
+ // runId, target.steps, trigger.activationId, and trigger.event.specVersion.
66
60
  workflow: Record<string, unknown>;
67
61
  toolRefs: AgentToolRef[];
68
62
  toolRefsSet: boolean;
@@ -136,6 +130,22 @@ export function ok<T>(body: T, headers?: ResponseHeaders): Response<T> {
136
130
  * const input = request("token", { region: "us-east-1" }, { id: "usr_123" });
137
131
  * ```
138
132
  */
133
+ export function parseSubjectId(
134
+ subjectId: string,
135
+ ): { kind: string; id: string } | undefined {
136
+ const trimmed = subjectId.trim();
137
+ const index = trimmed.indexOf(":");
138
+ if (index <= 0 || index >= trimmed.length - 1) {
139
+ return undefined;
140
+ }
141
+ const kind = trimmed.slice(0, index).trim();
142
+ const id = trimmed.slice(index + 1).trim();
143
+ if (!kind || !id) {
144
+ return undefined;
145
+ }
146
+ return { kind, id };
147
+ }
148
+
139
149
  export function request(
140
150
  token = "",
141
151
  connectionParams: Record<string, string> = {},
@@ -157,18 +167,12 @@ export function request(
157
167
  },
158
168
  subject: {
159
169
  id: subject.id ?? "",
160
- kind: subject.kind ?? "",
161
170
  credentialSubjectId: subject.credentialSubjectId ?? "",
162
- displayName: subject.displayName ?? "",
163
- authSource: subject.authSource ?? "",
164
171
  email: subject.email ?? "",
165
172
  },
166
173
  agentSubject: {
167
174
  id: agentSubject.id ?? "",
168
- kind: agentSubject.kind ?? "",
169
175
  credentialSubjectId: agentSubject.credentialSubjectId ?? "",
170
- displayName: agentSubject.displayName ?? "",
171
- authSource: agentSubject.authSource ?? "",
172
176
  email: agentSubject.email ?? "",
173
177
  },
174
178
  credential: {
package/src/app-access.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  structFromObject,
9
9
  type JsonObjectInput,
10
10
  } from "./protocol.ts";
11
+ import { hostInvocationContext } from "./invocation-context.ts";
11
12
  import {
12
13
  createHostServiceGrpcTransport,
13
14
  hostServiceMetadataInterceptors,
@@ -72,12 +73,12 @@ export interface App {
72
73
  */
73
74
  class AppImpl implements App {
74
75
  private readonly client: Client<typeof AppService>;
75
- private readonly invocationToken: string;
76
+ private readonly invocationContext: ReturnType<typeof hostInvocationContext>;
76
77
 
77
78
  constructor(request: Request);
78
79
  constructor(invocationToken: string);
79
80
  constructor(requestOrToken: Request | string) {
80
- this.invocationToken = normalizeInvocationToken(requestOrToken);
81
+ this.invocationContext = hostInvocationContext(requestOrToken);
81
82
 
82
83
  const { target, token } = requireHostServiceTarget("app");
83
84
  const transport = createHostServiceGrpcTransport(
@@ -95,7 +96,7 @@ class AppImpl implements App {
95
96
  options?: AppInvokeOptions,
96
97
  ): Promise<OperationResult> {
97
98
  const response = await this.client.invoke({
98
- invocationToken: this.invocationToken,
99
+ ...this.invocationContext,
99
100
  app,
100
101
  operation,
101
102
  params: structFromObject(params),
@@ -123,7 +124,7 @@ class AppImpl implements App {
123
124
  }
124
125
 
125
126
  const response = await this.client.invokeGraphQL({
126
- invocationToken: this.invocationToken,
127
+ invocationToken: this.invocationContext.invocationToken,
127
128
  app,
128
129
  document: trimmedDocument,
129
130
  ...(options?.variables !== undefined
@@ -148,7 +149,7 @@ class AppImpl implements App {
148
149
  ttlSeconds?: number;
149
150
  }): Promise<string> {
150
151
  const response = await this.client.exchangeInvocationToken({
151
- parentInvocationToken: this.invocationToken,
152
+ parentInvocationToken: this.invocationContext.invocationToken,
152
153
  grants: (options?.grants ?? [])
153
154
  .map((grant) => ({
154
155
  app: grant.app.trim(),
@@ -168,15 +169,3 @@ class AppImpl implements App {
168
169
  }
169
170
 
170
171
  export const App = AppImpl;
171
-
172
- function normalizeInvocationToken(requestOrToken: Request | string): string {
173
- const invocationToken =
174
- typeof requestOrToken === "string"
175
- ? requestOrToken
176
- : requestOrToken.invocationToken;
177
- const trimmed = invocationToken.trim();
178
- if (!trimmed) {
179
- throw new Error("app: invocation token is not available");
180
- }
181
- return trimmed;
182
- }