@nylorun/runtime 0.32.0-beta → 0.34.0-beta

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 (45) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/api/ag-ui/routes.js +4 -2
  3. package/dist/api/ag-ui/translate.js +3 -1
  4. package/dist/api/components.d.ts +35 -0
  5. package/dist/api/components.js +3 -1
  6. package/dist/api/http/routes/sessions.js +63 -2
  7. package/dist/api/openapi.js +3 -0
  8. package/dist/gates/credential-provider.d.ts +42 -0
  9. package/dist/gates/credential-provider.js +140 -0
  10. package/dist/gates/egress-credentials.d.ts +12 -0
  11. package/dist/gates/egress-credentials.js +60 -6
  12. package/dist/gates/egress.d.ts +14 -1
  13. package/dist/gates/egress.js +67 -19
  14. package/dist/gates/handler.js +2 -2
  15. package/dist/gates/in-process.d.ts +4 -3
  16. package/dist/gates/in-process.js +11 -5
  17. package/dist/gates/tenant-vaults.d.ts +4 -3
  18. package/dist/gates/tenant-vaults.js +2 -2
  19. package/dist/harness-api/start.js +30 -3
  20. package/dist/host/gates.d.ts +8 -1
  21. package/dist/host/gates.js +6 -1
  22. package/dist/host/main.js +17 -1
  23. package/dist/host/stack-config.d.ts +17 -1
  24. package/dist/host/stack-config.js +47 -1
  25. package/dist/management-openapi.json +61 -5
  26. package/dist/model/descriptor.d.ts +5 -4
  27. package/dist/model/descriptor.js +4 -3
  28. package/dist/model/pi-model.js +17 -1
  29. package/dist/openapi.json +516 -2
  30. package/dist/tenant/context.d.ts +12 -1
  31. package/dist/tenant/runtime.d.ts +6 -0
  32. package/dist/tenant/runtime.js +1 -0
  33. package/dist/tenant/session-model.d.ts +16 -0
  34. package/dist/tenant/session-model.js +46 -0
  35. package/dist/tuning.d.ts +6 -0
  36. package/dist/tuning.js +14 -0
  37. package/dist/vault/host-identity.d.ts +24 -0
  38. package/dist/vault/host-identity.js +35 -0
  39. package/dist/vault/host-model.d.ts +9 -5
  40. package/dist/vault/host-model.js +30 -19
  41. package/dist/vault/service.d.ts +18 -2
  42. package/dist/vault/service.js +52 -9
  43. package/dist/version.d.ts +1 -1
  44. package/dist/version.js +1 -1
  45. package/package.json +6 -6
package/dist/tuning.d.ts CHANGED
@@ -240,6 +240,12 @@ export declare const HostTuningSchema: z.ZodObject<{
240
240
  credentialsHeadersTimeoutMs: z.ZodDefault<z.ZodNumber>;
241
241
  credentialsMaxSockets: z.ZodDefault<z.ZodNumber>;
242
242
  }, z.core.$strict>>;
243
+ credentialProvider: z.ZodPrefault<z.ZodObject<{
244
+ cacheMs: z.ZodDefault<z.ZodNumber>;
245
+ retryMs: z.ZodDefault<z.ZodNumber>;
246
+ timeoutMs: z.ZodDefault<z.ZodNumber>;
247
+ cacheEntries: z.ZodDefault<z.ZodNumber>;
248
+ }, z.core.$strict>>;
243
249
  pods: z.ZodPrefault<z.ZodObject<{
244
250
  readyDeadlineMs: z.ZodDefault<z.ZodNumber>;
245
251
  pollMs: z.ZodDefault<z.ZodNumber>;
package/dist/tuning.js CHANGED
@@ -386,6 +386,20 @@ export const HostTuningSchema = z
386
386
  /** The upstream sockets one such tunnel opens at once. */
387
387
  credentialsMaxSockets: count(8),
388
388
  }),
