@ory/continue 0.10.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 +120 -0
- package/dist/cli/assets.d.ts +23 -0
- package/dist/cli/assets.js +92 -0
- package/dist/cli/main.d.ts +16 -0
- package/dist/cli/main.js +182 -0
- package/dist/cli/setup.d.ts +18 -0
- package/dist/cli/setup.js +114 -0
- package/dist/handlers.d.ts +17 -0
- package/dist/handlers.js +567 -0
- package/dist/hook.d.ts +13 -0
- package/dist/hook.js +76 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +9 -0
- package/dist/settings.d.ts +16 -0
- package/dist/settings.js +78 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.js +2 -0
- package/package.json +83 -0
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Ory Agent Plugin: Continue CLI
|
|
2
|
+
|
|
3
|
+
[Ory](https://ory.com) bundled into [Continue](https://continue.dev)'s `cn` CLI: skills and slash commands 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 Continue runs.
|
|
4
|
+
|
|
5
|
+
You don't need an Ory account or any prior Ory experience to start.
|
|
6
|
+
|
|
7
|
+
This integration targets the **`cn` CLI** (not the Continue IDE extension) and is verified against `@continuedev/cli`.
|
|
8
|
+
|
|
9
|
+
## New to Ory?
|
|
10
|
+
|
|
11
|
+
[Ory](https://www.ory.com/docs/) is an open-source identity and access platform — login, registration, sessions, social sign-in, multi-factor auth, and fine-grained permissions, so you don't have to build any of that yourself. Two things make it easy to try with no prior experience:
|
|
12
|
+
|
|
13
|
+
- **Ory Elements** are prebuilt, themeable UI components for the auth pages. The scaffolding skills wire them into your app for you.
|
|
14
|
+
- **The local Ory stack** is a complete Ory running on your laptop in Docker — no account, no signup, no API key.
|
|
15
|
+
|
|
16
|
+
## What this plugin does
|
|
17
|
+
|
|
18
|
+
Two independent things, and you can use either on its own:
|
|
19
|
+
|
|
20
|
+
1. **Build auth into your app.** Have Continue scaffold Ory login, registration, social sign-in, and permissions into the project you're working on, backed by the local stack. This needs nothing but Docker.
|
|
21
|
+
2. **Govern the agent itself.** Authenticate Continue's own session and authorize every tool it runs against Ory Permissions, with a full audit trail. See [Agent security](#agent-security).
|
|
22
|
+
|
|
23
|
+
## Prerequisites
|
|
24
|
+
|
|
25
|
+
- [Continue](https://continue.dev) `cn` CLI installed
|
|
26
|
+
- Node.js **≥ 22**
|
|
27
|
+
- [Docker](https://docs.docker.com/get-docker/) (only needed for the local Ory stack)
|
|
28
|
+
- macOS or Linux. Windows works via WSL2.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx -y -p @ory/continue ory-continue install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Continue has no native extension-install command, so `install` writes the Ory hooks directly into `<project>/.continue/settings.json` and materializes the Ory skills under `<project>/.continue/skills/`. Continue surfaces each skill as a slash command automatically, so the local-stack commands (`/local-up`, `/local-down`, `/temporal-up`) ship as skills too. Confirm everything landed:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx -y -p @ory/continue ory-continue status
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`status` prints configuration, user and agent identity, per-tool permission coverage, hook/skill registration, and a tail of recent debug logs. Unconfigured fields show inline as `(unset)`.
|
|
43
|
+
|
|
44
|
+
Uninstall removes only the Ory hooks and skills, leaving the rest of your settings intact:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx -y -p @ory/continue ory-continue uninstall
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Quickstart (≈ 3 minutes)
|
|
51
|
+
|
|
52
|
+
From any project where you'd like Ory authentication, inside Continue:
|
|
53
|
+
|
|
54
|
+
1. **Start a local Ory instance.** Ask Continue *"start the local Ory stack"* or run `/local-up`. A banner prints the seeded test user's email and password — note them.
|
|
55
|
+
2. **Scaffold Ory into your project.** Ask Continue *"add Ory auth to this app"* (the `ory-auth-setup` skill). It installs Ory Elements, wires the SDK, and generates the login / registration / recovery / settings pages, all targeting the local stack.
|
|
56
|
+
3. **Sign in.** Start your app, visit the login page, and sign in with the seeded credentials. You now have a real Ory session backed by a real Ory stack — locally, offline, zero configuration.
|
|
57
|
+
|
|
58
|
+
That's the full Ory DX path. Continue to [Agent security](#agent-security) when you're ready to enforce.
|
|
59
|
+
|
|
60
|
+
## How the integration works
|
|
61
|
+
|
|
62
|
+
Continue runs the Ory plugin as a **subprocess hook**, the same way [Claude Code](https://github.com/anthropics/claude-code) does — and Continue reads hooks from both `.continue/settings.json` and `.claude/settings.json`. Each lifecycle event launches the hook binary with the event payload as JSON on stdin; the hook replies on stdout and signals a hard block with **exit code 2**.
|
|
63
|
+
|
|
64
|
+
The hooks wire into these phases:
|
|
65
|
+
|
|
66
|
+
- **SessionStart** — run the user and agent auth gates.
|
|
67
|
+
- **PreToolUse / PermissionRequest** — check the tool against Ory Permissions; deny blocks the call (exit code 2) in enforce mode.
|
|
68
|
+
- **SubagentStart / SubagentStop** — resolve a distinct identity for typed sub-agents and record their lifecycle.
|
|
69
|
+
- **PostToolUse / Stop / SessionEnd** — trace-only audit spans.
|
|
70
|
+
|
|
71
|
+
The plugin is **fail-open** on its own infrastructure failures (network errors, rate limits, missing config): the agent always starts, and enforcement is only as strong as your permission grants.
|
|
72
|
+
|
|
73
|
+
## Agent security
|
|
74
|
+
|
|
75
|
+
Once pointed at an Ory project (local or hosted), Continue's session and every tool call can be governed by Ory.
|
|
76
|
+
|
|
77
|
+
- **Authentication.** The human at the keyboard (the **user**) authenticates interactively via Ory Identities when user login is on (`ORY_USER_LOGIN=true`, off by default — browser PKCE flow on first session, persisted token thereafter). The Continue process (the **agent**) gets its own OAuth2 identity, self-registered via [Dynamic Client Registration (RFC 7591)](https://datatracker.ietf.org/doc/html/rfc7591) on first run.
|
|
78
|
+
- **Authorization.** Before any tool runs, the plugin checks [Ory Permissions](https://www.ory.com/docs/keto) (Zanzibar-style relations) against the user's subject and blocks on `deny`.
|
|
79
|
+
- **Audit.** Every decision is recorded as a structured trace span (NDJSON file and/or OTLP export).
|
|
80
|
+
|
|
81
|
+
### Permission modes: observe → enforce
|
|
82
|
+
|
|
83
|
+
After install the plugin runs in **observe mode**: every tool call is checked, but a deny is recorded as a `permission.observe_deny` audit span and the tool runs anyway. This lets you see what *would* be blocked first.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Grant the current user `use` on every built-in tool (idempotent):
|
|
87
|
+
npx -y -p @ory/continue ory-continue permissions bootstrap
|
|
88
|
+
|
|
89
|
+
# See allowed/denied per tool:
|
|
90
|
+
npx -y -p @ory/continue ory-continue permissions status
|
|
91
|
+
|
|
92
|
+
# Turn on hard blocking once the observe-mode logs look right:
|
|
93
|
+
npx -y -p @ory/continue ory-continue permissions enforce
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Switch back any time with `permissions observe`. To disable Ory entirely (audit logging only, no auth or checks), run `ory-continue configure --audit-only`.
|
|
97
|
+
|
|
98
|
+
## Pointing at a real Ory project
|
|
99
|
+
|
|
100
|
+
The Quickstart uses the local stack. To point at a hosted [Ory Network](https://console.ory.sh) project:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npx -y -p @ory/continue ory-continue configure \
|
|
104
|
+
--project-url https://<id>.projects.oryapis.com \
|
|
105
|
+
--oauth2-client-id <public OAuth2 client id>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`--oauth2-client-id` is required whenever `--project-url` is set — the user PKCE flow needs a public OAuth2 client registered with the four loopback redirect URIs (`http://127.0.0.1:47823..47826/callback`). See the [repo README](../../README.md) and [`AGENTS.md`](../../AGENTS.md) for the full environment-variable reference (`ORY_PROJECT_URL`, `ORY_USER_LOGIN`, `ORY_OAUTH2_CLIENT_ID`, agent-identity vars) and permission-mode semantics. Config is shared across every Ory agent plugin at `~/.config/ory-agent-plugins/config.json`.
|
|
109
|
+
|
|
110
|
+
Without configuration the plugin still loads cleanly and runs in **pass-through mode**: skills and their slash commands work, but nothing is blocked.
|
|
111
|
+
|
|
112
|
+
## Links
|
|
113
|
+
|
|
114
|
+
- [Ory documentation](https://www.ory.com/docs/)
|
|
115
|
+
- [Continue documentation](https://docs.continue.dev/)
|
|
116
|
+
- [Repo README](../../README.md) and [AGENTS.md](../../AGENTS.md) — full env-var and permission-mode reference
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
Apache-2.0
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Materialize / clean the Ory skill catalog for the Continue CLI plugin.
|
|
3
|
+
*
|
|
4
|
+
* Continue (`cn`) surfaces slash commands exclusively from skills: every
|
|
5
|
+
* `skills/<name>/SKILL.md` it discovers automatically becomes a slash command.
|
|
6
|
+
* It does NOT read a `.continue/commands/` directory. So both the guide skills
|
|
7
|
+
* and the local-stack commands (local-up / local-down / temporal-up) are
|
|
8
|
+
* written as skills under `<root>/skills/<name>/SKILL.md` — the commands are
|
|
9
|
+
* wrapped with `commandToSkill` so they show up as `/local-up` etc.
|
|
10
|
+
*
|
|
11
|
+
* All content is rendered from the canonical `@ory/argus` templates — never
|
|
12
|
+
* re-defined inline — so the guidance stays in sync across every harness.
|
|
13
|
+
*
|
|
14
|
+
* Verified against @continuedev/cli.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Write all Ory skills (guides + local-stack commands rendered as skills)
|
|
18
|
+
* under `<root>/skills/<name>/SKILL.md`. For the manual-setup path that's
|
|
19
|
+
* `<projectDir>/.continue`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function installContinueOryAssets(root: string): void;
|
|
22
|
+
/** Remove every skill this plugin installed under `root`. */
|
|
23
|
+
export declare function uninstallContinueOryAssets(root: string): void;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Materialize / clean the Ory skill catalog for the Continue CLI plugin.
|
|
4
|
+
*
|
|
5
|
+
* Continue (`cn`) surfaces slash commands exclusively from skills: every
|
|
6
|
+
* `skills/<name>/SKILL.md` it discovers automatically becomes a slash command.
|
|
7
|
+
* It does NOT read a `.continue/commands/` directory. So both the guide skills
|
|
8
|
+
* and the local-stack commands (local-up / local-down / temporal-up) are
|
|
9
|
+
* written as skills under `<root>/skills/<name>/SKILL.md` — the commands are
|
|
10
|
+
* wrapped with `commandToSkill` so they show up as `/local-up` etc.
|
|
11
|
+
*
|
|
12
|
+
* All content is rendered from the canonical `@ory/argus` templates — never
|
|
13
|
+
* re-defined inline — so the guidance stays in sync across every harness.
|
|
14
|
+
*
|
|
15
|
+
* Verified against @continuedev/cli.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.installContinueOryAssets = installContinueOryAssets;
|
|
52
|
+
exports.uninstallContinueOryAssets = uninstallContinueOryAssets;
|
|
53
|
+
const fs = __importStar(require("node:fs"));
|
|
54
|
+
const path = __importStar(require("node:path"));
|
|
55
|
+
const argus_1 = require("@ory/argus");
|
|
56
|
+
const HARNESS = "continue";
|
|
57
|
+
const PACKAGE_NAME = "@ory/continue";
|
|
58
|
+
const RENDER_OPTS = {
|
|
59
|
+
binName: "ory-continue",
|
|
60
|
+
packageName: PACKAGE_NAME,
|
|
61
|
+
};
|
|
62
|
+
function safeRmEmpty(dir) {
|
|
63
|
+
try {
|
|
64
|
+
if (fs.existsSync(dir) && fs.readdirSync(dir).length === 0) {
|
|
65
|
+
fs.rmdirSync(dir);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
/* ignore — leave the dir if removal fails. */
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Write all Ory skills (guides + local-stack commands rendered as skills)
|
|
74
|
+
* under `<root>/skills/<name>/SKILL.md`. For the manual-setup path that's
|
|
75
|
+
* `<projectDir>/.continue`.
|
|
76
|
+
*/
|
|
77
|
+
function installContinueOryAssets(root) {
|
|
78
|
+
fs.mkdirSync(root, { recursive: true });
|
|
79
|
+
const skillsDir = path.join(root, "skills");
|
|
80
|
+
fs.rmSync(skillsDir, { recursive: true, force: true });
|
|
81
|
+
const guideSkills = (0, argus_1.renderOrySkills)(HARNESS, RENDER_OPTS);
|
|
82
|
+
const commandSkills = (0, argus_1.renderOryCommands)(HARNESS, RENDER_OPTS).map(argus_1.commandToSkill);
|
|
83
|
+
(0, argus_1.writeSkillTree)(skillsDir, [...guideSkills, ...commandSkills]);
|
|
84
|
+
}
|
|
85
|
+
/** Remove every skill this plugin installed under `root`. */
|
|
86
|
+
function uninstallContinueOryAssets(root) {
|
|
87
|
+
const skillsDir = path.join(root, "skills");
|
|
88
|
+
if (fs.existsSync(skillsDir)) {
|
|
89
|
+
(0, argus_1.removeSkillDirs)(skillsDir, [...argus_1.ORY_SKILL_NAMES, ...argus_1.ORY_COMMAND_SKILL_NAMES]);
|
|
90
|
+
safeRmEmpty(skillsDir);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Main CLI for @ory/continue.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx ory-continue install Write hooks to settings.json + assets
|
|
7
|
+
* npx ory-continue uninstall Remove hooks and assets
|
|
8
|
+
* npx ory-continue configure Set or view Ory credentials
|
|
9
|
+
* npx ory-continue setup [--project-dir] Write hooks to settings.json directly
|
|
10
|
+
* npx ory-continue status Show plugin status
|
|
11
|
+
* npx ory-continue local <cmd> Manage local Ory dev environment
|
|
12
|
+
*
|
|
13
|
+
* Continue (the `cn` CLI) has no extension-install command, so `install` is a
|
|
14
|
+
* thin wrapper over the same settings.json setup path the README documents.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Main CLI for @ory/continue.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx ory-continue install Write hooks to settings.json + assets
|
|
8
|
+
* npx ory-continue uninstall Remove hooks and assets
|
|
9
|
+
* npx ory-continue configure Set or view Ory credentials
|
|
10
|
+
* npx ory-continue setup [--project-dir] Write hooks to settings.json directly
|
|
11
|
+
* npx ory-continue status Show plugin status
|
|
12
|
+
* npx ory-continue local <cmd> Manage local Ory dev environment
|
|
13
|
+
*
|
|
14
|
+
* Continue (the `cn` CLI) has no extension-install command, so `install` is a
|
|
15
|
+
* thin wrapper over the same settings.json setup path the README documents.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
const path = __importStar(require("node:path"));
|
|
52
|
+
const fs = __importStar(require("node:fs"));
|
|
53
|
+
const argus_1 = require("@ory/argus");
|
|
54
|
+
const PACKAGE_ROOT = path.resolve(__dirname, "..", "..");
|
|
55
|
+
function main() {
|
|
56
|
+
const [command, ...args] = process.argv.slice(2);
|
|
57
|
+
switch (command) {
|
|
58
|
+
case "install":
|
|
59
|
+
install(args);
|
|
60
|
+
postInstallPermissions("ory-continue", "continue").then(() => process.exit(0), (err) => {
|
|
61
|
+
console.error(err.message ?? err);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
});
|
|
64
|
+
break;
|
|
65
|
+
case "uninstall":
|
|
66
|
+
uninstall(args);
|
|
67
|
+
break;
|
|
68
|
+
case "configure":
|
|
69
|
+
(0, argus_1.runConfigureCommand)("ory-continue", args);
|
|
70
|
+
break;
|
|
71
|
+
case "agent":
|
|
72
|
+
(0, argus_1.runAgentCommand)("ory-continue", args).then((code) => process.exit(code), (err) => {
|
|
73
|
+
console.error(err.message ?? err);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
});
|
|
76
|
+
break;
|
|
77
|
+
case "permissions":
|
|
78
|
+
(0, argus_1.runPermissionsCommand)("ory-continue", "continue", args).then((code) => process.exit(code), (err) => {
|
|
79
|
+
console.error(err.message ?? err);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
});
|
|
82
|
+
break;
|
|
83
|
+
case "setup":
|
|
84
|
+
require("./setup.js");
|
|
85
|
+
break;
|
|
86
|
+
case "status":
|
|
87
|
+
status().then(() => process.exit(0), (err) => {
|
|
88
|
+
console.error(err.message ?? err);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
});
|
|
91
|
+
break;
|
|
92
|
+
case "local":
|
|
93
|
+
(0, argus_1.runLocalCommand)("ory-continue", args).catch((err) => {
|
|
94
|
+
console.error(err.message ?? err);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
});
|
|
97
|
+
break;
|
|
98
|
+
case "help":
|
|
99
|
+
case "--help":
|
|
100
|
+
case "-h":
|
|
101
|
+
case undefined:
|
|
102
|
+
help();
|
|
103
|
+
break;
|
|
104
|
+
default:
|
|
105
|
+
console.error(`Unknown command: ${command}`);
|
|
106
|
+
help();
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Install = write the Ory hooks into the harness's settings.json and
|
|
112
|
+
* materialize the Ory skills. Continue has no native install command, so this
|
|
113
|
+
* delegates to the setup.ts code path.
|
|
114
|
+
*/
|
|
115
|
+
function install(args) {
|
|
116
|
+
console.log("Installing Ory hooks and skills for Continue...");
|
|
117
|
+
process.argv = ["node", "setup.js", ...args];
|
|
118
|
+
require("./setup.js");
|
|
119
|
+
printQuickstart();
|
|
120
|
+
(0, argus_1.printEnvHelp)("ory-continue");
|
|
121
|
+
}
|
|
122
|
+
function uninstall(args) {
|
|
123
|
+
const setupArgs = ["--uninstall", ...args];
|
|
124
|
+
process.argv = ["node", "setup.js", ...setupArgs];
|
|
125
|
+
require("./setup.js");
|
|
126
|
+
}
|
|
127
|
+
async function postInstallPermissions(binName, harness) {
|
|
128
|
+
const bootstrapped = await (0, argus_1.maybeAutoBootstrap)(binName, harness);
|
|
129
|
+
(0, argus_1.printPermissionsOnboardingHelp)(binName, harness, {
|
|
130
|
+
bootstrappedAutomatically: bootstrapped,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Print a three-line quickstart so a fresh user sees the happy path
|
|
135
|
+
* before the more detailed credentials and permissions banners scroll by.
|
|
136
|
+
*/
|
|
137
|
+
function printQuickstart() {
|
|
138
|
+
console.log("");
|
|
139
|
+
console.log("Quickstart:");
|
|
140
|
+
console.log(" 1. Inside Continue, run /local-up to start a local Ory stack.");
|
|
141
|
+
console.log(" 2. Ask Continue \"add Ory auth to this app\" to scaffold login/signup.");
|
|
142
|
+
console.log(" 3. Set ORY_USER_LOGIN=true to enable the interactive PKCE browser login.");
|
|
143
|
+
}
|
|
144
|
+
async function status() {
|
|
145
|
+
await (0, argus_1.runStatusCommand)("ory-continue", "continue", {
|
|
146
|
+
title: "Continue CLI",
|
|
147
|
+
printPluginSection: () => {
|
|
148
|
+
console.log("Hooks & plugin:");
|
|
149
|
+
console.log(` Hook script: ${fs.existsSync(path.join(PACKAGE_ROOT, "dist", "hook.js")) ? "built" : "NOT BUILT (run pnpm build)"}`);
|
|
150
|
+
console.log(` Settings: .continue/settings.json (per project)`);
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function help() {
|
|
155
|
+
console.log(`
|
|
156
|
+
ory-continue — Ory plugin for Continue CLI (cn)
|
|
157
|
+
|
|
158
|
+
Usage:
|
|
159
|
+
npx ory-continue <command> [options]
|
|
160
|
+
|
|
161
|
+
Commands:
|
|
162
|
+
install Write Ory hooks and skills into .continue/
|
|
163
|
+
uninstall Remove the Ory hooks and skills
|
|
164
|
+
configure Set or view Ory project URL and API key
|
|
165
|
+
agent <cmd> Manage the agent's OAuth2 (DCR) identity (status, unregister)
|
|
166
|
+
permissions <cmd> Manage permission mode and tool permissions (status, bootstrap, observe, enforce)
|
|
167
|
+
setup [--project-dir] Write hooks directly to .continue/settings.json
|
|
168
|
+
status Show plugin status and configuration
|
|
169
|
+
local <cmd> Manage local Ory dev environment (up, down, status, seed, ...)
|
|
170
|
+
|
|
171
|
+
After installing, the plugin hooks into these Continue CLI lifecycle events:
|
|
172
|
+
SessionStart Verify the user and agent identities via Ory
|
|
173
|
+
PreToolUse Check tool permissions via Ory Permissions
|
|
174
|
+
PostToolUse Audit log tool executions
|
|
175
|
+
|
|
176
|
+
Examples:
|
|
177
|
+
npx ory-continue install # Install hooks + assets
|
|
178
|
+
npx ory-continue status # Check configuration
|
|
179
|
+
npx ory-continue uninstall # Remove hooks + assets
|
|
180
|
+
`);
|
|
181
|
+
}
|
|
182
|
+
main();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Setup CLI for the Ory Continue CLI plugin.
|
|
4
|
+
*
|
|
5
|
+
* Continue has no extension-install command, so the Ory hooks are written
|
|
6
|
+
* directly into the harness's settings.json.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx ory-continue-setup # Auto-detect and configure
|
|
10
|
+
* npx ory-continue-setup --project-dir /path/to/repo
|
|
11
|
+
* npx ory-continue-setup --print # Print config to stdout without writing
|
|
12
|
+
* npx ory-continue-setup --uninstall # Remove Ory hooks from settings
|
|
13
|
+
*
|
|
14
|
+
* Verified against @continuedev/cli: Continue reads a top-level `hooks` object
|
|
15
|
+
* from `.continue/settings.json` (also `.claude/settings.json` and home
|
|
16
|
+
* variants). We target `<projectDir>/.continue/settings.json`.
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Setup CLI for the Ory Continue CLI plugin.
|
|
5
|
+
*
|
|
6
|
+
* Continue has no extension-install command, so the Ory hooks are written
|
|
7
|
+
* directly into the harness's settings.json.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* npx ory-continue-setup # Auto-detect and configure
|
|
11
|
+
* npx ory-continue-setup --project-dir /path/to/repo
|
|
12
|
+
* npx ory-continue-setup --print # Print config to stdout without writing
|
|
13
|
+
* npx ory-continue-setup --uninstall # Remove Ory hooks from settings
|
|
14
|
+
*
|
|
15
|
+
* Verified against @continuedev/cli: Continue reads a top-level `hooks` object
|
|
16
|
+
* from `.continue/settings.json` (also `.claude/settings.json` and home
|
|
17
|
+
* variants). We target `<projectDir>/.continue/settings.json`.
|
|
18
|
+
*/
|
|
19
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
22
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
23
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
24
|
+
}
|
|
25
|
+
Object.defineProperty(o, k2, desc);
|
|
26
|
+
}) : (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
o[k2] = m[k];
|
|
29
|
+
}));
|
|
30
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
31
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
32
|
+
}) : function(o, v) {
|
|
33
|
+
o["default"] = v;
|
|
34
|
+
});
|
|
35
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
36
|
+
var ownKeys = function(o) {
|
|
37
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
38
|
+
var ar = [];
|
|
39
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
40
|
+
return ar;
|
|
41
|
+
};
|
|
42
|
+
return ownKeys(o);
|
|
43
|
+
};
|
|
44
|
+
return function (mod) {
|
|
45
|
+
if (mod && mod.__esModule) return mod;
|
|
46
|
+
var result = {};
|
|
47
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
48
|
+
__setModuleDefault(result, mod);
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
})();
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
const fs = __importStar(require("node:fs"));
|
|
54
|
+
const path = __importStar(require("node:path"));
|
|
55
|
+
const argus_1 = require("@ory/argus");
|
|
56
|
+
const assets_js_1 = require("./assets.js");
|
|
57
|
+
const BIN_NAME = "ory-continue-hook";
|
|
58
|
+
const PACKAGE_NAME = "@ory/continue";
|
|
59
|
+
function getSettingsPath(args) {
|
|
60
|
+
return path.join(args.projectDir, ".continue", "settings.json");
|
|
61
|
+
}
|
|
62
|
+
function generateHooksConfig() {
|
|
63
|
+
const cmd = (0, argus_1.resolveHookCommand)(PACKAGE_NAME, BIN_NAME);
|
|
64
|
+
return {
|
|
65
|
+
SessionStart: (0, argus_1.matcherHookEntry)(cmd),
|
|
66
|
+
PreToolUse: (0, argus_1.matcherHookEntry)(cmd),
|
|
67
|
+
PostToolUse: (0, argus_1.matcherHookEntry)(cmd),
|
|
68
|
+
PostToolUseFailure: (0, argus_1.matcherHookEntry)(cmd),
|
|
69
|
+
PermissionRequest: (0, argus_1.matcherHookEntry)(cmd),
|
|
70
|
+
UserPromptSubmit: (0, argus_1.matcherHookEntry)(cmd),
|
|
71
|
+
SubagentStart: (0, argus_1.matcherHookEntry)(cmd),
|
|
72
|
+
SubagentStop: (0, argus_1.matcherHookEntry)(cmd),
|
|
73
|
+
Stop: (0, argus_1.matcherHookEntry)(cmd),
|
|
74
|
+
SessionEnd: (0, argus_1.matcherHookEntry)(cmd),
|
|
75
|
+
PreCompact: (0, argus_1.matcherHookEntry)(cmd),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function main() {
|
|
79
|
+
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
80
|
+
(0, argus_1.printSetupHelp)("ory-continue-setup", "Continue CLI");
|
|
81
|
+
process.exit(0);
|
|
82
|
+
}
|
|
83
|
+
const args = (0, argus_1.parseSetupArgs)();
|
|
84
|
+
const hooksConfig = generateHooksConfig();
|
|
85
|
+
if (args.print) {
|
|
86
|
+
console.log(JSON.stringify({ hooks: hooksConfig }, null, 2));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const settingsPath = getSettingsPath(args);
|
|
90
|
+
const existing = (0, argus_1.readJsonFile)(settingsPath);
|
|
91
|
+
const continueDir = path.join(args.projectDir, ".continue");
|
|
92
|
+
if (args.uninstall) {
|
|
93
|
+
if (!fs.existsSync(settingsPath)) {
|
|
94
|
+
console.log("No settings file found. Nothing to uninstall.");
|
|
95
|
+
(0, assets_js_1.uninstallContinueOryAssets)(continueDir);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
let updated = (0, argus_1.removeMatcherHooks)(existing, BIN_NAME);
|
|
99
|
+
updated = (0, argus_1.removeMcpServer)(updated);
|
|
100
|
+
(0, argus_1.writeJsonFile)(settingsPath, updated);
|
|
101
|
+
(0, assets_js_1.uninstallContinueOryAssets)(continueDir);
|
|
102
|
+
console.log(`Removed Ory hooks and MCP server from ${settingsPath}`);
|
|
103
|
+
console.log(`Removed Ory skills from ${continueDir}`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
let merged = (0, argus_1.mergeMatcherHooks)(existing, hooksConfig, BIN_NAME);
|
|
107
|
+
merged = (0, argus_1.mergeMcpServer)(merged);
|
|
108
|
+
(0, argus_1.writeJsonFile)(settingsPath, merged);
|
|
109
|
+
(0, assets_js_1.installContinueOryAssets)(continueDir);
|
|
110
|
+
console.log(`Ory hooks and MCP server installed to ${settingsPath}`);
|
|
111
|
+
console.log(`Ory skills installed to ${continueDir}`);
|
|
112
|
+
(0, argus_1.printNextSteps)("Continue CLI", "npx ory-continue-setup --uninstall");
|
|
113
|
+
}
|
|
114
|
+
main();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OryAgentClient, ensureUserAuthenticated, ensureAgentIdentity, ensureSubAgentIdentity } from "@ory/argus";
|
|
2
|
+
import type { ContinueHookInput, ContinueHookOutput } from "./types.js";
|
|
3
|
+
export interface HandleHookEventDeps {
|
|
4
|
+
/** Test injection point for the user login flow. */
|
|
5
|
+
userLogin?: 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
|
+
* Route a Continue CLI hook event to the appropriate Ory integration.
|
|
13
|
+
*
|
|
14
|
+
* Event names are verified against @continuedev/cli. Unknown events pass
|
|
15
|
+
* through.
|
|
16
|
+
*/
|
|
17
|
+
export declare function handleHookEvent(input: ContinueHookInput, client: OryAgentClient, deps?: HandleHookEventDeps): Promise<ContinueHookOutput>;
|