@ory/openclaw 0.1.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,91 @@
1
+ # Ory Agent Plugin: OpenClaw
2
+
3
+ [Ory](https://ory.com) bundled into [OpenClaw](https://github.com/openclaw/openclaw): skills that scaffold Ory authentication into your codebase, a local Ory stack you can spin up in one command, and (when pointed at an Ory project) authentication, authorization, and audit for every tool OpenClaw runs.
4
+
5
+ ## Install
6
+
7
+ OpenClaw loads in-process plugins registered in `.openclaw/config.json`. Install and register in one step, with no prior `npm install` required:
8
+
9
+ ```bash
10
+ npx @ory/openclaw install # registers in .openclaw/config.json
11
+ npx @ory/openclaw install --project-dir <path>
12
+ npx @ory/openclaw uninstall
13
+ ```
14
+
15
+ `install` adds the Ory plugin and the Ory MCP server to your OpenClaw config non-destructively (existing entries are preserved) and drops the Ory skill catalog into `.openclaw/skills/`, registered under `skills.load.extraDirs` so OpenClaw discovers it.
16
+
17
+ ## Developer experience
18
+
19
+ This plugin is a productivity layer for Ory itself. You don't need a real Ory project, an account, or any prior Ory experience to start using it.
20
+
21
+ ### Skills for scaffolding Ory into your application
22
+
23
+ Ask OpenClaw to add Ory auth to your codebase, or invoke a skill directly. Each skill is a vetted, end-to-end playbook:
24
+
25
+ - **`ory-auth-setup`**: full project setup. Install the Ory CLI, create an Ory Network project, add Ory Elements, configure the SDK, build the auth pages, wire session middleware.
26
+ - **`ory-login-flow`**: login, registration, recovery, verification, and settings pages with Ory Elements. Next.js App Router and React SPA variants.
27
+ - **`ory-social-login`**: Google, GitHub, Apple, Microsoft, Discord, and other OIDC providers with Jsonnet data mappers.
28
+ - **`ory-local-dev`**: drive the local Ory stack (below) from within OpenClaw to prototype and test against without a remote project.
29
+
30
+ Skills are versioned with the plugin so guidance stays in sync as Ory APIs evolve.
31
+
32
+ ### Ory MCP server
33
+
34
+ Bundled and registered automatically. It exposes the Ory CLI and the Ory Network REST API as MCP tools so OpenClaw can manage identities, OAuth2 clients, projects, permission tuples, and configuration without ever leaving the chat. Useful for seeding test data, verifying a scaffolded integration, or running one-off admin tasks.
35
+
36
+ ### Local Ory stack in one command
37
+
38
+ From OpenClaw's skill picker:
39
+
40
+ ```
41
+ ory-local-up # start a local Ory instance in Docker
42
+ ory-local-down # tear it all down
43
+ ```
44
+
45
+ Or via the CLI: `npx ory-openclaw local up | down`.
46
+
47
+ `local up` runs a local Ory instance in Docker, covering everything the plugin and your scaffolded application need. It also brings up a login UI on `:3000` and Jaeger on `:16686`, all reachable through `http://localhost:4000`. A test user identity is seeded and the credentials are printed for you. Use it to:
48
+
49
+ - **Learn Ory hands-on** without signing up for a hosted project.
50
+ - **Prototype** flows (login, social, MFA, recovery, permission tuples) against a real Ory backend in your local dev loop.
51
+ - **Test** an auth integration end-to-end before pushing anything to a real environment.
52
+ - **Develop** your application against the same identity, OAuth2, and permission surfaces you'll ship with.
53
+
54
+ Point `ORY_PROJECT_URL` at `http://localhost:4000` (or run `npx ory-openclaw configure`) and the security features below run against the local stack.
55
+
56
+ ## Configure
57
+
58
+ ```bash
59
+ npx ory-openclaw configure --project-url https://<id>.projects.oryapis.com --api-key ory_pat_...
60
+ ```
61
+
62
+ Config is saved to `~/.config/ory-agent-plugins/config.json` and shared across every Ory agent plugin on the machine. Without it the plugin still loads cleanly and runs in **pass-through mode**: skills work, but nothing is blocked.
63
+
64
+ ## Agent security (Argus)
65
+
66
+ Once the plugin is pointed at an Ory project (local or hosted), OpenClaw's session and every tool call are governed by Ory.
67
+
68
+ - **Authentication.** Two identities. The human at the keyboard (the **user**) authenticates interactively via Ory Identities when `ORY_AUTH_GATE=1`; tokens refresh and a `user.auth` audit span is emitted at every session start. The OpenClaw process (the **agent**) gets its own OAuth2 identity, self-registered via Dynamic Client Registration on first run.
69
+ - **Authorization.** Before any tool runs, the plugin checks Ory Permissions against the user's subject and blocks the tool call on `deny`. MCP tool calls additionally get a server-level check.
70
+ - **Audit.** Every decision (allow, deny, fallback) is recorded as a structured trace span: NDJSON file output and/or OTLP/HTTP export to Jaeger, Honeycomb, Grafana, and similar collectors. The user-to-agent delegation is written to Ory as a Zanzibar tuple so "agent X acting on behalf of user Y" stays queryable after tokens expire.
71
+
72
+ The plugin is **fail-open** on its own infrastructure failures (network errors, rate limits, missing config), so enforcement is only as strong as your tuples; grant explicit `invoke` relations for the tools each user should be able to run.
73
+
74
+ ## CLI
75
+
76
+ ```
77
+ npx ory-openclaw install | uninstall [--project-dir <path>]
78
+ npx ory-openclaw configure [--project-url <url>] [--api-key <key>] [--audit-only]
79
+ npx ory-openclaw agent <status|unregister> Manage the agent's OAuth2 identity
80
+ npx ory-openclaw local <up|down|status|seed|logs|env|configure|reset>
81
+ npx ory-openclaw watch [<trace-file>]
82
+ npx ory-openclaw status [--project-dir <path>]
83
+ ```
84
+
85
+ ## Links
86
+
87
+ - [ory.com](https://ory.com)
88
+
89
+ ## License
90
+
91
+ Apache-2.0
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Materialize / clean the Ory skill catalog and command-skills for the
3
+ * OpenClaw plugin. The 4 guide skills (auth-setup, login-flow, social-login,
4
+ * local-dev) plus the 2 local-stack commands (rendered as user-invocable
5
+ * skills) land at `<projectDir>/.openclaw/skills/<name>/SKILL.md`.
6
+ *
7
+ * The skills directory's absolute path is registered in the OpenClaw config
8
+ * under `skills.load.extraDirs` so the harness picks the skills up even when
9
+ * its default workspace discovery doesn't cover this location.
10
+ */
11
+ export declare function installOpenclawOryAssets(projectDir: string): void;
12
+ export declare function uninstallOpenclawOryAssets(projectDir: string): void;
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /**
3
+ * Materialize / clean the Ory skill catalog and command-skills for the
4
+ * OpenClaw plugin. The 4 guide skills (auth-setup, login-flow, social-login,
5
+ * local-dev) plus the 2 local-stack commands (rendered as user-invocable
6
+ * skills) land at `<projectDir>/.openclaw/skills/<name>/SKILL.md`.
7
+ *
8
+ * The skills directory's absolute path is registered in the OpenClaw config
9
+ * under `skills.load.extraDirs` so the harness picks the skills up even when
10
+ * its default workspace discovery doesn't cover this location.
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.installOpenclawOryAssets = installOpenclawOryAssets;
47
+ exports.uninstallOpenclawOryAssets = uninstallOpenclawOryAssets;
48
+ const fs = __importStar(require("node:fs"));
49
+ const path = __importStar(require("node:path"));
50
+ const argus_1 = require("@ory/argus");
51
+ const RENDER_OPTS = {
52
+ binName: "ory-openclaw",
53
+ packageName: "@ory/openclaw",
54
+ };
55
+ const CONFIG_DIR = ".openclaw";
56
+ function configDir(projectDir) {
57
+ return path.join(projectDir, CONFIG_DIR);
58
+ }
59
+ function configPath(projectDir) {
60
+ return path.join(configDir(projectDir), "config.json");
61
+ }
62
+ function skillsDir(projectDir) {
63
+ return path.join(configDir(projectDir), "skills");
64
+ }
65
+ /** Write the absolute skills dir into `skills.load.extraDirs` (deduped). */
66
+ function addExtraDir(projectDir, absDir) {
67
+ const file = configPath(projectDir);
68
+ const config = (0, argus_1.readJsonFile)(file);
69
+ const skills = (config.skills ?? {});
70
+ const load = (skills.load ?? {});
71
+ const dirs = (load.extraDirs ?? []);
72
+ const next = [...dirs.filter((d) => d !== absDir), absDir];
73
+ load.extraDirs = next;
74
+ skills.load = load;
75
+ config.skills = skills;
76
+ fs.mkdirSync(path.dirname(file), { recursive: true });
77
+ fs.writeFileSync(file, JSON.stringify(config, null, 2) + "\n");
78
+ }
79
+ /** Remove the absolute skills dir from `skills.load.extraDirs`. */
80
+ function removeExtraDir(projectDir, absDir) {
81
+ const file = configPath(projectDir);
82
+ if (!fs.existsSync(file))
83
+ return;
84
+ const config = (0, argus_1.readJsonFile)(file);
85
+ const skills = (config.skills ?? {});
86
+ const load = (skills.load ?? {});
87
+ const dirs = (load.extraDirs ?? []);
88
+ const next = dirs.filter((d) => d !== absDir);
89
+ if (next.length === 0) {
90
+ delete load.extraDirs;
91
+ }
92
+ else {
93
+ load.extraDirs = next;
94
+ }
95
+ if (Object.keys(load).length === 0)
96
+ delete skills.load;
97
+ if (Object.keys(skills).length === 0)
98
+ delete config.skills;
99
+ fs.writeFileSync(file, JSON.stringify(config, null, 2) + "\n");
100
+ }
101
+ function installOpenclawOryAssets(projectDir) {
102
+ const dir = skillsDir(projectDir);
103
+ fs.mkdirSync(dir, { recursive: true });
104
+ const guideSkills = (0, argus_1.renderOrySkills)("openclaw", RENDER_OPTS);
105
+ const commandSkills = (0, argus_1.renderOryCommands)("openclaw", RENDER_OPTS).map(argus_1.commandToSkill);
106
+ (0, argus_1.writeSkillTree)(dir, [...guideSkills, ...commandSkills]);
107
+ addExtraDir(projectDir, path.resolve(dir));
108
+ }
109
+ function safeRmEmpty(dir) {
110
+ try {
111
+ if (fs.existsSync(dir) && fs.readdirSync(dir).length === 0) {
112
+ fs.rmdirSync(dir);
113
+ }
114
+ }
115
+ catch {
116
+ /* ignore */
117
+ }
118
+ }
119
+ function uninstallOpenclawOryAssets(projectDir) {
120
+ const dir = skillsDir(projectDir);
121
+ if (fs.existsSync(dir)) {
122
+ (0, argus_1.removeSkillDirs)(dir, [...argus_1.ORY_SKILL_NAMES, ...argus_1.ORY_COMMAND_SKILL_NAMES]);
123
+ safeRmEmpty(dir);
124
+ }
125
+ removeExtraDir(projectDir, path.resolve(dir));
126
+ }
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Main CLI for @ory/openclaw.
4
+ *
5
+ * Usage:
6
+ * npx ory-openclaw install [--project-dir <path>] Register plugin in OpenClaw config
7
+ * npx ory-openclaw uninstall Remove plugin from OpenClaw config
8
+ * npx ory-openclaw configure Set or view Ory project URL and API key
9
+ * npx ory-openclaw status Show plugin status
10
+ * npx ory-openclaw watch [trace-file] Watch live trace output
11
+ */
12
+ export {};
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Main CLI for @ory/openclaw.
5
+ *
6
+ * Usage:
7
+ * npx ory-openclaw install [--project-dir <path>] Register plugin in OpenClaw config
8
+ * npx ory-openclaw uninstall Remove plugin from OpenClaw config
9
+ * npx ory-openclaw configure Set or view Ory project URL and API key
10
+ * npx ory-openclaw status Show plugin status
11
+ * npx ory-openclaw watch [trace-file] Watch live trace output
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ const path = __importStar(require("node:path"));
48
+ const fs = __importStar(require("node:fs"));
49
+ const argus_1 = require("@ory/argus");
50
+ const assets_js_1 = require("./assets.js");
51
+ const PLUGIN_MODULE = "@ory/openclaw";
52
+ const CONFIG_DIR = ".openclaw";
53
+ function main() {
54
+ const [command, ...args] = process.argv.slice(2);
55
+ switch (command) {
56
+ case "install":
57
+ install(args);
58
+ break;
59
+ case "uninstall":
60
+ uninstall(args);
61
+ break;
62
+ case "configure":
63
+ (0, argus_1.runConfigureCommand)("ory-openclaw", args);
64
+ break;
65
+ case "agent":
66
+ (0, argus_1.runAgentCommand)("ory-openclaw", args).then((code) => process.exit(code), (err) => {
67
+ console.error(err.message ?? err);
68
+ process.exit(1);
69
+ });
70
+ break;
71
+ case "status":
72
+ status(args);
73
+ break;
74
+ case "local":
75
+ (0, argus_1.runLocalCommand)("ory-openclaw", args).catch((err) => {
76
+ console.error(err.message ?? err);
77
+ process.exit(1);
78
+ });
79
+ break;
80
+ case "watch":
81
+ (0, argus_1.runWatchCommand)(args);
82
+ break;
83
+ case "help":
84
+ case "--help":
85
+ case "-h":
86
+ case undefined:
87
+ help();
88
+ break;
89
+ default:
90
+ console.error(`Unknown command: ${command}`);
91
+ help();
92
+ process.exit(1);
93
+ }
94
+ }
95
+ function parseProjectDir(args) {
96
+ const idx = args.indexOf("--project-dir");
97
+ if (idx !== -1 && args[idx + 1])
98
+ return args[idx + 1];
99
+ return process.cwd();
100
+ }
101
+ function getOpenClawConfigPath(projectDir) {
102
+ return path.join(projectDir, CONFIG_DIR, "config.json");
103
+ }
104
+ function ensureConfigDir(projectDir) {
105
+ const dir = path.join(projectDir, CONFIG_DIR);
106
+ if (!fs.existsSync(dir)) {
107
+ fs.mkdirSync(dir, { recursive: true });
108
+ }
109
+ }
110
+ function install(args) {
111
+ const projectDir = parseProjectDir(args);
112
+ const configPath = getOpenClawConfigPath(projectDir);
113
+ ensureConfigDir(projectDir);
114
+ const config = (0, argus_1.readJsonFile)(configPath);
115
+ const plugins = (config.plugins ?? []).filter((p) => p !== PLUGIN_MODULE);
116
+ plugins.push(PLUGIN_MODULE);
117
+ config.plugins = plugins;
118
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
119
+ (0, assets_js_1.installOpenclawOryAssets)(projectDir);
120
+ console.log(`Ory plugin registered in ${configPath}`);
121
+ console.log(` Module: ${PLUGIN_MODULE}`);
122
+ console.log(` Skills + commands installed under ${path.join(projectDir, CONFIG_DIR, "skills")}`);
123
+ (0, argus_1.printEnvHelp)("ory-openclaw");
124
+ }
125
+ function uninstall(args) {
126
+ const projectDir = parseProjectDir(args);
127
+ const configPath = getOpenClawConfigPath(projectDir);
128
+ if (!fs.existsSync(configPath)) {
129
+ console.log("No OpenClaw config found. Nothing to uninstall.");
130
+ return;
131
+ }
132
+ (0, assets_js_1.uninstallOpenclawOryAssets)(projectDir);
133
+ const config = (0, argus_1.readJsonFile)(configPath);
134
+ const plugins = (config.plugins ?? []).filter((p) => p !== PLUGIN_MODULE);
135
+ if (plugins.length === 0) {
136
+ delete config.plugins;
137
+ }
138
+ else {
139
+ config.plugins = plugins;
140
+ }
141
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
142
+ console.log(`Ory plugin and skills removed from ${configPath}`);
143
+ }
144
+ function status(args) {
145
+ const projectDir = parseProjectDir(args);
146
+ const configPath = getOpenClawConfigPath(projectDir);
147
+ console.log("Ory Agent Plugin Status (OpenClaw)");
148
+ console.log("===================================");
149
+ console.log("");
150
+ // OpenClaw-specific: check plugin registration
151
+ const config = (0, argus_1.readJsonFile)(configPath);
152
+ const plugins = (config.plugins ?? []);
153
+ const registered = plugins.includes(PLUGIN_MODULE);
154
+ console.log("Plugin Registration:");
155
+ console.log(` Config file: ${configPath}`);
156
+ console.log(` Plugin registered: ${registered ? "yes" : "NO"}`);
157
+ if (registered) {
158
+ console.log(` Module: ${PLUGIN_MODULE}`);
159
+ }
160
+ // Shared Ory config
161
+ console.log("");
162
+ console.log("Ory Configuration:");
163
+ const resolved = (0, argus_1.resolveConfig)();
164
+ const oryConfigPath = (0, argus_1.getConfigPath)();
165
+ console.log(` Config file: ${oryConfigPath}`);
166
+ console.log(` Project URL: ${resolved.projectUrl ?? "NOT SET"} [source: ${resolved.projectUrlSource}]`);
167
+ console.log(` API Key: ${resolved.apiKey ? "(set)" : "NOT SET"} [source: ${resolved.apiKeySource}]`);
168
+ console.log("");
169
+ console.log("OpenClaw Integration:");
170
+ console.log(" Blocking support: YES (before_tool_call can deny tool execution)");
171
+ console.log(" Hooks registered: session_start, before_tool_call, after_tool_call");
172
+ (0, argus_1.printEnvironment)();
173
+ (0, argus_1.printLogTail)();
174
+ }
175
+ function help() {
176
+ console.log(`
177
+ ory-openclaw — Ory plugin for OpenClaw
178
+
179
+ Usage:
180
+ npx ory-openclaw <command> [options]
181
+
182
+ Commands:
183
+ install [--project-dir <path>] Register the Ory plugin in OpenClaw config
184
+ uninstall [--project-dir <path>] Remove the Ory plugin from OpenClaw config
185
+ configure Set or view Ory project URL and API key
186
+ status [--project-dir <path>] Show plugin configuration and status
187
+ watch [trace-file] Watch live trace output
188
+ local <cmd> Manage local Ory dev environment (up, down, status, seed, ...)
189
+
190
+ After installing, the plugin hooks into these OpenClaw lifecycle events:
191
+ session_start Verify agent session via Ory Identities
192
+ before_tool_call Check tool permissions via Ory Permissions (can block)
193
+ after_tool_call Record tool completion trace
194
+
195
+ Examples:
196
+ npx ory-openclaw install # Register in current directory
197
+ npx ory-openclaw configure --project-url https://my.oryapis.com --api-key ory_pat_...
198
+ npx ory-openclaw status # Check configuration
199
+ npx ory-openclaw watch # Watch trace output in real-time
200
+ npx ory-openclaw uninstall # Remove plugin
201
+ `);
202
+ }
203
+ main();
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Setup CLI for the Ory OpenClaw plugin.
4
+ *
5
+ * Usage:
6
+ * npx ory-openclaw-setup # Auto-detect and configure
7
+ * npx ory-openclaw-setup --project-dir /path/to/repo
8
+ * npx ory-openclaw-setup --print # Print config to stdout without writing
9
+ * npx ory-openclaw-setup --uninstall # Remove Ory plugin from config
10
+ */
11
+ export {};
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Setup CLI for the Ory OpenClaw plugin.
5
+ *
6
+ * Usage:
7
+ * npx ory-openclaw-setup # Auto-detect and configure
8
+ * npx ory-openclaw-setup --project-dir /path/to/repo
9
+ * npx ory-openclaw-setup --print # Print config to stdout without writing
10
+ * npx ory-openclaw-setup --uninstall # Remove Ory plugin from config
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ const fs = __importStar(require("node:fs"));
47
+ const path = __importStar(require("node:path"));
48
+ const argus_1 = require("@ory/argus");
49
+ const assets_js_1 = require("./assets.js");
50
+ const PLUGIN_MODULE = "@ory/openclaw";
51
+ const CONFIG_DIR = ".openclaw";
52
+ function getConfigPath(args) {
53
+ return path.join(args.projectDir, CONFIG_DIR, "config.json");
54
+ }
55
+ function ensureConfigDir(args) {
56
+ const dir = path.join(args.projectDir, CONFIG_DIR);
57
+ if (!fs.existsSync(dir)) {
58
+ fs.mkdirSync(dir, { recursive: true });
59
+ }
60
+ }
61
+ function mergePlugin(existing) {
62
+ const merged = { ...existing };
63
+ const plugins = (merged.plugins ?? []).filter((p) => p !== PLUGIN_MODULE);
64
+ plugins.push(PLUGIN_MODULE);
65
+ merged.plugins = plugins;
66
+ return merged;
67
+ }
68
+ function removePlugin(existing) {
69
+ const merged = { ...existing };
70
+ const plugins = (merged.plugins ?? []).filter((p) => p !== PLUGIN_MODULE);
71
+ if (plugins.length === 0) {
72
+ delete merged.plugins;
73
+ }
74
+ else {
75
+ merged.plugins = plugins;
76
+ }
77
+ return merged;
78
+ }
79
+ function main() {
80
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
81
+ (0, argus_1.printSetupHelp)("ory-openclaw-setup", "OpenClaw");
82
+ process.exit(0);
83
+ }
84
+ const args = (0, argus_1.parseSetupArgs)();
85
+ if (args.print) {
86
+ console.log(JSON.stringify({ plugins: [PLUGIN_MODULE] }, null, 2));
87
+ return;
88
+ }
89
+ const configPath = getConfigPath(args);
90
+ const existing = (0, argus_1.readJsonFile)(configPath);
91
+ if (args.uninstall) {
92
+ if (!fs.existsSync(configPath)) {
93
+ console.log("No OpenClaw config found. Nothing to uninstall.");
94
+ return;
95
+ }
96
+ (0, assets_js_1.uninstallOpenclawOryAssets)(args.projectDir);
97
+ let updated = removePlugin(existing);
98
+ updated = (0, argus_1.removeMcpServer)(updated);
99
+ (0, argus_1.writeJsonFile)(configPath, updated);
100
+ console.log(`Removed Ory plugin, MCP server, and skills from ${configPath}`);
101
+ return;
102
+ }
103
+ ensureConfigDir(args);
104
+ let merged = mergePlugin(existing);
105
+ merged = (0, argus_1.mergeMcpServer)(merged);
106
+ (0, argus_1.writeJsonFile)(configPath, merged);
107
+ (0, assets_js_1.installOpenclawOryAssets)(args.projectDir);
108
+ console.log(`Ory plugin and MCP server configured in ${configPath}`);
109
+ console.log(`Ory skills installed to ${path.join(args.projectDir, CONFIG_DIR, "skills")}`);
110
+ (0, argus_1.printNextSteps)("OpenClaw", "npx ory-openclaw-setup --uninstall");
111
+ }
112
+ main();
@@ -0,0 +1,4 @@
1
+ export { createOryPlugin } from "./plugin.js";
2
+ export type { OpenClawPluginEntry, OpenClawPluginApi, HookEvent, HookHandler, HookRegistrationOpts, HookResult, BeforeToolCallContext, AfterToolCallContext, SessionStartContext, BeforeAgentStartContext, SessionEndContext, } from "./types.js";
3
+ declare const _default: import("./types.js").OpenClawPluginEntry;
4
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createOryPlugin = void 0;
4
+ var plugin_js_1 = require("./plugin.js");
5
+ Object.defineProperty(exports, "createOryPlugin", { enumerable: true, get: function () { return plugin_js_1.createOryPlugin; } });
6
+ // Default export for OpenClaw plugin discovery.
7
+ // When OpenClaw loads this module, it calls `register(api)` on the default export.
8
+ const plugin_js_2 = require("./plugin.js");
9
+ exports.default = (0, plugin_js_2.createOryPlugin)();
@@ -0,0 +1,28 @@
1
+ import { OryAgentClient, ensureUserAuthenticated, ensureAgentIdentity, ensureSubAgentIdentity } from "@ory/argus";
2
+ import type { OpenClawPluginEntry } from "./types.js";
3
+ export interface CreateOryPluginDeps {
4
+ /** Test injection point for the user auth gate. */
5
+ authGate?: typeof ensureUserAuthenticated;
6
+ /** Test injection point for the agent identity gate. */
7
+ agentGate?: typeof ensureAgentIdentity;
8
+ /** Test injection point for the sub-agent identity resolver. */
9
+ subAgentGate?: typeof ensureSubAgentIdentity;
10
+ }
11
+ /**
12
+ * Create the Ory plugin entry for OpenClaw.
13
+ *
14
+ * OpenClaw plugins export { id, name, register(api) } where register
15
+ * receives a PluginApi for registering hooks. The `before_tool_call`
16
+ * hook can return `{ block: true }` to deny tool execution — this
17
+ * makes permission checks enforceable, unlike harnesses that can only
18
+ * log denials.
19
+ *
20
+ * The `session_start` hook returns `Promise<void>` so the auth gate is
21
+ * advisory at session start: the gate still runs to emit the audit span,
22
+ * refresh tokens, and prompt for the project URL when interactive, but
23
+ * cannot hard-block the session.
24
+ */
25
+ export declare function createOryPlugin(clientOrConfig?: OryAgentClient | {
26
+ projectUrl: string;
27
+ apiKey?: string;
28
+ }, deps?: CreateOryPluginDeps): OpenClawPluginEntry;