@ory/vercel-ai 0.10.0 → 0.11.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/README.md +4 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +17 -14
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -27,7 +27,10 @@ each call it authorizes the tool and records spans. In **enforce** mode
|
|
|
27
27
|
in **observe** mode (default) the tool runs and a `permission.observe_deny` span is recorded.
|
|
28
28
|
Tools without an `execute` (provider-defined) pass through untouched.
|
|
29
29
|
|
|
30
|
-
Derive the permission subject from per-call context with `subjectFromOptions
|
|
30
|
+
Derive the permission subject from per-call context with `subjectFromOptions`. A non-empty
|
|
31
|
+
return value takes precedence over the client's user principal and env overrides for that
|
|
32
|
+
call — this is how multi-user servers attribute each request to its own acting user. When it
|
|
33
|
+
returns undefined/empty, resolution falls back to the principal / env chain:
|
|
31
34
|
|
|
32
35
|
```ts
|
|
33
36
|
withOry(tools, { subjectFromOptions: (o) => o?.experimental_context?.userId });
|
package/dist/index.d.ts
CHANGED
|
@@ -29,8 +29,10 @@ export interface WithOryOptions {
|
|
|
29
29
|
canBlock?: boolean;
|
|
30
30
|
/**
|
|
31
31
|
* Derive the permission subject from the AI SDK call options (e.g. read a thread/user id
|
|
32
|
-
* from `options.experimental_context`).
|
|
33
|
-
*
|
|
32
|
+
* from `options.experimental_context`). A non-empty return value takes precedence over the
|
|
33
|
+
* client's user principal and env overrides for that call — this is how multi-user servers
|
|
34
|
+
* attribute each request to its own acting user. When the function returns
|
|
35
|
+
* undefined/empty, resolution falls back to the principal / env chain.
|
|
34
36
|
*/
|
|
35
37
|
subjectFromOptions?: (options: unknown) => string | undefined;
|
|
36
38
|
}
|
package/dist/index.js
CHANGED
|
@@ -26,19 +26,22 @@ const HARNESS = "vercel-ai";
|
|
|
26
26
|
function withOry(tools, options = {}) {
|
|
27
27
|
const client = options.client ?? argus_1.OryAgentClient.fromEnv(HARNESS);
|
|
28
28
|
const canBlock = options.canBlock ?? true;
|
|
29
|
-
let
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
let sessionPromise;
|
|
30
|
+
// Cache the in-flight promise (not a boolean) so concurrent first calls all
|
|
31
|
+
// await the same session start instead of racing past a still-running gate.
|
|
32
|
+
// Fail-open: a rejection is logged, never rethrown, and clears the cache so
|
|
33
|
+
// a later call can retry.
|
|
34
|
+
const ensureSession = () => {
|
|
35
|
+
sessionPromise ??= (0, argus_1.sessionStart)(client, {
|
|
36
|
+
harness: HARNESS,
|
|
37
|
+
projectUrl: options.projectUrl,
|
|
38
|
+
}).then(() => undefined, (err) => {
|
|
39
|
+
sessionPromise = undefined;
|
|
38
40
|
client.logger.warn("session_start.failed", {
|
|
39
41
|
message: err instanceof Error ? err.message : String(err),
|
|
40
42
|
});
|
|
41
|
-
}
|
|
43
|
+
});
|
|
44
|
+
return sessionPromise;
|
|
42
45
|
};
|
|
43
46
|
const wrapped = {};
|
|
44
47
|
for (const [name, tool] of Object.entries(tools)) {
|
|
@@ -51,14 +54,14 @@ function withOry(tools, options = {}) {
|
|
|
51
54
|
...tool,
|
|
52
55
|
execute: async (input, callOptions) => {
|
|
53
56
|
await ensureSession();
|
|
54
|
-
|
|
55
|
-
const
|
|
57
|
+
// A per-call subject wins over the client principal / env overrides.
|
|
58
|
+
const subjectOverride = options.subjectFromOptions?.(callOptions);
|
|
59
|
+
const result = await (0, argus_1.runWithUserSubject)(subjectOverride, () => (0, argus_1.gate)(client, {
|
|
56
60
|
harness: HARNESS,
|
|
57
61
|
toolName: name,
|
|
58
62
|
toolArgs: input,
|
|
59
|
-
subjectFallback,
|
|
60
63
|
canBlock,
|
|
61
|
-
});
|
|
64
|
+
}));
|
|
62
65
|
if (result.blocked) {
|
|
63
66
|
throw new argus_1.OryDenialError({
|
|
64
67
|
tool: name,
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ory/vercel-ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Ory Agent Security for the Vercel AI SDK — per-tool authorization, tracing, and identity propagation by wrapping tool execute(). Built on @ory/argus.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public",
|
|
8
|
+
"registry": "https://registry.npmjs.org/",
|
|
9
|
+
"provenance": true
|
|
10
|
+
},
|
|
6
11
|
"main": "dist/index.js",
|
|
7
12
|
"types": "dist/index.d.ts",
|
|
8
13
|
"exports": {
|
|
@@ -25,7 +30,7 @@
|
|
|
25
30
|
"permissions"
|
|
26
31
|
],
|
|
27
32
|
"dependencies": {
|
|
28
|
-
"@ory/argus": "0.
|
|
33
|
+
"@ory/argus": "0.11.1"
|
|
29
34
|
},
|
|
30
35
|
"devDependencies": {
|
|
31
36
|
"typescript": "^6.0.2",
|