@ours.network/fleet 1.2.0-nightly.48 → 1.2.0-nightly.49
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/dist/build-info.json +5 -4
- package/dist/capabilities.d.ts +3 -1
- package/dist/capabilities.js +3 -0
- package/dist/harness/codex-reasoning.d.ts +5 -0
- package/dist/harness/codex-reasoning.js +12 -0
- package/dist/harness/codex.js +12 -6
- package/dist/managed-cli.js +3 -2
- package/dist/web/workspace-tunnel.js +5 -3
- package/docs/validation/managed-cli-permissions.md +8 -3
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.2.0-nightly.
|
|
3
|
-
"buildId": "
|
|
4
|
-
"commit": "
|
|
2
|
+
"version": "1.2.0-nightly.49",
|
|
3
|
+
"buildId": "992b454dab6f",
|
|
4
|
+
"commit": "007bb41d5f822b22ebc9c708882f6cd7e70ae537",
|
|
5
5
|
"dirty": true,
|
|
6
|
-
"builtAt": "2026-10-
|
|
6
|
+
"builtAt": "2026-10-06T08:03:31.440Z",
|
|
7
7
|
"capabilities": [
|
|
8
|
+
"managed-cli.codex-reasoning-effort-v1",
|
|
8
9
|
"managed-cli.setup-v1",
|
|
9
10
|
"workspace.enroll.preserve-profile-v1",
|
|
10
11
|
"cowork.http-management-v1",
|
package/dist/capabilities.d.ts
CHANGED
|
@@ -18,7 +18,9 @@ export declare const CAP_HTTP_COWORK = "cowork.http-management-v1";
|
|
|
18
18
|
export declare const CAP_WORKSPACE_PRESERVE_PROFILE = "workspace.enroll.preserve-profile-v1";
|
|
19
19
|
/** `ours-fleet managed-cli setup|status` and the `managed_cli` Agent key (#233). */
|
|
20
20
|
export declare const CAP_MANAGED_CLI_SETUP = "managed-cli.setup-v1";
|
|
21
|
-
|
|
21
|
+
/** Managed CLI accepts validated Codex Brain reasoning effort without dropping it (#235). */
|
|
22
|
+
export declare const CAP_MANAGED_CLI_CODEX_EFFORT = "managed-cli.codex-reasoning-effort-v1";
|
|
23
|
+
export declare const CAPABILITIES: readonly ["managed-cli.codex-reasoning-effort-v1", "managed-cli.setup-v1", "workspace.enroll.preserve-profile-v1", "cowork.http-management-v1", "monitor.interrupt.after_tool"];
|
|
22
24
|
export type Capability = (typeof CAPABILITIES)[number];
|
|
23
25
|
/** Does this build declare `token`? */
|
|
24
26
|
export declare const hasCapability: (token: string) => boolean;
|
package/dist/capabilities.js
CHANGED
|
@@ -18,7 +18,10 @@ export const CAP_HTTP_COWORK = 'cowork.http-management-v1';
|
|
|
18
18
|
export const CAP_WORKSPACE_PRESERVE_PROFILE = 'workspace.enroll.preserve-profile-v1';
|
|
19
19
|
/** `ours-fleet managed-cli setup|status` and the `managed_cli` Agent key (#233). */
|
|
20
20
|
export const CAP_MANAGED_CLI_SETUP = 'managed-cli.setup-v1';
|
|
21
|
+
/** Managed CLI accepts validated Codex Brain reasoning effort without dropping it (#235). */
|
|
22
|
+
export const CAP_MANAGED_CLI_CODEX_EFFORT = 'managed-cli.codex-reasoning-effort-v1';
|
|
21
23
|
export const CAPABILITIES = [
|
|
24
|
+
CAP_MANAGED_CLI_CODEX_EFFORT,
|
|
22
25
|
CAP_MANAGED_CLI_SETUP,
|
|
23
26
|
CAP_WORKSPACE_PRESERVE_PROFILE,
|
|
24
27
|
CAP_HTTP_COWORK,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Efforts supported by Fleet's Codex Brain contract. Keep native eligibility in sync. */
|
|
2
|
+
export declare const CODEX_REASONING_EFFORTS: readonly ["low", "medium", "high", "xhigh", "max", "ultra"];
|
|
3
|
+
export declare function isCodexReasoningEffort(value: unknown): value is string;
|
|
4
|
+
/** Only inspected model tuning may bypass the managed CLI native-config guard. */
|
|
5
|
+
export declare function isManagedCliCodexConfig(config: unknown): boolean;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Efforts supported by Fleet's Codex Brain contract. Keep native eligibility in sync. */
|
|
2
|
+
export const CODEX_REASONING_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'];
|
|
3
|
+
export function isCodexReasoningEffort(value) {
|
|
4
|
+
return typeof value === 'string' && CODEX_REASONING_EFFORTS.includes(value);
|
|
5
|
+
}
|
|
6
|
+
/** Only inspected model tuning may bypass the managed CLI native-config guard. */
|
|
7
|
+
export function isManagedCliCodexConfig(config) {
|
|
8
|
+
if (config == null)
|
|
9
|
+
return true;
|
|
10
|
+
return typeof config === 'object' && !Array.isArray(config)
|
|
11
|
+
&& Object.entries(config).every(([key, value]) => key === 'model_reasoning_effort' && isCodexReasoningEffort(value));
|
|
12
|
+
}
|
package/dist/harness/codex.js
CHANGED
|
@@ -8,6 +8,7 @@ import { harnessRuntimeDir } from '../isolation/policy.js';
|
|
|
8
8
|
import { resolveBundledAcpAgent, } from './acp-agent.js';
|
|
9
9
|
import { VERIFIED_CODEX_ACP_VERSIONS, probeCodexRuntime, codexVersionAtLeast, hostCodex } from './codex-runtime.js';
|
|
10
10
|
import { CodexAgentSessionAdapter } from './codex-session.js';
|
|
11
|
+
import { CODEX_REASONING_EFFORTS, isCodexReasoningEffort } from './codex-reasoning.js';
|
|
11
12
|
const OPTION_KEYS = [
|
|
12
13
|
'launcher', 'sandbox', 'approval', 'permission_mode', 'search', 'profile', 'config', 'add_dirs',
|
|
13
14
|
'monitor',
|
|
@@ -141,6 +142,13 @@ function neutralSandboxMode(role) {
|
|
|
141
142
|
function isNativeConfigKeyAllowed(key) {
|
|
142
143
|
return NATIVE_CONFIG_ALLOWLIST.has(key);
|
|
143
144
|
}
|
|
145
|
+
/** Brain wins; a validated native effort also needs delivery through ACP's selection API. */
|
|
146
|
+
function reasoningEffort(role) {
|
|
147
|
+
if (typeof role.effort === 'string')
|
|
148
|
+
return role.effort;
|
|
149
|
+
const value = role.harness_options?.config?.model_reasoning_effort;
|
|
150
|
+
return isCodexReasoningEffort(value) ? value : undefined;
|
|
151
|
+
}
|
|
144
152
|
/** Defense in depth for callers which launch a role after validation was bypassed. */
|
|
145
153
|
export function nativeCodexConfig(role) {
|
|
146
154
|
const options = role.harness_options;
|
|
@@ -318,10 +326,8 @@ export function makeCodexAdapter(exec = realExec, transport, nativeTransport) {
|
|
|
318
326
|
id: 'codex',
|
|
319
327
|
agentSession: new CodexAgentSessionAdapter({
|
|
320
328
|
resolveBrain(brain) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
&& (typeof brain.effort !== 'string' || !levels.includes(brain.effort)))
|
|
324
|
-
throw new Error(`Codex Brain effort must be one of: ${levels.join(', ')}`);
|
|
329
|
+
if (brain.effort != null && !isCodexReasoningEffort(brain.effort))
|
|
330
|
+
throw new Error(`Codex Brain effort must be one of: ${CODEX_REASONING_EFFORTS.join(', ')}`);
|
|
325
331
|
const harnessOptions = { ...(brain.harnessOptions ?? {}) };
|
|
326
332
|
if (brain.effort)
|
|
327
333
|
harnessOptions.config = {
|
|
@@ -343,8 +349,8 @@ export function makeCodexAdapter(exec = realExec, transport, nativeTransport) {
|
|
|
343
349
|
sessionConfigSelections: role => [
|
|
344
350
|
...(typeof role.model === 'string'
|
|
345
351
|
? [{ configId: 'model', value: role.model }] : []),
|
|
346
|
-
...(
|
|
347
|
-
? [{ configId: 'reasoning_effort', value: role
|
|
352
|
+
...(reasoningEffort(role)
|
|
353
|
+
? [{ configId: 'reasoning_effort', value: reasoningEffort(role) }] : []),
|
|
348
354
|
],
|
|
349
355
|
permissionModeId: role => acpAgentMode(role),
|
|
350
356
|
mcpServers: () => undefined,
|
package/dist/managed-cli.js
CHANGED
|
@@ -26,6 +26,7 @@ import { managedPinMarker } from './fleet-command-audit.js';
|
|
|
26
26
|
import { MANAGED_CLI_WORKFLOW_IDS, splitRootFor, } from './config.js';
|
|
27
27
|
import { resolveBundledAcpAgent } from './harness/acp-agent.js';
|
|
28
28
|
import { executableOnPath, hostCodex } from './harness/codex-runtime.js';
|
|
29
|
+
import { isManagedCliCodexConfig } from './harness/codex-reasoning.js';
|
|
29
30
|
import { getAdapter } from './harness/registry.js';
|
|
30
31
|
import { agentDir, defaultConfigPath, home, stateRoot } from './paths.js';
|
|
31
32
|
/** Capability-gated by the installer; see src/capabilities.ts. */
|
|
@@ -333,8 +334,8 @@ export function analyzeManagedCli(role, configPath, options = {}) {
|
|
|
333
334
|
// directories the role adds. Native settings Fleet cannot read may add more.
|
|
334
335
|
const native = (role.harness_options ?? {});
|
|
335
336
|
const writable = [workspace, ...(Array.isArray(native.add_dirs) ? native.add_dirs.filter((dir) => typeof dir === 'string').map(dir => resolve(workspace, dir)) : [])];
|
|
336
|
-
if (role.harness === 'codex' && (native.profile != null || (native.config
|
|
337
|
-
reasons.push('harness_native.config or harness_native.profile
|
|
337
|
+
if (role.harness === 'codex' && (native.profile != null || !isManagedCliCodexConfig(native.config)))
|
|
338
|
+
reasons.push('harness_native.config or harness_native.profile contains invalid or uninspected Codex settings (for example extra writable roots), so Fleet does not inspect enough to tell whether the agent could replace the pinned files; only validated model_reasoning_effort is supported; drop the other settings or keep this role sandboxed');
|
|
338
339
|
if (role.isolation)
|
|
339
340
|
reasons.push('the role declares isolation:, and Fleet\'s outer sandbox is kept as-is; the workflow is not qualified inside it');
|
|
340
341
|
if (!plainExecutable(paths.node))
|
|
@@ -21,12 +21,14 @@ export function startWorkspaceTunnel(origin) {
|
|
|
21
21
|
return;
|
|
22
22
|
child = spawn('cloudflared', ['tunnel', '--no-autoupdate', 'run', '--token-file', tokenFile], { stdio: 'ignore' });
|
|
23
23
|
let scheduled = false;
|
|
24
|
+
// Keep an error listener for the child's whole lifetime, including shutdown.
|
|
24
25
|
const retry = () => { if (scheduled || stopped)
|
|
25
26
|
return; scheduled = true; timer = setTimeout(launch, backoff); backoff = Math.min(30000, backoff * 2); };
|
|
26
|
-
child.
|
|
27
|
+
child.on('error', retry);
|
|
27
28
|
child.once('exit', retry);
|
|
28
29
|
};
|
|
29
30
|
launch();
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
// A failed spawn has no pid and reports error/close rather than exit.
|
|
32
|
+
return async () => { stopped = true; clearTimeout(timer); const current = child; if (!current?.pid || current.exitCode !== null || current.signalCode !== null)
|
|
33
|
+
return; await new Promise(resolve => { const timeout = setTimeout(() => { current.kill('SIGKILL'); resolve(); }, 5000); current.once('close', () => { clearTimeout(timeout); resolve(); }); current.kill('SIGTERM'); }); };
|
|
32
34
|
}
|
|
@@ -127,9 +127,14 @@ commands; roles declaring `isolation:`; unspellable paths; a Node path needing
|
|
|
127
127
|
quotes; Codex older than 0.160.0 with quoted paths; and any pinned file the
|
|
128
128
|
agent could replace — inside its workspace or a `harness_options.add_dirs`
|
|
129
129
|
directory, lexically or through a symlink. Codex roles with
|
|
130
|
-
`harness_options.
|
|
131
|
-
those change the native sandbox (for example extra writable roots) in ways
|
|
132
|
-
does not inspect.
|
|
130
|
+
`harness_options.profile` or uninspected `harness_options.config` remain unsupported:
|
|
131
|
+
those can change the native sandbox (for example extra writable roots) in ways
|
|
132
|
+
Fleet does not inspect. The only accepted nonempty config is
|
|
133
|
+
`model_reasoning_effort` with a supported value (`low`, `medium`, `high`, `xhigh`,
|
|
134
|
+
`max`, `ultra`). This includes the config generated by Codex Brain `effort` (#235).
|
|
135
|
+
The chosen effort remains in native launch config and ACP reasoning selection;
|
|
136
|
+
adding any unknown or security-bearing config key still prevents policy setup.
|
|
137
|
+
Native user settings Fleet cannot read are outside this check.
|
|
133
138
|
|
|
134
139
|
### Qualification
|
|
135
140
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ours.network/fleet",
|
|
3
|
-
"version": "1.2.0-nightly.
|
|
3
|
+
"version": "1.2.0-nightly.49",
|
|
4
4
|
"description": "Harness-agnostic fleet of persistent, identity-bound AI agents. Declarative fleet.yaml, managed native/ACP sessions, supervision, and ours.network messaging.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|