@agent-native/core 0.198.3 → 0.198.5

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 (94) hide show
  1. package/dist/a2a/types.d.ts +5 -0
  2. package/dist/agent/production-agent.js +26 -1
  3. package/dist/catalog.json +1 -0
  4. package/dist/client/chat/agentkit-agent-native.js +15 -15
  5. package/dist/client/chat/runtime.js +5 -3
  6. package/dist/client/feature-flags/types.d.ts +2 -0
  7. package/dist/client/i18n.d.ts +2 -0
  8. package/dist/client/i18n.js +2 -0
  9. package/dist/client/integrations/index.d.ts +1 -0
  10. package/dist/client/integrations/index.js +1 -0
  11. package/dist/client/labs/index.d.ts +1 -1
  12. package/dist/client/labs/use-lab.d.ts +5 -0
  13. package/dist/client/labs/use-lab.js +7 -3
  14. package/dist/client/resources/mcp-connection-resume.d.ts +5 -3
  15. package/dist/client/resources/mcp-connection-resume.js +150 -13
  16. package/dist/client/sse-event-processor.d.ts +6 -0
  17. package/dist/client/uploads/index.d.ts +1 -0
  18. package/dist/client/uploads/index.js +1 -0
  19. package/dist/client/uploads/private-icon.d.ts +10 -0
  20. package/dist/client/uploads/private-icon.js +52 -0
  21. package/dist/collab/routes.d.ts +2 -2
  22. package/dist/feature-flags/actions/get-feature-flags.js +20 -0
  23. package/dist/feature-flags/actions/list-feature-flags.d.ts +2 -0
  24. package/dist/feature-flags/actions/list-feature-flags.js +5 -0
  25. package/dist/feature-flags/actions/set-feature-flag.js +5 -0
  26. package/dist/file-upload/actions/upload-image.d.ts +3 -3
  27. package/dist/framework-tools.js +2 -0
  28. package/dist/icon-assets/index.d.ts +3 -0
  29. package/dist/icon-assets/index.js +3 -0
  30. package/dist/icon-assets/multipart.d.ts +9 -0
  31. package/dist/icon-assets/multipart.js +60 -0
  32. package/dist/icon-assets/schema.d.ts +194 -0
  33. package/dist/icon-assets/schema.js +16 -0
  34. package/dist/icon-assets/store.d.ts +38 -0
  35. package/dist/icon-assets/store.js +187 -0
  36. package/dist/icon-assets/svg.d.ts +2 -0
  37. package/dist/icon-assets/svg.js +146 -0
  38. package/dist/icon-assets/workspace-transport.d.ts +20 -0
  39. package/dist/icon-assets/workspace-transport.js +122 -0
  40. package/dist/identity/rekey.js +1 -0
  41. package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
  42. package/dist/labs/actions/get-lab-states.d.ts +2 -0
  43. package/dist/labs/actions/get-lab-states.js +14 -0
  44. package/dist/labs/actions/get-labs.js +2 -2
  45. package/dist/labs/actions/set-lab.js +4 -2
  46. package/dist/labs/index.d.ts +1 -1
  47. package/dist/labs/index.js +1 -1
  48. package/dist/labs/registry.d.ts +3 -0
  49. package/dist/labs/registry.js +14 -0
  50. package/dist/labs/server.d.ts +1 -1
  51. package/dist/labs/server.js +1 -1
  52. package/dist/labs/store.d.ts +13 -2
  53. package/dist/labs/store.js +124 -7
  54. package/dist/localization/default-messages.d.ts +2 -0
  55. package/dist/localization/default-messages.js +1 -1
  56. package/dist/localization/icon-picker-messages.d.ts +44 -0
  57. package/dist/localization/icon-picker-messages.js +22 -0
  58. package/dist/mcp-client/oauth-client.d.ts +1 -0
  59. package/dist/mcp-client/oauth-client.js +42 -4
  60. package/dist/mcp-client/oauth-routes.js +15 -2
  61. package/dist/notifications/routes.d.ts +1 -1
  62. package/dist/observability/routes.d.ts +9 -9
  63. package/dist/org/actions/list-workspace-icons.d.ts +7 -0
  64. package/dist/org/actions/list-workspace-icons.js +41 -0
  65. package/dist/org/handlers.d.ts +1 -1
  66. package/dist/org/handlers.js +28 -1
  67. package/dist/org/index.d.ts +1 -1
  68. package/dist/org/migrations.js +21 -0
  69. package/dist/org/plugin.js +42 -0
  70. package/dist/org/private-icon-handlers.d.ts +6 -0
  71. package/dist/org/private-icon-handlers.js +212 -0
  72. package/dist/progress/routes.d.ts +1 -1
  73. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  74. package/dist/provider-api/actions/provider-api.d.ts +5 -5
  75. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  76. package/dist/provider-api/index.d.ts +1 -1
  77. package/dist/provider-api/index.js +26 -6
  78. package/dist/secrets/routes.d.ts +4 -4
  79. package/dist/server/action-discovery.js +5 -0
  80. package/dist/server/agent-chat-plugin.js +14 -0
  81. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  82. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  83. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  84. package/dist/server/core-routes-plugin.d.ts +1 -1
  85. package/dist/server/core-routes-plugin.js +18 -3
  86. package/dist/server/index.d.ts +1 -1
  87. package/dist/server/index.js +1 -1
  88. package/dist/server/workspace-provider-oauth.d.ts +1 -0
  89. package/dist/server/workspace-provider-oauth.js +4 -2
  90. package/dist/templates/chat/app/components/chat/ChatRouteContent.tsx +9 -16
  91. package/dist/triggers/actions/manage-automation.d.ts +5 -5
  92. package/dist/vite/action-types-plugin.js +4 -0
  93. package/package.json +7 -9
  94. package/src/templates/chat/app/components/chat/ChatRouteContent.tsx +9 -16
