@agent-native/core 0.201.1-nightly-20261005213104 → 0.201.1
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/dist/a2a/handlers.js +96 -44
- package/dist/a2a/organization-identity.d.ts +9 -0
- package/dist/a2a/organization-identity.js +34 -0
- package/dist/a2a/server.d.ts +13 -7
- package/dist/a2a/server.js +187 -88
- package/dist/a2a/task-store.d.ts +7 -2
- package/dist/a2a/task-store.js +23 -8
- package/dist/a2a-claims.js +12 -2
- package/dist/app-config/mcp.d.ts +4 -0
- package/dist/app-config/mcp.js +7 -0
- package/dist/app-config/schema.d.ts +3 -0
- package/dist/app-config/schema.js +2 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/client/route-chunk-recovery.js +75 -11
- package/dist/client/route-warmup.d.ts +2 -0
- package/dist/client/route-warmup.js +3 -0
- package/dist/client/vite-dev-recovery-script.js +85 -17
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.js +3 -1
- package/dist/feature-flags/a2a-action-route.js +3 -4
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/mcp/build-server.d.ts +4 -0
- package/dist/mcp/build-server.js +133 -39
- package/dist/mcp/server.js +21 -8
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +9 -9
- package/dist/onboarding/app-profile.js +2 -1
- package/dist/onboarding/workspace-services.js +3 -0
- package/dist/org/context.d.ts +13 -0
- package/dist/org/context.js +60 -0
- package/dist/org/index.d.ts +1 -1
- package/dist/org/membership.d.ts +6 -0
- package/dist/org/membership.js +23 -5
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +6 -6
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +11 -11
- package/dist/server/action-routes.js +12 -5
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
- package/dist/server/builder-browser.d.ts +4 -2
- package/dist/server/builder-browser.js +147 -9
- package/dist/server/core-routes-plugin.js +13 -6
- package/dist/server/entry-server.js +43 -2
- package/dist/server/sentry.js +9 -1
- package/dist/server/ssr-handler.d.ts +1 -1
- package/dist/server/ssr-handler.js +3 -7
- package/dist/shared/cache-control.d.ts +4 -1
- package/dist/shared/cache-control.js +11 -6
- package/dist/shared/route-chunk-recovery-bootstrap.d.ts +7 -0
- package/dist/shared/route-chunk-recovery-bootstrap.js +38 -0
- package/dist/triggers/actions/manage-automation.d.ts +5 -5
- package/package.json +6 -4
package/dist/mcp/build-server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "../authorization/check-action.js";
|
|
2
|
+
import { verifyA2AOrganizationIdentity } from "../a2a/organization-identity.js";
|
|
2
3
|
import { actionCallEmitsChange, actionChangeResource, } from "../action-call-classification.js";
|
|
3
4
|
import { MCP_APP_EXTENSION_ID, MCP_APP_MIME_TYPE, MCP_APP_RESOURCE_URI_META_KEY, } from "../action.js";
|
|
4
5
|
import { isActionContractError, isActionExposedToExternalAgents, } from "../action.js";
|
|
@@ -7,6 +8,7 @@ import { getAppConfig } from "../app-config/store.js";
|
|
|
7
8
|
import { isMcpActionResult } from "../mcp-client/app-result.js";
|
|
8
9
|
import { writeActionChangeMarker } from "../server/action-change-marker-write.js";
|
|
9
10
|
import { getConfiguredAppBasePath } from "../server/app-base-path.js";
|
|
11
|
+
import { readDeployCredentialEnv } from "../server/credential-provider.js";
|
|
10
12
|
import { buildDeepLink, isAgentNativeOpenUrl, isSameOriginUrl, toAbsoluteOpenUrl, toDesktopOpenUrl, toVsCodeOpenUrl, } from "../server/deep-link.js";
|
|
11
13
|
import { getRequestContext, getRequestOrgId, getRequestUserEmail, runWithRequestContext, } from "../server/request-context.js";
|
|
12
14
|
import { agentNativeMcpInstructions, agentNativeToolTitle, } from "../shared/agent-mcp-metadata.js";
|
|
@@ -1940,11 +1942,13 @@ export function getBearerToken(authHeader) {
|
|
|
1940
1942
|
const match = /^Bearer\s+(.+)$/i.exec(authHeader.trim());
|
|
1941
1943
|
return match?.[1]?.trim() || undefined;
|
|
1942
1944
|
}
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1945
|
+
export class McpIdentityVerificationUnavailableError extends Error {
|
|
1946
|
+
cause;
|
|
1947
|
+
constructor(cause) {
|
|
1948
|
+
super("MCP identity verification is temporarily unavailable");
|
|
1949
|
+
this.name = "McpIdentityVerificationUnavailableError";
|
|
1950
|
+
this.cause = cause;
|
|
1951
|
+
}
|
|
1948
1952
|
}
|
|
1949
1953
|
async function verifyA2AJwtForMcp(token, resourceUrl) {
|
|
1950
1954
|
const jose = await import("jose");
|
|
@@ -1955,37 +1959,96 @@ async function verifyA2AJwtForMcp(token, resourceUrl) {
|
|
|
1955
1959
|
catch {
|
|
1956
1960
|
return null;
|
|
1957
1961
|
}
|
|
1958
|
-
const candidateSecrets = [];
|
|
1959
|
-
addSecretCandidate(candidateSecrets, process.env.A2A_SECRET);
|
|
1960
1962
|
const orgDomain = typeof unverifiedPayload.org_domain === "string"
|
|
1961
|
-
? unverifiedPayload.org_domain
|
|
1963
|
+
? unverifiedPayload.org_domain.trim().toLowerCase()
|
|
1962
1964
|
: undefined;
|
|
1963
|
-
if (orgDomain) {
|
|
1964
|
-
try {
|
|
1965
|
-
const { getA2ASecretByDomain } = await import("../org/context.js");
|
|
1966
|
-
addSecretCandidate(candidateSecrets, await getA2ASecretByDomain(orgDomain));
|
|
1967
|
-
}
|
|
1968
|
-
catch {
|
|
1969
|
-
// DB not ready or org lookup unavailable — fall back to other candidates.
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
1965
|
const firstPartyMcp = unverifiedPayload.agent_native_first_party_mcp === true;
|
|
1973
1966
|
const audiences = firstPartyMcp ? mcpAudienceList(resourceUrl) : null;
|
|
1974
1967
|
if (firstPartyMcp && !audiences?.length)
|
|
1975
1968
|
return null;
|
|
1976
|
-
|
|
1977
|
-
const encodedSecret = new TextEncoder().encode(secret);
|
|
1969
|
+
const verifyWithSecret = async (secret) => {
|
|
1978
1970
|
for (const audience of audiences ?? [undefined]) {
|
|
1979
1971
|
try {
|
|
1980
|
-
const { payload } = await jose.jwtVerify(token,
|
|
1972
|
+
const { payload } = await jose.jwtVerify(token, new TextEncoder().encode(secret), audience ? { audience } : undefined);
|
|
1981
1973
|
return payload;
|
|
1982
1974
|
}
|
|
1983
1975
|
catch {
|
|
1984
|
-
//
|
|
1976
|
+
// coercion-ok: bad signature or audience rejects this candidate; credential lookup failures throw separately.
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
return null;
|
|
1980
|
+
};
|
|
1981
|
+
const globalSecret = readDeployCredentialEnv("A2A_SECRET")?.trim();
|
|
1982
|
+
if (globalSecret) {
|
|
1983
|
+
const payload = await verifyWithSecret(globalSecret);
|
|
1984
|
+
if (payload) {
|
|
1985
|
+
const tokenScope = typeof payload.scope === "string" ? payload.scope : undefined;
|
|
1986
|
+
const firstPartyMcp = payload.agent_native_first_party_mcp === true;
|
|
1987
|
+
const hasOrganizationClaim = Object.prototype.hasOwnProperty.call(payload, "org_id") &&
|
|
1988
|
+
payload.org_id !== null;
|
|
1989
|
+
const locallyIssuedConnectToken = tokenScope === MCP_CONNECT_SCOPE && !firstPartyMcp;
|
|
1990
|
+
const unclaimedFirstPartyToken = firstPartyMcp && !hasOrganizationClaim;
|
|
1991
|
+
if (locallyIssuedConnectToken || unclaimedFirstPartyToken) {
|
|
1992
|
+
return payload;
|
|
1993
|
+
}
|
|
1994
|
+
let verifiedOrganization;
|
|
1995
|
+
try {
|
|
1996
|
+
verifiedOrganization = await verifyA2AOrganizationIdentity(payload);
|
|
1985
1997
|
}
|
|
1998
|
+
catch (error) {
|
|
1999
|
+
throw new McpIdentityVerificationUnavailableError(error);
|
|
2000
|
+
}
|
|
2001
|
+
if (verifiedOrganization === null)
|
|
2002
|
+
return null;
|
|
2003
|
+
return verifiedOrganization
|
|
2004
|
+
? {
|
|
2005
|
+
...payload,
|
|
2006
|
+
org_id: verifiedOrganization.orgId,
|
|
2007
|
+
org_domain: verifiedOrganization.orgDomain,
|
|
2008
|
+
}
|
|
2009
|
+
: payload;
|
|
1986
2010
|
}
|
|
1987
2011
|
}
|
|
1988
|
-
|
|
2012
|
+
if (!orgDomain)
|
|
2013
|
+
return null;
|
|
2014
|
+
let organization;
|
|
2015
|
+
try {
|
|
2016
|
+
const { resolveA2AOrganizationCredentialsByDomain } = await import("../org/context.js");
|
|
2017
|
+
organization = await resolveA2AOrganizationCredentialsByDomain(orgDomain);
|
|
2018
|
+
}
|
|
2019
|
+
catch (error) {
|
|
2020
|
+
throw new McpIdentityVerificationUnavailableError(error);
|
|
2021
|
+
}
|
|
2022
|
+
if (!organization)
|
|
2023
|
+
return null;
|
|
2024
|
+
const payload = await verifyWithSecret(organization.secret);
|
|
2025
|
+
if (!payload)
|
|
2026
|
+
return null;
|
|
2027
|
+
const verifiedDomain = typeof payload.org_domain === "string"
|
|
2028
|
+
? payload.org_domain.trim().toLowerCase()
|
|
2029
|
+
: "";
|
|
2030
|
+
const email = typeof payload.sub === "string" ? payload.sub.trim() : "";
|
|
2031
|
+
const claimedOrgId = payload.org_id;
|
|
2032
|
+
if (!email ||
|
|
2033
|
+
verifiedDomain !== organization.orgDomain ||
|
|
2034
|
+
(typeof claimedOrgId !== "undefined" &&
|
|
2035
|
+
(typeof claimedOrgId !== "string" ||
|
|
2036
|
+
claimedOrgId.trim() !== organization.orgId))) {
|
|
2037
|
+
return null;
|
|
2038
|
+
}
|
|
2039
|
+
try {
|
|
2040
|
+
const { isOrgMemberForA2A } = await import("../org/membership.js");
|
|
2041
|
+
if (!(await isOrgMemberForA2A(organization.orgId, email)))
|
|
2042
|
+
return null;
|
|
2043
|
+
}
|
|
2044
|
+
catch (error) {
|
|
2045
|
+
throw new McpIdentityVerificationUnavailableError(error);
|
|
2046
|
+
}
|
|
2047
|
+
return {
|
|
2048
|
+
...payload,
|
|
2049
|
+
org_id: organization.orgId,
|
|
2050
|
+
org_domain: organization.orgDomain,
|
|
2051
|
+
};
|
|
1989
2052
|
}
|
|
1990
2053
|
function mcpAudienceList(resource) {
|
|
1991
2054
|
const raw = Array.isArray(resource) ? resource : resource ? [resource] : [];
|
|
@@ -2058,13 +2121,24 @@ function orgIdFromConnectTokenResolution(resolution) {
|
|
|
2058
2121
|
if (resolution.status === "claimed" || resolution.status === "found") {
|
|
2059
2122
|
return resolution.orgId;
|
|
2060
2123
|
}
|
|
2061
|
-
// A
|
|
2062
|
-
// knows. Its `org_domain` claim must not grant that domain's org
|
|
2063
|
-
// runs Personal.
|
|
2124
|
+
// A first-party cross-app token with no row here was not issued for any org
|
|
2125
|
+
// this app knows. Its `org_domain` claim must not grant that domain's org.
|
|
2064
2126
|
if (resolution.status === "missing")
|
|
2065
2127
|
return null;
|
|
2066
2128
|
return undefined;
|
|
2067
2129
|
}
|
|
2130
|
+
function matchesStoredConnectTokenIdentity(resolution, input) {
|
|
2131
|
+
const stored = resolution.status === "found"
|
|
2132
|
+
? resolution
|
|
2133
|
+
: resolution.status === "claimed"
|
|
2134
|
+
? resolution.storedConnectToken
|
|
2135
|
+
: undefined;
|
|
2136
|
+
if (!stored || !input.ownerEmail?.trim())
|
|
2137
|
+
return false;
|
|
2138
|
+
return (stored.ownerEmail.trim().toLowerCase() ===
|
|
2139
|
+
input.ownerEmail.trim().toLowerCase() &&
|
|
2140
|
+
(input.orgId === undefined || stored.orgId === input.orgId));
|
|
2141
|
+
}
|
|
2068
2142
|
/**
|
|
2069
2143
|
* Credentials this app issues (MCP OAuth access tokens and connect tokens)
|
|
2070
2144
|
* carry the organization chosen when they were issued: the signed `org_id`
|
|
@@ -2076,9 +2150,10 @@ function orgIdFromConnectTokenResolution(resolution) {
|
|
|
2076
2150
|
* They also carry the subject's address, which an email change retires; a
|
|
2077
2151
|
* credential signed for it before the change is refused, Personal or not.
|
|
2078
2152
|
*
|
|
2079
|
-
*
|
|
2080
|
-
*
|
|
2081
|
-
*
|
|
2153
|
+
* Shared-secret A2A org claims must resolve against local metadata before they
|
|
2154
|
+
* become request scope. A sibling app's user roster is not this app's roster;
|
|
2155
|
+
* locally issued connect credentials instead use their stored JTI owner and
|
|
2156
|
+
* organization.
|
|
2082
2157
|
*/
|
|
2083
2158
|
async function admitIssuedCredential(result, requestOrigin, orgResolution, issuedAt) {
|
|
2084
2159
|
const { checkCredentialEmailRetirement, checkCredentialOrgMembership } = await import("./credential-membership.js");
|
|
@@ -2139,7 +2214,7 @@ async function admitIssuedCredential(result, requestOrigin, orgResolution, issue
|
|
|
2139
2214
|
*/
|
|
2140
2215
|
export async function verifyAuth(authHeader, ownerEmailHeader, options = {}) {
|
|
2141
2216
|
const accessTokens = getAccessTokens();
|
|
2142
|
-
const hasA2ASecret = !!
|
|
2217
|
+
const hasA2ASecret = !!readDeployCredentialEnv("A2A_SECRET")?.trim();
|
|
2143
2218
|
const token = getBearerToken(authHeader);
|
|
2144
2219
|
if (token) {
|
|
2145
2220
|
const oauthIdentity = await verifyMcpOAuthAccessToken(token, options.resourceUrl);
|
|
@@ -2155,6 +2230,13 @@ export async function verifyAuth(authHeader, ownerEmailHeader, options = {}) {
|
|
|
2155
2230
|
if (orgResolution.status === "unavailable") {
|
|
2156
2231
|
return { authed: false, unavailable: true };
|
|
2157
2232
|
}
|
|
2233
|
+
if (oauthIdentity.clientId === MCP_CONNECT_OAUTH_CLIENT_ID &&
|
|
2234
|
+
!matchesStoredConnectTokenIdentity(orgResolution, {
|
|
2235
|
+
ownerEmail: oauthIdentity.userEmail,
|
|
2236
|
+
orgId: oauthIdentity.orgId,
|
|
2237
|
+
})) {
|
|
2238
|
+
return { authed: false };
|
|
2239
|
+
}
|
|
2158
2240
|
const orgId = orgIdFromConnectTokenResolution(orgResolution);
|
|
2159
2241
|
const admitted = await admitIssuedCredential({
|
|
2160
2242
|
authed: true,
|
|
@@ -2187,7 +2269,16 @@ export async function verifyAuth(authHeader, ownerEmailHeader, options = {}) {
|
|
|
2187
2269
|
}
|
|
2188
2270
|
if (!token)
|
|
2189
2271
|
return { authed: false };
|
|
2190
|
-
|
|
2272
|
+
let payload;
|
|
2273
|
+
try {
|
|
2274
|
+
payload = await verifyA2AJwtForMcp(token, options.resourceUrl);
|
|
2275
|
+
}
|
|
2276
|
+
catch (error) {
|
|
2277
|
+
if (error instanceof McpIdentityVerificationUnavailableError) {
|
|
2278
|
+
return { authed: false, unavailable: true };
|
|
2279
|
+
}
|
|
2280
|
+
throw error;
|
|
2281
|
+
}
|
|
2191
2282
|
if (payload) {
|
|
2192
2283
|
const tokenScope = typeof payload.scope === "string" ? payload.scope : undefined;
|
|
2193
2284
|
if (tokenScope && tokenScope !== MCP_CONNECT_SCOPE) {
|
|
@@ -2213,6 +2304,14 @@ export async function verifyAuth(authHeader, ownerEmailHeader, options = {}) {
|
|
|
2213
2304
|
if (orgResolution.status === "unavailable") {
|
|
2214
2305
|
return { authed: false, unavailable: true };
|
|
2215
2306
|
}
|
|
2307
|
+
if (tokenScope === MCP_CONNECT_SCOPE && !firstPartyMcp) {
|
|
2308
|
+
if (!matchesStoredConnectTokenIdentity(orgResolution, {
|
|
2309
|
+
ownerEmail: typeof payload.sub === "string" ? payload.sub : undefined,
|
|
2310
|
+
orgId: orgIdClaim.orgId,
|
|
2311
|
+
})) {
|
|
2312
|
+
return { authed: false };
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2216
2315
|
const orgId = orgIdFromConnectTokenResolution(orgResolution);
|
|
2217
2316
|
const verified = {
|
|
2218
2317
|
authed: true,
|
|
@@ -2237,15 +2336,10 @@ export async function verifyAuth(authHeader, ownerEmailHeader, options = {}) {
|
|
|
2237
2336
|
}
|
|
2238
2337
|
return admitted;
|
|
2239
2338
|
}
|
|
2240
|
-
if (accessTokens.length === 0
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
}
|
|
2244
|
-
return {
|
|
2245
|
-
authed: true,
|
|
2246
|
-
identity: deriveStaticTokenIdentity(ownerEmailHeader),
|
|
2247
|
-
fullSurface: !!(ownerEmailHeader && ownerEmailHeader.trim()),
|
|
2248
|
-
};
|
|
2339
|
+
if (accessTokens.length === 0) {
|
|
2340
|
+
// A supplied bearer that failed JWT verification must not fall through to
|
|
2341
|
+
// dev-open auth or reuse a forwarded owner-email hint.
|
|
2342
|
+
return { authed: false };
|
|
2249
2343
|
}
|
|
2250
2344
|
// Try ACCESS_TOKEN / ACCESS_TOKENS exact match. Static tokens carry no
|
|
2251
2345
|
// per-caller claims, so derive identity from the forwarded owner-email
|
package/dist/mcp/server.js
CHANGED
|
@@ -7,7 +7,7 @@ import { getH3App } from "../server/framework-request-handler.js";
|
|
|
7
7
|
import { getOrigin } from "../server/google-oauth.js";
|
|
8
8
|
import { readBody } from "../server/h3-helpers.js";
|
|
9
9
|
import { trackMcpInitialize } from "./analytics.js";
|
|
10
|
-
import { createMCPServerForRequest, verifyAuth, getAccessTokens, resolveOrgIdFromDomain, buildLinkArtifacts, McpDirectoryProfileValidationError, validateMcpDirectoryProfile, validateMcpDirectoryWidgetDomain, selectMcpActionSurface, } from "./build-server.js";
|
|
10
|
+
import { createMCPServerForRequest, verifyAuth, McpIdentityVerificationUnavailableError, getAccessTokens, resolveOrgIdFromDomain, buildLinkArtifacts, McpDirectoryProfileValidationError, validateMcpDirectoryProfile, validateMcpDirectoryWidgetDomain, selectMcpActionSurface, } from "./build-server.js";
|
|
11
11
|
import { buildMcpOAuthChallenge, getMcpOAuthAudiences, getMcpOAuthIssuer, getMcpOAuthProtectedResourceMetadataUrl, getMcpOAuthResource, } from "./oauth-route.js";
|
|
12
12
|
import { MCP_DIRECTORY_ROUTE_PREFIX, MCP_PUBLIC_ROUTE_PREFIX, MCP_ROUTE_PREFIXES, joinMcpRoute, } from "./route-paths.js";
|
|
13
13
|
export { createMCPServerForRequest, verifyAuth, getAccessTokens, resolveOrgIdFromDomain, buildLinkArtifacts, };
|
|
@@ -228,13 +228,26 @@ async function handleMcpRequestInternal(event, config, routePath = MCP_PUBLIC_RO
|
|
|
228
228
|
widgetDomain: requestMeta.origin,
|
|
229
229
|
}
|
|
230
230
|
: config;
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
231
|
+
let authResult;
|
|
232
|
+
try {
|
|
233
|
+
authResult = await verifyAuth(authHeader, ownerEmailHeader, {
|
|
234
|
+
allowDevOpen: isLoopbackRequest(event) &&
|
|
235
|
+
isLoopbackOrigin(requestMeta.origin) &&
|
|
236
|
+
(hasLocalOwnerHint || getAppConfig().mcp.allowDevOpen),
|
|
237
|
+
resourceUrl: getMcpOAuthAudiences(event, routePath),
|
|
238
|
+
requestOrigin: getOrigin(event),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
if (!(error instanceof McpIdentityVerificationUnavailableError))
|
|
243
|
+
throw error;
|
|
244
|
+
setResponseStatus(event, 503);
|
|
245
|
+
setResponseHeader(event, "Retry-After", "5");
|
|
246
|
+
return {
|
|
247
|
+
error: "Service Unavailable",
|
|
248
|
+
message: CREDENTIAL_MEMBERSHIP_UNAVAILABLE_MESSAGE,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
238
251
|
if (!authResult.authed && authResult.unavailable) {
|
|
239
252
|
// The token is valid but its org membership could not be checked. No auth
|
|
240
253
|
// challenge: re-authenticating would not help, and the client must keep
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
2
2
|
count: number;
|
|
3
3
|
updated?: undefined;
|
|
4
|
-
error?: undefined;
|
|
5
4
|
ok?: undefined;
|
|
5
|
+
error?: undefined;
|
|
6
6
|
} | {
|
|
7
7
|
count?: undefined;
|
|
8
8
|
updated: number;
|
|
9
|
-
error?: undefined;
|
|
10
9
|
ok?: undefined;
|
|
10
|
+
error?: undefined;
|
|
11
11
|
} | {
|
|
12
12
|
count?: undefined;
|
|
13
13
|
updated?: undefined;
|
|
@@ -16,6 +16,6 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
|
|
|
16
16
|
} | {
|
|
17
17
|
count?: undefined;
|
|
18
18
|
updated?: undefined;
|
|
19
|
-
error?: undefined;
|
|
20
19
|
ok: boolean;
|
|
20
|
+
error?: undefined;
|
|
21
21
|
}>>;
|
|
@@ -27,38 +27,38 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
27
27
|
thumbsUpRate: number;
|
|
28
28
|
avgEvalScore: number;
|
|
29
29
|
} | {
|
|
30
|
-
id?: undefined;
|
|
31
|
-
ok?: undefined;
|
|
32
30
|
error: string;
|
|
33
31
|
message: string;
|
|
34
32
|
summary?: undefined;
|
|
35
33
|
spans?: undefined;
|
|
36
|
-
} | {
|
|
37
34
|
id?: undefined;
|
|
38
|
-
error?: undefined;
|
|
39
35
|
ok?: undefined;
|
|
36
|
+
} | {
|
|
40
37
|
message?: undefined;
|
|
41
38
|
summary: import("./types.js").TraceSummary;
|
|
42
39
|
spans: import("./types.js").TraceSpan[];
|
|
43
|
-
|
|
40
|
+
id?: undefined;
|
|
44
41
|
error?: undefined;
|
|
45
42
|
ok?: undefined;
|
|
43
|
+
} | {
|
|
46
44
|
message?: undefined;
|
|
47
45
|
summary?: undefined;
|
|
48
46
|
spans?: undefined;
|
|
49
47
|
id: string;
|
|
50
|
-
|
|
51
|
-
id?: undefined;
|
|
48
|
+
error?: undefined;
|
|
52
49
|
ok?: undefined;
|
|
50
|
+
} | {
|
|
53
51
|
message?: undefined;
|
|
54
52
|
summary?: undefined;
|
|
55
53
|
spans?: undefined;
|
|
54
|
+
id?: undefined;
|
|
56
55
|
error: any;
|
|
56
|
+
ok?: undefined;
|
|
57
57
|
} | {
|
|
58
|
-
id?: undefined;
|
|
59
|
-
error?: undefined;
|
|
60
58
|
message?: undefined;
|
|
61
59
|
summary?: undefined;
|
|
62
60
|
spans?: undefined;
|
|
61
|
+
id?: undefined;
|
|
62
|
+
error?: undefined;
|
|
63
63
|
ok: boolean;
|
|
64
64
|
}>>;
|
|
@@ -7,7 +7,8 @@ const SYSTEM_ONE_CAPABILITY = {
|
|
|
7
7
|
suggested: true,
|
|
8
8
|
builderIncluded: true,
|
|
9
9
|
keySummary: "Jev decision model key",
|
|
10
|
-
|
|
10
|
+
whyKey: "agentChat.onboarding.capability.systemOne.why",
|
|
11
|
+
why: "Jev is an optional decision model that helps choose relevant tools and skills before the agent's first model request.",
|
|
11
12
|
};
|
|
12
13
|
const PROFILES = {
|
|
13
14
|
analytics: {
|
|
@@ -15,6 +15,7 @@ export const LLM_CAPABILITY = {
|
|
|
15
15
|
keySummary: "Connect your own AI model",
|
|
16
16
|
labelKey: "agentChat.settingsInfra.aiModel",
|
|
17
17
|
keySummaryKey: "agentChat.onboarding.capability.llm.keySummary",
|
|
18
|
+
whyKey: "agentChat.onboarding.capability.llm.why",
|
|
18
19
|
why: "The agent uses a language model to understand requests and produce answers.",
|
|
19
20
|
};
|
|
20
21
|
export const FILE_UPLOAD_STORAGE_CAPABILITY = {
|
|
@@ -26,6 +27,7 @@ export const FILE_UPLOAD_STORAGE_CAPABILITY = {
|
|
|
26
27
|
keySummary: "File uploads and storage",
|
|
27
28
|
labelKey: "agentChat.settingsShell.search.fileUploads",
|
|
28
29
|
keySummaryKey: "agentChat.onboarding.capability.fileStorage.keySummary",
|
|
30
|
+
whyKey: "agentChat.onboarding.capability.fileStorage.why",
|
|
29
31
|
why: "Uploaded images and files need durable object storage so the agent can reuse them throughout a thread.",
|
|
30
32
|
};
|
|
31
33
|
export const VOICE_INPUT_CAPABILITY = {
|
|
@@ -70,6 +72,7 @@ export const DESIGN_SYSTEM_INTELLIGENCE_CAPABILITY = {
|
|
|
70
72
|
builderIncluded: true,
|
|
71
73
|
keySummary: "Builder Design System Intelligence",
|
|
72
74
|
labelKey: "agentChat.settingsInfra.designSystem",
|
|
75
|
+
whyKey: "agentChat.settingsInfra.whyDesignSystem",
|
|
73
76
|
why: "Uses your brand and design-system guidance to keep generated work on brand.",
|
|
74
77
|
};
|
|
75
78
|
export const BACKGROUND_AGENTS_CAPABILITY = {
|
package/dist/org/context.d.ts
CHANGED
|
@@ -47,4 +47,17 @@ export declare function resolveOrgByDomain(domain: string): Promise<{
|
|
|
47
47
|
orgId: string;
|
|
48
48
|
orgName: string;
|
|
49
49
|
} | null>;
|
|
50
|
+
export declare function resolveA2AOrganizationMetadataByDomain(domain: string): Promise<{
|
|
51
|
+
orgId: string;
|
|
52
|
+
orgDomain: string | null;
|
|
53
|
+
} | null>;
|
|
54
|
+
export declare function resolveA2AOrganizationMetadataById(orgId: string): Promise<{
|
|
55
|
+
orgId: string;
|
|
56
|
+
orgDomain: string | null;
|
|
57
|
+
} | null>;
|
|
58
|
+
export declare function resolveA2AOrganizationCredentialsByDomain(domain: string): Promise<{
|
|
59
|
+
orgId: string;
|
|
60
|
+
orgDomain: string;
|
|
61
|
+
secret: string;
|
|
62
|
+
} | null>;
|
|
50
63
|
export declare function isSoleOrgDomain(domain: string): Promise<boolean>;
|
package/dist/org/context.js
CHANGED
|
@@ -743,6 +743,66 @@ export async function resolveOrgByDomain(domain) {
|
|
|
743
743
|
return null;
|
|
744
744
|
}
|
|
745
745
|
}
|
|
746
|
+
export async function resolveA2AOrganizationMetadataByDomain(domain) {
|
|
747
|
+
const normalizedDomain = domain.trim().toLowerCase();
|
|
748
|
+
if (!normalizedDomain)
|
|
749
|
+
return null;
|
|
750
|
+
const { rows } = await getDbExec().execute({
|
|
751
|
+
sql: `SELECT id, allowed_domain
|
|
752
|
+
FROM organizations WHERE LOWER(allowed_domain) = ? LIMIT 1`,
|
|
753
|
+
args: [normalizedDomain],
|
|
754
|
+
});
|
|
755
|
+
const row = rows[0];
|
|
756
|
+
if (!row)
|
|
757
|
+
return null;
|
|
758
|
+
const orgId = String(row.id ?? "").trim();
|
|
759
|
+
const orgDomain = String(row.allowed_domain ?? "")
|
|
760
|
+
.trim()
|
|
761
|
+
.toLowerCase();
|
|
762
|
+
if (!orgId || !orgDomain || orgDomain !== normalizedDomain)
|
|
763
|
+
return null;
|
|
764
|
+
return { orgId, orgDomain };
|
|
765
|
+
}
|
|
766
|
+
export async function resolveA2AOrganizationMetadataById(orgId) {
|
|
767
|
+
const normalizedOrgId = orgId.trim();
|
|
768
|
+
if (!normalizedOrgId)
|
|
769
|
+
return null;
|
|
770
|
+
const { rows } = await getDbExec().execute({
|
|
771
|
+
sql: `SELECT id, allowed_domain FROM organizations WHERE id = ? LIMIT 1`,
|
|
772
|
+
args: [normalizedOrgId],
|
|
773
|
+
});
|
|
774
|
+
const row = rows[0];
|
|
775
|
+
if (!row)
|
|
776
|
+
return null;
|
|
777
|
+
const resolvedOrgId = String(row.id ?? "").trim();
|
|
778
|
+
if (!resolvedOrgId || resolvedOrgId !== normalizedOrgId)
|
|
779
|
+
return null;
|
|
780
|
+
const rawDomain = String(row.allowed_domain ?? "")
|
|
781
|
+
.trim()
|
|
782
|
+
.toLowerCase();
|
|
783
|
+
return { orgId: resolvedOrgId, orgDomain: rawDomain || null };
|
|
784
|
+
}
|
|
785
|
+
export async function resolveA2AOrganizationCredentialsByDomain(domain) {
|
|
786
|
+
const normalizedDomain = domain.trim().toLowerCase();
|
|
787
|
+
if (!normalizedDomain)
|
|
788
|
+
return null;
|
|
789
|
+
const { rows } = await getDbExec().execute({
|
|
790
|
+
sql: `SELECT id, allowed_domain, a2a_secret
|
|
791
|
+
FROM organizations WHERE LOWER(allowed_domain) = ? LIMIT 1`,
|
|
792
|
+
args: [normalizedDomain],
|
|
793
|
+
});
|
|
794
|
+
const row = rows[0];
|
|
795
|
+
if (!row)
|
|
796
|
+
return null;
|
|
797
|
+
const orgId = String(row.id ?? "").trim();
|
|
798
|
+
const orgDomain = String(row.allowed_domain ?? "")
|
|
799
|
+
.trim()
|
|
800
|
+
.toLowerCase();
|
|
801
|
+
const secret = String(row.a2a_secret ?? "").trim();
|
|
802
|
+
if (!orgId || orgDomain !== normalizedDomain || !secret)
|
|
803
|
+
return null;
|
|
804
|
+
return { orgId, orgDomain, secret };
|
|
805
|
+
}
|
|
746
806
|
export async function isSoleOrgDomain(domain) {
|
|
747
807
|
try {
|
|
748
808
|
const exec = getDbExec();
|
package/dist/org/index.d.ts
CHANGED
|
@@ -179,8 +179,8 @@ export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import(
|
|
|
179
179
|
export declare const createOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
180
180
|
name?: undefined;
|
|
181
181
|
success: boolean;
|
|
182
|
-
role?: undefined;
|
|
183
182
|
id?: undefined;
|
|
183
|
+
role?: undefined;
|
|
184
184
|
} | {
|
|
185
185
|
success?: undefined;
|
|
186
186
|
id: string;
|
package/dist/org/membership.d.ts
CHANGED
|
@@ -2,3 +2,9 @@ export declare function isMissingOrganizationTableError(error: unknown): boolean
|
|
|
2
2
|
export declare function isOrgMember(orgId: string, email: string, options?: {
|
|
3
3
|
requireOrganizationMetadata?: boolean;
|
|
4
4
|
}): Promise<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Checks membership for an A2A identity authenticated by an organization
|
|
7
|
+
* secret. Unlike legacy callers, this requires readable organization metadata
|
|
8
|
+
* as well as the membership row before the token subject can become an owner.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isOrgMemberForA2A(orgId: string, email: string): Promise<boolean>;
|
package/dist/org/membership.js
CHANGED
|
@@ -17,7 +17,7 @@ export function isMissingOrganizationTableError(error) {
|
|
|
17
17
|
}
|
|
18
18
|
return false;
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
async function isOrgMemberWithPolicy(orgId, email, options) {
|
|
21
21
|
const normalized = email.trim().toLowerCase();
|
|
22
22
|
if (!orgId || !normalized)
|
|
23
23
|
return false;
|
|
@@ -41,13 +41,14 @@ export async function isOrgMember(orgId, email, options = {}) {
|
|
|
41
41
|
})).rows;
|
|
42
42
|
}
|
|
43
43
|
catch (error) {
|
|
44
|
-
if (
|
|
45
|
-
!isMissingOrganizationTableError(error))
|
|
44
|
+
if (!isMissingOrganizationTableError(error))
|
|
46
45
|
throw error;
|
|
47
|
-
|
|
46
|
+
if (options.allowMissingOrganizationTable)
|
|
47
|
+
return true;
|
|
48
|
+
throw error;
|
|
48
49
|
}
|
|
49
50
|
const organization = organizationRows[0];
|
|
50
|
-
if (!organization && options.
|
|
51
|
+
if (!organization && options.requireOrganizationRecord)
|
|
51
52
|
return false;
|
|
52
53
|
const linked = String(organization?.identity_authority ?? "").trim() ||
|
|
53
54
|
String(organization?.identity_id ?? "").trim();
|
|
@@ -67,3 +68,20 @@ export async function isOrgMember(orgId, email, options = {}) {
|
|
|
67
68
|
});
|
|
68
69
|
return validation.active;
|
|
69
70
|
}
|
|
71
|
+
export function isOrgMember(orgId, email, options = {}) {
|
|
72
|
+
return isOrgMemberWithPolicy(orgId, email, {
|
|
73
|
+
allowMissingOrganizationTable: !options.requireOrganizationMetadata,
|
|
74
|
+
requireOrganizationRecord: !!options.requireOrganizationMetadata,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Checks membership for an A2A identity authenticated by an organization
|
|
79
|
+
* secret. Unlike legacy callers, this requires readable organization metadata
|
|
80
|
+
* as well as the membership row before the token subject can become an owner.
|
|
81
|
+
*/
|
|
82
|
+
export function isOrgMemberForA2A(orgId, email) {
|
|
83
|
+
return isOrgMemberWithPolicy(orgId, email, {
|
|
84
|
+
allowMissingOrganizationTable: false,
|
|
85
|
+
requireOrganizationRecord: true,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -75,9 +75,10 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
75
75
|
user: "user";
|
|
76
76
|
}>>;
|
|
77
77
|
}, z.core.$strip>>, {
|
|
78
|
+
message?: undefined;
|
|
78
79
|
id?: undefined;
|
|
79
|
-
deleted?: undefined;
|
|
80
80
|
provider?: undefined;
|
|
81
|
+
deleted?: undefined;
|
|
81
82
|
providers: {
|
|
82
83
|
id: string;
|
|
83
84
|
label: string;
|
|
@@ -91,8 +92,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
91
92
|
found?: undefined;
|
|
92
93
|
registered?: undefined;
|
|
93
94
|
label?: undefined;
|
|
94
|
-
message?: undefined;
|
|
95
95
|
} | {
|
|
96
|
+
message?: undefined;
|
|
96
97
|
id?: undefined;
|
|
97
98
|
deleted?: undefined;
|
|
98
99
|
providers?: undefined;
|
|
@@ -101,18 +102,18 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
101
102
|
provider: import("../custom-registry.js").CustomProviderConfig;
|
|
102
103
|
registered?: undefined;
|
|
103
104
|
label?: undefined;
|
|
104
|
-
message?: undefined;
|
|
105
105
|
} | {
|
|
106
|
-
|
|
106
|
+
message?: undefined;
|
|
107
107
|
provider?: undefined;
|
|
108
|
+
deleted?: undefined;
|
|
108
109
|
providers?: undefined;
|
|
109
110
|
count?: undefined;
|
|
110
111
|
found: boolean;
|
|
111
112
|
id: string;
|
|
112
113
|
registered?: undefined;
|
|
113
114
|
label?: undefined;
|
|
114
|
-
message?: undefined;
|
|
115
115
|
} | {
|
|
116
|
+
message?: undefined;
|
|
116
117
|
provider?: undefined;
|
|
117
118
|
providers?: undefined;
|
|
118
119
|
count?: undefined;
|
|
@@ -121,10 +122,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
121
122
|
id: string;
|
|
122
123
|
registered?: undefined;
|
|
123
124
|
label?: undefined;
|
|
124
|
-
message?: undefined;
|
|
125
125
|
} | {
|
|
126
|
-
deleted?: undefined;
|
|
127
126
|
provider?: undefined;
|
|
127
|
+
deleted?: undefined;
|
|
128
128
|
providers?: undefined;
|
|
129
129
|
count?: undefined;
|
|
130
130
|
found?: undefined;
|