@ory/opencode 0.13.9 → 0.14.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 CHANGED
@@ -21,12 +21,14 @@ Run one command. It installs the plugin and walks you through connecting:
21
21
  npx -y -p @ory/opencode ory-opencode install
22
22
  ```
23
23
 
24
- You'll be asked how you want to connect — **press Enter for the default**:
24
+ It opens a guided setup **in your browser** where you pick how to connect — the default takes just a click:
25
25
 
26
26
  - **Ory Network** *(default)* — sign in, or create a free account, in your browser. The project, keys, permissions, and login are all set up for you. Nothing to configure by hand.
27
27
  - **Local** — run a complete Ory on your laptop with Docker. No account, no signup, no keys. Great for trying it out.
28
28
  - **Audit-only** — skip Ory entirely and just log what OpenCode does.
29
29
 
30
+ > No browser available (CI, SSH, headless)? The same walkthrough runs right in your terminal instead — or force it with `--no-web`.
31
+
30
32
  That's it. Confirm everything landed with:
31
33
 
32
34
  ```bash
@@ -68,6 +70,7 @@ If Ory is ever unreachable, the plugin gets out of the way and lets OpenCode kee
68
70
  Everything the plugin does is observable out of the box — no configuration required:
69
71
 
70
72
  - **Status at a glance.** `npx -y -p @ory/opencode ory-opencode status` shows what's configured, who's signed in, how many built-in tools your permissions cover, and the most recent tool-call activity.
73
+ - **Live dashboard.** `npx -y -p @ory/opencode ory-opencode dashboard` opens the same picture in your browser — configuration, identities, permission coverage, Ory service health, and the latest tool-call activity, all refreshing live. From there you can flip **enforcement** on or off, toggle **user login**, and use **Change stack** to reconnect to a different Ory — no CLI required.
71
74
  - **Live traces.** Every tool call is recorded as an OpenTelemetry-style span. Watch them stream as the agent works:
72
75
 
73
76
  ```bash
@@ -85,7 +88,7 @@ When the watch-mode logs look right, turn on blocking with one command (setup al
85
88
  npx -y -p @ory/opencode ory-opencode permissions enforce
86
89
  ```
87
90
 
88
- Now a denied tool is actually blocked and OpenCode shows why. In watch mode, OpenCode's own permission prompt is left in place for you to answer; only an explicit allow or a block-mode deny changes that. Go back to watch mode anytime with `permissions observe`. Use `permissions status` to see what's covered and `permissions bootstrap` to (re-)grant the built-in tools — or just ask OpenCode in chat, e.g. *"grant me use of the bash tool."*
91
+ Now a denied tool is actually blocked and OpenCode shows why. In watch mode, OpenCode's own permission prompt is left in place for you to answer; only an explicit allow or a block-mode deny changes that. Go back to watch mode anytime with `permissions observe`. Prefer clicking? The dashboard has the same **Enforce** switch — flip it on, or back to watch mode, without touching the CLI. Use `permissions status` to see what's covered and `permissions bootstrap` to (re-)grant the built-in tools — or just ask OpenCode in chat, e.g. *"grant me use of the bash tool."*
89
92
 
90
93
  ## Also: add login to your own app
91
94
 
@@ -100,11 +103,10 @@ The guided setup covers most people. For scripted or CI setups, or to point at a
100
103
  ```bash
101
104
  npx -y -p @ory/opencode ory-opencode configure \
102
105
  --project-url https://<slug>.projects.oryapis.com \
103
- --oauth2-client-id <sign-in client id> \
104
- --user-login
106
+ --oauth2-client-id <sign-in client id>
105
107
  ```
106
108
 
107
- OpenCode's own identity registers itself automatically on first run — nothing to create. The `--oauth2-client-id` is the one piece browser sign-in needs; the guided setup makes it for you, or see below to do it by hand. For logging-only with no checks, use `--audit-only`. The equivalent env vars are `ORY_PROJECT_URL`, `ORY_OAUTH2_CLIENT_ID`, `ORY_USER_LOGIN`, and `ORY_AGENT_API_KEY`.
109
+ OpenCode's own identity registers itself automatically on first run — nothing to create. The `--oauth2-client-id` is the one piece browser sign-in needs; the guided setup makes it for you, or see below to do it by hand. For logging-only with no checks, use `--audit-only`. The interactive user login runs every session (always on, non-blocking) and only needs `ORY_OAUTH2_CLIENT_ID` to complete the browser flow. The equivalent env vars are `ORY_PROJECT_URL`, `ORY_OAUTH2_CLIENT_ID`, and `ORY_AGENT_API_KEY`.
108
110
 
