@ory/antigravity 0.13.8 → 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 +12 -9
- package/dist/cli/assets.js +1 -1
- package/dist/cli/main.js +8 -1
- package/dist/handlers.js +7 -101
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -23,12 +23,14 @@ Run one command. It installs the plugin (registering it with Antigravity via `ag
|
|
|
23
23
|
npx -y -p @ory/antigravity ory-agy install
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
It opens a guided setup **in your browser** where you pick how to connect — the default takes just a click:
|
|
27
27
|
|
|
28
28
|
- **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.
|
|
29
29
|
- **Local** — run a complete Ory on your laptop with Docker. No account, no signup, no keys. Great for trying it out.
|
|
30
30
|
- **Audit-only** — skip Ory entirely and just log what the agent does.
|
|
31
31
|
|
|
32
|
+
> No browser available (CI, SSH, headless)? The same walkthrough runs right in your terminal instead — or force it with `--no-web`.
|
|
33
|
+
|
|
32
34
|
That's it. Confirm everything landed with:
|
|
33
35
|
|
|
34
36
|
```bash
|
|
@@ -68,6 +70,7 @@ The plugin hooks into these Antigravity lifecycle events: `SessionStart` (check
|
|
|
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/antigravity ory-agy 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/antigravity ory-agy 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/antigravity ory-agy permissions enforce
|
|
86
89
|
```
|
|
87
90
|
|
|
88
|
-
Now a denied tool is actually blocked and Antigravity shows why (the `deny_reason`). 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 (`run_command`, `view_file`, `write_to_file`, …) — or add permissions for MCP-server tools by hand, or via the Ory MCP server right from inside Antigravity.
|
|
91
|
+
Now a denied tool is actually blocked and Antigravity shows why (the `deny_reason`). 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 (`run_command`, `view_file`, `write_to_file`, …) — or add permissions for MCP-server tools by hand, or via the Ory MCP server right from inside Antigravity.
|
|
89
92
|
|
|
90
93
|
## Also: add login to your own app
|
|
91
94
|
|
|
@@ -110,11 +113,10 @@ The guided setup covers most people. For scripted or CI setups, or to point at a
|
|
|
110
113
|
```bash
|
|
111
114
|
npx -y -p @ory/antigravity ory-agy configure \
|
|
112
115
|
--project-url https://<slug>.projects.oryapis.com \
|
|
113
|
-
--oauth2-client-id <login client id>
|
|
114
|
-
--user-login
|
|
116
|
+
--oauth2-client-id <login client id>
|
|
115
117
|
```
|
|
116
118
|
|
|
117
|
-
The agent'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 matching env vars are `ORY_PROJECT_URL`, `ORY_OAUTH2_CLIENT_ID`,
|
|
119
|
+
The agent'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 matching env vars are `ORY_PROJECT_URL`, `ORY_OAUTH2_CLIENT_ID`, and `ORY_AGENT_API_KEY`.
|
|
118
120
|
|
|
119
121
|
<details>
|
|
120
122
|
<summary>Create the sign-in client by hand</summary>
|
|
@@ -123,7 +125,7 @@ The guided setup normally does this. To do it yourself, create a **public** OAut
|
|
|
123
125
|
|
|
124
126
|
```bash
|
|
125
127
|
ory create oauth2-client --project <project-id> \
|
|
126
|
-
--name "
|
|
128
|
+
--name "Ory Agent Security · user login (PKCE)" \
|
|
127
129
|
--grant-type authorization_code,refresh_token \
|
|
128
130
|
--response-type code \
|
|
129
131
|
--scope openid,offline_access \
|
|
@@ -134,7 +136,7 @@ ory create oauth2-client --project <project-id> \
|
|
|
134
136
|
--redirect-uri http://127.0.0.1:47826/callback
|
|
135
137
|
```
|
|
136
138
|
|
|
137
|
-
Pass the resulting id to `configure --oauth2-client-id
|
|
139
|
+
Pass the resulting id to `configure --oauth2-client-id`. Running headless with a session token already? Set `ORY_USER_SESSION_TOKEN` and skip the browser step entirely.
|
|
138
140
|
|
|
139
141
|
</details>
|
|
140
142
|
|
|
@@ -143,11 +145,12 @@ With nothing configured, the plugin still loads and runs in **pass-through mode*
|
|
|
143
145
|
## Commands
|
|
144
146
|
|
|
145
147
|
```
|
|
146
|
-
ory-agy install | uninstall Install/remove; --reconfigure re-runs setup, --no-configure skips it
|
|
148
|
+
ory-agy install | uninstall Install/remove; --reconfigure re-runs setup, --no-web forces the terminal wizard, --no-configure skips it
|
|
147
149
|
ory-agy status Show configuration, identities, permission coverage, recent activity
|
|
150
|
+
ory-agy dashboard Open the live browser dashboard (status + service health + Change stack)
|
|
148
151
|
ory-agy watch Tail the live trace stream (OTel spans)
|
|
149
152
|
ory-agy permissions <cmd> status | bootstrap | observe (watch) | enforce (block)
|
|
150
|
-
ory-agy configure <flags> Point at a project by hand (--project-url, --oauth2-client-id, --
|
|
153
|
+
ory-agy configure <flags> Point at a project by hand (--project-url, --oauth2-client-id, --audit-only)
|
|
151
154
|
ory-agy agent <status|unregister> Manage the agent's own auto-created identity
|
|
152
155
|
ory-agy local <up|down|status|…> Run / manage a local Ory in Docker
|
|
153
156
|
ory-agy-setup Install into .agents/ directly (no agy binary)
|
package/dist/cli/assets.js
CHANGED
|
@@ -88,7 +88,7 @@ function readPackageVersion() {
|
|
|
88
88
|
* tool name on the tool events.
|
|
89
89
|
*/
|
|
90
90
|
function renderHooks(version) {
|
|
91
|
-
const command = `npx -y -p ${PACKAGE_NAME}@${version} ${HOOK_BIN_NAME}
|
|
91
|
+
const command = (0, argus_1.pinHookToLocalRegistry)(`npx -y -p ${PACKAGE_NAME}@${version} ${HOOK_BIN_NAME}`);
|
|
92
92
|
const entry = (matcher, timeout) => [
|
|
93
93
|
{ matcher, hooks: [{ type: "command", command, timeout }] },
|
|
94
94
|
];
|
package/dist/cli/main.js
CHANGED
|
@@ -110,6 +110,12 @@ function main() {
|
|
|
110
110
|
case "watch":
|
|
111
111
|
(0, argus_1.runWatchCommand)("antigravity", args);
|
|
112
112
|
break;
|
|
113
|
+
case "dashboard":
|
|
114
|
+
(0, argus_1.runDashboardCommand)("ory-agy", "antigravity", args).then((code) => process.exit(code), (err) => {
|
|
115
|
+
console.error(err.message ?? err);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
});
|
|
118
|
+
break;
|
|
113
119
|
case "version":
|
|
114
120
|
case "--version":
|
|
115
121
|
case "-v":
|
|
@@ -176,7 +182,7 @@ function printQuickstart() {
|
|
|
176
182
|
console.log("Quickstart:");
|
|
177
183
|
console.log(" 1. Inside Antigravity, run /ory:local-up to start a local Ory stack.");
|
|
178
184
|
console.log(' 2. Ask Antigravity "add Ory auth to this app" to scaffold login/signup.');
|
|
179
|
-
console.log(" 3. Set
|
|
185
|
+
console.log(" 3. Set ORY_OAUTH2_CLIENT_ID so the per-session PKCE browser login can complete.");
|
|
180
186
|
}
|
|
181
187
|
async function status() {
|
|
182
188
|
await (0, argus_1.runStatusCommand)("ory-agy", "antigravity", {
|
|
@@ -205,6 +211,7 @@ Commands:
|
|
|
205
211
|
permissions <cmd> Manage permission mode and tool permissions (status, bootstrap, observe, enforce)
|
|
206
212
|
setup [--project-dir] Write the plugin bundle into .agents directly (fallback)
|
|
207
213
|
status Show plugin status and configuration
|
|
214
|
+
dashboard Open the Ory Agent dashboard (system health + configuration)
|
|
208
215
|
watch [trace-file] Tail the trace stream (OTel spans) live
|
|
209
216
|
version Show version and the ory-agent-plugins build commit
|
|
210
217
|
local <cmd> Manage local Ory dev environment (up, down, status, seed, ...)
|
package/dist/handlers.js
CHANGED
|
@@ -58,87 +58,24 @@ async function handleSessionStart(input, client, deps) {
|
|
|
58
58
|
client.tracer.record("session.start", "ok", {
|
|
59
59
|
attributes: { model: input.model, source: input.source },
|
|
60
60
|
});
|
|
61
|
-
// User login (interactive PKCE / token refresh).
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
// session always proceeds. Tool-call enforcement is unaffected.
|
|
61
|
+
// User login (interactive PKCE / token refresh). Runs every session and
|
|
62
|
+
// never blocks — it refreshes tokens, prompts if needed, and emits the
|
|
63
|
+
// audit span, but the session always proceeds. Enforcement happens at
|
|
64
|
+
// tool-call time and is governed solely by permissionMode.
|
|
66
65
|
const userGate = deps.userLogin ?? argus_1.ensureUserAuthenticated;
|
|
67
|
-
|
|
66
|
+
await userGate(client, {
|
|
68
67
|
binName: "ory-agy",
|
|
69
68
|
harness: HARNESS,
|
|
70
|
-
allowBlock: false,
|
|
71
69
|
});
|
|
72
70
|
// Resolve the agent identity regardless of how user auth went — never
|
|
73
71
|
// blocks; attaches the agent's bearer token to outgoing Ory calls.
|
|
74
72
|
const agentGate = deps.agentGate ?? argus_1.ensureAgentIdentity;
|
|
75
73
|
await agentGate(client, { projectUrl: (0, argus_1.resolveConfig)().projectUrl, harness: HARNESS });
|
|
76
74
|
// Record the user→agent delegation (audit-trail only; fail-open).
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return {};
|
|
80
|
-
}
|
|
81
|
-
// Legacy fallthrough: honor pre-supplied tokens for backward compat.
|
|
82
|
-
const resolved = (0, argus_1.resolveConfig)();
|
|
83
|
-
if (resolved.auditOnly || !resolved.projectUrl) {
|
|
84
|
-
return {};
|
|
85
|
-
}
|
|
86
|
-
const sessionToken = process.env.ORY_SESSION_TOKEN;
|
|
87
|
-
const oauth2Token = process.env.ORY_OAUTH2_TOKEN;
|
|
88
|
-
if (sessionToken) {
|
|
89
|
-
await verifySessionToken(sessionToken, client);
|
|
90
|
-
}
|
|
91
|
-
else if (oauth2Token) {
|
|
92
|
-
await verifyOAuth2Token(oauth2Token, client);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
client.logger.warn("session.no_credentials", {
|
|
96
|
-
message: "No user login enabled and neither ORY_SESSION_TOKEN nor " +
|
|
97
|
-
"ORY_OAUTH2_TOKEN is set. Skipping authentication.",
|
|
98
|
-
});
|
|
99
|
-
}
|
|
75
|
+
// Written at most once per install.
|
|
76
|
+
await (0, argus_1.writeUserDelegatesAgent)(client);
|
|
100
77
|
return {};
|
|
101
78
|
}
|
|
102
|
-
async function verifySessionToken(token, client) {
|
|
103
|
-
try {
|
|
104
|
-
const session = await client.verifySession(token);
|
|
105
|
-
if (!session.active) {
|
|
106
|
-
client.logger.warn("session.inactive", {
|
|
107
|
-
message: "Ory session is not active. Re-authenticate to enable auth checks.",
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
catch (err) {
|
|
112
|
-
const oryErr = err;
|
|
113
|
-
client.logger.warn("session.verify_failed", {
|
|
114
|
-
code: oryErr.code,
|
|
115
|
-
message: oryErr.message,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
async function verifyOAuth2Token(token, client) {
|
|
120
|
-
try {
|
|
121
|
-
const tokenInfo = await client.introspectToken(token);
|
|
122
|
-
if (!tokenInfo.active) {
|
|
123
|
-
client.logger.warn("oauth2.token_inactive", {
|
|
124
|
-
message: "Ory OAuth2 token is not active.",
|
|
125
|
-
});
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
client.logger.info("oauth2.session_authenticated", {
|
|
129
|
-
clientId: tokenInfo.clientId,
|
|
130
|
-
subject: tokenInfo.subject,
|
|
131
|
-
scope: tokenInfo.scope,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
catch (err) {
|
|
135
|
-
const oryErr = err;
|
|
136
|
-
client.logger.warn("oauth2.introspect_failed", {
|
|
137
|
-
code: oryErr.code,
|
|
138
|
-
message: oryErr.message,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
79
|
// ─── PreToolUse ─────────────────────────────────────────────────────
|
|
143
80
|
async function handlePreToolUse(input, client) {
|
|
144
81
|
const toolName = input.tool_name ?? "unknown";
|
|
@@ -261,37 +198,6 @@ function handleSessionEnd(input, client) {
|
|
|
261
198
|
function resolveNamespace() {
|
|
262
199
|
return process.env.ORY_PERMISSION_NAMESPACE ?? "AgentTools";
|
|
263
200
|
}
|
|
264
|
-
/**
|
|
265
|
-
* Write the user→agent delegation tuple. Idempotent and fail-open:
|
|
266
|
-
* needs both principal subjects; any error is logged and swallowed.
|
|
267
|
-
*/
|
|
268
|
-
async function recordUserDelegatesAgent(client) {
|
|
269
|
-
const user = client.userPrincipal.subject;
|
|
270
|
-
const agent = client.agentPrincipal.subject;
|
|
271
|
-
if (!user || !agent) {
|
|
272
|
-
client.logger.debug("delegation.skip", {
|
|
273
|
-
reason: "missing principal",
|
|
274
|
-
hasUser: !!user,
|
|
275
|
-
hasAgent: !!agent,
|
|
276
|
-
});
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
try {
|
|
280
|
-
await client.createRelationship({
|
|
281
|
-
namespace: resolveNamespace(),
|
|
282
|
-
object: `agent:${agent}`,
|
|
283
|
-
relation: "delegate",
|
|
284
|
-
subjectId: `user:${user}`,
|
|
285
|
-
}, { spanAttributes: { delegation: "user-to-agent" } });
|
|
286
|
-
}
|
|
287
|
-
catch (err) {
|
|
288
|
-
const oryErr = err;
|
|
289
|
-
client.logger.warn("delegation.user_to_agent.failed", {
|
|
290
|
-
code: oryErr.code,
|
|
291
|
-
message: oryErr.message,
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
201
|
/**
|
|
296
202
|
* Fail-open on a permission-check error: log and allow the tool. Critical
|
|
297
203
|
* on Antigravity — returning anything other than `allow_tool: true` here
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ory/antigravity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Ory plugin for Google Antigravity: 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://github.com/ory/ory-agent-plugins/tree/main/packages/antigravity",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
],
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"reo-census": "^1.2.8",
|
|
76
|
-
"@ory/argus": "0.
|
|
76
|
+
"@ory/argus": "0.14.0"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"typescript": "^6.0.2",
|