389
+ /**
390
+ * The outside credential provider (`NYLORUN_CREDENTIAL_PROVIDER_URL`), which egress-gate asks
391
+ * for an Agent's connected hosts and core for its variables (`gates/credential-provider.ts`).
392
+ */
393
+ credentialProvider: group({
394
+ /** How long an Agent's answer (hosts, or variables) is reused. */
395
+ cacheMs: ms(15_000, 0),
396
+ /** How long a failed answer (nothing) is reused before the provider is asked again. */
397
+ retryMs: ms(5_000, 0),
398
+ /** How long one `hosts` or `environment` call may take. */
399
+ timeoutMs: ms(3_000),
400
+ /** How many Agents' answers are kept. */
401
+ cacheEntries: count(4_096),
402
+ }),
389
403
  /** Sandbox pods through the sandboxes service (F7.2). */
390
404
  pods: group({
391
405
  /** How long a pod may take to be ready before its start fails. */
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The Host's identity for model calls (ADR-71): a model credential of type `host_identity` holds
3
+ * no secret, only the Google Cloud project and location. The model gate calls Agent Platform with
4
+ * the Host's Google Application Default Credentials, which Google's client library finds at each
5
+ * call (`GOOGLE_APPLICATION_CREDENTIALS`, gcloud's file, or the metadata server on Google Cloud).
6
+ * Nothing of them is stored, logged or passed to a sandbox.
7
+ *
8
+ * Off unless the Host's operator lends it, per provider, with `NYLORUN_MODEL_HOST_IDENTITY` on the
9
+ * process that runs the gates. Every Tenant on the Host may then use it, so a Host that serves
10
+ * several organizations must not set it.
11
+ */
12
+ /** The providers that can use the Host's identity. */
13
+ export declare const HOST_IDENTITY_PROVIDERS: readonly ["google-vertex"];
14
+ /**
15
+ * What pi-ai's Vertex AI client takes in place of an API key to use Application Default
16
+ * Credentials, with the project and location in the call's `env`.
17
+ */
18
+ export declare const VERTEX_ADC_MARKER = "gcp-vertex-credentials";
19
+ /** Sets the providers this process lends the Host's identity to (at startup). */
20
+ export declare function useHostIdentity(providers: readonly string[]): void;
21
+ /** Why a model of `provider` may not use the Host's identity here, or undefined when it may. */
22
+ export declare function hostIdentityRefused(provider: string): string | undefined;
23
+ /** The call's `env` for a `host_identity` credential: where Agent Platform runs it. */
24
+ export declare function hostIdentityEnv(project: string, location: string): Record<string, string>;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The Host's identity for model calls (ADR-71): a model credential of type `host_identity` holds
3
+ * no secret, only the Google Cloud project and location. The model gate calls Agent Platform with
4
+ * the Host's Google Application Default Credentials, which Google's client library finds at each
5
+ * call (`GOOGLE_APPLICATION_CREDENTIALS`, gcloud's file, or the metadata server on Google Cloud).
6
+ * Nothing of them is stored, logged or passed to a sandbox.
7
+ *
8
+ * Off unless the Host's operator lends it, per provider, with `NYLORUN_MODEL_HOST_IDENTITY` on the
9
+ * process that runs the gates. Every Tenant on the Host may then use it, so a Host that serves
10
+ * several organizations must not set it.
11
+ */
12
+ /** The providers that can use the Host's identity. */
13
+ export const HOST_IDENTITY_PROVIDERS = ["google-vertex"];
14
+ /**
15
+ * What pi-ai's Vertex AI client takes in place of an API key to use Application Default
16
+ * Credentials, with the project and location in the call's `env`.
17
+ */
18
+ export const VERTEX_ADC_MARKER = "gcp-vertex-credentials";
19
+ let lent = [];
20
+ /** Sets the providers this process lends the Host's identity to (at startup). */
21
+ export function useHostIdentity(providers) {
22
+ lent = [...providers];
23
+ }
24
+ /** Why a model of `provider` may not use the Host's identity here, or undefined when it may. */
25
+ export function hostIdentityRefused(provider) {
26
+ if (!HOST_IDENTITY_PROVIDERS.includes(provider))
27
+ return `The Host's identity authenticates ${HOST_IDENTITY_PROVIDERS.join(", ")} only, not ${provider}.`;
28
+ if (!lent.includes(provider))
29
+ return `This Host doesn't lend its identity to ${provider}: its operator sets NYLORUN_MODEL_HOST_IDENTITY=${provider}.`;
30
+ return undefined;
31
+ }
32
+ /** The call's `env` for a `host_identity` credential: where Agent Platform runs it. */
33
+ export function hostIdentityEnv(project, location) {
34
+ return { GOOGLE_CLOUD_PROJECT: project, GOOGLE_CLOUD_LOCATION: location };
35
+ }
@@ -18,11 +18,15 @@ export declare class HostModelVault {
18
18
  private readonly kek;
19
19
  constructor(options: HostModelVaultOptions);
20
20
  /**
21
- * Reads the active host model secret, with the inputs the operator added to catalog models
22
- * (protocol 12). Decrypts after the read commits.
21
+ * Reads the host model secret a call uses, with the inputs the operator added to catalog
22
+ * models (protocol 12): the session's own model while its provider is connected (Host feature
23
+ * `session-model`), else the Tenant's active one. Decrypts after the read commits.
24
+ */
25
+ readHostModel(sessionId?: string): Promise<HostModelSecret | undefined>;
26
+ /**
27
+ * Replaces a host model's secret, keeping its binding: `provider`'s, the one the refreshed
28
+ * credential was read for, else the active one's.
23
29
  */
24
- readHostModel(): Promise<HostModelSecret | undefined>;
25
- /** Replaces the active host model's secret, keeping its binding. */
26
30
  updateHostCredential(credential: {
27
31
  type: "api_key" | "oauth";
28
32
  key?: string;
@@ -30,5 +34,5 @@ export declare class HostModelVault {
30
34
  refresh?: string;
31
35
  access?: string;
32
36
  expires?: number;
33
- }): Promise<void>;
37
+ }, provider?: string): Promise<void>;
34
38
  }
@@ -1,7 +1,7 @@
1
1
  import { readAddedInputs } from "../tenant/model-setting.js";
2
2
  import { encryptSecret } from "./crypto.js";
3
3
  import { VaultError } from "./error.js";
4
- import { activeHostCredentialRow, HOST_VAULT_ID, hostModelAad, modelBinding, readHostPayload, } from "./service.js";
4
+ import { activeHostCredentialRow, hostCredentialRowFor, hostCredentialRowOf, HOST_VAULT_ID, hostModelAad, modelBinding, readHostPayload, } from "./service.js";
5
5
  export class HostModelVault {
6
6
  store;
7
7
  kek;
@@ -10,28 +10,36 @@ export class HostModelVault {
10
10
  this.kek = options.kek;
11
11
  }
12
12
  /**
13
- * Reads the active host model secret, with the inputs the operator added to catalog models
14
- * (protocol 12). Decrypts after the read commits.
13
+ * Reads the host model secret a call uses, with the inputs the operator added to catalog
14
+ * models (protocol 12): the session's own model while its provider is connected (Host feature
15
+ * `session-model`), else the Tenant's active one. Decrypts after the read commits.
15
16
  */
16
- async readHostModel() {
17
- const { row, addedInputs } = await this.store.tx(async (t) => ({
18
- row: await activeHostCredentialRow(t),
19
- addedInputs: await readAddedInputs(t),
20
- }));
21
- if (!row)
17
+ async readHostModel(sessionId) {
18
+ const { found, addedInputs } = await this.store.tx(async (t) => {
19
+ const session = sessionId === undefined ? undefined : await t.get("sessions", sessionId);
20
+ return {
21
+ found: await hostCredentialRowOf(t, session?.model),
22
+ addedInputs: await readAddedInputs(t),
23
+ };
24
+ });
25
+ if (!found)
22
26
  return undefined;
23
- const binding = modelBinding(row);
24
- const payload = readHostPayload(this.kek(), row, binding);
27
+ const { row, binding } = found;
28
+ // The row's own binding seals its secret; a session's model only changes what is called.
29
+ const payload = readHostPayload(this.kek(), row, modelBinding(row));
25
30
  const credential = binding.authType === "oauth"
26
31
  ? { type: "oauth", ...payload.oauth }
27
32
  : binding.authType === "workload"
28
33
  ? // The workload token is read from its file at each call (#496), never stored.
29
34
  { type: "workload" }
30
- : {
31
- type: "api_key",
32
- key: payload.apiKey,
33
- ...(payload.env ? { env: payload.env } : {}),
34
- };
35
+ : binding.authType === "host_identity"
36
+ ? // The Host's identity is found at each call (ADR-71): only where the calls go is kept.
37
+ { type: "host_identity", ...(payload.env ? { env: payload.env } : {}) }
38
+ : {
39
+ type: "api_key",
40
+ key: payload.apiKey,
41
+ ...(payload.env ? { env: payload.env } : {}),
42
+ };
35
43
  return {
36
44
  provider: binding.provider,
37
45
  model: binding.model,
@@ -42,11 +50,14 @@ export class HostModelVault {
42
50
  credential,
43
51
  };
44
52
  }
45
- /** Replaces the active host model's secret, keeping its binding. */
46
- async updateHostCredential(credential) {
53
+ /**
54
+ * Replaces a host model's secret, keeping its binding: `provider`'s, the one the refreshed
55
+ * credential was read for, else the active one's.
56
+ */
57
+ async updateHostCredential(credential, provider) {
47
58
  const kek = this.kek();
48
59
  await this.store.tx(async (t) => {
49
- const row = await activeHostCredentialRow(t);
60
+ const row = provider === undefined ? await activeHostCredentialRow(t) : await hostCredentialRowFor(t, provider);
50
61
  if (!row)
51
62
  throw new VaultError(404, "Model provider is not configured");
52
63
  const binding = modelBinding(row);
@@ -1,4 +1,4 @@
1
- import type { CredentialCoverage, CredentialCoverageRequest, CredentialIdentity, EnvironmentSecretSlot, AgentSecretView, HostModelAuthType, HostModelProviderInfo, HostModelView, PutAgentSecretRequest, PutHostModelRequest, CustomModelSettings, ModelInput, SelectHostModelRequest } from "@nylorun/core/contracts";
1
+ import type { CredentialCoverage, CredentialCoverageRequest, CredentialIdentity, EnvironmentSecretSlot, AgentSecretView, HostModelAuthType, HostModelProviderInfo, HostModelView, SessionModelChoice, SessionModelView, PutAgentSecretRequest, PutHostModelRequest, CustomModelSettings, ModelInput, SelectHostModelRequest } from "@nylorun/core/contracts";
2
2
  import type { AgentManifest, WorkflowManifest } from "@nylorun/core/define";
3
3
  import type { SessionStore, Tx, VaultCredentialRow } from "../store/types.js";
4
4
  export declare const HOST_VAULT_ID = "host";
@@ -166,7 +166,13 @@ export declare class VaultService {
166
166
  * the credential of the Agent's vault bound to the URL. Reads no secret, writes no audit row.
167
167
  */
168
168
  coverage(manifest: AgentManifest | WorkflowManifest, request: CredentialCoverageRequest): Promise<CredentialCoverage>;
169
- getHostModel(): Promise<HostModelView>;
169
+ /**
170
+ * The Tenant's model, or the model a session's turns use (`choice`, its own, while its provider
171
+ * is connected).
172
+ */
173
+ getHostModel(choice?: SessionModelChoice): Promise<HostModelView>;
174
+ /** The model a session's next turn uses, and where it comes from (Host feature `session-model`). */
175
+ getSessionModel(choice?: SessionModelChoice): Promise<SessionModelView>;
170
176
  listHostProviders(): Promise<{
171
177
  providers: HostModelProviderInfo[];
172
178
  }>;
@@ -194,6 +200,16 @@ export declare function hostModelRows(t: Tx): Promise<VaultCredentialRow[]>;
194
200
  export declare function hostCredentialRowFor(t: Tx, provider: string): Promise<VaultCredentialRow | undefined>;
195
201
  /** The provider the host model selection names, or the only (or legacy) one configured. */
196
202
  export declare function activeProviderId(t: Tx): Promise<string | undefined>;
203
+ /**
204
+ * The host model credential row a session's calls use (ciphertext), in `t`, with the binding
205
+ * they call: its own model (`choice`) on its provider's row while that provider is connected,
206
+ * else the Tenant's active one. `row`'s own binding seals its secret (`readHostPayload`).
207
+ */
208
+ export declare function hostCredentialRowOf(t: Tx, choice: SessionModelChoice | undefined): Promise<{
209
+ row: VaultCredentialRow;
210
+ binding: ModelBinding;
211
+ source: "session" | "tenant";
212
+ } | undefined>;
197
213
  /** The active host model credential row (ciphertext), in `t`. */
198
214
  export declare function activeHostCredentialRow(t: Tx): Promise<VaultCredentialRow | undefined>;
199
215
  export declare function readHostPayload(kek: Buffer, row: VaultCredentialRow, binding: ModelBinding): HostSecretPayload;
@@ -39,7 +39,8 @@
39
39
  * coverage(manifest: AgentManifest | WorkflowManifest, request: CredentialCoverageRequest): Promise<CredentialCoverage>
40
40
  *
41
41
  * // Host model credential: each opens its own transaction.
42
- * getHostModel(): Promise<HostModelView>
42
+ * getHostModel(choice?: SessionModelChoice): Promise<HostModelView>
43
+ * getSessionModel(choice?: SessionModelChoice): Promise<SessionModelView>
43
44
  * listHostProviders(): Promise<{ providers: HostModelProviderInfo[] }>
44
45
  * putHostModel(body: PutHostModelRequest): Promise<HostModelView>
45
46
  * selectHostModel(body: SelectHostModelRequest): Promise<HostModelView>
@@ -88,6 +89,7 @@ import { hostModelCatalog, inputsOfHostModel } from "../model/catalog.js";
88
89
  import { inputsError } from "../model/capabilities.js";
89
90
  import { readAddedInputs } from "../tenant/model-setting.js";
90
91
  import { normalizeVaultUrl } from "./url.js";
92
+ import { hostIdentityEnv, hostIdentityRefused } from "./host-identity.js";
91
93
  export const HOST_VAULT_ID = "host";
92
94
  const HOST_MODEL_ID = "host-model";
93
95
  export class VaultService {
@@ -510,8 +512,29 @@ export class VaultService {
510
512
  });
511
513
  }
512
514
  // --- host model ----------------------------------------------------------------
513
- async getHostModel() {
514
- return this.store.tx((t) => this.hostModelView(t));
515
+ /**
516
+ * The Tenant's model, or the model a session's turns use (`choice`, its own, while its provider
517
+ * is connected).
518
+ */
519
+ async getHostModel(choice) {
520
+ return this.store.tx((t) => this.hostModelView(t, choice));
521
+ }
522
+ /** The model a session's next turn uses, and where it comes from (Host feature `session-model`). */
523
+ async getSessionModel(choice) {
524
+ return this.store.tx(async (t) => {
525
+ const found = await hostCredentialRowOf(t, choice);
526
+ const kept = choice ? { choice } : {};
527
+ if (!found)
528
+ return { configured: false, ...kept };
529
+ return {
530
+ configured: true,
531
+ source: found.source,
532
+ provider: found.binding.provider,
533
+ model: found.binding.model,
534
+ ...(found.binding.baseUrl ? { baseUrl: found.binding.baseUrl } : {}),
535
+ ...kept,
536
+ };
537
+ });
515
538
  }
516
539
  async listHostProviders() {
517
540
  return this.store.tx(async (t) => {
@@ -546,10 +569,16 @@ export class VaultService {
546
569
  this.validateHostModel(body);
547
570
  if (body.auth.type === "workload" && body.provider !== "custom")
548
571
  throw new VaultError(400, "The workload token authenticates a custom provider only.");
572
+ if (body.auth.type === "host_identity") {
573
+ const refused = hostIdentityRefused(body.provider);
574
+ if (refused)
575
+ throw new VaultError(400, refused);
576
+ }
549
577
  await this.ensureHostVault(t);
550
578
  const credentialId = hostModelCredentialId(body.provider);
551
579
  await this.deleteHostProviderRows(t, body.provider);
552
- // The workload token is read on every call and never stored (#496).
580
+ // The workload token is read on every call and never stored (#496); the Host's identity
581
+ // too (ADR-71), which keeps only where its calls go.
553
582
  const payload = body.auth.type === "api_key"
554
583
  ? {
555
584
  apiKey: body.auth.key,
@@ -557,7 +586,9 @@ export class VaultService {
557
586
  }
558
587
  : body.auth.type === "oauth"
559
588
  ? { oauth: body.auth }
560
- : {};
589
+ : body.auth.type === "host_identity"
590
+ ? { env: hostIdentityEnv(body.auth.project, body.auth.location) }
591
+ : {};
561
592
  await this.insertHostCredential(t, kek, {
562
593
  id: credentialId,
563
594
  provider: body.provider,
@@ -714,11 +745,11 @@ export class VaultService {
714
745
  ...sealed,
715
746
  });
716
747
  }
717
- async hostModelView(t) {
718
- const row = await activeHostCredentialRow(t);
719
- if (!row)
748
+ async hostModelView(t, choice) {
749
+ const found = await hostCredentialRowOf(t, choice);
750
+ if (!found)
720
751
  return { configured: false };
721
- const binding = modelBinding(row);
752
+ const { binding } = found;
722
753
  return {
723
754
  configured: true,
724
755
  provider: binding.provider,
@@ -904,6 +935,18 @@ export async function activeProviderId(t) {
904
935
  return modelBinding(legacy).provider;
905
936
  return modelBinding(rows[0]).provider;
906
937
  }
938
+ /**
939
+ * The host model credential row a session's calls use (ciphertext), in `t`, with the binding
940
+ * they call: its own model (`choice`) on its provider's row while that provider is connected,
941
+ * else the Tenant's active one. `row`'s own binding seals its secret (`readHostPayload`).
942
+ */
943
+ export async function hostCredentialRowOf(t, choice) {
944
+ const chosen = choice && (await hostCredentialRowFor(t, choice.provider));
945
+ if (chosen)
946
+ return { row: chosen, binding: { ...modelBinding(chosen), model: choice.model }, source: "session" };
947
+ const row = await activeHostCredentialRow(t);
948
+ return row && { row, binding: modelBinding(row), source: "tenant" };
949
+ }
907
950
  /** The active host model credential row (ciphertext), in `t`. */
908
951
  export async function activeHostCredentialRow(t) {
909
952
  const active = await activeProviderId(t);
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const RUNTIME_VERSION = "0.32.0-beta";
1
+ export declare const RUNTIME_VERSION = "0.34.0-beta";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // Kept in step with package.json by runtime/server/scripts/check-package.mjs, which runs in npm run check.
2
2
  // release:prepare also rewrites this when it bumps @nylorun/runtime.
3
- export const RUNTIME_VERSION = "0.32.0-beta";
3
+ export const RUNTIME_VERSION = "0.34.0-beta";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nylorun/runtime",
3
- "version": "0.32.0-beta",
3
+ "version": "0.34.0-beta",
4
4
  "description": "Nylorun Runtime: the agent execution Host on Postgres, Restate and S2, and model providers.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -59,14 +59,14 @@
59
59
  "db:studio": "drizzle-kit studio"
60
60
  },
61
61
  "dependencies": {
62
- "@ag-ui/core": "~1.0.2",
62
+ "@ag-ui/core": "~1.0.3",
63
63
  "@asteasolutions/zod-to-openapi": "^9.1.0",
64
- "@earendil-works/pi-ai": "1.2.0",
64
+ "@earendil-works/pi-ai": "1.3.0",
65
65
  "@hono/node-server": "^2.1.5",
66
66
  "@hono/zod-openapi": "^1.6.3",
67
67
  "@modelcontextprotocol/sdk": "^1.32.1",
68
- "@nylorun/core": "0.28.0-beta",
69
- "@nylorun/harness": "0.29.4-beta",
68
+ "@nylorun/core": "0.30.0-beta",
69
+ "@nylorun/harness": "0.29.6-beta",
70
70
  "@restatedev/restate-sdk": "1.17.3",
71
71
  "@restatedev/restate-sdk-clients": "1.17.3",
72
72
  "@s2-dev/streamstore": "0.28.0",
@@ -85,7 +85,7 @@
85
85
  },
86
86
  "devDependencies": {
87
87
  "@a2a-js/sdk": "~1.3.0",
88
- "@ag-ui/client": "1.0.2",
88
+ "@ag-ui/client": "1.0.3",
89
89
  "@scalar/openapi-parser": "^0.29.13",
90
90
  "@types/node": "^26.6.5",
91
91
  "@types/pg": "^8.23.1",