109
111
  <details>
110
112
  <summary>Create the sign-in client by hand</summary>
@@ -113,7 +115,7 @@ The guided setup normally does this. To do it yourself, create a **public** OAut
113
115
 
114
116
  ```bash
115
117
  ory create oauth2-client --project <project-id> \
116
- --name "ory-agent-plugin" \
118
+ --name "Ory Agent Security · user login (PKCE)" \
117
119
  --grant-type authorization_code,refresh_token \
118
120
  --response-type code \
119
121
  --scope openid,offline_access \
@@ -133,11 +135,12 @@ With nothing configured, the plugin still loads and runs in **pass-through mode*
133
135
  ## Commands
134
136
 
135
137
  ```
136
- ory-opencode install | uninstall Install/remove; --reconfigure re-runs setup, --no-configure skips it
138
+ ory-opencode install | uninstall Install/remove; --reconfigure re-runs setup, --no-web forces the terminal wizard, --no-configure skips it
137
139
  ory-opencode status Show configuration, identities, permission coverage, recent activity
140
+ ory-opencode dashboard Open the live browser dashboard (status + service health + Change stack)
138
141
  ory-opencode watch Tail the live trace stream (OTel spans)
139
142
  ory-opencode permissions <cmd> status | bootstrap | observe (watch) | enforce (block)
140
- ory-opencode configure <flags> Point at a project by hand (--project-url, --oauth2-client-id, --user-login, --audit-only)
143
+ ory-opencode configure <flags> Point at a project by hand (--project-url, --oauth2-client-id, --audit-only)
141
144
  ory-opencode agent <status|unregister> Manage OpenCode's own auto-created identity
142
145
  ory-opencode local <up|down|status|…> Run / manage a local Ory in Docker
