@ory/codex 0.13.9 → 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 +72 -64
- package/dist/cli/main.d.ts +1 -1
- package/dist/cli/main.js +33 -11
- package/dist/cli/setup.d.ts +2 -1
- package/dist/cli/setup.js +94 -39
- package/dist/handlers.d.ts +3 -19
- package/dist/handlers.js +158 -346
- package/dist/hook.js +41 -16
- package/dist/session-state.d.ts +3 -0
- package/dist/session-state.js +61 -0
- package/dist/types.d.ts +1 -0
- package/marketplace/plugins/ory-codex/.codex-plugin/plugin.json +1 -1
- package/package.json +9 -8
package/dist/hook.js
CHANGED
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
const argus_1 = require("@ory/argus");
|
|
12
12
|
const handlers_js_1 = require("./handlers.js");
|
|
13
|
+
const EVENT_FLUSH_TIMEOUT_MS = 750;
|
|
14
|
+
let client;
|
|
15
|
+
async function flushEvents() {
|
|
16
|
+
try {
|
|
17
|
+
await client?.flushEvents(EVENT_FLUSH_TIMEOUT_MS);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// The hook decision must not depend on activity delivery.
|
|
21
|
+
}
|
|
22
|
+
}
|
|
13
23
|
/**
|
|
14
24
|
* Read all of stdin as a string.
|
|
15
25
|
*
|
|
@@ -21,29 +31,42 @@ function readStdin() {
|
|
|
21
31
|
return new Promise((resolve, reject) => {
|
|
22
32
|
const chunks = [];
|
|
23
33
|
let resolved = false;
|
|
34
|
+
let idleTimer;
|
|
35
|
+
function cleanup() {
|
|
36
|
+
if (idleTimer)
|
|
37
|
+
clearTimeout(idleTimer);
|
|
38
|
+
process.stdin.off("data", onData);
|
|
39
|
+
process.stdin.off("end", done);
|
|
40
|
+
process.stdin.off("error", onError);
|
|
41
|
+
process.stdin.pause();
|
|
42
|
+
}
|
|
24
43
|
function done() {
|
|
25
44
|
if (!resolved) {
|
|
26
45
|
resolved = true;
|
|
46
|
+
cleanup();
|
|
27
47
|
resolve(Buffer.concat(chunks).toString("utf-8"));
|
|
28
48
|
}
|
|
29
49
|
}
|
|
30
|
-
|
|
50
|
+
function onData(chunk) {
|
|
31
51
|
chunks.push(chunk);
|
|
32
|
-
|
|
52
|
+
if (idleTimer)
|
|
53
|
+
clearTimeout(idleTimer);
|
|
33
54
|
idleTimer = setTimeout(done, 100);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
process.stdin.on("error", (err) => {
|
|
55
|
+
}
|
|
56
|
+
function onError(err) {
|
|
37
57
|
if (!resolved) {
|
|
38
58
|
resolved = true;
|
|
59
|
+
cleanup();
|
|
39
60
|
reject(err);
|
|
40
61
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
62
|
+
}
|
|
63
|
+
process.stdin.on("data", onData);
|
|
64
|
+
process.stdin.on("end", done);
|
|
65
|
+
process.stdin.on("error", onError);
|
|
43
66
|
});
|
|
44
67
|
}
|
|
45
68
|
async function main() {
|
|
46
|
-
|
|
69
|
+
client = argus_1.OryAgentClient.fromEnv("codex");
|
|
47
70
|
const raw = await readStdin();
|
|
48
71
|
let input;
|
|
49
72
|
try {
|
|
@@ -51,24 +74,26 @@ async function main() {
|
|
|
51
74
|
}
|
|
52
75
|
catch {
|
|
53
76
|
client.logger.error("hook.stdin.parse_failed", { raw: raw.slice(0, 200) });
|
|
54
|
-
|
|
55
|
-
|
|
77
|
+
process.exitCode = 0; // Don't block on parse errors
|
|
78
|
+
return;
|
|
56
79
|
}
|
|
57
80
|
const output = await (0, handlers_js_1.handleHookEvent)(input, client);
|
|
58
81
|
if (output.decision === "block") {
|
|
59
82
|
// Codex reads the block reason from stderr
|
|
60
83
|
process.stderr.write(output.reason ?? "Blocked by Ory agent plugin");
|
|
61
84
|
process.stdout.write(JSON.stringify(output));
|
|
62
|
-
await
|
|
63
|
-
process.
|
|
85
|
+
await flushEvents();
|
|
86
|
+
process.exitCode = 2;
|
|
87
|
+
return;
|
|
64
88
|
}
|
|
65
89
|
if ((0, handlers_js_1.shouldEmitOutput)(output)) {
|
|
66
90
|
process.stdout.write(JSON.stringify(output));
|
|
67
91
|
}
|
|
68
|
-
await
|
|
69
|
-
process.
|
|
92
|
+
await flushEvents();
|
|
93
|
+
process.exitCode = 0;
|
|
70
94
|
}
|
|
71
|
-
main().catch((err) => {
|
|
95
|
+
main().catch(async (err) => {
|
|
72
96
|
process.stderr.write(`[ory-agent] fatal: ${err}\n`);
|
|
73
|
-
|
|
97
|
+
await flushEvents();
|
|
98
|
+
process.exitCode = 0; // Fail open
|
|
74
99
|
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.hasCodexSessionStarted = hasCodexSessionStarted;
|
|
37
|
+
exports.markCodexSessionStarted = markCodexSessionStarted;
|
|
38
|
+
exports.clearCodexSessionStarts = clearCodexSessionStarts;
|
|
39
|
+
const node_crypto_1 = require("node:crypto");
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
const argus_1 = require("@ory/argus");
|
|
43
|
+
const SESSION_START_DIR = "session-started";
|
|
44
|
+
function sessionStartPath(sessionId) {
|
|
45
|
+
const digest = (0, node_crypto_1.createHash)("sha256").update(sessionId).digest("hex");
|
|
46
|
+
return path.join((0, argus_1.getHarnessDataDir)("codex"), SESSION_START_DIR, digest);
|
|
47
|
+
}
|
|
48
|
+
function hasCodexSessionStarted(sessionId) {
|
|
49
|
+
return fs.existsSync(sessionStartPath(sessionId));
|
|
50
|
+
}
|
|
51
|
+
function markCodexSessionStarted(sessionId) {
|
|
52
|
+
const marker = sessionStartPath(sessionId);
|
|
53
|
+
fs.mkdirSync(path.dirname(marker), { recursive: true });
|
|
54
|
+
fs.writeFileSync(marker, "", { flag: "a" });
|
|
55
|
+
}
|
|
56
|
+
function clearCodexSessionStarts() {
|
|
57
|
+
fs.rmSync(path.join((0, argus_1.getHarnessDataDir)("codex"), SESSION_START_DIR), {
|
|
58
|
+
recursive: true,
|
|
59
|
+
force: true,
|
|
60
|
+
});
|
|
61
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - `"apply_patch"` — canonical name for file edits. `Write`/`Edit` are
|
|
11
11
|
* matcher aliases only; the serialized name is always `apply_patch`.
|
|
12
12
|
* - `"mcp__<server>__<tool>"` for MCP tools.
|
|
13
|
+
* - `"collaborationspawn_agent"` for a Codex collaboration Sub-Agent spawn.
|
|
13
14
|
*
|
|
14
15
|
* Supported events: SessionStart, PreToolUse, PostToolUse, PermissionRequest,
|
|
15
16
|
* UserPromptSubmit, Stop.
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"interface": {
|
|
25
25
|
"displayName": "Ory",
|
|
26
26
|
"shortDescription": "Authn/authz and audit for every Codex tool call",
|
|
27
|
-
"longDescription": "Adds Ory Identities, Permissions, and audit logging to Codex. Auth gate on session start, per-tool permission checks before every invocation,
|
|
27
|
+
"longDescription": "Adds Ory Identities, Permissions, and audit logging to Codex. Auth gate on session start, per-tool permission checks before every invocation, privacy-safe activity events for every decision, and a bundled Ory MCP server for managing identities, OAuth2 clients, and permission tuples from inside Codex.",
|
|
28
28
|
"developerName": "Ory",
|
|
29
29
|
"category": "Security",
|
|
30
30
|
"capabilities": ["Write"],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ory/codex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Ory plugin for Codex: 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",
|
|
@@ -34,8 +34,7 @@
|
|
|
34
34
|
"agent-security",
|
|
35
35
|
"guardrails",
|
|
36
36
|
"llm",
|
|
37
|
-
"
|
|
38
|
-
"distributed-tracing",
|
|
37
|
+
"activity-auditing",
|
|
39
38
|
"observability",
|
|
40
39
|
"kratos",
|
|
41
40
|
"keto",
|
|
@@ -46,6 +45,10 @@
|
|
|
46
45
|
"registry": "https://registry.npmjs.org/",
|
|
47
46
|
"provenance": true
|
|
48
47
|
},
|
|
48
|
+
"reova": {
|
|
49
|
+
"enabled": true,
|
|
50
|
+
"endpoint": "https://telemetry.reo.dev/data"
|
|
51
|
+
},
|
|
49
52
|
"main": "dist/index.js",
|
|
50
53
|
"types": "dist/index.d.ts",
|
|
51
54
|
"exports": {
|
|
@@ -61,13 +64,12 @@
|
|
|
61
64
|
},
|
|
62
65
|
"files": [
|
|
63
66
|
"dist",
|
|
64
|
-
"!dist/dev",
|
|
65
67
|
"!dist/**/*.tsbuildinfo",
|
|
66
68
|
"marketplace"
|
|
67
69
|
],
|
|
68
70
|
"dependencies": {
|
|
69
|
-
"
|
|
70
|
-
"@ory/argus": "0.
|
|
71
|
+
"reova": "^0.7.0",
|
|
72
|
+
"@ory/argus": "1.0.0"
|
|
71
73
|
},
|
|
72
74
|
"engines": {
|
|
73
75
|
"node": ">=22"
|
|
@@ -77,7 +79,6 @@
|
|
|
77
79
|
"clean": "rm -rf dist *.tsbuildinfo",
|
|
78
80
|
"test": "vitest run",
|
|
79
81
|
"test:watch": "vitest",
|
|
80
|
-
"typecheck": "tsc --noEmit"
|
|
81
|
-
"dev": "node dist/dev/launcher.js"
|
|
82
|
+
"typecheck": "tsc --noEmit"
|
|
82
83
|
}
|
|
83
84
|
}
|