@@ -7,7 +7,31 @@ import { listSSOProvidersHandler, createSSOProviderHandler, verifySSOProviderHan
7
7
  import { CROSS_APP_ORG_FEDERATION_FLAG } from "./feature-flags.js";
8
8
  import { getMyOrgHandler, createOrgHandler, updateOrgHandler, deleteOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, retryPendingFederatedRemovalHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, joinByDomainHandler, setDomainHandler, setWorkspaceUrlHandler, setRequiredAuthProviderHandler, revealA2ASecretHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setWorkspaceAppDefaultVisibilityHandler, setOrgVisualIdentityHandler, } from "./handlers.js";
9
9
  import { ORG_MIGRATIONS } from "./migrations.js";
10
+ import { readWorkspacePrivateIconHandler, uploadWorkspacePrivateIconHandler, } from "./private-icon-handlers.js";
10
11
  const ORG_PREFIX = `${FRAMEWORK_PREFIX}/org`;
12
+ async function workspaceIconUploadResponse(event) {
13
+ try {
14
+ return await uploadWorkspacePrivateIconHandler(event);
15
+ }
16
+ catch (error) {
17
+ const statusCode = error &&
18
+ typeof error === "object" &&
19
+ "statusCode" in error &&
20
+ typeof error.statusCode === "number"
21
+ ? error.statusCode
22
+ : 500;
23
+ setResponseStatus(event, statusCode);
24
+ return {
25
+ message: statusCode < 500 &&
26
+ error &&
27
+ typeof error === "object" &&
28
+ "message" in error &&
29
+ typeof error.message === "string"
30
+ ? error.message
31
+ : "Workspace icon upload failed.",
32
+ };
33
+ }
34
+ }
11
35
  /**
12
36
  * Mounts the org REST routes under `/_agent-native/org/*` and runs the org
13
37
  * module's migrations.
@@ -47,6 +71,24 @@ export function createOrgPlugin() {
47
71
  await awaitBootstrap(nitroApp);
48
72
  await migrate(nitroApp);
49
73
  const app = getH3App(nitroApp);
74
+ app.use(`${ORG_PREFIX}/private-icons`, defineEventHandler(async (event) => {
75
+ const tail = getRequestURL(event).pathname || "/";
76
+ const method = getMethod(event);
77
+ if (tail === "/" ||
78
+ tail === "" ||
79
+ tail === `${ORG_PREFIX}/private-icons` ||
80
+ tail === `${ORG_PREFIX}/private-icons/`) {
81
+ if (method === "POST")
82
+ return workspaceIconUploadResponse(event);
83
+ setResponseStatus(event, 405);
84
+ return { error: "Method not allowed" };
85
+ }
86
+ if (method === "GET")
87
+ return readWorkspacePrivateIconHandler(event);
88
+ setResponseStatus(event, 405);
89
+ return { error: "Method not allowed" };
90
+ }));
91
+ // GET /me
50
92
  app.use(`${ORG_PREFIX}/me`, defineEventHandler(async (event) => {
51
93
  if (getMethod(event) !== "GET") {
52
94
  setResponseStatus(event, 405);
@@ -0,0 +1,6 @@
1
+ export declare const uploadWorkspacePrivateIconHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
2
+ id: string;
3
+ }>>;
4
+ export declare const readWorkspacePrivateIconHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<Buffer<ArrayBuffer>>>;
5
+ export declare function assertOwnedLocalWorkspaceIcon(assetId: string, email: string, orgId: string): Promise<void>;
6
+ export declare function requirePrivateWorkspaceIconId(assetId: string): void;
@@ -0,0 +1,212 @@
1
+ import { createError, defineEventHandler, getRequestURL, setResponseHeader, setResponseStatus, } from "h3";
2
+ import { getDbExec } from "../db/client.js";
3
+ import { getIconAsset, IconUploadBodyError, putIconAsset, readIconUploadFormData, readIconAssetForAuthorizedReference, } from "../icon-assets/index.js";
4
+ import { readFederatedWorkspaceIcon, uploadFederatedWorkspaceIcon, verifyFederatedWorkspaceIconOwner, } from "../icon-assets/workspace-transport.js";
5
+ import { getSession } from "../server/auth.js";
6
+ import { runWithRequestContext } from "../server/request-context.js";
7
+ import { getOrgContext } from "./context.js";
8
+ import { validateFederatedOrganizationMembership } from "./federation.js";
9
+ import { parseOrganizationIconJson } from "./visual-identity.js";
10
+ const ASSET_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11
+ const ORG_ID = /^[A-Za-z0-9_-]{1,128}$/;
12
+ const MAX_ICON_BYTES = 5 * 1024 * 1024;
13
+ const IMAGE_TYPES = new Set([
14
+ "image/png",
15
+ "image/jpeg",
16
+ "image/webp",
17
+ "image/svg+xml",
18
+ ]);
19
+ async function readOrg(orgId) {
20
+ const result = await getDbExec().execute({
21
+ sql: `SELECT identity_authority, identity_id, allowed_domain, icon_json
22
+ FROM organizations WHERE id = ? LIMIT 1`,
23
+ args: [orgId],
24
+ });
25
+ const row = result.rows[0];
26
+ if (!row)
27
+ return null;
28
+ return {
29
+ identityAuthority: typeof row.identity_authority === "string"
30
+ ? row.identity_authority
31
+ : null,
32
+ identityId: typeof row.identity_id === "string" ? row.identity_id : null,
33
+ allowedDomain: typeof row.allowed_domain === "string" ? row.allowed_domain : null,
34
+ iconJson: row.icon_json,
35
+ };
36
+ }
37
+ function isFederated(org) {
38
+ if (Boolean(org.identityAuthority) !== Boolean(org.identityId)) {
39
+ throw new Error("Workspace identity mapping is incomplete.");
40
+ }
41
+ return Boolean(org.identityAuthority);
42
+ }
43
+ export const uploadWorkspacePrivateIconHandler = defineEventHandler(async (event) => {
44
+ const ctx = await getOrgContext(event);
45
+ if (!ctx.orgId || !ctx.email)
46
+ throw createError({
47
+ statusCode: 401,
48
+ message: "Organization access required",
49
+ });
50
+ if (ctx.role !== "owner" && ctx.role !== "admin") {
51
+ throw createError({
52
+ statusCode: 403,
53
+ message: "Only owners and admins can upload workspace icons",
54
+ });
55
+ }
56
+ const org = await readOrg(ctx.orgId);
57
+ if (!org)
58
+ throw createError({ statusCode: 404, message: "Organization not found" });
59
+ const form = await readIconUploadFormData(event.req).catch((error) => {
60
+ if (error instanceof IconUploadBodyError) {
61
+ throw createError({
62
+ statusCode: error.statusCode,
63
+ cause: error,
64
+ message: error.statusCode === 413
65
+ ? "Workspace icon is too large"
66
+ : error.message,
67
+ });
68
+ }
69
+ throw error;
70
+ });
71
+ const file = form.get("file");
72
+ if (!file || typeof file === "string" || !file.size)
73
+ throw createError({ statusCode: 400, message: "Image file required" });
74
+ if (file.size > MAX_ICON_BYTES)
75
+ throw createError({
76
+ statusCode: 413,
77
+ message: "Workspace icon is too large",
78
+ });
79
+ const mimeType = file.type?.toLowerCase();
80
+ if (!mimeType || !IMAGE_TYPES.has(mimeType)) {
81
+ throw createError({
82
+ statusCode: 415,
83
+ message: "Unsupported workspace icon image type",
84
+ });
85
+ }
86
+ const data = new Uint8Array(await file.arrayBuffer());
87
+ const id = await runWithRequestContext({ userEmail: ctx.email, orgId: ctx.orgId }, async () => isFederated(org)
88
+ ? uploadFederatedWorkspaceIcon(event, org, ctx.email, {
89
+ data,
90
+ mimeType,
91
+ filename: file.name || "workspace-icon",
92
+ })
93
+ : (await putIconAsset({
94
+ data,
95
+ mimeType,
96
+ filename: file.name || undefined,
97
+ ownerEmail: ctx.email,
98
+ orgId: ctx.orgId,
99
+ })).id);
100
+ if (!ASSET_ID.test(id))
101
+ throw new Error("Workspace icon storage returned an invalid asset ID.");
102
+ setResponseStatus(event, 201);
103
+ return { id };
104
+ });
105
+ export const readWorkspacePrivateIconHandler = defineEventHandler(async (event) => {
106
+ const session = await getSession(event);
107
+ if (!session?.email)
108
+ throw createError({
109
+ statusCode: 401,
110
+ message: "Authentication required",
111
+ });
112
+ const path = getRequestURL(event).pathname;
113
+ const match = path.match(/^(?:\/_agent-native\/org\/private-icons)?\/(library\/)?([A-Za-z0-9_-]{1,128})\/([0-9a-f-]{36})\/?$/i);
114
+ if (!match || !ORG_ID.test(match[2]) || !ASSET_ID.test(match[3])) {
115
+ throw createError({
116
+ statusCode: 404,
117
+ message: "Workspace icon not found",
118
+ });
119
+ }
120
+ const [, library, orgId, assetId] = match;
121
+ const membership = await getDbExec().execute({
122
+ sql: `SELECT role FROM org_members
123
+ WHERE org_id = ? AND LOWER(email) = ?
124
+ AND federation_removal_pending_at IS NULL LIMIT 1`,
125
+ args: [orgId, session.email.toLowerCase()],
126
+ });
127
+ if (!membership.rows.length)
128
+ throw createError({
129
+ statusCode: 404,
130
+ message: "Workspace icon not found",
131
+ });
132
+ if (library &&
133
+ membership.rows[0]?.role !== "owner" &&
134
+ membership.rows[0]?.role !== "admin") {
135
+ throw createError({
136
+ statusCode: 404,
137
+ message: "Workspace icon not found",
138
+ });
139
+ }
140
+ const org = await readOrg(orgId);
141
+ if (!org)
142
+ throw createError({
143
+ statusCode: 404,
144
+ message: "Workspace icon not found",
145
+ });
146
+ if (library) {
147
+ const owned = isFederated(org)
148
+ ? await verifyFederatedWorkspaceIconOwner(event, org, session.email, assetId)
149
+ : Boolean(await getIconAsset(assetId, { ownerEmail: session.email, orgId }));
150
+ if (!owned)
151
+ throw createError({
152
+ statusCode: 404,
153
+ message: "Workspace icon not found",
154
+ });
155
+ }
156
+ else {
157
+ const icon = parseOrganizationIconJson(org.iconJson);
158
+ if (icon?.kind !== "image" ||
159
+ icon.authority !== "private-icon" ||
160
+ icon.assetId !== assetId) {
161
+ throw createError({
162
+ statusCode: 404,
163
+ message: "Workspace icon not found",
164
+ });
165
+ }
166
+ }
167
+ if (isFederated(org)) {
168
+ const verified = await validateFederatedOrganizationMembership(event, {
169
+ orgId,
170
+ email: session.email,
171
+ });
172
+ if (!verified.active)
173
+ throw createError({
174
+ statusCode: 404,
175
+ message: "Workspace icon not found",
176
+ });
177
+ }
178
+ const bytes = isFederated(org)
179
+ ? await readFederatedWorkspaceIcon(event, org, session.email, assetId)
180
+ : await readIconAssetForAuthorizedReference(assetId, { orgId });
181
+ if (!bytes || !IMAGE_TYPES.has(bytes.mimeType)) {
182
+ throw createError({
183
+ statusCode: 404,
184
+ message: "Workspace icon not found",
185
+ });
186
+ }
187
+ setResponseHeader(event, "Content-Type", bytes.mimeType);
188
+ setResponseHeader(event, "Content-Length", String(bytes.data.length));
189
+ setResponseHeader(event, "Cache-Control", "private, no-store");
190
+ setResponseHeader(event, "X-Content-Type-Options", "nosniff");
191
+ if (bytes.mimeType === "image/svg+xml") {
192
+ setResponseHeader(event, "Content-Security-Policy", "sandbox; default-src 'none'; style-src 'unsafe-inline'; img-src data:");
193
+ }
194
+ return Buffer.from(bytes.data);
195
+ });
196
+ export async function assertOwnedLocalWorkspaceIcon(assetId, email, orgId) {
197
+ if (!ASSET_ID.test(assetId) ||
198
+ !(await getIconAsset(assetId, { ownerEmail: email, orgId }))) {
199
+ throw createError({
200
+ statusCode: 403,
201
+ message: "Workspace icon asset is not owned by this organization administrator",
202
+ });
203
+ }
204
+ }
205
+ export function requirePrivateWorkspaceIconId(assetId) {
206
+ if (!ASSET_ID.test(assetId)) {
207
+ throw createError({
208
+ statusCode: 400,
209
+ message: "Invalid workspace icon asset ID",
210
+ });
211
+ }
212
+ }
@@ -2,6 +2,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
2
2
  error: string;
3
3
  ok?: undefined;
4
4
  } | {
5
- ok: boolean;
6
5
  error?: undefined;
6
+ ok: boolean;
7
7
  }>>;
@@ -75,10 +75,11 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
75
75
  user: "user";
76
76
  }>>;
77
77
  }, z.core.$strip>>, {
78
- id?: undefined;
79
78
  message?: undefined;
80
- found?: undefined;
81
79
  deleted?: undefined;
80
+ id?: undefined;
81
+ provider?: undefined;
82
+ found?: undefined;
82
83
  providers: {
83
84
  id: string;
84
85
  label: string;
@@ -89,13 +90,12 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
89
90
  updatedAt: number;
90
91
  }[];
91
92
  count: number;
92
- provider?: undefined;
93
93
  registered?: undefined;
94
94
  label?: undefined;
95
95
  } | {
96
- id?: undefined;
97
96
  message?: undefined;
98
97
  deleted?: undefined;
98
+ id?: undefined;
99
99
  providers?: undefined;
100
100
  count?: undefined;
101
101
  found: boolean;
@@ -105,29 +105,29 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
105
105
  } | {
106
106
  message?: undefined;
107
107
  deleted?: undefined;
108
+ provider?: undefined;
108
109
  providers?: undefined;
109
110
  count?: undefined;
110
- provider?: undefined;
111
111
  found: boolean;
112
112
  id: string;
113
113
  registered?: undefined;
114
114
  label?: undefined;
115
115
  } | {
116
116
  message?: undefined;
117
+ provider?: undefined;
117
118
  found?: undefined;
118
119
  providers?: undefined;
119
120
  count?: undefined;
120
- provider?: undefined;
121
121
  deleted: boolean;
122
122
  id: string;
123
123
  registered?: undefined;
124
124
  label?: undefined;
125
125
  } | {
126
- found?: undefined;
127
126
  deleted?: undefined;
127
+ provider?: undefined;
128
+ found?: undefined;
128
129
  providers?: undefined;
129
130
  count?: undefined;
130
- provider?: undefined;
131
131
  registered: boolean;
132
132
  id: string;
133
133
  label: string;
@@ -311,10 +311,10 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
311
311
  notes?: string | undefined;
312
312
  scope?: "org" | "user" | undefined;
313
313
  }, {
314
- id?: undefined;
315
314
  provider?: undefined;
316
- deleted?: undefined;
315
+ id?: undefined;
317
316
  message?: undefined;
317
+ deleted?: undefined;
318
318
  found?: undefined;
319
319
  providers: {
320
320
  id: string;
@@ -330,9 +330,9 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
330
330
  label?: undefined;
331
331
  } | {
332
332
  id?: undefined;
333
- deleted?: undefined;
334
333
  count?: undefined;
335
334
  message?: undefined;
335
+ deleted?: undefined;
336
336
  providers?: undefined;
337
337
  found: boolean;
338
338
  provider: import("../custom-registry.js").CustomProviderConfig;
@@ -340,9 +340,9 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
340
340
  label?: undefined;
341
341
  } | {
342
342
  provider?: undefined;
343
- deleted?: undefined;
344
343
  count?: undefined;
345
344
  message?: undefined;
345
+ deleted?: undefined;
346
346
  providers?: undefined;
347
347
  found: boolean;
348
348
  id: string;
@@ -360,8 +360,8 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
360
360
  label?: undefined;
361
361
  } | {
362
362
  provider?: undefined;
363
- deleted?: undefined;
364
363
  count?: undefined;
364
+ deleted?: undefined;
365
365
  found?: undefined;
366
366
  providers?: undefined;
367
367
  registered: boolean;
@@ -73,6 +73,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
73
73
  offset?: unknown;
74
74
  limit?: unknown;
75
75
  }, {
76
+ deleted?: undefined;
76
77
  jobs: {
77
78
  id: string;
78
79
  name: string;
@@ -83,7 +84,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
83
84
  updatedAt: string;
84
85
  }[];
85
86
  total: number;
86
- deleted?: undefined;
87
87
  jobId?: undefined;
88
88
  } | {
89
89
  jobs?: undefined;
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
91
91
  deleted: boolean;
92
92
  jobId: string;
93
93
  } | {
94
+ deleted?: undefined;
94
95
  jobs?: undefined;
95
96
  total?: undefined;
96
- deleted?: undefined;
97
97
  jobId?: undefined;
98
98
  hits: Record<string, unknown>[];
99
99
  offset: number;
@@ -1,4 +1,4 @@
1
- import type { WorkspaceConnectionTemplateUse } from "../connections/catalog.js";
1
+ import { type WorkspaceConnectionTemplateUse } from "../connections/catalog.js";
2
2
  import { type CredentialContext } from "../credentials/index.js";
3
3
  import { type WebContentSearchOptions, type WebExtractMode, type WebResponseMode } from "../extensions/web-content.js";
4
4
  import type { CustomProviderConfig } from "./custom-registry.js";
@@ -1,5 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { AgentConnectionRequiredError } from "../action.js";
3
+ import { getWorkspaceConnectionProvider, } from "../connections/catalog.js";
3
4
  import { assertCredentialCanReachEndpoint, describeCredentialScopeGap, resolveCredentialDetailed, } from "../credentials/index.js";
4
5
  import { createSsrfSafeDispatcher, isBlockedExtensionUrlWithDns, } from "../extensions/url-safety.js";
5
6
  import { processWebContent, } from "../extensions/web-content.js";
@@ -1452,6 +1453,7 @@ export async function resolveProviderApiOAuthAccessToken(args, runtime) {
1452
1453
  })
1453
1454
  : await resolveOAuthBearerToken({
1454
1455
  auth: oauthAuth,
1456
+ runtime,
1455
1457
  ctx,
1456
1458
  accountId: args.accountId,
1457
1459
  });
@@ -2756,8 +2758,10 @@ async function resolveAuth(config, runtime, ctx, args) {
2756
2758
  })
2757
2759
  : await resolveOAuthBearerToken({
2758
2760
  auth: { ...auth, oauthProvider },
2761
+ runtime,
2759
2762
  ctx,
2760
2763
  accountId: args.accountId,
2764
+ connectionId: args.connectionId,
2761
2765
  });
2762
2766
  return {
2763
2767
  headers: { Authorization: `Bearer ${credential.value}` },
@@ -3009,9 +3013,7 @@ async function resolveAnyCredential(options) {
3009
3013
  return credential;
3010
3014
  }
3011
3015
  const scopeGap = await describeCredentialScopeGap(options.keys, options.ctx).catch(() => null);
3012
- if (options.workspaceProvider &&
3013
- !options.runtime.resolveCredential &&
3014
- !scopeGap) {
3016
+ if (options.workspaceProvider && !scopeGap) {
3015
3017
  return throwWorkspaceConnectionRequired({
3016
3018
  runtime: options.runtime,
3017
3019
  provider: options.workspaceProvider,
@@ -3029,9 +3031,7 @@ async function resolveRequiredCredential(options) {
3029
3031
  // coercion-ok: only enriches an error we throw either way — losing the scope
3030
3032
  // hint still surfaces the real "not configured" failure, never a success.
3031
3033
  .catch(() => null);
3032
- if (options.workspaceProvider &&
3033
- !options.runtime.resolveCredential &&
3034
- !scopeGap) {
3034
+ if (options.workspaceProvider && !scopeGap) {
3035
3035
  return throwWorkspaceConnectionRequired({
3036
3036
  runtime: options.runtime,
3037
3037
  provider: options.workspaceProvider,
@@ -3152,6 +3152,14 @@ async function resolveOAuthBearerToken(options) {
3152
3152
  const ownerEmail = options.ownerEmail?.trim() || options.ctx.userEmail;
3153
3153
  const accounts = await listOAuthAccountsByOwner(options.auth.oauthProvider, ownerEmail);
3154
3154
  if (accounts.length === 0) {
3155
+ if (options.auth.workspaceProvider) {
3156
+ return throwWorkspaceConnectionRequired({
3157
+ runtime: options.runtime,
3158
+ provider: options.auth.workspaceProvider,
3159
+ connectionId: options.connectionId,
3160
+ message: `${options.auth.tokenLabel} requires an available workspace connection.`,
3161
+ });
3162
+ }
3155
3163
  throw new Error(`${options.auth.tokenLabel} is not connected for ${ownerEmail}.`);
3156
3164
  }
3157
3165
  const accountId = options.accountId?.trim();
@@ -3205,10 +3213,20 @@ async function throwWorkspaceConnectionRequired(options) {
3205
3213
  resolved.connection.status !== "connected") {
3206
3214
  reason = "reauthorize";
3207
3215
  }
3216
+ const connectionProvider = getWorkspaceConnectionProvider(options.provider);
3208
3217
  throw new AgentConnectionRequiredError(options.message, {
3209
3218
  provider: options.provider,
3210
3219
  reason,
3211
3220
  appId: options.runtime.appId,
3221
+ ...(connectionProvider
3222
+ ? {
3223
+ source: {
3224
+ id: options.provider,
3225
+ kind: "workspace_connection",
3226
+ label: connectionProvider.label,
3227
+ },
3228
+ }
3229
+ : {}),
3212
3230
  });
3213
3231
  }
3214
3232
  async function resolveOptionalConnectionBoundOAuthBearerToken(options) {
@@ -3252,9 +3270,11 @@ async function resolveOptionalConnectionBoundOAuthBearerToken(options) {
3252
3270
  }
3253
3271
  const credential = await resolveOAuthBearerToken({
3254
3272
  auth: options.auth,
3273
+ runtime: options.runtime,
3255
3274
  ctx: options.ctx,
3256
3275
  accountId: connectionAccountId,
3257
3276
  ownerEmail: resolved.connection.ownerEmail,
3277
+ connectionId: requestedConnectionId,
3258
3278
  salesforceLoginUrl: options.auth.oauthProvider === "salesforce" &&
3259
3279
  typeof resolved.connection.config?.salesforceLoginUrl === "string"
3260
3280
  ? resolved.connection.config.salesforceLoginUrl
@@ -55,31 +55,31 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
55
55
  } | {
56
56
  error: string;
57
57
  errorCode?: undefined;
58
- status?: undefined;
59
58
  ok?: undefined;
59
+ status?: undefined;
60
60
  } | {
61
61
  error: string;
62
62
  errorCode: string;
63
- status?: undefined;
64
63
  ok?: undefined;
64
+ status?: undefined;
65
65
  } | {
66
66
  errorCode?: undefined;
67
67
  ok: boolean;
68
68
  status: string;
69
69
  error?: undefined;
70
70
  } | {
71
+ ok?: undefined;
71
72
  error: string;
72
73
  removed?: undefined;
73
- ok?: undefined;
74
74
  } | {
75
75
  ok: boolean;
76
76
  removed: boolean;
77
77
  error?: undefined;
78
78
  }>>;
79
79
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
80
+ ok?: undefined;
80
81
  error: string;
81
82
  note?: undefined;
82
- ok?: undefined;
83
83
  } | {
84
84
  ok: boolean;
85
85
  note?: undefined;
@@ -437,6 +437,10 @@ export async function mergeCoreSharingActions(registry) {
437
437
  "list-workspace-app-access",
438
438
  () => import("../org/actions/list-workspace-app-access.js"),
439
439
  ],
440
+ [
441
+ "list-workspace-icons",
442
+ () => import("../org/actions/list-workspace-icons.js"),
443
+ ],
440
444
  [
441
445
  "set-workspace-app-access",
442
446
  () => import("../org/actions/set-workspace-app-access.js"),
@@ -545,6 +549,7 @@ export async function mergeCoreSharingActions(registry) {
545
549
  () => import("../feature-flags/actions/set-feature-flag.js"),
546
550
  ],
547
551
  ["get-labs", () => import("../labs/actions/get-labs.js")],
552
+ ["get-lab-states", () => import("../labs/actions/get-lab-states.js")],
548
553
  ["set-lab", () => import("../labs/actions/set-lab.js")],
549
554
  [
550
555
  "get-chatgpt-subscription-status",
@@ -2126,6 +2126,20 @@ export function createAgentChatPlugin(options) {
2126
2126
  ...(connectionRequest.detail
2127
2127
  ? { detail: connectionRequest.detail }
2128
2128
  : {}),
2129
+ ...(connectionRequest.source?.kind === "workspace_connection" &&
2130
+ connectionRequest.source.id === connectionRequest.provider
2131
+ ? {
2132
+ source: {
2133
+ id: connectionRequest.provider,
2134
+ kind: "workspace_connection",
2135
+ ...(connectionRequest.source.label
2136
+ ? {
2137
+ label: connectionRequest.source.label.slice(0, 120),
2138
+ }
2139
+ : {}),
2140
+ },
2141
+ }
2142
+ : {}),
2129
2143
  };
2130
2144
  yield {
2131
2145
  role: "agent",
@@ -65,6 +65,7 @@ export declare function createAgentEngineApiKeyHandler(): import("h3").EventHand
65
65
  error: any;
66
66
  code: any;
67
67
  } | {
68
+ error?: undefined;
68
69
  errorCode?: undefined;
69
70
  code?: undefined;
70
71
  ok: boolean;
@@ -72,6 +73,5 @@ export declare function createAgentEngineApiKeyHandler(): import("h3").EventHand
72
73
  baseUrlKey?: string;
73
74
  scope: AgentEngineApiKeyScope;
74
75
  defaultModel?: import("./agent-engine-default-model-route.js").SavedKeyDefaultModelOutcome;
75
- error?: undefined;
76
76
  }>>;
77
77
  export {};
@@ -8,8 +8,8 @@ export declare const AGENT_ENGINE_API_KEY_ACTION_NAME = "agent-engine-api-key";
8
8
  * resolveEngine's credential detection.
9
9
  */
10
10
  export declare function createAgentEngineDisconnectHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
11
- error: string;
12
11
  ok?: undefined;
12
+ error: string;
13
13
  scope?: undefined;
14
14
  } | {
15
15
  ok: boolean;
@@ -3,7 +3,7 @@ export declare function createAgentEngineOllamaModelsHandler(): import("h3").Eve
3
3
  ok?: undefined;
4
4
  models?: undefined;
5
5
  } | {
6
- error?: undefined;
7
6
  ok: boolean;
8
7
  models: string[];
8
+ error?: undefined;
9
9
  }>>;
@@ -616,7 +616,7 @@ export declare function resolveOAuthCustodyBuilderKeyStatus(dependencies?: {
616
616
  lookupFailed: boolean;
617
617
  }>;
618
618
  }): Promise<OAuthCustodyBuilderKeyStatus>;
619
- export declare function createOAuthPopupWaitingHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, "<!doctype html><html><head><meta charset=\"utf-8\"><meta name=\"color-scheme\" content=\"light dark\"><title></title></head><body></body></html>" | {
619
+ export declare function createOAuthPopupWaitingHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, string | {
620
620
  error: string;
621
621
  }>;
622
622
  export declare function mountApplicationStateRoutes(nitroApp: any, routePrefix?: string, app?: H3AppShim, options?: {