143
146
  ```
package/dist/cli/main.js CHANGED
@@ -95,6 +95,12 @@ function main() {
95
95
  case "watch":
96
96
  (0, argus_1.runWatchCommand)("opencode", args);
97
97
  break;
98
+ case "dashboard":
99
+ (0, argus_1.runDashboardCommand)("ory-opencode", "opencode", args).then((code) => process.exit(code), (err) => {
100
+ console.error(err.message ?? err);
101
+ process.exit(1);
102
+ });
103
+ break;
98
104
  case "version":
99
105
  case "--version":
100
106
  case "-v":
@@ -227,6 +233,7 @@ Commands:
227
233
  local <cmd> Manage local Ory dev environment
228
234
  (up, down, status, seed, logs, env, configure, reset)
229
235
  status [--project-dir <path>] Show plugin configuration and status
236
+ dashboard Open the Ory Agent dashboard (system health + configuration)
230
237
  watch [trace-file] Tail the trace stream (OTel spans) live
231
238
  version Show version and the ory-agent-plugins build commit
232
239
 
package/dist/plugin.d.ts CHANGED
@@ -13,10 +13,10 @@ export interface CreateOryPluginDeps {
13
13
  * context and returns a Hooks object. Hook functions use a mutating
14
14
  * (input, output) => Promise<void> pattern.
15
15
  *
16
- * The `server` factory has no return-value channel for blocking, so the
17
- * user login runs in advisory mode at startup — it emits the audit span,
18
- * refreshes tokens, and may launch a browser flow when interactive, but
19
- * cannot prevent the session from starting.
16
+ * The user login runs on every session at startup — it emits the audit
17
+ * span, refreshes tokens, and may launch a browser flow when interactive.
18
+ * It never blocks the session; enforcement is governed solely by
19
+ * permissionMode at tool-call time.
20
20
  */
21
21
  export declare function createOryPlugin(clientOrConfig?: OryAgentClient | {
22
22
  projectUrl: string;
package/dist/plugin.js CHANGED
@@ -9,10 +9,10 @@ const argus_1 = require("@ory/argus");
9
9
  * context and returns a Hooks object. Hook functions use a mutating
10
10
  * (input, output) => Promise<void> pattern.
11
11
  *
12
- * The `server` factory has no return-value channel for blocking, so the
13
- * user login runs in advisory mode at startup — it emits the audit span,
14
- * refreshes tokens, and may launch a browser flow when interactive, but
15
- * cannot prevent the session from starting.
12
+ * The user login runs on every session at startup — it emits the audit
13
+ * span, refreshes tokens, and may launch a browser flow when interactive.
14
+ * It never blocks the session; enforcement is governed solely by
15
+ * permissionMode at tool-call time.
16
16
  */
17
17
  function createOryPlugin(clientOrConfig, deps = {}) {
18
18
  return {
@@ -79,17 +79,14 @@ function createChatMessageHandler(client) {
79
79
  }
80
80
  // ─── Session verification on startup ────────────────────────────────
81
81
  async function verifyOnStartup(client, deps) {
82
- // Run the user login. The OpenCode `server` factory has no block
83
- // primitive, so allowBlock is false — the flow emits the user.auth
82
+ // Run the user login on every session. The flow emits the user.auth
84
83
  // audit span, refreshes tokens, and may prompt the user, but never
85
- // prevents the session from starting. When ORY_USER_LOGIN is unset
86
- // it's a no-op (mode === "disabled") and we fall through to legacy
87
- // logging.
84
+ // prevents the session from starting — enforcement is governed solely
85
+ // by permissionMode at tool-call time.
88
86
  const userGate = deps.userLogin ?? argus_1.ensureUserAuthenticated;
89
- const decision = await userGate(client, {
87
+ await userGate(client, {
90
88
  binName: "ory-opencode",
91
89
  harness: "opencode",
92
- allowBlock: false,
93
90
  });
94
91
  // Resolve the agent identity (machine credentials). Never blocks;
95
92
  // attaches the agent's bearer token to outgoing Ory API calls.
@@ -101,70 +98,6 @@ async function verifyOnStartup(client, deps) {
101
98
  // any failure is logged and swallowed (fail-open — delegation tracking is
102
99
  // for audit, not enforcement).
103
100
  await (0, argus_1.writeUserDelegatesAgent)(client);
104
- if (decision.mode !== "disabled") {
105
- return;
106
- }
107
- const resolved = (0, argus_1.resolveConfig)();
108
- if (resolved.auditOnly) {
109
- client.logger.info("config.audit_only", {
110
- message: "Audit-only mode enabled. Auth and permission checks are disabled.",
111
- });
112
- return;
113
- }
114
- if (!resolved.projectUrl) {
115
- client.logger.warn("config.not_configured", {
116
- message: "Ory plugin is not configured. Auth and permission checks are disabled. " +
117
- "Run 'npx ory-opencode configure' to connect to an Ory project.",
118
- });
119
- return;
120
- }
121
- const sessionToken = process.env.ORY_SESSION_TOKEN;
122
- const oauth2Token = process.env.ORY_OAUTH2_TOKEN;
123
- if (sessionToken) {
124
- try {
125
- const session = await client.verifySession(sessionToken);
126
- if (!session.active) {
127
- client.logger.warn("session.inactive", {
128
- message: "Ory session is not active. Re-authenticate to enable auth checks.",
129
- });
130
- }
131
- }
132
- catch (err) {
133
- const oryErr = err;
134
- client.logger.warn("session.verify_failed", {
135
- code: isOryError(err) ? oryErr.code : "unknown",
136
- message: err instanceof Error ? err.message : String(err),
137
- });
138
- }
139
- return;
140
- }
141
- if (oauth2Token) {
142
- try {
143
- const tokenInfo = await client.introspectToken(oauth2Token);
144
- if (!tokenInfo.active) {
145
- client.logger.warn("oauth2.token_inactive", {
146
- message: "Ory OAuth2 token is not active. Obtain a new token to enable auth checks.",
147
- });
148
- return;
149
- }
150
- client.logger.info("oauth2.session_authenticated", {
151
- clientId: tokenInfo.clientId,
152
- subject: tokenInfo.subject,
153
- });
154
- }
155
- catch (err) {
156
- const oryErr = err;
157
- client.logger.warn("oauth2.introspect_failed", {
158
- code: isOryError(err) ? oryErr.code : "unknown",
159
- message: err instanceof Error ? err.message : String(err),
160
- });
161
- }
162
- return;
163
- }
164
- client.logger.warn("session.no_credentials", {
165
- message: "Neither ORY_SESSION_TOKEN nor ORY_OAUTH2_TOKEN is set. " +
166
- "Skipping authentication.",
167
- });
168
101
  }
169
102
  // ─── permission.ask ─────────────────────────────────────────────────
170
103
  function createPermissionHandler(client, _options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ory/opencode",
3
- "version": "0.13.9",
3
+ "version": "0.14.0",
4
4
  "description": "Ory plugin for OpenCode: scaffolding skills, a local Ory instance, and authentication, authorization, and audit for every tool call",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ory.com",
@@ -64,7 +64,7 @@
64
64
  ],
65
65
  "dependencies": {
66
66
  "reo-census": "^1.2.8",
67
- "@ory/argus": "0.13.9"
67
+ "@ory/argus": "0.14.0"
68
68
  },
69
69
  "engines": {
70
70
  "node": ">=22"