@ours.network/codex 1.2.0-nightly.1 → 1.2.0-nightly.11
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/.codex-plugin/plugin.json +1 -1
- package/README.md +11 -28
- package/bin/codex-config-install.mjs +3 -3
- package/bin/ours-codex-install.mjs +4 -31
- package/bin/proxy.mjs +1 -17
- package/dist/hooks-runner.mjs +422 -16509
- package/dist/host-hooks.mjs +386 -0
- package/dist/monitor-mcp.mjs +20 -125
- package/dist/network-watch.mjs +17 -121
- package/dist/profile.mjs +14 -156
- package/install.sh +14 -33
- package/package.json +4 -3
- package/skills/ours/SKILL.md +6 -6
- package/skills/ours/references/configuration.md +20 -22
- package/src/hooks/runner.mjs +8 -70
- package/src/host-hooks.mjs +25 -0
- package/src/launcher.mjs +1 -9
- package/src/profile.mjs +1 -40
- package/bin/container-launch.mjs +0 -40
- package/dist/network-proxy.mjs +0 -16782
- package/src/network-proxy.mjs +0 -308
package/README.md
CHANGED
|
@@ -51,38 +51,21 @@ The launcher never starts, stops, restarts, or reconfigures the ours daemon. If
|
|
|
51
51
|
selected daemon is absent or incompatible, it exits with an error and leaves standard
|
|
52
52
|
`codex` available.
|
|
53
53
|
|
|
54
|
-
## Selecting a
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
local-daemon precedence remains:
|
|
62
|
-
|
|
63
|
-
1. `ours-codex --ours-port <port>`
|
|
64
|
-
2. `OURS_PORT`
|
|
65
|
-
3. the config selected by `OURS_CONFIG`
|
|
66
|
-
4. `~/.ours/config.json`
|
|
67
|
-
5. port `3050`
|
|
68
|
-
|
|
69
|
-
All MCP, hooks, unread, and watcher calls inherit the same selected profile. Host-profile
|
|
70
|
-
traffic goes directly to the selected daemon's authenticated `/mcp` endpoint through the
|
|
71
|
-
Codex package; it does not require Docker or an installed `@ours.network/mcp` package.
|
|
72
|
-
Example:
|
|
54
|
+
## Selecting a gateway
|
|
55
|
+
|
|
56
|
+
Every client uses `~/.ours-client/profile.json`; `OURS_CONFIG` can select a complete
|
|
57
|
+
alternate profile. It contains `serverUrl`, `expectedInstanceId`, and `credentialPath`.
|
|
58
|
+
The daemon endpoint is derived as `serverUrl + /daemon`, including gateway path prefixes.
|
|
59
|
+
Missing, unsafe, or invalid profiles fail closed. Remove legacy port/state/token
|
|
60
|
+
selectors; `--ours-port` is rejected. Example after provisioning with `ours-install client`:
|
|
73
61
|
|
|
74
62
|
```sh
|
|
75
|
-
OURS_CONFIG="$HOME/.ours/testing.json" ours-codex
|
|
63
|
+
OURS_CONFIG="$HOME/.ours-client/testing.json" ours-codex
|
|
76
64
|
```
|
|
77
65
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
`OURS_STATE_DIR`. Codex forwards the actual selected path as `OURS_CONFIG` and the optional `OURS_MCP_CONFIG` host
|
|
82
|
-
record location; the SDK verifies the expected
|
|
83
|
-
daemon instance and rereads `credentialPath` for every request, so an operator token
|
|
84
|
-
update takes effect in the running hook and live monitor without a restart or token
|
|
85
|
-
snapshot in child process environments.
|
|
66
|
+
MCP, hooks, unread and watcher requests inherit that profile. The SDK verifies the
|
|
67
|
+
instance and rereads the issued credential for each request. Client installation and
|
|
68
|
+
launch never install, start, restart or reconfigure server services.
|
|
86
69
|
|
|
87
70
|
Native ownership is keyed by Codex's actual thread ID. A normal live TUI exit forwards
|
|
88
71
|
that ID through the same `SessionEnd` input used by the hook. If Codex has not produced
|
|
@@ -33,7 +33,7 @@ export function planTomlInstall(text) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Render the managed TOML block: the `ours` MCP server pointing at the globally-installed
|
|
36
|
-
//
|
|
36
|
+
// gateway client (`ours-mcp proxy`). Equivalent to `codex mcp add ours -- ours-mcp proxy`.
|
|
37
37
|
export function renderTomlBlock() {
|
|
38
38
|
return `${SENTINEL}
|
|
39
39
|
# Added by @ours.network/codex install.sh. Remove this whole block to uninstall.
|
|
@@ -41,9 +41,9 @@ export function renderTomlBlock() {
|
|
|
41
41
|
[mcp_servers.ours]
|
|
42
42
|
command = "ours-mcp"
|
|
43
43
|
args = ["proxy"]
|
|
44
|
-
# Optional
|
|
44
|
+
# Optional whole shared gateway profile override:
|
|
45
45
|
# [mcp_servers.ours.env]
|
|
46
|
-
#
|
|
46
|
+
# OURS_CONFIG = "/absolute/private/path/profile.json"
|
|
47
47
|
${SENTINEL_END}
|
|
48
48
|
`;
|
|
49
49
|
}
|
|
@@ -5,14 +5,7 @@
|
|
|
5
5
|
// npm i -g @ours.network/codex
|
|
6
6
|
// ours-codex-install
|
|
7
7
|
//
|
|
8
|
-
//
|
|
9
|
-
// WHOLE stack (ours core + harness plugins + ours-fleet + Telegram). `ours-codex-install` is kept
|
|
10
|
-
// as a THIN ALIAS — by default it hands off to `ours-install` when that's available, so an old
|
|
11
|
-
// muscle-memory command still lands the user in the current, unified flow. Pass `--codex-only`
|
|
12
|
-
// (or set OURS_CODEX_LEGACY=1) to force the legacy Codex-only install below.
|
|
13
|
-
//
|
|
14
|
-
// Usage:
|
|
15
|
-
// ours-codex-install [--codex-only] [--codex-dir DIR] [--skills-dir DIR] [--skip-daemon]
|
|
8
|
+
// Installs client plugin wiring only after shared gateway profile validation.
|
|
16
9
|
import { spawnSync } from 'node:child_process';
|
|
17
10
|
import { fileURLToPath } from 'node:url';
|
|
18
11
|
import { dirname, join } from 'node:path';
|
|
@@ -33,38 +26,19 @@ for (let i = 0; i < argv.length; i++) {
|
|
|
33
26
|
else { console.error(`ours-codex-install: unknown argument "${a}"`); help(); process.exit(2); }
|
|
34
27
|
}
|
|
35
28
|
|
|
36
|
-
// Thin-alias hand-off: unless the caller forced the legacy Codex-only path, run the unified
|
|
37
|
-
// `ours-install` if we can find it — on PATH (published), or the monorepo sibling (dev/test).
|
|
38
|
-
if (!opts.codexOnly && !process.env.OURS_CODEX_LEGACY) {
|
|
39
|
-
const onPath = spawnSync('bash', ['-c', 'command -v ours-install'], { encoding: 'utf8' });
|
|
40
|
-
const unified = (onPath.status === 0 && (onPath.stdout || '').trim())
|
|
41
|
-
? { cmd: (onPath.stdout || '').trim(), args: argv }
|
|
42
|
-
: (() => {
|
|
43
|
-
const sib = join(PKG, '..', 'installer', 'install.mjs');
|
|
44
|
-
return existsSync(sib) ? { cmd: process.execPath, args: [sib, ...argv] } : null;
|
|
45
|
-
})();
|
|
46
|
-
if (unified) {
|
|
47
|
-
const r = spawnSync(unified.cmd, unified.args, { stdio: 'inherit', env: process.env });
|
|
48
|
-
if (r.error) { console.error(`ours-codex-install: ${r.error.message}`); process.exit(1); }
|
|
49
|
-
process.exit(r.status ?? 0);
|
|
50
|
-
}
|
|
51
|
-
// No unified installer found → fall through to the legacy Codex-only install (still never a dead end).
|
|
52
|
-
}
|
|
53
|
-
|
|
54
29
|
function help() {
|
|
55
30
|
console.log(`ours-codex-install — set up the ours.network plugin for the OpenAI Codex CLI.
|
|
56
31
|
|
|
57
32
|
ours-codex-install [options]
|
|
58
33
|
|
|
59
|
-
|
|
60
|
-
stack). Use --codex-only to run the legacy Codex-only install instead. Standard mode uses
|
|
34
|
+
Requires clients and a shared gateway profile provisioned by \`ours-install client\`. Standard mode uses
|
|
61
35
|
\`codex\`; live mode uses \`ours-codex\`. Live monitoring still requires explicit consent.
|
|
62
36
|
|
|
63
37
|
Options:
|
|
64
|
-
--codex-only
|
|
38
|
+
--codex-only compatibility flag; plugin setup is always client-only
|
|
65
39
|
--codex-dir <dir> Codex config+AGENTS.md root (default ~/.codex) [--codex-only]
|
|
66
40
|
--skills-dir <dir> skills root (default ~/.agents/skills — USER scope) [--codex-only]
|
|
67
|
-
--skip-daemon
|
|
41
|
+
--skip-daemon compatibility flag; server lifecycle is never changed [--codex-only]
|
|
68
42
|
-h, --help show this help
|
|
69
43
|
|
|
70
44
|
Idempotent: safe to re-run. Start a new Codex thread after installation and review the
|
|
@@ -81,7 +55,6 @@ if (!existsSync(INSTALL)) {
|
|
|
81
55
|
const env = { ...process.env };
|
|
82
56
|
if (opts.codexDir) env.CODEX_DIR = opts.codexDir;
|
|
83
57
|
if (opts.skillsDir) env.SKILLS_DIR = opts.skillsDir;
|
|
84
|
-
if (opts.skipDaemon) env.OURS_INSTALL_SKIP_DAEMON = '1';
|
|
85
58
|
|
|
86
59
|
const res = spawnSync('bash', [INSTALL], { stdio: 'inherit', env });
|
|
87
60
|
if (res.error) { console.error(`ours-codex-install: ${res.error.message}`); process.exit(1); }
|
package/bin/proxy.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { spawn } from 'node:child_process';
|
|
4
|
-
import { existsSync
|
|
5
|
-
import { homedir } from 'node:os';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
6
5
|
import { dirname, join } from 'node:path';
|
|
7
6
|
import { fileURLToPath } from 'node:url';
|
|
8
7
|
|
|
@@ -15,21 +14,6 @@ const here = dirname(fileURLToPath(import.meta.url));
|
|
|
15
14
|
const env = { ...process.env };
|
|
16
15
|
|
|
17
16
|
async function main() {
|
|
18
|
-
const network = await import('../dist/network-proxy.mjs');
|
|
19
|
-
const profile = network.hostProfileFromEnv(env);
|
|
20
|
-
if (profile) {
|
|
21
|
-
const configPath = env.OURS_MCP_CONFIG || join(env.HOME || homedir(), '.ours-mcp', 'config.json');
|
|
22
|
-
const hostRecordRoot = dirname(configPath);
|
|
23
|
-
if (sessionEnd) {
|
|
24
|
-
const payload = JSON.parse(readFileSync(0, 'utf8') || '{}');
|
|
25
|
-
if (typeof payload.session_id !== 'string' || !payload.session_id) throw new Error('SessionEnd requires session_id.');
|
|
26
|
-
await network.endNetworkNativeSession({ profile, nativeSessionId: payload.session_id, hostRecordRoot });
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
await network.runNetworkProxy({ profile, hostRecordRoot, env });
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
17
|
let cliPath;
|
|
34
18
|
try { cliPath = require.resolve(spec); } catch { /* try plugin cache layouts */ }
|
|
35
19
|
if (!cliPath) {
|