@ory/openrouter-agent 0.0.0-bootstrap.0 → 1.0.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/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # @ory/openrouter-agent
2
+
3
+ Ory Agent Security for the [OpenRouter Agent SDK](https://openrouter.ai/docs/agent-sdk/overview).
4
+
5
+ It authenticates each agent session, authorizes every client-side tool call against Ory
6
+ Permissions, and records privacy-safe invocation activity through OpenRouter lifecycle hooks.
7
+
8
+ ```bash
9
+ npm install @ory/openrouter-agent
10
+ ```
11
+
12
+ ```ts
13
+ import { OpenRouter } from "@openrouter/agent";
14
+ import { createOryHooks } from "@ory/openrouter-agent";
15
+
16
+ const openrouter = new OpenRouter({
17
+ apiKey: process.env.OPENROUTER_API_KEY,
18
+ });
19
+
20
+ const result = openrouter.callModel({
21
+ model: "openai/gpt-5.4",
22
+ input: "Inspect the deployment configuration",
23
+ tools,
24
+ hooks: createOryHooks(),
25
+ });
26
+
27
+ console.log(await result.getText());
28
+ ```
29
+
30
+ `createOryHooks()` returns inline `SessionStart`, `PreToolUse`, `PostToolUse`,
31
+ `PostToolUseFailure`, and `SessionEnd` hooks. In **observe** mode (default), denies are logged
32
+ but tools run. In **enforce** mode, a deny returns OpenRouter's native `{ block: reason }`
33
+ result, so the client-side tool does not execute.
34
+
35
+ For a multi-user service, resolve the acting user from the run's session context:
36
+
37
+ ```ts
38
+ const hooks = createOryHooks({
39
+ subjectFromContext: ({ sessionId }) => usersBySession.get(sessionId)?.id,
40
+ });
41
+ ```
42
+
43
+ OpenRouter-hosted server tools execute remotely and do not cross the SDK's client-side
44
+ `PreToolUse` boundary. Restrict those tools before the model request or enforce their access
45
+ with OpenRouter-side policy. Local tools, including locally wrapped MCP tools, are gated.
46
+ Child agents do not inherit their parent's hooks; pass `createOryHooks()` to each child run
47
+ that should receive its own Ory session identity and tool gate.
48
+
49
+ This package depends only on `@ory/argus`; its OpenRouter hook types are defined locally.
50
+ Credentials come from the shared `~/.config/ory-agent-plugins/config.json`.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Ory Agent Security for the OpenRouter Agent SDK.
3
+ *
4
+ * Pass {@link createOryHooks} to `callModel({ hooks })`. The returned inline
5
+ * hooks authenticate each session, authorize every client-side tool before it
6
+ * executes, and record success or failure through `@ory/argus`.
7
+ */
8
+ import { OryAgentClient } from "@ory/argus";
9
+ import type { LifecycleHookContext, OryOpenRouterHooks } from "./types.js";
10
+ export interface OryOpenRouterOptions {
11
+ /** Client to use. Defaults to `OryAgentClient.fromEnv("openrouter-agent")`. */
12
+ client?: OryAgentClient;
13
+ /** Override the Ory project URL for the session gates. */
14
+ projectUrl?: string;
15
+ /** Whether a denied tool is hard-blocked. Default true. */
16
+ canBlock?: boolean;
17
+ /** Resolve the acting user for a run from OpenRouter's lifecycle context. */
18
+ subjectFromContext?: (context: LifecycleHookContext) => string | undefined;
19
+ }
20
+ /** Build inline lifecycle hooks for `OpenRouter.callModel({ hooks })`. */
21
+ export declare function createOryHooks(options?: OryOpenRouterOptions): OryOpenRouterHooks;
22
+ export { OryAgentClient } from "@ory/argus";
23
+ export type { HookEntry, HookHandler, LifecycleHookContext, OryOpenRouterHooks, PostToolUseFailurePayload, PostToolUsePayload, PreToolUsePayload, PreToolUseResult, SessionEndPayload, SessionStartPayload, SessionUsageTotals, } from "./types.js";
package/dist/index.js ADDED
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ /**
3
+ * Ory Agent Security for the OpenRouter Agent SDK.
4
+ *
5
+ * Pass {@link createOryHooks} to `callModel({ hooks })`. The returned inline
6
+ * hooks authenticate each session, authorize every client-side tool before it
7
+ * executes, and record success or failure through `@ory/argus`.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.OryAgentClient = void 0;
11
+ exports.createOryHooks = createOryHooks;
12
+ const argus_1 = require("@ory/argus");
13
+ const HARNESS = "openrouter-agent";
14
+ /** Build inline lifecycle hooks for `OpenRouter.callModel({ hooks })`. */
15
+ function createOryHooks(options = {}) {
16
+ const client = options.client ?? argus_1.OryAgentClient.fromEnv(HARNESS);
17
+ const canBlock = options.canBlock ?? true;
18
+ const sessionStarters = new Map();
19
+ const starterFor = (sessionId) => {
20
+ const existing = sessionStarters.get(sessionId);
21
+ if (existing)
22
+ return existing;
23
+ const starter = (0, argus_1.createSessionStarter)(client, {
24
+ harness: HARNESS,
25
+ projectUrl: options.projectUrl,
26
+ });
27
+ sessionStarters.set(sessionId, starter);
28
+ return starter;
29
+ };
30
+ const inContext = (context, work) => (0, argus_1.withHookContext)(client, { sessionId: context.sessionId }, () => (0, argus_1.runWithUserSubject)(options.subjectFromContext?.(context), work));
31
+ return {
32
+ SessionStart: [{
33
+ handler: (_payload, context) => inContext(context, () => starterFor(context.sessionId)()),
34
+ }],
35
+ PreToolUse: [{
36
+ handler: (payload, context) => inContext(context, async () => {
37
+ await starterFor(context.sessionId)();
38
+ const result = await (0, argus_1.gate)(client, {
39
+ harness: HARNESS,
40
+ toolName: payload.toolName,
41
+ toolArgs: payload.toolInput,
42
+ canBlock,
43
+ });
44
+ return result.kind === "deny" && result.blocked
45
+ ? { block: result.denialMessage ?? "Ory: permission denied" }
46
+ : undefined;
47
+ }),
48
+ }],
49
+ PostToolUse: [{
50
+ handler: (payload, context) => inContext(context, () => {
51
+ (0, argus_1.complete)(client, {
52
+ toolName: payload.toolName,
53
+ input: payload.toolInput,
54
+ output: payload.toolOutput,
55
+ });
56
+ }),
57
+ }],
58
+ PostToolUseFailure: [{
59
+ handler: (payload, context) => inContext(context, () => {
60
+ (0, argus_1.fail)(client, {
61
+ toolName: payload.toolName,
62
+ input: payload.toolInput,
63
+ error: payload.error,
64
+ });
65
+ }),
66
+ }],
67
+ SessionEnd: [{
68
+ handler: (_payload, context) => inContext(context, () => {
69
+ sessionStarters.delete(context.sessionId);
70
+ }),
71
+ }],
72
+ };
73
+ }
74
+ var argus_2 = require("@ory/argus");
75
+ Object.defineProperty(exports, "OryAgentClient", { enumerable: true, get: function () { return argus_2.OryAgentClient; } });
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Minimal OpenRouter Agent SDK lifecycle-hook shapes.
3
+ *
4
+ * These mirror `@openrouter/agent` without making the SDK a runtime dependency.
5
+ */
6
+ export interface LifecycleHookContext {
7
+ readonly signal: AbortSignal;
8
+ readonly hookName: string;
9
+ readonly sessionId: string;
10
+ }
11
+ export type HookHandler<Payload, Result = undefined> = (payload: Payload, context: LifecycleHookContext) => Result | void | Promise<Result | void>;
12
+ export interface HookEntry<Payload, Result = undefined> {
13
+ readonly handler: HookHandler<Payload, Result>;
14
+ readonly matcher?: string | RegExp | ((toolName: string) => boolean);
15
+ readonly filter?: (payload: Payload) => boolean;
16
+ }
17
+ export interface SessionStartPayload {
18
+ readonly config?: Record<string, unknown>;
19
+ }
20
+ export interface ModelCallUsage {
21
+ readonly inputTokens: number;
22
+ readonly outputTokens: number;
23
+ readonly totalTokens: number;
24
+ readonly cachedTokens: number;
25
+ readonly reasoningTokens: number;
26
+ readonly cost?: number;
27
+ }
28
+ export interface SessionUsageTotals extends ModelCallUsage {
29
+ readonly modelCalls: number;
30
+ }
31
+ export interface SessionEndPayload {
32
+ readonly reason: "user" | "error" | "max_turns" | "complete";
33
+ readonly totalUsage?: SessionUsageTotals;
34
+ }
35
+ export interface PreToolUsePayload {
36
+ readonly toolName: string;
37
+ readonly toolInput: Record<string, unknown>;
38
+ }
39
+ export interface PreToolUseResult {
40
+ readonly mutatedInput?: Record<string, unknown>;
41
+ readonly block?: boolean | string;
42
+ }
43
+ export interface PostToolUsePayload {
44
+ readonly toolName: string;
45
+ readonly toolInput: Record<string, unknown>;
46
+ readonly toolOutput: unknown;
47
+ readonly durationMs: number;
48
+ }
49
+ export interface PostToolUseFailurePayload {
50
+ readonly toolName: string;
51
+ readonly toolInput: Record<string, unknown>;
52
+ readonly error: unknown;
53
+ }
54
+ /** Inline hook configuration accepted by `callModel({ hooks })`. */
55
+ export interface OryOpenRouterHooks {
56
+ readonly SessionStart: HookEntry<SessionStartPayload>[];
57
+ readonly PreToolUse: HookEntry<PreToolUsePayload, PreToolUseResult>[];
58
+ readonly PostToolUse: HookEntry<PostToolUsePayload>[];
59
+ readonly PostToolUseFailure: HookEntry<PostToolUseFailurePayload>[];
60
+ readonly SessionEnd: HookEntry<SessionEndPayload>[];
61
+ }
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Minimal OpenRouter Agent SDK lifecycle-hook shapes.
4
+ *
5
+ * These mirror `@openrouter/agent` without making the SDK a runtime dependency.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1 +1,50 @@
1
- {"name":"@ory/openrouter-agent","version":"0.0.0-bootstrap.0","license":"Apache-2.0","description":"Bootstrap package for trusted publishing"}
1
+ {
2
+ "name": "@ory/openrouter-agent",
3
+ "version": "1.0.0",
4
+ "description": "Ory Agent Security for the OpenRouter Agent SDK - per-tool authorization, activity auditing, and session identity via lifecycle hooks. Built on @ory/argus.",
5
+ "license": "Apache-2.0",
6
+ "publishConfig": {
7
+ "access": "public",
8
+ "registry": "https://registry.npmjs.org/",
9
+ "provenance": true
10
+ },
11
+ "reova": {
12
+ "enabled": true,
13
+ "endpoint": "https://telemetry.reo.dev/data"
14
+ },
15
+ "main": "dist/index.js",
16
+ "types": "dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "!dist/**/*.tsbuildinfo"
26
+ ],
27
+ "keywords": [
28
+ "ory",
29
+ "openrouter",
30
+ "agent-sdk",
31
+ "authorization",
32
+ "agent",
33
+ "ai"
34
+ ],
35
+ "dependencies": {
36
+ "reova": "^0.7.0",
37
+ "@ory/argus": "1.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "typescript": "^6.0.2",
41
+ "vitest": "4.1.4"
42
+ },
43
+ "scripts": {
44
+ "build": "tsc",
45
+ "clean": "rm -rf dist *.tsbuildinfo",
46
+ "test": "vitest run",
47
+ "test:watch": "vitest",
48
+ "typecheck": "tsc --noEmit"
49
+ }
50
+ }