@agent-native/core 0.206.0-nightly-20261009153146 → 0.206.0
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/action.d.ts +7 -1
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat/index.js +1 -1
- package/dist/client/embed-auth.d.ts +2 -0
- package/dist/client/embed-auth.js +160 -12
- package/dist/client/host/index.d.ts +1 -1
- package/dist/client/host/index.js +1 -1
- package/dist/client/mcp-app-host.d.ts +1 -0
- package/dist/client/mcp-app-host.js +4 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/mcp/build-server.d.ts +15 -0
- package/dist/mcp/build-server.js +307 -91
- package/dist/mcp/connect-route.js +1 -0
- package/dist/mcp/embed-app.js +291 -31
- package/dist/mcp/oauth-route.js +3 -0
- package/dist/mcp/oauth-store.d.ts +2 -1
- package/dist/mcp/oauth-store.js +5 -6
- package/dist/mcp/oauth-token.d.ts +5 -0
- package/dist/mcp/oauth-token.js +17 -0
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.js +2 -2
- package/dist/observability/routes.d.ts +5 -5
- package/dist/org/handlers.d.ts +1 -1
- package/dist/org/workspace-app-access-request.d.ts +8 -0
- package/dist/org/workspace-app-access-request.js +20 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +11 -11
- package/dist/server/action-routes.d.ts +2 -0
- package/dist/server/action-routes.js +187 -31
- package/dist/server/agent-chat/mcp-options.d.ts +3 -1
- package/dist/server/agent-chat-plugin.js +26 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
- package/dist/server/auth.js +11 -20
- package/dist/server/embed-route.js +5 -3
- package/dist/server/embed-session.d.ts +30 -1
- package/dist/server/embed-session.js +376 -30
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/request-context.js +25 -1
- package/dist/shared/embed-auth.d.ts +74 -0
- package/dist/shared/embed-auth.js +379 -10
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/triggers/actions/manage-automation.d.ts +3 -3
- package/package.json +4 -4
|
@@ -6,14 +6,28 @@ export declare const MCP_APP_CHAT_BRIDGE_QUERY_PARAM = "__an_mcp_chat_bridge";
|
|
|
6
6
|
export declare const MCP_DIRECTORY_WIDGET_QUERY_PARAM = "__an_mcp_directory_widget";
|
|
7
7
|
export declare const EMBED_SESSION_COOKIE = "an_embed_session";
|
|
8
8
|
export declare const EMBED_TARGET_HEADER = "x-agent-native-embed-target";
|
|
9
|
+
export declare const MCP_DIRECTORY_WIDGET_SESSION_EXPIRED_HEADER = "x-agent-native-widget-session-expired";
|
|
9
10
|
export declare const MCP_DIRECTORY_WIDGET_READ_CAPABILITY_PREFIX = "capability:mcp-directory-widget-read:";
|
|
11
|
+
export declare const MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_PREFIX = "capability:mcp-directory-widget-write:";
|
|
10
12
|
export declare const MCP_DIRECTORY_WIDGET_READ_CAPABILITY_MAX_LENGTH = 2048;
|
|
13
|
+
export declare const MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_MAX_LENGTH = 4096;
|
|
14
|
+
export declare const MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_MAX_AGE_MS: number;
|
|
11
15
|
export interface McpDirectoryWidgetReadCapabilityInput {
|
|
12
16
|
appId: string;
|
|
13
17
|
resourceUri: string;
|
|
14
18
|
resourceIds: Record<string, string>;
|
|
15
19
|
actionArguments: Record<string, Record<string, McpDirectoryWidgetReadArgument>>;
|
|
16
20
|
}
|
|
21
|
+
export interface McpDirectoryWidgetWriteCapabilityInput {
|
|
22
|
+
appId: string;
|
|
23
|
+
resourceUri: string;
|
|
24
|
+
resourceIds: Record<string, string>;
|
|
25
|
+
userEmail: string;
|
|
26
|
+
orgId?: string;
|
|
27
|
+
expiresAtMs: number;
|
|
28
|
+
readActionArguments: Record<string, Record<string, McpDirectoryWidgetReadArgument>>;
|
|
29
|
+
writeActionArguments: Record<string, Record<string, McpDirectoryWidgetReadArgument>>;
|
|
30
|
+
}
|
|
17
31
|
export type McpDirectoryWidgetReadArgument = string | {
|
|
18
32
|
type: "integerRange";
|
|
19
33
|
min: number;
|
|
@@ -22,21 +36,81 @@ export type McpDirectoryWidgetReadArgument = string | {
|
|
|
22
36
|
/** Dynamic input validated against the server action schema after resource binding. */
|
|
23
37
|
| {
|
|
24
38
|
type: "actionSchema";
|
|
39
|
+
}
|
|
40
|
+
/** Dynamic input whose artifact relationship is checked by the action. */
|
|
41
|
+
| {
|
|
42
|
+
type: "actionSchemaResourceBound";
|
|
43
|
+
resourceKey: string;
|
|
25
44
|
};
|
|
26
45
|
export declare function createMcpDirectoryWidgetReadCapability(input: McpDirectoryWidgetReadCapabilityInput): string | undefined;
|
|
46
|
+
export declare function createMcpDirectoryWidgetWriteCapability(input: McpDirectoryWidgetWriteCapabilityInput): string | undefined;
|
|
47
|
+
export declare function renewMcpDirectoryWidgetCapabilityScope(scope: string | undefined, input: {
|
|
48
|
+
appId: string;
|
|
49
|
+
resourceUri: string;
|
|
50
|
+
userEmail: string;
|
|
51
|
+
orgId?: string | null;
|
|
52
|
+
expiresAtMs: number;
|
|
53
|
+
readAllowed: boolean;
|
|
54
|
+
writeAllowed: boolean;
|
|
55
|
+
}): string | undefined;
|
|
56
|
+
export declare function canRenewMcpDirectoryWidgetCapabilityScope(previousScope: string, renewedScope: string, identity: {
|
|
57
|
+
userEmail: string;
|
|
58
|
+
orgId?: string | null;
|
|
59
|
+
}): boolean;
|
|
27
60
|
export declare function isMcpDirectoryWidgetReadCapabilityScope(scope: string | undefined): boolean;
|
|
61
|
+
export declare function isMcpDirectoryWidgetWriteCapabilityScope(scope: string | undefined): boolean;
|
|
62
|
+
export declare function isMcpDirectoryWidgetCapabilityScope(scope: string | undefined): boolean;
|
|
63
|
+
export declare function matchesMcpDirectoryWidgetWriteCapability(scope: string | undefined, input: {
|
|
64
|
+
appId: string;
|
|
65
|
+
resourceUri: string;
|
|
66
|
+
userEmail: string;
|
|
67
|
+
orgId?: string | null;
|
|
68
|
+
}): boolean;
|
|
69
|
+
export declare function isExpiredMcpDirectoryWidgetWriteCapability(scope: string | undefined, input: {
|
|
70
|
+
appId: string;
|
|
71
|
+
resourceUri: string;
|
|
72
|
+
userEmail: string;
|
|
73
|
+
orgId?: string | null;
|
|
74
|
+
}): boolean;
|
|
75
|
+
export declare function getMcpDirectoryWidgetWriteCapabilityGrant(scope: string | undefined, input: {
|
|
76
|
+
appId: string;
|
|
77
|
+
resourceUri: string;
|
|
78
|
+
userEmail: string;
|
|
79
|
+
orgId?: string | null;
|
|
80
|
+
}): {
|
|
81
|
+
resourceIds: Record<string, string>;
|
|
82
|
+
actionNames: string[];
|
|
83
|
+
} | undefined;
|
|
84
|
+
export declare function getMcpDirectoryWidgetWriteCapabilityExpiresAt(scope: string | undefined): number | undefined;
|
|
85
|
+
export declare function matchesMcpDirectoryWidgetReadCapabilityResource(scope: string | undefined, input: {
|
|
86
|
+
appId: string;
|
|
87
|
+
resourceUri: string;
|
|
88
|
+
}): boolean;
|
|
28
89
|
export declare function normalizeMcpDirectoryWidgetReadActionArguments(scope: string | undefined, input: {
|
|
29
90
|
actionName: string;
|
|
30
91
|
appId: string | undefined;
|
|
31
92
|
resourceUri: string | undefined;
|
|
32
93
|
args?: Record<string, unknown>;
|
|
94
|
+
userEmail?: string;
|
|
95
|
+
orgId?: string | null;
|
|
33
96
|
allowedArgumentNames?: readonly string[];
|
|
34
97
|
requireArgumentMatch?: boolean;
|
|
35
98
|
}): Record<string, unknown> | undefined;
|
|
99
|
+
export declare function normalizeMcpDirectoryWidgetWriteActionArguments(scope: string | undefined, input: {
|
|
100
|
+
actionName: string;
|
|
101
|
+
appId: string | undefined;
|
|
102
|
+
resourceUri: string | undefined;
|
|
103
|
+
userEmail: string | undefined;
|
|
104
|
+
orgId?: string | null;
|
|
105
|
+
args?: Record<string, unknown>;
|
|
106
|
+
allowedArgumentNames?: readonly string[];
|
|
107
|
+
}): Record<string, unknown> | undefined;
|
|
36
108
|
export declare function allowsMcpDirectoryWidgetReadAction(scope: string | undefined, input: {
|
|
37
109
|
actionName: string;
|
|
38
110
|
appId: string | undefined;
|
|
39
111
|
resourceUri: string | undefined;
|
|
112
|
+
userEmail?: string;
|
|
113
|
+
orgId?: string | null;
|
|
40
114
|
args?: Record<string, unknown>;
|
|
41
115
|
allowedArgumentNames?: readonly string[];
|
|
42
116
|
requireArgumentMatch?: boolean;
|
|
@@ -6,8 +6,12 @@ export const MCP_APP_CHAT_BRIDGE_QUERY_PARAM = "__an_mcp_chat_bridge";
|
|
|
6
6
|
export const MCP_DIRECTORY_WIDGET_QUERY_PARAM = "__an_mcp_directory_widget";
|
|
7
7
|
export const EMBED_SESSION_COOKIE = "an_embed_session";
|
|
8
8
|
export const EMBED_TARGET_HEADER = "x-agent-native-embed-target";
|
|
9
|
+
export const MCP_DIRECTORY_WIDGET_SESSION_EXPIRED_HEADER = "x-agent-native-widget-session-expired";
|
|
9
10
|
export const MCP_DIRECTORY_WIDGET_READ_CAPABILITY_PREFIX = "capability:mcp-directory-widget-read:";
|
|
11
|
+
export const MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_PREFIX = "capability:mcp-directory-widget-write:";
|
|
10
12
|
export const MCP_DIRECTORY_WIDGET_READ_CAPABILITY_MAX_LENGTH = 2048;
|
|
13
|
+
export const MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_MAX_LENGTH = 4096;
|
|
14
|
+
export const MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_MAX_AGE_MS = 15 * 60 * 1000;
|
|
11
15
|
const MCP_DIRECTORY_WIDGET_INTEGER_ARGUMENT_MAX = 5_000;
|
|
12
16
|
const MCP_DIRECTORY_ACTION_NAME = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
13
17
|
const MCP_DIRECTORY_SCOPE_KEY = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
@@ -25,7 +29,7 @@ function isStringRecord(value, { minEntries = 1, maxEntries = 16 } = {}) {
|
|
|
25
29
|
item.length <= 256 &&
|
|
26
30
|
!CONTROL_CHARS.test(item)));
|
|
27
31
|
}
|
|
28
|
-
function isWidgetReadArgument(value) {
|
|
32
|
+
function isWidgetReadArgument(value, allowResourceBound = false) {
|
|
29
33
|
if (typeof value === "string") {
|
|
30
34
|
return (value.length > 0 && value.length <= 256 && !CONTROL_CHARS.test(value));
|
|
31
35
|
}
|
|
@@ -36,6 +40,12 @@ function isWidgetReadArgument(value) {
|
|
|
36
40
|
if (range.type === "actionSchema") {
|
|
37
41
|
return Object.keys(range).length === 1;
|
|
38
42
|
}
|
|
43
|
+
if (range.type === "actionSchemaResourceBound") {
|
|
44
|
+
return (allowResourceBound &&
|
|
45
|
+
Object.keys(range).length === 2 &&
|
|
46
|
+
typeof range.resourceKey === "string" &&
|
|
47
|
+
MCP_DIRECTORY_SCOPE_KEY.test(range.resourceKey));
|
|
48
|
+
}
|
|
39
49
|
return (range.type === "integerRange" &&
|
|
40
50
|
Object.keys(range).length === 3 &&
|
|
41
51
|
Number.isSafeInteger(range.min) &&
|
|
@@ -44,14 +54,15 @@ function isWidgetReadArgument(value) {
|
|
|
44
54
|
range.max >= range.min &&
|
|
45
55
|
range.max <= MCP_DIRECTORY_WIDGET_INTEGER_ARGUMENT_MAX);
|
|
46
56
|
}
|
|
47
|
-
function isWidgetReadArgumentRecord(value, { minEntries = 1, maxEntries = 16 } = {}) {
|
|
57
|
+
function isWidgetReadArgumentRecord(value, { minEntries = 1, maxEntries = 16, allowResourceBound = false, } = {}) {
|
|
48
58
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
49
59
|
return false;
|
|
50
60
|
}
|
|
51
61
|
const entries = Object.entries(value);
|
|
52
62
|
return (entries.length >= minEntries &&
|
|
53
63
|
entries.length <= maxEntries &&
|
|
54
|
-
entries.every(([key, item]) => MCP_DIRECTORY_SCOPE_KEY.test(key) &&
|
|
64
|
+
entries.every(([key, item]) => MCP_DIRECTORY_SCOPE_KEY.test(key) &&
|
|
65
|
+
isWidgetReadArgument(item, allowResourceBound)));
|
|
55
66
|
}
|
|
56
67
|
function isWidgetReadCapability(value) {
|
|
57
68
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -109,6 +120,68 @@ function decodeMcpDirectoryWidgetReadCapability(scope) {
|
|
|
109
120
|
? { ok: true, capability: value }
|
|
110
121
|
: { ok: false, reason: "invalid-capability" };
|
|
111
122
|
}
|
|
123
|
+
function decodeMcpDirectoryWidgetWriteCapability(scope) {
|
|
124
|
+
if (!scope.startsWith(MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_PREFIX) ||
|
|
125
|
+
scope.length > MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_MAX_LENGTH) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const value = JSON.parse(decodeURIComponent(scope.slice(MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_PREFIX.length)));
|
|
130
|
+
if (value.version !== 1 ||
|
|
131
|
+
typeof value.appId !== "string" ||
|
|
132
|
+
!MCP_DIRECTORY_SCOPE_KEY.test(value.appId) ||
|
|
133
|
+
typeof value.resourceUri !== "string" ||
|
|
134
|
+
!value.resourceUri.startsWith("ui://") ||
|
|
135
|
+
value.resourceUri.length > 512 ||
|
|
136
|
+
CONTROL_CHARS.test(value.resourceUri) ||
|
|
137
|
+
!isStringRecord(value.resourceIds) ||
|
|
138
|
+
typeof value.userEmail !== "string" ||
|
|
139
|
+
value.userEmail.length > 320 ||
|
|
140
|
+
CONTROL_CHARS.test(value.userEmail) ||
|
|
141
|
+
(value.orgId !== undefined &&
|
|
142
|
+
(typeof value.orgId !== "string" ||
|
|
143
|
+
value.orgId.length > 256 ||
|
|
144
|
+
CONTROL_CHARS.test(value.orgId))) ||
|
|
145
|
+
!Number.isSafeInteger(value.expiresAtMs)) {
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
const readActionArguments = value.readActionArguments;
|
|
149
|
+
const writeActionArguments = value.writeActionArguments;
|
|
150
|
+
if (!isWidgetActionArgumentMap(readActionArguments, { minActions: 0 }) ||
|
|
151
|
+
!isWidgetActionArgumentMap(writeActionArguments, {
|
|
152
|
+
maxArguments: 32,
|
|
153
|
+
allowResourceBound: true,
|
|
154
|
+
}) ||
|
|
155
|
+
Object.keys(writeActionArguments).some((actionName) => {
|
|
156
|
+
const args = writeActionArguments[actionName];
|
|
157
|
+
return !Object.values(args).some((argument) => typeof argument === "string"
|
|
158
|
+
? Object.values(value.resourceIds).includes(argument)
|
|
159
|
+
: argument.type === "actionSchemaResourceBound" &&
|
|
160
|
+
Object.hasOwn(value.resourceIds, argument.resourceKey));
|
|
161
|
+
})) {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// coercion-ok: malformed caller scope remains an absent, denied capability.
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function isWidgetActionArgumentMap(value, { minActions = 1, maxArguments = 16, allowResourceBound = false, } = {}) {
|
|
172
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
const actions = Object.entries(value);
|
|
176
|
+
return (actions.length >= minActions &&
|
|
177
|
+
actions.length <= 32 &&
|
|
178
|
+
actions.every(([actionName, args]) => MCP_DIRECTORY_ACTION_NAME.test(actionName) &&
|
|
179
|
+
isWidgetReadArgumentRecord(args, {
|
|
180
|
+
minEntries: 0,
|
|
181
|
+
maxEntries: maxArguments,
|
|
182
|
+
allowResourceBound,
|
|
183
|
+
})));
|
|
184
|
+
}
|
|
112
185
|
function sortStringRecord(value) {
|
|
113
186
|
return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)));
|
|
114
187
|
}
|
|
@@ -156,22 +229,253 @@ export function createMcpDirectoryWidgetReadCapability(input) {
|
|
|
156
229
|
? scope
|
|
157
230
|
: undefined;
|
|
158
231
|
}
|
|
232
|
+
export function createMcpDirectoryWidgetWriteCapability(input) {
|
|
233
|
+
const now = Date.now();
|
|
234
|
+
if (!input ||
|
|
235
|
+
typeof input.appId !== "string" ||
|
|
236
|
+
!MCP_DIRECTORY_SCOPE_KEY.test(input.appId) ||
|
|
237
|
+
typeof input.resourceUri !== "string" ||
|
|
238
|
+
!input.resourceUri.startsWith("ui://") ||
|
|
239
|
+
input.resourceUri.length > 512 ||
|
|
240
|
+
CONTROL_CHARS.test(input.resourceUri) ||
|
|
241
|
+
!isStringRecord(input.resourceIds) ||
|
|
242
|
+
typeof input.userEmail !== "string" ||
|
|
243
|
+
!input.userEmail.trim() ||
|
|
244
|
+
input.userEmail.length > 320 ||
|
|
245
|
+
CONTROL_CHARS.test(input.userEmail) ||
|
|
246
|
+
(input.orgId !== undefined &&
|
|
247
|
+
(typeof input.orgId !== "string" ||
|
|
248
|
+
!input.orgId.trim() ||
|
|
249
|
+
input.orgId.length > 256 ||
|
|
250
|
+
CONTROL_CHARS.test(input.orgId))) ||
|
|
251
|
+
!Number.isSafeInteger(input.expiresAtMs) ||
|
|
252
|
+
input.expiresAtMs <= now ||
|
|
253
|
+
input.expiresAtMs >
|
|
254
|
+
now + MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_MAX_AGE_MS ||
|
|
255
|
+
!isWidgetActionArgumentMap(input.readActionArguments, { minActions: 0 }) ||
|
|
256
|
+
!isWidgetActionArgumentMap(input.writeActionArguments, {
|
|
257
|
+
maxArguments: 32,
|
|
258
|
+
allowResourceBound: true,
|
|
259
|
+
}) ||
|
|
260
|
+
Object.values(input.writeActionArguments).some((args) => !Object.values(args).some((argument) => typeof argument === "string"
|
|
261
|
+
? Object.values(input.resourceIds).includes(argument)
|
|
262
|
+
: argument.type === "actionSchemaResourceBound" &&
|
|
263
|
+
Object.hasOwn(input.resourceIds, argument.resourceKey)))) {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
const capability = {
|
|
267
|
+
version: 1,
|
|
268
|
+
appId: input.appId,
|
|
269
|
+
resourceUri: input.resourceUri,
|
|
270
|
+
resourceIds: sortStringRecord(input.resourceIds),
|
|
271
|
+
userEmail: input.userEmail.trim().toLowerCase(),
|
|
272
|
+
...(input.orgId ? { orgId: input.orgId } : {}),
|
|
273
|
+
expiresAtMs: input.expiresAtMs,
|
|
274
|
+
readActionArguments: Object.fromEntries(Object.entries(input.readActionArguments)
|
|
275
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
276
|
+
.map(([actionName, args]) => [
|
|
277
|
+
actionName,
|
|
278
|
+
sortWidgetReadArgumentRecord(args),
|
|
279
|
+
])),
|
|
280
|
+
writeActionArguments: Object.fromEntries(Object.entries(input.writeActionArguments)
|
|
281
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
282
|
+
.map(([actionName, args]) => [
|
|
283
|
+
actionName,
|
|
284
|
+
sortWidgetReadArgumentRecord(args),
|
|
285
|
+
])),
|
|
286
|
+
};
|
|
287
|
+
const scope = MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_PREFIX +
|
|
288
|
+
encodeURIComponent(JSON.stringify(capability));
|
|
289
|
+
return scope.length <= MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_MAX_LENGTH
|
|
290
|
+
? scope
|
|
291
|
+
: undefined;
|
|
292
|
+
}
|
|
293
|
+
export function renewMcpDirectoryWidgetCapabilityScope(scope, input) {
|
|
294
|
+
if (!scope || !input.appId || !input.userEmail || !input.readAllowed) {
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
if (isMcpDirectoryWidgetWriteCapabilityScope(scope)) {
|
|
298
|
+
const capability = decodeMcpDirectoryWidgetWriteCapability(scope);
|
|
299
|
+
if (!capability ||
|
|
300
|
+
capability.appId !== input.appId ||
|
|
301
|
+
capability.userEmail !== input.userEmail.trim().toLowerCase() ||
|
|
302
|
+
capability.orgId !== (input.orgId ?? undefined)) {
|
|
303
|
+
return undefined;
|
|
304
|
+
}
|
|
305
|
+
if (!input.writeAllowed) {
|
|
306
|
+
return createMcpDirectoryWidgetReadCapability({
|
|
307
|
+
appId: capability.appId,
|
|
308
|
+
resourceUri: input.resourceUri,
|
|
309
|
+
resourceIds: capability.resourceIds,
|
|
310
|
+
actionArguments: capability.readActionArguments,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
return createMcpDirectoryWidgetWriteCapability({
|
|
314
|
+
...capability,
|
|
315
|
+
resourceUri: input.resourceUri,
|
|
316
|
+
expiresAtMs: input.expiresAtMs,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
const decoded = decodeMcpDirectoryWidgetReadCapability(scope);
|
|
320
|
+
return decoded.ok && decoded.capability.appId === input.appId
|
|
321
|
+
? createMcpDirectoryWidgetReadCapability({
|
|
322
|
+
...decoded.capability,
|
|
323
|
+
resourceUri: input.resourceUri,
|
|
324
|
+
})
|
|
325
|
+
: undefined;
|
|
326
|
+
}
|
|
327
|
+
function sameWidgetActionArguments(left, right) {
|
|
328
|
+
const normalize = (value) => Object.fromEntries(Object.entries(value)
|
|
329
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
330
|
+
.map(([actionName, args]) => [
|
|
331
|
+
actionName,
|
|
332
|
+
Object.fromEntries(Object.entries(args).sort(([a], [b]) => a.localeCompare(b))),
|
|
333
|
+
]));
|
|
334
|
+
return JSON.stringify(normalize(left)) === JSON.stringify(normalize(right));
|
|
335
|
+
}
|
|
336
|
+
export function canRenewMcpDirectoryWidgetCapabilityScope(previousScope, renewedScope, identity) {
|
|
337
|
+
if (!identity.userEmail.trim())
|
|
338
|
+
return false;
|
|
339
|
+
const previousWrite = isMcpDirectoryWidgetWriteCapabilityScope(previousScope);
|
|
340
|
+
const renewedWrite = isMcpDirectoryWidgetWriteCapabilityScope(renewedScope);
|
|
341
|
+
if (renewedWrite && !previousWrite)
|
|
342
|
+
return false;
|
|
343
|
+
const identityMatches = (capability) => capability.userEmail === identity.userEmail.trim().toLowerCase() &&
|
|
344
|
+
capability.orgId === (identity.orgId ?? undefined);
|
|
345
|
+
if (previousWrite) {
|
|
346
|
+
const previous = decodeMcpDirectoryWidgetWriteCapability(previousScope);
|
|
347
|
+
if (!previous || !identityMatches(previous))
|
|
348
|
+
return false;
|
|
349
|
+
if (renewedWrite) {
|
|
350
|
+
const renewed = decodeMcpDirectoryWidgetWriteCapability(renewedScope);
|
|
351
|
+
return Boolean(renewed &&
|
|
352
|
+
identityMatches(renewed) &&
|
|
353
|
+
renewed.appId === previous.appId &&
|
|
354
|
+
sameWidgetActionArguments(renewed.readActionArguments, previous.readActionArguments) &&
|
|
355
|
+
sameWidgetActionArguments(renewed.writeActionArguments, previous.writeActionArguments) &&
|
|
356
|
+
JSON.stringify(renewed.resourceIds) ===
|
|
357
|
+
JSON.stringify(previous.resourceIds));
|
|
358
|
+
}
|
|
359
|
+
const renewed = decodeMcpDirectoryWidgetReadCapability(renewedScope);
|
|
360
|
+
return Boolean(renewed.ok &&
|
|
361
|
+
renewed.capability.appId === previous.appId &&
|
|
362
|
+
sameWidgetActionArguments(renewed.capability.actionArguments, previous.readActionArguments) &&
|
|
363
|
+
JSON.stringify(renewed.capability.resourceIds) ===
|
|
364
|
+
JSON.stringify(previous.resourceIds));
|
|
365
|
+
}
|
|
366
|
+
const previous = decodeMcpDirectoryWidgetReadCapability(previousScope);
|
|
367
|
+
const renewed = decodeMcpDirectoryWidgetReadCapability(renewedScope);
|
|
368
|
+
return Boolean(!renewedWrite &&
|
|
369
|
+
previous.ok &&
|
|
370
|
+
renewed.ok &&
|
|
371
|
+
renewed.capability.appId === previous.capability.appId &&
|
|
372
|
+
sameWidgetActionArguments(renewed.capability.actionArguments, previous.capability.actionArguments) &&
|
|
373
|
+
JSON.stringify(renewed.capability.resourceIds) ===
|
|
374
|
+
JSON.stringify(previous.capability.resourceIds));
|
|
375
|
+
}
|
|
159
376
|
export function isMcpDirectoryWidgetReadCapabilityScope(scope) {
|
|
160
377
|
return (scope?.startsWith(MCP_DIRECTORY_WIDGET_READ_CAPABILITY_PREFIX) === true);
|
|
161
378
|
}
|
|
379
|
+
export function isMcpDirectoryWidgetWriteCapabilityScope(scope) {
|
|
380
|
+
return (scope?.startsWith(MCP_DIRECTORY_WIDGET_WRITE_CAPABILITY_PREFIX) === true);
|
|
381
|
+
}
|
|
382
|
+
export function isMcpDirectoryWidgetCapabilityScope(scope) {
|
|
383
|
+
return (isMcpDirectoryWidgetReadCapabilityScope(scope) ||
|
|
384
|
+
isMcpDirectoryWidgetWriteCapabilityScope(scope));
|
|
385
|
+
}
|
|
386
|
+
export function matchesMcpDirectoryWidgetWriteCapability(scope, input) {
|
|
387
|
+
if (!scope || !isMcpDirectoryWidgetWriteCapabilityScope(scope)) {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
const capability = decodeMcpDirectoryWidgetWriteCapability(scope);
|
|
391
|
+
return (capability !== undefined &&
|
|
392
|
+
capability.expiresAtMs > Date.now() &&
|
|
393
|
+
capability.appId === input.appId &&
|
|
394
|
+
capability.resourceUri === input.resourceUri &&
|
|
395
|
+
capability.userEmail === input.userEmail.trim().toLowerCase() &&
|
|
396
|
+
capability.orgId === (input.orgId ?? undefined));
|
|
397
|
+
}
|
|
398
|
+
export function isExpiredMcpDirectoryWidgetWriteCapability(scope, input) {
|
|
399
|
+
if (!scope || !isMcpDirectoryWidgetWriteCapabilityScope(scope)) {
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
const capability = decodeMcpDirectoryWidgetWriteCapability(scope);
|
|
403
|
+
return (capability !== undefined &&
|
|
404
|
+
capability.expiresAtMs <= Date.now() &&
|
|
405
|
+
capability.appId === input.appId &&
|
|
406
|
+
capability.resourceUri === input.resourceUri &&
|
|
407
|
+
capability.userEmail === input.userEmail.trim().toLowerCase() &&
|
|
408
|
+
capability.orgId === (input.orgId ?? undefined));
|
|
409
|
+
}
|
|
410
|
+
export function getMcpDirectoryWidgetWriteCapabilityGrant(scope, input) {
|
|
411
|
+
if (!matchesMcpDirectoryWidgetWriteCapability(scope, input) || !scope) {
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
const capability = decodeMcpDirectoryWidgetWriteCapability(scope);
|
|
415
|
+
return capability
|
|
416
|
+
? {
|
|
417
|
+
resourceIds: { ...capability.resourceIds },
|
|
418
|
+
actionNames: Object.keys(capability.writeActionArguments),
|
|
419
|
+
}
|
|
420
|
+
: undefined;
|
|
421
|
+
}
|
|
422
|
+
export function getMcpDirectoryWidgetWriteCapabilityExpiresAt(scope) {
|
|
423
|
+
if (!scope || !isMcpDirectoryWidgetWriteCapabilityScope(scope)) {
|
|
424
|
+
return undefined;
|
|
425
|
+
}
|
|
426
|
+
return decodeMcpDirectoryWidgetWriteCapability(scope)?.expiresAtMs;
|
|
427
|
+
}
|
|
428
|
+
export function matchesMcpDirectoryWidgetReadCapabilityResource(scope, input) {
|
|
429
|
+
if (!scope || !isMcpDirectoryWidgetReadCapabilityScope(scope))
|
|
430
|
+
return false;
|
|
431
|
+
const decoded = decodeMcpDirectoryWidgetReadCapability(scope);
|
|
432
|
+
return (decoded.ok &&
|
|
433
|
+
decoded.capability.appId === input.appId &&
|
|
434
|
+
decoded.capability.resourceUri === input.resourceUri);
|
|
435
|
+
}
|
|
436
|
+
function widgetReadActionArgumentsForScope(scope) {
|
|
437
|
+
if (isMcpDirectoryWidgetWriteCapabilityScope(scope)) {
|
|
438
|
+
const capability = decodeMcpDirectoryWidgetWriteCapability(scope);
|
|
439
|
+
return capability && capability.expiresAtMs > Date.now()
|
|
440
|
+
? capability.readActionArguments
|
|
441
|
+
: undefined;
|
|
442
|
+
}
|
|
443
|
+
const decoded = decodeMcpDirectoryWidgetReadCapability(scope);
|
|
444
|
+
return decoded.ok ? decoded.capability.actionArguments : undefined;
|
|
445
|
+
}
|
|
162
446
|
export function normalizeMcpDirectoryWidgetReadActionArguments(scope, input) {
|
|
163
447
|
if (!scope || !input.appId || !input.resourceUri)
|
|
164
448
|
return undefined;
|
|
165
|
-
const
|
|
166
|
-
if (!
|
|
449
|
+
const actionArguments = widgetReadActionArgumentsForScope(scope);
|
|
450
|
+
if (!actionArguments)
|
|
167
451
|
return undefined;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
452
|
+
let capabilityAppId;
|
|
453
|
+
let capabilityResourceUri;
|
|
454
|
+
let capabilityUserEmail;
|
|
455
|
+
let capabilityOrgId;
|
|
456
|
+
if (isMcpDirectoryWidgetWriteCapabilityScope(scope)) {
|
|
457
|
+
const capability = decodeMcpDirectoryWidgetWriteCapability(scope);
|
|
458
|
+
capabilityAppId = capability?.appId;
|
|
459
|
+
capabilityResourceUri = capability?.resourceUri;
|
|
460
|
+
capabilityUserEmail = capability?.userEmail;
|
|
461
|
+
capabilityOrgId = capability?.orgId;
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
const decoded = decodeMcpDirectoryWidgetReadCapability(scope);
|
|
465
|
+
capabilityAppId = decoded.ok ? decoded.capability.appId : undefined;
|
|
466
|
+
capabilityResourceUri = decoded.ok
|
|
467
|
+
? decoded.capability.resourceUri
|
|
468
|
+
: undefined;
|
|
469
|
+
}
|
|
470
|
+
if (capabilityAppId !== input.appId ||
|
|
471
|
+
capabilityResourceUri !== input.resourceUri ||
|
|
472
|
+
(capabilityUserEmail &&
|
|
473
|
+
capabilityUserEmail !== input.userEmail?.trim().toLowerCase()) ||
|
|
474
|
+
(isMcpDirectoryWidgetWriteCapabilityScope(scope) &&
|
|
475
|
+
capabilityOrgId !== (input.orgId ?? undefined))) {
|
|
172
476
|
return undefined;
|
|
173
477
|
}
|
|
174
|
-
const expectedArgs =
|
|
478
|
+
const expectedArgs = actionArguments[input.actionName];
|
|
175
479
|
if (!expectedArgs)
|
|
176
480
|
return undefined;
|
|
177
481
|
const allowedNames = [...(input.allowedArgumentNames ?? [])].sort();
|
|
@@ -205,6 +509,71 @@ export function normalizeMcpDirectoryWidgetReadActionArguments(scope, input) {
|
|
|
205
509
|
normalizedArgs.push([name, value]);
|
|
206
510
|
continue;
|
|
207
511
|
}
|
|
512
|
+
if (expected.type === "actionSchemaResourceBound")
|
|
513
|
+
return undefined;
|
|
514
|
+
const number = typeof value === "number"
|
|
515
|
+
? value
|
|
516
|
+
: typeof value === "string" && /^(0|[1-9]\d*)$/.test(value)
|
|
517
|
+
? Number(value)
|
|
518
|
+
: Number.NaN;
|
|
519
|
+
if (!Number.isSafeInteger(number) ||
|
|
520
|
+
number < expected.min ||
|
|
521
|
+
number > expected.max) {
|
|
522
|
+
return undefined;
|
|
523
|
+
}
|
|
524
|
+
normalizedArgs.push([name, number]);
|
|
525
|
+
}
|
|
526
|
+
return Object.fromEntries(normalizedArgs);
|
|
527
|
+
}
|
|
528
|
+
export function normalizeMcpDirectoryWidgetWriteActionArguments(scope, input) {
|
|
529
|
+
if (!scope ||
|
|
530
|
+
!isMcpDirectoryWidgetWriteCapabilityScope(scope) ||
|
|
531
|
+
!input.appId ||
|
|
532
|
+
!input.resourceUri ||
|
|
533
|
+
!input.userEmail) {
|
|
534
|
+
return undefined;
|
|
535
|
+
}
|
|
536
|
+
const capability = decodeMcpDirectoryWidgetWriteCapability(scope);
|
|
537
|
+
if (!capability ||
|
|
538
|
+
capability.expiresAtMs <= Date.now() ||
|
|
539
|
+
capability.appId !== input.appId ||
|
|
540
|
+
capability.resourceUri !== input.resourceUri ||
|
|
541
|
+
capability.userEmail !== input.userEmail.trim().toLowerCase() ||
|
|
542
|
+
capability.orgId !== (input.orgId ?? undefined)) {
|
|
543
|
+
return undefined;
|
|
544
|
+
}
|
|
545
|
+
const expectedArgs = capability.writeActionArguments[input.actionName];
|
|
546
|
+
if (!expectedArgs)
|
|
547
|
+
return undefined;
|
|
548
|
+
const allowedNames = [...(input.allowedArgumentNames ?? [])].sort();
|
|
549
|
+
const expectedNames = Object.keys(expectedArgs).sort();
|
|
550
|
+
if (allowedNames.length !== expectedNames.length ||
|
|
551
|
+
allowedNames.some((name, index) => name !== expectedNames[index])) {
|
|
552
|
+
return undefined;
|
|
553
|
+
}
|
|
554
|
+
const suppliedArgs = Object.entries(input.args ?? {});
|
|
555
|
+
const includesResourceBinding = suppliedArgs.some(([name, value]) => typeof expectedArgs[name] === "string" && expectedArgs[name] === value) ||
|
|
556
|
+
Object.values(expectedArgs).some((expected) => typeof expected !== "string" &&
|
|
557
|
+
expected.type === "actionSchemaResourceBound" &&
|
|
558
|
+
Object.hasOwn(capability.resourceIds, expected.resourceKey));
|
|
559
|
+
if (!includesResourceBinding)
|
|
560
|
+
return undefined;
|
|
561
|
+
const normalizedArgs = [];
|
|
562
|
+
for (const [name, value] of suppliedArgs) {
|
|
563
|
+
if (!Object.hasOwn(expectedArgs, name))
|
|
564
|
+
return undefined;
|
|
565
|
+
const expected = expectedArgs[name];
|
|
566
|
+
if (typeof expected === "string") {
|
|
567
|
+
if (expected !== value)
|
|
568
|
+
return undefined;
|
|
569
|
+
normalizedArgs.push([name, value]);
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
if (expected.type === "actionSchema" ||
|
|
573
|
+
expected.type === "actionSchemaResourceBound") {
|
|
574
|
+
normalizedArgs.push([name, value]);
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
208
577
|
const number = typeof value === "number"
|
|
209
578
|
? value
|
|
210
579
|
: typeof value === "string" && /^(0|[1-9]\d*)$/.test(value)
|
|
@@ -2,6 +2,7 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
2
2
|
resourceType: string;
|
|
3
3
|
resourceId: string;
|
|
4
4
|
}, {
|
|
5
|
+
role?: undefined;
|
|
5
6
|
ownerEmail: any;
|
|
6
7
|
visibility: any;
|
|
7
8
|
shares: any[];
|
|
@@ -11,7 +12,6 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
11
12
|
supportsGroupShares?: boolean;
|
|
12
13
|
};
|
|
13
14
|
orgId?: undefined;
|
|
14
|
-
role?: undefined;
|
|
15
15
|
agentReadable?: undefined;
|
|
16
16
|
} | {
|
|
17
17
|
ownerEmail: string;
|
|
@@ -14,6 +14,7 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
14
14
|
executionCwd?: string;
|
|
15
15
|
}, {
|
|
16
16
|
deleted?: undefined;
|
|
17
|
+
enabled?: undefined;
|
|
17
18
|
created: boolean;
|
|
18
19
|
name: string;
|
|
19
20
|
scope: "organization" | "personal";
|
|
@@ -24,25 +25,24 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
24
25
|
reasoningEffort: "auto" | "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh";
|
|
25
26
|
webhookPath: string;
|
|
26
27
|
nextRun: string;
|
|
27
|
-
enabled?: undefined;
|
|
28
28
|
executionHostId?: undefined;
|
|
29
29
|
executionEngine?: undefined;
|
|
30
30
|
executionCwd?: undefined;
|
|
31
31
|
} | {
|
|
32
|
+
enabled?: undefined;
|
|
33
|
+
nextRun?: undefined;
|
|
32
34
|
created?: undefined;
|
|
33
35
|
scope?: undefined;
|
|
34
36
|
triggerType?: undefined;
|
|
35
37
|
event?: undefined;
|
|
36
38
|
deleted: boolean;
|
|
37
39
|
name: string;
|
|
38
|
-
enabled?: undefined;
|
|
39
40
|
schedule?: undefined;
|
|
40
41
|
timezone?: undefined;
|
|
41
42
|
reasoningEffort?: undefined;
|
|
42
43
|
executionHostId?: undefined;
|
|
43
44
|
executionEngine?: undefined;
|
|
44
45
|
executionCwd?: undefined;
|
|
45
|
-
nextRun?: undefined;
|
|
46
46
|
webhookPath?: undefined;
|
|
47
47
|
} | {
|
|
48
48
|
deleted?: undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.206.0
|
|
3
|
+
"version": "0.206.0",
|
|
4
4
|
"description": "The agentic application framework for building autonomous agents with intuitive UIs",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -688,8 +688,8 @@
|
|
|
688
688
|
"yaml": "^2.9.0",
|
|
689
689
|
"yjs": "^13.6.33",
|
|
690
690
|
"zod": "^4.3.6",
|
|
691
|
-
"@agent-native/agentkit": "^0.206.0
|
|
692
|
-
"@agent-native/recap-cli": "^0.5.68
|
|
691
|
+
"@agent-native/agentkit": "^0.206.0",
|
|
692
|
+
"@agent-native/recap-cli": "^0.5.68"
|
|
693
693
|
},
|
|
694
694
|
"devDependencies": {
|
|
695
695
|
"@ai-sdk/anthropic": "^3.0.71",
|
|
@@ -759,7 +759,7 @@
|
|
|
759
759
|
"xlsx": "^0.18.5"
|
|
760
760
|
},
|
|
761
761
|
"peerDependencies": {
|
|
762
|
-
"@agent-native/core-corpus": "0.
|
|
762
|
+
"@agent-native/core-corpus": ">=0.196.0",
|
|
763
763
|
"@ai-sdk/anthropic": ">=3",
|
|
764
764
|
"@ai-sdk/cohere": ">=3",
|
|
765
765
|
"@ai-sdk/google": ">=3",
|